reroute-js 0.34.7 → 0.34.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/bin.d.ts +1 -1
- package/cli/bin.js +199 -78
- package/cli/bin.js.map +13 -13
- package/cli/index.d.ts +1 -1
- package/cli/index.js +4 -4
- package/cli/index.js.map +1 -1
- package/cli/src/cli.d.ts +1 -1
- package/cli/src/commands/analyze.d.ts +1 -1
- package/cli/src/commands/build.d.ts +1 -1
- package/cli/src/commands/dev.d.ts +1 -1
- package/cli/src/commands/gen.d.ts +1 -1
- package/cli/src/commands/gen.d.ts.map +1 -1
- package/cli/src/commands/index.d.ts +1 -1
- package/cli/src/commands/init.d.ts +1 -1
- package/cli/src/commands/lib/assets.d.ts +1 -1
- package/cli/src/commands/lib/bundler.d.ts +1 -1
- package/cli/src/commands/lib/command.d.ts +1 -1
- package/cli/src/commands/lib/env.d.ts +1 -1
- package/cli/src/commands/lib/index.d.ts +1 -1
- package/cli/src/commands/lib/log.d.ts +1 -1
- package/cli/src/commands/lib/markdown/availability.d.ts +1 -1
- package/cli/src/commands/lib/markdown/index.d.ts +1 -1
- package/cli/src/commands/lib/markdown/processor.d.ts +1 -1
- package/cli/src/commands/lib/production.d.ts +1 -1
- package/cli/src/commands/lib/server.d.ts +1 -1
- package/cli/src/commands/lib/streaming/analyzer.d.ts +1 -1
- package/cli/src/commands/lib/streaming/suspense.d.ts +1 -1
- package/cli/src/commands/lib/tailwind.d.ts +1 -1
- package/cli/src/commands/lib/terminal-ui.d.ts +1 -1
- package/cli/src/commands/lib/version.d.ts +1 -1
- package/cli/src/commands/og.d.ts +1 -1
- package/cli/src/commands/start.d.ts +1 -1
- package/cli/src/index.d.ts +1 -1
- package/core/index.d.ts +1 -1
- package/core/index.js +194 -74
- package/core/index.js.map +12 -12
- package/core/src/bundler/hash.d.ts +1 -1
- package/core/src/bundler/index.d.ts +1 -1
- package/core/src/config.d.ts +1 -1
- package/core/src/content/discovery.d.ts +1 -1
- package/core/src/content/index.d.ts +1 -1
- package/core/src/content/metadata.d.ts +1 -1
- package/core/src/index.d.ts +1 -1
- package/core/src/llms/extractor.d.ts +1 -1
- package/core/src/llms/formatter.d.ts +1 -1
- package/core/src/llms/full-generator.d.ts +1 -1
- package/core/src/llms/full-generator.d.ts.map +1 -1
- package/core/src/llms/index-generator.d.ts +2 -3
- package/core/src/llms/index-generator.d.ts.map +1 -1
- package/core/src/llms/index.d.ts +1 -1
- package/core/src/og/discovery.d.ts +1 -1
- package/core/src/og/index.d.ts +1 -1
- package/core/src/og/meta.d.ts +1 -1
- package/core/src/og/render.d.ts +1 -1
- package/core/src/og/types.d.ts +1 -1
- package/core/src/robots/discovery.d.ts +1 -1
- package/core/src/robots/generator.d.ts +1 -1
- package/core/src/robots/index.d.ts +1 -1
- package/core/src/robots/policies.d.ts +1 -1
- package/core/src/rss/discovery.d.ts +4 -4
- package/core/src/rss/discovery.d.ts.map +1 -1
- package/core/src/rss/generator.d.ts +1 -1
- package/core/src/rss/index.d.ts +1 -1
- package/core/src/sitemap/discovery.d.ts +3 -3
- package/core/src/sitemap/discovery.d.ts.map +1 -1
- package/core/src/sitemap/generator.d.ts +1 -1
- package/core/src/sitemap/index.d.ts +1 -1
- package/core/src/ssr/index.d.ts +1 -1
- package/core/src/ssr/lib/cache.d.ts +1 -1
- package/core/src/ssr/lib/collections.d.ts +1 -1
- package/core/src/ssr/lib/compression.d.ts +1 -1
- package/core/src/ssr/lib/compute/content.d.ts +1 -1
- package/core/src/ssr/lib/compute/index.d.ts +4 -2
- package/core/src/ssr/lib/compute/index.d.ts.map +1 -1
- package/core/src/ssr/lib/compute/layouts.d.ts +1 -1
- package/core/src/ssr/lib/compute/routes.d.ts +1 -1
- package/core/src/ssr/lib/data.d.ts +1 -1
- package/core/src/ssr/lib/html.d.ts +1 -1
- package/core/src/ssr/lib/imports.d.ts +1 -1
- package/core/src/ssr/lib/index.d.ts +1 -1
- package/core/src/ssr/lib/layouts.d.ts +1 -1
- package/core/src/ssr/lib/metadata.d.ts +1 -1
- package/core/src/ssr/lib/metadata.d.ts.map +1 -1
- package/core/src/ssr/lib/mime.d.ts +1 -1
- package/core/src/ssr/lib/modules.d.ts +1 -1
- package/core/src/ssr/lib/path.d.ts +1 -1
- package/core/src/ssr/lib/preload.d.ts +1 -1
- package/core/src/ssr/lib/preload.d.ts.map +1 -1
- package/core/src/ssr/lib/scripts/collections.d.ts +1 -1
- package/core/src/ssr/lib/scripts/data.d.ts +1 -1
- package/core/src/ssr/lib/scripts/escape.d.ts +1 -1
- package/core/src/ssr/lib/scripts/feeds.d.ts +1 -1
- package/core/src/ssr/lib/scripts/index.d.ts +1 -1
- package/core/src/ssr/lib/seed.d.ts +1 -1
- package/core/src/ssr/lib/serialize.d.ts +1 -1
- package/core/src/ssr/lib/setup.d.ts +1 -1
- package/core/src/ssr/lib/styles.d.ts +1 -1
- package/core/src/ssr/lib/template.d.ts +1 -1
- package/core/src/ssr/lib/types.d.ts +1 -1
- package/core/src/ssr/render.d.ts +1 -1
- package/core/src/ssr/stream.d.ts +1 -1
- package/elysia/index.d.ts +1 -1
- package/elysia/index.js +204 -88
- package/elysia/index.js.map +16 -16
- package/elysia/src/index.d.ts +1 -1
- package/elysia/src/libs/assets.d.ts +1 -1
- package/elysia/src/libs/cache.d.ts +1 -1
- package/elysia/src/libs/caching.d.ts +1 -1
- package/elysia/src/libs/http.d.ts +1 -1
- package/elysia/src/libs/image.d.ts +1 -1
- package/elysia/src/libs/index.d.ts +1 -1
- package/elysia/src/libs/llms.d.ts +1 -1
- package/elysia/src/libs/response.d.ts +1 -1
- package/elysia/src/libs/serving.d.ts +1 -1
- package/elysia/src/plugin.d.ts +1 -1
- package/elysia/src/plugin.d.ts.map +1 -1
- package/elysia/src/routes/artifacts.d.ts +1 -1
- package/elysia/src/routes/content.d.ts +1 -1
- package/elysia/src/routes/image.d.ts +1 -1
- package/elysia/src/routes/index.d.ts +1 -1
- package/elysia/src/routes/internal.d.ts +1 -1
- package/elysia/src/routes/llms.d.ts +1 -1
- package/elysia/src/routes/llms.d.ts.map +1 -1
- package/elysia/src/routes/og.d.ts +1 -1
- package/elysia/src/routes/redirects.d.ts +1 -1
- package/elysia/src/routes/robots.d.ts +1 -1
- package/elysia/src/routes/rss.d.ts +1 -1
- package/elysia/src/routes/rss.d.ts.map +1 -1
- package/elysia/src/routes/search.d.ts +1 -1
- package/elysia/src/routes/sitemap.d.ts +1 -2
- package/elysia/src/routes/sitemap.d.ts.map +1 -1
- package/elysia/src/routes/ssr.d.ts +1 -1
- package/elysia/src/routes/static.d.ts +1 -1
- package/elysia/src/types.d.ts +1 -1
- package/package.json +1 -1
- package/react/index.d.ts +1 -1
- package/react/index.js +2 -2
- package/react/index.js.map +1 -1
- package/react/src/components/ClientOnly.d.ts +1 -1
- package/react/src/components/ContentRoute.d.ts +1 -1
- package/react/src/components/Image.d.ts +1 -1
- package/react/src/components/LazyRoute.d.ts +1 -1
- package/react/src/components/Link.d.ts +1 -1
- package/react/src/components/Markdown.d.ts +1 -1
- package/react/src/components/Outlet.d.ts +1 -1
- package/react/src/components/index.d.ts +1 -1
- package/react/src/hooks/index.d.ts +1 -1
- package/react/src/hooks/useContent.d.ts +1 -1
- package/react/src/hooks/useData.d.ts +1 -1
- package/react/src/hooks/useFeed.d.ts +1 -1
- package/react/src/hooks/useLayoutData.d.ts +1 -1
- package/react/src/hooks/useLlms.d.ts +1 -1
- package/react/src/hooks/useNavigate.d.ts +1 -1
- package/react/src/hooks/useParams.d.ts +1 -1
- package/react/src/hooks/useRouter.d.ts +1 -1
- package/react/src/hooks/useSearch.d.ts +1 -1
- package/react/src/hooks/useSearchParams.d.ts +1 -1
- package/react/src/hooks/useToc.d.ts +1 -1
- package/react/src/index.d.ts +1 -1
- package/react/src/lib/collection.d.ts +1 -1
- package/react/src/lib/content.d.ts +1 -1
- package/react/src/lib/head.d.ts +1 -1
- package/react/src/lib/index.d.ts +1 -1
- package/react/src/lib/lazy-route.d.ts +1 -1
- package/react/src/lib/route-loader.d.ts +1 -1
- package/react/src/providers/ContentProvider.d.ts +1 -1
- package/react/src/providers/RerouteProvider.d.ts +1 -1
- package/react/src/providers/RouterProvider.d.ts +1 -1
- package/react/src/providers/index.d.ts +1 -1
- package/react/src/types/any.d.ts +1 -1
- package/react/src/types/index.d.ts +1 -1
- package/react/src/types/router.d.ts +1 -1
- package/telemetry/react.d.ts +1 -1
- package/telemetry/react.js +2 -2
- package/telemetry/react.js.map +1 -1
- package/telemetry/server.d.ts +1 -1
- package/telemetry/server.js +3 -2
- package/telemetry/server.js.map +10 -10
- package/telemetry/src/react/api.d.ts +1 -1
- package/telemetry/src/react/context.d.ts +1 -1
- package/telemetry/src/react/index.d.ts +1 -1
- package/telemetry/src/react/telemetry.d.ts +1 -1
- package/telemetry/src/server/context.d.ts +1 -1
- package/telemetry/src/server/index.d.ts +1 -1
- package/telemetry/src/server/instrumentation.d.ts +1 -1
- package/telemetry/src/server/plugin.d.ts +1 -1
- package/telemetry/src/server/sourcemap.d.ts +1 -1
package/telemetry/server.js.map
CHANGED
|
@@ -11,27 +11,27 @@
|
|
|
11
11
|
"import { ssrCache, statusCache } from '../cache';\nimport { toPromise } from '../imports';\nimport type { ComputeOptions, Doc } from '../types';\n\ntype ContentComputeResult = {\n\tdata: Record<string, unknown>;\n\terror?: string;\n\tstatusOverride?: number;\n\tpendingTasks: Promise<unknown>[];\n};\n\nfunction checkStatusCache(\n\tstatusCacheKey: string,\n\tmaxAgeMs: number,\n): number | undefined {\n\tif (maxAgeMs <= 0) return undefined;\n\treturn statusCache.get<number>(statusCacheKey);\n}\n\nfunction checkDataCache(cacheKey: string, maxAgeMs: number): unknown {\n\tif (maxAgeMs <= 0) return undefined;\n\treturn ssrCache.get(cacheKey);\n}\n\nfunction createDataTask(\n\tdataFn: (ctx: Doc) => unknown | Promise<unknown>,\n\tpathname: string,\n\tparts: string[],\n\tsearchParams: URLSearchParams | undefined,\n\tset: { status: number },\n): Promise<unknown> {\n\treturn toPromise(\n\t\tdataFn({\n\t\t\tpathname,\n\t\t\tparams: { name: parts[1] },\n\t\t\tset,\n\t\t\tsearchParams,\n\t\t} as Doc),\n\t).catch((err) => {\n\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\tconst error = `SSR data() failed: ${msg}`;\n\t\tconsole.error(`[reroute] ${error}`);\n\t\tthrow err;\n\t});\n}\n\nfunction handleStreamingMode(\n\tssrData: Record<string, unknown>,\n\tpathname: string,\n\ttask: Promise<unknown>,\n\tset: { status: number },\n\tcacheKey: string,\n\tstatusCacheKey: string,\n\tmaxAgeMs: number,\n\tpendingTasks: Promise<unknown>[],\n): void {\n\tssrData[pathname] = task;\n\n\tconst storeTask = task.then((value) => {\n\t\tif (set.status !== 200) {\n\t\t\t// statusOverride handled by caller\n\t\t}\n\t\tif (maxAgeMs > 0) {\n\t\t\tstatusCache.set(statusCacheKey, set.status, maxAgeMs);\n\t\t}\n\t\tif (maxAgeMs > 0 && set.status === 200) {\n\t\t\tssrCache.set(cacheKey, value, maxAgeMs);\n\t\t}\n\t\treturn value;\n\t});\n\n\tpendingTasks.push(\n\t\tstoreTask\n\t\t\t.then((value) => {\n\t\t\t\tssrData[pathname] = value;\n\t\t\t})\n\t\t\t.catch(() => {}),\n\t);\n}\n\nasync function handleNonStreamingMode(\n\tssrData: Record<string, unknown>,\n\tpathname: string,\n\ttask: Promise<unknown>,\n\tcacheKey: string,\n\tstatusCacheKey: string,\n\tmaxAgeMs: number,\n): Promise<unknown> {\n\tconst result = await task;\n\tssrData[pathname] = result;\n\n\tif (maxAgeMs > 0) {\n\t\tstatusCache.set(\n\t\t\tstatusCacheKey,\n\t\t\t(result as { status?: number }).status || 200,\n\t\t\tmaxAgeMs,\n\t\t);\n\t}\n\tif (maxAgeMs > 0) {\n\t\tssrCache.set(cacheKey, result, maxAgeMs);\n\t}\n\n\treturn result;\n}\n\n/**\n * Compute SSR data for content pages (e.g., /blog/my-post).\n * Content pages export ssr.data via __REROUTE_SSR_EXPORTS__.\n *\n * @param sharedSsrData - In streaming mode, the shared ssrData object that gets passed to React.\n * Promise resolution callbacks must update THIS object directly.\n */\nexport async function computeContentData(\n\tpathname: string,\n\toptions: ComputeOptions,\n\tsearchParams?: URLSearchParams,\n\tsharedSsrData?: Record<string, unknown>,\n): Promise<ContentComputeResult> {\n\tconst streaming = options.streaming === true;\n\tconst ssrData: Record<string, unknown> =\n\t\tstreaming && sharedSsrData ? sharedSsrData : {};\n\tconst pendingTasks: Promise<unknown>[] = [];\n\tlet error: string | undefined;\n\tlet statusOverride: number | undefined;\n\n\tconst maxAge = options.maxAge || 0;\n\tconst maxAgeMs = maxAge * 1000;\n\n\ttry {\n\t\tconst parts = pathname.split('/').filter(Boolean);\n\t\tif (parts.length < 2) {\n\t\t\treturn { data: ssrData, pendingTasks };\n\t\t}\n\n\t\tconst g = globalThis as Doc;\n\t\tconst key = `${parts[0]}:${parts[1]}`;\n\t\tconst exp = g.__REROUTE_SSR_EXPORTS__?.[key] as\n\t\t\t| { ssr?: { data?: (ctx: Doc) => unknown | Promise<unknown> } }\n\t\t\t| undefined;\n\n\t\tconst dataFn = (exp as Doc)?.ssr?.data as\n\t\t\t| ((ctx: Doc) => unknown | Promise<unknown>)\n\t\t\t| undefined;\n\n\t\tif (typeof dataFn !== 'function') {\n\t\t\treturn { data: ssrData, pendingTasks };\n\t\t}\n\n\t\tconst cacheKey = `content:${pathname}:${parts[1]}`;\n\t\tconst statusCacheKey = `status:${cacheKey}`;\n\n\t\tconst cachedStatus = checkStatusCache(statusCacheKey, maxAgeMs);\n\t\tif (cachedStatus && cachedStatus !== 200) {\n\t\t\tstatusOverride = cachedStatus;\n\t\t}\n\n\t\tconst cached = checkDataCache(cacheKey, maxAgeMs);\n\t\tif (cached !== undefined) {\n\t\t\tssrData[pathname] = cached;\n\t\t\treturn { data: ssrData, statusOverride, pendingTasks };\n\t\t}\n\n\t\tconst set = { status: 200 };\n\t\tconst task = createDataTask(dataFn, pathname, parts, searchParams, set);\n\n\t\tif (streaming) {\n\t\t\thandleStreamingMode(\n\t\t\t\tssrData,\n\t\t\t\tpathname,\n\t\t\t\ttask,\n\t\t\t\tset,\n\t\t\t\tcacheKey,\n\t\t\t\tstatusCacheKey,\n\t\t\t\tmaxAgeMs,\n\t\t\t\tpendingTasks,\n\t\t\t);\n\t\t\tif (set.status !== 200) {\n\t\t\t\tstatusOverride = set.status;\n\t\t\t}\n\t\t} else {\n\t\t\tawait handleNonStreamingMode(\n\t\t\t\tssrData,\n\t\t\t\tpathname,\n\t\t\t\ttask,\n\t\t\t\tcacheKey,\n\t\t\t\tstatusCacheKey,\n\t\t\t\tmaxAgeMs,\n\t\t\t);\n\t\t\tif (set.status !== 200) {\n\t\t\t\tstatusOverride = set.status;\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Return what we have on error\n\t}\n\n\treturn { data: ssrData, error, statusOverride, pendingTasks };\n}\n",
|
|
12
12
|
"import { ssrCache, statusCache } from '../cache';\nimport { dynamicImport, toPromise } from '../imports';\nimport {\n\tcreateLayoutCacheKey,\n\tcreateLayoutDataKey,\n\tgetMatchingLayouts,\n} from '../layouts';\nimport { join } from '../path';\nimport type { ComputeOptions, Doc } from '../types';\n\ntype LayoutComputeResult = {\n\tdata: Record<string, unknown>;\n\tstatusOverride?: number;\n\tpendingTasks: Promise<unknown>[];\n};\n\nasync function loadLayoutSSRExport(\n\tlayout: Doc,\n\tclientDir: string,\n\tisWatchMode: boolean,\n): Promise<Doc | undefined> {\n\tlet ssrExport = (layout as Doc)?.ssr as Doc | undefined;\n\n\tif (!ssrExport) {\n\t\tconst abs = join(clientDir, 'routes', String(layout.path));\n\t\tconst mod = await dynamicImport(abs, isWatchMode);\n\t\tssrExport = (mod as Doc)?.ssr as Doc | undefined;\n\t}\n\n\treturn ssrExport;\n}\n\nfunction checkLayoutCache(\n\tcacheKey: string,\n\tstatusCacheKey: string,\n\tmaxAgeMs: number,\n): { cachedData?: unknown; cachedStatus?: number } {\n\tconst cachedStatus =\n\t\tmaxAgeMs > 0 ? statusCache.get<number>(statusCacheKey) : undefined;\n\tconst cachedData = maxAgeMs > 0 ? ssrCache.get(cacheKey) : undefined;\n\n\treturn { cachedData, cachedStatus };\n}\n\nfunction createLayoutDataTask(\n\tdataFn: (ctx: Doc) => unknown | Promise<unknown>,\n\tpathname: string,\n\tsearchParams: URLSearchParams | undefined,\n\tlayoutPattern: string,\n): Promise<unknown> {\n\tconst set = { status: 200 };\n\treturn toPromise(\n\t\tdataFn({ pathname, params: {}, set, searchParams } as Doc),\n\t).catch((err) => {\n\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\tconsole.error(\n\t\t\t`[reroute] Layout SSR data() failed for ${layoutPattern}:`,\n\t\t\tmsg,\n\t\t);\n\t\tthrow err;\n\t});\n}\n\nfunction handleLayoutStreamingMode(\n\tssrData: Record<string, unknown>,\n\tlayoutKey: string,\n\ttask: Promise<unknown>,\n\tset: { status: number },\n\tcacheKey: string,\n\tstatusCacheKey: string,\n\tmaxAgeMs: number,\n\tpendingTasks: Promise<unknown>[],\n): void {\n\tssrData[layoutKey] = task;\n\n\tconst storeTask = task.then((value) => {\n\t\tif (maxAgeMs > 0) {\n\t\t\tstatusCache.set(statusCacheKey, set.status, maxAgeMs);\n\t\t}\n\t\tif (maxAgeMs > 0 && set.status === 200) {\n\t\t\tssrCache.set(cacheKey, value, maxAgeMs);\n\t\t}\n\t\treturn value;\n\t});\n\n\tpendingTasks.push(\n\t\tstoreTask\n\t\t\t.then((value) => {\n\t\t\t\tssrData[layoutKey] = value;\n\t\t\t})\n\t\t\t.catch(() => {}),\n\t);\n}\n\nasync function handleLayoutNonStreamingMode(\n\tssrData: Record<string, unknown>,\n\tlayoutKey: string,\n\ttask: Promise<unknown>,\n\tcacheKey: string,\n\tstatusCacheKey: string,\n\tmaxAgeMs: number,\n): Promise<unknown> {\n\tconst result = await task;\n\tssrData[layoutKey] = result;\n\n\tif (maxAgeMs > 0) {\n\t\tstatusCache.set(\n\t\t\tstatusCacheKey,\n\t\t\t(result as { status?: number }).status || 200,\n\t\t\tmaxAgeMs,\n\t\t);\n\t}\n\tif (maxAgeMs > 0) {\n\t\tssrCache.set(cacheKey, result, maxAgeMs);\n\t}\n\n\treturn result;\n}\n\nasync function processLayout(\n\tlayout: Doc,\n\tpathname: string,\n\tclientDir: string,\n\tisWatchMode: boolean,\n\tstreaming: boolean,\n\tmaxAgeMs: number,\n\tsearchParams: URLSearchParams | undefined,\n\tssrData: Record<string, unknown>,\n\tpendingTasks: Promise<unknown>[],\n): Promise<number | undefined> {\n\tif (typeof layout?.path !== 'string') return undefined;\n\n\tconst ssrExport = await loadLayoutSSRExport(layout, clientDir, isWatchMode);\n\tconst dataFn = ssrExport?.data as\n\t\t| ((ctx: Doc) => unknown | Promise<unknown>)\n\t\t| undefined;\n\n\tif (typeof dataFn !== 'function') return undefined;\n\n\tconst pattern = String(layout.pattern || '/');\n\tconst layoutKey = createLayoutDataKey(pattern);\n\tconst cacheKey = createLayoutCacheKey(pattern, pathname);\n\tconst statusCacheKey = `status:${cacheKey}`;\n\n\tconst { cachedData, cachedStatus } = checkLayoutCache(\n\t\tcacheKey,\n\t\tstatusCacheKey,\n\t\tmaxAgeMs,\n\t);\n\n\tif (cachedStatus && cachedStatus !== 200) {\n\t\treturn cachedStatus;\n\t}\n\n\tif (cachedData !== undefined) {\n\t\tssrData[layoutKey] = cachedData;\n\t\treturn undefined;\n\t}\n\n\tconst set = { status: 200 };\n\tconst task = createLayoutDataTask(dataFn, pathname, searchParams, pattern);\n\n\tif (streaming) {\n\t\thandleLayoutStreamingMode(\n\t\t\tssrData,\n\t\t\tlayoutKey,\n\t\t\ttask,\n\t\t\tset,\n\t\t\tcacheKey,\n\t\t\tstatusCacheKey,\n\t\t\tmaxAgeMs,\n\t\t\tpendingTasks,\n\t\t);\n\t} else {\n\t\tawait handleLayoutNonStreamingMode(\n\t\t\tssrData,\n\t\t\tlayoutKey,\n\t\t\ttask,\n\t\t\tcacheKey,\n\t\t\tstatusCacheKey,\n\t\t\tmaxAgeMs,\n\t\t);\n\t}\n\n\treturn set.status !== 200 ? set.status : undefined;\n}\n\n/**\n * Compute SSR data from all matching layouts for a pathname.\n * Executes layout ssr.data() functions in hierarchical order (root → nested).\n *\n * @param sharedSsrData - In streaming mode, the shared ssrData object that gets passed to React.\n * Promise resolution callbacks must update THIS object directly.\n */\nexport async function computeLayoutData(\n\tpathname: string,\n\tclientDir: string,\n\t_cwd: string,\n\tisWatchMode: boolean,\n\toptions: ComputeOptions,\n\tsearchParams?: URLSearchParams,\n\troutesModule?: Doc,\n\tsharedSsrData?: Record<string, unknown>,\n): Promise<LayoutComputeResult> {\n\tconst streaming = options.streaming === true;\n\tconst ssrData: Record<string, unknown> =\n\t\tstreaming && sharedSsrData ? sharedSsrData : {};\n\tconst pendingTasks: Promise<unknown>[] = [];\n\tlet statusOverride: number | undefined;\n\n\tconst maxAge = options.maxAge || 0;\n\tconst maxAgeMs = maxAge * 1000;\n\n\ttry {\n\t\tconst layouts = routesModule?.layouts as Doc[] | undefined;\n\t\tconst matchingLayouts = getMatchingLayouts(pathname, layouts);\n\n\t\tfor (const layout of matchingLayouts) {\n\t\t\ttry {\n\t\t\t\tconst layoutStatus = await processLayout(\n\t\t\t\t\tlayout,\n\t\t\t\t\tpathname,\n\t\t\t\t\tclientDir,\n\t\t\t\t\tisWatchMode,\n\t\t\t\t\tstreaming,\n\t\t\t\t\tmaxAgeMs,\n\t\t\t\t\tsearchParams,\n\t\t\t\t\tssrData,\n\t\t\t\t\tpendingTasks,\n\t\t\t\t);\n\n\t\t\t\tif (layoutStatus && !statusOverride) {\n\t\t\t\t\tstatusOverride = layoutStatus;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Continue to next layout on error\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Return empty data on failure\n\t}\n\n\treturn { data: ssrData, statusOverride, pendingTasks };\n}\n\n/**\n * Merge layout data into route data for non-streaming mode.\n * Users can call useData() without knowing about layout keys.\n */\nexport function mergeLayoutData(\n\tssrData: Record<string, unknown>,\n\tpathname: string,\n): void {\n\tconst layoutKeys = Object.keys(ssrData).filter((key) =>\n\t\tkey.startsWith('__layout:'),\n\t);\n\n\tconst layoutData: Record<string, unknown> = {};\n\tfor (const key of layoutKeys) {\n\t\tObject.assign(layoutData, ssrData[key] as Record<string, unknown>);\n\t}\n\n\tif (pathname in ssrData) {\n\t\tssrData[pathname] = {\n\t\t\t...layoutData,\n\t\t\t...(typeof ssrData[pathname] === 'object' && ssrData[pathname] !== null\n\t\t\t\t? (ssrData[pathname] as Record<string, unknown>)\n\t\t\t\t: {}),\n\t\t};\n\t} else if (Object.keys(layoutData).length > 0) {\n\t\tssrData[pathname] = layoutData;\n\t}\n}\n",
|
|
13
13
|
"import { ssrCache, statusCache } from '../cache';\nimport { dynamicImport, isThenable, toPromise } from '../imports';\nimport { join } from '../path';\nimport type { ComputeOptions, Doc, RouteMatch } from '../types';\n\ntype RouteComputeResult = {\n\tdata: Record<string, unknown>;\n\terror?: string;\n\tstatusOverride?: number;\n\tpendingTasks: Promise<unknown>[];\n};\n\n/**\n * Compute SSR data for route-level ssr.data() functions.\n * Handles both streaming and non-streaming modes with promise flattening.\n *\n * @param sharedSsrData - In streaming mode, the shared ssrData object that gets passed to React.\n * Promise resolution callbacks must update THIS object directly.\n */\nfunction checkCache(\n\tcacheKey: string,\n\tstatusCacheKey: string,\n\tmaxAgeMs: number,\n\tpathname: string,\n\tssrData: Record<string, unknown>,\n): { cached: boolean; statusOverride?: number } {\n\t// Check status cache first\n\tconst cachedStatus =\n\t\tmaxAgeMs > 0 ? statusCache.get<number>(statusCacheKey) : undefined;\n\tconst statusOverride =\n\t\tcachedStatus && cachedStatus !== 200 ? cachedStatus : undefined;\n\n\t// Check data cache\n\tconst cached = maxAgeMs > 0 ? ssrCache.get(cacheKey) : undefined;\n\n\tif (cached !== undefined) {\n\t\tssrData[pathname] = cached;\n\t\treturn { cached: true, statusOverride };\n\t}\n\n\treturn { cached: false, statusOverride };\n}\n\nasync function loadRouteSSRExport(\n\troute: Doc,\n\tclientDir: string,\n\tisWatchMode: boolean,\n): Promise<Doc | undefined> {\n\t// Try to use bundled ssr export first (compiled binary)\n\tlet ssrExport = (route as Doc)?.ssr;\n\n\t// Fallback to dynamic import if not bundled (dev mode)\n\tif (!ssrExport) {\n\t\tconst routePath = String(route.path);\n\t\tconst cwd = join(clientDir, '..');\n\n\t\t// Try streaming wrapper first (for routes with ssr.data())\n\t\tlet abs = join(cwd, '.reroute', 'streaming', routePath);\n\t\tlet mod = await dynamicImport(abs, isWatchMode).catch(() => null);\n\n\t\t// Fallback to source if streaming doesn't exist\n\t\tif (!mod) {\n\t\t\tabs = join(clientDir, 'routes', routePath);\n\t\t\tmod = await dynamicImport(abs, isWatchMode);\n\t\t}\n\n\t\tssrExport = (mod as Doc)?.ssr as Doc | undefined;\n\t}\n\n\treturn ssrExport;\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Route data computation handles caching, streaming, and promise flattening\nexport async function computeRouteData(\n\tpathname: string,\n\tclientDir: string,\n\t_cwd: string,\n\tisWatchMode: boolean,\n\toptions: ComputeOptions,\n\tsearchParams?: URLSearchParams,\n\troutesModule?: Doc,\n\tsharedSsrData?: Record<string, unknown>,\n): Promise<RouteComputeResult> {\n\tconst streaming = options.streaming === true;\n\tconst ssrData: Record<string, unknown> =\n\t\tstreaming && sharedSsrData ? sharedSsrData : {};\n\tconst pendingTasks: Promise<unknown>[] = [];\n\tlet error: string | undefined;\n\tlet statusOverride: number | undefined;\n\n\tconst maxAge = options.maxAge || 0;\n\tconst maxAgeMs = maxAge * 1000;\n\n\tconst storeResult = (key: string, task: Promise<unknown>) => {\n\t\tpendingTasks.push(\n\t\t\ttask\n\t\t\t\t.then((value) => {\n\t\t\t\t\tssrData[key] = value;\n\t\t\t\t})\n\t\t\t\t.catch(() => {}),\n\t\t);\n\t};\n\n\ttry {\n\t\t// Strip query string for route matching\n\t\tconst pathnameOnly = pathname.split('?')[0];\n\t\tconst match: RouteMatch =\n\t\t\ttypeof routesModule?.matchRoute === 'function'\n\t\t\t\t? routesModule.matchRoute(pathnameOnly)\n\t\t\t\t: null;\n\n\t\tconst route = match?.route;\n\t\tconst params = match?.params || {};\n\n\t\tif (!route || typeof route.path !== 'string') {\n\t\t\treturn { data: ssrData, pendingTasks };\n\t\t}\n\n\t\t// Load SSR export\n\t\tconst ssrExport = await loadRouteSSRExport(route, clientDir, isWatchMode);\n\n\t\tconst dataFn = ssrExport?.data as\n\t\t\t| ((ctx: Doc) => unknown | Promise<unknown>)\n\t\t\t| undefined;\n\n\t\tif (typeof dataFn !== 'function') {\n\t\t\treturn { data: ssrData, pendingTasks };\n\t\t}\n\n\t\t// Include search params in cache key\n\t\tconst searchQuery = searchParams ? `?${searchParams.toString()}` : '';\n\t\tconst cacheKey = `route:${pathname}${searchQuery}:${JSON.stringify(params)}`;\n\t\tconst statusCacheKey = `status:${cacheKey}`;\n\n\t\tconst cacheResult = checkCache(\n\t\t\tcacheKey,\n\t\t\tstatusCacheKey,\n\t\t\tmaxAgeMs,\n\t\t\tpathname,\n\t\t\tssrData,\n\t\t);\n\n\t\tif (cacheResult.cached) {\n\t\t\treturn {\n\t\t\t\tdata: ssrData,\n\t\t\t\tstatusOverride: cacheResult.statusOverride,\n\t\t\t\tpendingTasks,\n\t\t\t};\n\t\t}\n\n\t\tif (cacheResult.statusOverride) {\n\t\t\tstatusOverride = cacheResult.statusOverride;\n\t\t}\n\n\t\t// Execute data function\n\t\tconst set = { status: 200 };\n\t\tconst rawResult = dataFn({\n\t\t\tpathname,\n\t\t\tparams,\n\t\t\tset,\n\t\t\tsearchParams,\n\t\t} as Doc);\n\t\tconst isPromise = rawResult instanceof Promise;\n\n\t\tif (streaming) {\n\t\t\tconst result = await handleStreamingRouteData(\n\t\t\t\trawResult,\n\t\t\t\tisPromise,\n\t\t\t\tpathname,\n\t\t\t\tset,\n\t\t\t\t{ ssrData, pendingTasks, storeResult },\n\t\t\t\t{ cacheKey, statusCacheKey, maxAgeMs },\n\t\t\t\t(msg) => {\n\t\t\t\t\terror = msg;\n\t\t\t\t},\n\t\t\t\t(val) => {\n\t\t\t\t\tif (!statusOverride) statusOverride = val;\n\t\t\t\t},\n\t\t\t);\n\t\t\tObject.assign(ssrData, result);\n\t\t} else {\n\t\t\tconst task = toPromise(rawResult).catch((err) => {\n\t\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\t\terror = `SSR data() failed: ${msg}`;\n\t\t\t\tconsole.error(`[reroute] ${error}`);\n\t\t\t\tthrow err;\n\t\t\t});\n\n\t\t\tconst result = await task;\n\t\t\tif (set.status !== 200 && !statusOverride) {\n\t\t\t\tstatusOverride = set.status;\n\t\t\t}\n\t\t\tssrData[pathname] = result;\n\t\t\tif (maxAgeMs > 0) {\n\t\t\t\tstatusCache.set(statusCacheKey, set.status, maxAgeMs);\n\t\t\t}\n\t\t\tif (maxAgeMs > 0 && set.status === 200) {\n\t\t\t\tssrCache.set(cacheKey, result, maxAgeMs);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Return what we have on error\n\t}\n\n\treturn { data: ssrData, error, statusOverride, pendingTasks };\n}\n\ntype StreamingContext = {\n\tssrData: Record<string, unknown>;\n\tpendingTasks: Promise<unknown>[];\n\tstoreResult: (key: string, task: Promise<unknown>) => void;\n};\n\ntype CacheContext = {\n\tcacheKey: string;\n\tstatusCacheKey: string;\n\tmaxAgeMs: number;\n};\n\nfunction shouldFlattenResult(\n\trawResult: unknown,\n\tisPromise: boolean,\n): { should: boolean; entries?: [string, unknown][] } {\n\tif (\n\t\ttypeof rawResult === 'object' &&\n\t\trawResult !== null &&\n\t\t!Array.isArray(rawResult) &&\n\t\t!isPromise\n\t) {\n\t\tconst entries = Object.entries(rawResult as Record<string, unknown>);\n\t\tconst hasMultipleKeys = entries.length > 1;\n\t\tconst hasPromises = entries.some(([_, v]) => isThenable(v));\n\n\t\tif (hasMultipleKeys || hasPromises) {\n\t\t\treturn { should: true, entries };\n\t\t}\n\t}\n\n\treturn { should: false };\n}\n\nfunction handleCaching(\n\tvalue: unknown,\n\tset: { status: number },\n\tcache: CacheContext,\n\tsetStatus: (val: number) => void,\n) {\n\tconst { cacheKey, statusCacheKey, maxAgeMs } = cache;\n\n\tif (set.status !== 200) {\n\t\tsetStatus(set.status);\n\t}\n\tif (maxAgeMs > 0) {\n\t\tstatusCache.set(statusCacheKey, set.status, maxAgeMs);\n\t}\n\tif (maxAgeMs > 0 && set.status === 200) {\n\t\tssrCache.set(cacheKey, value, maxAgeMs);\n\t}\n}\n\nasync function handleStreamingRouteData(\n\trawResult: unknown,\n\tisPromise: boolean,\n\tpathname: string,\n\tset: { status: number },\n\tctx: StreamingContext,\n\tcache: CacheContext,\n\tsetError: (msg: string) => void,\n\tsetStatus: (val: number) => void,\n): Promise<Record<string, unknown>> {\n\tconst { ssrData, storeResult } = ctx;\n\n\t// Check if this is a plain object with promises (flattening candidate)\n\tconst flattenCheck = shouldFlattenResult(rawResult, isPromise);\n\tif (flattenCheck.should && flattenCheck.entries) {\n\t\treturn handleFlattenedResult(\n\t\t\tflattenCheck.entries,\n\t\t\tset,\n\t\t\tctx,\n\t\t\tcache,\n\t\t\tsetError,\n\t\t\tsetStatus,\n\t\t);\n\t}\n\n\t// Single value, promise, or array - handle normally\n\tconst task = toPromise(rawResult).catch((err) => {\n\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\tsetError(`SSR data() failed: ${msg}`);\n\t\tconsole.error(`[reroute] SSR data() failed: ${msg}`);\n\t\tthrow err;\n\t});\n\n\tssrData[pathname] = task;\n\tstoreResult(\n\t\tpathname,\n\t\ttask.then((value) => {\n\t\t\thandleCaching(value, set, cache, setStatus);\n\t\t\tssrData[pathname] = value;\n\t\t\treturn value;\n\t\t}),\n\t);\n\n\treturn {};\n}\n\n/**\n * Handle flattened object result where each key streams independently.\n */\nfunction handleFlattenedResult(\n\tentries: [string, unknown][],\n\tset: { status: number },\n\tctx: StreamingContext,\n\tcache: CacheContext,\n\tsetError: (msg: string) => void,\n\tsetStatus: (val: number) => void,\n): Record<string, unknown> {\n\tconst { ssrData, storeResult } = ctx;\n\tconst { cacheKey, statusCacheKey, maxAgeMs } = cache;\n\n\tconst promisesToResolve: Promise<[string, unknown]>[] = [];\n\n\tfor (const [key, val] of entries) {\n\t\tif (isThenable(val)) {\n\t\t\tconst wrappedPromise = (val as Promise<unknown>)\n\t\t\t\t.then((resolved) => {\n\t\t\t\t\tif (set.status !== 200) {\n\t\t\t\t\t\tsetStatus(set.status);\n\t\t\t\t\t}\n\t\t\t\t\treturn resolved;\n\t\t\t\t})\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\tsetError(`SSR data() failed for key ${key}: ${msg}`);\n\t\t\t\t\tconsole.error(`[reroute] SSR data() failed for key ${key}: ${msg}`);\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\tssrData[key] = wrappedPromise;\n\t\t\tstoreResult(key, wrappedPromise);\n\t\t\tpromisesToResolve.push(\n\t\t\t\twrappedPromise.then((resolved) => [key, resolved] as [string, unknown]),\n\t\t\t);\n\t\t} else {\n\t\t\tssrData[key] = val;\n\t\t\tpromisesToResolve.push(Promise.resolve([key, val] as [string, unknown]));\n\t\t}\n\t}\n\n\t// Cache when all promises resolve\n\tif (maxAgeMs > 0) {\n\t\tPromise.all(promisesToResolve)\n\t\t\t.then((resolvedEntries) => {\n\t\t\t\tstatusCache.set(statusCacheKey, set.status, maxAgeMs);\n\t\t\t\tif (set.status === 200) {\n\t\t\t\t\tconst resolvedResult: Record<string, unknown> = {};\n\t\t\t\t\tfor (const [key, value] of resolvedEntries) {\n\t\t\t\t\t\tresolvedResult[key] = value;\n\t\t\t\t\t}\n\t\t\t\t\tssrCache.set(cacheKey, resolvedResult, maxAgeMs);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\t// Don't cache on failure\n\t\t\t});\n\t}\n\n\treturn {};\n}\n",
|
|
14
|
-
"import { dynamicImport } from '../imports';\nimport { join } from '../path';\nimport type { ComputeOptions, ComputeResult, Doc } from '../types';\nimport { computeContentData } from './content';\nimport { computeLayoutData, mergeLayoutData } from './layouts';\nimport { computeRouteData } from './routes';\n\n/**\n * Match a route pattern against a pathname\n * Used in compiled binary mode when matchRoute isn't available from routes.ts\n */\nfunction matchPatternUtil(\n\tpattern: string,\n\tpathname: string,\n): Record<string, string> | null {\n\tconst patternParts = pattern.split('/').filter(Boolean);\n\tconst pathnameParts = pathname.split('/').filter(Boolean);\n\n\tif (patternParts.length !== pathnameParts.length) {\n\t\treturn null;\n\t}\n\n\tconst params: Record<string, string> = {};\n\n\tfor (let i = 0; i < patternParts.length; i++) {\n\t\tconst patternPart = patternParts[i];\n\t\tconst pathnamePart = pathnameParts[i];\n\n\t\tif (patternPart.startsWith(':')) {\n\t\t\tparams[patternPart.slice(1)] = pathnamePart;\n\t\t} else if (patternPart !== pathnamePart) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\treturn params;\n}\n\nexport { computeContentData } from './content';\nexport { computeLayoutData, mergeLayoutData } from './layouts';\nexport { computeRouteData } from './routes';\n\nfunction createBundledRoutesModule(\n\tbundledRoutes: unknown,\n\tbundledLayouts: unknown,\n): Doc {\n\treturn {\n\t\troutes: bundledRoutes,\n\t\tlayouts: bundledLayouts,\n\t\tmatchRoute: (pathname: string) => {\n\t\t\tfor (const route of bundledRoutes as Doc[]) {\n\t\t\t\tconst pattern = String(route?.pattern || '');\n\t\t\t\tconst match = matchPatternUtil(pattern, pathname);\n\t\t\t\tif (match) {\n\t\t\t\t\treturn { route, params: match };\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t};\n}\n\nasync function loadRoutesModule(\n\tcwd: string,\n\tisWatchMode: boolean,\n): Promise<Doc | null> {\n\ttry {\n\t\tconst bundledRoutes = (globalThis as Record<string, unknown>)\n\t\t\t.__REROUTE_ROUTES__;\n\t\tconst bundledLayouts = (globalThis as Record<string, unknown>)\n\t\t\t.__REROUTE_LAYOUTS__;\n\n\t\tif (bundledRoutes && bundledLayouts) {\n\t\t\treturn createBundledRoutesModule(bundledRoutes, bundledLayouts);\n\t\t}\n\n\t\tconst routesPath = join(cwd, '.reroute', 'routes.ts');\n\t\treturn await dynamicImport(routesPath, isWatchMode);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction mergeComputeResult(\n\tresult: {\n\t\tdata: Record<string, unknown>;\n\t\terror?: string;\n\t\tstatusOverride?: number;\n\t\tpendingTasks: Promise<unknown>[];\n\t},\n\tssrData: Record<string, unknown>,\n\tstatusContainer: { value: number | undefined },\n\tallPendingTasks: Promise<unknown>[],\n\tstreaming: boolean,\n): string | undefined {\n\tif (!streaming) {\n\t\tObject.assign(ssrData, result.data);\n\t}\n\tif (result.statusOverride && !statusContainer.value) {\n\t\tstatusContainer.value = result.statusOverride;\n\t}\n\tallPendingTasks.push(...result.pendingTasks);\n\treturn result.error;\n}\n\n/**\n * Compute SSR data by executing ssr.data() from layouts, routes, and content modules.\n * Orchestrates the full data computation pipeline for a request.\n */\nexport async function computeSSRData(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n\toptions: ComputeOptions = {},\n\tsearchParams?: URLSearchParams,\n): Promise<ComputeResult> {\n\tconst ssrData: Record<string, unknown> = {};\n\tlet error: string | undefined;\n\tconst statusContainer = { value: undefined as number | undefined };\n\tconst allPendingTasks: Promise<unknown>[] = [];\n\tconst streaming = options.streaming === true;\n\n\tconst routesModule = await loadRoutesModule(cwd, isWatchMode);\n\tif (!routesModule) {\n\t\treturn {\n\t\t\tdata: ssrData,\n\t\t\terror: 'Failed to load routes module',\n\t\t\tstatusContainer,\n\t\t};\n\t}\n\n\ttry {\n\t\tconst layoutResult = await computeLayoutData(\n\t\t\tpathname,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t\toptions,\n\t\t\tsearchParams,\n\t\t\troutesModule,\n\t\t\tssrData,\n\t\t);\n\t\tmergeComputeResult(\n\t\t\tlayoutResult,\n\t\t\tssrData,\n\t\t\tstatusContainer,\n\t\t\tallPendingTasks,\n\t\t\tstreaming,\n\t\t);\n\t} catch {\n\t\t// Continue with other data sources\n\t}\n\n\ttry {\n\t\tconst contentResult = await computeContentData(\n\t\t\tpathname,\n\t\t\toptions,\n\t\t\tsearchParams,\n\t\t\tssrData,\n\t\t);\n\t\terror = mergeComputeResult(\n\t\t\tcontentResult,\n\t\t\tssrData,\n\t\t\tstatusContainer,\n\t\t\tallPendingTasks,\n\t\t\tstreaming,\n\t\t);\n\t} catch {\n\t\t// Continue with route data\n\t}\n\n\ttry {\n\t\tconst routeResult = await computeRouteData(\n\t\t\tpathname,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t\toptions,\n\t\t\tsearchParams,\n\t\t\troutesModule,\n\t\t\tssrData,\n\t\t);\n\t\tconst routeError = mergeComputeResult(\n\t\t\trouteResult,\n\t\t\tssrData,\n\t\t\tstatusContainer,\n\t\t\tallPendingTasks,\n\t\t\tstreaming,\n\t\t);\n\t\tif (routeError) error = routeError;\n\t} catch {\n\t\t// Return what we have\n\t}\n\n\tif (!streaming) {\n\t\tmergeLayoutData(ssrData, pathname);\n\t}\n\n\tconst pending =\n\t\tstreaming && allPendingTasks.length\n\t\t\t? Promise.allSettled(allPendingTasks).then(() => undefined)\n\t\t\t: undefined;\n\n\treturn { data: ssrData, error, pending, statusContainer };\n}\n\n/**\n * Set global SSR data for client hydration\n */\nexport function setGlobalSSRData(data: Record<string, unknown>): void {\n\ttry {\n\t\t(globalThis as Doc).__REROUTE_DATA__ = data;\n\t} catch {\n\t\t// Ignore errors in restricted environments\n\t}\n}\n",
|
|
14
|
+
"import { dynamicImport } from '../imports';\nimport { join } from '../path';\nimport type { ComputeOptions, ComputeResult, Doc } from '../types';\nimport { computeContentData } from './content';\nimport { computeLayoutData, mergeLayoutData } from './layouts';\nimport { computeRouteData } from './routes';\n\n/**\n * Match a route pattern against a pathname\n * Used in compiled binary mode when matchRoute isn't available from routes.ts\n */\nfunction matchPatternUtil(\n\tpattern: string,\n\tpathname: string,\n): Record<string, string> | null {\n\tconst patternParts = pattern.split('/').filter(Boolean);\n\tconst pathnameParts = pathname.split('/').filter(Boolean);\n\n\tif (patternParts.length !== pathnameParts.length) {\n\t\treturn null;\n\t}\n\n\tconst params: Record<string, string> = {};\n\n\tfor (let i = 0; i < patternParts.length; i++) {\n\t\tconst patternPart = patternParts[i];\n\t\tconst pathnamePart = pathnameParts[i];\n\n\t\tif (patternPart.startsWith(':')) {\n\t\t\tparams[patternPart.slice(1)] = pathnamePart;\n\t\t} else if (patternPart !== pathnamePart) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\treturn params;\n}\n\nexport { computeContentData } from './content';\nexport { computeLayoutData, mergeLayoutData } from './layouts';\nexport { computeRouteData } from './routes';\nexport { loadRoutesModule };\n\nfunction createBundledRoutesModule(\n\tbundledRoutes: unknown,\n\tbundledLayouts: unknown,\n): Doc {\n\tconst bundledNotFoundRoutes = (globalThis as Record<string, unknown>)\n\t\t.__REROUTE_NOT_FOUND_ROUTES__;\n\n\treturn {\n\t\troutes: bundledRoutes,\n\t\tlayouts: bundledLayouts,\n\t\tnotFoundRoutes: bundledNotFoundRoutes,\n\t\tmatchRoute: (pathname: string) => {\n\t\t\tfor (const route of bundledRoutes as Doc[]) {\n\t\t\t\tconst pattern = String(route?.pattern || '');\n\t\t\t\tconst match = matchPatternUtil(pattern, pathname);\n\t\t\t\tif (match) {\n\t\t\t\t\treturn { route, params: match };\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t};\n}\n\nasync function loadRoutesModule(\n\tcwd: string,\n\tisWatchMode: boolean,\n): Promise<Doc | null> {\n\ttry {\n\t\tconst bundledRoutes = (globalThis as Record<string, unknown>)\n\t\t\t.__REROUTE_ROUTES__;\n\t\tconst bundledLayouts = (globalThis as Record<string, unknown>)\n\t\t\t.__REROUTE_LAYOUTS__;\n\n\t\tif (bundledRoutes && bundledLayouts) {\n\t\t\treturn createBundledRoutesModule(bundledRoutes, bundledLayouts);\n\t\t}\n\n\t\tconst routesPath = join(cwd, '.reroute', 'routes.ts');\n\t\treturn await dynamicImport(routesPath, isWatchMode);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction mergeComputeResult(\n\tresult: {\n\t\tdata: Record<string, unknown>;\n\t\terror?: string;\n\t\tstatusOverride?: number;\n\t\tpendingTasks: Promise<unknown>[];\n\t},\n\tssrData: Record<string, unknown>,\n\tstatusContainer: { value: number | undefined },\n\tallPendingTasks: Promise<unknown>[],\n\tstreaming: boolean,\n): string | undefined {\n\tif (!streaming) {\n\t\tObject.assign(ssrData, result.data);\n\t}\n\tif (result.statusOverride && !statusContainer.value) {\n\t\tstatusContainer.value = result.statusOverride;\n\t}\n\tallPendingTasks.push(...result.pendingTasks);\n\treturn result.error;\n}\n\n/**\n * Compute SSR data by executing ssr.data() from layouts, routes, and content modules.\n * Orchestrates the full data computation pipeline for a request.\n */\nexport async function computeSSRData(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n\toptions: ComputeOptions = {},\n\tsearchParams?: URLSearchParams,\n): Promise<ComputeResult> {\n\tconst ssrData: Record<string, unknown> = {};\n\tlet error: string | undefined;\n\tconst statusContainer = { value: undefined as number | undefined };\n\tconst allPendingTasks: Promise<unknown>[] = [];\n\tconst streaming = options.streaming === true;\n\n\tconst routesModule = await loadRoutesModule(cwd, isWatchMode);\n\tif (!routesModule) {\n\t\treturn {\n\t\t\tdata: ssrData,\n\t\t\terror: 'Failed to load routes module',\n\t\t\tstatusContainer,\n\t\t};\n\t}\n\n\ttry {\n\t\tconst layoutResult = await computeLayoutData(\n\t\t\tpathname,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t\toptions,\n\t\t\tsearchParams,\n\t\t\troutesModule,\n\t\t\tssrData,\n\t\t);\n\t\tmergeComputeResult(\n\t\t\tlayoutResult,\n\t\t\tssrData,\n\t\t\tstatusContainer,\n\t\t\tallPendingTasks,\n\t\t\tstreaming,\n\t\t);\n\t} catch {\n\t\t// Continue with other data sources\n\t}\n\n\ttry {\n\t\tconst contentResult = await computeContentData(\n\t\t\tpathname,\n\t\t\toptions,\n\t\t\tsearchParams,\n\t\t\tssrData,\n\t\t);\n\t\terror = mergeComputeResult(\n\t\t\tcontentResult,\n\t\t\tssrData,\n\t\t\tstatusContainer,\n\t\t\tallPendingTasks,\n\t\t\tstreaming,\n\t\t);\n\t} catch {\n\t\t// Continue with route data\n\t}\n\n\ttry {\n\t\tconst routeResult = await computeRouteData(\n\t\t\tpathname,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t\toptions,\n\t\t\tsearchParams,\n\t\t\troutesModule,\n\t\t\tssrData,\n\t\t);\n\t\tconst routeError = mergeComputeResult(\n\t\t\trouteResult,\n\t\t\tssrData,\n\t\t\tstatusContainer,\n\t\t\tallPendingTasks,\n\t\t\tstreaming,\n\t\t);\n\t\tif (routeError) error = routeError;\n\t} catch {\n\t\t// Return what we have\n\t}\n\n\tif (!streaming) {\n\t\tmergeLayoutData(ssrData, pathname);\n\t}\n\n\tconst pending =\n\t\tstreaming && allPendingTasks.length\n\t\t\t? Promise.allSettled(allPendingTasks).then(() => undefined)\n\t\t\t: undefined;\n\n\treturn { data: ssrData, error, pending, statusContainer };\n}\n\n/**\n * Set global SSR data for client hydration\n */\nexport function setGlobalSSRData(data: Record<string, unknown>): void {\n\ttry {\n\t\t(globalThis as Doc).__REROUTE_DATA__ = data;\n\t} catch {\n\t\t// Ignore errors in restricted environments\n\t}\n}\n",
|
|
15
15
|
"import { readdir, stat } from 'node:fs/promises';\nimport { dynamicImport } from './imports';\nimport { join } from './path';\nimport type { Doc } from './types';\n\n/**\n * Import a content module for a given pathname like \"/collection/name\".\n * Prefers the latest built chunk in .reroute, falls back to source TS/TSX.\n */\nexport async function importContentModuleForPath(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n): Promise<Doc | null> {\n\ttry {\n\t\t// Strip query params and hash\n\t\tconst pathOnly = pathname.split('?')[0].split('#')[0];\n\t\tconst parts = pathOnly.split('/').filter(Boolean);\n\t\tif (parts.length < 2) return null;\n\n\t\tconst collection = parts[0];\n\t\tconst name = parts[1];\n\n\t\t// 1) Try registry mapping for exact chunk path\n\t\tconst registryModule = await tryRegistryImport(\n\t\t\tcollection,\n\t\t\tname,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t);\n\t\tif (registryModule) return registryModule;\n\n\t\t// 2) Try latest prebuilt chunk from .reroute\n\t\tconst chunkModule = await tryChunkImport(\n\t\t\tcollection,\n\t\t\tname,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t);\n\t\tif (chunkModule) return chunkModule;\n\n\t\t// 3) Fallback to source files\n\t\tconst sourceModule = await trySourceImport(\n\t\t\tcollection,\n\t\t\tname,\n\t\t\tclientDir,\n\t\t\tisWatchMode,\n\t\t);\n\t\tif (sourceModule) return sourceModule;\n\t} catch {\n\t\t// Return null on any error\n\t}\n\n\treturn null;\n}\n\nasync function tryRegistryImport(\n\tcollection: string,\n\tname: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n): Promise<Doc | null> {\n\ttry {\n\t\tconst registryPath = join(cwd, '.reroute', 'content.ts');\n\t\tconst reg = await dynamicImport(registryPath, isWatchMode);\n\n\t\tconst get = reg?.getContentEntry as\n\t\t\t| ((c: string, n: string) => { module?: string } | undefined)\n\t\t\t| undefined;\n\t\tconst entry = typeof get === 'function' ? get(collection, name) : undefined;\n\t\tconst moduleUrl = (entry as Doc)?.module as string | undefined;\n\n\t\tif (!moduleUrl?.endsWith('.js')) return null;\n\n\t\tconst raw = moduleUrl.split('?')[0] || '';\n\t\tconst normalized = raw.replace(/^\\/+/, '');\n\n\t\tconst candidates: string[] = [];\n\t\tif (normalized) {\n\t\t\tcandidates.push(join(cwd, normalized));\n\t\t\tif (!normalized.startsWith('.reroute/')) {\n\t\t\t\tcandidates.push(join(cwd, '.reroute', normalized));\n\t\t\t}\n\t\t}\n\n\t\tfor (const abs of candidates) {\n\t\t\ttry {\n\t\t\t\tif (!(await Bun.file(abs).exists())) continue;\n\t\t\t\treturn await dynamicImport(abs, isWatchMode);\n\t\t\t} catch {\n\t\t\t\t// Try next candidate\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Registry unavailable\n\t}\n\n\treturn null;\n}\n\nasync function tryChunkImport(\n\tcollection: string,\n\tname: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n): Promise<Doc | null> {\n\ttry {\n\t\tconst chunkDir = join(cwd, '.reroute', 'chunks', collection);\n\t\tconst files = await readdir(chunkDir);\n\t\tconst matches = files.filter(\n\t\t\t(n) => n.startsWith(`${name}.`) && n.endsWith('.js'),\n\t\t);\n\n\t\tif (!matches.length) return null;\n\n\t\t// Find latest by modification time\n\t\tlet latest = matches[0];\n\t\tlet latestM = 0;\n\t\tfor (const f of matches) {\n\t\t\ttry {\n\t\t\t\tconst s = await stat(join(chunkDir, f));\n\t\t\t\tif (s.mtimeMs >= latestM) {\n\t\t\t\t\tlatestM = s.mtimeMs;\n\t\t\t\t\tlatest = f;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Skip inaccessible files\n\t\t\t}\n\t\t}\n\n\t\tconst absChunk = join(chunkDir, latest);\n\t\treturn await dynamicImport(absChunk, isWatchMode);\n\t} catch {\n\t\t// Chunk directory doesn't exist\n\t}\n\n\treturn null;\n}\n\nasync function trySourceImport(\n\tcollection: string,\n\tname: string,\n\tclientDir: string,\n\tisWatchMode: boolean,\n): Promise<Doc | null> {\n\ttry {\n\t\tconst srcTsx = join(\n\t\t\tclientDir,\n\t\t\t'routes',\n\t\t\tcollection,\n\t\t\t'content',\n\t\t\t`${name}.tsx`,\n\t\t);\n\t\tconst srcTs = join(\n\t\t\tclientDir,\n\t\t\t'routes',\n\t\t\tcollection,\n\t\t\t'content',\n\t\t\t`${name}.ts`,\n\t\t);\n\n\t\tlet absSrc: string | null = null;\n\t\tif (await Bun.file(srcTsx).exists()) {\n\t\t\tabsSrc = srcTsx;\n\t\t} else if (await Bun.file(srcTs).exists()) {\n\t\t\tabsSrc = srcTs;\n\t\t}\n\n\t\tif (absSrc) {\n\t\t\treturn await dynamicImport(absSrc, isWatchMode);\n\t\t}\n\t} catch {\n\t\t// Source files don't exist\n\t}\n\n\treturn null;\n}\n",
|
|
16
16
|
"import { importContentModuleForPath } from './modules';\nimport type { Doc } from './types';\n\n/**\n * Seed SSR module store for a content path.\n * Makes the content module available for server-side rendering.\n */\nexport async function seedSSRModuleForPath(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n): Promise<void> {\n\ttry {\n\t\tconst pathOnly = pathname.split('?')[0].split('#')[0];\n\t\tconst parts = pathOnly.split('/').filter(Boolean);\n\n\t\tif (parts.length < 2) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst collection = parts[0];\n\t\tconst name = parts[1];\n\t\tconst key = `${collection}:${name}`;\n\n\t\tconst mod = await importContentModuleForPath(\n\t\t\tpathname,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t);\n\n\t\tif (!mod) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Store full module for hooks like useToc\n\t\t(globalThis as Doc).__REROUTE_SSR_MODULES__ =\n\t\t\t(globalThis as Doc).__REROUTE_SSR_MODULES__ || {};\n\t\t(globalThis as Doc).__REROUTE_SSR_MODULES__[key] = mod;\n\n\t\t// Capture exports for head injection\n\t\ttry {\n\t\t\t(globalThis as Doc).__REROUTE_SSR_EXPORTS__ =\n\t\t\t\t(globalThis as Doc).__REROUTE_SSR_EXPORTS__ || {};\n\t\t\t(globalThis as Doc).__REROUTE_SSR_EXPORTS__[key] = {\n\t\t\t\tmeta: (mod as Doc).meta || {},\n\t\t\t\tssr: (mod as Doc).ssr || {},\n\t\t\t\ttoc: (mod as Doc).toc || [],\n\t\t\t};\n\t\t} catch {\n\t\t\t// Ignore export capture errors\n\t\t}\n\t} catch {\n\t\t// Ignore seeding errors\n\t}\n}\n",
|
|
17
17
|
"import { dynamicImport } from './imports';\nimport { getMatchingLayouts } from './layouts';\nimport { join } from './path';\nimport { seedSSRModuleForPath } from './seed';\nimport type { ComputeParams, Doc } from './types';\n\n/**\n * Match a route pattern against a pathname\n * Used in compiled binary mode when matchRoute isn't available\n */\nfunction matchPattern(\n\tpattern: string,\n\tpathname: string,\n): Record<string, string> | null {\n\tconst patternParts = pattern.split('/').filter(Boolean);\n\tconst pathnameParts = pathname.split('/').filter(Boolean);\n\n\tif (patternParts.length !== pathnameParts.length) {\n\t\treturn null;\n\t}\n\n\tconst params: Record<string, string> = {};\n\n\tfor (let i = 0; i < patternParts.length; i++) {\n\t\tconst patternPart = patternParts[i];\n\t\tconst pathnamePart = pathnameParts[i];\n\n\t\tif (patternPart.startsWith(':')) {\n\t\t\tparams[patternPart.slice(1)] = pathnamePart;\n\t\t} else if (patternPart !== pathnamePart) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\treturn params;\n}\n\n/**\n * Compute SSR data for client-side navigation.\n * Returns lazy markers for promises to support progressive loading.\n */\nfunction loadContentData(\n\tpathname: string,\n\tsearchParams?: URLSearchParams,\n): { key: string; data: unknown } | null {\n\ttry {\n\t\tconst parts = pathname.split('/').filter(Boolean);\n\t\tif (parts.length < 2) return null;\n\n\t\tconst key = `${parts[0]}:${parts[1]}`;\n\t\tconst g = globalThis as Doc;\n\t\tconst exp = g.__REROUTE_SSR_EXPORTS__?.[key];\n\t\tconst dataFn = (exp as Doc)?.ssr?.data as\n\t\t\t| ((ctx: Doc) => unknown | Promise<unknown>)\n\t\t\t| undefined;\n\n\t\tif (typeof dataFn === 'function') {\n\t\t\tconst rawResult = dataFn({\n\t\t\t\tpathname,\n\t\t\t\tparams: { name: parts[1] },\n\t\t\t\tsearchParams,\n\t\t\t});\n\n\t\t\tconst result = processDataResult(rawResult, pathname, pathname);\n\t\t\treturn { key: pathname, data: result };\n\t\t}\n\t} catch {\n\t\t// Content data unavailable\n\t}\n\n\treturn null;\n}\n\nfunction loadMatchedRouteData(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n\tsearchParams?: URLSearchParams,\n): Promise<{ key: string; data: unknown } | null> {\n\treturn loadRouteDataInternal(\n\t\tpathname,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\tsearchParams,\n\t);\n}\n\nasync function loadRouteDataInternal(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n\tsearchParams?: URLSearchParams,\n): Promise<{ key: string; data: unknown } | null> {\n\ttry {\n\t\t// Check for bundled routes first (compiled binary support)\n\t\tlet routes = (globalThis as Record<string, unknown>).__REROUTE_ROUTES__ as\n\t\t\t| Doc[]\n\t\t\t| undefined;\n\t\tlet matchRouteFn: ((pathname: string) => Doc | null) | undefined;\n\n\t\t// Fallback to dynamic import (dev mode)\n\t\tif (!routes) {\n\t\t\tconst routesPath = join(cwd, '.reroute', 'routes.ts');\n\t\t\tconst m = await dynamicImport(routesPath, isWatchMode);\n\t\t\troutes = m?.routes as Doc[] | undefined;\n\t\t\tmatchRouteFn = (m as Doc)?.matchRoute as\n\t\t\t\t| ((pathname: string) => Doc | null)\n\t\t\t\t| undefined;\n\t\t} else {\n\t\t\t// In bundled mode, we need to match manually\n\t\t\tmatchRouteFn = (pathname: string) => {\n\t\t\t\tfor (const route of routes || []) {\n\t\t\t\t\tconst pattern = String(route?.pattern || '');\n\t\t\t\t\tconst match = matchPattern(pattern, pathname);\n\t\t\t\t\tif (match) {\n\t\t\t\t\t\treturn { route, params: match };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t};\n\t\t}\n\n\t\tconst pathnameOnly = pathname.split('?')[0];\n\t\tconst match =\n\t\t\ttypeof matchRouteFn === 'function' ? matchRouteFn(pathnameOnly) : null;\n\n\t\tconst r = (match as Doc | null)?.route;\n\t\tconst paramsValue = ((match as Doc | null)?.params || {}) as Record<\n\t\t\tstring,\n\t\t\tstring\n\t\t>;\n\n\t\tif (r && typeof (r as Doc).path === 'string') {\n\t\t\t// Try to use bundled ssr export first (compiled binary)\n\t\t\tlet ssrExport = (r as Doc)?.ssr as Doc | undefined;\n\n\t\t\t// Fallback to dynamic import if not bundled (dev mode)\n\t\t\tif (!ssrExport) {\n\t\t\t\t// In dev mode, routes might be from .reroute/routes.ts which imports from streaming wrappers\n\t\t\t\t// The streaming wrapper re-exports ssr, so we should try loading from there first\n\t\t\t\tconst routePath = String((r as Doc).path);\n\t\t\t\tlet abs = join(cwd, '.reroute', 'streaming', routePath);\n\n\t\t\t\tlet mod = await dynamicImport(abs, isWatchMode).catch(() => null);\n\n\t\t\t\t// If streaming wrapper doesn't exist or fails, load from source\n\t\t\t\tif (!mod) {\n\t\t\t\t\tabs = join(clientDir, 'routes', routePath);\n\t\t\t\t\tmod = await dynamicImport(abs, isWatchMode);\n\t\t\t\t}\n\n\t\t\t\tssrExport = (mod as Doc)?.ssr as Doc | undefined;\n\t\t\t}\n\n\t\t\tconst dataFn = ssrExport?.data as\n\t\t\t\t| ((ctx: Doc) => unknown | Promise<unknown>)\n\t\t\t\t| undefined;\n\n\t\t\tif (typeof dataFn === 'function') {\n\t\t\t\tconst rawResult = dataFn({\n\t\t\t\t\tpathname,\n\t\t\t\t\tparams: paramsValue,\n\t\t\t\t\tsearchParams,\n\t\t\t\t});\n\n\t\t\t\tconst data = processDataResult(rawResult, pathname, pathname);\n\t\t\t\treturn { key: pathname, data };\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Route data unavailable\n\t}\n\n\treturn null;\n}\n\nfunction determineReturnStructure(allData: Record<string, unknown>): unknown {\n\tconst dataKeys = Object.keys(allData);\n\n\tif (dataKeys.length > 1) {\n\t\treturn { __reroute_multiple__: true, ...allData };\n\t}\n\n\tif (dataKeys.length === 1) {\n\t\tconst singleKey = dataKeys[0];\n\t\t// Keep layout key structure for proper client-side handling\n\t\tif (singleKey.startsWith('__layout:')) {\n\t\t\treturn allData;\n\t\t}\n\t\treturn allData[singleKey];\n\t}\n\n\treturn null;\n}\n\nexport async function computeSSRDataForPath(\n\tparams: ComputeParams,\n): Promise<unknown> {\n\tconst { pathname, clientDir, cwd, isWatchMode, searchParams } = params;\n\n\t// Seed content modules for potential content pages\n\ttry {\n\t\tawait seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode);\n\t} catch {\n\t\t// Continue without seeding\n\t}\n\n\t// 1) Layout data\n\tconst allData = await loadLayoutData(\n\t\tpathname,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\tsearchParams,\n\t);\n\n\t// 2) Content-level data\n\tconst contentResult = loadContentData(pathname, searchParams);\n\tif (contentResult) {\n\t\t// For content pages, return directly if it's the only data\n\t\tif (Object.keys(allData).length === 0) {\n\t\t\treturn contentResult.data;\n\t\t}\n\t\tallData[contentResult.key] = contentResult.data;\n\t}\n\n\t// 3) Route-level data\n\tconst routeResult = await loadMatchedRouteData(\n\t\tpathname,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\tsearchParams,\n\t);\n\tif (routeResult) {\n\t\tallData[routeResult.key] = routeResult.data;\n\t}\n\n\treturn determineReturnStructure(allData);\n}\n\nfunction processLayoutDataResult(\n\trawResult: unknown,\n\tpathname: string,\n\tlayoutKey: string,\n): unknown {\n\tif (rawResult instanceof Promise) {\n\t\treturn createLazyMarker(pathname, layoutKey);\n\t}\n\n\tif (\n\t\ttypeof rawResult === 'object' &&\n\t\trawResult !== null &&\n\t\t!Array.isArray(rawResult)\n\t) {\n\t\tconst entries = Object.entries(rawResult as Record<string, unknown>);\n\t\tconst hasPromises = entries.some(([_, v]) => v instanceof Promise);\n\n\t\tif (hasPromises) {\n\t\t\tconst flattened: Record<string, unknown> = { __flatten__: true };\n\t\t\tfor (const [k, value] of entries) {\n\t\t\t\tif (value instanceof Promise) {\n\t\t\t\t\tflattened[k] = createLazyMarker(pathname, k);\n\t\t\t\t} else {\n\t\t\t\t\tflattened[k] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn flattened;\n\t\t}\n\t}\n\n\treturn rawResult;\n}\n\nasync function processLayout(\n\tlayout: Doc,\n\tpathname: string,\n\tclientDir: string,\n\tisWatchMode: boolean,\n\tsearchParams?: URLSearchParams,\n): Promise<{ key: string; data: unknown } | null> {\n\tif (typeof layout?.path !== 'string') return null;\n\n\ttry {\n\t\t// Try to use bundled ssr export first (compiled binary)\n\t\tlet ssrExport = (layout as Doc)?.ssr as Doc | undefined;\n\n\t\t// Fallback to dynamic import if not bundled (dev mode)\n\t\tif (!ssrExport) {\n\t\t\tconst abs = join(clientDir, 'routes', String(layout.path));\n\t\t\tconst mod = await dynamicImport(abs, isWatchMode);\n\t\t\tssrExport = (mod as Doc)?.ssr as Doc | undefined;\n\t\t}\n\n\t\tconst dataFn = ssrExport?.data as\n\t\t\t| ((ctx: Doc) => unknown | Promise<unknown>)\n\t\t\t| undefined;\n\n\t\tif (typeof dataFn !== 'function') return null;\n\n\t\tconst pattern = String(layout.pattern || '/');\n\t\tconst layoutKey = `__layout:${pattern}`;\n\t\tconst rawResult = dataFn({\n\t\t\tpathname,\n\t\t\tparams: {},\n\t\t\tsearchParams,\n\t\t});\n\n\t\tconst processedData = processLayoutDataResult(\n\t\t\trawResult,\n\t\t\tpathname,\n\t\t\tlayoutKey,\n\t\t);\n\t\treturn { key: layoutKey, data: processedData };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function loadLayoutData(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n\tsearchParams?: URLSearchParams,\n): Promise<Record<string, unknown>> {\n\tconst allData: Record<string, unknown> = {};\n\n\ttry {\n\t\t// Check for bundled layouts first (compiled binary support)\n\t\tlet layouts = (globalThis as Record<string, unknown>).__REROUTE_LAYOUTS__ as\n\t\t\t| Doc[]\n\t\t\t| undefined;\n\n\t\t// Fallback to dynamic import (dev mode)\n\t\tif (!layouts) {\n\t\t\tconst routesPath = join(cwd, '.reroute', 'routes.ts');\n\t\t\tconst m = await dynamicImport(routesPath, isWatchMode);\n\t\t\tlayouts = m?.layouts as Doc[] | undefined;\n\t\t}\n\n\t\tconst matchingLayouts = getMatchingLayouts(pathname, layouts);\n\n\t\tfor (const layout of matchingLayouts) {\n\t\t\tconst result = await processLayout(\n\t\t\t\tlayout,\n\t\t\t\tpathname,\n\t\t\t\tclientDir,\n\t\t\t\tisWatchMode,\n\t\t\t\tsearchParams,\n\t\t\t);\n\n\t\t\tif (result) {\n\t\t\t\tallData[result.key] = result.data;\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Routes unavailable\n\t}\n\n\treturn allData;\n}\n\nfunction processDataResult(\n\trawResult: unknown,\n\tpathname: string,\n\tkey: string,\n): unknown {\n\treturn processLayoutDataResult(rawResult, pathname, key);\n}\n\nfunction createLazyMarker(pathname: string, key: string): unknown {\n\treturn {\n\t\t__lazy__: true,\n\t\t__fetch__: `/__reroute_data?path=${encodeURIComponent(pathname)}&key=${encodeURIComponent(key)}`,\n\t};\n}\n",
|
|
18
18
|
"import type { OGImageOptions } from '../config';\nimport { findOGImageForPath } from './discovery';\n\n/**\n * Generate OG image meta tags for SSR\n */\nexport async function generateOGImageMetaTags(\n\tpathname: string,\n\tclientDir: string,\n\togConfig: OGImageOptions | undefined,\n): Promise<string> {\n\tif (!ogConfig?.enabled) {\n\t\treturn '';\n\t}\n\n\tconst width = ogConfig.width || 1200;\n\tconst height = ogConfig.height || 630;\n\n\t// Check if there's an OG image component for this route\n\tconst ogPath = await findOGImageForPath(pathname, clientDir);\n\tconst hasOGImage = ogPath !== null || ogConfig.defaultTemplate;\n\n\tif (!hasOGImage) {\n\t\treturn '';\n\t}\n\n\t// Generate OG image URL (relative path)\n\t// For root (/), use /index.png; for /blog, use /blog/index.png\n\tlet ogImagePath: string;\n\tif (pathname === '/' || pathname === '') {\n\t\togImagePath = '/__reroute_og/index.png';\n\t} else if (pathname.endsWith('/')) {\n\t\togImagePath = `/__reroute_og${pathname}index.png`;\n\t} else {\n\t\togImagePath = `/__reroute_og${pathname}.png`;\n\t}\n\n\t// Convert to absolute URL if baseUrl is provided\n\tconst baseUrl = ogConfig.baseUrl;\n\tif (baseUrl) {\n\t\t// Remove trailing slash from baseUrl if present\n\t\tconst cleanBaseUrl = baseUrl.replace(/\\/$/, '');\n\t\togImagePath = `${cleanBaseUrl}${ogImagePath}`;\n\t} else {\n\t\tconsole.warn(\n\t\t\t'[reroute] OG images require a baseUrl for proper social media sharing. Add baseUrl to ogImage config.',\n\t\t);\n\t}\n\n\t// Generate meta tags\n\treturn `<meta property=\"og:image\" content=\"${ogImagePath}\" />\n<meta property=\"og:image:width\" content=\"${width}\" />\n<meta property=\"og:image:height\" content=\"${height}\" />\n<meta name=\"twitter:card\" content=\"summary_large_image\" />\n<meta name=\"twitter:image\" content=\"${ogImagePath}\" />`;\n}\n",
|
|
19
|
-
"import type { OGImageOptions } from '../../config';\nimport { buildHeadFromMeta } from '../../content/metadata';\nimport { generateOGImageMetaTags } from '../../og/meta';\nimport { dynamicImport } from './imports';\nimport { getMatchingLayouts } from './layouts';\nimport { join } from './path';\nimport type { Doc, MetadataResult } from './types';\n\n/**\n * Generate canonical URL meta tag\n */\nfunction generateCanonicalUrl(baseUrl: string, pathname: string): string {\n\t// Remove trailing slash from baseUrl if present\n\tconst cleanBaseUrl = baseUrl.replace(/\\/$/, '');\n\t// Remove query parameters from pathname for canonical URL\n\tconst cleanPathname = pathname.split('?')[0];\n\t// Canonical URLs should not have trailing slashes (except for root)\n\tconst normalizedPath =\n\t\tcleanPathname === '/' ? '/' : cleanPathname.replace(/\\/$/, '');\n\tconst canonicalUrl = `${cleanBaseUrl}${normalizedPath}`;\n\treturn `<link rel=\"canonical\" href=\"${canonicalUrl}\" />`;\n}\n\n/**\n * Generate og:url meta tag to match canonical URL\n */\nfunction generateOgUrl(baseUrl: string, pathname: string): string {\n\t// Remove trailing slash from baseUrl if present\n\tconst cleanBaseUrl = baseUrl.replace(/\\/$/, '');\n\t// Remove query parameters from pathname for og:url\n\tconst cleanPathname = pathname.split('?')[0];\n\t// og:url should not have trailing slashes (except for root)\n\tconst normalizedPath =\n\t\tcleanPathname === '/' ? '/' : cleanPathname.replace(/\\/$/, '');\n\tconst ogUrl = `${cleanBaseUrl}${normalizedPath}`;\n\treturn `<meta property=\"og:url\" content=\"${ogUrl}\" />`;\n}\n\n/**\n * Extract per-page head and metadata from layouts, routes, and content modules\n */\nexport async function extractPageMetadata(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n\tcurrentStatusOverride?: number,\n\togConfig?: OGImageOptions,\n\tbaseUrl?: string,\n\tautoCanonical?: boolean,\n): Promise<MetadataResult> {\n\tlet perPageHead = '';\n\tlet pageLang: string | undefined;\n\tlet statusOverride = currentStatusOverride;\n\n\t// 1. Extract layout metadata hierarchically\n\tawait extractLayoutMetadata(\n\t\tpathname,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\t(head) => {\n\t\t\tperPageHead += head;\n\t\t},\n\t\t(lang) => {\n\t\t\tif (!pageLang) pageLang = lang;\n\t\t},\n\t);\n\n\t// 2. Canonical URL and og:url (auto-generated, should be overridable by custom tags)\n\t// Default to true if baseUrl is set, unless explicitly disabled\n\tconst shouldGenerateCanonical =\n\t\tautoCanonical !== false && baseUrl !== undefined;\n\tif (shouldGenerateCanonical) {\n\t\tconst canonicalTag = generateCanonicalUrl(baseUrl, pathname);\n\t\tconst ogUrlTag = generateOgUrl(baseUrl, pathname);\n\t\tperPageHead += `\\n${canonicalTag}`;\n\t\tperPageHead += `\\n${ogUrlTag}`;\n\t}\n\n\t// 3. OG Image meta tags (auto-generated, should be overridable by custom tags)\n\ttry {\n\t\tconst ogMetaTags = await generateOGImageMetaTags(\n\t\t\tpathname,\n\t\t\tclientDir,\n\t\t\togConfig,\n\t\t);\n\t\tif (ogMetaTags) {\n\t\t\tperPageHead += `\\n${ogMetaTags}`;\n\t\t}\n\t} catch (error) {\n\t\tconsole.warn('[reroute] Failed to generate OG image meta tags:', error);\n\t}\n\n\t// 4. Content page metadata (can override auto-generated tags)\n\textractContentMetadata(\n\t\tpathname,\n\t\t(head) => {\n\t\t\tperPageHead += head;\n\t\t},\n\t\t(lang) => {\n\t\t\tpageLang = lang;\n\t\t},\n\t);\n\n\t// 5. Route-level metadata (most specific, can override everything)\n\tconst routeResult = await extractRouteMetadata(\n\t\tpathname,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\tstatusOverride,\n\t);\n\tperPageHead += routeResult.head;\n\tif (routeResult.lang) pageLang = routeResult.lang;\n\tstatusOverride = routeResult.statusOverride;\n\n\treturn { perPageHead, pageLang, statusOverride };\n}\n\nasync function processLayoutForMetadata(\n\tlayout: Doc,\n\tclientDir: string,\n\tisWatchMode: boolean,\n\taddHead: (head: string) => void,\n\tsetLang: (lang: string) => void,\n): Promise<void> {\n\tif (typeof layout?.path !== 'string') return;\n\n\ttry {\n\t\tconst abs = join(clientDir, 'routes', String(layout.path));\n\t\tconst mod = await dynamicImport(abs, isWatchMode);\n\n\t\tconst meta = (mod as Doc)?.meta;\n\t\tconst ssr = (mod as Doc)?.ssr;\n\n\t\tif (meta) addHead(buildHeadFromMeta(meta));\n\n\t\tif (ssr) {\n\t\t\tconst ssrHead = extractSSRHead(ssr);\n\t\t\tif (ssrHead) addHead(`\\n${ssrHead}`);\n\n\t\t\tconst lang = extractSSRLang(ssr);\n\t\t\tif (lang) setLang(lang);\n\t\t}\n\t} catch {\n\t\t// Continue to next layout\n\t}\n}\n\nasync function extractLayoutMetadata(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n\taddHead: (head: string) => void,\n\tsetLang: (lang: string) => void,\n): Promise<void> {\n\ttry {\n\t\tconst routesPath = join(cwd, '.reroute', 'routes.ts');\n\t\tconst m = await dynamicImport(routesPath, isWatchMode);\n\t\tconst matchingLayouts = getMatchingLayouts(pathname, m?.layouts);\n\n\t\tfor (const layout of matchingLayouts) {\n\t\t\tawait processLayoutForMetadata(\n\t\t\t\tlayout,\n\t\t\t\tclientDir,\n\t\t\t\tisWatchMode,\n\t\t\t\taddHead,\n\t\t\t\tsetLang,\n\t\t\t);\n\t\t}\n\t} catch {\n\t\t// Routes module unavailable\n\t}\n}\n\nfunction extractContentMetadata(\n\tpathname: string,\n\taddHead: (head: string) => void,\n\tsetLang: (lang: string) => void,\n): void {\n\ttry {\n\t\tconst parts = pathname.split('/').filter(Boolean);\n\t\tif (parts.length < 2) return;\n\n\t\tconst key = `${parts[0]}:${parts[1]}`;\n\t\tconst g = globalThis as Doc;\n\t\tconst exp = g.__REROUTE_SSR_EXPORTS__?.[key] as\n\t\t\t| { meta?: unknown; ssr?: unknown }\n\t\t\t| undefined;\n\n\t\tconst meta = (exp as Doc)?.meta;\n\t\tconst ssr = (exp as Doc)?.ssr;\n\n\t\taddHead(buildHeadFromMeta(meta));\n\n\t\tconst ssrHead = extractSSRHead(ssr);\n\t\tif (ssrHead) addHead(`\\n${ssrHead}`);\n\n\t\tconst lang = extractSSRLang(ssr);\n\t\tif (lang) setLang(lang);\n\t} catch {\n\t\t// Content metadata unavailable\n\t}\n}\n\nasync function extractMatchedRouteMetadata(\n\tpathname: string,\n\tclientDir: string,\n\tm: Doc,\n\tisWatchMode: boolean,\n\tstatusOverride: number | undefined,\n): Promise<{ head: string; lang?: string; statusOverride?: number }> {\n\tconst pathnameOnly = pathname.split('?')[0];\n\tconst match =\n\t\ttypeof m.matchRoute === 'function' ? m.matchRoute(pathnameOnly) : null;\n\tconst r = match?.route as Doc | undefined;\n\n\tif (!r) {\n\t\treturn { head: '', statusOverride: statusOverride || 404 };\n\t}\n\n\tif (r && typeof r.path === 'string') {\n\t\ttry {\n\t\t\tconst abs = join(clientDir, 'routes', String(r.path));\n\t\t\tconst mod = await dynamicImport(abs, isWatchMode);\n\n\t\t\tconst meta = (mod as Doc)?.meta;\n\t\t\tconst ssr = (mod as Doc)?.ssr;\n\n\t\t\tlet head = '';\n\t\t\tif (meta) head += buildHeadFromMeta(meta);\n\n\t\t\tif (ssr) {\n\t\t\t\tconst ssrHead = extractSSRHead(ssr);\n\t\t\t\tif (ssrHead) head += `\\n${ssrHead}`;\n\t\t\t\treturn { head, lang: extractSSRLang(ssr), statusOverride };\n\t\t\t}\n\n\t\t\treturn { head, statusOverride };\n\t\t} catch {\n\t\t\t// Route module unavailable\n\t\t}\n\t}\n\n\treturn { head: '', statusOverride };\n}\n\nasync function extractRouteMetadata(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n\tcurrentStatusOverride?: number,\n): Promise<{ head: string; lang?: string; statusOverride?: number }> {\n\tlet head = '';\n\tlet lang: string | undefined;\n\tlet statusOverride = currentStatusOverride;\n\n\ttry {\n\t\tconst routesPath = join(cwd, '.reroute', 'routes.ts');\n\t\tconst m = await dynamicImport(routesPath, isWatchMode);\n\n\t\tconst pathnameOnly = pathname.split('?')[0];\n\t\tconst match =\n\t\t\ttypeof m.matchRoute === 'function' ? m.matchRoute(pathnameOnly) : null;\n\t\tconst r = match?.route as Doc | undefined;\n\n\t\tif (!r) {\n\t\t\tstatusOverride = statusOverride || 404;\n\t\t}\n\n\t\tif (r && typeof r.path === 'string') {\n\t\t\tconst result = await extractMatchedRouteMetadata(\n\t\t\t\tpathname,\n\t\t\t\tclientDir,\n\t\t\t\tm,\n\t\t\t\tisWatchMode,\n\t\t\t\tstatusOverride,\n\t\t\t);\n\n\t\t\thead = result.head;\n\t\t\tlang = result.lang;\n\t\t\tstatusOverride = result.statusOverride;\n\t\t} else {\n\t\t\t// Try notFound route metadata only when no route matched\n\t\t\thead += await extractNotFoundMetadata(\n\t\t\t\tpathname,\n\t\t\t\tclientDir,\n\t\t\t\tm,\n\t\t\t\tisWatchMode,\n\t\t\t\t(l) => {\n\t\t\t\t\tlang = l;\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t} catch {\n\t\t// Routes module unavailable\n\t}\n\n\treturn { head, lang, statusOverride };\n}\n\nfunction findBestNotFoundRoute(list: Doc[], pathname: string): Doc | undefined {\n\tlet chosen: Doc | undefined;\n\tlet bestLen = -1;\n\n\tfor (const nf of list) {\n\t\tconst pat = String((nf as Doc)?.pattern || '/');\n\t\tif (!pathname.startsWith(pat)) continue;\n\n\t\tconst len = pat.split('/').filter(Boolean).length;\n\t\tif (len >= bestLen) {\n\t\t\tbestLen = len;\n\t\t\tchosen = nf;\n\t\t}\n\t}\n\n\treturn chosen;\n}\n\nasync function extractNotFoundMetadata(\n\tpathname: string,\n\tclientDir: string,\n\troutesModule: Doc,\n\tisWatchMode: boolean,\n\tsetLang: (lang: string) => void,\n): Promise<string> {\n\tlet head = '';\n\n\ttry {\n\t\tconst list = routesModule?.notFoundRoutes as Doc[] | undefined;\n\t\tif (!Array.isArray(list)) return head;\n\n\t\tconst chosen = findBestNotFoundRoute(list, pathname);\n\n\t\tif (chosen && typeof (chosen as Doc).path === 'string') {\n\t\t\tconst abs = join(clientDir, 'routes', String((chosen as Doc).path));\n\t\t\tconst mod = await dynamicImport(abs, isWatchMode);\n\n\t\t\tconst meta = (mod as Doc)?.meta;\n\t\t\tconst ssr = (mod as Doc)?.ssr;\n\n\t\t\tif (meta) head += buildHeadFromMeta(meta);\n\n\t\t\tconst ssrHead = extractSSRHead(ssr);\n\t\t\tif (ssrHead) head += `\\n${ssrHead}`;\n\n\t\t\tconst lang = extractSSRLang(ssr);\n\t\t\tif (lang) setLang(lang);\n\t\t}\n\t} catch {\n\t\t// NotFound metadata unavailable\n\t}\n\n\treturn head;\n}\n\nfunction extractSSRHead(ssr: Doc): string {\n\tif (!ssr) return '';\n\n\tif (typeof ssr.head === 'string') return ssr.head;\n\tif (Array.isArray(ssr.head)) return String(ssr.head.join('\\n'));\n\n\treturn '';\n}\n\nfunction extractSSRLang(ssr: Doc): string | undefined {\n\tif (!ssr) return undefined;\n\n\tif (typeof ssr.lang === 'string' && ssr.lang.trim()) {\n\t\treturn ssr.lang.trim();\n\t}\n\n\treturn undefined;\n}\n",
|
|
20
|
-
"import { readdir, stat } from 'node:fs/promises';\nimport { dynamicImport } from './imports';\nimport { join } from './path';\nimport type { Doc, PreloadResult } from './types';\n\n/**\n * Handle content module preloading for content pages\n */\nexport async function preloadContentModule(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n): Promise<PreloadResult> {\n\tlet extraHead = '';\n\tlet hydrationScript = '';\n\tlet statusOverride: number | undefined;\n\n\ttry {\n\t\tconst pathOnly = pathname.split('?')[0].split('#')[0];\n\t\tconst parts = pathOnly.split('/').filter(Boolean);\n\n\t\tif (parts.length < 2) {\n\t\t\treturn { extraHead, hydrationScript };\n\t\t}\n\n\t\tconst collection = parts[0];\n\t\tconst name = parts[1];\n\n\t\t// Check if this is a content collection\n\t\tif (!(await isContentCollection(clientDir, collection))) {\n\t\t\treturn { extraHead, hydrationScript };\n\t\t}\n\n\t\t// Try to find module path\n\t\tconst modulePath = await findContentModulePath(\n\t\t\tcollection,\n\t\t\tname,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t);\n\n\t\tif (!modulePath) {\n\t\t\tstatusOverride = 404;\n\t\t\treturn { extraHead, hydrationScript, statusOverride };\n\t\t}\n\n\t\tconst key = `${collection}:${name}`;\n\t\textraHead += `\\n<link rel=\"modulepreload\" href=\"${modulePath}\" />`;\n\n\t\t// Store the module path and key for the inline loader\n\t\t// The actual loading happens via a blocking mechanism in the data script\n\t\thydrationScript += `<script>\n// Mark that this content module needs to be preloaded\n(globalThis.__REROUTE_CONTENT_PRELOAD__ ||= []).push({src:'${modulePath}',key:'${key}'});\n</script>`;\n\t} catch {\n\t\t// Return empty result on error\n\t}\n\n\treturn { extraHead, hydrationScript, statusOverride };\n}\n\nasync function isContentCollection(\n\tclientDir: string,\n\tcollection: string,\n): Promise<boolean> {\n\ttry {\n\t\tconst maybeDir = join(clientDir, 'routes', collection, 'content');\n\t\tconst s = await stat(maybeDir);\n\t\treturn typeof s?.isDirectory === 'function' ? s.isDirectory() : true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function findLatestCandidate(\n\tchunkDir: string,\n\tcandidates: string[],\n): Promise<string> {\n\tlet latest = candidates[0];\n\tlet latestM = 0;\n\n\tfor (const candidateName of candidates) {\n\t\ttry {\n\t\t\tconst s = await stat(join(chunkDir, candidateName));\n\t\t\tif (s.mtimeMs >= latestM) {\n\t\t\t\tlatestM = s.mtimeMs;\n\t\t\t\tlatest = candidateName;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Skip inaccessible files\n\t\t}\n\t}\n\n\treturn latest;\n}\n\nasync function findContentModulePath(\n\tcollection: string,\n\tname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n): Promise<string | null> {\n\t// 1. Try registry mapping\n\ttry {\n\t\tconst registryPath = join(cwd, '.reroute', 'content.ts');\n\t\tconst reg = await dynamicImport(registryPath, isWatchMode);\n\t\tconst get = reg?.getContentEntry as\n\t\t\t| ((c: string, n: string) => { module?: string } | undefined)\n\t\t\t| undefined;\n\t\tconst entry = typeof get === 'function' ? get(collection, name) : undefined;\n\t\tconst moduleUrl = (entry as Doc)?.module as string | undefined;\n\n\t\tif (moduleUrl?.endsWith('.js')) {\n\t\t\treturn moduleUrl;\n\t\t}\n\t} catch {\n\t\t// Registry unavailable\n\t}\n\n\t// 2. Try newest chunk\n\ttry {\n\t\tconst chunkDir = join(cwd, '.reroute', 'chunks', collection);\n\t\tconst files = await readdir(chunkDir);\n\t\tconst candidates = files.filter(\n\t\t\t(n) => n.startsWith(`${name}.`) && n.endsWith('.js'),\n\t\t);\n\n\t\tif (candidates.length) {\n\t\t\tconst latest = await findLatestCandidate(chunkDir, candidates);\n\t\t\treturn `/${join('.reroute', 'chunks', collection, latest).replace(/\\\\+/g, '/')}`;\n\t\t}\n\t} catch {\n\t\t// Chunk directory unavailable\n\t}\n\n\t// 3. Try source files\n\ttry {\n\t\tconst tsx = join(clientDir, 'routes', collection, 'content', `${name}.tsx`);\n\t\tconst ts = join(clientDir, 'routes', collection, 'content', `${name}.ts`);\n\n\t\tif (await Bun.file(tsx).exists()) {\n\t\t\treturn `/${join('routes', collection, 'content', `${name}.tsx`).replace(/\\\\+/g, '/')}`;\n\t\t}\n\t\tif (await Bun.file(ts).exists()) {\n\t\t\treturn `/${join('routes', collection, 'content', `${name}.ts`).replace(/\\\\+/g, '/')}`;\n\t\t}\n\t} catch {\n\t\t// Source files unavailable\n\t}\n\n\treturn null;\n}\n\n/**\n * Reset SSR access tracking for a new request\n */\nexport function resetSSRAccessTracking(): void {\n\ttry {\n\t\t(globalThis as Doc).__REROUTE_SSR_ACCESSED__ = {};\n\t} catch {\n\t\t// Ignore errors in restricted environments\n\t}\n}\n\n/**\n * Create bundle preload link\n */\nexport function createBundlePreload(bundleUrl: string): string {\n\ttry {\n\t\tif (typeof bundleUrl === 'string' && bundleUrl.endsWith('.js')) {\n\t\t\treturn `\\n<link rel=\"modulepreload\" href=\"${bundleUrl}\" />`;\n\t\t}\n\t} catch {\n\t\t// Return empty on error\n\t}\n\treturn '';\n}\n",
|
|
19
|
+
"import type { OGImageOptions } from '../../config';\nimport { buildHeadFromMeta } from '../../content/metadata';\nimport { generateOGImageMetaTags } from '../../og/meta';\nimport { loadRoutesModule } from './compute';\nimport { dynamicImport } from './imports';\nimport { getMatchingLayouts } from './layouts';\nimport { join } from './path';\nimport type { Doc, MetadataResult } from './types';\n\n/**\n * Generate canonical URL meta tag\n */\nfunction generateCanonicalUrl(baseUrl: string, pathname: string): string {\n\t// Remove trailing slash from baseUrl if present\n\tconst cleanBaseUrl = baseUrl.replace(/\\/$/, '');\n\t// Remove query parameters from pathname for canonical URL\n\tconst cleanPathname = pathname.split('?')[0];\n\t// Canonical URLs should not have trailing slashes (except for root)\n\tconst normalizedPath =\n\t\tcleanPathname === '/' ? '/' : cleanPathname.replace(/\\/$/, '');\n\tconst canonicalUrl = `${cleanBaseUrl}${normalizedPath}`;\n\treturn `<link rel=\"canonical\" href=\"${canonicalUrl}\" />`;\n}\n\n/**\n * Generate og:url meta tag to match canonical URL\n */\nfunction generateOgUrl(baseUrl: string, pathname: string): string {\n\t// Remove trailing slash from baseUrl if present\n\tconst cleanBaseUrl = baseUrl.replace(/\\/$/, '');\n\t// Remove query parameters from pathname for og:url\n\tconst cleanPathname = pathname.split('?')[0];\n\t// og:url should not have trailing slashes (except for root)\n\tconst normalizedPath =\n\t\tcleanPathname === '/' ? '/' : cleanPathname.replace(/\\/$/, '');\n\tconst ogUrl = `${cleanBaseUrl}${normalizedPath}`;\n\treturn `<meta property=\"og:url\" content=\"${ogUrl}\" />`;\n}\n\n/**\n * Extract per-page head and metadata from layouts, routes, and content modules\n */\nexport async function extractPageMetadata(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n\tcurrentStatusOverride?: number,\n\togConfig?: OGImageOptions,\n\tbaseUrl?: string,\n\tautoCanonical?: boolean,\n): Promise<MetadataResult> {\n\tlet perPageHead = '';\n\tlet pageLang: string | undefined;\n\tlet statusOverride = currentStatusOverride;\n\n\t// 1. Extract layout metadata hierarchically\n\tawait extractLayoutMetadata(\n\t\tpathname,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\t(head) => {\n\t\t\tperPageHead += head;\n\t\t},\n\t\t(lang) => {\n\t\t\tif (!pageLang) pageLang = lang;\n\t\t},\n\t);\n\n\t// 2. Canonical URL and og:url (auto-generated, should be overridable by custom tags)\n\t// Default to true if baseUrl is set, unless explicitly disabled\n\tconst shouldGenerateCanonical =\n\t\tautoCanonical !== false && baseUrl !== undefined;\n\tif (shouldGenerateCanonical) {\n\t\tconst canonicalTag = generateCanonicalUrl(baseUrl, pathname);\n\t\tconst ogUrlTag = generateOgUrl(baseUrl, pathname);\n\t\tperPageHead += `\\n${canonicalTag}`;\n\t\tperPageHead += `\\n${ogUrlTag}`;\n\t}\n\n\t// 3. OG Image meta tags (auto-generated, should be overridable by custom tags)\n\ttry {\n\t\tconst ogMetaTags = await generateOGImageMetaTags(\n\t\t\tpathname,\n\t\t\tclientDir,\n\t\t\togConfig,\n\t\t);\n\t\tif (ogMetaTags) {\n\t\t\tperPageHead += `\\n${ogMetaTags}`;\n\t\t}\n\t} catch (error) {\n\t\tconsole.warn('[reroute] Failed to generate OG image meta tags:', error);\n\t}\n\n\t// 4. Content page metadata (can override auto-generated tags)\n\textractContentMetadata(\n\t\tpathname,\n\t\t(head) => {\n\t\t\tperPageHead += head;\n\t\t},\n\t\t(lang) => {\n\t\t\tpageLang = lang;\n\t\t},\n\t);\n\n\t// 5. Route-level metadata (most specific, can override everything)\n\tconst routeResult = await extractRouteMetadata(\n\t\tpathname,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\tstatusOverride,\n\t);\n\tperPageHead += routeResult.head;\n\tif (routeResult.lang) pageLang = routeResult.lang;\n\tstatusOverride = routeResult.statusOverride;\n\n\treturn { perPageHead, pageLang, statusOverride };\n}\n\nasync function processLayoutForMetadata(\n\tlayout: Doc,\n\tclientDir: string,\n\tisWatchMode: boolean,\n\taddHead: (head: string) => void,\n\tsetLang: (lang: string) => void,\n): Promise<void> {\n\tif (typeof layout?.path !== 'string') return;\n\n\ttry {\n\t\tconst abs = join(clientDir, 'routes', String(layout.path));\n\t\tconst mod = await dynamicImport(abs, isWatchMode);\n\n\t\tconst meta = (mod as Doc)?.meta;\n\t\tconst ssr = (mod as Doc)?.ssr;\n\n\t\tif (meta) addHead(buildHeadFromMeta(meta));\n\n\t\tif (ssr) {\n\t\t\tconst ssrHead = extractSSRHead(ssr);\n\t\t\tif (ssrHead) addHead(`\\n${ssrHead}`);\n\n\t\t\tconst lang = extractSSRLang(ssr);\n\t\t\tif (lang) setLang(lang);\n\t\t}\n\t} catch {\n\t\t// Continue to next layout\n\t}\n}\n\nasync function extractLayoutMetadata(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n\taddHead: (head: string) => void,\n\tsetLang: (lang: string) => void,\n): Promise<void> {\n\ttry {\n\t\tconst routesPath = join(cwd, '.reroute', 'routes.ts');\n\t\tconst m = await dynamicImport(routesPath, isWatchMode);\n\t\tconst matchingLayouts = getMatchingLayouts(pathname, m?.layouts);\n\n\t\tfor (const layout of matchingLayouts) {\n\t\t\tawait processLayoutForMetadata(\n\t\t\t\tlayout,\n\t\t\t\tclientDir,\n\t\t\t\tisWatchMode,\n\t\t\t\taddHead,\n\t\t\t\tsetLang,\n\t\t\t);\n\t\t}\n\t} catch {\n\t\t// Routes module unavailable\n\t}\n}\n\nfunction extractContentMetadata(\n\tpathname: string,\n\taddHead: (head: string) => void,\n\tsetLang: (lang: string) => void,\n): void {\n\ttry {\n\t\tconst parts = pathname.split('/').filter(Boolean);\n\t\tif (parts.length < 2) return;\n\n\t\tconst key = `${parts[0]}:${parts[1]}`;\n\t\tconst g = globalThis as Doc;\n\t\tconst exp = g.__REROUTE_SSR_EXPORTS__?.[key] as\n\t\t\t| { meta?: unknown; ssr?: unknown }\n\t\t\t| undefined;\n\n\t\tconst meta = (exp as Doc)?.meta;\n\t\tconst ssr = (exp as Doc)?.ssr;\n\n\t\taddHead(buildHeadFromMeta(meta));\n\n\t\tconst ssrHead = extractSSRHead(ssr);\n\t\tif (ssrHead) addHead(`\\n${ssrHead}`);\n\n\t\tconst lang = extractSSRLang(ssr);\n\t\tif (lang) setLang(lang);\n\t} catch {\n\t\t// Content metadata unavailable\n\t}\n}\n\nasync function extractMatchedRouteMetadata(\n\tpathname: string,\n\tclientDir: string,\n\tm: Doc,\n\tisWatchMode: boolean,\n\tstatusOverride: number | undefined,\n): Promise<{ head: string; lang?: string; statusOverride?: number }> {\n\tconst pathnameOnly = pathname.split('?')[0];\n\tconst match =\n\t\ttypeof m.matchRoute === 'function' ? m.matchRoute(pathnameOnly) : null;\n\tconst r = match?.route as Doc | undefined;\n\n\tif (!r) {\n\t\treturn { head: '', statusOverride: statusOverride || 404 };\n\t}\n\n\tif (r && typeof r.path === 'string') {\n\t\ttry {\n\t\t\tconst abs = join(clientDir, 'routes', String(r.path));\n\t\t\tconst mod = await dynamicImport(abs, isWatchMode);\n\n\t\t\tconst meta = (mod as Doc)?.meta;\n\t\t\tconst ssr = (mod as Doc)?.ssr;\n\n\t\t\tlet head = '';\n\t\t\tif (meta) head += buildHeadFromMeta(meta);\n\n\t\t\tif (ssr) {\n\t\t\t\tconst ssrHead = extractSSRHead(ssr);\n\t\t\t\tif (ssrHead) head += `\\n${ssrHead}`;\n\t\t\t\treturn { head, lang: extractSSRLang(ssr), statusOverride };\n\t\t\t}\n\n\t\t\treturn { head, statusOverride };\n\t\t} catch {\n\t\t\t// Route module unavailable\n\t\t}\n\t}\n\n\treturn { head: '', statusOverride };\n}\n\nasync function extractRouteMetadata(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n\tcurrentStatusOverride?: number,\n): Promise<{ head: string; lang?: string; statusOverride?: number }> {\n\tlet head = '';\n\tlet lang: string | undefined;\n\tlet statusOverride = currentStatusOverride;\n\n\ttry {\n\t\tconst m = await loadRoutesModule(cwd, isWatchMode);\n\t\tif (!m) {\n\t\t\treturn { head, lang, statusOverride: statusOverride || 404 };\n\t\t}\n\n\t\tconst pathnameOnly = pathname.split('?')[0];\n\t\tconst match =\n\t\t\ttypeof m.matchRoute === 'function' ? m.matchRoute(pathnameOnly) : null;\n\t\tconst r = match?.route as Doc | undefined;\n\n\t\tif (!r) {\n\t\t\tstatusOverride = statusOverride || 404;\n\t\t}\n\n\t\tif (r && typeof r.path === 'string') {\n\t\t\tconst result = await extractMatchedRouteMetadata(\n\t\t\t\tpathname,\n\t\t\t\tclientDir,\n\t\t\t\tm,\n\t\t\t\tisWatchMode,\n\t\t\t\tstatusOverride,\n\t\t\t);\n\n\t\t\thead = result.head;\n\t\t\tlang = result.lang;\n\t\t\tstatusOverride = result.statusOverride;\n\t\t} else {\n\t\t\t// Try notFound route metadata only when no route matched\n\t\t\thead += await extractNotFoundMetadata(\n\t\t\t\tpathname,\n\t\t\t\tclientDir,\n\t\t\t\tm,\n\t\t\t\tisWatchMode,\n\t\t\t\t(l) => {\n\t\t\t\t\tlang = l;\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t} catch {\n\t\t// Routes module unavailable\n\t}\n\n\treturn { head, lang, statusOverride };\n}\n\nfunction findBestNotFoundRoute(list: Doc[], pathname: string): Doc | undefined {\n\tlet chosen: Doc | undefined;\n\tlet bestLen = -1;\n\n\tfor (const nf of list) {\n\t\tconst pat = String((nf as Doc)?.pattern || '/');\n\t\tif (!pathname.startsWith(pat)) continue;\n\n\t\tconst len = pat.split('/').filter(Boolean).length;\n\t\tif (len >= bestLen) {\n\t\t\tbestLen = len;\n\t\t\tchosen = nf;\n\t\t}\n\t}\n\n\treturn chosen;\n}\n\nasync function extractNotFoundMetadata(\n\tpathname: string,\n\tclientDir: string,\n\troutesModule: Doc,\n\tisWatchMode: boolean,\n\tsetLang: (lang: string) => void,\n): Promise<string> {\n\tlet head = '';\n\n\ttry {\n\t\tconst list = routesModule?.notFoundRoutes as Doc[] | undefined;\n\t\tif (!Array.isArray(list)) return head;\n\n\t\tconst chosen = findBestNotFoundRoute(list, pathname);\n\n\t\tif (chosen && typeof (chosen as Doc).path === 'string') {\n\t\t\tconst abs = join(clientDir, 'routes', String((chosen as Doc).path));\n\t\t\tconst mod = await dynamicImport(abs, isWatchMode);\n\n\t\t\tconst meta = (mod as Doc)?.meta;\n\t\t\tconst ssr = (mod as Doc)?.ssr;\n\n\t\t\tif (meta) head += buildHeadFromMeta(meta);\n\n\t\t\tconst ssrHead = extractSSRHead(ssr);\n\t\t\tif (ssrHead) head += `\\n${ssrHead}`;\n\n\t\t\tconst lang = extractSSRLang(ssr);\n\t\t\tif (lang) setLang(lang);\n\t\t}\n\t} catch {\n\t\t// NotFound metadata unavailable\n\t}\n\n\treturn head;\n}\n\nfunction extractSSRHead(ssr: Doc): string {\n\tif (!ssr) return '';\n\n\tif (typeof ssr.head === 'string') return ssr.head;\n\tif (Array.isArray(ssr.head)) return String(ssr.head.join('\\n'));\n\n\treturn '';\n}\n\nfunction extractSSRLang(ssr: Doc): string | undefined {\n\tif (!ssr) return undefined;\n\n\tif (typeof ssr.lang === 'string' && ssr.lang.trim()) {\n\t\treturn ssr.lang.trim();\n\t}\n\n\treturn undefined;\n}\n",
|
|
20
|
+
"import { readdir, stat } from 'node:fs/promises';\nimport { dynamicImport } from './imports';\nimport { join } from './path';\nimport type { Doc, PreloadResult } from './types';\n\n/**\n * Handle content module preloading for content pages\n */\nexport async function preloadContentModule(\n\tpathname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n): Promise<PreloadResult> {\n\tlet extraHead = '';\n\tlet hydrationScript = '';\n\tlet statusOverride: number | undefined;\n\n\ttry {\n\t\tconst pathOnly = pathname.split('?')[0].split('#')[0];\n\t\tconst parts = pathOnly.split('/').filter(Boolean);\n\n\t\tif (parts.length < 2) {\n\t\t\treturn { extraHead, hydrationScript };\n\t\t}\n\n\t\tconst collection = parts[0];\n\t\tconst name = parts[1];\n\n\t\t// Check if this is a content collection\n\t\tif (!(await isContentCollection(clientDir, collection))) {\n\t\t\treturn { extraHead, hydrationScript };\n\t\t}\n\n\t\t// Try to find module path\n\t\tconst modulePath = await findContentModulePath(\n\t\t\tcollection,\n\t\t\tname,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t);\n\n\t\tif (!modulePath) {\n\t\t\tstatusOverride = 404;\n\t\t\treturn { extraHead, hydrationScript, statusOverride };\n\t\t}\n\n\t\tconst key = `${collection}:${name}`;\n\t\textraHead += `\\n<link rel=\"modulepreload\" href=\"${modulePath}\" />`;\n\n\t\t// Store the module path and key for the inline loader\n\t\t// The actual loading happens via a blocking mechanism in the data script\n\t\thydrationScript += `<script>\n// Mark that this content module needs to be preloaded\n(globalThis.__REROUTE_CONTENT_PRELOAD__ ||= []).push({src:'${modulePath}',key:'${key}'});\n</script>`;\n\t} catch {\n\t\t// Return empty result on error\n\t}\n\n\treturn { extraHead, hydrationScript, statusOverride };\n}\n\nasync function isContentCollection(\n\tclientDir: string,\n\tcollection: string,\n): Promise<boolean> {\n\ttry {\n\t\t// In production (clientDir = .reroute), check for collection files instead of source dirs\n\t\tconst isProduction = clientDir.endsWith('.reroute');\n\n\t\tif (isProduction) {\n\t\t\t// Check if collection file exists in .reroute/collections/\n\t\t\tconst collectionFile = join(clientDir, 'collections', `${collection}.js`);\n\t\t\ttry {\n\t\t\t\tconst s = await stat(collectionFile);\n\t\t\t\treturn s?.isFile() ?? false;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// In development, check for content directory\n\t\tconst maybeDir = join(clientDir, 'routes', collection, 'content');\n\t\tconst s = await stat(maybeDir);\n\t\treturn typeof s?.isDirectory === 'function' ? s.isDirectory() : true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function findLatestCandidate(\n\tchunkDir: string,\n\tcandidates: string[],\n): Promise<string> {\n\tlet latest = candidates[0];\n\tlet latestM = 0;\n\n\tfor (const candidateName of candidates) {\n\t\ttry {\n\t\t\tconst s = await stat(join(chunkDir, candidateName));\n\t\t\tif (s.mtimeMs >= latestM) {\n\t\t\t\tlatestM = s.mtimeMs;\n\t\t\t\tlatest = candidateName;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Skip inaccessible files\n\t\t}\n\t}\n\n\treturn latest;\n}\n\nasync function findContentModulePath(\n\tcollection: string,\n\tname: string,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n): Promise<string | null> {\n\t// 1. Try registry mapping\n\ttry {\n\t\tconst registryPath = join(cwd, '.reroute', 'content.ts');\n\t\tconst reg = await dynamicImport(registryPath, isWatchMode);\n\t\tconst get = reg?.getContentEntry as\n\t\t\t| ((c: string, n: string) => { module?: string } | undefined)\n\t\t\t| undefined;\n\t\tconst entry = typeof get === 'function' ? get(collection, name) : undefined;\n\t\tconst moduleUrl = (entry as Doc)?.module as string | undefined;\n\n\t\tif (moduleUrl?.endsWith('.js')) {\n\t\t\treturn moduleUrl;\n\t\t}\n\t} catch {\n\t\t// Registry unavailable\n\t}\n\n\t// 2. Try newest chunk\n\ttry {\n\t\tconst chunkDir = join(cwd, '.reroute', 'chunks', collection);\n\t\tconst files = await readdir(chunkDir);\n\t\tconst candidates = files.filter(\n\t\t\t(n) => n.startsWith(`${name}.`) && n.endsWith('.js'),\n\t\t);\n\n\t\tif (candidates.length) {\n\t\t\tconst latest = await findLatestCandidate(chunkDir, candidates);\n\t\t\treturn `/${join('.reroute', 'chunks', collection, latest).replace(/\\\\+/g, '/')}`;\n\t\t}\n\t} catch {\n\t\t// Chunk directory unavailable\n\t}\n\n\t// 3. Try source files\n\ttry {\n\t\tconst tsx = join(clientDir, 'routes', collection, 'content', `${name}.tsx`);\n\t\tconst ts = join(clientDir, 'routes', collection, 'content', `${name}.ts`);\n\n\t\tif (await Bun.file(tsx).exists()) {\n\t\t\treturn `/${join('routes', collection, 'content', `${name}.tsx`).replace(/\\\\+/g, '/')}`;\n\t\t}\n\t\tif (await Bun.file(ts).exists()) {\n\t\t\treturn `/${join('routes', collection, 'content', `${name}.ts`).replace(/\\\\+/g, '/')}`;\n\t\t}\n\t} catch {\n\t\t// Source files unavailable\n\t}\n\n\treturn null;\n}\n\n/**\n * Reset SSR access tracking for a new request\n */\nexport function resetSSRAccessTracking(): void {\n\ttry {\n\t\t(globalThis as Doc).__REROUTE_SSR_ACCESSED__ = {};\n\t} catch {\n\t\t// Ignore errors in restricted environments\n\t}\n}\n\n/**\n * Create bundle preload link\n */\nexport function createBundlePreload(bundleUrl: string): string {\n\ttry {\n\t\tif (typeof bundleUrl === 'string' && bundleUrl.endsWith('.js')) {\n\t\t\treturn `\\n<link rel=\"modulepreload\" href=\"${bundleUrl}\" />`;\n\t\t}\n\t} catch {\n\t\t// Return empty on error\n\t}\n\treturn '';\n}\n",
|
|
21
21
|
"export { createCollectionScript, processCollections } from './collections';\nexport { createDataScript, duplicateQueryParamData } from './data';\nexport { escapeJsonForScript } from './escape';\nexport { createFeedsScript, createLlmsScript } from './feeds';\n",
|
|
22
|
-
"import type { Span } from '@opentelemetry/api';\nimport { withParentSpan, withSpan } from 'reroute-js/telemetry/server';\nimport type { OGImageOptions } from '../../config';\nimport { loadCollections, setGlobalCollections } from './collections';\nimport { computeSSRData, setGlobalSSRData } from './compute';\nimport { extractPageMetadata } from './metadata';\nimport {\n\tcreateBundlePreload,\n\tpreloadContentModule,\n\tresetSSRAccessTracking,\n} from './preload';\nimport {\n\tcreateCollectionScript,\n\tcreateDataScript,\n\tcreateFeedsScript,\n\tcreateLlmsScript,\n\tprocessCollections,\n} from './scripts';\nimport { seedSSRModuleForPath } from './seed';\nimport { inlineTailwindCSS } from './styles';\nimport type { ComputeResult } from './types';\n\n/**\n * Common SSR options shared between render and stream modes\n */\ntype SSRSetupOptions = {\n\tpathname: string;\n\tclientDir: string;\n\tcwd: string;\n\tisWatchMode: boolean;\n\tbundleUrl: string;\n\tcachedCollections?: Record<string, unknown[]>;\n\tcachedTailwindCSS?: string;\n\tdebug?: boolean;\n\tmaxAge?: number;\n\tsearchParams?: URLSearchParams;\n\togConfig?: OGImageOptions;\n\tbaseUrl?: string;\n\tautoCanonical?: boolean;\n\tparentSpan?: Span | null;\n};\n\n/**\n * Result of SSR setup phase\n */\ntype SSRSetupResult = {\n\tssrData: Record<string, unknown>;\n\tssrError?: string;\n\tstatusContainer: { value: number | undefined };\n\tbyCollectionForSSR: Record<string, unknown[]>;\n\tbundlePreload: string;\n\tpreloadExtraHead: string;\n\tpreloadHydrationScript: string;\n\tpreloadStatusOverride?: number;\n\tinlineStyleTag: string;\n\tmetadataResult: {\n\t\tperPageHead: string;\n\t\tpageLang?: string;\n\t\tstatusOverride?: number;\n\t};\n\tpending?: Promise<void>;\n};\n\n/**\n * Perform common SSR setup steps shared between render and stream modes.\n * This includes seeding modules, computing data, loading collections, and preloading.\n */\nasync function performSSRSetup(\n\toptions: SSRSetupOptions,\n\tstreaming = false,\n): Promise<SSRSetupResult> {\n\tconst { pathname } = options;\n\n\t// Add a global timeout for SSR setup to prevent indefinite hangs\n\t// In streaming mode, we want setup to complete quickly so we can start sending HTML\n\tconst setupTimeout = streaming ? 10000 : 30000; // 10s for streaming, 30s otherwise\n\tconst timeoutPromise = new Promise<never>((_, reject) => {\n\t\tsetTimeout(() => {\n\t\t\treject(\n\t\t\t\tnew Error(\n\t\t\t\t\t`[reroute] SSR setup timeout after ${setupTimeout}ms for ${pathname}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}, setupTimeout);\n\t});\n\n\ttry {\n\t\treturn await Promise.race([\n\t\t\twithParentSpan(options.parentSpan, () =>\n\t\t\t\tperformSSRSetupInternal(options, streaming),\n\t\t\t),\n\t\t\ttimeoutPromise,\n\t\t]);\n\t} catch (error) {\n\t\tconsole.error('[reroute] SSR setup error:', error);\n\t\t// Return minimal setup result to allow page to render with fallback\n\t\treturn {\n\t\t\tssrData: {},\n\t\t\tssrError: error instanceof Error ? error.message : String(error),\n\t\t\tstatusContainer: { value: 500 },\n\t\t\tbyCollectionForSSR: {},\n\t\t\tbundlePreload: '',\n\t\t\tpreloadExtraHead: '',\n\t\t\tpreloadHydrationScript: '',\n\t\t\tinlineStyleTag: '',\n\t\t\tmetadataResult: { perPageHead: '' },\n\t\t};\n\t}\n}\n\n/**\n * Internal SSR setup implementation (wrapped with timeout above)\n */\nasync function performSSRSetupInternal(\n\toptions: SSRSetupOptions,\n\tstreaming: boolean,\n): Promise<SSRSetupResult> {\n\tconst debug = options.debug ?? false;\n\tconst t0 = debug ? performance.now() : 0;\n\tconst {\n\t\tpathname,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\tbundleUrl,\n\t\tmaxAge = 0,\n\t\tsearchParams,\n\t\togConfig,\n\t} = options;\n\n\t// Note: We don't reset SSR globals here because multiple requests may run concurrently.\n\t// Instead, we use pathname-scoped serialization to ensure each response only includes\n\t// its own data (see createContentHtmlScript and createSSRExportsScript).\n\n\t// 1. Seed content modules for SSR rendering\n\tawait withSpan('ssr.seed', async (span) => {\n\t\tspan.setAttribute('pathname', pathname);\n\t\tspan.setAttribute('streaming', streaming);\n\t\tawait seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode);\n\t\tif (debug)\n\t\t\tconsole.log(\n\t\t\t\t`[Setup] ${pathname} - seedModule: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t);\n\t});\n\n\t// 2. Reset SSR access tracking and create bundle preload\n\tresetSSRAccessTracking();\n\tconst bundlePreload = createBundlePreload(bundleUrl);\n\n\t// 3. Preload content module\n\tconst preloadResult = await withSpan('ssr.preload', async (span) => {\n\t\tspan.setAttribute('pathname', pathname);\n\t\tconst result = await preloadContentModule(\n\t\t\tpathname,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t);\n\t\tspan.setAttribute('has_module', !!result.modulePath);\n\t\tif (debug)\n\t\t\tconsole.log(\n\t\t\t\t`[Setup] ${pathname} - preloadContent: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t);\n\t\treturn result;\n\t});\n\n\t// 4. Compute SSR data\n\tconst computeResult: ComputeResult = await withSpan(\n\t\t'ssr.compute.data',\n\t\tasync (span) => {\n\t\t\tspan.setAttribute('pathname', pathname);\n\t\t\tspan.setAttribute('streaming', streaming);\n\t\t\tconst result = await computeSSRData(\n\t\t\t\tpathname,\n\t\t\t\tclientDir,\n\t\t\t\tcwd,\n\t\t\t\tisWatchMode,\n\t\t\t\t{ streaming, maxAge },\n\t\t\t\tsearchParams,\n\t\t\t);\n\t\t\tspan.setAttribute('has_error', !!result.error);\n\t\t\tspan.setAttribute('has_data', Object.keys(result.data).length > 0);\n\t\t\tif (debug)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[Setup] ${pathname} - computeSSRData: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t\t);\n\t\t\treturn result;\n\t\t},\n\t);\n\n\tsetGlobalSSRData(computeResult.data);\n\n\t// 5. Load content collections (use cached if available)\n\tconst usingCachedCollections = !!options.cachedCollections;\n\tconst byCollectionForSSR = await withSpan(\n\t\t'ssr.load.collections',\n\t\tasync (span) => {\n\t\t\tspan.setAttribute('pathname', pathname);\n\t\t\tspan.setAttribute('cached', usingCachedCollections);\n\t\t\tconst collections = options.cachedCollections\n\t\t\t\t? options.cachedCollections\n\t\t\t\t: await loadCollections(cwd, isWatchMode);\n\t\t\tspan.setAttribute('collection_count', Object.keys(collections).length);\n\t\t\tif (debug)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[Setup] ${pathname} - loadCollections (cached: ${usingCachedCollections}): ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t\t);\n\t\t\treturn collections;\n\t\t},\n\t);\n\tsetGlobalCollections(byCollectionForSSR);\n\n\t// 6. Inline Tailwind CSS (use cached if available)\n\tconst usingCachedCSS = !!options.cachedTailwindCSS;\n\tconst inlineStyleTag = await withSpan('ssr.inline.css', async (span) => {\n\t\tconst css = options.cachedTailwindCSS\n\t\t\t? options.cachedTailwindCSS\n\t\t\t: await inlineTailwindCSS(clientDir, !streaming, isWatchMode);\n\t\tspan.setAttributes({\n\t\t\t'reroute.cached': usingCachedCSS,\n\t\t\t'reroute.css.size': css.length,\n\t\t});\n\t\tif (debug)\n\t\t\tconsole.log(\n\t\t\t\t`[Setup] ${pathname} - inlineTailwindCSS (cached: ${usingCachedCSS}): ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t);\n\t\treturn css;\n\t});\n\n\t// 7. Determine initial status override\n\tlet statusOverride = preloadResult.statusOverride;\n\tif (computeResult.statusContainer.value) {\n\t\tstatusOverride = computeResult.statusContainer.value;\n\t}\n\n\t// 8. Extract page metadata\n\tconst metadataResult = await withSpan(\n\t\t'ssr.extract.metadata',\n\t\tasync (span) => {\n\t\t\tconst result = await extractPageMetadata(\n\t\t\t\tpathname,\n\t\t\t\tclientDir,\n\t\t\t\tcwd,\n\t\t\t\tisWatchMode,\n\t\t\t\tstatusOverride,\n\t\t\t\togConfig,\n\t\t\t\toptions.baseUrl,\n\t\t\t\toptions.autoCanonical,\n\t\t\t);\n\t\t\tspan.setAttributes({\n\t\t\t\t'reroute.pathname': pathname,\n\t\t\t\t'reroute.metadata.exists': !!result.perPageHead,\n\t\t\t});\n\t\t\tif (debug)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[Setup] ${pathname} - extractMetadata: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t\t);\n\t\t\treturn result;\n\t\t},\n\t);\n\n\treturn {\n\t\tssrData: computeResult.data,\n\t\tssrError: computeResult.error,\n\t\tstatusContainer: computeResult.statusContainer,\n\t\tbyCollectionForSSR,\n\t\tbundlePreload,\n\t\tpreloadExtraHead: preloadResult.extraHead,\n\t\tpreloadHydrationScript: preloadResult.hydrationScript,\n\t\tpreloadStatusOverride: preloadResult.statusOverride,\n\t\tinlineStyleTag,\n\t\tmetadataResult,\n\t\tpending: computeResult.pending,\n\t};\n}\n\n/**\n * Generate hydration scripts for collections that were accessed during SSR.\n */\nfunction generateCollectionScripts(\n\tbyCollectionForSSR: Record<string, unknown[]>,\n): string {\n\ttry {\n\t\tconst g = globalThis as unknown as { __REROUTE_SSR_ACCESSED__?: unknown };\n\t\tconst acc = g.__REROUTE_SSR_ACCESSED__;\n\n\t\tif (acc) {\n\t\t\tconst { subset, partial } = processCollections(acc, byCollectionForSSR);\n\t\t\tif (Object.keys(subset).length > 0) {\n\t\t\t\treturn createCollectionScript(subset, partial);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Ignore errors\n\t}\n\treturn '';\n}\n\n/**\n * Generate all hydration scripts for SSR\n */\nfunction generateHydrationScripts(\n\tssrData: Record<string, unknown>,\n\tisWatchMode: boolean,\n\tssrError?: string,\n\tcollectionScripts = '',\n\tpreloadScript = '',\n\tbundleUrl = '',\n\tpathname = '',\n\tbrowserTelemetryConfig?: Record<string, unknown>,\n\ttraceContext?: { traceparent?: string; tracestate?: string },\n): string {\n\tlet scripts = preloadScript;\n\n\t// Add collection scripts\n\tscripts += collectionScripts;\n\n\t// Add SSR data script (pathname is used to scope content HTML and exports to current request)\n\tscripts += createDataScript(\n\t\tssrData,\n\t\tisWatchMode ? ssrError : undefined,\n\t\tpathname,\n\t\tbrowserTelemetryConfig,\n\t\ttraceContext,\n\t);\n\n\t// Add feeds and llms scripts\n\tscripts += createFeedsScript();\n\tscripts += createLlmsScript();\n\n\t// Add bundle script\n\tif (bundleUrl) {\n\t\tscripts += `<script type=\"module\" src=\"${bundleUrl}\"></script>`;\n\t}\n\n\t// Add dev watcher in watch mode\n\tif (isWatchMode) {\n\t\tscripts += `<script type=\"module\" src=\"/__reroute_watch.js\"></script>`;\n\t}\n\n\treturn scripts;\n}\n\nexport type { SSRSetupOptions, SSRSetupResult };\nexport { performSSRSetup, generateCollectionScripts, generateHydrationScripts };\n",
|
|
22
|
+
"import type { Span } from '@opentelemetry/api';\nimport { withParentSpan, withSpan } from 'reroute-js/telemetry/server';\nimport type { OGImageOptions } from '../../config';\nimport { loadCollections, setGlobalCollections } from './collections';\nimport { computeSSRData, setGlobalSSRData } from './compute';\nimport { extractPageMetadata } from './metadata';\nimport {\n\tcreateBundlePreload,\n\tpreloadContentModule,\n\tresetSSRAccessTracking,\n} from './preload';\nimport {\n\tcreateCollectionScript,\n\tcreateDataScript,\n\tcreateFeedsScript,\n\tcreateLlmsScript,\n\tprocessCollections,\n} from './scripts';\nimport { seedSSRModuleForPath } from './seed';\nimport { inlineTailwindCSS } from './styles';\nimport type { ComputeResult } from './types';\n\n/**\n * Common SSR options shared between render and stream modes\n */\ntype SSRSetupOptions = {\n\tpathname: string;\n\tclientDir: string;\n\tcwd: string;\n\tisWatchMode: boolean;\n\tbundleUrl: string;\n\tcachedCollections?: Record<string, unknown[]>;\n\tcachedTailwindCSS?: string;\n\tdebug?: boolean;\n\tmaxAge?: number;\n\tsearchParams?: URLSearchParams;\n\togConfig?: OGImageOptions;\n\tbaseUrl?: string;\n\tautoCanonical?: boolean;\n\tparentSpan?: Span | null;\n};\n\n/**\n * Result of SSR setup phase\n */\ntype SSRSetupResult = {\n\tssrData: Record<string, unknown>;\n\tssrError?: string;\n\tstatusContainer: { value: number | undefined };\n\tbyCollectionForSSR: Record<string, unknown[]>;\n\tbundlePreload: string;\n\tpreloadExtraHead: string;\n\tpreloadHydrationScript: string;\n\tpreloadStatusOverride?: number;\n\tinlineStyleTag: string;\n\tmetadataResult: {\n\t\tperPageHead: string;\n\t\tpageLang?: string;\n\t\tstatusOverride?: number;\n\t};\n\tpending?: Promise<void>;\n};\n\n/**\n * Perform common SSR setup steps shared between render and stream modes.\n * This includes seeding modules, computing data, loading collections, and preloading.\n */\nasync function performSSRSetup(\n\toptions: SSRSetupOptions,\n\tstreaming = false,\n): Promise<SSRSetupResult> {\n\tconst { pathname } = options;\n\n\t// Add a global timeout for SSR setup to prevent indefinite hangs\n\t// In streaming mode, we want setup to complete quickly so we can start sending HTML\n\tconst setupTimeout = streaming ? 10000 : 30000; // 10s for streaming, 30s otherwise\n\tconst timeoutPromise = new Promise<never>((_, reject) => {\n\t\tsetTimeout(() => {\n\t\t\treject(\n\t\t\t\tnew Error(\n\t\t\t\t\t`[reroute] SSR setup timeout after ${setupTimeout}ms for ${pathname}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}, setupTimeout);\n\t});\n\n\ttry {\n\t\treturn await Promise.race([\n\t\t\twithParentSpan(options.parentSpan, () =>\n\t\t\t\tperformSSRSetupInternal(options, streaming),\n\t\t\t),\n\t\t\ttimeoutPromise,\n\t\t]);\n\t} catch (error) {\n\t\tconsole.error('[reroute] SSR setup error:', error);\n\t\t// Return minimal setup result to allow page to render with fallback\n\t\treturn {\n\t\t\tssrData: {},\n\t\t\tssrError: error instanceof Error ? error.message : String(error),\n\t\t\tstatusContainer: { value: 500 },\n\t\t\tbyCollectionForSSR: {},\n\t\t\tbundlePreload: '',\n\t\t\tpreloadExtraHead: '',\n\t\t\tpreloadHydrationScript: '',\n\t\t\tinlineStyleTag: '',\n\t\t\tmetadataResult: { perPageHead: '' },\n\t\t};\n\t}\n}\n\n/**\n * Internal SSR setup implementation (wrapped with timeout above)\n */\nasync function performSSRSetupInternal(\n\toptions: SSRSetupOptions,\n\tstreaming: boolean,\n): Promise<SSRSetupResult> {\n\tconst debug = options.debug ?? false;\n\tconst t0 = debug ? performance.now() : 0;\n\tconst {\n\t\tpathname,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\tbundleUrl,\n\t\tmaxAge = 0,\n\t\tsearchParams,\n\t\togConfig,\n\t} = options;\n\n\t// Note: We don't reset SSR globals here because multiple requests may run concurrently.\n\t// Instead, we use pathname-scoped serialization to ensure each response only includes\n\t// its own data (see createContentHtmlScript and createSSRExportsScript).\n\n\t// 1. Seed content modules for SSR rendering\n\tawait withSpan('ssr.seed', async (span) => {\n\t\tspan.setAttribute('pathname', pathname);\n\t\tspan.setAttribute('streaming', streaming);\n\t\tawait seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode);\n\t\tif (debug)\n\t\t\tconsole.log(\n\t\t\t\t`[Setup] ${pathname} - seedModule: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t);\n\t});\n\n\t// 2. Reset SSR access tracking and create bundle preload\n\tresetSSRAccessTracking();\n\tconst bundlePreload = createBundlePreload(bundleUrl);\n\n\t// 3. Preload content module\n\tconst preloadResult = await withSpan('ssr.preload', async (span) => {\n\t\tspan.setAttribute('pathname', pathname);\n\t\tconst result = await preloadContentModule(\n\t\t\tpathname,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t);\n\t\tspan.setAttribute('has_module', !!result.modulePath);\n\t\tif (debug)\n\t\t\tconsole.log(\n\t\t\t\t`[Setup] ${pathname} - preloadContent: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t);\n\t\treturn result;\n\t});\n\n\t// 4. Compute SSR data\n\tconst computeResult: ComputeResult = await withSpan(\n\t\t'ssr.compute.data',\n\t\tasync (span) => {\n\t\t\tspan.setAttribute('pathname', pathname);\n\t\t\tspan.setAttribute('streaming', streaming);\n\t\t\tconst result = await computeSSRData(\n\t\t\t\tpathname,\n\t\t\t\tclientDir,\n\t\t\t\tcwd,\n\t\t\t\tisWatchMode,\n\t\t\t\t{ streaming, maxAge },\n\t\t\t\tsearchParams,\n\t\t\t);\n\t\t\tspan.setAttribute('has_error', !!result.error);\n\t\t\tspan.setAttribute('has_data', Object.keys(result.data).length > 0);\n\t\t\tif (debug)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[Setup] ${pathname} - computeSSRData: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t\t);\n\t\t\treturn result;\n\t\t},\n\t);\n\n\tsetGlobalSSRData(computeResult.data);\n\n\t// 5. Load content collections (use cached if available)\n\tconst usingCachedCollections = !!options.cachedCollections;\n\tconst byCollectionForSSR = await withSpan(\n\t\t'ssr.load.collections',\n\t\tasync (span) => {\n\t\t\tspan.setAttribute('pathname', pathname);\n\t\t\tspan.setAttribute('cached', usingCachedCollections);\n\t\t\tconst collections = options.cachedCollections\n\t\t\t\t? options.cachedCollections\n\t\t\t\t: await loadCollections(cwd, isWatchMode);\n\t\t\tspan.setAttribute('collection_count', Object.keys(collections).length);\n\t\t\tif (debug)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[Setup] ${pathname} - loadCollections (cached: ${usingCachedCollections}): ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t\t);\n\t\t\treturn collections;\n\t\t},\n\t);\n\tsetGlobalCollections(byCollectionForSSR);\n\n\t// 6. Inline Tailwind CSS (use cached if available)\n\tconst usingCachedCSS = !!options.cachedTailwindCSS;\n\tconst inlineStyleTag = await withSpan('ssr.inline.css', async (span) => {\n\t\tconst css = options.cachedTailwindCSS\n\t\t\t? options.cachedTailwindCSS\n\t\t\t: await inlineTailwindCSS(clientDir, !streaming, isWatchMode);\n\t\tspan.setAttributes({\n\t\t\t'reroute.cached': usingCachedCSS,\n\t\t\t'reroute.css.size': css.length,\n\t\t});\n\t\tif (debug)\n\t\t\tconsole.log(\n\t\t\t\t`[Setup] ${pathname} - inlineTailwindCSS (cached: ${usingCachedCSS}): ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t);\n\t\treturn css;\n\t});\n\n\t// 7. Determine initial status override\n\tlet statusOverride = preloadResult.statusOverride;\n\tif (computeResult.statusContainer.value !== undefined) {\n\t\tstatusOverride = computeResult.statusContainer.value;\n\t}\n\n\t// 8. Extract page metadata\n\tconst metadataResult = await withSpan(\n\t\t'ssr.extract.metadata',\n\t\tasync (span) => {\n\t\t\tconst result = await extractPageMetadata(\n\t\t\t\tpathname,\n\t\t\t\tclientDir,\n\t\t\t\tcwd,\n\t\t\t\tisWatchMode,\n\t\t\t\tstatusOverride,\n\t\t\t\togConfig,\n\t\t\t\toptions.baseUrl,\n\t\t\t\toptions.autoCanonical,\n\t\t\t);\n\t\t\tspan.setAttributes({\n\t\t\t\t'reroute.pathname': pathname,\n\t\t\t\t'reroute.metadata.exists': !!result.perPageHead,\n\t\t\t});\n\t\t\tif (debug)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[Setup] ${pathname} - extractMetadata: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t\t);\n\t\t\treturn result;\n\t\t},\n\t);\n\n\treturn {\n\t\tssrData: computeResult.data,\n\t\tssrError: computeResult.error,\n\t\tstatusContainer: computeResult.statusContainer,\n\t\tbyCollectionForSSR,\n\t\tbundlePreload,\n\t\tpreloadExtraHead: preloadResult.extraHead,\n\t\tpreloadHydrationScript: preloadResult.hydrationScript,\n\t\tpreloadStatusOverride: preloadResult.statusOverride,\n\t\tinlineStyleTag,\n\t\tmetadataResult,\n\t\tpending: computeResult.pending,\n\t};\n}\n\n/**\n * Generate hydration scripts for collections that were accessed during SSR.\n */\nfunction generateCollectionScripts(\n\tbyCollectionForSSR: Record<string, unknown[]>,\n): string {\n\ttry {\n\t\tconst g = globalThis as unknown as { __REROUTE_SSR_ACCESSED__?: unknown };\n\t\tconst acc = g.__REROUTE_SSR_ACCESSED__;\n\n\t\tif (acc) {\n\t\t\tconst { subset, partial } = processCollections(acc, byCollectionForSSR);\n\t\t\tif (Object.keys(subset).length > 0) {\n\t\t\t\treturn createCollectionScript(subset, partial);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Ignore errors\n\t}\n\treturn '';\n}\n\n/**\n * Generate all hydration scripts for SSR\n */\nfunction generateHydrationScripts(\n\tssrData: Record<string, unknown>,\n\tisWatchMode: boolean,\n\tssrError?: string,\n\tcollectionScripts = '',\n\tpreloadScript = '',\n\tbundleUrl = '',\n\tpathname = '',\n\tbrowserTelemetryConfig?: Record<string, unknown>,\n\ttraceContext?: { traceparent?: string; tracestate?: string },\n): string {\n\tlet scripts = preloadScript;\n\n\t// Add collection scripts\n\tscripts += collectionScripts;\n\n\t// Add SSR data script (pathname is used to scope content HTML and exports to current request)\n\tscripts += createDataScript(\n\t\tssrData,\n\t\tisWatchMode ? ssrError : undefined,\n\t\tpathname,\n\t\tbrowserTelemetryConfig,\n\t\ttraceContext,\n\t);\n\n\t// Add feeds and llms scripts\n\tscripts += createFeedsScript();\n\tscripts += createLlmsScript();\n\n\t// Add bundle script\n\tif (bundleUrl) {\n\t\tscripts += `<script type=\"module\" src=\"${bundleUrl}\"></script>`;\n\t}\n\n\t// Add dev watcher in watch mode\n\tif (isWatchMode) {\n\t\tscripts += `<script type=\"module\" src=\"/__reroute_watch.js\"></script>`;\n\t}\n\n\treturn scripts;\n}\n\nexport type { SSRSetupOptions, SSRSetupResult };\nexport { performSSRSetup, generateCollectionScripts, generateHydrationScripts };\n",
|
|
23
23
|
"// Types\n\n// Core utilities\nexport * from './cache';\n// Content handling\nexport * from './collections';\n// HTTP utilities\nexport * from './compression';\n// SSR compute\nexport * from './compute';\nexport { computeSSRDataForPath } from './data';\n// HTML handling\nexport * from './html';\nexport * from './imports';\nexport * from './layouts';\nexport * from './metadata';\nexport * from './mime';\nexport * from './modules';\nexport * from './path';\nexport * from './preload';\n// Script generation\nexport * from './scripts';\nexport * from './seed';\n// Shared setup\nexport * from './setup';\nexport * from './styles';\nexport * from './template';\nexport * from './types';\n",
|
|
24
|
-
"import type { Span } from '@opentelemetry/api';\nimport dedent from 'dedent';\nimport { cloneElement, type ReactElement } from 'react';\nimport { renderToString } from 'react-dom/server';\nimport {\n\tgetTraceContextForInjection,\n\twithSpan,\n\twithSpanSync,\n} from 'reroute-js/telemetry/server';\nimport { loadConfig, type OGImageOptions } from '../config';\nimport {\n\ttype Doc,\n\tduplicateQueryParamData,\n\tgenerateCollectionScripts,\n\tgenerateHydrationScripts,\n\tperformSSRSetup,\n\tsetGlobalSSRData,\n} from './lib';\nimport { applyIndexTemplate, loadIndexHtml } from './lib/html';\n\ntype SSRRenderOptions = {\n\tpathname: string;\n\trootComponent: ReactElement;\n\tclientDir: string;\n\tcwd: string;\n\tisWatchMode: boolean;\n\tbundleUrl: string;\n\tcachedCollections?: Record<string, unknown[]>;\n\tcachedTailwindCSS?: string;\n\thead?: string;\n\tlang?: string;\n\tappId?: string;\n\tminify?: boolean;\n\tmaxAge?: number;\n\tsearchParams?: URLSearchParams;\n\togConfig?: OGImageOptions;\n\tbaseUrl?: string;\n\tautoCanonical?: boolean;\n\tparentSpan?: Span | null;\n};\n\ntype SSRRenderResult = {\n\thtml: string;\n\tstatus: number;\n};\n\n/**\n * Render a React component to a complete HTML document for SSR.\n * Uses synchronous rendering (renderToString) for full HTML generation.\n */\nasync function renderSSRDocument(\n\toptions: SSRRenderOptions,\n): Promise<SSRRenderResult> {\n\tconst {\n\t\tpathname,\n\t\trootComponent,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\tbundleUrl,\n\t\thead = '',\n\t\tlang = 'en',\n\t\tappId = 'root',\n\t\tmaxAge = 0,\n\t\tsearchParams,\n\t\togConfig,\n\t} = options;\n\n\t// Perform shared SSR setup\n\tconst setup = await performSSRSetup(\n\t\t{\n\t\t\tpathname,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t\tparentSpan: options.parentSpan,\n\t\t\tbundleUrl,\n\t\t\tmaxAge,\n\t\t\tsearchParams,\n\t\t\togConfig,\n\t\t\tbaseUrl: options.baseUrl,\n\t\t\tautoCanonical: options.autoCanonical,\n\t\t\tcachedCollections: options.cachedCollections,\n\t\t\tcachedTailwindCSS: options.cachedTailwindCSS,\n\t\t},\n\t\tfalse, // not streaming\n\t);\n\n\t// Duplicate data for query param routes\n\tconst duplicatedData = duplicateQueryParamData(setup.ssrData);\n\tsetGlobalSSRData(duplicatedData);\n\n\t// Render React component to string\n\tconst appHtml = await withSpan('ssr.render.react', async (span) => {\n\t\tconst componentWithPathname = cloneElement<Doc>(rootComponent, {\n\t\t\tpathname,\n\t\t\tsearchParams,\n\t\t} as Doc);\n\t\tspan.setAttribute('reroute.pathname', pathname);\n\t\tconst html = renderToString(componentWithPathname);\n\t\tspan.setAttribute('reroute.html.final.size', html.length);\n\t\treturn html;\n\t});\n\n\t// Load base template\n\tconst baseTemplate = await withSpan('ssr.load.template', async (span) => {\n\t\tconst template = await loadIndexHtml(clientDir);\n\t\tspan.setAttribute('reroute.template.size', template.length);\n\t\treturn template;\n\t});\n\n\t// Generate collection scripts from accessed collections\n\tconst collectionScripts = generateCollectionScripts(setup.byCollectionForSSR);\n\n\t// Load config to get browser telemetry settings\n\tconst config = await loadConfig(cwd);\n\tconst browserTelemetryConfigRaw = config.telemetry?.browser as\n\t\t| Record<string, unknown>\n\t\t| undefined;\n\n\t// Serialize browser telemetry config (convert functions to strings for JSON)\n\tconst { serializeBrowserTelemetryConfig } = await import('./lib/serialize');\n\tconst browserTelemetryConfig = serializeBrowserTelemetryConfig(\n\t\tbrowserTelemetryConfigRaw,\n\t);\n\n\t// Extract trace context from parent span for distributed tracing\n\tconst traceContext = getTraceContextForInjection(options.parentSpan);\n\n\t// Generate all hydration scripts\n\tconst hydrationScript = await withSpan(\n\t\t'ssr.generate.scripts',\n\t\tasync (span) => {\n\t\t\tconst script = generateHydrationScripts(\n\t\t\t\tsetup.ssrData,\n\t\t\t\tisWatchMode,\n\t\t\t\tsetup.ssrError,\n\t\t\t\tcollectionScripts,\n\t\t\t\tsetup.preloadHydrationScript,\n\t\t\t\tbundleUrl,\n\t\t\t\tpathname,\n\t\t\t\tbrowserTelemetryConfig,\n\t\t\t\ttraceContext,\n\t\t\t);\n\t\t\tspan.setAttribute('reroute.scripts.size', script.length);\n\t\t\treturn script;\n\t\t},\n\t);\n\n\t// Determine final status\n\tlet statusOverride = setup.preloadStatusOverride;\n\tif (setup.statusContainer.value) {\n\t\tstatusOverride = setup.statusContainer.value;\n\t}\n\tif (setup.metadataResult.statusOverride) {\n\t\tstatusOverride = setup.metadataResult.statusOverride;\n\t}\n\n\t// Build combined head content\n\tconst extraHead = setup.bundlePreload + setup.preloadExtraHead;\n\tconst combinedHead = dedent(\n\t\t[\n\t\t\tdedent(head) || '',\n\t\t\tdedent(extraHead),\n\t\t\tdedent(setup.metadataResult.perPageHead),\n\t\t]\n\t\t\t.filter(Boolean)\n\t\t\t.join('\\n'),\n\t);\n\n\t// Apply template with SSR content\n\tconst html = withSpanSync('ssr.apply.template', (span) => {\n\t\tconst result = applyIndexTemplate(baseTemplate, appHtml, {\n\t\t\thead: [setup.inlineStyleTag, combinedHead].filter(Boolean).join('\\n'),\n\t\t\thydrationScript,\n\t\t\tlang: setup.metadataResult.pageLang || lang,\n\t\t\tappId,\n\t\t});\n\t\tspan.setAttributes({\n\t\t\t'reroute.html.final.size': result.length,\n\t\t\t'reroute.html.original.size': appHtml.length,\n\t\t});\n\t\treturn result;\n\t});\n\n\treturn {\n\t\thtml,\n\t\tstatus: statusOverride || 200,\n\t};\n}\n\nexport { renderSSRDocument, type SSRRenderOptions, type SSRRenderResult };\n",
|
|
24
|
+
"import type { Span } from '@opentelemetry/api';\nimport dedent from 'dedent';\nimport { cloneElement, type ReactElement } from 'react';\nimport { renderToString } from 'react-dom/server';\nimport {\n\tgetTraceContextForInjection,\n\twithSpan,\n\twithSpanSync,\n} from 'reroute-js/telemetry/server';\nimport { loadConfig, type OGImageOptions } from '../config';\nimport {\n\ttype Doc,\n\tduplicateQueryParamData,\n\tgenerateCollectionScripts,\n\tgenerateHydrationScripts,\n\tperformSSRSetup,\n\tsetGlobalSSRData,\n} from './lib';\nimport { applyIndexTemplate, loadIndexHtml } from './lib/html';\n\ntype SSRRenderOptions = {\n\tpathname: string;\n\trootComponent: ReactElement;\n\tclientDir: string;\n\tcwd: string;\n\tisWatchMode: boolean;\n\tbundleUrl: string;\n\tcachedCollections?: Record<string, unknown[]>;\n\tcachedTailwindCSS?: string;\n\thead?: string;\n\tlang?: string;\n\tappId?: string;\n\tminify?: boolean;\n\tmaxAge?: number;\n\tsearchParams?: URLSearchParams;\n\togConfig?: OGImageOptions;\n\tbaseUrl?: string;\n\tautoCanonical?: boolean;\n\tparentSpan?: Span | null;\n};\n\ntype SSRRenderResult = {\n\thtml: string;\n\tstatus: number;\n};\n\n/**\n * Render a React component to a complete HTML document for SSR.\n * Uses synchronous rendering (renderToString) for full HTML generation.\n */\nasync function renderSSRDocument(\n\toptions: SSRRenderOptions,\n): Promise<SSRRenderResult> {\n\tconst {\n\t\tpathname,\n\t\trootComponent,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\tbundleUrl,\n\t\thead = '',\n\t\tlang = 'en',\n\t\tappId = 'root',\n\t\tmaxAge = 0,\n\t\tsearchParams,\n\t\togConfig,\n\t} = options;\n\n\t// Perform shared SSR setup\n\tconst setup = await performSSRSetup(\n\t\t{\n\t\t\tpathname,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t\tparentSpan: options.parentSpan,\n\t\t\tbundleUrl,\n\t\t\tmaxAge,\n\t\t\tsearchParams,\n\t\t\togConfig,\n\t\t\tbaseUrl: options.baseUrl,\n\t\t\tautoCanonical: options.autoCanonical,\n\t\t\tcachedCollections: options.cachedCollections,\n\t\t\tcachedTailwindCSS: options.cachedTailwindCSS,\n\t\t},\n\t\tfalse, // not streaming\n\t);\n\n\t// Duplicate data for query param routes\n\tconst duplicatedData = duplicateQueryParamData(setup.ssrData);\n\tsetGlobalSSRData(duplicatedData);\n\n\t// Render React component to string\n\tconst appHtml = await withSpan('ssr.render.react', async (span) => {\n\t\tconst componentWithPathname = cloneElement<Doc>(rootComponent, {\n\t\t\tpathname,\n\t\t\tsearchParams,\n\t\t} as Doc);\n\t\tspan.setAttribute('reroute.pathname', pathname);\n\t\tconst html = renderToString(componentWithPathname);\n\t\tspan.setAttribute('reroute.html.final.size', html.length);\n\t\treturn html;\n\t});\n\n\t// Load base template\n\tconst baseTemplate = await withSpan('ssr.load.template', async (span) => {\n\t\tconst template = await loadIndexHtml(clientDir);\n\t\tspan.setAttribute('reroute.template.size', template.length);\n\t\treturn template;\n\t});\n\n\t// Generate collection scripts from accessed collections\n\tconst collectionScripts = generateCollectionScripts(setup.byCollectionForSSR);\n\n\t// Load config to get browser telemetry settings\n\tconst config = await loadConfig(cwd);\n\tconst browserTelemetryConfigRaw = config.telemetry?.browser as\n\t\t| Record<string, unknown>\n\t\t| undefined;\n\n\t// Serialize browser telemetry config (convert functions to strings for JSON)\n\tconst { serializeBrowserTelemetryConfig } = await import('./lib/serialize');\n\tconst browserTelemetryConfig = serializeBrowserTelemetryConfig(\n\t\tbrowserTelemetryConfigRaw,\n\t);\n\n\t// Extract trace context from parent span for distributed tracing\n\tconst traceContext = getTraceContextForInjection(options.parentSpan);\n\n\t// Generate all hydration scripts\n\tconst hydrationScript = await withSpan(\n\t\t'ssr.generate.scripts',\n\t\tasync (span) => {\n\t\t\tconst script = generateHydrationScripts(\n\t\t\t\tsetup.ssrData,\n\t\t\t\tisWatchMode,\n\t\t\t\tsetup.ssrError,\n\t\t\t\tcollectionScripts,\n\t\t\t\tsetup.preloadHydrationScript,\n\t\t\t\tbundleUrl,\n\t\t\t\tpathname,\n\t\t\t\tbrowserTelemetryConfig,\n\t\t\t\ttraceContext,\n\t\t\t);\n\t\t\tspan.setAttribute('reroute.scripts.size', script.length);\n\t\t\treturn script;\n\t\t},\n\t);\n\n\t// Determine final status (only override if value is set)\n\tlet statusOverride = setup.preloadStatusOverride;\n\tif (setup.statusContainer.value !== undefined) {\n\t\tstatusOverride = setup.statusContainer.value;\n\t}\n\tif (setup.metadataResult.statusOverride !== undefined) {\n\t\tstatusOverride = setup.metadataResult.statusOverride;\n\t}\n\n\t// Build combined head content\n\tconst extraHead = setup.bundlePreload + setup.preloadExtraHead;\n\tconst combinedHead = dedent(\n\t\t[\n\t\t\tdedent(head) || '',\n\t\t\tdedent(extraHead),\n\t\t\tdedent(setup.metadataResult.perPageHead),\n\t\t]\n\t\t\t.filter(Boolean)\n\t\t\t.join('\\n'),\n\t);\n\n\t// Apply template with SSR content\n\tconst html = withSpanSync('ssr.apply.template', (span) => {\n\t\tconst result = applyIndexTemplate(baseTemplate, appHtml, {\n\t\t\thead: [setup.inlineStyleTag, combinedHead].filter(Boolean).join('\\n'),\n\t\t\thydrationScript,\n\t\t\tlang: setup.metadataResult.pageLang || lang,\n\t\t\tappId,\n\t\t});\n\t\tspan.setAttributes({\n\t\t\t'reroute.html.final.size': result.length,\n\t\t\t'reroute.html.original.size': appHtml.length,\n\t\t});\n\t\treturn result;\n\t});\n\n\treturn {\n\t\thtml,\n\t\tstatus: statusOverride || 200,\n\t};\n}\n\nexport { renderSSRDocument, type SSRRenderOptions, type SSRRenderResult };\n",
|
|
25
25
|
"import { pathToFileURL } from 'node:url';\nimport type { ReactElement } from 'react';\nimport { renderToStaticMarkup } from 'react-dom/server';\nimport type { LLMsOptions } from '../config';\nimport { join } from '../ssr/lib/path';\nimport type { Doc } from '../ssr/lib/types';\nimport { renderSSRDocument } from '../ssr/render';\nimport { extractTitle, htmlToMarkdown, stripHtmlTags } from './formatter';\n\n/**\n * Check if a route should be excluded from LLM features\n * Supports strings (substring match), RegExp, and custom functions\n */\nexport function shouldExcludeRoute(\n\tpathname: string,\n\texcludeRoutes?: (string | RegExp | ((pathname: string) => boolean))[],\n): boolean {\n\tif (!excludeRoutes || excludeRoutes.length === 0) {\n\t\treturn false;\n\t}\n\n\treturn Boolean(\n\t\texcludeRoutes.find((pattern) => {\n\t\t\tif (typeof pattern === 'string') {\n\t\t\t\t// Substring match for simplicity\n\t\t\t\treturn pathname.includes(pattern);\n\t\t\t}\n\t\t\tif (pattern instanceof RegExp) {\n\t\t\t\treturn pattern.test(pathname);\n\t\t\t}\n\t\t\tif (typeof pattern === 'function') {\n\t\t\t\treturn pattern(pathname);\n\t\t\t}\n\t\t\treturn false;\n\t\t}),\n\t);\n}\n\nasync function loadCollectionItem(\n\tcwd: string,\n\tpathname: string,\n\tisWatchMode: boolean,\n): Promise<{ item: Doc; collection: string } | null> {\n\tconst parts = pathname.split('/').filter(Boolean);\n\tif (parts.length < 2) return null;\n\n\tconst collection = parts[0];\n\tconst collectionFile = join(\n\t\tcwd,\n\t\t'.reroute',\n\t\t'collections',\n\t\t`${collection}.js`,\n\t);\n\tconst exists = await Bun.file(collectionFile).exists();\n\tif (!exists) return null;\n\n\tconst url = `${pathToFileURL(collectionFile).href}${isWatchMode ? `?t=${Date.now()}` : ''}`;\n\tconst mod = await import(url);\n\tconst items = mod.items || [];\n\n\tconst item = items.find((i: Doc) => i.href === pathname);\n\tif (!item) return null;\n\n\treturn { item, collection };\n}\n\nasync function findComponentPath(\n\tclientDir: string,\n\tcollection: string,\n\tslug: string,\n): Promise<string | null> {\n\tconst extensions = ['.mdx', '.md', '.tsx', '.jsx'];\n\n\tfor (const ext of extensions) {\n\t\tconst testPath = join(\n\t\t\tclientDir,\n\t\t\t'routes',\n\t\t\tcollection,\n\t\t\t'content',\n\t\t\t`${slug}${ext}`,\n\t\t);\n\t\tconst file = Bun.file(testPath);\n\t\tif (await file.exists()) {\n\t\t\treturn testPath;\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction stripFrontmatterAndJsx(content: string, isMdx: boolean): string {\n\tlet rawContent = content.replace(/^---\\n[\\s\\S]*?\\n---\\n/, '');\n\n\tif (isMdx) {\n\t\trawContent = rawContent.replace(\n\t\t\t/^import\\s+.*?from\\s+['\"].*?['\"];?\\s*$/gm,\n\t\t\t'',\n\t\t);\n\t\trawContent = rawContent.replace(/<[A-Z][\\w]*[^>]*\\/>/g, '');\n\t\trawContent = rawContent.replace(\n\t\t\t/<[A-Z][\\w]*[^>]*>[\\s\\S]*?<\\/[A-Z][\\w]*>/g,\n\t\t\t'',\n\t\t);\n\t}\n\n\treturn rawContent.trim();\n}\n\nasync function extractMarkdownContent(\n\tcomponentPath: string,\n\tmeta: Record<string, unknown>,\n): Promise<{ title?: string; body: string; markdown: string }> {\n\tconst file = Bun.file(componentPath);\n\tlet rawContent = await file.text();\n\n\tconst isMdx = componentPath.endsWith('.mdx');\n\trawContent = stripFrontmatterAndJsx(rawContent, isMdx);\n\n\treturn {\n\t\ttitle: (meta.title as string) || extractTitle(rawContent),\n\t\tbody: stripHtmlTags(rawContent),\n\t\tmarkdown: rawContent,\n\t};\n}\n\nasync function extractComponentContent(\n\tcomponentPath: string,\n\tmeta: Record<string, unknown>,\n\tisWatchMode: boolean,\n): Promise<{ title?: string; body: string; markdown: string } | null> {\n\ttry {\n\t\tconst componentUrl = `${pathToFileURL(componentPath).href}${isWatchMode ? `?t=${Date.now()}` : ''}`;\n\t\tconst componentMod = await import(componentUrl);\n\n\t\tconst Component = componentMod.default;\n\t\tif (!Component || typeof Component !== 'function') return null;\n\n\t\tconst html = renderToStaticMarkup(Component({}));\n\n\t\treturn {\n\t\t\ttitle: (meta.title as string) || extractTitle(html),\n\t\t\tbody: stripHtmlTags(html),\n\t\t\tmarkdown: htmlToMarkdown(html),\n\t\t};\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\t`[reroute/llms] Failed to import component ${componentPath}:`,\n\t\t\terror,\n\t\t);\n\t\treturn null;\n\t}\n}\n\n/**\n * Extract content from a collection item (markdown/mdx)\n */\nasync function extractCollectionContent(\n\tcwd: string,\n\tclientDir: string,\n\tpathname: string,\n\tisWatchMode: boolean,\n\t_format: 'txt' | 'md',\n): Promise<{ title?: string; body: string; markdown: string } | null> {\n\ttry {\n\t\tconst collectionData = await loadCollectionItem(cwd, pathname, isWatchMode);\n\t\tif (!collectionData) return null;\n\n\t\tconst { item, collection } = collectionData;\n\t\tconst slug = item.slug || item.name;\n\t\tif (!slug) return null;\n\n\t\tconst componentPath = await findComponentPath(clientDir, collection, slug);\n\t\tif (!componentPath) return null;\n\n\t\tconst meta = item.meta || {};\n\n\t\tif (componentPath.endsWith('.md') || componentPath.endsWith('.mdx')) {\n\t\t\treturn await extractMarkdownContent(componentPath, meta);\n\t\t}\n\n\t\treturn await extractComponentContent(componentPath, meta, isWatchMode);\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\t`[reroute/llms] Failed to extract collection content for ${pathname}:`,\n\t\t\terror,\n\t\t);\n\t\treturn null;\n\t}\n}\n\n/**\n * Extract content from an SSR route using full app rendering\n */\nasync function extractSSRContent(\n\tpathname: string,\n\trootComponent: ReactElement,\n\tclientDir: string,\n\tcwd: string,\n\tisWatchMode: boolean,\n\tbundleUrl: string,\n\t_format: 'txt' | 'md',\n): Promise<{ title?: string; body: string; markdown: string } | null> {\n\ttry {\n\t\t// Use the full SSR rendering pipeline to get the complete HTML\n\t\t// This includes all providers, context, and hooks - just like a real request\n\t\tconst { html } = await renderSSRDocument({\n\t\t\tpathname,\n\t\t\trootComponent,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t\tbundleUrl,\n\t\t\tminify: false,\n\t\t\tmaxAge: 0,\n\t\t});\n\n\t\t// Extract just the content from the rendered HTML\n\t\t// Remove script tags, styles, nav, footer, etc.\n\t\tlet contentHtml = html;\n\n\t\t// Extract the body content (inside the app div)\n\t\tconst appDivMatch = html.match(/<div id=\"[^\"]+\">(.+?)<\\/div>\\s*<script/s);\n\t\tif (appDivMatch) {\n\t\t\tcontentHtml = appDivMatch[1];\n\t\t}\n\n\t\t// Remove nav and footer elements (common layout noise)\n\t\tcontentHtml = contentHtml.replace(/<nav[\\s\\S]*?<\\/nav>/gi, '');\n\t\tcontentHtml = contentHtml.replace(/<footer[\\s\\S]*?<\\/footer>/gi, '');\n\t\tcontentHtml = contentHtml.replace(/<header[\\s\\S]*?<\\/header>/gi, '');\n\t\tcontentHtml = contentHtml.replace(/<aside[\\s\\S]*?<\\/aside>/gi, '');\n\n\t\treturn {\n\t\t\ttitle: extractTitle(html),\n\t\t\tbody: stripHtmlTags(contentHtml),\n\t\t\tmarkdown: htmlToMarkdown(contentHtml),\n\t\t};\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\t`[reroute/llms] Failed to extract SSR content for ${pathname}:`,\n\t\t\terror,\n\t\t);\n\t\treturn null;\n\t}\n}\n\n/**\n * Main content extraction function\n * Extracts clean, LLM-optimized content from any route type\n */\nexport async function extractContentForLLMs(options: {\n\tpathname: string;\n\trootComponent?: ReactElement;\n\tclientDir: string;\n\tcwd: string;\n\tisWatchMode: boolean;\n\tbundleUrl?: string;\n\tformat: 'txt' | 'md';\n\tllmsConfig?: LLMsOptions;\n}): Promise<string> {\n\tconst {\n\t\tpathname,\n\t\trootComponent,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\tbundleUrl,\n\t\tformat,\n\t\tllmsConfig,\n\t} = options;\n\n\t// Check if route should be excluded\n\tif (shouldExcludeRoute(pathname, llmsConfig?.excludeRoutes)) {\n\t\tthrow new Error('Route excluded from LLM features');\n\t}\n\n\t// Try collection content first (most common case for content sites)\n\tlet content = await extractCollectionContent(\n\t\tcwd,\n\t\tclientDir,\n\t\tpathname,\n\t\tisWatchMode,\n\t\tformat,\n\t);\n\n\t// Fall back to SSR route (uses full app rendering)\n\tif (!content && rootComponent && bundleUrl) {\n\t\tcontent = await extractSSRContent(\n\t\t\tpathname,\n\t\t\trootComponent,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t\tbundleUrl,\n\t\t\tformat,\n\t\t);\n\t}\n\n\t// If we still don't have content, throw\n\tif (!content) {\n\t\tthrow new Error('Content not found');\n\t}\n\n\t// Return based on format\n\tif (format === 'md') {\n\t\t// Return markdown with title as h1\n\t\tconst parts: string[] = [];\n\t\tif (content.title) {\n\t\t\tparts.push(`# ${content.title}`);\n\t\t\tparts.push('');\n\t\t}\n\t\tparts.push(content.markdown);\n\t\treturn parts.join('\\n');\n\t}\n\n\t// Return plain text\n\tconst parts: string[] = [];\n\tif (content.title) {\n\t\tparts.push(content.title);\n\t\tparts.push('');\n\t}\n\tparts.push(content.body);\n\treturn parts.join('\\n');\n}\n",
|
|
26
|
-
"import type { ReactElement } from 'react';\nimport type { LLMsOptions } from '../config';\nimport { extractContentForLLMs, shouldExcludeRoute } from './extractor';\n\ntype RouteEntry = {\n\tpath: string;\n\tdate?: string;\n};\n\nfunction buildHeader(baseUrl: string, llmsConfig?: LLMsOptions): string[] {\n\tconst parts: string[] = [];\n\n\tif (llmsConfig?.siteName) {\n\t\tparts.push(`# ${llmsConfig.siteName}`);\n\t\tparts.push('');\n\t}\n\n\tif (llmsConfig?.siteDescription) {\n\t\tparts.push(llmsConfig.siteDescription);\n\t\tparts.push('');\n\t}\n\n\tif (parts.length > 0) {\n\t\tparts.push(`${baseUrl}/index.txt`);\n\t\tparts.push('');\n\t\tparts.push('---');\n\t\tparts.push('');\n\t}\n\n\treturn parts;\n}\n\nasync function discoverAllRoutes(\n\tcwd: string,\n\
|
|
27
|
-
"import { pathToFileURL } from 'node:url';\nimport type { LLMsOptions } from '../config';\nimport { join } from '../ssr/lib/path';\nimport type { Doc } from '../ssr/lib/types';\nimport { shouldExcludeRoute } from './extractor';\n\ntype RouteEntry = {\n\tpath: string;\n\tsection?: string;\n\ttitle?: string;\n};\n\n/**\n * Discover static routes from routes.ts\n */\nexport async function discoverStaticRoutes(\n\tcwd: string,\n\tisWatchMode: boolean,\n): Promise<RouteEntry[]> {\n\tconst routes: RouteEntry[] = [];\n\n\ttry {\n\t\t// Check for bundled routes first (compiled binary support)\n\t\tlet routesList = (globalThis as Record<string, unknown>)\n\t\t\t.__REROUTE_ROUTES__ as Doc[] | undefined;\n\n\t\t// Fallback to dynamic import (dev mode)\n\t\tif (!routesList) {\n\t\t\tconst routesPath = join(cwd, '.reroute', 'routes.ts');\n\t\t\tconst url = pathToFileURL(routesPath).href;\n\t\t\tconst mod = await import(\n\t\t\t\t`${url}${isWatchMode ? `?t=${Date.now()}` : ''}`\n\t\t\t);\n\t\t\troutesList = (mod as Doc)?.routes as Doc[] | undefined;\n\t\t}\n\t\tif (Array.isArray(routesList)) {\n\t\t\tfor (const route of routesList) {\n\t\t\t\tconst pattern = String(route?.pattern || '');\n\n\t\t\t\t// Skip error pages, layouts, and dynamic routes\n\t\t\t\tif (\n\t\t\t\t\tpattern.includes('[404]') ||\n\t\t\t\t\tpattern.includes('[layout]') ||\n\t\t\t\t\tpattern.includes('[skeleton]') ||\n\t\t\t\t\tpattern.includes(':')\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\troutes.push({\n\t\t\t\t\tpath: pattern,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tconsole.error('[reroute/llms] Failed to discover routes for index:', error);\n\t}\n\n\treturn routes;\n}\n\nasync function loadCollectionModule(\n\tcwd: string,\n\tcollection: string,\n\tisWatchMode: boolean,\n): Promise<Doc[] | null> {\n\tconst collectionFile = join(\n\t\tcwd,\n\t\t'.reroute',\n\t\t'collections',\n\t\t`${collection}.js`,\n\t);\n\tconst exists = await Bun.file(collectionFile).exists();\n\n\tif (!exists) return null;\n\n\tconst url = `${pathToFileURL(collectionFile).href}${isWatchMode ? `?t=${Date.now()}` : ''}`;\n\tconst mod = await import(url);\n\treturn mod.items || [];\n}\n\nfunction createRouteEntriesFromItems(\n\titems: Doc[],\n\tcollection: string,\n): RouteEntry[] {\n\tconst routes: RouteEntry[] = [];\n\n\tfor (const item of items) {\n\t\tconst href = String(item.href || '');\n\t\tif (href) {\n\t\t\tconst title = item.meta?.title || item.meta?.name || item.name;\n\t\t\troutes.push({\n\t\t\t\tpath: href,\n\t\t\t\tsection: collection,\n\t\t\t\ttitle,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn routes;\n}\n\nfunction sortRoutesByDate(routes: RouteEntry[], items: Doc[]): void {\n\troutes.sort((a, b) => {\n\t\tconst aItem = items.find((i: Doc) => i.href === a.path);\n\t\tconst bItem = items.find((i: Doc) => i.href === b.path);\n\n\t\tconst aDate = aItem?.meta?.date;\n\t\tconst bDate = bItem?.meta?.date;\n\n\t\tif (aDate && bDate) {\n\t\t\treturn new Date(bDate).getTime() - new Date(aDate).getTime();\n\t\t}\n\n\t\treturn 0;\n\t});\n}\n\n/**\n * Discover collection content\n */\nexport async function discoverCollectionRoutes(\n\tcwd: string,\n\tcollections: string[],\n\tisWatchMode: boolean,\n\tllmsConfig?: LLMsOptions,\n): Promise<Map<string, RouteEntry[]>> {\n\tconst collectionsMap = new Map<string, RouteEntry[]>();\n\n\tfor (const collection of collections) {\n\t\tif (llmsConfig?.excludeCollections?.includes(collection)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\ttry {\n\t\t\tconst items = await loadCollectionModule(cwd, collection, isWatchMode);\n\t\t\tif (!items) continue;\n\n\t\t\tconst routes = createRouteEntriesFromItems(items, collection);\n\n\t\t\tif (routes.length > 0) {\n\t\t\t\tsortRoutesByDate(routes, items);\n\t\t\t\tcollectionsMap.set(collection, routes);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error(\n\t\t\t\t`[reroute/llms] Failed to discover collection ${collection}:`,\n\t\t\t\terror,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn collectionsMap;\n}\n\nasync function loadRouteModule(\n\tclientDir: string,\n\troutePath: string,\n\tisWatchMode: boolean,\n): Promise<Doc | null> {\n\ttry {\n\t\tconst abs = join(clientDir, 'routes', routePath);\n\t\tconst modUrl = `${pathToFileURL(abs).href}${isWatchMode ? `?t=${Date.now()}` : ''}`;\n\t\treturn (await import(modUrl)) as Doc;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function callDataFunction(\n\tdataFn: (ctx: Doc) => unknown | Promise<unknown>,\n\troutePath: string,\n): Promise<unknown> {\n\tconst mockSet = { status: 200 };\n\treturn await dataFn({\n\t\tpathname: routePath,\n\t\tparams: {},\n\t\tset: mockSet,\n\t});\n}\n\nfunction extractIdentifier(item: Record<string, unknown>): string | undefined {\n\treturn (item.version || item.slug || item.id || item.name || item.key) as\n\t\t| string\n\t\t| undefined;\n}\n\nfunction createEntriesFromArray(array: Doc[], routePath: string): RouteEntry[] {\n\tconst entries: RouteEntry[] = [];\n\n\tfor (const item of array) {\n\t\tif (typeof item !== 'object' || item === null) continue;\n\n\t\tconst identifier = extractIdentifier(item);\n\t\tif (identifier) {\n\t\t\tentries.push({\n\t\t\t\tpath: `${routePath}/${identifier}`,\n\t\t\t\tsection: routePath.split('/').filter(Boolean)[0],\n\t\t\t});\n\t\t}\n\t}\n\n\treturn entries;\n}\n\n/**\n * Discover SSR data routes (routes with ssr.data that return arrays)\n */\nexport async function discoverSSRDataRoutes(\n\t_cwd: string,\n\tclientDir: string,\n\tstaticRoutes: RouteEntry[],\n\tisWatchMode: boolean,\n): Promise<Map<string, RouteEntry[]>> {\n\tconst ssrDataRoutes = new Map<string, RouteEntry[]>();\n\n\tfor (const route of staticRoutes) {\n\t\tconst mod = await loadRouteModule(clientDir, route.path, isWatchMode);\n\t\tif (!mod) continue;\n\n\t\tconst ssr = (mod as Doc)?.ssr as Doc | undefined;\n\t\tconst dataFn = (ssr as Doc)?.data as\n\t\t\t| ((ctx: Doc) => unknown | Promise<unknown>)\n\t\t\t| undefined;\n\n\t\tif (typeof dataFn !== 'function') continue;\n\n\t\tconst result = await callDataFunction(dataFn, route.path);\n\t\tconst arrays = findArraysInData(result);\n\n\t\tfor (const array of arrays) {\n\t\t\tif (array.length === 0) continue;\n\n\t\t\tconst entries = createEntriesFromArray(array, route.path);\n\t\t\tif (entries.length > 0) {\n\t\t\t\tssrDataRoutes.set(route.path, entries);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ssrDataRoutes;\n}\n\n/**\n * Find arrays in data object (recursive)\n */\nfunction findArraysInData(obj: unknown): Doc[] {\n\tconst arrays: Doc[] = [];\n\n\tif (!obj || typeof obj !== 'object') {\n\t\treturn arrays;\n\t}\n\n\tfor (const value of Object.values(obj)) {\n\t\tif (Array.isArray(value)) {\n\t\t\tarrays.push(value);\n\t\t} else if (value && typeof value === 'object') {\n\t\t\tarrays.push(...findArraysInData(value));\n\t\t}\n\t}\n\n\treturn arrays;\n}\n\nfunction addIndexHeader(parts: string[], llmsConfig?: LLMsOptions): void {\n\tif (llmsConfig?.siteName) {\n\t\tparts.push(`# ${llmsConfig.siteName}`);\n\t\tparts.push('');\n\t}\n\n\tif (llmsConfig?.siteDescription) {\n\t\tparts.push(llmsConfig.siteDescription);\n\t\tparts.push('');\n\t}\n}\n\nfunction groupStaticRoutes(\n\tstaticRoutes: RouteEntry[],\n\tllmsConfig?: LLMsOptions,\n): { sections: Map<string, RouteEntry[]>; rootRoutes: RouteEntry[] } {\n\tconst sections = new Map<string, RouteEntry[]>();\n\tconst rootRoutes: RouteEntry[] = [];\n\n\tfor (const route of staticRoutes) {\n\t\tif (shouldExcludeRoute(route.path, llmsConfig?.excludeRoutes)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (route.path === '/') {\n\t\t\trootRoutes.push(route);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst firstSegment = route.path.split('/').filter(Boolean)[0];\n\t\tif (!firstSegment) {\n\t\t\trootRoutes.push(route);\n\t\t} else {\n\t\t\tif (!sections.has(firstSegment)) {\n\t\t\t\tsections.set(firstSegment, []);\n\t\t\t}\n\t\t\tsections.get(firstSegment)?.push(route);\n\t\t}\n\t}\n\n\treturn { sections, rootRoutes };\n}\n\nfunction formatRouteUrl(routePath: string, baseUrl: string): string {\n\tconst urlPath = routePath === '/' ? '/index' : routePath;\n\treturn `${baseUrl}${urlPath}.txt`;\n}\n\nfunction getRouteTitle(route: RouteEntry): string {\n\treturn (\n\t\troute.title ||\n\t\t(route.path === '/' ? 'Home' : route.path.split('/').pop() || 'Page')\n\t);\n}\n\nfunction addRootRoutes(\n\tparts: string[],\n\trootRoutes: RouteEntry[],\n\tbaseUrl: string,\n\tisSingleCollection: boolean,\n): void {\n\tif (isSingleCollection || rootRoutes.length === 0) return;\n\n\tfor (const route of rootRoutes) {\n\t\tconst title = getRouteTitle(route);\n\t\tconst url = formatRouteUrl(route.path, baseUrl);\n\t\tparts.push(`- [${title}](${url})`);\n\t}\n\tparts.push('');\n}\n\nfunction addCollectionSection(\n\tparts: string[],\n\tcollection: string,\n\troutes: RouteEntry[],\n\tbaseUrl: string,\n\tllmsConfig?: LLMsOptions,\n): void {\n\tconst filteredRoutes = routes.filter(\n\t\t(r) => !shouldExcludeRoute(r.path, llmsConfig?.excludeRoutes),\n\t);\n\n\tif (filteredRoutes.length === 0) return;\n\n\tconst sectionName = collection.charAt(0).toUpperCase() + collection.slice(1);\n\tparts.push(`## ${sectionName}`);\n\tparts.push('');\n\n\tfor (const route of filteredRoutes) {\n\t\tconst title = route.title || route.path.split('/').pop() || 'Untitled';\n\t\tconst url = `${baseUrl}${route.path}.txt`;\n\t\tparts.push(`- [${title}](${url})`);\n\t}\n\tparts.push('');\n}\n\nfunction shouldIncludeSection(\n\tsection: string,\n\tisSingleCollection: boolean,\n\ttargetCollection: string | null,\n): boolean {\n\treturn !isSingleCollection || section === targetCollection;\n}\n\nfunction addSSRDataSection(\n\tparts: string[],\n\troutePattern: string,\n\troutes: RouteEntry[],\n\tbaseUrl: string,\n\tisSingleCollection: boolean,\n\ttargetCollection: string | null,\n\tllmsConfig?: LLMsOptions,\n): void {\n\tconst routeSection = routePattern.split('/').filter(Boolean)[0];\n\n\tif (\n\t\t!shouldIncludeSection(routeSection, isSingleCollection, targetCollection)\n\t) {\n\t\treturn;\n\t}\n\n\tconst filteredRoutes = routes.filter(\n\t\t(r) => !shouldExcludeRoute(r.path, llmsConfig?.excludeRoutes),\n\t);\n\n\tif (filteredRoutes.length === 0) return;\n\n\tconst sectionName =\n\t\trouteSection?.charAt(0).toUpperCase() + routeSection?.slice(1) || 'Content';\n\tparts.push(`## ${sectionName}`);\n\tparts.push('');\n\n\tfor (const route of filteredRoutes) {\n\t\tconst title = route.title || route.path.split('/').pop() || 'Untitled';\n\t\tconst url = `${baseUrl}${route.path}.txt`;\n\t\tparts.push(`- [${title}](${url})`);\n\t}\n\tparts.push('');\n}\n\nfunction addStaticSection(\n\tparts: string[],\n\tsection: string,\n\troutes: RouteEntry[],\n\tbaseUrl: string,\n\tisSingleCollection: boolean,\n\ttargetCollection: string | null,\n\tcollectionsMap: Map<string, RouteEntry[]>,\n\tllmsConfig?: LLMsOptions,\n): void {\n\tif (!shouldIncludeSection(section, isSingleCollection, targetCollection)) {\n\t\treturn;\n\t}\n\n\tconst filteredRoutes = routes.filter(\n\t\t(r) => !shouldExcludeRoute(r.path, llmsConfig?.excludeRoutes),\n\t);\n\n\tif (filteredRoutes.length === 0 || collectionsMap.has(section)) return;\n\n\tconst sectionName = section.charAt(0).toUpperCase() + section.slice(1);\n\tparts.push(`## ${sectionName}`);\n\tparts.push('');\n\n\tfor (const route of filteredRoutes) {\n\t\tconst title = route.title || route.path.split('/').pop() || 'Untitled';\n\t\tconst url = `${baseUrl}${route.path}.txt`;\n\t\tparts.push(`- [${title}](${url})`);\n\t}\n\tparts.push('');\n}\n\n/**\n * Generate /llms.txt index\n * Simple, token-efficient format: just URLs grouped by section\n */\nexport async function generateLLMsIndex(options: {\n\tcwd: string;\n\tclientDir: string;\n\tcollections: string[];\n\tbaseUrl: string;\n\tisWatchMode: boolean;\n\tllmsConfig?: LLMsOptions;\n}): Promise<string> {\n\tconst { cwd, clientDir, collections, baseUrl, isWatchMode, llmsConfig } =\n\t\toptions;\n\n\tconst parts: string[] = [];\n\taddIndexHeader(parts, llmsConfig);\n\n\tconst staticRoutes = await discoverStaticRoutes(cwd, isWatchMode);\n\tconst collectionsMap = await discoverCollectionRoutes(\n\t\tcwd,\n\t\tcollections,\n\t\tisWatchMode,\n\t\tllmsConfig,\n\t);\n\tconst ssrDataRoutes = await discoverSSRDataRoutes(\n\t\tcwd,\n\t\tclientDir,\n\t\tstaticRoutes,\n\t\tisWatchMode,\n\t);\n\n\tconst isSingleCollection = collections.length === 1;\n\tconst targetCollection = isSingleCollection ? collections[0] : null;\n\n\tconst { sections, rootRoutes } = groupStaticRoutes(staticRoutes, llmsConfig);\n\n\taddRootRoutes(parts, rootRoutes, baseUrl, isSingleCollection);\n\n\tfor (const [collection, routes] of collectionsMap.entries()) {\n\t\tif (routes.length > 0) {\n\t\t\taddCollectionSection(parts, collection, routes, baseUrl, llmsConfig);\n\t\t}\n\t}\n\n\tfor (const [routePattern, routes] of ssrDataRoutes.entries()) {\n\t\tif (routes.length > 0) {\n\t\t\taddSSRDataSection(\n\t\t\t\tparts,\n\t\t\t\troutePattern,\n\t\t\t\troutes,\n\t\t\t\tbaseUrl,\n\t\t\t\tisSingleCollection,\n\t\t\t\ttargetCollection,\n\t\t\t\tllmsConfig,\n\t\t\t);\n\t\t}\n\t}\n\n\tfor (const [section, routes] of sections.entries()) {\n\t\tif (routes.length > 0) {\n\t\t\taddStaticSection(\n\t\t\t\tparts,\n\t\t\t\tsection,\n\t\t\t\troutes,\n\t\t\t\tbaseUrl,\n\t\t\t\tisSingleCollection,\n\t\t\t\ttargetCollection,\n\t\t\t\tcollectionsMap,\n\t\t\t\tllmsConfig,\n\t\t\t);\n\t\t}\n\t}\n\n\tparts.push('---');\n\tparts.push('');\n\tparts.push(\n\t\t'Formats: .txt | .md | Accept: text/plain | Accept: text/markdown',\n\t);\n\n\treturn parts.join('\\n');\n}\n",
|
|
26
|
+
"import type { ReactElement } from 'react';\nimport type { LLMsOptions } from '../config';\nimport { extractContentForLLMs, shouldExcludeRoute } from './extractor';\n\ntype RouteEntry = {\n\tpath: string;\n\tdate?: string;\n};\n\nfunction buildHeader(baseUrl: string, llmsConfig?: LLMsOptions): string[] {\n\tconst parts: string[] = [];\n\n\tif (llmsConfig?.siteName) {\n\t\tparts.push(`# ${llmsConfig.siteName}`);\n\t\tparts.push('');\n\t}\n\n\tif (llmsConfig?.siteDescription) {\n\t\tparts.push(llmsConfig.siteDescription);\n\t\tparts.push('');\n\t}\n\n\tif (parts.length > 0) {\n\t\tparts.push(`${baseUrl}/index.txt`);\n\t\tparts.push('');\n\t\tparts.push('---');\n\t\tparts.push('');\n\t}\n\n\treturn parts;\n}\n\nasync function discoverAllRoutes(\n\tcwd: string,\n\tcollections: string[],\n\tisWatchMode: boolean,\n\tllmsConfig?: LLMsOptions,\n): Promise<RouteEntry[]> {\n\tconst {\n\t\tdiscoverStaticRoutes,\n\t\tdiscoverCollectionRoutes,\n\t\tdiscoverSSRDataRoutes,\n\t} = await import('./index-generator');\n\n\tconst staticRoutes = await discoverStaticRoutes(cwd, isWatchMode);\n\tconst collectionsMap = await discoverCollectionRoutes(\n\t\tcwd,\n\t\tcollections,\n\t\tisWatchMode,\n\t\tllmsConfig,\n\t);\n\tconst ssrDataRoutes = await discoverSSRDataRoutes(\n\t\tcwd,\n\t\tstaticRoutes,\n\t\tisWatchMode,\n\t);\n\n\tconst allRoutes: RouteEntry[] = [];\n\n\tfor (const route of staticRoutes) {\n\t\tif (!shouldExcludeRoute(route.path, llmsConfig?.excludeRoutes)) {\n\t\t\tallRoutes.push({ path: route.path });\n\t\t}\n\t}\n\n\tfor (const [_collection, routes] of collectionsMap.entries()) {\n\t\tfor (const route of routes) {\n\t\t\tif (!shouldExcludeRoute(route.path, llmsConfig?.excludeRoutes)) {\n\t\t\t\tallRoutes.push({ path: route.path });\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const [_routePattern, routes] of ssrDataRoutes.entries()) {\n\t\tfor (const route of routes) {\n\t\t\tif (!shouldExcludeRoute(route.path, llmsConfig?.excludeRoutes)) {\n\t\t\t\tallRoutes.push({ path: route.path });\n\t\t\t}\n\t\t}\n\t}\n\n\treturn allRoutes;\n}\n\nfunction formatContentBlock(\n\tcontent: string,\n\troutePath: string,\n\tbaseUrl: string,\n): string[] {\n\tconst parts: string[] = [];\n\tconst lines = content.split('\\n');\n\tconst title = lines[0] || 'Untitled';\n\tconst body = lines.slice(lines[1] === '' ? 2 : 1).join('\\n');\n\n\tconst urlPath = routePath === '/' ? '/index' : routePath;\n\tconst url = `${baseUrl}${urlPath}.txt`;\n\n\tparts.push(title);\n\tparts.push('');\n\tparts.push(url);\n\tparts.push('');\n\tif (body.trim()) {\n\t\tparts.push(body);\n\t\tparts.push('');\n\t}\n\tparts.push('---');\n\tparts.push('');\n\n\treturn parts;\n}\n\nasync function extractRouteContents(\n\troutes: RouteEntry[],\n\toptions: {\n\t\trootComponent?: ReactElement;\n\t\tcwd: string;\n\t\tclientDir: string;\n\t\tbaseUrl: string;\n\t\tisWatchMode: boolean;\n\t\tbundleUrl?: string;\n\t\tllmsConfig?: LLMsOptions;\n\t},\n): Promise<{ parts: string[]; itemCount: number; currentSize: number }> {\n\tconst parts: string[] = [];\n\tconst maxSize = options.llmsConfig?.maxSize || 50 * 1024 * 1024;\n\tlet itemCount = 0;\n\tlet currentSize = 0;\n\n\tfor (const route of routes) {\n\t\ttry {\n\t\t\tconst content = await extractContentForLLMs({\n\t\t\t\tpathname: route.path,\n\t\t\t\trootComponent: options.rootComponent,\n\t\t\t\tclientDir: options.clientDir,\n\t\t\t\tcwd: options.cwd,\n\t\t\t\tisWatchMode: options.isWatchMode,\n\t\t\t\tbundleUrl: options.bundleUrl,\n\t\t\t\tformat: 'txt',\n\t\t\t\tllmsConfig: options.llmsConfig,\n\t\t\t});\n\n\t\t\tconst contentSize = Buffer.byteLength(content, 'utf8');\n\t\t\tif (currentSize + contentSize > maxSize) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[reroute/llms] Reached size limit (${maxSize} bytes), stopping at ${itemCount} items`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst blockParts = formatContentBlock(\n\t\t\t\tcontent,\n\t\t\t\troute.path,\n\t\t\t\toptions.baseUrl,\n\t\t\t);\n\t\t\tparts.push(...blockParts);\n\n\t\t\titemCount++;\n\t\t\tcurrentSize += contentSize;\n\t\t} catch (error) {\n\t\t\tconsole.warn(\n\t\t\t\t`[reroute/llms] Failed to extract content for ${route.path}:`,\n\t\t\t\terror,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn { parts, itemCount, currentSize };\n}\n\nfunction buildFooter(parts: string[]): void {\n\tif (parts.length === 0) return;\n\n\t// Remove last separator\n\tif (parts[parts.length - 1] === '') parts.pop();\n\tif (parts[parts.length - 1] === '---') parts.pop();\n\tif (parts[parts.length - 1] === '') parts.pop();\n\n\tparts.push('---');\n\tparts.push('');\n\tparts.push(\n\t\t'Formats: .txt | .md | Accept: text/plain | Accept: text/markdown',\n\t);\n}\n\n/**\n * Generate /llms-full.txt - all site content in one file\n * Runtime-only generation with aggressive caching (7 days default)\n */\nexport async function generateLLMsFullContent(options: {\n\trootComponent?: ReactElement;\n\tcwd: string;\n\tclientDir: string;\n\tcollections: string[];\n\tbaseUrl: string;\n\tisWatchMode: boolean;\n\tbundleUrl?: string;\n\tllmsConfig?: LLMsOptions;\n}): Promise<{\n\tcontent: string;\n\tstats: { itemCount: number; byteSize: number };\n}> {\n\tconst { cwd, collections, baseUrl, isWatchMode, llmsConfig } = options;\n\n\tconst parts = buildHeader(baseUrl, llmsConfig);\n\n\tconst allRoutes = await discoverAllRoutes(\n\t\tcwd,\n\t\tcollections,\n\t\tisWatchMode,\n\t\tllmsConfig,\n\t);\n\n\tconst maxItems = llmsConfig?.maxItems || 10000;\n\tconst routesToProcess = allRoutes.slice(0, maxItems);\n\n\tconst extracted = await extractRouteContents(routesToProcess, options);\n\tparts.push(...extracted.parts);\n\n\tbuildFooter(parts);\n\n\tconst fullContent = parts.join('\\n');\n\tconst byteSize = Buffer.byteLength(fullContent, 'utf8');\n\n\treturn {\n\t\tcontent: fullContent,\n\t\tstats: { itemCount: extracted.itemCount, byteSize },\n\t};\n}\n",
|
|
27
|
+
"import { pathToFileURL } from 'node:url';\nimport type { LLMsOptions } from '../config';\nimport { join } from '../ssr/lib/path';\nimport type { Doc } from '../ssr/lib/types';\nimport { shouldExcludeRoute } from './extractor';\n\ntype RouteEntry = {\n\tpath: string;\n\tsection?: string;\n\ttitle?: string;\n};\n\n/**\n * Discover static routes from routes.ts\n */\nexport async function discoverStaticRoutes(\n\tcwd: string,\n\tisWatchMode: boolean,\n): Promise<RouteEntry[]> {\n\tconst routes: RouteEntry[] = [];\n\n\ttry {\n\t\t// Check for bundled routes first (compiled binary support)\n\t\tlet routesList = (globalThis as Record<string, unknown>)\n\t\t\t.__REROUTE_ROUTES__ as Doc[] | undefined;\n\n\t\t// Fallback to dynamic import (dev mode)\n\t\tif (!routesList) {\n\t\t\tconst routesPath = join(cwd, '.reroute', 'routes.ts');\n\t\t\tconst url = pathToFileURL(routesPath).href;\n\t\t\tconst mod = await import(\n\t\t\t\t`${url}${isWatchMode ? `?t=${Date.now()}` : ''}`\n\t\t\t);\n\t\t\troutesList = (mod as Doc)?.routes as Doc[] | undefined;\n\t\t}\n\t\tif (Array.isArray(routesList)) {\n\t\t\tfor (const route of routesList) {\n\t\t\t\tconst pattern = String(route?.pattern || '');\n\n\t\t\t\t// Skip error pages, layouts, and dynamic routes\n\t\t\t\tif (\n\t\t\t\t\tpattern.includes('[404]') ||\n\t\t\t\t\tpattern.includes('[layout]') ||\n\t\t\t\t\tpattern.includes('[skeleton]') ||\n\t\t\t\t\tpattern.includes(':')\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\troutes.push({\n\t\t\t\t\tpath: pattern,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tconsole.error('[reroute/llms] Failed to discover routes for index:', error);\n\t}\n\n\treturn routes;\n}\n\nasync function loadCollectionModule(\n\tcwd: string,\n\tcollection: string,\n\tisWatchMode: boolean,\n): Promise<Doc[] | null> {\n\tconst collectionFile = join(\n\t\tcwd,\n\t\t'.reroute',\n\t\t'collections',\n\t\t`${collection}.js`,\n\t);\n\tconst exists = await Bun.file(collectionFile).exists();\n\n\tif (!exists) return null;\n\n\tconst url = `${pathToFileURL(collectionFile).href}${isWatchMode ? `?t=${Date.now()}` : ''}`;\n\tconst mod = await import(url);\n\treturn mod.items || [];\n}\n\nfunction createRouteEntriesFromItems(\n\titems: Doc[],\n\tcollection: string,\n): RouteEntry[] {\n\tconst routes: RouteEntry[] = [];\n\n\tfor (const item of items) {\n\t\tconst href = String(item.href || '');\n\t\tif (href) {\n\t\t\tconst title = item.meta?.title || item.meta?.name || item.name;\n\t\t\troutes.push({\n\t\t\t\tpath: href,\n\t\t\t\tsection: collection,\n\t\t\t\ttitle,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn routes;\n}\n\nfunction sortRoutesByDate(routes: RouteEntry[], items: Doc[]): void {\n\troutes.sort((a, b) => {\n\t\tconst aItem = items.find((i: Doc) => i.href === a.path);\n\t\tconst bItem = items.find((i: Doc) => i.href === b.path);\n\n\t\tconst aDate = aItem?.meta?.date;\n\t\tconst bDate = bItem?.meta?.date;\n\n\t\tif (aDate && bDate) {\n\t\t\treturn new Date(bDate).getTime() - new Date(aDate).getTime();\n\t\t}\n\n\t\treturn 0;\n\t});\n}\n\n/**\n * Discover collection content\n */\nexport async function discoverCollectionRoutes(\n\tcwd: string,\n\tcollections: string[],\n\tisWatchMode: boolean,\n\tllmsConfig?: LLMsOptions,\n): Promise<Map<string, RouteEntry[]>> {\n\tconst collectionsMap = new Map<string, RouteEntry[]>();\n\n\tfor (const collection of collections) {\n\t\tif (llmsConfig?.excludeCollections?.includes(collection)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\ttry {\n\t\t\tconst items = await loadCollectionModule(cwd, collection, isWatchMode);\n\t\t\tif (!items) continue;\n\n\t\t\tconst routes = createRouteEntriesFromItems(items, collection);\n\n\t\t\tif (routes.length > 0) {\n\t\t\t\tsortRoutesByDate(routes, items);\n\t\t\t\tcollectionsMap.set(collection, routes);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error(\n\t\t\t\t`[reroute/llms] Failed to discover collection ${collection}:`,\n\t\t\t\terror,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn collectionsMap;\n}\n\nasync function loadRouteModule(\n\tcwd: string,\n\troutePath: string,\n\tisWatchMode: boolean,\n): Promise<Doc | null> {\n\ttry {\n\t\tconst abs = join(cwd, 'src', 'client', 'routes', routePath);\n\t\tconst modUrl = `${pathToFileURL(abs).href}${isWatchMode ? `?t=${Date.now()}` : ''}`;\n\t\treturn (await import(modUrl)) as Doc;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function callDataFunction(\n\tdataFn: (ctx: Doc) => unknown | Promise<unknown>,\n\troutePath: string,\n): Promise<unknown> {\n\tconst mockSet = { status: 200 };\n\treturn await dataFn({\n\t\tpathname: routePath,\n\t\tparams: {},\n\t\tset: mockSet,\n\t});\n}\n\nfunction extractIdentifier(item: Record<string, unknown>): string | undefined {\n\treturn (item.version || item.slug || item.id || item.name || item.key) as\n\t\t| string\n\t\t| undefined;\n}\n\nfunction createEntriesFromArray(array: Doc[], routePath: string): RouteEntry[] {\n\tconst entries: RouteEntry[] = [];\n\n\tfor (const item of array) {\n\t\tif (typeof item !== 'object' || item === null) continue;\n\n\t\tconst identifier = extractIdentifier(item);\n\t\tif (identifier) {\n\t\t\tentries.push({\n\t\t\t\tpath: `${routePath}/${identifier}`,\n\t\t\t\tsection: routePath.split('/').filter(Boolean)[0],\n\t\t\t});\n\t\t}\n\t}\n\n\treturn entries;\n}\n\n/**\n * Discover SSR data routes (routes with ssr.data that return arrays)\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: discovering ssr data routes is complex\nexport async function discoverSSRDataRoutes(\n\tcwd: string,\n\tstaticRoutes: RouteEntry[],\n\tisWatchMode: boolean,\n): Promise<Map<string, RouteEntry[]>> {\n\tconst ssrDataRoutes = new Map<string, RouteEntry[]>();\n\n\t// Check for bundled routes first (compiled binary support)\n\tconst bundledRoutes = (globalThis as Record<string, unknown>)\n\t\t.__REROUTE_ROUTES__ as Doc[] | undefined;\n\n\tif (bundledRoutes && Array.isArray(bundledRoutes)) {\n\t\t// In production: use pre-loaded SSR data from bundled routes\n\t\t// Match static routes against bundled routes to get their ssr.data\n\t\tfor (const route of staticRoutes) {\n\t\t\t// Find the matching bundled route by path\n\t\t\tconst bundledRoute = bundledRoutes.find((r) => r?.path === route.path);\n\n\t\t\tif (!bundledRoute) continue;\n\n\t\t\tconst ssr = (bundledRoute as Doc)?.ssr as Doc | undefined;\n\t\t\tconst dataFn = (ssr as Doc)?.data as\n\t\t\t\t| ((ctx: Doc) => unknown | Promise<unknown>)\n\t\t\t\t| undefined;\n\n\t\t\tif (typeof dataFn !== 'function') continue;\n\n\t\t\tconst result = await callDataFunction(dataFn, route.path);\n\t\t\tconst arrays = findArraysInData(result);\n\n\t\t\tfor (const array of arrays) {\n\t\t\t\tif (array.length === 0) continue;\n\n\t\t\t\tconst entries = createEntriesFromArray(array, route.path);\n\t\t\t\tif (entries.length > 0) {\n\t\t\t\t\tssrDataRoutes.set(route.path, entries);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// Dev mode: dynamically import route modules\n\t\tfor (const route of staticRoutes) {\n\t\t\tconst mod = await loadRouteModule(cwd, route.path, isWatchMode);\n\t\t\tif (!mod) continue;\n\n\t\t\tconst ssr = (mod as Doc)?.ssr as Doc | undefined;\n\t\t\tconst dataFn = (ssr as Doc)?.data as\n\t\t\t\t| ((ctx: Doc) => unknown | Promise<unknown>)\n\t\t\t\t| undefined;\n\n\t\t\tif (typeof dataFn !== 'function') continue;\n\n\t\t\tconst result = await callDataFunction(dataFn, route.path);\n\t\t\tconst arrays = findArraysInData(result);\n\n\t\t\tfor (const array of arrays) {\n\t\t\t\tif (array.length === 0) continue;\n\n\t\t\t\tconst entries = createEntriesFromArray(array, route.path);\n\t\t\t\tif (entries.length > 0) {\n\t\t\t\t\tssrDataRoutes.set(route.path, entries);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ssrDataRoutes;\n}\n\n/**\n * Find arrays in data object (recursive)\n */\nfunction findArraysInData(obj: unknown): Doc[] {\n\tconst arrays: Doc[] = [];\n\n\tif (!obj || typeof obj !== 'object') {\n\t\treturn arrays;\n\t}\n\n\tfor (const value of Object.values(obj)) {\n\t\tif (Array.isArray(value)) {\n\t\t\tarrays.push(value);\n\t\t} else if (value && typeof value === 'object') {\n\t\t\tarrays.push(...findArraysInData(value));\n\t\t}\n\t}\n\n\treturn arrays;\n}\n\nfunction addIndexHeader(parts: string[], llmsConfig?: LLMsOptions): void {\n\tif (llmsConfig?.siteName) {\n\t\tparts.push(`# ${llmsConfig.siteName}`);\n\t\tparts.push('');\n\t}\n\n\tif (llmsConfig?.siteDescription) {\n\t\tparts.push(llmsConfig.siteDescription);\n\t\tparts.push('');\n\t}\n}\n\nfunction groupStaticRoutes(\n\tstaticRoutes: RouteEntry[],\n\tllmsConfig?: LLMsOptions,\n): { sections: Map<string, RouteEntry[]>; rootRoutes: RouteEntry[] } {\n\tconst sections = new Map<string, RouteEntry[]>();\n\tconst rootRoutes: RouteEntry[] = [];\n\n\tfor (const route of staticRoutes) {\n\t\tif (shouldExcludeRoute(route.path, llmsConfig?.excludeRoutes)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (route.path === '/') {\n\t\t\trootRoutes.push(route);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst firstSegment = route.path.split('/').filter(Boolean)[0];\n\t\tif (!firstSegment) {\n\t\t\trootRoutes.push(route);\n\t\t} else {\n\t\t\tif (!sections.has(firstSegment)) {\n\t\t\t\tsections.set(firstSegment, []);\n\t\t\t}\n\t\t\tsections.get(firstSegment)?.push(route);\n\t\t}\n\t}\n\n\treturn { sections, rootRoutes };\n}\n\nfunction formatRouteUrl(routePath: string, baseUrl: string): string {\n\tconst urlPath = routePath === '/' ? '/index' : routePath;\n\treturn `${baseUrl}${urlPath}.txt`;\n}\n\nfunction getRouteTitle(route: RouteEntry): string {\n\treturn (\n\t\troute.title ||\n\t\t(route.path === '/' ? 'Home' : route.path.split('/').pop() || 'Page')\n\t);\n}\n\nfunction addRootRoutes(\n\tparts: string[],\n\trootRoutes: RouteEntry[],\n\tbaseUrl: string,\n\tisSingleCollection: boolean,\n): void {\n\tif (isSingleCollection || rootRoutes.length === 0) return;\n\n\tfor (const route of rootRoutes) {\n\t\tconst title = getRouteTitle(route);\n\t\tconst url = formatRouteUrl(route.path, baseUrl);\n\t\tparts.push(`- [${title}](${url})`);\n\t}\n\tparts.push('');\n}\n\nfunction addCollectionSection(\n\tparts: string[],\n\tcollection: string,\n\troutes: RouteEntry[],\n\tbaseUrl: string,\n\tllmsConfig?: LLMsOptions,\n): void {\n\tconst filteredRoutes = routes.filter(\n\t\t(r) => !shouldExcludeRoute(r.path, llmsConfig?.excludeRoutes),\n\t);\n\n\tif (filteredRoutes.length === 0) return;\n\n\tconst sectionName = collection.charAt(0).toUpperCase() + collection.slice(1);\n\tparts.push(`## ${sectionName}`);\n\tparts.push('');\n\n\tfor (const route of filteredRoutes) {\n\t\tconst title = route.title || route.path.split('/').pop() || 'Untitled';\n\t\tconst url = `${baseUrl}${route.path}.txt`;\n\t\tparts.push(`- [${title}](${url})`);\n\t}\n\tparts.push('');\n}\n\nfunction shouldIncludeSection(\n\tsection: string,\n\tisSingleCollection: boolean,\n\ttargetCollection: string | null,\n): boolean {\n\treturn !isSingleCollection || section === targetCollection;\n}\n\nfunction addSSRDataSection(\n\tparts: string[],\n\troutePattern: string,\n\troutes: RouteEntry[],\n\tbaseUrl: string,\n\tisSingleCollection: boolean,\n\ttargetCollection: string | null,\n\tllmsConfig?: LLMsOptions,\n): void {\n\tconst routeSection = routePattern.split('/').filter(Boolean)[0];\n\n\tif (\n\t\t!shouldIncludeSection(routeSection, isSingleCollection, targetCollection)\n\t) {\n\t\treturn;\n\t}\n\n\tconst filteredRoutes = routes.filter(\n\t\t(r) => !shouldExcludeRoute(r.path, llmsConfig?.excludeRoutes),\n\t);\n\n\tif (filteredRoutes.length === 0) return;\n\n\tconst sectionName =\n\t\trouteSection?.charAt(0).toUpperCase() + routeSection?.slice(1) || 'Content';\n\tparts.push(`## ${sectionName}`);\n\tparts.push('');\n\n\tfor (const route of filteredRoutes) {\n\t\tconst title = route.title || route.path.split('/').pop() || 'Untitled';\n\t\tconst url = `${baseUrl}${route.path}.txt`;\n\t\tparts.push(`- [${title}](${url})`);\n\t}\n\tparts.push('');\n}\n\nfunction addStaticSection(\n\tparts: string[],\n\tsection: string,\n\troutes: RouteEntry[],\n\tbaseUrl: string,\n\tisSingleCollection: boolean,\n\ttargetCollection: string | null,\n\tcollectionsMap: Map<string, RouteEntry[]>,\n\tllmsConfig?: LLMsOptions,\n): void {\n\tif (!shouldIncludeSection(section, isSingleCollection, targetCollection)) {\n\t\treturn;\n\t}\n\n\tconst filteredRoutes = routes.filter(\n\t\t(r) => !shouldExcludeRoute(r.path, llmsConfig?.excludeRoutes),\n\t);\n\n\tif (filteredRoutes.length === 0 || collectionsMap.has(section)) return;\n\n\tconst sectionName = section.charAt(0).toUpperCase() + section.slice(1);\n\tparts.push(`## ${sectionName}`);\n\tparts.push('');\n\n\tfor (const route of filteredRoutes) {\n\t\tconst title = route.title || route.path.split('/').pop() || 'Untitled';\n\t\tconst url = `${baseUrl}${route.path}.txt`;\n\t\tparts.push(`- [${title}](${url})`);\n\t}\n\tparts.push('');\n}\n\n/**\n * Generate /llms.txt index\n * Simple, token-efficient format: just URLs grouped by section\n */\nexport async function generateLLMsIndex(options: {\n\tcwd: string;\n\tcollections: string[];\n\tbaseUrl: string;\n\tisWatchMode: boolean;\n\tllmsConfig?: LLMsOptions;\n}): Promise<string> {\n\tconst { cwd, collections, baseUrl, isWatchMode, llmsConfig } = options;\n\n\tconst parts: string[] = [];\n\taddIndexHeader(parts, llmsConfig);\n\n\tconst staticRoutes = await discoverStaticRoutes(cwd, isWatchMode);\n\tconst collectionsMap = await discoverCollectionRoutes(\n\t\tcwd,\n\t\tcollections,\n\t\tisWatchMode,\n\t\tllmsConfig,\n\t);\n\tconst ssrDataRoutes = await discoverSSRDataRoutes(\n\t\tcwd,\n\t\tstaticRoutes,\n\t\tisWatchMode,\n\t);\n\n\tconst isSingleCollection = collections.length === 1;\n\tconst targetCollection = isSingleCollection ? collections[0] : null;\n\n\tconst { sections, rootRoutes } = groupStaticRoutes(staticRoutes, llmsConfig);\n\n\taddRootRoutes(parts, rootRoutes, baseUrl, isSingleCollection);\n\n\tfor (const [collection, routes] of collectionsMap.entries()) {\n\t\tif (routes.length > 0) {\n\t\t\taddCollectionSection(parts, collection, routes, baseUrl, llmsConfig);\n\t\t}\n\t}\n\n\tfor (const [routePattern, routes] of ssrDataRoutes.entries()) {\n\t\tif (routes.length > 0) {\n\t\t\taddSSRDataSection(\n\t\t\t\tparts,\n\t\t\t\troutePattern,\n\t\t\t\troutes,\n\t\t\t\tbaseUrl,\n\t\t\t\tisSingleCollection,\n\t\t\t\ttargetCollection,\n\t\t\t\tllmsConfig,\n\t\t\t);\n\t\t}\n\t}\n\n\tfor (const [section, routes] of sections.entries()) {\n\t\tif (routes.length > 0) {\n\t\t\taddStaticSection(\n\t\t\t\tparts,\n\t\t\t\tsection,\n\t\t\t\troutes,\n\t\t\t\tbaseUrl,\n\t\t\t\tisSingleCollection,\n\t\t\t\ttargetCollection,\n\t\t\t\tcollectionsMap,\n\t\t\t\tllmsConfig,\n\t\t\t);\n\t\t}\n\t}\n\n\tparts.push('---');\n\tparts.push('');\n\tparts.push(\n\t\t'Formats: .txt | .md | Accept: text/plain | Accept: text/markdown',\n\t);\n\n\treturn parts.join('\\n');\n}\n",
|
|
28
28
|
"/**\n * LLMs Feature - Native LLM-friendly content formats\n *\n * Provides:\n * - .txt and .md extensions for any route\n * - Accept header content negotiation (text/plain, text/markdown)\n * - /llms.txt index of all content\n * - /llms-full.txt bundle of all content\n *\n * All formats are token-efficient: minimal metadata, maximum useful content\n */\n\nexport { extractContentForLLMs, shouldExcludeRoute } from './extractor';\nexport {\n\textractTitle,\n\tformatAsMarkdown,\n\tformatAsText,\n\tgenerateLLMsFooter,\n\thtmlToMarkdown,\n\tstripHtmlTags,\n} from './formatter';\nexport { generateLLMsFullContent } from './full-generator';\nexport { generateLLMsIndex } from './index-generator';\n",
|
|
29
29
|
"import type { ImageResponseOptions } from '@vercel/og';\nimport { createElement } from 'react';\nimport type { OGImageFont } from '../config';\nimport type { OGImageProps } from './types';\n\n// biome-ignore lint/suspicious/noExplicitAny: what we can do here?\ntype Any = any;\n/**\n * Render an OG image component to PNG using Satori and resvg\n */\n\nexport async function renderOGImageToPNG(\n\tComponent: Any,\n\tprops: OGImageProps,\n\toptions: {\n\t\twidth?: number;\n\t\theight?: number;\n\t\tfonts?: OGImageFont[];\n\t} = {},\n): Promise<Buffer> {\n\tconst width = options.width || 1200;\n\tconst height = options.height || 630;\n\n\ttry {\n\t\t// Dynamically import @vercel/og to avoid bundling it if not used\n\t\tconst { ImageResponse } = await import('@vercel/og');\n\n\t\t// Create React element from component\n\t\tconst element = createElement(Component, props);\n\n\t\t// Use ImageResponse to render the component\n\t\tconst imageResponse = new ImageResponse(element, {\n\t\t\twidth,\n\t\t\theight,\n\t\t\tfonts: options.fonts as ImageResponseOptions['fonts'],\n\t\t});\n\n\t\t// Convert Response to Buffer\n\t\tconst arrayBuffer = await imageResponse.arrayBuffer();\n\t\treturn Buffer.from(arrayBuffer);\n\t} catch (error) {\n\t\tconsole.error('[reroute] Failed to render OG image:', error);\n\t\tthrow new Error(\n\t\t\t`Failed to render OG image: ${error instanceof Error ? error.message : String(error)}`,\n\t\t);\n\t}\n}\n\n/**\n * Default OG image template\n * Renders a simple card with title and description\n */\nexport function DefaultOGTemplate({\n\tmeta,\n\tavatar,\n\tsiteName: siteNameProp,\n}: OGImageProps) {\n\tconst title = meta?.title || 'Untitled';\n\tconst description = meta?.description || '';\n\tconst siteName = siteNameProp || meta?.site_name || meta?.siteName || '';\n\n\treturn createElement(\n\t\t'div',\n\t\t{\n\t\t\tstyle: {\n\t\t\t\tdisplay: 'flex',\n\t\t\t\tflexDirection: 'column',\n\t\t\t\twidth: '100%',\n\t\t\t\theight: '100%',\n\t\t\t\tbackgroundColor: '#ffffff',\n\t\t\t\tpadding: '80px',\n\t\t\t\tfontFamily: 'system-ui, sans-serif',\n\t\t\t},\n\t\t},\n\t\tcreateElement(\n\t\t\t'div',\n\t\t\t{\n\t\t\t\tstyle: {\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\tflexDirection: 'column',\n\t\t\t\t\twidth: '100%',\n\t\t\t\t\theight: '100%',\n\t\t\t\t\tborder: '4px solid #000000',\n\t\t\t\t\tborderRadius: '24px',\n\t\t\t\t\tpadding: '64px',\n\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t},\n\t\t\t},\n\t\t\tcreateElement(\n\t\t\t\t'div',\n\t\t\t\t{\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\tflexDirection: 'column',\n\t\t\t\t\t\tgap: '24px',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcreateElement(\n\t\t\t\t\t'h1',\n\t\t\t\t\t{\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tfontSize: '72px',\n\t\t\t\t\t\t\tfontWeight: 'bold',\n\t\t\t\t\t\t\tlineHeight: 1.2,\n\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\tcolor: '#000000',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\ttitle,\n\t\t\t\t),\n\t\t\t\tdescription &&\n\t\t\t\t\tcreateElement(\n\t\t\t\t\t\t'p',\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\tfontSize: '32px',\n\t\t\t\t\t\t\t\tlineHeight: 1.5,\n\t\t\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\t\t\tcolor: '#666666',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdescription,\n\t\t\t\t\t),\n\t\t\t),\n\t\t\tcreateElement(\n\t\t\t\t'div',\n\t\t\t\t{\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tsiteName &&\n\t\t\t\t\tcreateElement(\n\t\t\t\t\t\t'div',\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\t\tfontSize: '28px',\n\t\t\t\t\t\t\t\tcolor: '#999999',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsiteName,\n\t\t\t\t\t),\n\t\t\t\tavatar &&\n\t\t\t\t\tcreateElement('img', {\n\t\t\t\t\t\tsrc: avatar,\n\t\t\t\t\t\twidth: 80,\n\t\t\t\t\t\theight: 80,\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\tobjectFit: 'cover',\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t!avatar &&\n\t\t\t\t\tcreateElement('div', {\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\twidth: '80px',\n\t\t\t\t\t\t\theight: '80px',\n\t\t\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t\t\t\tbackgroundColor: '#6366f1',\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t);\n}\n",
|
|
30
30
|
"export {\n\textractParamsFromPath,\n\tfindOGImageForPath,\n\tloadOGImageComponent,\n} from './discovery';\nexport { generateOGImageMetaTags } from './meta';\nexport { DefaultOGTemplate, renderOGImageToPNG } from './render';\nexport type { OGImageProps } from './types';\n",
|
|
31
31
|
"export * from './discovery';\nexport * from './generator';\nexport * from './policies';\n",
|
|
32
32
|
"export * from './discovery';\nexport * from './generator';\n",
|
|
33
33
|
"export * from './discovery';\nexport * from './generator';\n",
|
|
34
|
-
"import type { Span } from '@opentelemetry/api';\nimport { cloneElement, type ReactElement } from 'react';\nimport { renderToReadableStream } from 'react-dom/server';\nimport {\n\tgetTraceContextForInjection,\n\twithParentSpan,\n\twithSpan,\n} from 'reroute-js/telemetry/server';\nimport { loadConfig, type OGImageOptions } from '../config';\nimport {\n\tcreateDataScript,\n\tcreateFeedsScript,\n\tcreateLlmsScript,\n\ttype Doc,\n\tgenerateCollectionScripts,\n\tperformSSRSetup,\n} from './lib';\nimport { deduplicateMetaTags, loadIndexHtml } from './lib/html';\nimport { isThenable } from './lib/imports';\nimport { splitTemplate } from './lib/template';\n\ntype StreamingSSROptions = {\n\tpathname: string;\n\trootComponent: ReactElement;\n\tclientDir: string;\n\tcwd: string;\n\tisWatchMode: boolean;\n\tbundleUrl: string;\n\tcachedCollections?: Record<string, unknown[]>;\n\tcachedTailwindCSS?: string;\n\tcachedIndexHtml?: string;\n\tdebug?: boolean;\n\thead?: string;\n\tlang?: string;\n\tappId?: string;\n\tmaxAge?: number;\n\tsearchParams?: URLSearchParams;\n\togConfig?: OGImageOptions;\n\tbaseUrl?: string;\n\tautoCanonical?: boolean;\n\tparentSpan?: Span | null;\n};\n\ntype StreamingSSRResult = {\n\tstream: ReadableStream<Uint8Array>;\n\tstatus: number;\n};\n\n/**\n * Render a React component to a streaming HTML response.\n * Uses React 19's streaming with progressive Suspense resolution.\n */\nasync function renderSSRDocumentStream(\n\toptions: StreamingSSROptions,\n): Promise<StreamingSSRResult> {\n\tconst debug = options.debug ?? false;\n\tconst t0 = debug ? performance.now() : 0;\n\tconst {\n\t\tpathname,\n\t\trootComponent,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\tbundleUrl,\n\t\thead = '',\n\t\tlang = 'en',\n\t\tappId = 'root',\n\t\tmaxAge = 0,\n\t\tsearchParams,\n\t\togConfig,\n\t} = options;\n\n\tif (debug) console.log(`[renderStream] ${pathname} - start: 0ms`);\n\n\t// Perform shared SSR setup\n\tconst setup = await performSSRSetup(\n\t\t{\n\t\t\tpathname,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t\tparentSpan: options.parentSpan,\n\t\t\tbundleUrl,\n\t\t\tmaxAge,\n\t\t\tsearchParams,\n\t\t\togConfig,\n\t\t\tbaseUrl: options.baseUrl,\n\t\t\tautoCanonical: options.autoCanonical,\n\t\t\tcachedCollections: options.cachedCollections,\n\t\t\tcachedTailwindCSS: options.cachedTailwindCSS,\n\t\t\tdebug,\n\t\t},\n\t\ttrue, // streaming mode\n\t);\n\tif (debug)\n\t\tconsole.log(\n\t\t\t`[renderStream] ${pathname} - performSSRSetup: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t);\n\n\t// Determine status\n\tlet statusOverride = setup.preloadStatusOverride;\n\tif (setup.statusContainer.value) {\n\t\tstatusOverride = setup.statusContainer.value;\n\t}\n\tif (setup.metadataResult.statusOverride) {\n\t\tstatusOverride = setup.metadataResult.statusOverride;\n\t}\n\n\t// Set up streaming\n\tconst encoder = new TextEncoder();\n\tconst { readable, writable } = new TransformStream<Uint8Array>();\n\tconst writer = writable.getWriter();\n\n\t// Load and split template (use cached if available)\n\tconst usingCache = !!options.cachedIndexHtml;\n\tconst { htmlHead, rootStart, rootEnd, htmlTail } = await withSpan(\n\t\t'ssr.load.template',\n\t\tasync (span) => {\n\t\t\tconst template = options.cachedIndexHtml\n\t\t\t\t? options.cachedIndexHtml\n\t\t\t\t: await loadIndexHtml(clientDir);\n\n\t\t\tspan.setAttribute('reroute.cached', usingCache);\n\t\t\tspan.setAttribute('reroute.template.size', template.length);\n\n\t\t\tif (debug)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[renderStream] ${pathname} - loadIndexHtml (cached: ${usingCache}): ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t\t);\n\n\t\t\tconst parts = splitTemplate(template, appId);\n\n\t\t\tif (debug)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[renderStream] ${pathname} - splitTemplate: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t\t);\n\n\t\t\treturn {\n\t\t\t\t...parts,\n\t\t\t};\n\t\t},\n\t);\n\n\t// Build head with lang attribute\n\tconst pageLang = setup.metadataResult.pageLang || lang;\n\tlet headWithLang = htmlHead.replace(\n\t\t/<html([^>]*)>/i,\n\t\t`<html$1 lang=\"${pageLang}\">`,\n\t);\n\n\t// Build extra head content\n\tconst extraHead =\n\t\tsetup.bundlePreload +\n\t\tsetup.preloadExtraHead +\n\t\tsetup.metadataResult.perPageHead;\n\n\t// Remove default title/description from template if we have page-specific ones\n\tif (/<title[\\s\\S]*?<\\/title>/i.test(extraHead)) {\n\t\theadWithLang = headWithLang.replace(/<title[\\s\\S]*?<\\/title>/i, '');\n\t}\n\tif (/<meta\\s+name\\s*=\\s*['\"]description['\"][^>]*>/i.test(extraHead)) {\n\t\theadWithLang = headWithLang.replace(\n\t\t\t/<meta\\s+name\\s*=\\s*['\"]description['\"][^>]*>/i,\n\t\t\t'',\n\t\t);\n\t}\n\n\t// Load config to get browser telemetry settings\n\tconst config = await loadConfig(cwd);\n\tconst browserTelemetryConfigRaw = config.telemetry?.browser as\n\t\t| Record<string, unknown>\n\t\t| undefined;\n\n\t// Serialize browser telemetry config (convert functions to strings for JSON)\n\tconst { serializeBrowserTelemetryConfig } = await import('./lib/serialize');\n\tconst browserTelemetryConfig = serializeBrowserTelemetryConfig(\n\t\tbrowserTelemetryConfigRaw,\n\t);\n\n\t// Extract trace context from parent span for distributed tracing\n\tconst traceContext = getTraceContextForInjection(options.parentSpan);\n\n\t// Start streaming in background\n\tstreamSSRContent(writer, encoder, {\n\t\trootComponent,\n\t\tpathname,\n\t\tsearchParams,\n\t\theadWithLang,\n\t\thead,\n\t\textraHead,\n\t\tinlineStyleTag: setup.inlineStyleTag,\n\t\tpageLang,\n\t\trootStart,\n\t\trootEnd,\n\t\thtmlTail,\n\t\tbundleUrl,\n\t\tisWatchMode,\n\t\tdebug,\n\t\tssrData: setup.ssrData,\n\t\tssrError: setup.ssrError,\n\t\tbyCollectionForSSR: setup.byCollectionForSSR,\n\t\tpreloadHydrationScript: setup.preloadHydrationScript,\n\t\tbrowserTelemetryConfig,\n\t\ttraceContext,\n\t\tparentSpan: options.parentSpan,\n\t});\n\n\tif (debug)\n\t\tconsole.log(\n\t\t\t`[renderStream] ${pathname} - returning stream: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t);\n\treturn { stream: readable, status: statusOverride || 200 };\n}\n\ntype StreamContext = {\n\trootComponent: ReactElement;\n\tpathname: string;\n\tsearchParams?: URLSearchParams;\n\theadWithLang: string;\n\thead: string;\n\textraHead: string;\n\tinlineStyleTag: string;\n\tpageLang: string;\n\trootStart: string;\n\trootEnd: string;\n\thtmlTail: string;\n\tbundleUrl: string;\n\tisWatchMode: boolean;\n\tdebug: boolean;\n\tssrData: Record<string, unknown>;\n\tssrError?: string;\n\tbyCollectionForSSR: Record<string, unknown[]>;\n\tpreloadHydrationScript: string;\n\tbrowserTelemetryConfig?: Record<string, unknown>;\n\ttraceContext?: { traceparent?: string; tracestate?: string };\n\tparentSpan?: Span | null;\n};\n\n/**\n * Stream SSR content progressively\n * NOTE: This runs during the HTTP request lifecycle - Elysia waits for the stream\n * to complete before calling onAfterResponse\n */\nasync function streamSSRContent(\n\twriter: WritableStreamDefaultWriter<Uint8Array>,\n\tencoder: TextEncoder,\n\tctx: StreamContext,\n): Promise<void> {\n\t// Execute within parent span context to properly nest spans\n\treturn withParentSpan(ctx.parentSpan, async () => {\n\t\tconst t0 = ctx.debug ? performance.now() : 0;\n\t\t// Set a maximum streaming timeout to prevent server hangs\n\t\t// This ensures the stream always completes even if React is waiting for promises\n\t\tconst STREAM_TIMEOUT_MS = 60000; // 60 seconds max for entire streaming\n\t\tlet streamTimedOut = false;\n\t\tlet timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n\t\tconst cleanup = () => {\n\t\t\tif (timeoutId) {\n\t\t\t\tclearTimeout(timeoutId);\n\t\t\t\ttimeoutId = null;\n\t\t\t}\n\t\t};\n\n\t\ttry {\n\t\t\t// 1. Send HTML head immediately (shell)\n\t\t\tconst combinedHead = deduplicateMetaTags(\n\t\t\t\t[ctx.inlineStyleTag, ctx.head, ctx.extraHead]\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t.join('\\n'),\n\t\t\t);\n\t\t\t// Inject combined head BEFORE </head> (not after)\n\t\t\tconst headWithLangAndContent = ctx.headWithLang\n\t\t\t\t.replace(/<html([^>]*)>/i, `<html$1 lang=\"${ctx.pageLang}\">`)\n\t\t\t\t.replace(\n\t\t\t\t\t/<\\/head>/i,\n\t\t\t\t\t`${combinedHead ? `${combinedHead}\\n` : ''}</head>`,\n\t\t\t\t);\n\t\t\tconst headContent = `${headWithLangAndContent}<body>`;\n\t\t\tawait writer.write(encoder.encode(headContent));\n\t\t\tif (ctx.debug)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[Stream] ${ctx.pathname} - first byte written: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t\t);\n\n\t\t\t// 2. Send root div start\n\t\t\tawait writer.write(encoder.encode(ctx.rootStart));\n\n\t\t\t// 3. Stream React content (both create and pipe)\n\t\t\t// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Stream creation and piping requires timeout handling\n\t\t\tawait withSpan('ssr.document.stream', async (span) => {\n\t\t\t\tconst componentWithPathname = cloneElement(ctx.rootComponent, {\n\t\t\t\t\tpathname: ctx.pathname,\n\t\t\t\t\tsearchParams: ctx.searchParams,\n\t\t\t\t} as Doc);\n\n\t\t\t\tspan.setAttribute('reroute.pathname', ctx.pathname);\n\n\t\t\t\tlet streamError: Error | null = null;\n\t\t\t\tconst streamPromise = renderToReadableStream(componentWithPathname, {\n\t\t\t\t\tonError(error) {\n\t\t\t\t\t\tconsole.error('[reroute] SSR stream error:', error);\n\t\t\t\t\t\tstreamError =\n\t\t\t\t\t\t\terror instanceof Error ? error : new Error(String(error));\n\t\t\t\t\t},\n\t\t\t\t}).catch((err) => {\n\t\t\t\t\tstreamError = err;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\tconst reactStream = await streamPromise;\n\t\t\t\tif (streamError) throw streamError;\n\n\t\t\t\t// Pipe React stream to writer\n\t\t\t\t// Set up streaming timeout - if React takes too long, force close\n\t\t\t\tconst streamTimeoutPromise = new Promise<{\n\t\t\t\t\tdone: true;\n\t\t\t\t\tvalue: undefined;\n\t\t\t\t}>((resolve) => {\n\t\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`[reroute] Stream timeout after ${STREAM_TIMEOUT_MS}ms for ${ctx.pathname}, forcing close`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tstreamTimedOut = true;\n\t\t\t\t\t\tresolve({ done: true, value: undefined });\n\t\t\t\t\t}, STREAM_TIMEOUT_MS);\n\t\t\t\t});\n\n\t\t\t\tconst reader = reactStream.getReader();\n\t\t\t\tlet chunkCount = 0;\n\t\t\t\twhile (true) {\n\t\t\t\t\t// Race between getting next chunk and timeout\n\t\t\t\t\tconst result = await Promise.race([\n\t\t\t\t\t\treader.read(),\n\t\t\t\t\t\tstreamTimeoutPromise,\n\t\t\t\t\t]);\n\n\t\t\t\t\tif (result.done || streamTimedOut) {\n\t\t\t\t\t\t// Release the reader lock before breaking\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\treader.releaseLock();\n\t\t\t\t\t\t} catch {}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (result.value) {\n\t\t\t\t\t\tawait writer.write(result.value);\n\t\t\t\t\t\tchunkCount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcleanup();\n\n\t\t\t\tspan.setAttributes({\n\t\t\t\t\t'reroute.stream.chunks': chunkCount,\n\t\t\t\t\t'reroute.stream.timedOut': streamTimedOut,\n\t\t\t\t});\n\t\t\t});\n\n\t\t\t// 4. Close root div\n\t\t\tawait writer.write(encoder.encode(ctx.rootEnd));\n\n\t\t\t// 5. Generate scripts\n\t\t\tconst allScripts = await withSpan(\n\t\t\t\t'ssr.generate.scripts',\n\t\t\t\tasync (span) => {\n\t\t\t\t\tconst scripts = buildStreamingScripts(ctx);\n\t\t\t\t\tspan.setAttribute('reroute.script_size', scripts.length);\n\t\t\t\t\treturn scripts;\n\t\t\t\t},\n\t\t\t);\n\t\t\tawait writer.write(encoder.encode(allScripts + ctx.htmlTail));\n\t\t\tawait writer.close();\n\t\t} catch (error) {\n\t\t\tcleanup();\n\t\t\tconsole.error('[reroute] Stream error:', error);\n\t\t\ttry {\n\t\t\t\tawait writer.abort(error);\n\t\t\t} catch {\n\t\t\t\t// Writer might already be closed\n\t\t\t}\n\t\t}\n\t});\n}\n\n/**\n * Build all scripts for streaming SSR\n */\nfunction buildStreamingScripts(ctx: StreamContext): string {\n\t// Generate collection scripts\n\tconst collectionScripts = generateCollectionScripts(ctx.byCollectionForSSR);\n\n\t// Create snapshot of resolved SSR data\n\tconst ssrDataSnapshot: Record<string, unknown> = {};\n\tfor (const key of Object.keys(ctx.ssrData)) {\n\t\tconst value = ctx.ssrData[key];\n\t\tif (!isThenable(value)) {\n\t\t\tssrDataSnapshot[key] = value;\n\t\t}\n\t}\n\n\t// Build scripts\n\tconst dataScript = createDataScript(\n\t\tssrDataSnapshot,\n\t\tctx.isWatchMode ? ctx.ssrError : undefined,\n\t\tctx.pathname,\n\t\tctx.browserTelemetryConfig,\n\t\tctx.traceContext,\n\t);\n\tconst feedsScript = createFeedsScript();\n\tconst llmsScript = createLlmsScript();\n\n\tlet allScripts =\n\t\tdataScript +\n\t\tfeedsScript +\n\t\tllmsScript +\n\t\tcollectionScripts +\n\t\tctx.preloadHydrationScript;\n\n\t// Add bundle script\n\tallScripts += `<script type=\"module\" src=\"${ctx.bundleUrl}\"></script>`;\n\n\t// Add dev watcher\n\tif (ctx.isWatchMode) {\n\t\tallScripts += `<script type=\"module\" src=\"/__reroute_watch.js\"></script>`;\n\t}\n\n\treturn allScripts;\n}\n\nexport { renderSSRDocumentStream };\nexport type { StreamingSSROptions, StreamingSSRResult };\n",
|
|
34
|
+
"import type { Span } from '@opentelemetry/api';\nimport { cloneElement, type ReactElement } from 'react';\nimport { renderToReadableStream } from 'react-dom/server';\nimport {\n\tgetTraceContextForInjection,\n\twithParentSpan,\n\twithSpan,\n} from 'reroute-js/telemetry/server';\nimport { loadConfig, type OGImageOptions } from '../config';\nimport {\n\tcreateDataScript,\n\tcreateFeedsScript,\n\tcreateLlmsScript,\n\ttype Doc,\n\tgenerateCollectionScripts,\n\tperformSSRSetup,\n} from './lib';\nimport { deduplicateMetaTags, loadIndexHtml } from './lib/html';\nimport { isThenable } from './lib/imports';\nimport { splitTemplate } from './lib/template';\n\ntype StreamingSSROptions = {\n\tpathname: string;\n\trootComponent: ReactElement;\n\tclientDir: string;\n\tcwd: string;\n\tisWatchMode: boolean;\n\tbundleUrl: string;\n\tcachedCollections?: Record<string, unknown[]>;\n\tcachedTailwindCSS?: string;\n\tcachedIndexHtml?: string;\n\tdebug?: boolean;\n\thead?: string;\n\tlang?: string;\n\tappId?: string;\n\tmaxAge?: number;\n\tsearchParams?: URLSearchParams;\n\togConfig?: OGImageOptions;\n\tbaseUrl?: string;\n\tautoCanonical?: boolean;\n\tparentSpan?: Span | null;\n};\n\ntype StreamingSSRResult = {\n\tstream: ReadableStream<Uint8Array>;\n\tstatus: number;\n};\n\n/**\n * Render a React component to a streaming HTML response.\n * Uses React 19's streaming with progressive Suspense resolution.\n */\nasync function renderSSRDocumentStream(\n\toptions: StreamingSSROptions,\n): Promise<StreamingSSRResult> {\n\tconst debug = options.debug ?? false;\n\tconst t0 = debug ? performance.now() : 0;\n\tconst {\n\t\tpathname,\n\t\trootComponent,\n\t\tclientDir,\n\t\tcwd,\n\t\tisWatchMode,\n\t\tbundleUrl,\n\t\thead = '',\n\t\tlang = 'en',\n\t\tappId = 'root',\n\t\tmaxAge = 0,\n\t\tsearchParams,\n\t\togConfig,\n\t} = options;\n\n\tif (debug) console.log(`[renderStream] ${pathname} - start: 0ms`);\n\n\t// Perform shared SSR setup\n\tconst setup = await performSSRSetup(\n\t\t{\n\t\t\tpathname,\n\t\t\tclientDir,\n\t\t\tcwd,\n\t\t\tisWatchMode,\n\t\t\tparentSpan: options.parentSpan,\n\t\t\tbundleUrl,\n\t\t\tmaxAge,\n\t\t\tsearchParams,\n\t\t\togConfig,\n\t\t\tbaseUrl: options.baseUrl,\n\t\t\tautoCanonical: options.autoCanonical,\n\t\t\tcachedCollections: options.cachedCollections,\n\t\t\tcachedTailwindCSS: options.cachedTailwindCSS,\n\t\t\tdebug,\n\t\t},\n\t\ttrue, // streaming mode\n\t);\n\tif (debug)\n\t\tconsole.log(\n\t\t\t`[renderStream] ${pathname} - performSSRSetup: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t);\n\n\t// Determine status (only override if value is set)\n\tlet statusOverride = setup.preloadStatusOverride;\n\tif (setup.statusContainer.value !== undefined) {\n\t\tstatusOverride = setup.statusContainer.value;\n\t}\n\tif (setup.metadataResult.statusOverride !== undefined) {\n\t\tstatusOverride = setup.metadataResult.statusOverride;\n\t}\n\n\t// Set up streaming\n\tconst encoder = new TextEncoder();\n\tconst { readable, writable } = new TransformStream<Uint8Array>();\n\tconst writer = writable.getWriter();\n\n\t// Load and split template (use cached if available)\n\tconst usingCache = !!options.cachedIndexHtml;\n\tconst { htmlHead, rootStart, rootEnd, htmlTail } = await withSpan(\n\t\t'ssr.load.template',\n\t\tasync (span) => {\n\t\t\tconst template = options.cachedIndexHtml\n\t\t\t\t? options.cachedIndexHtml\n\t\t\t\t: await loadIndexHtml(clientDir);\n\n\t\t\tspan.setAttribute('reroute.cached', usingCache);\n\t\t\tspan.setAttribute('reroute.template.size', template.length);\n\n\t\t\tif (debug)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[renderStream] ${pathname} - loadIndexHtml (cached: ${usingCache}): ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t\t);\n\n\t\t\tconst parts = splitTemplate(template, appId);\n\n\t\t\tif (debug)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[renderStream] ${pathname} - splitTemplate: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t\t);\n\n\t\t\treturn {\n\t\t\t\t...parts,\n\t\t\t};\n\t\t},\n\t);\n\n\t// Build head with lang attribute\n\tconst pageLang = setup.metadataResult.pageLang || lang;\n\tlet headWithLang = htmlHead.replace(\n\t\t/<html([^>]*)>/i,\n\t\t`<html$1 lang=\"${pageLang}\">`,\n\t);\n\n\t// Build extra head content\n\tconst extraHead =\n\t\tsetup.bundlePreload +\n\t\tsetup.preloadExtraHead +\n\t\tsetup.metadataResult.perPageHead;\n\n\t// Remove default title/description from template if we have page-specific ones\n\tif (/<title[\\s\\S]*?<\\/title>/i.test(extraHead)) {\n\t\theadWithLang = headWithLang.replace(/<title[\\s\\S]*?<\\/title>/i, '');\n\t}\n\tif (/<meta\\s+name\\s*=\\s*['\"]description['\"][^>]*>/i.test(extraHead)) {\n\t\theadWithLang = headWithLang.replace(\n\t\t\t/<meta\\s+name\\s*=\\s*['\"]description['\"][^>]*>/i,\n\t\t\t'',\n\t\t);\n\t}\n\n\t// Load config to get browser telemetry settings\n\tconst config = await loadConfig(cwd);\n\tconst browserTelemetryConfigRaw = config.telemetry?.browser as\n\t\t| Record<string, unknown>\n\t\t| undefined;\n\n\t// Serialize browser telemetry config (convert functions to strings for JSON)\n\tconst { serializeBrowserTelemetryConfig } = await import('./lib/serialize');\n\tconst browserTelemetryConfig = serializeBrowserTelemetryConfig(\n\t\tbrowserTelemetryConfigRaw,\n\t);\n\n\t// Extract trace context from parent span for distributed tracing\n\tconst traceContext = getTraceContextForInjection(options.parentSpan);\n\n\t// Start streaming in background\n\tstreamSSRContent(writer, encoder, {\n\t\trootComponent,\n\t\tpathname,\n\t\tsearchParams,\n\t\theadWithLang,\n\t\thead,\n\t\textraHead,\n\t\tinlineStyleTag: setup.inlineStyleTag,\n\t\tpageLang,\n\t\trootStart,\n\t\trootEnd,\n\t\thtmlTail,\n\t\tbundleUrl,\n\t\tisWatchMode,\n\t\tdebug,\n\t\tssrData: setup.ssrData,\n\t\tssrError: setup.ssrError,\n\t\tbyCollectionForSSR: setup.byCollectionForSSR,\n\t\tpreloadHydrationScript: setup.preloadHydrationScript,\n\t\tbrowserTelemetryConfig,\n\t\ttraceContext,\n\t\tparentSpan: options.parentSpan,\n\t});\n\n\tif (debug)\n\t\tconsole.log(\n\t\t\t`[renderStream] ${pathname} - returning stream: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t);\n\treturn { stream: readable, status: statusOverride || 200 };\n}\n\ntype StreamContext = {\n\trootComponent: ReactElement;\n\tpathname: string;\n\tsearchParams?: URLSearchParams;\n\theadWithLang: string;\n\thead: string;\n\textraHead: string;\n\tinlineStyleTag: string;\n\tpageLang: string;\n\trootStart: string;\n\trootEnd: string;\n\thtmlTail: string;\n\tbundleUrl: string;\n\tisWatchMode: boolean;\n\tdebug: boolean;\n\tssrData: Record<string, unknown>;\n\tssrError?: string;\n\tbyCollectionForSSR: Record<string, unknown[]>;\n\tpreloadHydrationScript: string;\n\tbrowserTelemetryConfig?: Record<string, unknown>;\n\ttraceContext?: { traceparent?: string; tracestate?: string };\n\tparentSpan?: Span | null;\n};\n\n/**\n * Stream SSR content progressively\n * NOTE: This runs during the HTTP request lifecycle - Elysia waits for the stream\n * to complete before calling onAfterResponse\n */\nasync function streamSSRContent(\n\twriter: WritableStreamDefaultWriter<Uint8Array>,\n\tencoder: TextEncoder,\n\tctx: StreamContext,\n): Promise<void> {\n\t// Execute within parent span context to properly nest spans\n\treturn withParentSpan(ctx.parentSpan, async () => {\n\t\tconst t0 = ctx.debug ? performance.now() : 0;\n\t\t// Set a maximum streaming timeout to prevent server hangs\n\t\t// This ensures the stream always completes even if React is waiting for promises\n\t\tconst STREAM_TIMEOUT_MS = 60000; // 60 seconds max for entire streaming\n\t\tlet streamTimedOut = false;\n\t\tlet timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n\t\tconst cleanup = () => {\n\t\t\tif (timeoutId) {\n\t\t\t\tclearTimeout(timeoutId);\n\t\t\t\ttimeoutId = null;\n\t\t\t}\n\t\t};\n\n\t\ttry {\n\t\t\t// 1. Send HTML head immediately (shell)\n\t\t\tconst combinedHead = deduplicateMetaTags(\n\t\t\t\t[ctx.inlineStyleTag, ctx.head, ctx.extraHead]\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t.join('\\n'),\n\t\t\t);\n\t\t\t// Inject combined head BEFORE </head> (not after)\n\t\t\tconst headWithLangAndContent = ctx.headWithLang\n\t\t\t\t.replace(/<html([^>]*)>/i, `<html$1 lang=\"${ctx.pageLang}\">`)\n\t\t\t\t.replace(\n\t\t\t\t\t/<\\/head>/i,\n\t\t\t\t\t`${combinedHead ? `${combinedHead}\\n` : ''}</head>`,\n\t\t\t\t);\n\t\t\tconst headContent = `${headWithLangAndContent}<body>`;\n\t\t\tawait writer.write(encoder.encode(headContent));\n\t\t\tif (ctx.debug)\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[Stream] ${ctx.pathname} - first byte written: ${(performance.now() - t0).toFixed(2)}ms`,\n\t\t\t\t);\n\n\t\t\t// 2. Send root div start\n\t\t\tawait writer.write(encoder.encode(ctx.rootStart));\n\n\t\t\t// 3. Stream React content (both create and pipe)\n\t\t\t// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Stream creation and piping requires timeout handling\n\t\t\tawait withSpan('ssr.document.stream', async (span) => {\n\t\t\t\tconst componentWithPathname = cloneElement(ctx.rootComponent, {\n\t\t\t\t\tpathname: ctx.pathname,\n\t\t\t\t\tsearchParams: ctx.searchParams,\n\t\t\t\t} as Doc);\n\n\t\t\t\tspan.setAttribute('reroute.pathname', ctx.pathname);\n\n\t\t\t\tlet streamError: Error | null = null;\n\t\t\t\tconst streamPromise = renderToReadableStream(componentWithPathname, {\n\t\t\t\t\tonError(error) {\n\t\t\t\t\t\tconsole.error('[reroute] SSR stream error:', error);\n\t\t\t\t\t\tstreamError =\n\t\t\t\t\t\t\terror instanceof Error ? error : new Error(String(error));\n\t\t\t\t\t},\n\t\t\t\t}).catch((err) => {\n\t\t\t\t\tstreamError = err;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\tconst reactStream = await streamPromise;\n\t\t\t\tif (streamError) throw streamError;\n\n\t\t\t\t// Pipe React stream to writer\n\t\t\t\t// Set up streaming timeout - if React takes too long, force close\n\t\t\t\tconst streamTimeoutPromise = new Promise<{\n\t\t\t\t\tdone: true;\n\t\t\t\t\tvalue: undefined;\n\t\t\t\t}>((resolve) => {\n\t\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`[reroute] Stream timeout after ${STREAM_TIMEOUT_MS}ms for ${ctx.pathname}, forcing close`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tstreamTimedOut = true;\n\t\t\t\t\t\tresolve({ done: true, value: undefined });\n\t\t\t\t\t}, STREAM_TIMEOUT_MS);\n\t\t\t\t});\n\n\t\t\t\tconst reader = reactStream.getReader();\n\t\t\t\tlet chunkCount = 0;\n\t\t\t\twhile (true) {\n\t\t\t\t\t// Race between getting next chunk and timeout\n\t\t\t\t\tconst result = await Promise.race([\n\t\t\t\t\t\treader.read(),\n\t\t\t\t\t\tstreamTimeoutPromise,\n\t\t\t\t\t]);\n\n\t\t\t\t\tif (result.done || streamTimedOut) {\n\t\t\t\t\t\t// Release the reader lock before breaking\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\treader.releaseLock();\n\t\t\t\t\t\t} catch {}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (result.value) {\n\t\t\t\t\t\tawait writer.write(result.value);\n\t\t\t\t\t\tchunkCount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcleanup();\n\n\t\t\t\tspan.setAttributes({\n\t\t\t\t\t'reroute.stream.chunks': chunkCount,\n\t\t\t\t\t'reroute.stream.timedOut': streamTimedOut,\n\t\t\t\t});\n\t\t\t});\n\n\t\t\t// 4. Close root div\n\t\t\tawait writer.write(encoder.encode(ctx.rootEnd));\n\n\t\t\t// 5. Generate scripts\n\t\t\tconst allScripts = await withSpan(\n\t\t\t\t'ssr.generate.scripts',\n\t\t\t\tasync (span) => {\n\t\t\t\t\tconst scripts = buildStreamingScripts(ctx);\n\t\t\t\t\tspan.setAttribute('reroute.script_size', scripts.length);\n\t\t\t\t\treturn scripts;\n\t\t\t\t},\n\t\t\t);\n\t\t\tawait writer.write(encoder.encode(allScripts + ctx.htmlTail));\n\t\t\tawait writer.close();\n\t\t} catch (error) {\n\t\t\tcleanup();\n\t\t\tconsole.error('[reroute] Stream error:', error);\n\t\t\ttry {\n\t\t\t\tawait writer.abort(error);\n\t\t\t} catch {\n\t\t\t\t// Writer might already be closed\n\t\t\t}\n\t\t}\n\t});\n}\n\n/**\n * Build all scripts for streaming SSR\n */\nfunction buildStreamingScripts(ctx: StreamContext): string {\n\t// Generate collection scripts\n\tconst collectionScripts = generateCollectionScripts(ctx.byCollectionForSSR);\n\n\t// Create snapshot of resolved SSR data\n\tconst ssrDataSnapshot: Record<string, unknown> = {};\n\tfor (const key of Object.keys(ctx.ssrData)) {\n\t\tconst value = ctx.ssrData[key];\n\t\tif (!isThenable(value)) {\n\t\t\tssrDataSnapshot[key] = value;\n\t\t}\n\t}\n\n\t// Build scripts\n\tconst dataScript = createDataScript(\n\t\tssrDataSnapshot,\n\t\tctx.isWatchMode ? ctx.ssrError : undefined,\n\t\tctx.pathname,\n\t\tctx.browserTelemetryConfig,\n\t\tctx.traceContext,\n\t);\n\tconst feedsScript = createFeedsScript();\n\tconst llmsScript = createLlmsScript();\n\n\tlet allScripts =\n\t\tdataScript +\n\t\tfeedsScript +\n\t\tllmsScript +\n\t\tcollectionScripts +\n\t\tctx.preloadHydrationScript;\n\n\t// Add bundle script\n\tallScripts += `<script type=\"module\" src=\"${ctx.bundleUrl}\"></script>`;\n\n\t// Add dev watcher\n\tif (ctx.isWatchMode) {\n\t\tallScripts += `<script type=\"module\" src=\"/__reroute_watch.js\"></script>`;\n\t}\n\n\treturn allScripts;\n}\n\nexport { renderSSRDocumentStream };\nexport type { StreamingSSROptions, StreamingSSRResult };\n",
|
|
35
35
|
"export * from './lib';\nexport * from './render';\nexport * from './stream';\n",
|
|
36
36
|
"export * from './bundler';\nexport * from './config';\nexport * from './content';\nexport * from './llms';\nexport * from './og';\nexport * from './robots';\nexport * from './rss';\nexport * from './sitemap';\nexport * from './ssr';\n",
|
|
37
37
|
"export * from './src';\n",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"export * from './context';\nexport * from './instrumentation';\nexport * from './plugin';\nexport * from './sourcemap';\n",
|
|
41
41
|
"export * from './src/server';\n"
|
|
42
42
|
],
|
|
43
|
-
"mappings": "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",
|
|
44
|
-
"debugId": "
|
|
43
|
+
"mappings": "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",
|
|
44
|
+
"debugId": "AAB2C123ADAECFA964756E2164756E21",
|
|
45
45
|
"names": []
|
|
46
46
|
}
|