← All @molecule/* packages · App templates
@molecule/api-resource-wiki-pageAPI resource · resource-wiki-page · API (Node) · v1.0.1 · Apache-2.0
Wiki page CRUD with breadcrumbs + search indexing
npm install @molecule/api-resource-wiki-page@molecule/api-resource-wiki-page is an API resource: the routes, validation and storage for resource-wiki-page, built on the database and auth cores so it runs on whichever providers your app has bonded.
import { createWikiPageRouter } from '@molecule/api-resource-wiki-page'
app.use('/pages', createWikiPageRouter())Works with: @molecule/api-bonds-default-express, @molecule/api-database, @molecule/api-i18n, @molecule/api-middleware-validation, @molecule/api-search
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
@molecule/api-resource-wiki-page — wiki/docs page CRUD with slug,
nested parents (breadcrumbs), space-scoped permissions, and optional
search-bond indexing.
Extracted from the wiki flagship.
import { createWikiPageRouter } from '@molecule/api-resource-wiki-page'
app.use('/pages', createWikiPageRouter())
import { createPage, getBreadcrumbs } from '@molecule/api-resource-wiki-page'
const page = await createPage({
space_id: spaceId,
slug: 'getting-started',
title: 'Getting started',
body: '# Welcome',
})
const crumbs = await getBreadcrumbs(page.id)
resource
npm install @molecule/api-resource-wiki-page @molecule/api-bonds-default-express @molecule/api-database @molecule/api-i18n @molecule/api-middleware-validation @molecule/api-search express zod
npm install -D @types/express
WikiPageBreadcrumbBreadcrumb entry used when rendering a wiki page's ancestor trail.
interface WikiPageBreadcrumb {
id: string
slug: string
title: string
}
WikiPageRowDatabase row shape for a wiki page record.
interface WikiPageRow {
id: string
space_id: string
parent_id: string | null
slug: string
title: string
body: string
position: number
is_published: boolean
created_at: string | Date
updated_at: string | Date
}
WikiSpaceRowDatabase row shape for a wiki space record.
interface WikiSpaceRow {
id: string
owner_id: string
is_public?: boolean
visibility?: string
}
countPagesInSpace(spaceId)Count total pages belonging to a given space.
function countPagesInSpace(spaceId: string): Promise<number>
createPage(data)Create a new wiki page and trigger search indexing.
function createPage(data: {
space_id: string
parent_id?: string | null
slug: string
title: string
body?: string
position?: number
is_published?: boolean
}): Promise<WikiPageRow>
createWikiPageRouter()Creates and returns the Express router with all wiki-page CRUD routes.
function createWikiPageRouter(): Router
deletePage(pageId)Recursively delete a wiki page and all its children.
function deletePage(pageId: string): Promise<boolean>
getAccessibleSpace(spaceId, userId)Resolve a space row + verify the user has access.
function getAccessibleSpace(spaceId: string, userId: string): Promise<WikiSpaceRow | null>
getBreadcrumbs(pageId, maxDepth?)Walk parent chain to build breadcrumbs (root → page).
function getBreadcrumbs(pageId: string, maxDepth?: number): Promise<WikiPageBreadcrumb[]>
getPageById(pageId)Fetch a single wiki page by its primary-key ID.
function getPageById(pageId: string): Promise<WikiPageRow | null>
getPageBySlug(spaceId, slug)Fetch a single wiki page by its space and URL slug.
function getPageBySlug(spaceId: string, slug: string): Promise<WikiPageRow | null>
listPagesInSpace(spaceId, opts?)List pages in a space, optionally filtered by parent and publish status.
function listPagesInSpace(
spaceId: string,
opts?: { parent_id?: string | null; is_published?: boolean },
): Promise<WikiPageRow[]>
slugify(input)Converts an arbitrary string into a URL-safe lowercase slug.
function slugify(input: string): string
updatePage(pageId, patch)Apply a partial patch to a wiki page and re-index it in search.
function updatePage(pageId: string, patch: Partial<WikiPageRow>): Promise<WikiPageRow | null>
slugRegexRegex that matches a valid wiki-page slug: lowercase alphanumeric with interior hyphens.
const slugRegex: RegExp
wikiPageCreateSchemaZod schema for validating wiki-page creation payloads.
const wikiPageCreateSchema: z.ZodObject<
{
space_id: z.ZodString
parent_id: z.ZodOptional<z.ZodNullable<z.ZodString>>
slug: z.ZodOptional<z.ZodString>
title: z.ZodString
body: z.ZodOptional<z.ZodString>
position: z.ZodOptional<z.ZodNumber>
is_published: z.ZodOptional<z.ZodBoolean>
},
z.core.$strip
>
wikiPageQuerySchemaZod schema for validating wiki-page list/query parameters.
const wikiPageQuerySchema: z.ZodObject<
{
space_id: z.ZodOptional<z.ZodString>
parent_id: z.ZodOptional<z.ZodNullable<z.ZodString>>
is_published: z.ZodOptional<z.ZodCoercedBoolean<unknown>>
q: z.ZodOptional<z.ZodString>
},
z.core.$strip
>
wikiPageUpdateSchemaZod schema for validating wiki-page update payloads.
const wikiPageUpdateSchema: z.ZodObject<
{
parent_id: z.ZodOptional<z.ZodNullable<z.ZodString>>
slug: z.ZodOptional<z.ZodString>
title: z.ZodOptional<z.ZodString>
body: z.ZodOptional<z.ZodString>
position: z.ZodOptional<z.ZodNumber>
is_published: z.ZodOptional<z.ZodBoolean>
},
z.core.$strip
>
Peer dependencies:
@molecule/api-bonds-default-express ^1.0.1@molecule/api-database ^1.0.1@molecule/api-i18n ^1.0.1@molecule/api-middleware-validation ^1.0.1@molecule/api-search ^1.0.1express ^5.0.0zod ^4.0.0@molecule/api-bonds-default-express@molecule/api-database@molecule/api-i18n@molecule/api-middleware-validation@molecule/api-searchexpresszodSession-auth prerequisite: every route reads the caller via
requireUser(res) (res.locals.session.userId, 401 fail-closed) — mount
createWikiPageRouter() behind your global auth middleware. There is no
routes/requestHandlerMap export; this package ships the Express router
factory shown above.
Access is space-scoped through getAccessibleSpace: a caller may READ a page
when they OWN its wiki_spaces row or the space is is_public. WRITES
(create/update/delete) are OWNER-ONLY — the write handlers additionally
require space.owner_id === userId, so a non-owner's write is refused (404)
even in a public space. If you need collaborative editing across a space,
wrap the router with your own role gate.
This package ships no space CRUD: create/seed the wiki_spaces row yourself
before creating pages. DELETE /:id is recursive (children first). If a
search provider is bonded via @molecule/api-search, creates and updates
index content automatically.
Tables: src/__setup__/wiki_pages.sql creates wiki_spaces and
wiki_pages. An mlcl-scaffolded API replays __setup__/*.sql automatically
on migrate; anywhere else run it once — nothing at runtime creates them.
Integration checklist — drive the real UI (live preview, no mocks), adapt
each item to this app's actual wiki/docs screens/flows, and check every box
off one by one. A box you can't check is an integration bug to fix — not a
skip. Reality check on versioning: this resource stores ONE current body per
page (updatePage is an in-place updateById) — there is NO built-in
revision history, revert, or diff, and no per-page author column (only
created_at/updated_at). So verify edits persist, and confirm the app does
NOT present a "version history / restore / last edited by" UI it cannot back
(that needs the app's own versions table — this resource will not supply it):
parent_id nests under its parent in the tree, and its breadcrumbs
(GET /:id/breadcrumbs) list the full root → page trail in order; deleting a
parent recursively removes its children (they vanish), never orphaning them.