| 1 | + | /** |
| 2 | + | * API reference data source for the docs app. |
| 3 | + | * |
| 4 | + | * Parses the `.d.ts` definitions of `@lazarv/react-server` and exposes: |
| 5 | + | * |
| 6 | + | * apiReferenceIndex() → metadata for every subpath page (sidebar, |
| 7 | + | * SSG enumeration, landing TOC) |
| 8 | + | * getApiReferenceData(slug) → structured page data (groups + items with |
| 9 | + | * signatures, JSDoc, examples) for the |
| 10 | + | * dynamic `/api/[slug]` JSX component |
| 11 | + | * renderApiReferencePageMdx(slug) → MDX body fragment for the |
| 12 | + | * dynamic route (compiled at request time |
| 13 | + | * through the same plugin chain as real |
| 14 | + | * `.mdx` pages) |
| 15 | + | * renderApiReferencePageMarkdown(slug) → plain markdown for the `.md` |
| 16 | + | * variant served to AI consumers |
| 17 | + | * renderApiReferenceLandingMarkdown() → landing `.md` variant |
| 18 | + | * |
| 19 | + | * No files are written to disk. The docs app pulls from these functions on |
| 20 | + | * every request in dev and at SSG build time. |
| 21 | + | * |
| 22 | + | * Each page's JSDoc description / `@param` / `@returns` / `@example` / |
| 23 | + | * `@deprecated` / `@see` is extracted via the TypeScript Compiler API. |
| 24 | + | */ |
| 25 | + | |
| 26 | + | import { createRequire } from "node:module"; |
| 27 | + | import fs from "node:fs"; |
| 28 | + | import path from "node:path"; |
| 29 | + | |
| 30 | + | // `createRequire` gives us a Node CJS resolver we can call at runtime. |
| 31 | + | // Used for two separate things: |
| 32 | + | // |
| 33 | + | // 1. Loading the `typescript` package on demand for the `.d.ts` |
| 34 | + | // parser. The require argument is held in a variable, not a |
| 35 | + | // literal — Rolldown only statically inlines `require("literal")` |
| 36 | + | // and leaves `require(var)` as runtime resolution. This keeps |
| 37 | + | // `typescript` out of every bundle, including the Cloudflare edge |
| 38 | + | // worker where `noExternal: true` would otherwise inline it and |
| 39 | + | // fail on its CJS `__filename` references. |
| 40 | + | // |
| 41 | + | // At SSG build time (Node) `require(tsModuleId)` resolves the |
| 42 | + | // package from the workspace's `node_modules`. At edge runtime |
| 43 | + | // `getTs()` is never reached for any path that actually ships — |
| 44 | + | // pre-rendered pages are served as assets and never invoke the |
| 45 | + | // parser — so the missing module never matters. |
| 46 | + | // |
| 47 | + | // 2. Resolving `@lazarv/react-server/*` `.d.ts` file paths via the |
| 48 | + | // runtime package's `"./*": "./*"` exports catch-all, which makes |
| 49 | + | // every file inside the package reachable by package name without |
| 50 | + | // any repo-layout assumption. |
| 51 | + | const require = createRequire(import.meta.url); |
| 52 | + | const tsModuleId = "typescript"; |
| 53 | + | |
| 54 | + | let _ts; |
| 55 | + | function getTs() { |
| 56 | + | if (!_ts) _ts = require(tsModuleId); |
| 57 | + | return _ts; |
| 58 | + | } |
| 59 | + | let _printer; |
| 60 | + | function getPrinter() { |
| 61 | + | if (!_printer) { |
| 62 | + | const ts = getTs(); |
| 63 | + | _printer = ts.createPrinter({ |
| 64 | + | removeComments: true, |
| 65 | + | newLine: ts.NewLineKind.LineFeed, |
| 66 | + | }); |
| 67 | + | } |
| 68 | + | return _printer; |
| 69 | + | } |
| 70 | + | |
| 71 | + | function resolveDts(relativePath) { |
| 72 | + | return require.resolve(`@lazarv/react-server/${relativePath}`); |
| 73 | + | } |
| 74 | + | |
| 75 | + | // ───────────────────────────────────────────────────────────────────────────── |
| 76 | + | // Page registry |
| 77 | + | // ───────────────────────────────────────────────────────────────────────────── |
| 78 | + | const pages = [ |
| 79 | + | { |
| 80 | + | slug: "core", |
| 81 | + | title: "Core", |
| 82 | + | importPath: "@lazarv/react-server", |
| 83 | + | dts: "server/index.d.ts", |
| 84 | + | order: 1, |
| 85 | + | description: |
| 86 | + | "The core runtime entry point. Exports the primitives every server component, middleware, and route handler relies on — HTTP context hooks, cookie helpers, caching utilities, and rendering controls.", |
| 87 | + | }, |
| 88 | + | { |
| 89 | + | slug: "client", |
| 90 | + | title: "Client", |
| 91 | + | importPath: "@lazarv/react-server/client", |
| 92 | + | dts: "client/index.d.ts", |
| 93 | + | order: 2, |
| 94 | + | description: |
| 95 | + | "Client-side runtime helpers. Exposes the client and outlet contexts used by navigation, refresh, and prefetching, plus the `ClientOnly` component for code that must only run after hydration.", |
| 96 | + | }, |
| 97 | + | { |
| 98 | + | slug: "router", |
| 99 | + | title: "Router", |
| 100 | + | importPath: "@lazarv/react-server/router", |
| 101 | + | dts: "server/router.d.ts", |
| 102 | + | order: 3, |
| 103 | + | description: |
| 104 | + | "Typed routing primitives for the file-system and programmatic routers. Includes route factories, schema-based validators, and the type-level helpers that extract params from route patterns.", |
| 105 | + | }, |
| 106 | + | { |
| 107 | + | slug: "navigation", |
| 108 | + | title: "Navigation", |
| 109 | + | importPath: "@lazarv/react-server/navigation", |
| 110 | + | dts: "client/navigation.d.ts", |
| 111 | + | order: 4, |
| 112 | + | description: |
| 113 | + | "Client navigation surface: `<Link>`, `<Form>`, `<Refresh>`, `<ReactServerComponent>`, hooks for location/search params/matching, navigation guards, redirect helpers, and scroll restoration.", |
| 114 | + | }, |
| 115 | + | { |
| 116 | + | slug: "resources", |
| 117 | + | title: "Resources", |
| 118 | + | importPath: "@lazarv/react-server/resources", |
| 119 | + | dts: "server/resources.d.ts", |
| 120 | + | order: 5, |
| 121 | + | description: |
| 122 | + | "Typed server resources — `createResource` / `createResources` — for binding validated data loaders to routes and reading them inside server components.", |
| 123 | + | }, |
| 124 | + | { |
| 125 | + | slug: "remote", |
| 126 | + | title: "Remote Components", |
| 127 | + | importPath: "@lazarv/react-server/remote", |
| 128 | + | dts: "server/remote.d.ts", |
| 129 | + | order: 6, |
| 130 | + | description: |
| 131 | + | "Loads a remote React component from another `@lazarv/react-server` deployment and renders it server-side, hydrating any client components via an import map.", |
| 132 | + | }, |
| 133 | + | { |
| 134 | + | slug: "error-boundary", |
| 135 | + | title: "Error Boundary", |
| 136 | + | importPath: "@lazarv/react-server/error-boundary", |
| 137 | + | dts: "server/error-boundary.d.ts", |
| 138 | + | order: 7, |
| 139 | + | description: |
| 140 | + | "Error boundary primitives for server components: catch rendering errors, render fallbacks, and surface error info to your observability stack.", |
| 141 | + | }, |
| 142 | + | { |
| 143 | + | slug: "prerender", |
| 144 | + | title: "Prerender", |
| 145 | + | importPath: "@lazarv/react-server/prerender", |
| 146 | + | dts: "server/prerender.d.ts", |
| 147 | + | order: 8, |
| 148 | + | description: |
| 149 | + | "Partial pre-rendering controls: `usePrerender` to mark a component for build-time rendering, and the `withPrerender` HOC wrapper.", |
| 150 | + | }, |
| 151 | + | { |
| 152 | + | slug: "memory-cache", |
| 153 | + | title: "Memory Cache", |
| 154 | + | importPath: "@lazarv/react-server/memory-cache", |
| 155 | + | dts: ["cache/index.d.ts", "cache/client.d.ts"], |
| 156 | + | order: 9, |
| 157 | + | description: |
| 158 | + | "Default in-memory cache provider. Exposes `useCache`, `invalidate`, and the client-side helpers used when the runtime's built-in cache is active.", |
| 159 | + | }, |
| 160 | + | { |
| 161 | + | slug: "storage-cache", |
| 162 | + | title: "Storage Cache", |
| 163 | + | importPath: "@lazarv/react-server/storage-cache", |
| 164 | + | dts: "cache/storage-cache.d.ts", |
| 165 | + | order: 10, |
| 166 | + | description: |
| 167 | + | "Durable cache backend built on [unstorage](https://unstorage.unjs.io/). Supports any unstorage driver — Redis, Cloudflare KV, Upstash, filesystem, etc.", |
| 168 | + | }, |
| 169 | + | { |
| 170 | + | slug: "rsc", |
| 171 | + | title: "RSC", |
| 172 | + | importPath: "@lazarv/react-server/rsc", |
| 173 | + | dts: "cache/rsc.d.ts", |
| 174 | + | order: 11, |
| 175 | + | description: |
| 176 | + | "Low-level RSC serialization helpers — serialize and deserialize React server component payloads directly. Most apps should not need these.", |
| 177 | + | }, |
| 178 | + | { |
| 179 | + | slug: "worker", |
| 180 | + | title: "Worker", |
| 181 | + | importPath: "@lazarv/react-server/worker", |
| 182 | + | dts: "worker/index.d.ts", |
| 183 | + | order: 12, |
| 184 | + | description: |
| 185 | + | 'Helpers for modules marked with the `"use worker"` directive. On the server runs in a Node Worker Thread; on the client runs in a Web Worker.', |
| 186 | + | }, |
| 187 | + | { |
| 188 | + | slug: "mcp", |
| 189 | + | title: "MCP", |
| 190 | + | importPath: "@lazarv/react-server/mcp", |
| 191 | + | dts: "server/mcp.d.ts", |
| 192 | + | order: 13, |
| 193 | + | description: |
| 194 | + | "Model Context Protocol primitives. Build typed tools, resources, and prompts, then expose them through an MCP server route handler.", |
| 195 | + | }, |
| 196 | + | { |
| 197 | + | slug: "http", |
| 198 | + | title: "HTTP", |
| 199 | + | importPath: "@lazarv/react-server/http", |
| 200 | + | dts: "lib/http/index.d.ts", |