import { type EntryData, getContext } from "../server/context"; import { serializeManifest, type SerializedManifest } from "../debug.js"; import { createRouteHelpers } from "../route-definition.js"; import MapRootLayout from "../server/root-layout.js"; import type { RouteEntry, TrailingSlashMode } from "../types"; /** * Build a serialized manifest from all route entries for debug inspection. * Used by the `debugManifest()` method on the router instance. */ export async function buildDebugManifest( routesEntries: RouteEntry[], ): Promise { const manifest = new Map(); for (const entry of routesEntries) { const Store = { manifest, namespace: `debug.M${entry.mountIndex}`, parent: null as EntryData | null, counters: {} as Record, mountIndex: entry.mountIndex, patterns: new Map(), trailingSlash: new Map(), }; await getContext().runWithStore( Store, `debug.M${entry.mountIndex}`, null, async () => { const helpers = createRouteHelpers(); // Wrap handler execution in root layout (same as loadManifest) let promiseResult: Promise | null = null; helpers.layout(MapRootLayout, () => { const result = entry.handler(); if (result instanceof Promise) { promiseResult = result; return []; } return result; }); if (promiseResult !== null) { const load = await (promiseResult as Promise); if (load && typeof load === "object" && "default" in load) { // Promise<{ default: fn }> — e.g. dynamic import if (typeof load.default !== "function") { throw new Error( `[@rangojs/router] Unsupported async handler: { default } must be a function, ` + `got ${typeof load.default}. Use () => import('./urls') for lazy loading.`, ); } load.default(helpers); } else if (typeof load === "function") { // Promise load(helpers); } else { // Reject unsupported async handler results (same policy as manifest.ts) throw new Error( `[@rangojs/router] Unsupported async handler result (${typeof load}). ` + `Lazy route handlers must resolve to a function or { default: fn }.`, ); } } }, ); } return serializeManifest(manifest); }