import fs from "node:fs/promises"; import path from "node:path"; import catalog from "../../../../content/catalog.json"; const directory = path.resolve(process.cwd(), "../../content/docs"); const validSlug = /^[a-z0-9]+(?:-[a-z0-9]+)*(?:\/[a-z0-9]+(?:-[a-z0-9]+)*)*$/; type Metadata = { slug?: string; category?: string; collection?: string; group?: string; description?: string; draft?: boolean; featured?: boolean }; export type DocLink = { slug: string; sourceSlug: string; category: string; title: string; searchText?: string; group: string; collection: string; description: string; draft: boolean; featured: boolean; }; export type Doc = DocLink & { content: string }; export async function readDoc(slug: string): Promise { if (!validSlug.test(slug)) throw new Error("Invalid document slug"); const sourceSlug = Object.entries(catalog.documents).find(([, metadata]) => metadata.slug === slug)?.[0] ?? slug; const content = await fs.readFile(path.join(directory, `${sourceSlug}.md`), "utf8"); const title = content.match(/^# (.+)$/m)?.[1]?.trim() ?? slug; const collection = catalog.collections.find((c) => !c.path || sourceSlug.startsWith(`${c.path}/`))!; const metadata: Metadata = (catalog.documents as Record)[sourceSlug] ?? {}; if (!metadata.slug || !metadata.category || !validSlug.test(metadata.slug) || metadata.slug.split("/").some((part) => /^\d+-/.test(part))) { throw new Error(`Register a semantic slug and category in content/catalog.json: ${sourceSlug}`); } return { slug: metadata.slug, sourceSlug, category: metadata.category, title, content, searchText: content, group: metadata.group ?? collection.title, collection: metadata.collection ?? collection.title, description: metadata.description ?? collection.description, draft: metadata.draft ?? false, featured: metadata.featured ?? false, }; } export async function listDocs(): Promise { async function walk(folder: string): Promise { const entries = await fs.readdir(path.join(directory, folder), { withFileTypes: true }); const files = await Promise.all(entries.map(async (entry) => { const relative = folder ? `${folder}/${entry.name}` : entry.name; if (entry.isDirectory()) return walk(relative); if (entry.isFile() && relative.endsWith(".md") && validSlug.test(relative.slice(0, -3))) return [relative.slice(0, -3)]; return []; })); return files.flat(); } const docs = await Promise.all((await walk("")).sort().map(async (slug) => { const { content: _, searchText: __, ...doc } = await readDoc(slug); void _; void __; return doc; })); if (new Set(docs.map((doc) => doc.slug)).size !== docs.length) throw new Error("Duplicate public document slug"); return docs; }