import fs from "node:fs"; import path from "node:path"; import { DOCS, DOC_GROUP_ORDER, type DocEntry, type DocGroup, } from "../../content/docs"; export type { DocEntry, DocGroup }; export { DOC_GROUP_ORDER }; // Build-time only. `output: "export"` means every one of these reads happens // during `next build`; nothing here runs per request. Mirrors the // readFileSync-from-cwd approach in export/app/changelog/page.tsx. // // Every path op on a cwd-derived path opts out of Turbopack's asset tracing // (plans/FACTS.md, "A path joined from `process.cwd()` …"). function docPath(entry: DocEntry): string { return path.join(/* turbopackIgnore: true */ process.cwd(), "content", "docs", entry.file); } // The manifest entries whose file actually exists. // // This filter is the whole safety property of the docs subsystem: it feeds BOTH // `generateStaticParams()` (with `dynamicParams = false`) AND the /docs/ index, // so a manifest entry with a missing file 404s quietly instead of crashing the // build, and the index can never link to a page that isn't there. Those two // facts have to come from the same call, or they will disagree. export function listDocs(): DocEntry[] { return DOCS.filter((entry) => { try { return fs.statSync(/* turbopackIgnore: true */ docPath(entry)).isFile(); } catch { return false; } }); } export function findDoc(slug: string): DocEntry | null { return listDocs().find((d) => d.slug === slug) ?? null; } // Read a doc's Markdown, minus its leading `# Title` line. The file keeps that // heading so it stands alone as a document; the page renders its own