vinext 0.0.21 → 0.0.23
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/dist/build/static-export.d.ts.map +1 -1
- package/dist/build/static-export.js +9 -7
- package/dist/build/static-export.js.map +1 -1
- package/dist/config/next-config.d.ts +4 -1
- package/dist/config/next-config.d.ts.map +1 -1
- package/dist/config/next-config.js +10 -5
- package/dist/config/next-config.js.map +1 -1
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +17 -4
- package/dist/deploy.js.map +1 -1
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +381 -38
- package/dist/index.js.map +1 -1
- package/dist/routing/app-router.d.ts +2 -1
- package/dist/routing/app-router.d.ts.map +1 -1
- package/dist/routing/app-router.js +74 -107
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/file-matcher.d.ts +24 -0
- package/dist/routing/file-matcher.d.ts.map +1 -0
- package/dist/routing/file-matcher.js +75 -0
- package/dist/routing/file-matcher.js.map +1 -0
- package/dist/routing/pages-router.d.ts +3 -2
- package/dist/routing/pages-router.d.ts.map +1 -1
- package/dist/routing/pages-router.js +25 -44
- package/dist/routing/pages-router.js.map +1 -1
- package/dist/routing/utils.d.ts +25 -0
- package/dist/routing/utils.d.ts.map +1 -0
- package/dist/routing/utils.js +70 -0
- package/dist/routing/utils.js.map +1 -0
- package/dist/server/app-dev-server.d.ts.map +1 -1
- package/dist/server/app-dev-server.js +123 -47
- package/dist/server/app-dev-server.js.map +1 -1
- package/dist/server/dev-server.d.ts +2 -1
- package/dist/server/dev-server.d.ts.map +1 -1
- package/dist/server/dev-server.js +93 -18
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/prod-server.d.ts.map +1 -1
- package/dist/server/prod-server.js +33 -2
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-log.d.ts +34 -0
- package/dist/server/request-log.d.ts.map +1 -0
- package/dist/server/request-log.js +65 -0
- package/dist/server/request-log.js.map +1 -0
- package/dist/shims/cache-runtime.d.ts.map +1 -1
- package/dist/shims/cache-runtime.js +5 -1
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.d.ts +7 -1
- package/dist/shims/cache.d.ts.map +1 -1
- package/dist/shims/cache.js +30 -5
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/head.d.ts +11 -0
- package/dist/shims/head.d.ts.map +1 -1
- package/dist/shims/head.js +21 -0
- package/dist/shims/head.js.map +1 -1
- package/dist/shims/headers.d.ts +8 -0
- package/dist/shims/headers.d.ts.map +1 -1
- package/dist/shims/headers.js +41 -0
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/metadata.d.ts +1 -0
- package/dist/shims/metadata.d.ts.map +1 -1
- package/dist/shims/metadata.js +5 -1
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/script.d.ts.map +1 -1
- package/dist/shims/script.js +7 -1
- package/dist/shims/script.js.map +1 -1
- package/dist/shims/server.d.ts.map +1 -1
- package/dist/shims/server.js +2 -1
- package/dist/shims/server.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-dev-server.js","sourceRoot":"","sources":["../../src/server/app-dev-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * App Router dev server handler.\n *\n * This module generates virtual entry points for the RSC/SSR/browser\n * environments that @vitejs/plugin-rsc manages. The RSC entry does\n * route matching and renders the component tree, then delegates to\n * the SSR entry for HTML generation.\n */\nimport fs from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport type { AppRoute } from \"../routing/app-router.js\";\nimport type { MetadataFileRoute } from \"./metadata-routes.js\";\nimport type { NextRedirect, NextRewrite, NextHeader } from \"../config/next-config.js\";\nimport { generateDevOriginCheckCode } from \"./dev-origin-check.js\";\nimport { generateSafeRegExpCode, generateMiddlewareMatcherCode, generateNormalizePathCode } from \"./middleware-codegen.js\";\nimport { isProxyFile } from \"./middleware.js\";\n\n/**\n * Resolved config options relevant to App Router request handling.\n * Passed from the Vite plugin where the full next.config.js is loaded.\n */\nexport interface AppRouterConfig {\n redirects?: NextRedirect[];\n rewrites?: {\n beforeFiles: NextRewrite[];\n afterFiles: NextRewrite[];\n fallback: NextRewrite[];\n };\n headers?: NextHeader[];\n /** Extra origins allowed for server action CSRF checks (from experimental.serverActions.allowedOrigins). */\n allowedOrigins?: string[];\n /** Extra origins allowed for dev server access (from serverActionsAllowedOrigins or custom config). */\n allowedDevOrigins?: string[];\n}\n\n/**\n * Generate the virtual RSC entry module.\n *\n * This runs in the `rsc` Vite environment (react-server condition).\n * It matches the incoming request URL to an app route, builds the\n * nested layout + page tree, and renders it to an RSC stream.\n */\nexport function generateRscEntry(\n appDir: string,\n routes: AppRoute[],\n middlewarePath?: string | null,\n metadataRoutes?: MetadataFileRoute[],\n globalErrorPath?: string | null,\n basePath?: string,\n trailingSlash?: boolean,\n config?: AppRouterConfig,\n): string {\n const bp = basePath ?? \"\";\n const ts = trailingSlash ?? false;\n const redirects = config?.redirects ?? [];\n const rewrites = config?.rewrites ?? { beforeFiles: [], afterFiles: [], fallback: [] };\n const headers = config?.headers ?? [];\n const allowedOrigins = config?.allowedOrigins ?? [];\n // Build import map for all page and layout files\n const imports: string[] = [];\n const importMap: Map<string, string> = new Map();\n let importIdx = 0;\n\n function getImportVar(filePath: string): string {\n if (importMap.has(filePath)) return importMap.get(filePath)!;\n const varName = `mod_${importIdx++}`;\n const absPath = filePath.replace(/\\\\/g, \"/\");\n imports.push(`import * as ${varName} from ${JSON.stringify(absPath)};`);\n importMap.set(filePath, varName);\n return varName;\n }\n\n // Pre-register all modules\n for (const route of routes) {\n if (route.pagePath) getImportVar(route.pagePath);\n if (route.routePath) getImportVar(route.routePath);\n for (const layout of route.layouts) getImportVar(layout);\n for (const tmpl of route.templates) getImportVar(tmpl);\n if (route.loadingPath) getImportVar(route.loadingPath);\n if (route.errorPath) getImportVar(route.errorPath);\n if (route.layoutErrorPaths) for (const ep of route.layoutErrorPaths) { if (ep) getImportVar(ep); }\n if (route.notFoundPath) getImportVar(route.notFoundPath);\n for (const nfp of route.notFoundPaths || []) { if (nfp) getImportVar(nfp); }\n if (route.forbiddenPath) getImportVar(route.forbiddenPath);\n if (route.unauthorizedPath) getImportVar(route.unauthorizedPath);\n // Register parallel slot modules\n for (const slot of route.parallelSlots) {\n if (slot.pagePath) getImportVar(slot.pagePath);\n if (slot.defaultPath) getImportVar(slot.defaultPath);\n if (slot.layoutPath) getImportVar(slot.layoutPath);\n if (slot.loadingPath) getImportVar(slot.loadingPath);\n if (slot.errorPath) getImportVar(slot.errorPath);\n // Register intercepting route page modules\n for (const ir of slot.interceptingRoutes) {\n getImportVar(ir.pagePath);\n }\n }\n }\n\n // Build route table as serialized JS\n const routeEntries = routes.map((route) => {\n const layoutVars = route.layouts.map((l) => getImportVar(l));\n const templateVars = route.templates.map((t) => getImportVar(t));\n const notFoundVars = (route.notFoundPaths || []).map((nf) => nf ? getImportVar(nf) : \"null\");\n const slotEntries = route.parallelSlots.map((slot) => {\n const interceptEntries = slot.interceptingRoutes.map((ir) => {\n return ` {\n convention: ${JSON.stringify(ir.convention)},\n targetPattern: ${JSON.stringify(ir.targetPattern)},\n page: ${getImportVar(ir.pagePath)},\n params: ${JSON.stringify(ir.params)},\n }`;\n });\n return ` ${JSON.stringify(slot.name)}: {\n page: ${slot.pagePath ? getImportVar(slot.pagePath) : \"null\"},\n default: ${slot.defaultPath ? getImportVar(slot.defaultPath) : \"null\"},\n layout: ${slot.layoutPath ? getImportVar(slot.layoutPath) : \"null\"},\n loading: ${slot.loadingPath ? getImportVar(slot.loadingPath) : \"null\"},\n error: ${slot.errorPath ? getImportVar(slot.errorPath) : \"null\"},\n layoutIndex: ${slot.layoutIndex},\n intercepts: [\n${interceptEntries.join(\",\\n\")}\n ],\n }`;\n });\n const layoutErrorVars = (route.layoutErrorPaths || []).map((ep) => ep ? getImportVar(ep) : \"null\");\n return ` {\n pattern: ${JSON.stringify(route.pattern)},\n isDynamic: ${route.isDynamic},\n params: ${JSON.stringify(route.params)},\n page: ${route.pagePath ? getImportVar(route.pagePath) : \"null\"},\n routeHandler: ${route.routePath ? getImportVar(route.routePath) : \"null\"},\n layouts: [${layoutVars.join(\", \")}],\n layoutSegmentDepths: ${JSON.stringify(route.layoutSegmentDepths)},\n templates: [${templateVars.join(\", \")}],\n errors: [${layoutErrorVars.join(\", \")}],\n slots: {\n${slotEntries.join(\",\\n\")}\n },\n loading: ${route.loadingPath ? getImportVar(route.loadingPath) : \"null\"},\n error: ${route.errorPath ? getImportVar(route.errorPath) : \"null\"},\n notFound: ${route.notFoundPath ? getImportVar(route.notFoundPath) : \"null\"},\n notFounds: [${notFoundVars.join(\", \")}],\n forbidden: ${route.forbiddenPath ? getImportVar(route.forbiddenPath) : \"null\"},\n unauthorized: ${route.unauthorizedPath ? getImportVar(route.unauthorizedPath) : \"null\"},\n }`;\n });\n\n // Find root not-found/forbidden/unauthorized pages and root layouts for global error handling\n const rootRoute = routes.find((r) => r.pattern === \"/\");\n const rootNotFoundVar = rootRoute?.notFoundPath\n ? getImportVar(rootRoute.notFoundPath)\n : null;\n const rootForbiddenVar = rootRoute?.forbiddenPath\n ? getImportVar(rootRoute.forbiddenPath)\n : null;\n const rootUnauthorizedVar = rootRoute?.unauthorizedPath\n ? getImportVar(rootRoute.unauthorizedPath)\n : null;\n const rootLayoutVars = rootRoute\n ? rootRoute.layouts.map((l) => getImportVar(l))\n : [];\n\n // Global error boundary (app/global-error.tsx)\n const globalErrorVar = globalErrorPath ? getImportVar(globalErrorPath) : null;\n\n // Build metadata route handling\n const effectiveMetaRoutes = metadataRoutes ?? [];\n const dynamicMetaRoutes = effectiveMetaRoutes.filter((r) => r.isDynamic);\n\n // Import dynamic metadata modules\n for (const mr of dynamicMetaRoutes) {\n getImportVar(mr.filePath);\n }\n\n // Build metadata route table\n // For static metadata files, read the file content at code-generation time\n // and embed it as base64. This ensures static metadata files work on runtimes\n // without filesystem access (e.g., Cloudflare Workers).\n const metaRouteEntries = effectiveMetaRoutes.map((mr) => {\n if (mr.isDynamic) {\n return ` {\n type: ${JSON.stringify(mr.type)},\n isDynamic: true,\n servedUrl: ${JSON.stringify(mr.servedUrl)},\n contentType: ${JSON.stringify(mr.contentType)},\n module: ${getImportVar(mr.filePath)},\n }`;\n }\n // Static: read file and embed as base64\n let fileDataBase64 = \"\";\n try {\n const buf = fs.readFileSync(mr.filePath);\n fileDataBase64 = buf.toString(\"base64\");\n } catch {\n // File unreadable — will serve empty response at runtime\n }\n return ` {\n type: ${JSON.stringify(mr.type)},\n isDynamic: false,\n servedUrl: ${JSON.stringify(mr.servedUrl)},\n contentType: ${JSON.stringify(mr.contentType)},\n fileDataBase64: ${JSON.stringify(fileDataBase64)},\n }`;\n });\n\n return `\nimport {\n renderToReadableStream,\n decodeReply,\n loadServerAction,\n createTemporaryReferenceSet,\n} from \"@vitejs/plugin-rsc/rsc\";\nimport { createElement, Suspense, Fragment } from \"react\";\nimport { setNavigationContext as _setNavigationContextOrig, getNavigationContext as _getNavigationContext } from \"next/navigation\";\nimport { setHeadersContext, headersContextFromRequest, getDraftModeCookieHeader, getAndClearPendingCookies, consumeDynamicUsage, markDynamicUsage, runWithHeadersContext, applyMiddlewareRequestHeaders } from \"next/headers\";\nimport { NextRequest } from \"next/server\";\nimport { ErrorBoundary, NotFoundBoundary } from \"vinext/error-boundary\";\nimport { LayoutSegmentProvider } from \"vinext/layout-segment-context\";\nimport { MetadataHead, mergeMetadata, resolveModuleMetadata, ViewportHead, mergeViewport, resolveModuleViewport } from \"vinext/metadata\";\n${middlewarePath ? `import * as middlewareModule from ${JSON.stringify(middlewarePath.replace(/\\\\/g, \"/\"))};` : \"\"}\n${effectiveMetaRoutes.length > 0 ? `import { sitemapToXml, robotsToText, manifestToJson } from ${JSON.stringify(fileURLToPath(new URL(\"./metadata-routes.js\", import.meta.url)).replace(/\\\\/g, \"/\"))};` : \"\"}\nimport { _consumeRequestScopedCacheLife, _runWithCacheState } from \"next/cache\";\nimport { runWithFetchCache } from \"vinext/fetch-cache\";\nimport { runWithPrivateCache as _runWithPrivateCache } from \"vinext/cache-runtime\";\n// Import server-only state module to register ALS-backed accessors.\nimport { runWithNavigationContext as _runWithNavigationContext } from \"vinext/navigation-state\";\nimport { reportRequestError as _reportRequestError } from \"vinext/instrumentation\";\nimport { getSSRFontLinks as _getSSRFontLinks, getSSRFontStyles as _getSSRFontStylesGoogle, getSSRFontPreloads as _getSSRFontPreloadsGoogle } from \"next/font/google\";\nimport { getSSRFontStyles as _getSSRFontStylesLocal, getSSRFontPreloads as _getSSRFontPreloadsLocal } from \"next/font/local\";\nfunction _getSSRFontStyles() { return [..._getSSRFontStylesGoogle(), ..._getSSRFontStylesLocal()]; }\nfunction _getSSRFontPreloads() { return [..._getSSRFontPreloadsGoogle(), ..._getSSRFontPreloadsLocal()]; }\n\n// Set navigation context in the ALS-backed store. \"use client\" components\n// rendered during SSR need the pathname/searchParams/params but the SSR\n// environment has a separate module instance of next/navigation.\n// Use _getNavigationContext() to read the current context — never cache\n// it in a module-level variable (that would leak between concurrent requests).\nfunction setNavigationContext(ctx) {\n _setNavigationContextOrig(ctx);\n}\n\n// ISR cache is disabled in dev mode — every request re-renders fresh,\n// matching Next.js dev behavior. Cache-Control headers are still emitted\n// based on export const revalidate for testing purposes.\n// Production ISR is handled by prod-server.ts and the Cloudflare worker entry.\n\n// Normalize null-prototype objects from matchPattern() into thenable objects\n// that work both as Promises (for Next.js 15+ async params) and as plain\n// objects with synchronous property access (for pre-15 code like params.id).\n//\n// matchPattern() uses Object.create(null), producing objects without\n// Object.prototype. The RSC serializer rejects these. Spreading ({...obj})\n// restores a normal prototype. Object.assign onto the Promise preserves\n// synchronous property access (params.id, params.slug) that existing\n// components and test fixtures rely on.\nfunction makeThenableParams(obj) {\n const plain = { ...obj };\n return Object.assign(Promise.resolve(plain), plain);\n}\n\n// djb2 hash — matches Next.js's stringHash for digest generation.\n// Produces a stable numeric string from error message + stack.\nfunction __errorDigest(str) {\n let hash = 5381;\n for (let i = str.length - 1; i >= 0; i--) {\n hash = (hash * 33) ^ str.charCodeAt(i);\n }\n return (hash >>> 0).toString();\n}\n\n// Sanitize an error for client consumption. In production, replaces the error\n// with a generic Error that only carries a digest hash (matching Next.js\n// behavior). In development, returns the original error for debugging.\n// Navigation errors (redirect, notFound, etc.) are always passed through\n// unchanged since their digests are used for client-side routing.\nfunction __sanitizeErrorForClient(error) {\n // Navigation errors must pass through with their digest intact\n if (error && typeof error === \"object\" && \"digest\" in error) {\n const digest = String(error.digest);\n if (\n digest.startsWith(\"NEXT_REDIRECT;\") ||\n digest === \"NEXT_NOT_FOUND\" ||\n digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")\n ) {\n return error;\n }\n }\n // In development, pass through the original error for debugging\n if (process.env.NODE_ENV !== \"production\") {\n return error;\n }\n // In production, create a sanitized error with only a digest hash\n const msg = error instanceof Error ? error.message : String(error);\n const stack = error instanceof Error ? (error.stack || \"\") : \"\";\n const sanitized = new Error(\n \"An error occurred in the Server Components render. \" +\n \"The specific message is omitted in production builds to avoid leaking sensitive details. \" +\n \"A digest property is included on this error instance which may provide additional details about the nature of the error.\"\n );\n sanitized.digest = __errorDigest(msg + stack);\n return sanitized;\n}\n\n// onError callback for renderToReadableStream — preserves the digest for\n// Next.js navigation errors (redirect, notFound, forbidden, unauthorized)\n// thrown during RSC streaming (e.g. inside Suspense boundaries).\n// For non-navigation errors in production, generates a digest hash so the\n// error can be correlated with server logs without leaking details.\nfunction rscOnError(error) {\n if (error && typeof error === \"object\" && \"digest\" in error) {\n return String(error.digest);\n }\n\n // In dev, detect the \"Only plain objects\" RSC serialization error and emit\n // an actionable hint. This error occurs when a Server Component passes a\n // class instance, ES module namespace object, or null-prototype object as a\n // prop to a Client Component.\n //\n // Root cause: Vite bundles modules as true ESM (module namespace objects\n // have a null-like internal slot), while Next.js's webpack build produces\n // plain CJS-wrapped objects with __esModule:true. React's RSC serializer\n // accepts the latter as plain objects but rejects the former — which means\n // code that accidentally passes \"import * as X\" works in webpack/Next.js\n // but correctly fails in vinext.\n //\n // Common triggers:\n // - \"import * as utils from './utils'\" passed as a prop\n // - class instances (new Foo()) passed as props\n // - Date / Map / Set instances passed as props\n // - Objects with Object.create(null) (null prototype)\n if (\n process.env.NODE_ENV !== \"production\" &&\n error instanceof Error &&\n error.message.includes(\"Only plain objects, and a few built-ins, can be passed to Client Components\")\n ) {\n console.error(\n \"[vinext] RSC serialization error: a non-plain object was passed from a Server Component to a Client Component.\\\\n\" +\n \"\\\\n\" +\n \"Common causes:\\\\n\" +\n \" * Passing a module namespace (import * as X) directly as a prop.\\\\n\" +\n \" Unlike Next.js (webpack), Vite produces real ESM module namespace objects\\\\n\" +\n \" which are not serializable. Fix: pass individual values instead,\\\\n\" +\n \" e.g. <Comp value={module.value} />\\\\n\" +\n \" * Passing a class instance (new Foo()) as a prop.\\\\n\" +\n \" Fix: convert to a plain object, e.g. { id: foo.id, name: foo.name }\\\\n\" +\n \" * Passing a Date, Map, or Set. Use .toISOString(), [...map.entries()], etc.\\\\n\" +\n \" * Passing Object.create(null). Use { ...obj } to restore a prototype.\\\\n\" +\n \"\\\\n\" +\n \"Original error:\",\n error.message,\n );\n return undefined;\n }\n\n // In production, generate a digest hash for non-navigation errors\n if (process.env.NODE_ENV === \"production\" && error) {\n const msg = error instanceof Error ? error.message : String(error);\n const stack = error instanceof Error ? (error.stack || \"\") : \"\";\n return __errorDigest(msg + stack);\n }\n return undefined;\n}\n\n${imports.join(\"\\n\")}\n\nconst routes = [\n${routeEntries.join(\",\\n\")}\n];\n\nconst metadataRoutes = [\n${metaRouteEntries.join(\",\\n\")}\n];\n\nconst rootNotFoundModule = ${rootNotFoundVar ? rootNotFoundVar : \"null\"};\nconst rootForbiddenModule = ${rootForbiddenVar ? rootForbiddenVar : \"null\"};\nconst rootUnauthorizedModule = ${rootUnauthorizedVar ? rootUnauthorizedVar : \"null\"};\nconst rootLayouts = [${rootLayoutVars.join(\", \")}];\n\n/**\n * Render an HTTP access fallback page (not-found/forbidden/unauthorized) with layouts and noindex meta.\n * Returns null if no matching component is available.\n *\n * @param opts.boundaryComponent - Override the boundary component (for layout-level notFound)\n * @param opts.layouts - Override the layouts to wrap with (for layout-level notFound, excludes the throwing layout)\n */\nasync function renderHTTPAccessFallbackPage(route, statusCode, isRscRequest, request, opts) {\n // Determine which boundary component to use based on status code\n let BoundaryComponent = opts?.boundaryComponent ?? null;\n if (!BoundaryComponent) {\n let boundaryModule;\n if (statusCode === 403) {\n boundaryModule = route?.forbidden ?? rootForbiddenModule;\n } else if (statusCode === 401) {\n boundaryModule = route?.unauthorized ?? rootUnauthorizedModule;\n } else {\n boundaryModule = route?.notFound ?? rootNotFoundModule;\n }\n BoundaryComponent = boundaryModule?.default ?? null;\n }\n const layouts = opts?.layouts ?? route?.layouts ?? rootLayouts;\n if (!BoundaryComponent) return null;\n\n // Resolve metadata and viewport from parent layouts so that not-found/error\n // pages inherit title, description, OG tags etc. — matching Next.js behavior.\n const metadataList = [];\n const viewportList = [];\n for (const layoutMod of layouts) {\n if (layoutMod) {\n const meta = await resolveModuleMetadata(layoutMod);\n if (meta) metadataList.push(meta);\n const vp = await resolveModuleViewport(layoutMod);\n if (vp) viewportList.push(vp);\n }\n }\n const resolvedMetadata = metadataList.length > 0 ? mergeMetadata(metadataList) : null;\n const resolvedViewport = viewportList.length > 0 ? mergeViewport(viewportList) : null;\n\n // Build element: metadata head + noindex meta + boundary component wrapped in layouts\n // Always include charset and default viewport for parity with Next.js.\n const charsetMeta = createElement(\"meta\", { charSet: \"utf-8\" });\n const noindexMeta = createElement(\"meta\", { name: \"robots\", content: \"noindex\" });\n const headElements = [charsetMeta, noindexMeta];\n if (resolvedMetadata) headElements.push(createElement(MetadataHead, { metadata: resolvedMetadata }));\n const effectiveViewport = resolvedViewport ?? { width: \"device-width\", initialScale: 1 };\n headElements.push(createElement(ViewportHead, { viewport: effectiveViewport }));\n let element = createElement(Fragment, null, ...headElements, createElement(BoundaryComponent));\n if (isRscRequest) {\n // For RSC requests (client-side navigation), wrap the element with the same\n // component wrappers that buildPageElement() uses. Without these wrappers,\n // React's reconciliation would see a mismatched tree structure between the\n // old fiber tree (ErrorBoundary > LayoutSegmentProvider > html > body > NotFoundBoundary > ...)\n // and the new tree (html > body > ...), causing it to destroy and recreate\n // the entire DOM tree, resulting in a blank white page.\n //\n // We wrap each layout with LayoutSegmentProvider and add GlobalErrorBoundary\n // to match the wrapping order in buildPageElement(), ensuring smooth\n // client-side tree reconciliation.\n const layoutDepths = route?.layoutSegmentDepths;\n for (let i = layouts.length - 1; i >= 0; i--) {\n const LayoutComponent = layouts[i]?.default;\n if (LayoutComponent) {\n element = createElement(LayoutComponent, { children: element });\n const layoutDepth = layoutDepths ? layoutDepths[i] : 0;\n element = createElement(LayoutSegmentProvider, { depth: layoutDepth }, element);\n }\n }\n ${globalErrorVar ? `\n const _GlobalErrorComponent = ${globalErrorVar}.default;\n if (_GlobalErrorComponent) {\n element = createElement(ErrorBoundary, {\n fallback: _GlobalErrorComponent,\n children: element,\n });\n }\n ` : \"\"}\n const rscStream = renderToReadableStream(element, { onError: rscOnError });\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(rscStream, {\n status: statusCode,\n headers: { \"Content-Type\": \"text/x-component; charset=utf-8\", \"Vary\": \"RSC, Accept\" },\n });\n }\n // For HTML (full page load) responses, wrap with layouts only (no client-side\n // wrappers needed since SSR generates the complete HTML document).\n for (let i = layouts.length - 1; i >= 0; i--) {\n const LayoutComponent = layouts[i]?.default;\n if (LayoutComponent) {\n element = createElement(LayoutComponent, { children: element });\n }\n }\n const rscStream = renderToReadableStream(element, { onError: rscOnError });\n // Collect font data from RSC environment\n const fontData = {\n links: _getSSRFontLinks(),\n styles: _getSSRFontStyles(),\n preloads: _getSSRFontPreloads(),\n };\n const ssrEntry = await import.meta.viteRsc.loadModule(\"ssr\", \"index\");\n const htmlStream = await ssrEntry.handleSsr(rscStream, _getNavigationContext(), fontData);\n setHeadersContext(null);\n setNavigationContext(null);\n const _respHeaders = { \"Content-Type\": \"text/html; charset=utf-8\", \"Vary\": \"RSC, Accept\" };\n const _linkParts = (fontData.preloads || []).map(function(p) { return \"<\" + p.href + \">; rel=preload; as=font; type=\" + p.type + \"; crossorigin\"; });\n if (_linkParts.length > 0) _respHeaders[\"Link\"] = _linkParts.join(\", \");\n return new Response(htmlStream, {\n status: statusCode,\n headers: _respHeaders,\n });\n}\n\n/** Convenience: render a not-found page (404) */\nasync function renderNotFoundPage(route, isRscRequest, request) {\n return renderHTTPAccessFallbackPage(route, 404, isRscRequest, request);\n}\n\n/**\n * Render an error.tsx boundary page when a server component or generateMetadata() throws.\n * Returns null if no error boundary component is available for this route.\n *\n * Next.js returns HTTP 200 when error.tsx catches an error (the error is \"handled\"\n * by the boundary). This matches that behavior intentionally.\n */\nasync function renderErrorBoundaryPage(route, error, isRscRequest, request) {\n // Resolve the error boundary component: leaf error.tsx first, then walk per-layout\n // errors from innermost to outermost (matching ancestor inheritance), then global-error.tsx.\n let ErrorComponent = route?.error?.default ?? null;\n if (!ErrorComponent && route?.errors) {\n for (let i = route.errors.length - 1; i >= 0; i--) {\n if (route.errors[i]?.default) {\n ErrorComponent = route.errors[i].default;\n break;\n }\n }\n }\n ErrorComponent = ErrorComponent${globalErrorVar ? ` ?? ${globalErrorVar}?.default` : \"\"};\n if (!ErrorComponent) return null;\n\n const rawError = error instanceof Error ? error : new Error(String(error));\n // Sanitize the error in production to avoid leaking internal details\n // (database errors, file paths, stack traces) through error.tsx to the client.\n // In development, pass the original error for debugging.\n const errorObj = __sanitizeErrorForClient(rawError);\n // Only pass error — reset is a client-side concern (re-renders the segment) and\n // can't be serialized through RSC. The error.tsx component will receive reset=undefined\n // during SSR, which is fine — onClick={undefined} is harmless, and the real reset\n // function is only meaningful after hydration.\n let element = createElement(ErrorComponent, {\n error: errorObj,\n });\n const layouts = route?.layouts ?? rootLayouts;\n if (isRscRequest) {\n // For RSC requests (client-side navigation), wrap with the same component\n // wrappers that buildPageElement() uses (LayoutSegmentProvider, GlobalErrorBoundary).\n // This ensures React can reconcile the tree without destroying the DOM.\n // Same rationale as renderHTTPAccessFallbackPage — see comment there.\n const layoutDepths = route?.layoutSegmentDepths;\n for (let i = layouts.length - 1; i >= 0; i--) {\n const LayoutComponent = layouts[i]?.default;\n if (LayoutComponent) {\n element = createElement(LayoutComponent, { children: element });\n const layoutDepth = layoutDepths ? layoutDepths[i] : 0;\n element = createElement(LayoutSegmentProvider, { depth: layoutDepth }, element);\n }\n }\n ${globalErrorVar ? `\n const _ErrGlobalComponent = ${globalErrorVar}.default;\n if (_ErrGlobalComponent) {\n element = createElement(ErrorBoundary, {\n fallback: _ErrGlobalComponent,\n children: element,\n });\n }\n ` : \"\"}\n const rscStream = renderToReadableStream(element, { onError: rscOnError });\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(rscStream, {\n status: 200,\n headers: { \"Content-Type\": \"text/x-component; charset=utf-8\", \"Vary\": \"RSC, Accept\" },\n });\n }\n // For HTML (full page load) responses, wrap with layouts only.\n for (let i = layouts.length - 1; i >= 0; i--) {\n const LayoutComponent = layouts[i]?.default;\n if (LayoutComponent) {\n element = createElement(LayoutComponent, { children: element });\n }\n }\n const rscStream = renderToReadableStream(element, { onError: rscOnError });\n // Collect font data from RSC environment so error pages include font styles\n const fontData = {\n links: _getSSRFontLinks(),\n styles: _getSSRFontStyles(),\n preloads: _getSSRFontPreloads(),\n };\n const ssrEntry = await import.meta.viteRsc.loadModule(\"ssr\", \"index\");\n const htmlStream = await ssrEntry.handleSsr(rscStream, _getNavigationContext(), fontData);\n setHeadersContext(null);\n setNavigationContext(null);\n const _errHeaders = { \"Content-Type\": \"text/html; charset=utf-8\", \"Vary\": \"RSC, Accept\" };\n const _errLinkParts = (fontData.preloads || []).map(function(p) { return \"<\" + p.href + \">; rel=preload; as=font; type=\" + p.type + \"; crossorigin\"; });\n if (_errLinkParts.length > 0) _errHeaders[\"Link\"] = _errLinkParts.join(\", \");\n return new Response(htmlStream, {\n status: 200,\n headers: _errHeaders,\n });\n}\n\nfunction matchRoute(url, routes) {\n const pathname = url.split(\"?\")[0];\n let normalizedUrl = pathname === \"/\" ? \"/\" : pathname.replace(/\\\\/$/, \"\");\n // NOTE: Do NOT decodeURIComponent here. The caller is responsible for decoding\n // the pathname exactly once at the request entry point. Decoding again here\n // would cause inconsistent path matching between middleware and routing.\n for (const route of routes) {\n const params = matchPattern(normalizedUrl, route.pattern);\n if (params !== null) return { route, params };\n }\n return null;\n}\n\nfunction matchPattern(url, pattern) {\n const urlParts = url.split(\"/\").filter(Boolean);\n const patternParts = pattern.split(\"/\").filter(Boolean);\n const params = Object.create(null);\n for (let i = 0; i < patternParts.length; i++) {\n const pp = patternParts[i];\n if (pp.endsWith(\"+\")) {\n const paramName = pp.slice(1, -1);\n const remaining = urlParts.slice(i);\n if (remaining.length === 0) return null;\n params[paramName] = remaining;\n return params;\n }\n if (pp.endsWith(\"*\")) {\n const paramName = pp.slice(1, -1);\n params[paramName] = urlParts.slice(i);\n return params;\n }\n if (pp.startsWith(\":\")) {\n if (i >= urlParts.length) return null;\n params[pp.slice(1)] = urlParts[i];\n continue;\n }\n if (i >= urlParts.length || urlParts[i] !== pp) return null;\n }\n if (urlParts.length !== patternParts.length) return null;\n return params;\n}\n\n// Build a global intercepting route lookup for RSC navigation.\n// Maps target URL patterns to { sourceRouteIndex, slotName, interceptPage, params }.\nconst interceptLookup = [];\nfor (let ri = 0; ri < routes.length; ri++) {\n const r = routes[ri];\n if (!r.slots) continue;\n for (const [slotName, slotMod] of Object.entries(r.slots)) {\n if (!slotMod.intercepts) continue;\n for (const intercept of slotMod.intercepts) {\n interceptLookup.push({\n sourceRouteIndex: ri,\n slotName,\n targetPattern: intercept.targetPattern,\n page: intercept.page,\n params: intercept.params,\n });\n }\n }\n}\n\n/**\n * Check if a pathname matches any intercepting route.\n * Returns the match info or null.\n */\nfunction findIntercept(pathname) {\n for (const entry of interceptLookup) {\n const params = matchPattern(pathname, entry.targetPattern);\n if (params !== null) {\n return { ...entry, matchedParams: params };\n }\n }\n return null;\n}\n\nasync function buildPageElement(route, params, opts, searchParams) {\n const PageComponent = route.page?.default;\n if (!PageComponent) {\n return createElement(\"div\", null, \"Page has no default export\");\n }\n\n // Resolve metadata and viewport from layouts and page\n const metadataList = [];\n const viewportList = [];\n for (const layoutMod of route.layouts) {\n if (layoutMod) {\n const meta = await resolveModuleMetadata(layoutMod, params);\n if (meta) metadataList.push(meta);\n const vp = await resolveModuleViewport(layoutMod, params);\n if (vp) viewportList.push(vp);\n }\n }\n if (route.page) {\n const pageMeta = await resolveModuleMetadata(route.page, params);\n if (pageMeta) metadataList.push(pageMeta);\n const pageVp = await resolveModuleViewport(route.page, params);\n if (pageVp) viewportList.push(pageVp);\n }\n const resolvedMetadata = metadataList.length > 0 ? mergeMetadata(metadataList) : null;\n const resolvedViewport = viewportList.length > 0 ? mergeViewport(viewportList) : null;\n\n // Build nested layout tree from outermost to innermost.\n // Next.js 16 passes params/searchParams as Promises (async pattern)\n // but pre-16 code accesses them as plain objects (params.id).\n // makeThenableParams() normalises null-prototype + preserves both patterns.\n const asyncParams = makeThenableParams(params);\n const pageProps = { params: asyncParams };\n if (searchParams) {\n const spObj = {};\n let hasSearchParams = false;\n if (searchParams.forEach) searchParams.forEach(function(v, k) {\n hasSearchParams = true;\n if (k in spObj) {\n // Multi-value: promote to array (Next.js returns string[] for duplicate keys)\n spObj[k] = Array.isArray(spObj[k]) ? spObj[k].concat(v) : [spObj[k], v];\n } else {\n spObj[k] = v;\n }\n });\n // If the URL has query parameters, mark the page as dynamic.\n // In Next.js, only accessing the searchParams prop signals dynamic usage,\n // but a Proxy-based approach doesn't work here because React's RSC debug\n // serializer accesses properties on all props (e.g. $$typeof check in\n // isClientReference), triggering the Proxy even when user code doesn't\n // read searchParams. Checking for non-empty query params is a safe\n // approximation: pages with query params in the URL are almost always\n // dynamic, and this avoids false positives from React internals.\n if (hasSearchParams) markDynamicUsage();\n pageProps.searchParams = makeThenableParams(spObj);\n }\n let element = createElement(PageComponent, pageProps);\n\n // Add metadata + viewport head tags (React 19 hoists title/meta/link to <head>)\n // Next.js always injects charset and default viewport even when no metadata/viewport\n // is exported. We replicate that by always emitting these essential head elements.\n {\n const headElements = [];\n // Always emit <meta charset=\"utf-8\"> — Next.js includes this on every page\n headElements.push(createElement(\"meta\", { charSet: \"utf-8\" }));\n if (resolvedMetadata) headElements.push(createElement(MetadataHead, { metadata: resolvedMetadata }));\n // Default viewport to standard responsive settings when none is exported\n const effectiveViewport = resolvedViewport ?? { width: \"device-width\", initialScale: 1 };\n headElements.push(createElement(ViewportHead, { viewport: effectiveViewport }));\n element = createElement(Fragment, null, ...headElements, element);\n }\n\n // Wrap with loading.tsx Suspense if present\n if (route.loading?.default) {\n element = createElement(\n Suspense,\n { fallback: createElement(route.loading.default) },\n element,\n );\n }\n\n // Wrap with the leaf's error.tsx ErrorBoundary if it's not already covered\n // by a per-layout error boundary (i.e., the leaf has error.tsx but no layout).\n // Per-layout error boundaries are interleaved with layouts below.\n {\n const lastLayoutError = route.errors ? route.errors[route.errors.length - 1] : null;\n if (route.error?.default && route.error !== lastLayoutError) {\n element = createElement(ErrorBoundary, {\n fallback: route.error.default,\n children: element,\n });\n }\n }\n\n // Wrap with NotFoundBoundary so client-side notFound() renders not-found.tsx\n // instead of crashing the React tree. Must be above ErrorBoundary since\n // ErrorBoundary re-throws notFound errors.\n // Pre-render the not-found component as a React element since it may be a\n // server component (not a client reference) and can't be passed as a function prop.\n {\n const NotFoundComponent = route.notFound?.default ?? ${rootNotFoundVar ? `${rootNotFoundVar}?.default` : \"null\"};\n if (NotFoundComponent) {\n element = createElement(NotFoundBoundary, {\n fallback: createElement(NotFoundComponent),\n children: element,\n });\n }\n }\n\n // Wrap with templates (innermost first, then outer)\n // Templates are like layouts but re-mount on navigation (client-side concern).\n // On the server, they just wrap the content like layouts do.\n if (route.templates) {\n for (let i = route.templates.length - 1; i >= 0; i--) {\n const TemplateComponent = route.templates[i]?.default;\n if (TemplateComponent) {\n element = createElement(TemplateComponent, { children: element, params });\n }\n }\n }\n\n // Wrap with layouts (innermost first, then outer).\n // At each layout level, first wrap with that level's error boundary (if any)\n // so the boundary is inside the layout and catches errors from children.\n // This matches Next.js behavior: Layout > ErrorBoundary > children.\n // Parallel slots are passed as named props to the innermost layout\n // (the layout at the same directory level as the page/slots)\n for (let i = route.layouts.length - 1; i >= 0; i--) {\n // Wrap with per-layout error boundary before wrapping with layout.\n // This places the ErrorBoundary inside the layout, catching errors\n // from child segments (matching Next.js per-segment error handling).\n if (route.errors && route.errors[i]?.default) {\n element = createElement(ErrorBoundary, {\n fallback: route.errors[i].default,\n children: element,\n });\n }\n\n const LayoutComponent = route.layouts[i]?.default;\n if (LayoutComponent) {\n // Per-layout NotFoundBoundary: wraps this layout's children so that\n // notFound() thrown from a child layout is caught here.\n // Matches Next.js behavior where each segment has its own boundary.\n // The boundary at level N catches errors from Layout[N+1] and below,\n // but NOT from Layout[N] itself (which propagates to level N-1).\n {\n const LayoutNotFound = route.notFounds?.[i]?.default;\n if (LayoutNotFound) {\n element = createElement(NotFoundBoundary, {\n fallback: createElement(LayoutNotFound),\n children: element,\n });\n }\n }\n\n const layoutProps = { children: element, params: makeThenableParams(params) };\n\n // Add parallel slot elements to the layout that defines them.\n // Each slot has a layoutIndex indicating which layout it belongs to.\n if (route.slots) {\n for (const [slotName, slotMod] of Object.entries(route.slots)) {\n // Attach slot to the layout at its layoutIndex, or to the innermost layout if -1\n const targetIdx = slotMod.layoutIndex >= 0 ? slotMod.layoutIndex : route.layouts.length - 1;\n if (i !== targetIdx) continue;\n // Check if this slot has an intercepting route that should activate\n let SlotPage = null;\n let slotParams = params;\n\n if (opts && opts.interceptSlot === slotName && opts.interceptPage) {\n // Use the intercepting route's page component\n SlotPage = opts.interceptPage.default;\n slotParams = opts.interceptParams || params;\n } else {\n SlotPage = slotMod.page?.default || slotMod.default?.default;\n }\n\n if (SlotPage) {\n let slotElement = createElement(SlotPage, { params: makeThenableParams(slotParams) });\n // Wrap with slot-specific layout if present.\n // In Next.js, @slot/layout.tsx wraps the slot's page content\n // before it is passed as a prop to the parent layout.\n const SlotLayout = slotMod.layout?.default;\n if (SlotLayout) {\n slotElement = createElement(SlotLayout, {\n children: slotElement,\n params: makeThenableParams(slotParams),\n });\n }\n // Wrap with slot-specific loading if present\n if (slotMod.loading?.default) {\n slotElement = createElement(Suspense,\n { fallback: createElement(slotMod.loading.default) },\n slotElement,\n );\n }\n // Wrap with slot-specific error boundary if present\n if (slotMod.error?.default) {\n slotElement = createElement(ErrorBoundary, {\n fallback: slotMod.error.default,\n children: slotElement,\n });\n }\n layoutProps[slotName] = slotElement;\n }\n }\n }\n\n element = createElement(LayoutComponent, layoutProps);\n\n // Wrap the layout with LayoutSegmentProvider so useSelectedLayoutSegments()\n // called INSIDE this layout knows its URL segment depth. The depth tells the\n // hook how many URL segments are above this layout, so it returns only the\n // segments below. We wrap the layout (not just children) because hooks are\n // called from components rendered inside the layout's own JSX.\n const layoutDepth = route.layoutSegmentDepths ? route.layoutSegmentDepths[i] : 0;\n element = createElement(LayoutSegmentProvider, { depth: layoutDepth }, element);\n }\n }\n\n // Wrap with global error boundary if app/global-error.tsx exists.\n // This catches errors in the root layout itself.\n ${globalErrorVar ? `\n const GlobalErrorComponent = ${globalErrorVar}.default;\n if (GlobalErrorComponent) {\n element = createElement(ErrorBoundary, {\n fallback: GlobalErrorComponent,\n children: element,\n });\n }\n ` : \"\"}\n\n return element;\n}\n\n${middlewarePath ? generateMiddlewareMatcherCode(\"modern\") : \"\"}\n\nconst __basePath = ${JSON.stringify(bp)};\nconst __trailingSlash = ${JSON.stringify(ts)};\nconst __configRedirects = ${JSON.stringify(redirects)};\nconst __configRewrites = ${JSON.stringify(rewrites)};\nconst __configHeaders = ${JSON.stringify(headers)};\nconst __allowedOrigins = ${JSON.stringify(allowedOrigins)};\n\n${generateDevOriginCheckCode(config?.allowedDevOrigins)}\n\n// ── CSRF origin validation for server actions ───────────────────────────\n// Matches Next.js behavior: compare the Origin header against the Host header.\n// If they don't match, the request is rejected with 403 unless the origin is\n// in the allowedOrigins list (from experimental.serverActions.allowedOrigins).\nfunction __isOriginAllowed(origin, allowed) {\n for (const pattern of allowed) {\n if (pattern.startsWith(\"*.\")) {\n // Wildcard: *.example.com matches sub.example.com, a.b.example.com\n const suffix = pattern.slice(1); // \".example.com\"\n if (origin === pattern.slice(2) || origin.endsWith(suffix)) return true;\n } else if (origin === pattern) {\n return true;\n }\n }\n return false;\n}\n\nfunction __validateCsrfOrigin(request) {\n const originHeader = request.headers.get(\"origin\");\n // If there's no Origin header, allow the request — same-origin requests\n // from non-fetch navigations (e.g. SSR) may lack an Origin header.\n // The x-rsc-action custom header already provides protection against simple\n // form-based CSRF since custom headers can't be set by cross-origin forms.\n if (!originHeader || originHeader === \"null\") return null;\n\n let originHost;\n try {\n originHost = new URL(originHeader).host.toLowerCase();\n } catch {\n return new Response(\"Forbidden\", { status: 403, headers: { \"Content-Type\": \"text/plain\" } });\n }\n\n // Only use the Host header for origin comparison — never trust\n // X-Forwarded-Host here, since it can be freely set by the client\n // and would allow the check to be bypassed if it matched a spoofed\n // Origin. The prod server's resolveHost() handles trusted proxy\n // scenarios separately.\n const hostHeader = (\n request.headers.get(\"host\") ||\n \"\"\n ).split(\",\")[0].trim().toLowerCase();\n\n if (!hostHeader) return null;\n\n // Same origin — allow\n if (originHost === hostHeader) return null;\n\n // Check allowedOrigins from next.config.js\n if (__allowedOrigins.length > 0 && __isOriginAllowed(originHost, __allowedOrigins)) return null;\n\n console.warn(\n \\`[vinext] CSRF origin mismatch: origin \"\\${originHost}\" does not match host \"\\${hostHeader}\". Blocking server action request.\\`\n );\n return new Response(\"Forbidden\", { status: 403, headers: { \"Content-Type\": \"text/plain\" } });\n}\n\n// ── ReDoS-safe regex compilation ────────────────────────────────────────\n${generateSafeRegExpCode(\"modern\")}\n\n// ── Path normalization ──────────────────────────────────────────────────\n${generateNormalizePathCode(\"modern\")}\n\n// ── Config pattern matching (redirects, rewrites, headers) ──────────────\nfunction __matchConfigPattern(pathname, pattern) {\n if (pattern.includes(\"(\") || pattern.includes(\"\\\\\\\\\") || /:[\\\\w-]+[*+][^/]/.test(pattern) || /:[\\\\w-]+\\\\./.test(pattern)) {\n try {\n const paramNames = [];\n const regexStr = pattern\n .replace(/\\\\./g, \"\\\\\\\\.\")\n .replace(/:([\\\\w-]+)\\\\*(?:\\\\(([^)]+)\\\\))?/g, (_, name, c) => { paramNames.push(name); return c ? \"(\" + c + \")\" : \"(.*)\"; })\n .replace(/:([\\\\w-]+)\\\\+(?:\\\\(([^)]+)\\\\))?/g, (_, name, c) => { paramNames.push(name); return c ? \"(\" + c + \")\" : \"(.+)\"; })\n .replace(/:([\\\\w-]+)\\\\(([^)]+)\\\\)/g, (_, name, c) => { paramNames.push(name); return \"(\" + c + \")\"; })\n .replace(/:([\\\\w-]+)/g, (_, name) => { paramNames.push(name); return \"([^/]+)\"; });\n const re = __safeRegExp(\"^\" + regexStr + \"$\");\n if (!re) return null;\n const match = re.exec(pathname);\n if (!match) return null;\n const params = Object.create(null);\n for (let i = 0; i < paramNames.length; i++) params[paramNames[i]] = match[i + 1] || \"\";\n return params;\n } catch { /* fall through */ }\n }\n const catchAllMatch = pattern.match(/:([\\\\w-]+)(\\\\*|\\\\+)$/);\n if (catchAllMatch) {\n const prefix = pattern.slice(0, pattern.lastIndexOf(\":\"));\n const paramName = catchAllMatch[1];\n const isPlus = catchAllMatch[2] === \"+\";\n if (!pathname.startsWith(prefix.replace(/\\\\/$/, \"\"))) return null;\n const rest = pathname.slice(prefix.replace(/\\\\/$/, \"\").length);\n if (isPlus && (!rest || rest === \"/\")) return null;\n let restValue = rest.startsWith(\"/\") ? rest.slice(1) : rest;\n // NOTE: Do NOT decodeURIComponent here. The pathname is already decoded at\n // the request entry point. Decoding again would produce incorrect param values.\n return { [paramName]: restValue };\n }\n const parts = pattern.split(\"/\");\n const pathParts = pathname.split(\"/\");\n if (parts.length !== pathParts.length) return null;\n const params = Object.create(null);\n for (let i = 0; i < parts.length; i++) {\n if (parts[i].startsWith(\":\")) params[parts[i].slice(1)] = pathParts[i];\n else if (parts[i] !== pathParts[i]) return null;\n }\n return params;\n}\n\nfunction __parseCookies(cookieHeader) {\n if (!cookieHeader) return {};\n const cookies = {};\n for (const part of cookieHeader.split(\";\")) {\n const eq = part.indexOf(\"=\");\n if (eq === -1) continue;\n const key = part.slice(0, eq).trim();\n const value = part.slice(eq + 1).trim();\n if (key) cookies[key] = value;\n }\n return cookies;\n}\n\nfunction __checkSingleCondition(condition, ctx) {\n switch (condition.type) {\n case \"header\": {\n const v = ctx.headers.get(condition.key);\n if (v === null) return false;\n if (condition.value !== undefined) { const re = __safeRegExp(condition.value); return re ? re.test(v) : v === condition.value; }\n return true;\n }\n case \"cookie\": {\n const v = ctx.cookies[condition.key];\n if (v === undefined) return false;\n if (condition.value !== undefined) { const re = __safeRegExp(condition.value); return re ? re.test(v) : v === condition.value; }\n return true;\n }\n case \"query\": {\n const v = ctx.query.get(condition.key);\n if (v === null) return false;\n if (condition.value !== undefined) { const re = __safeRegExp(condition.value); return re ? re.test(v) : v === condition.value; }\n return true;\n }\n case \"host\": {\n if (condition.value !== undefined) { const re = __safeRegExp(condition.value); return re ? re.test(ctx.host) : ctx.host === condition.value; }\n return ctx.host === condition.key;\n }\n default: return false;\n }\n}\n\nfunction __checkHasConditions(has, missing, ctx) {\n if (has) { for (const c of has) { if (!__checkSingleCondition(c, ctx)) return false; } }\n if (missing) { for (const c of missing) { if (__checkSingleCondition(c, ctx)) return false; } }\n return true;\n}\n\nfunction __buildRequestContext(request) {\n const url = new URL(request.url);\n return {\n headers: request.headers,\n cookies: __parseCookies(request.headers.get(\"cookie\")),\n query: url.searchParams,\n host: request.headers.get(\"host\") || url.host,\n };\n}\n\nfunction __sanitizeDestination(dest) {\n if (dest.startsWith(\"http://\") || dest.startsWith(\"https://\")) return dest;\n dest = dest.replace(/^[\\\\\\\\/]+/, \"/\");\n return dest;\n}\n\nfunction __applyConfigRedirects(pathname, ctx) {\n for (const rule of __configRedirects) {\n const params = __matchConfigPattern(pathname, rule.source);\n if (params) {\n if (ctx && (rule.has || rule.missing)) { if (!__checkHasConditions(rule.has, rule.missing, ctx)) continue; }\n let dest = rule.destination;\n for (const [key, value] of Object.entries(params)) { dest = dest.replace(\":\" + key + \"*\", value); dest = dest.replace(\":\" + key + \"+\", value); dest = dest.replace(\":\" + key, value); }\n dest = __sanitizeDestination(dest);\n return { destination: dest, permanent: rule.permanent };\n }\n }\n return null;\n}\n\nfunction __applyConfigRewrites(pathname, rules, ctx) {\n for (const rule of rules) {\n const params = __matchConfigPattern(pathname, rule.source);\n if (params) {\n if (ctx && (rule.has || rule.missing)) { if (!__checkHasConditions(rule.has, rule.missing, ctx)) continue; }\n let dest = rule.destination;\n for (const [key, value] of Object.entries(params)) { dest = dest.replace(\":\" + key + \"*\", value); dest = dest.replace(\":\" + key + \"+\", value); dest = dest.replace(\":\" + key, value); }\n dest = __sanitizeDestination(dest);\n return dest;\n }\n }\n return null;\n}\n\nfunction __isExternalUrl(url) {\n return /^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith(\"//\");\n}\n\n/**\n * Maximum server-action request body size (1 MB).\n * Matches the Next.js default for serverActions.bodySizeLimit.\n * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/serverActions#bodysizelimit\n * Prevents unbounded request body buffering.\n */\nvar __MAX_ACTION_BODY_SIZE = 1 * 1024 * 1024;\n\n/**\n * Read a request body as text with a size limit.\n * Enforces the limit on the actual byte stream to prevent bypasses\n * via chunked transfer-encoding where Content-Length is absent or spoofed.\n */\nasync function __readBodyWithLimit(request, maxBytes) {\n if (!request.body) return \"\";\n var reader = request.body.getReader();\n var decoder = new TextDecoder();\n var chunks = [];\n var totalSize = 0;\n for (;;) {\n var result = await reader.read();\n if (result.done) break;\n totalSize += result.value.byteLength;\n if (totalSize > maxBytes) {\n reader.cancel();\n throw new Error(\"Request body too large\");\n }\n chunks.push(decoder.decode(result.value, { stream: true }));\n }\n chunks.push(decoder.decode());\n return chunks.join(\"\");\n}\n\n/**\n * Read a request body as FormData with a size limit.\n * Consumes the body stream with a byte counter and then parses the\n * collected bytes as multipart form data via the Response constructor.\n */\nasync function __readFormDataWithLimit(request, maxBytes) {\n if (!request.body) return new FormData();\n var reader = request.body.getReader();\n var chunks = [];\n var totalSize = 0;\n for (;;) {\n var result = await reader.read();\n if (result.done) break;\n totalSize += result.value.byteLength;\n if (totalSize > maxBytes) {\n reader.cancel();\n throw new Error(\"Request body too large\");\n }\n chunks.push(result.value);\n }\n // Reconstruct a Response with the original Content-Type so that\n // the FormData parser can handle multipart boundaries correctly.\n var combined = new Uint8Array(totalSize);\n var offset = 0;\n for (var chunk of chunks) {\n combined.set(chunk, offset);\n offset += chunk.byteLength;\n }\n var contentType = request.headers.get(\"content-type\") || \"\";\n return new Response(combined, { headers: { \"Content-Type\": contentType } }).formData();\n}\n\nconst __hopByHopHeaders = new Set([\"connection\",\"keep-alive\",\"proxy-authenticate\",\"proxy-authorization\",\"te\",\"trailers\",\"transfer-encoding\",\"upgrade\"]);\n\nasync function __proxyExternalRequest(request, externalUrl) {\n const originalUrl = new URL(request.url);\n const targetUrl = new URL(externalUrl);\n for (const [key, value] of originalUrl.searchParams) {\n if (!targetUrl.searchParams.has(key)) targetUrl.searchParams.set(key, value);\n }\n const headers = new Headers(request.headers);\n headers.set(\"host\", targetUrl.host);\n headers.delete(\"connection\");\n // Strip credentials and internal headers to prevent leaking auth tokens,\n // session cookies, and middleware internals to third-party origins.\n headers.delete(\"cookie\");\n headers.delete(\"authorization\");\n headers.delete(\"x-api-key\");\n headers.delete(\"proxy-authorization\");\n for (const key of [...headers.keys()]) {\n if (key.startsWith(\"x-middleware-\")) headers.delete(key);\n }\n const method = request.method;\n const hasBody = method !== \"GET\" && method !== \"HEAD\";\n const init = { method, headers, redirect: \"manual\", signal: AbortSignal.timeout(30000) };\n if (hasBody && request.body) { init.body = request.body; init.duplex = \"half\"; }\n let upstream;\n try { upstream = await fetch(targetUrl.href, init); }\n catch (e) {\n if (e && e.name === \"TimeoutError\") return new Response(\"Gateway Timeout\", { status: 504 });\n console.error(\"[vinext] External rewrite proxy error:\", e); return new Response(\"Bad Gateway\", { status: 502 });\n }\n const respHeaders = new Headers();\n upstream.headers.forEach(function(value, key) { if (!__hopByHopHeaders.has(key.toLowerCase())) respHeaders.append(key, value); });\n return new Response(upstream.body, { status: upstream.status, statusText: upstream.statusText, headers: respHeaders });\n}\n\nfunction __applyConfigHeaders(pathname, ctx) {\n const result = [];\n for (const rule of __configHeaders) {\n const groups = [];\n const withPlaceholders = rule.source.replace(/\\\\(([^)]+)\\\\)/g, (_, inner) => {\n groups.push(inner);\n return \"___GROUP_\" + (groups.length - 1) + \"___\";\n });\n const escaped = withPlaceholders\n .replace(/\\\\./g, \"\\\\\\\\.\")\n .replace(/\\\\+/g, \"\\\\\\\\+\")\n .replace(/\\\\?/g, \"\\\\\\\\?\")\n .replace(/\\\\*/g, \".*\")\n .replace(/:[\\\\w-]+/g, \"[^/]+\")\n .replace(/___GROUP_(\\\\d+)___/g, (_, idx) => \"(\" + groups[Number(idx)] + \")\");\n const sourceRegex = __safeRegExp(\"^\" + escaped + \"$\");\n if (sourceRegex && sourceRegex.test(pathname)) {\n if (ctx && (rule.has || rule.missing)) {\n if (!__checkHasConditions(rule.has, rule.missing, ctx)) continue;\n }\n result.push(...rule.headers);\n }\n }\n return result;\n}\n\nexport default async function handler(request) {\n // Wrap the entire request in nested AsyncLocalStorage.run() scopes to ensure\n // per-request isolation for all state modules. Each runWith*() creates an\n // ALS scope that propagates through all async continuations (including RSC\n // streaming), preventing state leakage between concurrent requests on\n // Cloudflare Workers and other concurrent runtimes.\n const headersCtx = headersContextFromRequest(request);\n return runWithHeadersContext(headersCtx, () =>\n _runWithNavigationContext(() =>\n _runWithCacheState(() =>\n _runWithPrivateCache(() =>\n runWithFetchCache(async () => {\n const __reqCtx = __buildRequestContext(request);\n const response = await _handleRequest(request, __reqCtx);\n // Apply custom headers from next.config.js to non-redirect responses.\n // Skip redirects (3xx) because Response.redirect() creates immutable headers,\n // and Next.js doesn't apply custom headers to redirects anyway.\n if (__configHeaders.length && response && response.headers && !(response.status >= 300 && response.status < 400)) {\n const url = new URL(request.url);\n let pathname;\n try { pathname = __normalizePath(decodeURIComponent(url.pathname)); } catch { pathname = url.pathname; }\n ${bp ? `if (pathname.startsWith(${JSON.stringify(bp)})) pathname = pathname.slice(${JSON.stringify(bp)}.length) || \"/\";` : \"\"}\n const extraHeaders = __applyConfigHeaders(pathname, __reqCtx);\n for (const h of extraHeaders) {\n response.headers.set(h.key, h.value);\n }\n }\n return response;\n })\n )\n )\n )\n );\n}\n\nasync function _handleRequest(request, __reqCtx) {\n const url = new URL(request.url);\n\n // ── Cross-origin request protection ─────────────────────────────────\n // Block requests from non-localhost origins to prevent data exfiltration.\n const __originBlock = __validateDevRequestOrigin(request);\n if (__originBlock) return __originBlock;\n\n // Guard against protocol-relative URL open redirects.\n // Paths like //example.com/ would be redirected to //example.com by the\n // trailing-slash normalizer, which browsers interpret as http://example.com.\n // Backslashes are equivalent to forward slashes in the URL spec\n // (e.g. /\\\\evil.com is treated as //evil.com by browsers and the URL constructor).\n // Next.js returns 404 for these paths. Check the RAW pathname before\n // normalization so the guard fires before normalizePath collapses //.\n if (url.pathname.replaceAll(\"\\\\\\\\\", \"/\").startsWith(\"//\")) {\n return new Response(\"404 Not Found\", { status: 404 });\n }\n\n // Decode percent-encoding and normalize pathname to canonical form.\n // decodeURIComponent prevents /%61dmin from bypassing /admin matchers.\n // __normalizePath collapses //foo///bar → /foo/bar, resolves . and .. segments.\n let decodedUrlPathname;\n try { decodedUrlPathname = decodeURIComponent(url.pathname); } catch (e) {\n return new Response(\"Bad Request\", { status: 400 });\n }\n let pathname = __normalizePath(decodedUrlPathname);\n\n ${bp ? `\n // Strip basePath prefix\n if (__basePath && pathname.startsWith(__basePath)) {\n pathname = pathname.slice(__basePath.length) || \"/\";\n }\n ` : \"\"}\n\n // Trailing slash normalization (redirect to canonical form)\n if (pathname !== \"/\" && !pathname.startsWith(\"/api\")) {\n const hasTrailing = pathname.endsWith(\"/\");\n if (__trailingSlash && !hasTrailing && !pathname.endsWith(\".rsc\")) {\n return Response.redirect(new URL(__basePath + pathname + \"/\" + url.search, request.url), 308);\n } else if (!__trailingSlash && hasTrailing) {\n return Response.redirect(new URL(__basePath + pathname.replace(/\\\\/+$/, \"\") + url.search, request.url), 308);\n }\n }\n\n // ── Apply redirects from next.config.js ───────────────────────────────\n if (__configRedirects.length) {\n const __redir = __applyConfigRedirects(pathname, __reqCtx);\n if (__redir) {\n const __redirDest = __sanitizeDestination(\n __basePath && !__redir.destination.startsWith(__basePath)\n ? __basePath + __redir.destination\n : __redir.destination\n );\n return new Response(null, {\n status: __redir.permanent ? 308 : 307,\n headers: { Location: __redirDest },\n });\n }\n }\n\n // ── Apply beforeFiles rewrites from next.config.js ────────────────────\n if (__configRewrites.beforeFiles && __configRewrites.beforeFiles.length) {\n const __rewritten = __applyConfigRewrites(pathname, __configRewrites.beforeFiles, __reqCtx);\n if (__rewritten) {\n if (__isExternalUrl(__rewritten)) {\n setHeadersContext(null);\n setNavigationContext(null);\n return __proxyExternalRequest(request, __rewritten);\n }\n pathname = __rewritten;\n }\n }\n\n const isRscRequest = pathname.endsWith(\".rsc\") || request.headers.get(\"accept\")?.includes(\"text/x-component\");\n let cleanPathname = pathname.replace(/\\\\.rsc$/, \"\");\n\n // Middleware response headers to merge into the final response\n let _middlewareResponseHeaders = null;\n // Custom status code from middleware rewrite (e.g. NextResponse.rewrite(url, { status: 403 }))\n let _middlewareRewriteStatus = null;\n\n ${middlewarePath ? `\n // Run proxy/middleware if present and path matches.\n // Validate exports match the file type (proxy.ts vs middleware.ts), matching Next.js behavior.\n // https://github.com/vercel/next.js/blob/canary/test/e2e/app-dir/proxy-missing-export/proxy-missing-export.test.ts\n const _isProxy = ${JSON.stringify(isProxyFile(middlewarePath))};\n const middlewareFn = _isProxy\n ? (middlewareModule.proxy ?? middlewareModule.default)\n : (middlewareModule.middleware ?? middlewareModule.default);\n if (typeof middlewareFn !== \"function\") {\n const _fileType = _isProxy ? \"Proxy\" : \"Middleware\";\n const _expectedExport = _isProxy ? \"proxy\" : \"middleware\";\n throw new Error(\"The \" + _fileType + \" file must export a function named \\`\" + _expectedExport + \"\\` or a \\`default\\` function.\");\n }\n const middlewareMatcher = middlewareModule.config?.matcher;\n if (matchesMiddleware(cleanPathname, middlewareMatcher)) {\n try {\n // Wrap in NextRequest so middleware gets .nextUrl, .cookies, .geo, .ip, etc.\n // Always construct a new Request with the fully decoded + normalized pathname\n // so middleware and the router see the same canonical path.\n const mwUrl = new URL(request.url);\n mwUrl.pathname = cleanPathname;\n const mwRequest = new Request(mwUrl, request);\n const nextRequest = mwRequest instanceof NextRequest ? mwRequest : new NextRequest(mwRequest);\n const mwResponse = await middlewareFn(nextRequest);\n if (mwResponse) {\n // Check for x-middleware-next (continue)\n if (mwResponse.headers.get(\"x-middleware-next\") === \"1\") {\n // Middleware wants to continue — collect all headers except the two\n // control headers we've already consumed. x-middleware-request-*\n // headers are kept so applyMiddlewareRequestHeaders() can unpack them;\n // the blanket strip loop after that call removes every remaining\n // x-middleware-* header before the set is merged into the response.\n _middlewareResponseHeaders = new Headers();\n for (const [key, value] of mwResponse.headers) {\n if (key !== \"x-middleware-next\" && key !== \"x-middleware-rewrite\") {\n _middlewareResponseHeaders.append(key, value);\n }\n }\n } else {\n // Check for redirect\n if (mwResponse.status >= 300 && mwResponse.status < 400) {\n return mwResponse;\n }\n // Check for rewrite\n const rewriteUrl = mwResponse.headers.get(\"x-middleware-rewrite\");\n if (rewriteUrl) {\n const rewriteParsed = new URL(rewriteUrl, request.url);\n cleanPathname = rewriteParsed.pathname;\n // Capture custom status code from rewrite (e.g. NextResponse.rewrite(url, { status: 403 }))\n if (mwResponse.status !== 200) {\n _middlewareRewriteStatus = mwResponse.status;\n }\n // Also save any other headers from the rewrite response\n _middlewareResponseHeaders = new Headers();\n for (const [key, value] of mwResponse.headers) {\n if (key !== \"x-middleware-next\" && key !== \"x-middleware-rewrite\") {\n _middlewareResponseHeaders.append(key, value);\n }\n }\n } else {\n // Middleware returned a custom response\n return mwResponse;\n }\n }\n }\n } catch (err) {\n console.error(\"[vinext] Middleware error:\", err);\n return new Response(\"Internal Server Error\", { status: 500 });\n }\n }\n\n // Unpack x-middleware-request-* headers into the request context so that\n // headers() returns the middleware-modified headers instead of the original\n // request headers. Strip ALL x-middleware-* headers from the set that will\n // be merged into the outgoing HTTP response — this prefix is reserved for\n // internal routing signals and must never reach clients.\n if (_middlewareResponseHeaders) {\n applyMiddlewareRequestHeaders(_middlewareResponseHeaders);\n for (const key of [..._middlewareResponseHeaders.keys()]) {\n if (key.startsWith(\"x-middleware-\")) {\n _middlewareResponseHeaders.delete(key);\n }\n }\n }\n ` : \"\"}\n\n // ── Image optimization passthrough (dev mode — no transformation) ───────\n if (cleanPathname === \"/_vinext/image\") {\n const __rawImgUrl = url.searchParams.get(\"url\");\n // Normalize backslashes: browsers and the URL constructor treat\n // /\\\\evil.com as protocol-relative (//evil.com), bypassing the // check.\n const __imgUrl = __rawImgUrl?.replaceAll(\"\\\\\\\\\", \"/\") ?? null;\n // Allowlist: must start with \"/\" but not \"//\" — blocks absolute URLs,\n // protocol-relative, backslash variants, and exotic schemes.\n if (!__imgUrl || !__imgUrl.startsWith(\"/\") || __imgUrl.startsWith(\"//\")) {\n return new Response(!__rawImgUrl ? \"Missing url parameter\" : \"Only relative URLs allowed\", { status: 400 });\n }\n // Validate the constructed URL's origin hasn't changed (defense in depth).\n const __resolvedImg = new URL(__imgUrl, request.url);\n if (__resolvedImg.origin !== url.origin) {\n return new Response(\"Only relative URLs allowed\", { status: 400 });\n }\n // In dev, redirect to the original asset URL so Vite's static serving handles it.\n return Response.redirect(__resolvedImg.href, 302);\n }\n\n // Handle metadata routes (sitemap.xml, robots.txt, manifest.webmanifest, etc.)\n for (const metaRoute of metadataRoutes) {\n if (cleanPathname === metaRoute.servedUrl) {\n if (metaRoute.isDynamic) {\n // Dynamic metadata route — call the default export and serialize\n const metaFn = metaRoute.module.default;\n if (typeof metaFn === \"function\") {\n const result = await metaFn();\n let body;\n // If it's already a Response (e.g., ImageResponse), return directly\n if (result instanceof Response) return result;\n // Serialize based on type\n if (metaRoute.type === \"sitemap\") body = sitemapToXml(result);\n else if (metaRoute.type === \"robots\") body = robotsToText(result);\n else if (metaRoute.type === \"manifest\") body = manifestToJson(result);\n else body = JSON.stringify(result);\n return new Response(body, {\n headers: { \"Content-Type\": metaRoute.contentType },\n });\n }\n } else {\n // Static metadata file — decode from embedded base64 data\n try {\n const binary = atob(metaRoute.fileDataBase64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return new Response(bytes, {\n headers: {\n \"Content-Type\": metaRoute.contentType,\n \"Cache-Control\": \"public, max-age=0, must-revalidate\",\n },\n });\n } catch {\n return new Response(\"Not Found\", { status: 404 });\n }\n }\n }\n }\n\n // Set navigation context for Server Components.\n // Note: Headers context is already set by runWithHeadersContext in the handler wrapper.\n setNavigationContext({\n pathname: cleanPathname,\n searchParams: url.searchParams,\n params: {},\n });\n\n // Handle server action POST requests\n const actionId = request.headers.get(\"x-rsc-action\");\n if (request.method === \"POST\" && actionId) {\n // ── CSRF protection ─────────────────────────────────────────────────\n // Verify that the Origin header matches the Host header to prevent\n // cross-site request forgery, matching Next.js server action behavior.\n const csrfResponse = __validateCsrfOrigin(request);\n if (csrfResponse) return csrfResponse;\n\n // ── Body size limit ─────────────────────────────────────────────────\n // Reject payloads larger than the configured limit.\n // Check Content-Length as a fast path, then enforce on the actual\n // stream to prevent bypasses via chunked transfer-encoding.\n const contentLength = parseInt(request.headers.get(\"content-length\") || \"0\", 10);\n if (contentLength > __MAX_ACTION_BODY_SIZE) {\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(\"Payload Too Large\", { status: 413 });\n }\n\n try {\n const contentType = request.headers.get(\"content-type\") || \"\";\n let body;\n try {\n body = contentType.startsWith(\"multipart/form-data\")\n ? await __readFormDataWithLimit(request, __MAX_ACTION_BODY_SIZE)\n : await __readBodyWithLimit(request, __MAX_ACTION_BODY_SIZE);\n } catch (sizeErr) {\n if (sizeErr && sizeErr.message === \"Request body too large\") {\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(\"Payload Too Large\", { status: 413 });\n }\n throw sizeErr;\n }\n const temporaryReferences = createTemporaryReferenceSet();\n const args = await decodeReply(body, { temporaryReferences });\n const action = await loadServerAction(actionId);\n let returnValue;\n let actionRedirect = null;\n try {\n const data = await action.apply(null, args);\n returnValue = { ok: true, data };\n } catch (e) {\n // Detect redirect() / permanentRedirect() called inside the action.\n // These throw errors with digest \"NEXT_REDIRECT;replace;url[;status]\".\n // The URL is encodeURIComponent-encoded to prevent semicolons in the URL\n // from corrupting the delimiter-based digest format.\n if (e && typeof e === \"object\" && \"digest\" in e) {\n const digest = String(e.digest);\n if (digest.startsWith(\"NEXT_REDIRECT;\")) {\n const parts = digest.split(\";\");\n actionRedirect = {\n url: decodeURIComponent(parts[2]),\n type: parts[1] || \"replace\", // \"push\" or \"replace\"\n status: parts[3] ? parseInt(parts[3], 10) : 307,\n };\n returnValue = { ok: true, data: undefined };\n } else if (digest === \"NEXT_NOT_FOUND\" || digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")) {\n // notFound() / forbidden() / unauthorized() in action — package as error\n returnValue = { ok: false, data: e };\n } else {\n // Non-navigation digest error — sanitize in production to avoid\n // leaking internal details (connection strings, paths, etc.)\n console.error(\"[vinext] Server action error:\", e);\n returnValue = { ok: false, data: __sanitizeErrorForClient(e) };\n }\n } else {\n // Unhandled error — sanitize in production to avoid leaking\n // internal details (database errors, file paths, stack traces, etc.)\n console.error(\"[vinext] Server action error:\", e);\n returnValue = { ok: false, data: __sanitizeErrorForClient(e) };\n }\n }\n\n // If the action called redirect(), signal the client to navigate.\n // We can't use a real HTTP redirect (the fetch would follow it automatically\n // and receive a page HTML instead of RSC stream). Instead, we return a 200\n // with x-action-redirect header that the client entry detects and handles.\n if (actionRedirect) {\n const actionPendingCookies = getAndClearPendingCookies();\n const actionDraftCookie = getDraftModeCookieHeader();\n setHeadersContext(null);\n setNavigationContext(null);\n const redirectHeaders = new Headers({\n \"Content-Type\": \"text/x-component; charset=utf-8\",\n \"Vary\": \"RSC, Accept\",\n \"x-action-redirect\": actionRedirect.url,\n \"x-action-redirect-type\": actionRedirect.type,\n \"x-action-redirect-status\": String(actionRedirect.status),\n });\n for (const cookie of actionPendingCookies) {\n redirectHeaders.append(\"Set-Cookie\", cookie);\n }\n if (actionDraftCookie) redirectHeaders.append(\"Set-Cookie\", actionDraftCookie);\n // Send an empty RSC-like body (client will navigate instead of parsing)\n return new Response(\"\", { status: 200, headers: redirectHeaders });\n }\n\n // After the action, re-render the current page so the client\n // gets an updated React tree reflecting any mutations.\n const match = matchRoute(cleanPathname, routes);\n let element;\n if (match) {\n const { route: actionRoute, params: actionParams } = match;\n setNavigationContext({\n pathname: cleanPathname,\n searchParams: url.searchParams,\n params: actionParams,\n });\n element = buildPageElement(actionRoute, actionParams, undefined, url.searchParams);\n } else {\n element = createElement(\"div\", null, \"Page not found\");\n }\n\n const rscStream = renderToReadableStream(\n { root: element, returnValue },\n { temporaryReferences, onError: rscOnError },\n );\n\n // Collect cookies set during the action\n const actionPendingCookies = getAndClearPendingCookies();\n const actionDraftCookie = getDraftModeCookieHeader();\n setHeadersContext(null);\n setNavigationContext(null);\n\n const actionHeaders = { \"Content-Type\": \"text/x-component; charset=utf-8\", \"Vary\": \"RSC, Accept\" };\n const actionResponse = new Response(rscStream, { headers: actionHeaders });\n if (actionPendingCookies.length > 0 || actionDraftCookie) {\n for (const cookie of actionPendingCookies) {\n actionResponse.headers.append(\"Set-Cookie\", cookie);\n }\n if (actionDraftCookie) actionResponse.headers.append(\"Set-Cookie\", actionDraftCookie);\n }\n return actionResponse;\n } catch (err) {\n getAndClearPendingCookies(); // Clear pending cookies on error\n console.error(\"[vinext] Server action error:\", err);\n _reportRequestError(\n err instanceof Error ? err : new Error(String(err)),\n { path: cleanPathname, method: request.method, headers: Object.fromEntries(request.headers.entries()) },\n { routerKind: \"App Router\", routePath: cleanPathname, routeType: \"action\" },\n ).catch((reportErr) => {\n console.error(\"[vinext] Failed to report server action error:\", reportErr);\n });\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(\n process.env.NODE_ENV === \"production\"\n ? \"Internal Server Error\"\n : \"Server action failed: \" + (err && err.message ? err.message : String(err)),\n { status: 500 },\n );\n }\n }\n\n // ── Apply afterFiles rewrites from next.config.js ──────────────────────\n if (__configRewrites.afterFiles && __configRewrites.afterFiles.length) {\n const __afterRewritten = __applyConfigRewrites(cleanPathname, __configRewrites.afterFiles, __reqCtx);\n if (__afterRewritten) {\n if (__isExternalUrl(__afterRewritten)) {\n setHeadersContext(null);\n setNavigationContext(null);\n return __proxyExternalRequest(request, __afterRewritten);\n }\n cleanPathname = __afterRewritten;\n }\n }\n\n let match = matchRoute(cleanPathname, routes);\n\n // ── Fallback rewrites from next.config.js (if no route matched) ───────\n if (!match && __configRewrites.fallback && __configRewrites.fallback.length) {\n const __fallbackRewritten = __applyConfigRewrites(cleanPathname, __configRewrites.fallback, __reqCtx);\n if (__fallbackRewritten) {\n if (__isExternalUrl(__fallbackRewritten)) {\n setHeadersContext(null);\n setNavigationContext(null);\n return __proxyExternalRequest(request, __fallbackRewritten);\n }\n cleanPathname = __fallbackRewritten;\n match = matchRoute(cleanPathname, routes);\n }\n }\n\n if (!match) {\n // Render custom not-found page if available, otherwise plain 404\n const notFoundResponse = await renderNotFoundPage(null, isRscRequest, request);\n if (notFoundResponse) return notFoundResponse;\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(\"Not Found\", { status: 404 });\n }\n\n const { route, params } = match;\n\n // Update navigation context with matched params\n setNavigationContext({\n pathname: cleanPathname,\n searchParams: url.searchParams,\n params,\n });\n\n // Handle route.ts API handlers\n if (route.routeHandler) {\n const handler = route.routeHandler;\n const method = request.method.toUpperCase();\n\n // Collect exported HTTP methods for OPTIONS auto-response and Allow header\n const HTTP_METHODS = [\"GET\", \"HEAD\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\", \"OPTIONS\"];\n const exportedMethods = HTTP_METHODS.filter((m) => typeof handler[m] === \"function\");\n // If GET is exported, HEAD is implicitly supported\n if (exportedMethods.includes(\"GET\") && !exportedMethods.includes(\"HEAD\")) {\n exportedMethods.push(\"HEAD\");\n }\n const hasDefault = typeof handler[\"default\"] === \"function\";\n\n // OPTIONS auto-implementation: respond with Allow header and 204\n if (method === \"OPTIONS\" && typeof handler[\"OPTIONS\"] !== \"function\") {\n const allowMethods = hasDefault ? HTTP_METHODS : exportedMethods;\n if (!allowMethods.includes(\"OPTIONS\")) allowMethods.push(\"OPTIONS\");\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(null, {\n status: 204,\n headers: { \"Allow\": allowMethods.join(\", \") },\n });\n }\n\n // HEAD auto-implementation: run GET handler and strip body\n let handlerFn = handler[method] || handler[\"default\"];\n let isAutoHead = false;\n if (method === \"HEAD\" && typeof handler[\"HEAD\"] !== \"function\" && typeof handler[\"GET\"] === \"function\") {\n handlerFn = handler[\"GET\"];\n isAutoHead = true;\n }\n\n if (typeof handlerFn === \"function\") {\n try {\n const response = await handlerFn(request, { params });\n\n // Collect any Set-Cookie headers from cookies().set()/delete() calls\n const pendingCookies = getAndClearPendingCookies();\n const draftCookie = getDraftModeCookieHeader();\n setHeadersContext(null);\n setNavigationContext(null);\n\n // If we have pending cookies, create a new response with them attached\n if (pendingCookies.length > 0 || draftCookie) {\n const newHeaders = new Headers(response.headers);\n for (const cookie of pendingCookies) {\n newHeaders.append(\"Set-Cookie\", cookie);\n }\n if (draftCookie) newHeaders.append(\"Set-Cookie\", draftCookie);\n\n if (isAutoHead) {\n return new Response(null, {\n status: response.status,\n statusText: response.statusText,\n headers: newHeaders,\n });\n }\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers: newHeaders,\n });\n }\n\n if (isAutoHead) {\n // Strip body for auto-HEAD, preserve headers and status\n return new Response(null, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n }\n return response;\n } catch (err) {\n getAndClearPendingCookies(); // Clear any pending cookies on error\n // Catch redirect() / notFound() thrown from route handlers\n if (err && typeof err === \"object\" && \"digest\" in err) {\n const digest = String(err.digest);\n if (digest.startsWith(\"NEXT_REDIRECT;\")) {\n const parts = digest.split(\";\");\n const redirectUrl = decodeURIComponent(parts[2]);\n const statusCode = parts[3] ? parseInt(parts[3], 10) : 307;\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(null, {\n status: statusCode,\n headers: { Location: new URL(redirectUrl, request.url).toString() },\n });\n }\n if (digest === \"NEXT_NOT_FOUND\" || digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")) {\n const statusCode = digest === \"NEXT_NOT_FOUND\" ? 404 : parseInt(digest.split(\";\")[1], 10);\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(null, { status: statusCode });\n }\n }\n setHeadersContext(null);\n setNavigationContext(null);\n console.error(\"[vinext] Route handler error:\", err);\n _reportRequestError(\n err instanceof Error ? err : new Error(String(err)),\n { path: cleanPathname, method: request.method, headers: Object.fromEntries(request.headers.entries()) },\n { routerKind: \"App Router\", routePath: route.pattern, routeType: \"route\" },\n ).catch((reportErr) => {\n console.error(\"[vinext] Failed to report route handler error:\", reportErr);\n });\n return new Response(null, { status: 500 });\n }\n }\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(null, {\n status: 405,\n headers: { Allow: exportedMethods.join(\", \") },\n });\n }\n\n // Build the component tree: layouts wrapping the page\n const PageComponent = route.page?.default;\n if (!PageComponent) {\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(\"Page has no default export\", { status: 500 });\n }\n\n // Read route segment config from page module exports\n let revalidateSeconds = typeof route.page?.revalidate === \"number\" ? route.page.revalidate : null;\n const dynamicConfig = route.page?.dynamic; // 'auto' | 'force-dynamic' | 'force-static' | 'error'\n const dynamicParamsConfig = route.page?.dynamicParams; // true (default) | false\n const isForceStatic = dynamicConfig === \"force-static\";\n const isDynamicError = dynamicConfig === \"error\";\n\n // force-static: replace headers/cookies context with empty values and\n // clear searchParams so dynamic APIs return defaults instead of real data\n if (isForceStatic) {\n setHeadersContext({ headers: new Headers(), cookies: new Map() });\n setNavigationContext({\n pathname: cleanPathname,\n searchParams: new URLSearchParams(),\n params,\n });\n }\n\n // dynamic = 'error': set a trap context that throws when headers/cookies are accessed\n if (isDynamicError) {\n const errorMsg = 'Page with \\`dynamic = \"error\"\\` used a dynamic API. ' +\n 'This page was expected to be fully static, but headers(), cookies(), ' +\n 'or searchParams was accessed. Remove the dynamic API usage or change ' +\n 'the dynamic config to \"auto\" or \"force-dynamic\".';\n const throwingHeaders = new Proxy(new Headers(), {\n get(target, prop) {\n if (typeof prop === \"string\" && prop !== \"then\") throw new Error(errorMsg);\n return Reflect.get(target, prop);\n },\n });\n const throwingCookies = new Proxy(new Map(), {\n get(target, prop) {\n if (typeof prop === \"string\" && prop !== \"then\") throw new Error(errorMsg);\n return Reflect.get(target, prop);\n },\n });\n setHeadersContext({ headers: throwingHeaders, cookies: throwingCookies });\n setNavigationContext({\n pathname: cleanPathname,\n searchParams: new URLSearchParams(),\n params,\n });\n }\n\n // dynamicParams = false: only params from generateStaticParams are allowed\n if (dynamicParamsConfig === false && route.isDynamic && typeof route.page?.generateStaticParams === \"function\") {\n try {\n // Pass parent params to generateStaticParams (Next.js top-down params passing).\n // Parent params = all matched params that DON'T belong to the leaf page's own dynamic segments.\n // We pass the full matched params; the function uses only what it needs.\n const staticParams = await route.page.generateStaticParams({ params });\n if (Array.isArray(staticParams)) {\n const paramKeys = Object.keys(params);\n const isAllowed = staticParams.some(sp =>\n paramKeys.every(key => {\n const val = params[key];\n const staticVal = sp[key];\n // Allow parent params to not be in the returned set (they're inherited)\n if (staticVal === undefined) return true;\n if (Array.isArray(val)) return JSON.stringify(val) === JSON.stringify(staticVal);\n return String(val) === String(staticVal);\n })\n );\n if (!isAllowed) {\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(\"Not Found\", { status: 404 });\n }\n }\n } catch (err) {\n console.error(\"[vinext] generateStaticParams error:\", err);\n }\n }\n\n // force-dynamic: set no-store Cache-Control\n const isForceDynamic = dynamicConfig === \"force-dynamic\";\n\n // Check for intercepting routes on RSC requests (client-side navigation).\n // If the target URL matches an intercepting route in a parallel slot,\n // render the source route with the intercepting page in the slot.\n let interceptOpts = undefined;\n if (isRscRequest) {\n const intercept = findIntercept(cleanPathname);\n if (intercept) {\n const sourceRoute = routes[intercept.sourceRouteIndex];\n if (sourceRoute && sourceRoute !== route) {\n // Render the source route (e.g. /feed) with the intercepting page in the slot\n const sourceMatch = matchRoute(sourceRoute.pattern, routes);\n const sourceParams = sourceMatch ? sourceMatch.params : {};\n setNavigationContext({\n pathname: cleanPathname,\n searchParams: url.searchParams,\n params: intercept.matchedParams,\n });\n const interceptElement = await buildPageElement(sourceRoute, sourceParams, {\n interceptSlot: intercept.slotName,\n interceptPage: intercept.page,\n interceptParams: intercept.matchedParams,\n }, url.searchParams);\n const interceptStream = renderToReadableStream(interceptElement, { onError: rscOnError });\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(interceptStream, {\n headers: { \"Content-Type\": \"text/x-component; charset=utf-8\", \"Vary\": \"RSC, Accept\" },\n });\n }\n // If sourceRoute === route, apply intercept opts to the normal render\n interceptOpts = {\n interceptSlot: intercept.slotName,\n interceptPage: intercept.page,\n interceptParams: intercept.matchedParams,\n };\n }\n }\n\n let element;\n try {\n element = await buildPageElement(route, params, interceptOpts, url.searchParams);\n } catch (buildErr) {\n // Check for redirect/notFound/forbidden/unauthorized thrown during metadata resolution or async components\n if (buildErr && typeof buildErr === \"object\" && \"digest\" in buildErr) {\n const digest = String(buildErr.digest);\n if (digest.startsWith(\"NEXT_REDIRECT;\")) {\n const parts = digest.split(\";\");\n const redirectUrl = decodeURIComponent(parts[2]);\n const statusCode = parts[3] ? parseInt(parts[3], 10) : 307;\n setHeadersContext(null);\n setNavigationContext(null);\n return Response.redirect(new URL(redirectUrl, request.url), statusCode);\n }\n if (digest === \"NEXT_NOT_FOUND\" || digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")) {\n const statusCode = digest === \"NEXT_NOT_FOUND\" ? 404 : parseInt(digest.split(\";\")[1], 10);\n const fallbackResp = await renderHTTPAccessFallbackPage(route, statusCode, isRscRequest, request);\n if (fallbackResp) return fallbackResp;\n setHeadersContext(null);\n setNavigationContext(null);\n const statusText = statusCode === 403 ? \"Forbidden\" : statusCode === 401 ? \"Unauthorized\" : \"Not Found\";\n return new Response(statusText, { status: statusCode });\n }\n }\n // Non-special error (e.g. generateMetadata() threw) — render error.tsx if available\n const errorBoundaryResp = await renderErrorBoundaryPage(route, buildErr, isRscRequest, request);\n if (errorBoundaryResp) return errorBoundaryResp;\n throw buildErr;\n }\n\n // Note: CSS is automatically injected by @vitejs/plugin-rsc's\n // rscCssTransform — no manual loadCss() call needed.\n\n // Helper: check if an error is a redirect/notFound/forbidden/unauthorized thrown by the navigation shim\n async function handleRenderError(err) {\n if (err && typeof err === \"object\" && \"digest\" in err) {\n const digest = String(err.digest);\n if (digest.startsWith(\"NEXT_REDIRECT;\")) {\n const parts = digest.split(\";\");\n const redirectUrl = decodeURIComponent(parts[2]);\n const statusCode = parts[3] ? parseInt(parts[3], 10) : 307;\n setHeadersContext(null);\n setNavigationContext(null);\n return Response.redirect(new URL(redirectUrl, request.url), statusCode);\n }\n if (digest === \"NEXT_NOT_FOUND\" || digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")) {\n const statusCode = digest === \"NEXT_NOT_FOUND\" ? 404 : parseInt(digest.split(\";\")[1], 10);\n const fallbackResp = await renderHTTPAccessFallbackPage(route, statusCode, isRscRequest, request);\n if (fallbackResp) return fallbackResp;\n setHeadersContext(null);\n setNavigationContext(null);\n const statusText = statusCode === 403 ? \"Forbidden\" : statusCode === 401 ? \"Unauthorized\" : \"Not Found\";\n return new Response(statusText, { status: statusCode });\n }\n }\n return null;\n }\n\n // Pre-render layout components to catch notFound()/redirect() thrown from layouts.\n // In Next.js, each layout level has its own NotFoundBoundary. When a layout throws\n // notFound(), the parent layout's boundary catches it and renders the parent's\n // not-found.tsx. Since React Flight doesn't activate client error boundaries during\n // RSC rendering, we catch layout-level throws here and render the appropriate\n // fallback page with only the layouts above the throwing one.\n //\n // IMPORTANT: Layout pre-render runs BEFORE page pre-render. In Next.js, layouts\n // render before their children — if a layout throws notFound(), the page never\n // executes. By checking layouts first, we avoid a bug where the page's notFound()\n // triggers renderHTTPAccessFallbackPage with ALL route layouts, but one of those\n // layouts itself throws notFound() during the fallback rendering (causing a 500).\n if (route.layouts && route.layouts.length > 0) {\n const asyncParams = makeThenableParams(params);\n for (let li = route.layouts.length - 1; li >= 0; li--) {\n const LayoutComp = route.layouts[li]?.default;\n if (!LayoutComp) continue;\n try {\n const lr = LayoutComp({ params: asyncParams, children: null });\n if (lr && typeof lr === \"object\" && typeof lr.then === \"function\") await lr;\n } catch (layoutErr) {\n if (layoutErr && typeof layoutErr === \"object\" && \"digest\" in layoutErr) {\n const digest = String(layoutErr.digest);\n if (digest.startsWith(\"NEXT_REDIRECT;\")) {\n const parts = digest.split(\";\");\n const redirectUrl = decodeURIComponent(parts[2]);\n const statusCode = parts[3] ? parseInt(parts[3], 10) : 307;\n setHeadersContext(null);\n setNavigationContext(null);\n return Response.redirect(new URL(redirectUrl, request.url), statusCode);\n }\n if (digest === \"NEXT_NOT_FOUND\" || digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")) {\n const statusCode = digest === \"NEXT_NOT_FOUND\" ? 404 : parseInt(digest.split(\";\")[1], 10);\n // Find the not-found component from the parent level (the boundary that\n // would catch this in Next.js). Walk up from the throwing layout to find\n // the nearest not-found at a parent layout's directory.\n let parentNotFound = null;\n if (route.notFounds) {\n for (let pi = li - 1; pi >= 0; pi--) {\n if (route.notFounds[pi]?.default) {\n parentNotFound = route.notFounds[pi].default;\n break;\n }\n }\n }\n if (!parentNotFound) parentNotFound = ${rootNotFoundVar ? `${rootNotFoundVar}?.default` : \"null\"};\n // Wrap in only the layouts above the throwing one\n const parentLayouts = route.layouts.slice(0, li);\n const fallbackResp = await renderHTTPAccessFallbackPage(\n route, statusCode, isRscRequest, request,\n { boundaryComponent: parentNotFound, layouts: parentLayouts }\n );\n if (fallbackResp) return fallbackResp;\n setHeadersContext(null);\n setNavigationContext(null);\n const statusText = statusCode === 403 ? \"Forbidden\" : statusCode === 401 ? \"Unauthorized\" : \"Not Found\";\n return new Response(statusText, { status: statusCode });\n }\n }\n // Not a special error — let it propagate through normal RSC rendering\n }\n }\n }\n\n // Pre-render the page component to catch redirect()/notFound() thrown synchronously.\n // Server Components are just functions — we can call PageComponent directly to detect\n // these special throws before starting the RSC stream.\n //\n // For routes with a loading.tsx Suspense boundary, we skip awaiting async components.\n // The Suspense boundary + rscOnError will handle redirect/notFound thrown during\n // streaming, and blocking here would defeat streaming (the slow component's delay\n // would be hit before the RSC stream even starts).\n //\n // Because this calls the component outside React's render cycle, hooks like use()\n // trigger \"Invalid hook call\" console.error in dev. Suppress that expected warning.\n const _hasLoadingBoundary = !!(route.loading && route.loading.default);\n const _origConsoleError = console.error;\n console.error = (...args) => {\n if (typeof args[0] === \"string\" && args[0].includes(\"Invalid hook call\")) return;\n _origConsoleError.apply(console, args);\n };\n try {\n const testResult = PageComponent({ params });\n // If it's a promise (async component), only await if there's no loading boundary.\n // With a loading boundary, the Suspense streaming pipeline handles async resolution\n // and any redirect/notFound errors via rscOnError.\n if (testResult && typeof testResult === \"object\" && typeof testResult.then === \"function\") {\n if (!_hasLoadingBoundary) {\n await testResult;\n } else {\n // Suppress unhandled promise rejection — with a loading boundary,\n // redirect/notFound errors are handled by rscOnError during streaming.\n testResult.catch(() => {});\n }\n }\n } catch (preRenderErr) {\n const specialResponse = await handleRenderError(preRenderErr);\n if (specialResponse) return specialResponse;\n // Non-special errors from the pre-render test are expected (e.g. use() hook\n // fails outside React's render cycle, client references can't execute on server).\n // Only redirect/notFound/forbidden/unauthorized are actionable here — other\n // errors will be properly caught during actual RSC/SSR rendering below.\n } finally {\n console.error = _origConsoleError;\n }\n\n // Render to RSC stream\n const rscStream = renderToReadableStream(element, { onError: rscOnError });\n\n if (isRscRequest) {\n // Direct RSC stream response (for client-side navigation)\n // NOTE: Do NOT clear headers/navigation context here!\n // The RSC stream is consumed lazily - components render when chunks are read.\n // If we clear context now, headers()/cookies() will fail during rendering.\n // Context will be cleared when the next request starts (via runWithHeadersContext).\n const responseHeaders = { \"Content-Type\": \"text/x-component; charset=utf-8\", \"Vary\": \"RSC, Accept\" };\n // Include matched route params so the client can hydrate useParams()\n if (params && Object.keys(params).length > 0) {\n responseHeaders[\"X-Vinext-Params\"] = JSON.stringify(params);\n }\n if (isForceDynamic) {\n responseHeaders[\"Cache-Control\"] = \"no-store, must-revalidate\";\n } else if ((isForceStatic || isDynamicError) && !revalidateSeconds) {\n responseHeaders[\"Cache-Control\"] = \"s-maxage=31536000, stale-while-revalidate\";\n responseHeaders[\"X-Vinext-Cache\"] = \"STATIC\";\n } else if (revalidateSeconds) {\n responseHeaders[\"Cache-Control\"] = \"s-maxage=\" + revalidateSeconds + \", stale-while-revalidate\";\n }\n // Merge middleware response headers into the RSC response\n if (_middlewareResponseHeaders) {\n for (const [key, value] of _middlewareResponseHeaders) {\n responseHeaders[key] = value;\n }\n }\n return new Response(rscStream, { status: _middlewareRewriteStatus || 200, headers: responseHeaders });\n }\n\n // Collect font data from RSC environment before passing to SSR\n // (Fonts are loaded during RSC rendering when layout.tsx calls Geist() etc.)\n const fontData = {\n links: _getSSRFontLinks(),\n styles: _getSSRFontStyles(),\n preloads: _getSSRFontPreloads(),\n };\n\n // Build HTTP Link header for font preloading.\n // This lets the browser (and CDN) start fetching font files before parsing HTML,\n // eliminating the CSS → woff2 download waterfall.\n const fontPreloads = fontData.preloads || [];\n const fontLinkHeaderParts = [];\n for (const preload of fontPreloads) {\n fontLinkHeaderParts.push(\"<\" + preload.href + \">; rel=preload; as=font; type=\" + preload.type + \"; crossorigin\");\n }\n const fontLinkHeader = fontLinkHeaderParts.length > 0 ? fontLinkHeaderParts.join(\", \") : \"\";\n\n // Delegate to SSR environment for HTML rendering\n let htmlStream;\n try {\n const ssrEntry = await import.meta.viteRsc.loadModule(\"ssr\", \"index\");\n htmlStream = await ssrEntry.handleSsr(rscStream, _getNavigationContext(), fontData);\n } catch (ssrErr) {\n const specialResponse = await handleRenderError(ssrErr);\n if (specialResponse) return specialResponse;\n // Non-special error during SSR — render error.tsx if available\n const errorBoundaryResp = await renderErrorBoundaryPage(route, ssrErr, isRscRequest, request);\n if (errorBoundaryResp) return errorBoundaryResp;\n throw ssrErr;\n }\n\n // Check for draftMode Set-Cookie header (from draftMode().enable()/disable())\n const draftCookie = getDraftModeCookieHeader();\n\n setHeadersContext(null);\n setNavigationContext(null);\n\n // Helper to attach draftMode cookie, middleware headers, font Link header, and rewrite status to a response\n function attachMiddlewareContext(response) {\n if (draftCookie) {\n response.headers.append(\"Set-Cookie\", draftCookie);\n }\n // Set HTTP Link header for font preloading\n if (fontLinkHeader) {\n response.headers.set(\"Link\", fontLinkHeader);\n }\n // Merge middleware response headers into the final response\n if (_middlewareResponseHeaders) {\n for (const [key, value] of _middlewareResponseHeaders) {\n response.headers.append(key, value);\n }\n }\n // Apply custom status code from middleware rewrite\n if (_middlewareRewriteStatus) {\n return new Response(response.body, {\n status: _middlewareRewriteStatus,\n headers: response.headers,\n });\n }\n return response;\n }\n\n // Check if any component called connection(), cookies(), headers(), or noStore()\n // during rendering. If so, treat as dynamic (skip ISR, set no-store).\n const dynamicUsedDuringRender = consumeDynamicUsage();\n\n // Check if cacheLife() was called during rendering (e.g., page with file-level \"use cache\").\n // If so, use its revalidation period for the Cache-Control header.\n const requestCacheLife = _consumeRequestScopedCacheLife();\n if (requestCacheLife && requestCacheLife.revalidate !== undefined && revalidateSeconds === null) {\n revalidateSeconds = requestCacheLife.revalidate;\n }\n\n // force-dynamic: always return no-store (highest priority)\n if (isForceDynamic) {\n return attachMiddlewareContext(new Response(htmlStream, {\n headers: {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store, must-revalidate\",\n \"Vary\": \"RSC, Accept\",\n },\n }));\n }\n\n // force-static / error: treat as static regardless of dynamic usage.\n // force-static intentionally provides empty headers/cookies context so\n // dynamic APIs return safe defaults; we ignore the dynamic usage signal.\n // dynamic='error' should have already thrown (via throwing Proxy) if user\n // code accessed dynamic APIs, so reaching here means rendering succeeded.\n if ((isForceStatic || isDynamicError) && (revalidateSeconds === null || revalidateSeconds === 0)) {\n return attachMiddlewareContext(new Response(htmlStream, {\n headers: {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"s-maxage=31536000, stale-while-revalidate\",\n \"X-Vinext-Cache\": \"STATIC\",\n \"Vary\": \"RSC, Accept\",\n },\n }));\n }\n\n // auto mode: dynamic API usage (headers(), cookies(), connection(), noStore(),\n // searchParams access) opts the page into dynamic rendering with no-store.\n if (dynamicUsedDuringRender) {\n return attachMiddlewareContext(new Response(htmlStream, {\n headers: {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store, must-revalidate\",\n \"Vary\": \"RSC, Accept\",\n },\n }));\n }\n\n // Emit Cache-Control for ISR pages so tests can verify revalidate values,\n // but skip actual caching in dev — every request renders fresh.\n if (revalidateSeconds !== null && revalidateSeconds > 0) {\n return attachMiddlewareContext(new Response(htmlStream, {\n headers: {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"s-maxage=\" + revalidateSeconds + \", stale-while-revalidate\",\n \"Vary\": \"RSC, Accept\",\n },\n }));\n }\n\n return attachMiddlewareContext(new Response(htmlStream, {\n headers: { \"Content-Type\": \"text/html; charset=utf-8\", \"Vary\": \"RSC, Accept\" },\n }));\n}\n\nif (import.meta.hot) {\n import.meta.hot.accept();\n}\n`;\n}\n\n/**\n * Generate the virtual SSR entry module.\n *\n * This runs in the `ssr` Vite environment. It receives an RSC stream,\n * deserializes it to a React tree, and renders to HTML.\n */\nexport function generateSsrEntry(): string {\n return `\nimport { createFromReadableStream } from \"@vitejs/plugin-rsc/ssr\";\nimport { renderToReadableStream, renderToStaticMarkup } from \"react-dom/server.edge\";\nimport { setNavigationContext, ServerInsertedHTMLContext } from \"next/navigation\";\nimport { runWithNavigationContext as _runWithNavCtx } from \"vinext/navigation-state\";\nimport { safeJsonStringify } from \"vinext/html\";\nimport { createElement as _ssrCE } from \"react\";\n\n/**\n * Collect all chunks from a ReadableStream into an array of text strings.\n * Used to capture the RSC payload for embedding in HTML.\n * The RSC flight protocol is text-based (line-delimited key:value pairs),\n * so we decode to text strings instead of byte arrays — this is dramatically\n * more compact when JSON-serialized into inline <script> tags.\n */\nasync function collectStreamChunks(stream) {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n const chunks = [];\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n // Decode Uint8Array to text string for compact JSON serialization\n chunks.push(decoder.decode(value, { stream: true }));\n }\n return chunks;\n}\n\n// React 19 dev-mode workaround (see VinextFlightRoot in handleSsr):\n//\n// In dev, Flight error decoding in react-server-dom-webpack/client.edge\n// can hit resolveErrorDev() which (via React's dev error stack capture)\n// expects a non-null hooks dispatcher.\n//\n// Vinext previously called createFromReadableStream() outside of any React render.\n// When an RSC stream contains an error, dev-mode decoding could crash with:\n// - \"Invalid hook call\"\n// - \"Cannot read properties of null (reading 'useContext')\"\n//\n// Fix: call createFromReadableStream() lazily inside a React component render.\n// This mirrors Next.js behavior and ensures the dispatcher is set.\n\n/**\n * Create a TransformStream that appends RSC chunks as inline <script> tags\n * to the HTML stream. This allows progressive hydration — the browser receives\n * RSC data incrementally as Suspense boundaries resolve, rather than waiting\n * for the entire RSC payload before hydration can begin.\n *\n * Each chunk is written as:\n * <script>self.__VINEXT_RSC_CHUNKS__=self.__VINEXT_RSC_CHUNKS__||[];self.__VINEXT_RSC_CHUNKS__.push(\"...\")</script>\n *\n * Chunks are embedded as text strings (not byte arrays) since the RSC flight\n * protocol is text-based. The browser entry encodes them back to Uint8Array.\n * This is ~3x more compact than the previous byte-array format.\n */\nfunction createRscEmbedTransform(embedStream) {\n const reader = embedStream.getReader();\n const _decoder = new TextDecoder();\n let done = false;\n let pendingChunks = [];\n let reading = false;\n\n // Fix invalid preload \"as\" values in RSC Flight hint lines before\n // they reach the client. React Flight emits HL hints with\n // as=\"stylesheet\" for CSS, but the HTML spec requires as=\"style\"\n // for <link rel=\"preload\">. The fixPreloadAs() below only fixes the\n // server-rendered HTML stream; this fixes the raw Flight data that\n // gets embedded as __VINEXT_RSC_CHUNKS__ and processed client-side.\n function fixFlightHints(text) {\n // Flight hint format: <id>:HL[\"url\",\"stylesheet\"] or with options\n return text.replace(/(\\\\d+:HL\\\\[.*?),\"stylesheet\"(\\\\]|,)/g, '$1,\"style\"$2');\n }\n\n // Start reading RSC chunks in the background, accumulating them as text strings.\n // The RSC flight protocol is text-based, so decoding to strings and embedding\n // as JSON strings is ~3x more compact than the byte-array format.\n async function pumpReader() {\n if (reading) return;\n reading = true;\n try {\n while (true) {\n const result = await reader.read();\n if (result.done) {\n done = true;\n break;\n }\n const text = _decoder.decode(result.value, { stream: true });\n pendingChunks.push(fixFlightHints(text));\n }\n } catch (err) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[vinext] RSC embed stream read error:\", err);\n }\n done = true;\n }\n reading = false;\n }\n\n // Fire off the background reader immediately\n const pumpPromise = pumpReader();\n\n return {\n /**\n * Flush any accumulated RSC chunks as <script> tags.\n * Called after each HTML chunk is enqueued.\n */\n flush() {\n if (pendingChunks.length === 0) return \"\";\n const chunks = pendingChunks;\n pendingChunks = [];\n let scripts = \"\";\n for (const chunk of chunks) {\n scripts += \"<script>self.__VINEXT_RSC_CHUNKS__=self.__VINEXT_RSC_CHUNKS__||[];self.__VINEXT_RSC_CHUNKS__.push(\" + safeJsonStringify(chunk) + \")</script>\";\n }\n return scripts;\n },\n\n /**\n * Wait for the RSC stream to fully complete and return any final\n * script tags plus the closing signal.\n */\n async finalize() {\n await pumpPromise;\n let scripts = this.flush();\n // Signal that all RSC chunks have been sent.\n // Params are already embedded in <head> — no need to include here.\n scripts += \"<script>self.__VINEXT_RSC_DONE__=true</script>\";\n return scripts;\n },\n };\n}\n\n/**\n * Render the RSC stream to HTML.\n *\n * @param rscStream - The RSC payload stream from the RSC environment\n * @param navContext - Navigation context for client component SSR hooks.\n * \"use client\" components like those using usePathname() need the current\n * request URL during SSR, and they run in this SSR environment (separate\n * from the RSC environment where the context was originally set).\n * @param fontData - Font links and styles collected from the RSC environment.\n * Fonts are loaded during RSC rendering (when layout calls Geist() etc.),\n * and the data needs to be passed to SSR since they're separate module instances.\n */\nexport async function handleSsr(rscStream, navContext, fontData) {\n // Wrap in a navigation ALS scope for per-request isolation in the SSR\n // environment. The SSR environment has separate module instances from RSC,\n // so it needs its own ALS scope.\n return _runWithNavCtx(async () => {\n // Set navigation context so hooks like usePathname() work during SSR\n // of \"use client\" components\n if (navContext) {\n setNavigationContext(navContext);\n }\n\n // Clear any stale callbacks from previous requests\n const { clearServerInsertedHTML, flushServerInsertedHTML, useServerInsertedHTML: _addInsertedHTML } = await import(\"next/navigation\");\n clearServerInsertedHTML();\n\n try {\n // Tee the RSC stream - one for SSR rendering, one for embedding in HTML.\n // This ensures the browser uses the SAME RSC payload for hydration that\n // was used to generate the HTML, avoiding hydration mismatches (React #418).\n const [ssrStream, embedStream] = rscStream.tee();\n\n // Create the progressive RSC embed helper — it reads the embed stream\n // in the background and provides script tags to inject into the HTML stream.\n const rscEmbed = createRscEmbedTransform(embedStream);\n\n // Deserialize RSC stream back to React VDOM.\n // IMPORTANT: Do NOT await this — createFromReadableStream returns a thenable\n // that React's renderToReadableStream can consume progressively. By passing\n // the unresolved thenable, React will render Suspense fallbacks (loading.tsx)\n // immediately in the HTML shell, then stream in resolved content as RSC\n // chunks arrive. Awaiting here would block until all async server components\n // complete, collapsing the streaming behavior.\n // Lazily create the Flight root inside render so React's hook dispatcher is set\n // (avoids React 19 dev-mode resolveErrorDev() crash). VinextFlightRoot returns\n // a thenable (not a ReactNode), which React 19 consumes via its internal\n // thenable-as-child suspend/resume behavior. This matches Next.js's approach.\n let flightRoot;\n function VinextFlightRoot() {\n if (!flightRoot) {\n flightRoot = createFromReadableStream(ssrStream);\n }\n return flightRoot;\n }\n const root = _ssrCE(VinextFlightRoot);\n\n // Wrap with ServerInsertedHTMLContext.Provider so libraries that use\n // useContext(ServerInsertedHTMLContext) (Apollo Client, styled-components,\n // etc.) get a working callback registration function during SSR.\n // The provider value is useServerInsertedHTML — same function that direct\n // callers use — so both paths push to the same ALS-backed callback array.\n const ssrRoot = ServerInsertedHTMLContext\n ? _ssrCE(ServerInsertedHTMLContext.Provider, { value: _addInsertedHTML }, root)\n : root;\n\n // Get the bootstrap script content for the browser entry\n const bootstrapScriptContent =\n await import.meta.viteRsc.loadBootstrapScriptContent(\"index\");\n\n // djb2 hash for digest generation in the SSR environment.\n // Matches the RSC environment's __errorDigest function.\n function ssrErrorDigest(str) {\n let hash = 5381;\n for (let i = str.length - 1; i >= 0; i--) {\n hash = (hash * 33) ^ str.charCodeAt(i);\n }\n return (hash >>> 0).toString();\n }\n\n // Render HTML (streaming SSR)\n // useServerInsertedHTML callbacks are registered during this render.\n // The onError callback preserves the digest for Next.js navigation errors\n // (redirect, notFound, forbidden, unauthorized) thrown inside Suspense\n // boundaries during RSC streaming. Without this, React's default onError\n // returns undefined and the digest is lost in the $RX() call, preventing\n // client-side error boundaries from identifying the error type.\n // In production, non-navigation errors also get a digest hash so they\n // can be correlated with server logs without leaking details to clients.\n const htmlStream = await renderToReadableStream(ssrRoot, {\n bootstrapScriptContent,\n onError(error) {\n if (error && typeof error === \"object\" && \"digest\" in error) {\n return String(error.digest);\n }\n // In production, generate a digest hash for non-navigation errors\n if (process.env.NODE_ENV === \"production\" && error) {\n const msg = error instanceof Error ? error.message : String(error);\n const stack = error instanceof Error ? (error.stack || \"\") : \"\";\n return ssrErrorDigest(msg + stack);\n }\n return undefined;\n },\n });\n\n\n // Flush useServerInsertedHTML callbacks (CSS-in-JS style injection)\n const insertedElements = flushServerInsertedHTML();\n\n // Render the inserted elements to HTML strings\n const { Fragment } = await import(\"react\");\n let insertedHTML = \"\";\n for (const el of insertedElements) {\n try {\n insertedHTML += renderToStaticMarkup(_ssrCE(Fragment, null, el));\n } catch {\n // Skip elements that can't be rendered\n }\n }\n\n // Escape HTML attribute values (defense-in-depth for font URLs/types).\n function _escAttr(s) { return s.replace(/&/g, \"&\").replace(/\"/g, \""\"); }\n\n // Build font HTML from data passed from RSC environment\n // (Fonts are loaded during RSC rendering, and RSC/SSR are separate module instances)\n let fontHTML = \"\";\n if (fontData) {\n if (fontData.links && fontData.links.length > 0) {\n for (const url of fontData.links) {\n fontHTML += '<link rel=\"stylesheet\" href=\"' + _escAttr(url) + '\" />\\\\n';\n }\n }\n // Emit <link rel=\"preload\"> for local font files\n if (fontData.preloads && fontData.preloads.length > 0) {\n for (const preload of fontData.preloads) {\n fontHTML += '<link rel=\"preload\" href=\"' + _escAttr(preload.href) + '\" as=\"font\" type=\"' + _escAttr(preload.type) + '\" crossorigin />\\\\n';\n }\n }\n if (fontData.styles && fontData.styles.length > 0) {\n fontHTML += '<style data-vinext-fonts>' + fontData.styles.join(\"\\\\n\") + '</style>\\\\n';\n }\n }\n\n // Extract client entry module URL from bootstrapScriptContent to emit\n // a <link rel=\"modulepreload\"> hint. The RSC plugin formats bootstrap\n // content as: import(\"URL\") — we extract the URL so the browser can\n // speculatively fetch and parse the JS module while still processing\n // the HTML body, instead of waiting until it reaches the inline script.\n let modulePreloadHTML = \"\";\n if (bootstrapScriptContent) {\n const m = bootstrapScriptContent.match(/import\\\\(\"([^\"]+)\"\\\\)/);\n if (m && m[1]) {\n modulePreloadHTML = '<link rel=\"modulepreload\" href=\"' + _escAttr(m[1]) + '\" />\\\\n';\n }\n }\n\n // Head-injected HTML: server-inserted HTML, font HTML, route params,\n // and modulepreload hints.\n // RSC payload is now embedded progressively via script tags in the body stream.\n // Params are embedded eagerly in <head> so they're available before client\n // hydration starts, avoiding the need for polling on the client.\n const paramsScript = '<script>self.__VINEXT_RSC_PARAMS__=' + safeJsonStringify(navContext?.params || {}) + '</script>';\n const injectHTML = paramsScript + modulePreloadHTML + insertedHTML + fontHTML;\n\n // Inject the collected HTML before </head> and progressively embed RSC\n // chunks as script tags throughout the HTML body stream.\n const decoder = new TextDecoder();\n const encoder = new TextEncoder();\n let injected = false;\n\n // Fix invalid preload \"as\" values in server-rendered HTML.\n // React Fizz emits <link rel=\"preload\" as=\"stylesheet\"> for CSS,\n // but the HTML spec requires as=\"style\" for <link rel=\"preload\">.\n // Note: fixFlightHints() in createRscEmbedTransform handles the\n // complementary case — fixing the raw Flight stream data before\n // it's embedded as __VINEXT_RSC_CHUNKS__ for client-side processing.\n // See: https://html.spec.whatwg.org/multipage/links.html#link-type-preload\n function fixPreloadAs(html) {\n // Match <link ...rel=\"preload\"... as=\"stylesheet\"...> in any attribute order\n return html.replace(/<link(?=[^>]*\\\\srel=\"preload\")[^>]*>/g, function(tag) {\n return tag.replace(' as=\"stylesheet\"', ' as=\"style\"');\n });\n }\n\n // Tick-buffered RSC script injection.\n //\n // React's renderToReadableStream (Fizz) flushes chunks synchronously\n // within one microtask — all chunks from a single flushCompletedQueues\n // call arrive in the same macrotask. We buffer HTML chunks as they\n // arrive, then use setTimeout(0) to defer emitting them plus any\n // accumulated RSC scripts to the next macrotask. This guarantees we\n // never inject <script> tags between partial HTML chunks (which would\n // corrupt split elements like \"<linearGradi\" + \"ent>\"), while still\n // delivering RSC data progressively as Suspense boundaries resolve.\n //\n // Reference: rsc-html-stream by Devon Govett (credited by Next.js)\n // https://github.com/devongovett/rsc-html-stream\n let buffered = [];\n let timeoutId = null;\n\n const transform = new TransformStream({\n transform(chunk, controller) {\n const text = decoder.decode(chunk, { stream: true });\n const fixed = fixPreloadAs(text);\n buffered.push(fixed);\n\n if (timeoutId !== null) return;\n\n timeoutId = setTimeout(() => {\n // Flush all buffered HTML chunks from this React flush cycle\n for (const buf of buffered) {\n if (!injected) {\n const headEnd = buf.indexOf(\"</head>\");\n if (headEnd !== -1) {\n const before = buf.slice(0, headEnd);\n const after = buf.slice(headEnd);\n controller.enqueue(encoder.encode(before + injectHTML + after));\n injected = true;\n continue;\n }\n }\n controller.enqueue(encoder.encode(buf));\n }\n buffered = [];\n\n // Now safe to inject any accumulated RSC scripts — we're between\n // React flush cycles, so no partial HTML chunks can follow until\n // the next macrotask.\n const rscScripts = rscEmbed.flush();\n if (rscScripts) {\n controller.enqueue(encoder.encode(rscScripts));\n }\n\n timeoutId = null;\n }, 0);\n },\n async flush(controller) {\n // Cancel any pending setTimeout callback — flush() drains\n // everything itself, so the callback would be a no-op but\n // cancelling makes the code obviously correct.\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n // Flush any remaining buffered HTML chunks\n for (const buf of buffered) {\n if (!injected) {\n const headEnd = buf.indexOf(\"</head>\");\n if (headEnd !== -1) {\n const before = buf.slice(0, headEnd);\n const after = buf.slice(headEnd);\n controller.enqueue(encoder.encode(before + injectHTML + after));\n injected = true;\n continue;\n }\n }\n controller.enqueue(encoder.encode(buf));\n }\n buffered = [];\n\n if (!injected && injectHTML) {\n controller.enqueue(encoder.encode(injectHTML));\n }\n // Finalize: wait for the RSC stream to complete and emit remaining\n // chunks plus the __VINEXT_RSC_DONE__ signal.\n const finalScripts = await rscEmbed.finalize();\n if (finalScripts) {\n controller.enqueue(encoder.encode(finalScripts));\n }\n },\n });\n\n return htmlStream.pipeThrough(transform);\n } finally {\n // Clean up so we don't leak context between requests\n setNavigationContext(null);\n clearServerInsertedHTML();\n }\n }); // end _runWithNavCtx\n}\n\nexport default {\n async fetch(request) {\n const url = new URL(request.url);\n if (url.pathname.startsWith(\"//\")) {\n return new Response(\"404 Not Found\", { status: 404 });\n }\n const rscModule = await import.meta.viteRsc.loadModule(\"rsc\", \"index\");\n const result = await rscModule.default(request);\n if (result instanceof Response) {\n return result;\n }\n if (result === null || result === undefined) {\n return new Response(\"Not Found\", { status: 404 });\n }\n return new Response(String(result), { status: 200 });\n },\n};\n`;\n}\n\n/**\n * Generate the virtual browser entry module.\n *\n * This runs in the client (browser). It hydrates the page from the\n * embedded RSC payload and handles client-side navigation by re-fetching\n * RSC streams.\n */\nexport function generateBrowserEntry(): string {\n return `\nimport {\n createFromReadableStream,\n createFromFetch,\n setServerCallback,\n encodeReply,\n createTemporaryReferenceSet,\n} from \"@vitejs/plugin-rsc/browser\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport { flushSync } from \"react-dom\";\nimport { setClientParams, toRscUrl, getPrefetchCache, getPrefetchedUrls, PREFETCH_CACHE_TTL } from \"next/navigation\";\n\nlet reactRoot;\n\n/**\n * Convert the embedded RSC chunks back to a ReadableStream.\n * Each chunk is a text string that needs to be encoded back to Uint8Array.\n */\nfunction chunksToReadableStream(chunks) {\n const encoder = new TextEncoder();\n return new ReadableStream({\n start(controller) {\n for (const chunk of chunks) {\n controller.enqueue(encoder.encode(chunk));\n }\n controller.close();\n }\n });\n}\n\n/**\n * Create a ReadableStream from progressively-embedded RSC chunks.\n * The server injects RSC data as <script> tags that push to\n * self.__VINEXT_RSC_CHUNKS__ throughout the HTML stream, and sets\n * self.__VINEXT_RSC_DONE__ = true when complete.\n *\n * Instead of polling with setTimeout, we monkey-patch the array's\n * push() method so new chunks are delivered immediately when the\n * server's <script> tags execute. This eliminates unnecessary\n * wakeups and reduces latency — same pattern Next.js uses with\n * __next_f. The stream closes on DOMContentLoaded (when all\n * server-injected scripts have executed) or when __VINEXT_RSC_DONE__\n * is set, whichever comes first.\n */\nfunction createProgressiveRscStream() {\n const encoder = new TextEncoder();\n return new ReadableStream({\n start(controller) {\n const chunks = self.__VINEXT_RSC_CHUNKS__ || [];\n\n // Deliver any chunks that arrived before this code ran\n // (from <script> tags that executed before the browser entry loaded)\n for (const chunk of chunks) {\n controller.enqueue(encoder.encode(chunk));\n }\n\n // If the stream is already complete, close immediately\n if (self.__VINEXT_RSC_DONE__) {\n controller.close();\n return;\n }\n\n // Monkey-patch push() so future chunks stream in immediately\n // when the server's <script> tags execute\n let closed = false;\n function closeOnce() {\n if (!closed) {\n closed = true;\n controller.close();\n }\n }\n\n const arr = self.__VINEXT_RSC_CHUNKS__ = self.__VINEXT_RSC_CHUNKS__ || [];\n arr.push = function(chunk) {\n Array.prototype.push.call(this, chunk);\n if (!closed) {\n controller.enqueue(encoder.encode(chunk));\n if (self.__VINEXT_RSC_DONE__) {\n closeOnce();\n }\n }\n return this.length;\n };\n\n // Safety net: if the server crashes mid-stream and __VINEXT_RSC_DONE__\n // never arrives, close the stream when all server-injected scripts\n // have executed (DOMContentLoaded). Without this, a truncated response\n // leaves the ReadableStream open forever, hanging hydration.\n if (typeof document !== \"undefined\") {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", closeOnce);\n } else {\n // Document already loaded — close immediately if not already done\n closeOnce();\n }\n }\n }\n });\n}\n\n// Register the server action callback — React calls this internally\n// when a \"use server\" function is invoked from client code.\nsetServerCallback(async (id, args) => {\n const temporaryReferences = createTemporaryReferenceSet();\n const body = await encodeReply(args, { temporaryReferences });\n\n const fetchResponse = await fetch(toRscUrl(window.location.pathname + window.location.search), {\n method: \"POST\",\n headers: { \"x-rsc-action\": id },\n body,\n });\n\n // Check for redirect signal from server action that called redirect()\n const actionRedirect = fetchResponse.headers.get(\"x-action-redirect\");\n if (actionRedirect) {\n // External URLs (different origin) need a hard redirect — client-side\n // RSC navigation only works for same-origin paths.\n try {\n const redirectUrl = new URL(actionRedirect, window.location.origin);\n if (redirectUrl.origin !== window.location.origin) {\n window.location.href = actionRedirect;\n return undefined;\n }\n } catch {\n // If URL parsing fails, fall through to client-side navigation\n }\n\n // Navigate to the redirect target using client-side navigation\n const redirectType = fetchResponse.headers.get(\"x-action-redirect-type\") || \"replace\";\n if (redirectType === \"push\") {\n window.history.pushState(null, \"\", actionRedirect);\n } else {\n window.history.replaceState(null, \"\", actionRedirect);\n }\n // Trigger RSC navigation to the redirect target\n if (typeof window.__VINEXT_RSC_NAVIGATE__ === \"function\") {\n window.__VINEXT_RSC_NAVIGATE__(actionRedirect);\n }\n return undefined;\n }\n\n const result = await createFromFetch(Promise.resolve(fetchResponse), { temporaryReferences });\n\n // The RSC response for actions contains { root, returnValue }.\n // Re-render the page with the updated tree.\n if (result && typeof result === \"object\" && \"root\" in result) {\n reactRoot.render(result.root);\n // Return the action's return value to the caller\n if (result.returnValue) {\n if (!result.returnValue.ok) throw result.returnValue.data;\n return result.returnValue.data;\n }\n return undefined;\n }\n\n // Fallback: render the entire result as the tree\n reactRoot.render(result);\n return result;\n});\n\nasync function main() {\n let rscStream;\n\n // Use embedded RSC data for initial hydration if available.\n // This ensures we use the SAME RSC payload that generated the HTML,\n // avoiding hydration mismatches (React error #418).\n //\n // The server embeds RSC chunks progressively as <script> tags that push\n // to self.__VINEXT_RSC_CHUNKS__. When complete, self.__VINEXT_RSC_DONE__\n // is set and self.__VINEXT_RSC_PARAMS__ contains route params.\n // For backwards compat, also check the legacy self.__VINEXT_RSC__ format.\n if (self.__VINEXT_RSC_CHUNKS__ || self.__VINEXT_RSC_DONE__ || self.__VINEXT_RSC__) {\n if (self.__VINEXT_RSC__) {\n // Legacy format: single object with all chunks\n const embedData = self.__VINEXT_RSC__;\n delete self.__VINEXT_RSC__;\n if (embedData.params) {\n setClientParams(embedData.params);\n }\n rscStream = chunksToReadableStream(embedData.rsc);\n } else {\n // Progressive format: chunks arrive incrementally via script tags.\n // Params are embedded in <head> so they're always available by this point.\n if (self.__VINEXT_RSC_PARAMS__) {\n setClientParams(self.__VINEXT_RSC_PARAMS__);\n }\n rscStream = createProgressiveRscStream();\n }\n } else {\n // Fallback: fetch fresh RSC (shouldn't happen on initial page load)\n const rscResponse = await fetch(toRscUrl(window.location.pathname + window.location.search));\n\n // Hydrate useParams() with route params from the server before React hydration\n const paramsHeader = rscResponse.headers.get(\"X-Vinext-Params\");\n if (paramsHeader) {\n try { setClientParams(JSON.parse(paramsHeader)); } catch (_e) { /* ignore */ }\n }\n\n rscStream = rscResponse.body;\n }\n\n const root = await createFromReadableStream(rscStream);\n\n // Hydrate the document\n // In development, suppress Vite's error overlay for errors caught by React error\n // boundaries. Without this, React re-throws caught errors to the global handler,\n // which triggers Vite's overlay even though the error was handled by an error.tsx.\n // In production, preserve React's default onCaughtError (console.error) so\n // boundary-caught errors remain visible to error monitoring.\n reactRoot = hydrateRoot(document, root, import.meta.env.DEV ? {\n onCaughtError: function() {},\n } : undefined);\n\n // Store for client-side navigation\n window.__VINEXT_RSC_ROOT__ = reactRoot;\n\n // Client-side navigation handler\n // Checks the prefetch cache (populated by <Link> IntersectionObserver and\n // router.prefetch()) before making a network request. This makes navigation\n // near-instant for prefetched routes.\n window.__VINEXT_RSC_NAVIGATE__ = async function navigateRsc(href) {\n try {\n const url = new URL(href, window.location.origin);\n const rscUrl = toRscUrl(url.pathname + url.search);\n\n // Check the in-memory prefetch cache first\n let navResponse;\n const prefetchCache = getPrefetchCache();\n const cached = prefetchCache.get(rscUrl);\n if (cached && (Date.now() - cached.timestamp) < PREFETCH_CACHE_TTL) {\n navResponse = cached.response;\n prefetchCache.delete(rscUrl); // Consume the cached entry (one-time use)\n getPrefetchedUrls().delete(rscUrl); // Allow re-prefetch when link is visible again\n } else if (cached) {\n prefetchCache.delete(rscUrl); // Expired, clean up\n getPrefetchedUrls().delete(rscUrl);\n }\n\n // Fallback to network fetch if not in cache\n if (!navResponse) {\n navResponse = await fetch(rscUrl, {\n headers: { Accept: \"text/x-component\" },\n credentials: \"include\",\n });\n }\n\n // Update useParams() with route params from the server before re-rendering\n const navParamsHeader = navResponse.headers.get(\"X-Vinext-Params\");\n if (navParamsHeader) {\n try { setClientParams(JSON.parse(navParamsHeader)); } catch (_e) { /* ignore */ }\n } else {\n setClientParams({});\n }\n\n const rscPayload = await createFromFetch(Promise.resolve(navResponse));\n // Use flushSync to guarantee React commits the new tree to the DOM\n // synchronously before this function returns. Callers scroll to top\n // after awaiting, so the new content must be painted first.\n flushSync(function () { reactRoot.render(rscPayload); });\n } catch (err) {\n console.error(\"[vinext] RSC navigation error:\", err);\n // Fallback to full page load\n window.location.href = href;\n }\n };\n\n // Handle popstate (browser back/forward)\n // Store the navigation promise on a well-known property so that\n // restoreScrollPosition (in navigation.ts) can await it before scrolling.\n // This prevents a flash where the old content is visible at the restored\n // scroll position before the new RSC payload has rendered.\n window.addEventListener(\"popstate\", () => {\n const p = window.__VINEXT_RSC_NAVIGATE__(window.location.href);\n window.__VINEXT_RSC_PENDING__ = p;\n p.finally(() => {\n // Clear once settled so stale promises aren't awaited later\n if (window.__VINEXT_RSC_PENDING__ === p) {\n window.__VINEXT_RSC_PENDING__ = null;\n }\n });\n });\n\n // HMR: re-render on server module updates\n if (import.meta.hot) {\n import.meta.hot.on(\"rsc:update\", async () => {\n try {\n const rscPayload = await createFromFetch(\n fetch(toRscUrl(window.location.pathname + window.location.search))\n );\n reactRoot.render(rscPayload);\n } catch (err) {\n console.error(\"[vinext] RSC HMR error:\", err);\n }\n });\n }\n}\n\nmain();\n`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"app-dev-server.js","sourceRoot":"","sources":["../../src/server/app-dev-server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAIzC,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAC3H,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAoB9C;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAc,EACd,MAAkB,EAClB,cAA8B,EAC9B,cAAoC,EACpC,eAA+B,EAC/B,QAAiB,EACjB,aAAuB,EACvB,MAAwB;IAExB,MAAM,EAAE,GAAG,QAAQ,IAAI,EAAE,CAAC;IAC1B,MAAM,EAAE,GAAG,aAAa,IAAI,KAAK,CAAC;IAClC,MAAM,SAAS,GAAG,MAAM,EAAE,SAAS,IAAI,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IACvF,MAAM,OAAO,GAAG,MAAM,EAAE,OAAO,IAAI,EAAE,CAAC;IACtC,MAAM,cAAc,GAAG,MAAM,EAAE,cAAc,IAAI,EAAE,CAAC;IACpD,iDAAiD;IACjD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAwB,IAAI,GAAG,EAAE,CAAC;IACjD,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,SAAS,YAAY,CAAC,QAAgB;QACpC,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;QAC7D,MAAM,OAAO,GAAG,OAAO,SAAS,EAAE,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,eAAe,OAAO,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACxE,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,2BAA2B;IAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,QAAQ;YAAE,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,KAAK,CAAC,SAAS;YAAE,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACnD,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO;YAAE,YAAY,CAAC,MAAM,CAAC,CAAC;QACzD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS;YAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,KAAK,CAAC,WAAW;YAAE,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACvD,IAAI,KAAK,CAAC,SAAS;YAAE,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,KAAK,CAAC,gBAAgB;YAAE,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;gBAAC,IAAI,EAAE;oBAAE,YAAY,CAAC,EAAE,CAAC,CAAC;YAAC,CAAC;QAClG,IAAI,KAAK,CAAC,YAAY;YAAE,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACzD,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,aAAa,IAAI,EAAE,EAAE,CAAC;YAAC,IAAI,GAAG;gBAAE,YAAY,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;QAC5E,IAAI,KAAK,CAAC,aAAa;YAAE,YAAY,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC3D,IAAI,KAAK,CAAC,gBAAgB;YAAE,YAAY,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACjE,iCAAiC;QACjC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;YACvC,IAAI,IAAI,CAAC,QAAQ;gBAAE,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/C,IAAI,IAAI,CAAC,WAAW;gBAAE,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACrD,IAAI,IAAI,CAAC,UAAU;gBAAE,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACnD,IAAI,IAAI,CAAC,WAAW;gBAAE,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACrD,IAAI,IAAI,CAAC,SAAS;gBAAE,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACjD,2CAA2C;YAC3C,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBACzC,YAAY,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;IAED,qCAAqC;IACrC,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACxC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7D,MAAM,YAAY,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,MAAM,YAAY,GAAG,CAAC,KAAK,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC7F,MAAM,WAAW,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACnD,MAAM,gBAAgB,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;gBAC1D,OAAO;wBACS,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,UAAU,CAAC;2BAC1B,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,aAAa,CAAC;kBACzC,YAAY,CAAC,EAAE,CAAC,QAAQ,CAAC;oBACvB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC;UACnC,CAAC;YACL,CAAC,CAAC,CAAC;YACH,OAAO,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC/B,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM;mBACjD,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM;kBAC3D,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM;mBACvD,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM;iBAC5D,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM;uBAChD,IAAI,CAAC,WAAW;;EAErC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;;QAEtB,CAAC;QACL,CAAC,CAAC,CAAC;QACH,MAAM,eAAe,GAAG,CAAC,KAAK,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACnG,OAAO;eACI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;iBAC3B,KAAK,CAAC,SAAS;cAClB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC;YAC9B,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM;oBAC9C,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM;gBAC5D,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;2BACV,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,mBAAmB,CAAC;kBAClD,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;eAC1B,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;;EAEvC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;;eAEV,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM;aAC9D,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM;gBACrD,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM;kBAC5D,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;iBACxB,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM;oBAC7D,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,MAAM;IACtF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,8FAA8F;IAC9F,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,GAAG,CAAC,CAAC;IACxD,MAAM,eAAe,GAAG,SAAS,EAAE,YAAY;QAC7C,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,YAAY,CAAC;QACtC,CAAC,CAAC,IAAI,CAAC;IACT,MAAM,gBAAgB,GAAG,SAAS,EAAE,aAAa;QAC/C,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,aAAa,CAAC;QACvC,CAAC,CAAC,IAAI,CAAC;IACT,MAAM,mBAAmB,GAAG,SAAS,EAAE,gBAAgB;QACrD,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,gBAAgB,CAAC;QAC1C,CAAC,CAAC,IAAI,CAAC;IACT,MAAM,cAAc,GAAG,SAAS;QAC9B,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC,CAAC,EAAE,CAAC;IAEP,+CAA+C;IAC/C,MAAM,cAAc,GAAG,eAAe,CAAC,CAAC,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE9E,gCAAgC;IAChC,MAAM,mBAAmB,GAAG,cAAc,IAAI,EAAE,CAAC;IACjD,MAAM,iBAAiB,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEzE,kCAAkC;IAClC,KAAK,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;QACnC,YAAY,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAED,6BAA6B;IAC7B,2EAA2E;IAC3E,8EAA8E;IAC9E,wDAAwD;IACxD,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QACtD,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;YACjB,OAAO;YACD,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC;;iBAElB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC;mBAC1B,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,WAAW,CAAC;cACnC,YAAY,CAAC,EAAE,CAAC,QAAQ,CAAC;IACnC,CAAC;QACD,CAAC;QACD,wCAAwC;QACxC,IAAI,cAAc,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;YACzC,cAAc,GAAG,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,yDAAyD;QAC3D,CAAC;QACD,OAAO;YACC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC;;iBAElB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC;mBAC1B,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,WAAW,CAAC;sBAC3B,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC;IAChD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO;;;;;;;;;;;;;;EAcP,cAAc,CAAC,CAAC,CAAC,qCAAqC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;EAChH,mBAAmB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,8DAA8D,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,sBAAsB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+I1M,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;;;EAGlB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;;;;EAIxB,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;;;6BAGD,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM;8BACzC,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM;iCACzC,mBAAmB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,MAAM;uBAC5D,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAqE1C,cAAc,CAAC,CAAC,CAAC;oCACa,cAAc;;;;;;;KAO7C,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mCA6DyB,cAAc,CAAC,CAAC,CAAC,OAAO,cAAc,WAAW,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA8BnF,cAAc,CAAC,CAAC,CAAC;kCACW,cAAc;;;;;;;KAO3C,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2DAiNiD,eAAe,CAAC,CAAC,CAAC,GAAG,eAAe,WAAW,CAAC,CAAC,CAAC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAyH/G,cAAc,CAAC,CAAC,CAAC;iCACY,cAAc;;;;;;;GAO5C,CAAC,CAAC,CAAC,EAAE;;;;;EAKN,cAAc,CAAC,CAAC,CAAC,6BAA6B,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;;qBAE1C,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;0BACb,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;4BAChB,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;2BAC1B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;0BACzB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;2BACtB,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC;;EAEvD,0BAA0B,CAAC,MAAM,EAAE,iBAAiB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2DrD,sBAAsB,CAAC,QAAQ,CAAC;;;EAGhC,yBAAyB,CAAC,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAqSnB,EAAE,CAAC,CAAC,CAAC,2BAA2B,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,gCAAgC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAkEzI,EAAE,CAAC,CAAC,CAAC;;;;;GAKN,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAsDJ,cAAc,CAAC,CAAC,CAAC;;;;qBAIA,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgF7D,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oDA0mB4C,eAAe,CAAC,CAAC,CAAC,GAAG,eAAe,WAAW,CAAC,CAAC,CAAC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2P3G,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+aR,CAAC;AACF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6TR,CAAC;AACF,CAAC","sourcesContent":["/**\n * App Router dev server handler.\n *\n * This module generates virtual entry points for the RSC/SSR/browser\n * environments that @vitejs/plugin-rsc manages. The RSC entry does\n * route matching and renders the component tree, then delegates to\n * the SSR entry for HTML generation.\n */\nimport fs from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport type { AppRoute } from \"../routing/app-router.js\";\nimport type { MetadataFileRoute } from \"./metadata-routes.js\";\nimport type { NextRedirect, NextRewrite, NextHeader } from \"../config/next-config.js\";\nimport { generateDevOriginCheckCode } from \"./dev-origin-check.js\";\nimport { generateSafeRegExpCode, generateMiddlewareMatcherCode, generateNormalizePathCode } from \"./middleware-codegen.js\";\nimport { isProxyFile } from \"./middleware.js\";\n\n/**\n * Resolved config options relevant to App Router request handling.\n * Passed from the Vite plugin where the full next.config.js is loaded.\n */\nexport interface AppRouterConfig {\n redirects?: NextRedirect[];\n rewrites?: {\n beforeFiles: NextRewrite[];\n afterFiles: NextRewrite[];\n fallback: NextRewrite[];\n };\n headers?: NextHeader[];\n /** Extra origins allowed for server action CSRF checks (from experimental.serverActions.allowedOrigins). */\n allowedOrigins?: string[];\n /** Extra origins allowed for dev server access (from serverActionsAllowedOrigins or custom config). */\n allowedDevOrigins?: string[];\n}\n\n/**\n * Generate the virtual RSC entry module.\n *\n * This runs in the `rsc` Vite environment (react-server condition).\n * It matches the incoming request URL to an app route, builds the\n * nested layout + page tree, and renders it to an RSC stream.\n */\nexport function generateRscEntry(\n appDir: string,\n routes: AppRoute[],\n middlewarePath?: string | null,\n metadataRoutes?: MetadataFileRoute[],\n globalErrorPath?: string | null,\n basePath?: string,\n trailingSlash?: boolean,\n config?: AppRouterConfig,\n): string {\n const bp = basePath ?? \"\";\n const ts = trailingSlash ?? false;\n const redirects = config?.redirects ?? [];\n const rewrites = config?.rewrites ?? { beforeFiles: [], afterFiles: [], fallback: [] };\n const headers = config?.headers ?? [];\n const allowedOrigins = config?.allowedOrigins ?? [];\n // Build import map for all page and layout files\n const imports: string[] = [];\n const importMap: Map<string, string> = new Map();\n let importIdx = 0;\n\n function getImportVar(filePath: string): string {\n if (importMap.has(filePath)) return importMap.get(filePath)!;\n const varName = `mod_${importIdx++}`;\n const absPath = filePath.replace(/\\\\/g, \"/\");\n imports.push(`import * as ${varName} from ${JSON.stringify(absPath)};`);\n importMap.set(filePath, varName);\n return varName;\n }\n\n // Pre-register all modules\n for (const route of routes) {\n if (route.pagePath) getImportVar(route.pagePath);\n if (route.routePath) getImportVar(route.routePath);\n for (const layout of route.layouts) getImportVar(layout);\n for (const tmpl of route.templates) getImportVar(tmpl);\n if (route.loadingPath) getImportVar(route.loadingPath);\n if (route.errorPath) getImportVar(route.errorPath);\n if (route.layoutErrorPaths) for (const ep of route.layoutErrorPaths) { if (ep) getImportVar(ep); }\n if (route.notFoundPath) getImportVar(route.notFoundPath);\n for (const nfp of route.notFoundPaths || []) { if (nfp) getImportVar(nfp); }\n if (route.forbiddenPath) getImportVar(route.forbiddenPath);\n if (route.unauthorizedPath) getImportVar(route.unauthorizedPath);\n // Register parallel slot modules\n for (const slot of route.parallelSlots) {\n if (slot.pagePath) getImportVar(slot.pagePath);\n if (slot.defaultPath) getImportVar(slot.defaultPath);\n if (slot.layoutPath) getImportVar(slot.layoutPath);\n if (slot.loadingPath) getImportVar(slot.loadingPath);\n if (slot.errorPath) getImportVar(slot.errorPath);\n // Register intercepting route page modules\n for (const ir of slot.interceptingRoutes) {\n getImportVar(ir.pagePath);\n }\n }\n }\n\n // Build route table as serialized JS\n const routeEntries = routes.map((route) => {\n const layoutVars = route.layouts.map((l) => getImportVar(l));\n const templateVars = route.templates.map((t) => getImportVar(t));\n const notFoundVars = (route.notFoundPaths || []).map((nf) => nf ? getImportVar(nf) : \"null\");\n const slotEntries = route.parallelSlots.map((slot) => {\n const interceptEntries = slot.interceptingRoutes.map((ir) => {\n return ` {\n convention: ${JSON.stringify(ir.convention)},\n targetPattern: ${JSON.stringify(ir.targetPattern)},\n page: ${getImportVar(ir.pagePath)},\n params: ${JSON.stringify(ir.params)},\n }`;\n });\n return ` ${JSON.stringify(slot.name)}: {\n page: ${slot.pagePath ? getImportVar(slot.pagePath) : \"null\"},\n default: ${slot.defaultPath ? getImportVar(slot.defaultPath) : \"null\"},\n layout: ${slot.layoutPath ? getImportVar(slot.layoutPath) : \"null\"},\n loading: ${slot.loadingPath ? getImportVar(slot.loadingPath) : \"null\"},\n error: ${slot.errorPath ? getImportVar(slot.errorPath) : \"null\"},\n layoutIndex: ${slot.layoutIndex},\n intercepts: [\n${interceptEntries.join(\",\\n\")}\n ],\n }`;\n });\n const layoutErrorVars = (route.layoutErrorPaths || []).map((ep) => ep ? getImportVar(ep) : \"null\");\n return ` {\n pattern: ${JSON.stringify(route.pattern)},\n isDynamic: ${route.isDynamic},\n params: ${JSON.stringify(route.params)},\n page: ${route.pagePath ? getImportVar(route.pagePath) : \"null\"},\n routeHandler: ${route.routePath ? getImportVar(route.routePath) : \"null\"},\n layouts: [${layoutVars.join(\", \")}],\n layoutSegmentDepths: ${JSON.stringify(route.layoutSegmentDepths)},\n templates: [${templateVars.join(\", \")}],\n errors: [${layoutErrorVars.join(\", \")}],\n slots: {\n${slotEntries.join(\",\\n\")}\n },\n loading: ${route.loadingPath ? getImportVar(route.loadingPath) : \"null\"},\n error: ${route.errorPath ? getImportVar(route.errorPath) : \"null\"},\n notFound: ${route.notFoundPath ? getImportVar(route.notFoundPath) : \"null\"},\n notFounds: [${notFoundVars.join(\", \")}],\n forbidden: ${route.forbiddenPath ? getImportVar(route.forbiddenPath) : \"null\"},\n unauthorized: ${route.unauthorizedPath ? getImportVar(route.unauthorizedPath) : \"null\"},\n }`;\n });\n\n // Find root not-found/forbidden/unauthorized pages and root layouts for global error handling\n const rootRoute = routes.find((r) => r.pattern === \"/\");\n const rootNotFoundVar = rootRoute?.notFoundPath\n ? getImportVar(rootRoute.notFoundPath)\n : null;\n const rootForbiddenVar = rootRoute?.forbiddenPath\n ? getImportVar(rootRoute.forbiddenPath)\n : null;\n const rootUnauthorizedVar = rootRoute?.unauthorizedPath\n ? getImportVar(rootRoute.unauthorizedPath)\n : null;\n const rootLayoutVars = rootRoute\n ? rootRoute.layouts.map((l) => getImportVar(l))\n : [];\n\n // Global error boundary (app/global-error.tsx)\n const globalErrorVar = globalErrorPath ? getImportVar(globalErrorPath) : null;\n\n // Build metadata route handling\n const effectiveMetaRoutes = metadataRoutes ?? [];\n const dynamicMetaRoutes = effectiveMetaRoutes.filter((r) => r.isDynamic);\n\n // Import dynamic metadata modules\n for (const mr of dynamicMetaRoutes) {\n getImportVar(mr.filePath);\n }\n\n // Build metadata route table\n // For static metadata files, read the file content at code-generation time\n // and embed it as base64. This ensures static metadata files work on runtimes\n // without filesystem access (e.g., Cloudflare Workers).\n const metaRouteEntries = effectiveMetaRoutes.map((mr) => {\n if (mr.isDynamic) {\n return ` {\n type: ${JSON.stringify(mr.type)},\n isDynamic: true,\n servedUrl: ${JSON.stringify(mr.servedUrl)},\n contentType: ${JSON.stringify(mr.contentType)},\n module: ${getImportVar(mr.filePath)},\n }`;\n }\n // Static: read file and embed as base64\n let fileDataBase64 = \"\";\n try {\n const buf = fs.readFileSync(mr.filePath);\n fileDataBase64 = buf.toString(\"base64\");\n } catch {\n // File unreadable — will serve empty response at runtime\n }\n return ` {\n type: ${JSON.stringify(mr.type)},\n isDynamic: false,\n servedUrl: ${JSON.stringify(mr.servedUrl)},\n contentType: ${JSON.stringify(mr.contentType)},\n fileDataBase64: ${JSON.stringify(fileDataBase64)},\n }`;\n });\n\n return `\nimport {\n renderToReadableStream,\n decodeReply,\n loadServerAction,\n createTemporaryReferenceSet,\n} from \"@vitejs/plugin-rsc/rsc\";\nimport { createElement, Suspense, Fragment } from \"react\";\nimport { setNavigationContext as _setNavigationContextOrig, getNavigationContext as _getNavigationContext } from \"next/navigation\";\nimport { setHeadersContext, headersContextFromRequest, getDraftModeCookieHeader, getAndClearPendingCookies, consumeDynamicUsage, markDynamicUsage, runWithHeadersContext, applyMiddlewareRequestHeaders } from \"next/headers\";\nimport { NextRequest } from \"next/server\";\nimport { ErrorBoundary, NotFoundBoundary } from \"vinext/error-boundary\";\nimport { LayoutSegmentProvider } from \"vinext/layout-segment-context\";\nimport { MetadataHead, mergeMetadata, resolveModuleMetadata, ViewportHead, mergeViewport, resolveModuleViewport } from \"vinext/metadata\";\n${middlewarePath ? `import * as middlewareModule from ${JSON.stringify(middlewarePath.replace(/\\\\/g, \"/\"))};` : \"\"}\n${effectiveMetaRoutes.length > 0 ? `import { sitemapToXml, robotsToText, manifestToJson } from ${JSON.stringify(fileURLToPath(new URL(\"./metadata-routes.js\", import.meta.url)).replace(/\\\\/g, \"/\"))};` : \"\"}\nimport { _consumeRequestScopedCacheLife, _runWithCacheState } from \"next/cache\";\nimport { runWithFetchCache } from \"vinext/fetch-cache\";\nimport { runWithPrivateCache as _runWithPrivateCache } from \"vinext/cache-runtime\";\n// Import server-only state module to register ALS-backed accessors.\nimport { runWithNavigationContext as _runWithNavigationContext } from \"vinext/navigation-state\";\nimport { reportRequestError as _reportRequestError } from \"vinext/instrumentation\";\nimport { getSSRFontLinks as _getSSRFontLinks, getSSRFontStyles as _getSSRFontStylesGoogle, getSSRFontPreloads as _getSSRFontPreloadsGoogle } from \"next/font/google\";\nimport { getSSRFontStyles as _getSSRFontStylesLocal, getSSRFontPreloads as _getSSRFontPreloadsLocal } from \"next/font/local\";\nfunction _getSSRFontStyles() { return [..._getSSRFontStylesGoogle(), ..._getSSRFontStylesLocal()]; }\nfunction _getSSRFontPreloads() { return [..._getSSRFontPreloadsGoogle(), ..._getSSRFontPreloadsLocal()]; }\n\n// Set navigation context in the ALS-backed store. \"use client\" components\n// rendered during SSR need the pathname/searchParams/params but the SSR\n// environment has a separate module instance of next/navigation.\n// Use _getNavigationContext() to read the current context — never cache\n// it in a module-level variable (that would leak between concurrent requests).\nfunction setNavigationContext(ctx) {\n _setNavigationContextOrig(ctx);\n}\n\n// ISR cache is disabled in dev mode — every request re-renders fresh,\n// matching Next.js dev behavior. Cache-Control headers are still emitted\n// based on export const revalidate for testing purposes.\n// Production ISR is handled by prod-server.ts and the Cloudflare worker entry.\n\n// Normalize null-prototype objects from matchPattern() into thenable objects\n// that work both as Promises (for Next.js 15+ async params) and as plain\n// objects with synchronous property access (for pre-15 code like params.id).\n//\n// matchPattern() uses Object.create(null), producing objects without\n// Object.prototype. The RSC serializer rejects these. Spreading ({...obj})\n// restores a normal prototype. Object.assign onto the Promise preserves\n// synchronous property access (params.id, params.slug) that existing\n// components and test fixtures rely on.\nfunction makeThenableParams(obj) {\n const plain = { ...obj };\n return Object.assign(Promise.resolve(plain), plain);\n}\n\n// djb2 hash — matches Next.js's stringHash for digest generation.\n// Produces a stable numeric string from error message + stack.\nfunction __errorDigest(str) {\n let hash = 5381;\n for (let i = str.length - 1; i >= 0; i--) {\n hash = (hash * 33) ^ str.charCodeAt(i);\n }\n return (hash >>> 0).toString();\n}\n\n// Sanitize an error for client consumption. In production, replaces the error\n// with a generic Error that only carries a digest hash (matching Next.js\n// behavior). In development, returns the original error for debugging.\n// Navigation errors (redirect, notFound, etc.) are always passed through\n// unchanged since their digests are used for client-side routing.\nfunction __sanitizeErrorForClient(error) {\n // Navigation errors must pass through with their digest intact\n if (error && typeof error === \"object\" && \"digest\" in error) {\n const digest = String(error.digest);\n if (\n digest.startsWith(\"NEXT_REDIRECT;\") ||\n digest === \"NEXT_NOT_FOUND\" ||\n digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")\n ) {\n return error;\n }\n }\n // In development, pass through the original error for debugging\n if (process.env.NODE_ENV !== \"production\") {\n return error;\n }\n // In production, create a sanitized error with only a digest hash\n const msg = error instanceof Error ? error.message : String(error);\n const stack = error instanceof Error ? (error.stack || \"\") : \"\";\n const sanitized = new Error(\n \"An error occurred in the Server Components render. \" +\n \"The specific message is omitted in production builds to avoid leaking sensitive details. \" +\n \"A digest property is included on this error instance which may provide additional details about the nature of the error.\"\n );\n sanitized.digest = __errorDigest(msg + stack);\n return sanitized;\n}\n\n// onError callback for renderToReadableStream — preserves the digest for\n// Next.js navigation errors (redirect, notFound, forbidden, unauthorized)\n// thrown during RSC streaming (e.g. inside Suspense boundaries).\n// For non-navigation errors in production, generates a digest hash so the\n// error can be correlated with server logs without leaking details.\nfunction rscOnError(error) {\n if (error && typeof error === \"object\" && \"digest\" in error) {\n return String(error.digest);\n }\n\n // In dev, detect the \"Only plain objects\" RSC serialization error and emit\n // an actionable hint. This error occurs when a Server Component passes a\n // class instance, ES module namespace object, or null-prototype object as a\n // prop to a Client Component.\n //\n // Root cause: Vite bundles modules as true ESM (module namespace objects\n // have a null-like internal slot), while Next.js's webpack build produces\n // plain CJS-wrapped objects with __esModule:true. React's RSC serializer\n // accepts the latter as plain objects but rejects the former — which means\n // code that accidentally passes \"import * as X\" works in webpack/Next.js\n // but correctly fails in vinext.\n //\n // Common triggers:\n // - \"import * as utils from './utils'\" passed as a prop\n // - class instances (new Foo()) passed as props\n // - Date / Map / Set instances passed as props\n // - Objects with Object.create(null) (null prototype)\n if (\n process.env.NODE_ENV !== \"production\" &&\n error instanceof Error &&\n error.message.includes(\"Only plain objects, and a few built-ins, can be passed to Client Components\")\n ) {\n console.error(\n \"[vinext] RSC serialization error: a non-plain object was passed from a Server Component to a Client Component.\\\\n\" +\n \"\\\\n\" +\n \"Common causes:\\\\n\" +\n \" * Passing a module namespace (import * as X) directly as a prop.\\\\n\" +\n \" Unlike Next.js (webpack), Vite produces real ESM module namespace objects\\\\n\" +\n \" which are not serializable. Fix: pass individual values instead,\\\\n\" +\n \" e.g. <Comp value={module.value} />\\\\n\" +\n \" * Passing a class instance (new Foo()) as a prop.\\\\n\" +\n \" Fix: convert to a plain object, e.g. { id: foo.id, name: foo.name }\\\\n\" +\n \" * Passing a Date, Map, or Set. Use .toISOString(), [...map.entries()], etc.\\\\n\" +\n \" * Passing Object.create(null). Use { ...obj } to restore a prototype.\\\\n\" +\n \"\\\\n\" +\n \"Original error:\",\n error.message,\n );\n return undefined;\n }\n\n // In production, generate a digest hash for non-navigation errors\n if (process.env.NODE_ENV === \"production\" && error) {\n const msg = error instanceof Error ? error.message : String(error);\n const stack = error instanceof Error ? (error.stack || \"\") : \"\";\n return __errorDigest(msg + stack);\n }\n return undefined;\n}\n\n${imports.join(\"\\n\")}\n\nconst routes = [\n${routeEntries.join(\",\\n\")}\n];\n\nconst metadataRoutes = [\n${metaRouteEntries.join(\",\\n\")}\n];\n\nconst rootNotFoundModule = ${rootNotFoundVar ? rootNotFoundVar : \"null\"};\nconst rootForbiddenModule = ${rootForbiddenVar ? rootForbiddenVar : \"null\"};\nconst rootUnauthorizedModule = ${rootUnauthorizedVar ? rootUnauthorizedVar : \"null\"};\nconst rootLayouts = [${rootLayoutVars.join(\", \")}];\n\n/**\n * Render an HTTP access fallback page (not-found/forbidden/unauthorized) with layouts and noindex meta.\n * Returns null if no matching component is available.\n *\n * @param opts.boundaryComponent - Override the boundary component (for layout-level notFound)\n * @param opts.layouts - Override the layouts to wrap with (for layout-level notFound, excludes the throwing layout)\n */\nasync function renderHTTPAccessFallbackPage(route, statusCode, isRscRequest, request, opts) {\n // Determine which boundary component to use based on status code\n let BoundaryComponent = opts?.boundaryComponent ?? null;\n if (!BoundaryComponent) {\n let boundaryModule;\n if (statusCode === 403) {\n boundaryModule = route?.forbidden ?? rootForbiddenModule;\n } else if (statusCode === 401) {\n boundaryModule = route?.unauthorized ?? rootUnauthorizedModule;\n } else {\n boundaryModule = route?.notFound ?? rootNotFoundModule;\n }\n BoundaryComponent = boundaryModule?.default ?? null;\n }\n const layouts = opts?.layouts ?? route?.layouts ?? rootLayouts;\n if (!BoundaryComponent) return null;\n\n // Resolve metadata and viewport from parent layouts so that not-found/error\n // pages inherit title, description, OG tags etc. — matching Next.js behavior.\n const metadataList = [];\n const viewportList = [];\n for (const layoutMod of layouts) {\n if (layoutMod) {\n const meta = await resolveModuleMetadata(layoutMod);\n if (meta) metadataList.push(meta);\n const vp = await resolveModuleViewport(layoutMod);\n if (vp) viewportList.push(vp);\n }\n }\n const resolvedMetadata = metadataList.length > 0 ? mergeMetadata(metadataList) : null;\n const resolvedViewport = mergeViewport(viewportList);\n\n // Build element: metadata head + noindex meta + boundary component wrapped in layouts\n // Always include charset and default viewport for parity with Next.js.\n const charsetMeta = createElement(\"meta\", { charSet: \"utf-8\" });\n const noindexMeta = createElement(\"meta\", { name: \"robots\", content: \"noindex\" });\n const headElements = [charsetMeta, noindexMeta];\n if (resolvedMetadata) headElements.push(createElement(MetadataHead, { metadata: resolvedMetadata }));\n headElements.push(createElement(ViewportHead, { viewport: resolvedViewport }));\n let element = createElement(Fragment, null, ...headElements, createElement(BoundaryComponent));\n if (isRscRequest) {\n // For RSC requests (client-side navigation), wrap the element with the same\n // component wrappers that buildPageElement() uses. Without these wrappers,\n // React's reconciliation would see a mismatched tree structure between the\n // old fiber tree (ErrorBoundary > LayoutSegmentProvider > html > body > NotFoundBoundary > ...)\n // and the new tree (html > body > ...), causing it to destroy and recreate\n // the entire DOM tree, resulting in a blank white page.\n //\n // We wrap each layout with LayoutSegmentProvider and add GlobalErrorBoundary\n // to match the wrapping order in buildPageElement(), ensuring smooth\n // client-side tree reconciliation.\n const layoutDepths = route?.layoutSegmentDepths;\n for (let i = layouts.length - 1; i >= 0; i--) {\n const LayoutComponent = layouts[i]?.default;\n if (LayoutComponent) {\n element = createElement(LayoutComponent, { children: element });\n const layoutDepth = layoutDepths ? layoutDepths[i] : 0;\n element = createElement(LayoutSegmentProvider, { depth: layoutDepth }, element);\n }\n }\n ${globalErrorVar ? `\n const _GlobalErrorComponent = ${globalErrorVar}.default;\n if (_GlobalErrorComponent) {\n element = createElement(ErrorBoundary, {\n fallback: _GlobalErrorComponent,\n children: element,\n });\n }\n ` : \"\"}\n const rscStream = renderToReadableStream(element, { onError: rscOnError });\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(rscStream, {\n status: statusCode,\n headers: { \"Content-Type\": \"text/x-component; charset=utf-8\", \"Vary\": \"RSC, Accept\" },\n });\n }\n // For HTML (full page load) responses, wrap with layouts only (no client-side\n // wrappers needed since SSR generates the complete HTML document).\n for (let i = layouts.length - 1; i >= 0; i--) {\n const LayoutComponent = layouts[i]?.default;\n if (LayoutComponent) {\n element = createElement(LayoutComponent, { children: element });\n }\n }\n const rscStream = renderToReadableStream(element, { onError: rscOnError });\n // Collect font data from RSC environment\n const fontData = {\n links: _getSSRFontLinks(),\n styles: _getSSRFontStyles(),\n preloads: _getSSRFontPreloads(),\n };\n const ssrEntry = await import.meta.viteRsc.loadModule(\"ssr\", \"index\");\n const htmlStream = await ssrEntry.handleSsr(rscStream, _getNavigationContext(), fontData);\n setHeadersContext(null);\n setNavigationContext(null);\n const _respHeaders = { \"Content-Type\": \"text/html; charset=utf-8\", \"Vary\": \"RSC, Accept\" };\n const _linkParts = (fontData.preloads || []).map(function(p) { return \"<\" + p.href + \">; rel=preload; as=font; type=\" + p.type + \"; crossorigin\"; });\n if (_linkParts.length > 0) _respHeaders[\"Link\"] = _linkParts.join(\", \");\n return new Response(htmlStream, {\n status: statusCode,\n headers: _respHeaders,\n });\n}\n\n/** Convenience: render a not-found page (404) */\nasync function renderNotFoundPage(route, isRscRequest, request) {\n return renderHTTPAccessFallbackPage(route, 404, isRscRequest, request);\n}\n\n/**\n * Render an error.tsx boundary page when a server component or generateMetadata() throws.\n * Returns null if no error boundary component is available for this route.\n *\n * Next.js returns HTTP 200 when error.tsx catches an error (the error is \"handled\"\n * by the boundary). This matches that behavior intentionally.\n */\nasync function renderErrorBoundaryPage(route, error, isRscRequest, request) {\n // Resolve the error boundary component: leaf error.tsx first, then walk per-layout\n // errors from innermost to outermost (matching ancestor inheritance), then global-error.tsx.\n let ErrorComponent = route?.error?.default ?? null;\n if (!ErrorComponent && route?.errors) {\n for (let i = route.errors.length - 1; i >= 0; i--) {\n if (route.errors[i]?.default) {\n ErrorComponent = route.errors[i].default;\n break;\n }\n }\n }\n ErrorComponent = ErrorComponent${globalErrorVar ? ` ?? ${globalErrorVar}?.default` : \"\"};\n if (!ErrorComponent) return null;\n\n const rawError = error instanceof Error ? error : new Error(String(error));\n // Sanitize the error in production to avoid leaking internal details\n // (database errors, file paths, stack traces) through error.tsx to the client.\n // In development, pass the original error for debugging.\n const errorObj = __sanitizeErrorForClient(rawError);\n // Only pass error — reset is a client-side concern (re-renders the segment) and\n // can't be serialized through RSC. The error.tsx component will receive reset=undefined\n // during SSR, which is fine — onClick={undefined} is harmless, and the real reset\n // function is only meaningful after hydration.\n let element = createElement(ErrorComponent, {\n error: errorObj,\n });\n const layouts = route?.layouts ?? rootLayouts;\n if (isRscRequest) {\n // For RSC requests (client-side navigation), wrap with the same component\n // wrappers that buildPageElement() uses (LayoutSegmentProvider, GlobalErrorBoundary).\n // This ensures React can reconcile the tree without destroying the DOM.\n // Same rationale as renderHTTPAccessFallbackPage — see comment there.\n const layoutDepths = route?.layoutSegmentDepths;\n for (let i = layouts.length - 1; i >= 0; i--) {\n const LayoutComponent = layouts[i]?.default;\n if (LayoutComponent) {\n element = createElement(LayoutComponent, { children: element });\n const layoutDepth = layoutDepths ? layoutDepths[i] : 0;\n element = createElement(LayoutSegmentProvider, { depth: layoutDepth }, element);\n }\n }\n ${globalErrorVar ? `\n const _ErrGlobalComponent = ${globalErrorVar}.default;\n if (_ErrGlobalComponent) {\n element = createElement(ErrorBoundary, {\n fallback: _ErrGlobalComponent,\n children: element,\n });\n }\n ` : \"\"}\n const rscStream = renderToReadableStream(element, { onError: rscOnError });\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(rscStream, {\n status: 200,\n headers: { \"Content-Type\": \"text/x-component; charset=utf-8\", \"Vary\": \"RSC, Accept\" },\n });\n }\n // For HTML (full page load) responses, wrap with layouts only.\n for (let i = layouts.length - 1; i >= 0; i--) {\n const LayoutComponent = layouts[i]?.default;\n if (LayoutComponent) {\n element = createElement(LayoutComponent, { children: element });\n }\n }\n const rscStream = renderToReadableStream(element, { onError: rscOnError });\n // Collect font data from RSC environment so error pages include font styles\n const fontData = {\n links: _getSSRFontLinks(),\n styles: _getSSRFontStyles(),\n preloads: _getSSRFontPreloads(),\n };\n const ssrEntry = await import.meta.viteRsc.loadModule(\"ssr\", \"index\");\n const htmlStream = await ssrEntry.handleSsr(rscStream, _getNavigationContext(), fontData);\n setHeadersContext(null);\n setNavigationContext(null);\n const _errHeaders = { \"Content-Type\": \"text/html; charset=utf-8\", \"Vary\": \"RSC, Accept\" };\n const _errLinkParts = (fontData.preloads || []).map(function(p) { return \"<\" + p.href + \">; rel=preload; as=font; type=\" + p.type + \"; crossorigin\"; });\n if (_errLinkParts.length > 0) _errHeaders[\"Link\"] = _errLinkParts.join(\", \");\n return new Response(htmlStream, {\n status: 200,\n headers: _errHeaders,\n });\n}\n\nfunction matchRoute(url, routes) {\n const pathname = url.split(\"?\")[0];\n let normalizedUrl = pathname === \"/\" ? \"/\" : pathname.replace(/\\\\/$/, \"\");\n // NOTE: Do NOT decodeURIComponent here. The caller is responsible for decoding\n // the pathname exactly once at the request entry point. Decoding again here\n // would cause inconsistent path matching between middleware and routing.\n for (const route of routes) {\n const params = matchPattern(normalizedUrl, route.pattern);\n if (params !== null) return { route, params };\n }\n return null;\n}\n\nfunction matchPattern(url, pattern) {\n const urlParts = url.split(\"/\").filter(Boolean);\n const patternParts = pattern.split(\"/\").filter(Boolean);\n const params = Object.create(null);\n for (let i = 0; i < patternParts.length; i++) {\n const pp = patternParts[i];\n if (pp.endsWith(\"+\")) {\n const paramName = pp.slice(1, -1);\n const remaining = urlParts.slice(i);\n if (remaining.length === 0) return null;\n params[paramName] = remaining;\n return params;\n }\n if (pp.endsWith(\"*\")) {\n const paramName = pp.slice(1, -1);\n params[paramName] = urlParts.slice(i);\n return params;\n }\n if (pp.startsWith(\":\")) {\n if (i >= urlParts.length) return null;\n params[pp.slice(1)] = urlParts[i];\n continue;\n }\n if (i >= urlParts.length || urlParts[i] !== pp) return null;\n }\n if (urlParts.length !== patternParts.length) return null;\n return params;\n}\n\n// Build a global intercepting route lookup for RSC navigation.\n// Maps target URL patterns to { sourceRouteIndex, slotName, interceptPage, params }.\nconst interceptLookup = [];\nfor (let ri = 0; ri < routes.length; ri++) {\n const r = routes[ri];\n if (!r.slots) continue;\n for (const [slotName, slotMod] of Object.entries(r.slots)) {\n if (!slotMod.intercepts) continue;\n for (const intercept of slotMod.intercepts) {\n interceptLookup.push({\n sourceRouteIndex: ri,\n slotName,\n targetPattern: intercept.targetPattern,\n page: intercept.page,\n params: intercept.params,\n });\n }\n }\n}\n\n/**\n * Check if a pathname matches any intercepting route.\n * Returns the match info or null.\n */\nfunction findIntercept(pathname) {\n for (const entry of interceptLookup) {\n const params = matchPattern(pathname, entry.targetPattern);\n if (params !== null) {\n return { ...entry, matchedParams: params };\n }\n }\n return null;\n}\n\nasync function buildPageElement(route, params, opts, searchParams) {\n const PageComponent = route.page?.default;\n if (!PageComponent) {\n return createElement(\"div\", null, \"Page has no default export\");\n }\n\n // Resolve metadata and viewport from layouts and page\n const metadataList = [];\n const viewportList = [];\n for (const layoutMod of route.layouts) {\n if (layoutMod) {\n const meta = await resolveModuleMetadata(layoutMod, params);\n if (meta) metadataList.push(meta);\n const vp = await resolveModuleViewport(layoutMod, params);\n if (vp) viewportList.push(vp);\n }\n }\n if (route.page) {\n const pageMeta = await resolveModuleMetadata(route.page, params);\n if (pageMeta) metadataList.push(pageMeta);\n const pageVp = await resolveModuleViewport(route.page, params);\n if (pageVp) viewportList.push(pageVp);\n }\n const resolvedMetadata = metadataList.length > 0 ? mergeMetadata(metadataList) : null;\n const resolvedViewport = mergeViewport(viewportList);\n\n // Build nested layout tree from outermost to innermost.\n // Next.js 16 passes params/searchParams as Promises (async pattern)\n // but pre-16 code accesses them as plain objects (params.id).\n // makeThenableParams() normalises null-prototype + preserves both patterns.\n const asyncParams = makeThenableParams(params);\n const pageProps = { params: asyncParams };\n if (searchParams) {\n const spObj = {};\n let hasSearchParams = false;\n if (searchParams.forEach) searchParams.forEach(function(v, k) {\n hasSearchParams = true;\n if (k in spObj) {\n // Multi-value: promote to array (Next.js returns string[] for duplicate keys)\n spObj[k] = Array.isArray(spObj[k]) ? spObj[k].concat(v) : [spObj[k], v];\n } else {\n spObj[k] = v;\n }\n });\n // If the URL has query parameters, mark the page as dynamic.\n // In Next.js, only accessing the searchParams prop signals dynamic usage,\n // but a Proxy-based approach doesn't work here because React's RSC debug\n // serializer accesses properties on all props (e.g. $$typeof check in\n // isClientReference), triggering the Proxy even when user code doesn't\n // read searchParams. Checking for non-empty query params is a safe\n // approximation: pages with query params in the URL are almost always\n // dynamic, and this avoids false positives from React internals.\n if (hasSearchParams) markDynamicUsage();\n pageProps.searchParams = makeThenableParams(spObj);\n }\n let element = createElement(PageComponent, pageProps);\n\n // Add metadata + viewport head tags (React 19 hoists title/meta/link to <head>)\n // Next.js always injects charset and default viewport even when no metadata/viewport\n // is exported. We replicate that by always emitting these essential head elements.\n {\n const headElements = [];\n // Always emit <meta charset=\"utf-8\"> — Next.js includes this on every page\n headElements.push(createElement(\"meta\", { charSet: \"utf-8\" }));\n if (resolvedMetadata) headElements.push(createElement(MetadataHead, { metadata: resolvedMetadata }));\n headElements.push(createElement(ViewportHead, { viewport: resolvedViewport }));\n element = createElement(Fragment, null, ...headElements, element);\n }\n\n // Wrap with loading.tsx Suspense if present\n if (route.loading?.default) {\n element = createElement(\n Suspense,\n { fallback: createElement(route.loading.default) },\n element,\n );\n }\n\n // Wrap with the leaf's error.tsx ErrorBoundary if it's not already covered\n // by a per-layout error boundary (i.e., the leaf has error.tsx but no layout).\n // Per-layout error boundaries are interleaved with layouts below.\n {\n const lastLayoutError = route.errors ? route.errors[route.errors.length - 1] : null;\n if (route.error?.default && route.error !== lastLayoutError) {\n element = createElement(ErrorBoundary, {\n fallback: route.error.default,\n children: element,\n });\n }\n }\n\n // Wrap with NotFoundBoundary so client-side notFound() renders not-found.tsx\n // instead of crashing the React tree. Must be above ErrorBoundary since\n // ErrorBoundary re-throws notFound errors.\n // Pre-render the not-found component as a React element since it may be a\n // server component (not a client reference) and can't be passed as a function prop.\n {\n const NotFoundComponent = route.notFound?.default ?? ${rootNotFoundVar ? `${rootNotFoundVar}?.default` : \"null\"};\n if (NotFoundComponent) {\n element = createElement(NotFoundBoundary, {\n fallback: createElement(NotFoundComponent),\n children: element,\n });\n }\n }\n\n // Wrap with templates (innermost first, then outer)\n // Templates are like layouts but re-mount on navigation (client-side concern).\n // On the server, they just wrap the content like layouts do.\n if (route.templates) {\n for (let i = route.templates.length - 1; i >= 0; i--) {\n const TemplateComponent = route.templates[i]?.default;\n if (TemplateComponent) {\n element = createElement(TemplateComponent, { children: element, params });\n }\n }\n }\n\n // Wrap with layouts (innermost first, then outer).\n // At each layout level, first wrap with that level's error boundary (if any)\n // so the boundary is inside the layout and catches errors from children.\n // This matches Next.js behavior: Layout > ErrorBoundary > children.\n // Parallel slots are passed as named props to the innermost layout\n // (the layout at the same directory level as the page/slots)\n for (let i = route.layouts.length - 1; i >= 0; i--) {\n // Wrap with per-layout error boundary before wrapping with layout.\n // This places the ErrorBoundary inside the layout, catching errors\n // from child segments (matching Next.js per-segment error handling).\n if (route.errors && route.errors[i]?.default) {\n element = createElement(ErrorBoundary, {\n fallback: route.errors[i].default,\n children: element,\n });\n }\n\n const LayoutComponent = route.layouts[i]?.default;\n if (LayoutComponent) {\n // Per-layout NotFoundBoundary: wraps this layout's children so that\n // notFound() thrown from a child layout is caught here.\n // Matches Next.js behavior where each segment has its own boundary.\n // The boundary at level N catches errors from Layout[N+1] and below,\n // but NOT from Layout[N] itself (which propagates to level N-1).\n {\n const LayoutNotFound = route.notFounds?.[i]?.default;\n if (LayoutNotFound) {\n element = createElement(NotFoundBoundary, {\n fallback: createElement(LayoutNotFound),\n children: element,\n });\n }\n }\n\n const layoutProps = { children: element, params: makeThenableParams(params) };\n\n // Add parallel slot elements to the layout that defines them.\n // Each slot has a layoutIndex indicating which layout it belongs to.\n if (route.slots) {\n for (const [slotName, slotMod] of Object.entries(route.slots)) {\n // Attach slot to the layout at its layoutIndex, or to the innermost layout if -1\n const targetIdx = slotMod.layoutIndex >= 0 ? slotMod.layoutIndex : route.layouts.length - 1;\n if (i !== targetIdx) continue;\n // Check if this slot has an intercepting route that should activate\n let SlotPage = null;\n let slotParams = params;\n\n if (opts && opts.interceptSlot === slotName && opts.interceptPage) {\n // Use the intercepting route's page component\n SlotPage = opts.interceptPage.default;\n slotParams = opts.interceptParams || params;\n } else {\n SlotPage = slotMod.page?.default || slotMod.default?.default;\n }\n\n if (SlotPage) {\n let slotElement = createElement(SlotPage, { params: makeThenableParams(slotParams) });\n // Wrap with slot-specific layout if present.\n // In Next.js, @slot/layout.tsx wraps the slot's page content\n // before it is passed as a prop to the parent layout.\n const SlotLayout = slotMod.layout?.default;\n if (SlotLayout) {\n slotElement = createElement(SlotLayout, {\n children: slotElement,\n params: makeThenableParams(slotParams),\n });\n }\n // Wrap with slot-specific loading if present\n if (slotMod.loading?.default) {\n slotElement = createElement(Suspense,\n { fallback: createElement(slotMod.loading.default) },\n slotElement,\n );\n }\n // Wrap with slot-specific error boundary if present\n if (slotMod.error?.default) {\n slotElement = createElement(ErrorBoundary, {\n fallback: slotMod.error.default,\n children: slotElement,\n });\n }\n layoutProps[slotName] = slotElement;\n }\n }\n }\n\n element = createElement(LayoutComponent, layoutProps);\n\n // Wrap the layout with LayoutSegmentProvider so useSelectedLayoutSegments()\n // called INSIDE this layout knows its URL segment depth. The depth tells the\n // hook how many URL segments are above this layout, so it returns only the\n // segments below. We wrap the layout (not just children) because hooks are\n // called from components rendered inside the layout's own JSX.\n const layoutDepth = route.layoutSegmentDepths ? route.layoutSegmentDepths[i] : 0;\n element = createElement(LayoutSegmentProvider, { depth: layoutDepth }, element);\n }\n }\n\n // Wrap with global error boundary if app/global-error.tsx exists.\n // This catches errors in the root layout itself.\n ${globalErrorVar ? `\n const GlobalErrorComponent = ${globalErrorVar}.default;\n if (GlobalErrorComponent) {\n element = createElement(ErrorBoundary, {\n fallback: GlobalErrorComponent,\n children: element,\n });\n }\n ` : \"\"}\n\n return element;\n}\n\n${middlewarePath ? generateMiddlewareMatcherCode(\"modern\") : \"\"}\n\nconst __basePath = ${JSON.stringify(bp)};\nconst __trailingSlash = ${JSON.stringify(ts)};\nconst __configRedirects = ${JSON.stringify(redirects)};\nconst __configRewrites = ${JSON.stringify(rewrites)};\nconst __configHeaders = ${JSON.stringify(headers)};\nconst __allowedOrigins = ${JSON.stringify(allowedOrigins)};\n\n${generateDevOriginCheckCode(config?.allowedDevOrigins)}\n\n// ── CSRF origin validation for server actions ───────────────────────────\n// Matches Next.js behavior: compare the Origin header against the Host header.\n// If they don't match, the request is rejected with 403 unless the origin is\n// in the allowedOrigins list (from experimental.serverActions.allowedOrigins).\nfunction __isOriginAllowed(origin, allowed) {\n for (const pattern of allowed) {\n if (pattern.startsWith(\"*.\")) {\n // Wildcard: *.example.com matches sub.example.com, a.b.example.com\n const suffix = pattern.slice(1); // \".example.com\"\n if (origin === pattern.slice(2) || origin.endsWith(suffix)) return true;\n } else if (origin === pattern) {\n return true;\n }\n }\n return false;\n}\n\nfunction __validateCsrfOrigin(request) {\n const originHeader = request.headers.get(\"origin\");\n // If there's no Origin header, allow the request — same-origin requests\n // from non-fetch navigations (e.g. SSR) may lack an Origin header.\n // The x-rsc-action custom header already provides protection against simple\n // form-based CSRF since custom headers can't be set by cross-origin forms.\n if (!originHeader || originHeader === \"null\") return null;\n\n let originHost;\n try {\n originHost = new URL(originHeader).host.toLowerCase();\n } catch {\n return new Response(\"Forbidden\", { status: 403, headers: { \"Content-Type\": \"text/plain\" } });\n }\n\n // Only use the Host header for origin comparison — never trust\n // X-Forwarded-Host here, since it can be freely set by the client\n // and would allow the check to be bypassed if it matched a spoofed\n // Origin. The prod server's resolveHost() handles trusted proxy\n // scenarios separately.\n const hostHeader = (\n request.headers.get(\"host\") ||\n \"\"\n ).split(\",\")[0].trim().toLowerCase();\n\n if (!hostHeader) return null;\n\n // Same origin — allow\n if (originHost === hostHeader) return null;\n\n // Check allowedOrigins from next.config.js\n if (__allowedOrigins.length > 0 && __isOriginAllowed(originHost, __allowedOrigins)) return null;\n\n console.warn(\n \\`[vinext] CSRF origin mismatch: origin \"\\${originHost}\" does not match host \"\\${hostHeader}\". Blocking server action request.\\`\n );\n return new Response(\"Forbidden\", { status: 403, headers: { \"Content-Type\": \"text/plain\" } });\n}\n\n// ── ReDoS-safe regex compilation ────────────────────────────────────────\n${generateSafeRegExpCode(\"modern\")}\n\n// ── Path normalization ──────────────────────────────────────────────────\n${generateNormalizePathCode(\"modern\")}\n\n// ── Config pattern matching (redirects, rewrites, headers) ──────────────\nfunction __matchConfigPattern(pathname, pattern) {\n if (pattern.includes(\"(\") || pattern.includes(\"\\\\\\\\\") || /:[\\\\w-]+[*+][^/]/.test(pattern) || /:[\\\\w-]+\\\\./.test(pattern)) {\n try {\n const paramNames = [];\n const regexStr = pattern\n .replace(/\\\\./g, \"\\\\\\\\.\")\n .replace(/:([\\\\w-]+)\\\\*(?:\\\\(([^)]+)\\\\))?/g, (_, name, c) => { paramNames.push(name); return c ? \"(\" + c + \")\" : \"(.*)\"; })\n .replace(/:([\\\\w-]+)\\\\+(?:\\\\(([^)]+)\\\\))?/g, (_, name, c) => { paramNames.push(name); return c ? \"(\" + c + \")\" : \"(.+)\"; })\n .replace(/:([\\\\w-]+)\\\\(([^)]+)\\\\)/g, (_, name, c) => { paramNames.push(name); return \"(\" + c + \")\"; })\n .replace(/:([\\\\w-]+)/g, (_, name) => { paramNames.push(name); return \"([^/]+)\"; });\n const re = __safeRegExp(\"^\" + regexStr + \"$\");\n if (!re) return null;\n const match = re.exec(pathname);\n if (!match) return null;\n const params = Object.create(null);\n for (let i = 0; i < paramNames.length; i++) params[paramNames[i]] = match[i + 1] || \"\";\n return params;\n } catch { /* fall through */ }\n }\n const catchAllMatch = pattern.match(/:([\\\\w-]+)(\\\\*|\\\\+)$/);\n if (catchAllMatch) {\n const prefix = pattern.slice(0, pattern.lastIndexOf(\":\"));\n const paramName = catchAllMatch[1];\n const isPlus = catchAllMatch[2] === \"+\";\n if (!pathname.startsWith(prefix.replace(/\\\\/$/, \"\"))) return null;\n const rest = pathname.slice(prefix.replace(/\\\\/$/, \"\").length);\n if (isPlus && (!rest || rest === \"/\")) return null;\n let restValue = rest.startsWith(\"/\") ? rest.slice(1) : rest;\n // NOTE: Do NOT decodeURIComponent here. The pathname is already decoded at\n // the request entry point. Decoding again would produce incorrect param values.\n return { [paramName]: restValue };\n }\n const parts = pattern.split(\"/\");\n const pathParts = pathname.split(\"/\");\n if (parts.length !== pathParts.length) return null;\n const params = Object.create(null);\n for (let i = 0; i < parts.length; i++) {\n if (parts[i].startsWith(\":\")) params[parts[i].slice(1)] = pathParts[i];\n else if (parts[i] !== pathParts[i]) return null;\n }\n return params;\n}\n\nfunction __parseCookies(cookieHeader) {\n if (!cookieHeader) return {};\n const cookies = {};\n for (const part of cookieHeader.split(\";\")) {\n const eq = part.indexOf(\"=\");\n if (eq === -1) continue;\n const key = part.slice(0, eq).trim();\n const value = part.slice(eq + 1).trim();\n if (key) cookies[key] = value;\n }\n return cookies;\n}\n\nfunction __checkSingleCondition(condition, ctx) {\n switch (condition.type) {\n case \"header\": {\n const v = ctx.headers.get(condition.key);\n if (v === null) return false;\n if (condition.value !== undefined) { const re = __safeRegExp(condition.value); return re ? re.test(v) : v === condition.value; }\n return true;\n }\n case \"cookie\": {\n const v = ctx.cookies[condition.key];\n if (v === undefined) return false;\n if (condition.value !== undefined) { const re = __safeRegExp(condition.value); return re ? re.test(v) : v === condition.value; }\n return true;\n }\n case \"query\": {\n const v = ctx.query.get(condition.key);\n if (v === null) return false;\n if (condition.value !== undefined) { const re = __safeRegExp(condition.value); return re ? re.test(v) : v === condition.value; }\n return true;\n }\n case \"host\": {\n if (condition.value !== undefined) { const re = __safeRegExp(condition.value); return re ? re.test(ctx.host) : ctx.host === condition.value; }\n return ctx.host === condition.key;\n }\n default: return false;\n }\n}\n\nfunction __checkHasConditions(has, missing, ctx) {\n if (has) { for (const c of has) { if (!__checkSingleCondition(c, ctx)) return false; } }\n if (missing) { for (const c of missing) { if (__checkSingleCondition(c, ctx)) return false; } }\n return true;\n}\n\nfunction __buildRequestContext(request) {\n const url = new URL(request.url);\n return {\n headers: request.headers,\n cookies: __parseCookies(request.headers.get(\"cookie\")),\n query: url.searchParams,\n host: request.headers.get(\"host\") || url.host,\n };\n}\n\nfunction __sanitizeDestination(dest) {\n if (dest.startsWith(\"http://\") || dest.startsWith(\"https://\")) return dest;\n dest = dest.replace(/^[\\\\\\\\/]+/, \"/\");\n return dest;\n}\n\nfunction __applyConfigRedirects(pathname, ctx) {\n for (const rule of __configRedirects) {\n const params = __matchConfigPattern(pathname, rule.source);\n if (params) {\n if (ctx && (rule.has || rule.missing)) { if (!__checkHasConditions(rule.has, rule.missing, ctx)) continue; }\n let dest = rule.destination;\n for (const [key, value] of Object.entries(params)) { dest = dest.replace(\":\" + key + \"*\", value); dest = dest.replace(\":\" + key + \"+\", value); dest = dest.replace(\":\" + key, value); }\n dest = __sanitizeDestination(dest);\n return { destination: dest, permanent: rule.permanent };\n }\n }\n return null;\n}\n\nfunction __applyConfigRewrites(pathname, rules, ctx) {\n for (const rule of rules) {\n const params = __matchConfigPattern(pathname, rule.source);\n if (params) {\n if (ctx && (rule.has || rule.missing)) { if (!__checkHasConditions(rule.has, rule.missing, ctx)) continue; }\n let dest = rule.destination;\n for (const [key, value] of Object.entries(params)) { dest = dest.replace(\":\" + key + \"*\", value); dest = dest.replace(\":\" + key + \"+\", value); dest = dest.replace(\":\" + key, value); }\n dest = __sanitizeDestination(dest);\n return dest;\n }\n }\n return null;\n}\n\nfunction __isExternalUrl(url) {\n return /^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith(\"//\");\n}\n\n/**\n * Maximum server-action request body size (1 MB).\n * Matches the Next.js default for serverActions.bodySizeLimit.\n * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/serverActions#bodysizelimit\n * Prevents unbounded request body buffering.\n */\nvar __MAX_ACTION_BODY_SIZE = 1 * 1024 * 1024;\n\n/**\n * Read a request body as text with a size limit.\n * Enforces the limit on the actual byte stream to prevent bypasses\n * via chunked transfer-encoding where Content-Length is absent or spoofed.\n */\nasync function __readBodyWithLimit(request, maxBytes) {\n if (!request.body) return \"\";\n var reader = request.body.getReader();\n var decoder = new TextDecoder();\n var chunks = [];\n var totalSize = 0;\n for (;;) {\n var result = await reader.read();\n if (result.done) break;\n totalSize += result.value.byteLength;\n if (totalSize > maxBytes) {\n reader.cancel();\n throw new Error(\"Request body too large\");\n }\n chunks.push(decoder.decode(result.value, { stream: true }));\n }\n chunks.push(decoder.decode());\n return chunks.join(\"\");\n}\n\n/**\n * Read a request body as FormData with a size limit.\n * Consumes the body stream with a byte counter and then parses the\n * collected bytes as multipart form data via the Response constructor.\n */\nasync function __readFormDataWithLimit(request, maxBytes) {\n if (!request.body) return new FormData();\n var reader = request.body.getReader();\n var chunks = [];\n var totalSize = 0;\n for (;;) {\n var result = await reader.read();\n if (result.done) break;\n totalSize += result.value.byteLength;\n if (totalSize > maxBytes) {\n reader.cancel();\n throw new Error(\"Request body too large\");\n }\n chunks.push(result.value);\n }\n // Reconstruct a Response with the original Content-Type so that\n // the FormData parser can handle multipart boundaries correctly.\n var combined = new Uint8Array(totalSize);\n var offset = 0;\n for (var chunk of chunks) {\n combined.set(chunk, offset);\n offset += chunk.byteLength;\n }\n var contentType = request.headers.get(\"content-type\") || \"\";\n return new Response(combined, { headers: { \"Content-Type\": contentType } }).formData();\n}\n\nconst __hopByHopHeaders = new Set([\"connection\",\"keep-alive\",\"proxy-authenticate\",\"proxy-authorization\",\"te\",\"trailers\",\"transfer-encoding\",\"upgrade\"]);\n\nasync function __proxyExternalRequest(request, externalUrl) {\n const originalUrl = new URL(request.url);\n const targetUrl = new URL(externalUrl);\n for (const [key, value] of originalUrl.searchParams) {\n if (!targetUrl.searchParams.has(key)) targetUrl.searchParams.set(key, value);\n }\n const headers = new Headers(request.headers);\n headers.set(\"host\", targetUrl.host);\n headers.delete(\"connection\");\n // Strip credentials and internal headers to prevent leaking auth tokens,\n // session cookies, and middleware internals to third-party origins.\n headers.delete(\"cookie\");\n headers.delete(\"authorization\");\n headers.delete(\"x-api-key\");\n headers.delete(\"proxy-authorization\");\n for (const key of [...headers.keys()]) {\n if (key.startsWith(\"x-middleware-\")) headers.delete(key);\n }\n const method = request.method;\n const hasBody = method !== \"GET\" && method !== \"HEAD\";\n const init = { method, headers, redirect: \"manual\", signal: AbortSignal.timeout(30000) };\n if (hasBody && request.body) { init.body = request.body; init.duplex = \"half\"; }\n let upstream;\n try { upstream = await fetch(targetUrl.href, init); }\n catch (e) {\n if (e && e.name === \"TimeoutError\") return new Response(\"Gateway Timeout\", { status: 504 });\n console.error(\"[vinext] External rewrite proxy error:\", e); return new Response(\"Bad Gateway\", { status: 502 });\n }\n const respHeaders = new Headers();\n upstream.headers.forEach(function(value, key) { if (!__hopByHopHeaders.has(key.toLowerCase())) respHeaders.append(key, value); });\n return new Response(upstream.body, { status: upstream.status, statusText: upstream.statusText, headers: respHeaders });\n}\n\nfunction __applyConfigHeaders(pathname, ctx) {\n const result = [];\n for (const rule of __configHeaders) {\n const groups = [];\n const withPlaceholders = rule.source.replace(/\\\\(([^)]+)\\\\)/g, (_, inner) => {\n groups.push(inner);\n return \"___GROUP_\" + (groups.length - 1) + \"___\";\n });\n const escaped = withPlaceholders\n .replace(/\\\\./g, \"\\\\\\\\.\")\n .replace(/\\\\+/g, \"\\\\\\\\+\")\n .replace(/\\\\?/g, \"\\\\\\\\?\")\n .replace(/\\\\*/g, \".*\")\n .replace(/:[\\\\w-]+/g, \"[^/]+\")\n .replace(/___GROUP_(\\\\d+)___/g, (_, idx) => \"(\" + groups[Number(idx)] + \")\");\n const sourceRegex = __safeRegExp(\"^\" + escaped + \"$\");\n if (sourceRegex && sourceRegex.test(pathname)) {\n if (ctx && (rule.has || rule.missing)) {\n if (!__checkHasConditions(rule.has, rule.missing, ctx)) continue;\n }\n result.push(...rule.headers);\n }\n }\n return result;\n}\n\nexport default async function handler(request) {\n // Wrap the entire request in nested AsyncLocalStorage.run() scopes to ensure\n // per-request isolation for all state modules. Each runWith*() creates an\n // ALS scope that propagates through all async continuations (including RSC\n // streaming), preventing state leakage between concurrent requests on\n // Cloudflare Workers and other concurrent runtimes.\n const headersCtx = headersContextFromRequest(request);\n return runWithHeadersContext(headersCtx, () =>\n _runWithNavigationContext(() =>\n _runWithCacheState(() =>\n _runWithPrivateCache(() =>\n runWithFetchCache(async () => {\n const __reqCtx = __buildRequestContext(request);\n // Per-request container for middleware state. Passed into\n // _handleRequest which fills in .headers and .status;\n // avoids module-level variables that race on Workers.\n const _mwCtx = { headers: null, status: null };\n const response = await _handleRequest(request, __reqCtx, _mwCtx);\n // Apply custom headers from next.config.js to non-redirect responses.\n // Skip redirects (3xx) because Response.redirect() creates immutable headers,\n // and Next.js doesn't apply custom headers to redirects anyway.\n if (response && response.headers && !(response.status >= 300 && response.status < 400)) {\n if (__configHeaders.length) {\n const url = new URL(request.url);\n let pathname;\n try { pathname = __normalizePath(decodeURIComponent(url.pathname)); } catch { pathname = url.pathname; }\n ${bp ? `if (pathname.startsWith(${JSON.stringify(bp)})) pathname = pathname.slice(${JSON.stringify(bp)}.length) || \"/\";` : \"\"}\n const extraHeaders = __applyConfigHeaders(pathname, __reqCtx);\n for (const h of extraHeaders) {\n // Use append() for headers where multiple values must coexist\n // (Vary, Set-Cookie). Using set() on these would destroy\n // existing values like \"Vary: RSC, Accept\" which are critical\n // for correct CDN caching behavior.\n const lk = h.key.toLowerCase();\n if (lk === \"vary\" || lk === \"set-cookie\") {\n response.headers.append(h.key, h.value);\n } else {\n response.headers.set(h.key, h.value);\n }\n }\n }\n // Merge middleware response headers into the final response.\n // This runs at the top level so every response path (route\n // handlers, server actions, metadata, errors, etc.) gets them.\n if (_mwCtx.headers) {\n for (const [key, value] of _mwCtx.headers) {\n response.headers.append(key, value);\n }\n }\n }\n return response;\n })\n )\n )\n )\n );\n}\n\nasync function _handleRequest(request, __reqCtx, _mwCtx) {\n const __reqStart = process.env.NODE_ENV !== \"production\" ? performance.now() : 0;\n let __compileEnd;\n let __renderEnd;\n // __reqStart is included in the timing header so the Node logging middleware\n // can compute true compile time as: handlerStart - middlewareStart.\n // Format: \"handlerStart,compileMs,renderMs\" - all as integers (ms). Dev-only.\n const url = new URL(request.url);\n\n // ── Cross-origin request protection ─────────────────────────────────\n // Block requests from non-localhost origins to prevent data exfiltration.\n const __originBlock = __validateDevRequestOrigin(request);\n if (__originBlock) return __originBlock;\n\n // Guard against protocol-relative URL open redirects.\n // Paths like //example.com/ would be redirected to //example.com by the\n // trailing-slash normalizer, which browsers interpret as http://example.com.\n // Backslashes are equivalent to forward slashes in the URL spec\n // (e.g. /\\\\evil.com is treated as //evil.com by browsers and the URL constructor).\n // Next.js returns 404 for these paths. Check the RAW pathname before\n // normalization so the guard fires before normalizePath collapses //.\n if (url.pathname.replaceAll(\"\\\\\\\\\", \"/\").startsWith(\"//\")) {\n return new Response(\"404 Not Found\", { status: 404 });\n }\n\n // Decode percent-encoding and normalize pathname to canonical form.\n // decodeURIComponent prevents /%61dmin from bypassing /admin matchers.\n // __normalizePath collapses //foo///bar → /foo/bar, resolves . and .. segments.\n let decodedUrlPathname;\n try { decodedUrlPathname = decodeURIComponent(url.pathname); } catch (e) {\n return new Response(\"Bad Request\", { status: 400 });\n }\n let pathname = __normalizePath(decodedUrlPathname);\n\n ${bp ? `\n // Strip basePath prefix\n if (__basePath && pathname.startsWith(__basePath)) {\n pathname = pathname.slice(__basePath.length) || \"/\";\n }\n ` : \"\"}\n\n // Trailing slash normalization (redirect to canonical form)\n if (pathname !== \"/\" && !pathname.startsWith(\"/api\")) {\n const hasTrailing = pathname.endsWith(\"/\");\n if (__trailingSlash && !hasTrailing && !pathname.endsWith(\".rsc\")) {\n return Response.redirect(new URL(__basePath + pathname + \"/\" + url.search, request.url), 308);\n } else if (!__trailingSlash && hasTrailing) {\n return Response.redirect(new URL(__basePath + pathname.replace(/\\\\/+$/, \"\") + url.search, request.url), 308);\n }\n }\n\n // ── Apply redirects from next.config.js ───────────────────────────────\n if (__configRedirects.length) {\n // Strip .rsc suffix before matching redirect rules - RSC (client-side nav) requests\n // arrive as /some/path.rsc but redirect patterns are defined without it (e.g.\n // /some/path). Without this, soft-nav fetches bypass all config redirects.\n const __redirPathname = pathname.endsWith(\".rsc\") ? pathname.slice(0, -4) : pathname;\n const __redir = __applyConfigRedirects(__redirPathname, __reqCtx);\n if (__redir) {\n const __redirDest = __sanitizeDestination(\n __basePath && !__redir.destination.startsWith(__basePath)\n ? __basePath + __redir.destination\n : __redir.destination\n );\n return new Response(null, {\n status: __redir.permanent ? 308 : 307,\n headers: { Location: __redirDest },\n });\n }\n }\n\n // ── Apply beforeFiles rewrites from next.config.js ────────────────────\n if (__configRewrites.beforeFiles && __configRewrites.beforeFiles.length) {\n // Strip .rsc suffix before matching rewrite rules — same reason as redirects above.\n const __rewritePathname = pathname.endsWith(\".rsc\") ? pathname.slice(0, -4) : pathname;\n const __rewritten = __applyConfigRewrites(__rewritePathname, __configRewrites.beforeFiles, __reqCtx);\n if (__rewritten) {\n if (__isExternalUrl(__rewritten)) {\n setHeadersContext(null);\n setNavigationContext(null);\n return __proxyExternalRequest(request, __rewritten);\n }\n pathname = __rewritten;\n }\n }\n\n const isRscRequest = pathname.endsWith(\".rsc\") || request.headers.get(\"accept\")?.includes(\"text/x-component\");\n let cleanPathname = pathname.replace(/\\\\.rsc$/, \"\");\n\n // Middleware response headers and custom rewrite status are stored in\n // _mwCtx (per-request container) so handler() can merge them into\n // every response path without module-level state that races on Workers.\n\n ${middlewarePath ? `\n // Run proxy/middleware if present and path matches.\n // Validate exports match the file type (proxy.ts vs middleware.ts), matching Next.js behavior.\n // https://github.com/vercel/next.js/blob/canary/test/e2e/app-dir/proxy-missing-export/proxy-missing-export.test.ts\n const _isProxy = ${JSON.stringify(isProxyFile(middlewarePath))};\n const middlewareFn = _isProxy\n ? (middlewareModule.proxy ?? middlewareModule.default)\n : (middlewareModule.middleware ?? middlewareModule.default);\n if (typeof middlewareFn !== \"function\") {\n const _fileType = _isProxy ? \"Proxy\" : \"Middleware\";\n const _expectedExport = _isProxy ? \"proxy\" : \"middleware\";\n throw new Error(\"The \" + _fileType + \" file must export a function named \\`\" + _expectedExport + \"\\` or a \\`default\\` function.\");\n }\n const middlewareMatcher = middlewareModule.config?.matcher;\n if (matchesMiddleware(cleanPathname, middlewareMatcher)) {\n try {\n // Wrap in NextRequest so middleware gets .nextUrl, .cookies, .geo, .ip, etc.\n // Always construct a new Request with the fully decoded + normalized pathname\n // so middleware and the router see the same canonical path.\n const mwUrl = new URL(request.url);\n mwUrl.pathname = cleanPathname;\n const mwRequest = new Request(mwUrl, request);\n const nextRequest = mwRequest instanceof NextRequest ? mwRequest : new NextRequest(mwRequest);\n const mwResponse = await middlewareFn(nextRequest);\n if (mwResponse) {\n // Check for x-middleware-next (continue)\n if (mwResponse.headers.get(\"x-middleware-next\") === \"1\") {\n // Middleware wants to continue — collect all headers except the two\n // control headers we've already consumed. x-middleware-request-*\n // headers are kept so applyMiddlewareRequestHeaders() can unpack them;\n // the blanket strip loop after that call removes every remaining\n // x-middleware-* header before the set is merged into the response.\n _mwCtx.headers = new Headers();\n for (const [key, value] of mwResponse.headers) {\n if (key !== \"x-middleware-next\" && key !== \"x-middleware-rewrite\") {\n _mwCtx.headers.append(key, value);\n }\n }\n } else {\n // Check for redirect\n if (mwResponse.status >= 300 && mwResponse.status < 400) {\n return mwResponse;\n }\n // Check for rewrite\n const rewriteUrl = mwResponse.headers.get(\"x-middleware-rewrite\");\n if (rewriteUrl) {\n const rewriteParsed = new URL(rewriteUrl, request.url);\n cleanPathname = rewriteParsed.pathname;\n // Capture custom status code from rewrite (e.g. NextResponse.rewrite(url, { status: 403 }))\n if (mwResponse.status !== 200) {\n _mwCtx.status = mwResponse.status;\n }\n // Also save any other headers from the rewrite response\n _mwCtx.headers = new Headers();\n for (const [key, value] of mwResponse.headers) {\n if (key !== \"x-middleware-next\" && key !== \"x-middleware-rewrite\") {\n _mwCtx.headers.append(key, value);\n }\n }\n } else {\n // Middleware returned a custom response\n return mwResponse;\n }\n }\n }\n } catch (err) {\n console.error(\"[vinext] Middleware error:\", err);\n return new Response(\"Internal Server Error\", { status: 500 });\n }\n }\n\n // Unpack x-middleware-request-* headers into the request context so that\n // headers() returns the middleware-modified headers instead of the original\n // request headers. Strip ALL x-middleware-* headers from the set that will\n // be merged into the outgoing HTTP response — this prefix is reserved for\n // internal routing signals and must never reach clients.\n if (_mwCtx.headers) {\n applyMiddlewareRequestHeaders(_mwCtx.headers);\n for (const key of [..._mwCtx.headers.keys()]) {\n if (key.startsWith(\"x-middleware-\")) {\n _mwCtx.headers.delete(key);\n }\n }\n }\n ` : \"\"}\n\n // ── Image optimization passthrough (dev mode — no transformation) ───────\n if (cleanPathname === \"/_vinext/image\") {\n const __rawImgUrl = url.searchParams.get(\"url\");\n // Normalize backslashes: browsers and the URL constructor treat\n // /\\\\evil.com as protocol-relative (//evil.com), bypassing the // check.\n const __imgUrl = __rawImgUrl?.replaceAll(\"\\\\\\\\\", \"/\") ?? null;\n // Allowlist: must start with \"/\" but not \"//\" — blocks absolute URLs,\n // protocol-relative, backslash variants, and exotic schemes.\n if (!__imgUrl || !__imgUrl.startsWith(\"/\") || __imgUrl.startsWith(\"//\")) {\n return new Response(!__rawImgUrl ? \"Missing url parameter\" : \"Only relative URLs allowed\", { status: 400 });\n }\n // Validate the constructed URL's origin hasn't changed (defense in depth).\n const __resolvedImg = new URL(__imgUrl, request.url);\n if (__resolvedImg.origin !== url.origin) {\n return new Response(\"Only relative URLs allowed\", { status: 400 });\n }\n // In dev, redirect to the original asset URL so Vite's static serving handles it.\n return Response.redirect(__resolvedImg.href, 302);\n }\n\n // Handle metadata routes (sitemap.xml, robots.txt, manifest.webmanifest, etc.)\n for (const metaRoute of metadataRoutes) {\n if (cleanPathname === metaRoute.servedUrl) {\n if (metaRoute.isDynamic) {\n // Dynamic metadata route — call the default export and serialize\n const metaFn = metaRoute.module.default;\n if (typeof metaFn === \"function\") {\n const result = await metaFn();\n let body;\n // If it's already a Response (e.g., ImageResponse), return directly\n if (result instanceof Response) return result;\n // Serialize based on type\n if (metaRoute.type === \"sitemap\") body = sitemapToXml(result);\n else if (metaRoute.type === \"robots\") body = robotsToText(result);\n else if (metaRoute.type === \"manifest\") body = manifestToJson(result);\n else body = JSON.stringify(result);\n return new Response(body, {\n headers: { \"Content-Type\": metaRoute.contentType },\n });\n }\n } else {\n // Static metadata file — decode from embedded base64 data\n try {\n const binary = atob(metaRoute.fileDataBase64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return new Response(bytes, {\n headers: {\n \"Content-Type\": metaRoute.contentType,\n \"Cache-Control\": \"public, max-age=0, must-revalidate\",\n },\n });\n } catch {\n return new Response(\"Not Found\", { status: 404 });\n }\n }\n }\n }\n\n // Set navigation context for Server Components.\n // Note: Headers context is already set by runWithHeadersContext in the handler wrapper.\n setNavigationContext({\n pathname: cleanPathname,\n searchParams: url.searchParams,\n params: {},\n });\n\n // Handle server action POST requests\n const actionId = request.headers.get(\"x-rsc-action\");\n if (request.method === \"POST\" && actionId) {\n // ── CSRF protection ─────────────────────────────────────────────────\n // Verify that the Origin header matches the Host header to prevent\n // cross-site request forgery, matching Next.js server action behavior.\n const csrfResponse = __validateCsrfOrigin(request);\n if (csrfResponse) return csrfResponse;\n\n // ── Body size limit ─────────────────────────────────────────────────\n // Reject payloads larger than the configured limit.\n // Check Content-Length as a fast path, then enforce on the actual\n // stream to prevent bypasses via chunked transfer-encoding.\n const contentLength = parseInt(request.headers.get(\"content-length\") || \"0\", 10);\n if (contentLength > __MAX_ACTION_BODY_SIZE) {\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(\"Payload Too Large\", { status: 413 });\n }\n\n try {\n const contentType = request.headers.get(\"content-type\") || \"\";\n let body;\n try {\n body = contentType.startsWith(\"multipart/form-data\")\n ? await __readFormDataWithLimit(request, __MAX_ACTION_BODY_SIZE)\n : await __readBodyWithLimit(request, __MAX_ACTION_BODY_SIZE);\n } catch (sizeErr) {\n if (sizeErr && sizeErr.message === \"Request body too large\") {\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(\"Payload Too Large\", { status: 413 });\n }\n throw sizeErr;\n }\n const temporaryReferences = createTemporaryReferenceSet();\n const args = await decodeReply(body, { temporaryReferences });\n const action = await loadServerAction(actionId);\n let returnValue;\n let actionRedirect = null;\n try {\n const data = await action.apply(null, args);\n returnValue = { ok: true, data };\n } catch (e) {\n // Detect redirect() / permanentRedirect() called inside the action.\n // These throw errors with digest \"NEXT_REDIRECT;replace;url[;status]\".\n // The URL is encodeURIComponent-encoded to prevent semicolons in the URL\n // from corrupting the delimiter-based digest format.\n if (e && typeof e === \"object\" && \"digest\" in e) {\n const digest = String(e.digest);\n if (digest.startsWith(\"NEXT_REDIRECT;\")) {\n const parts = digest.split(\";\");\n actionRedirect = {\n url: decodeURIComponent(parts[2]),\n type: parts[1] || \"replace\", // \"push\" or \"replace\"\n status: parts[3] ? parseInt(parts[3], 10) : 307,\n };\n returnValue = { ok: true, data: undefined };\n } else if (digest === \"NEXT_NOT_FOUND\" || digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")) {\n // notFound() / forbidden() / unauthorized() in action — package as error\n returnValue = { ok: false, data: e };\n } else {\n // Non-navigation digest error — sanitize in production to avoid\n // leaking internal details (connection strings, paths, etc.)\n console.error(\"[vinext] Server action error:\", e);\n returnValue = { ok: false, data: __sanitizeErrorForClient(e) };\n }\n } else {\n // Unhandled error — sanitize in production to avoid leaking\n // internal details (database errors, file paths, stack traces, etc.)\n console.error(\"[vinext] Server action error:\", e);\n returnValue = { ok: false, data: __sanitizeErrorForClient(e) };\n }\n }\n\n // If the action called redirect(), signal the client to navigate.\n // We can't use a real HTTP redirect (the fetch would follow it automatically\n // and receive a page HTML instead of RSC stream). Instead, we return a 200\n // with x-action-redirect header that the client entry detects and handles.\n if (actionRedirect) {\n const actionPendingCookies = getAndClearPendingCookies();\n const actionDraftCookie = getDraftModeCookieHeader();\n setHeadersContext(null);\n setNavigationContext(null);\n const redirectHeaders = new Headers({\n \"Content-Type\": \"text/x-component; charset=utf-8\",\n \"Vary\": \"RSC, Accept\",\n \"x-action-redirect\": actionRedirect.url,\n \"x-action-redirect-type\": actionRedirect.type,\n \"x-action-redirect-status\": String(actionRedirect.status),\n });\n for (const cookie of actionPendingCookies) {\n redirectHeaders.append(\"Set-Cookie\", cookie);\n }\n if (actionDraftCookie) redirectHeaders.append(\"Set-Cookie\", actionDraftCookie);\n // Send an empty RSC-like body (client will navigate instead of parsing)\n return new Response(\"\", { status: 200, headers: redirectHeaders });\n }\n\n // After the action, re-render the current page so the client\n // gets an updated React tree reflecting any mutations.\n const match = matchRoute(cleanPathname, routes);\n let element;\n if (match) {\n const { route: actionRoute, params: actionParams } = match;\n setNavigationContext({\n pathname: cleanPathname,\n searchParams: url.searchParams,\n params: actionParams,\n });\n element = buildPageElement(actionRoute, actionParams, undefined, url.searchParams);\n } else {\n element = createElement(\"div\", null, \"Page not found\");\n }\n\n const rscStream = renderToReadableStream(\n { root: element, returnValue },\n { temporaryReferences, onError: rscOnError },\n );\n\n // Collect cookies set during the action\n const actionPendingCookies = getAndClearPendingCookies();\n const actionDraftCookie = getDraftModeCookieHeader();\n setHeadersContext(null);\n setNavigationContext(null);\n\n const actionHeaders = { \"Content-Type\": \"text/x-component; charset=utf-8\", \"Vary\": \"RSC, Accept\" };\n const actionResponse = new Response(rscStream, { headers: actionHeaders });\n if (actionPendingCookies.length > 0 || actionDraftCookie) {\n for (const cookie of actionPendingCookies) {\n actionResponse.headers.append(\"Set-Cookie\", cookie);\n }\n if (actionDraftCookie) actionResponse.headers.append(\"Set-Cookie\", actionDraftCookie);\n }\n return actionResponse;\n } catch (err) {\n getAndClearPendingCookies(); // Clear pending cookies on error\n console.error(\"[vinext] Server action error:\", err);\n _reportRequestError(\n err instanceof Error ? err : new Error(String(err)),\n { path: cleanPathname, method: request.method, headers: Object.fromEntries(request.headers.entries()) },\n { routerKind: \"App Router\", routePath: cleanPathname, routeType: \"action\" },\n ).catch((reportErr) => {\n console.error(\"[vinext] Failed to report server action error:\", reportErr);\n });\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(\n process.env.NODE_ENV === \"production\"\n ? \"Internal Server Error\"\n : \"Server action failed: \" + (err && err.message ? err.message : String(err)),\n { status: 500 },\n );\n }\n }\n\n // ── Apply afterFiles rewrites from next.config.js ──────────────────────\n if (__configRewrites.afterFiles && __configRewrites.afterFiles.length) {\n const __afterRewritten = __applyConfigRewrites(cleanPathname, __configRewrites.afterFiles, __reqCtx);\n if (__afterRewritten) {\n if (__isExternalUrl(__afterRewritten)) {\n setHeadersContext(null);\n setNavigationContext(null);\n return __proxyExternalRequest(request, __afterRewritten);\n }\n cleanPathname = __afterRewritten;\n }\n }\n\n let match = matchRoute(cleanPathname, routes);\n\n // ── Fallback rewrites from next.config.js (if no route matched) ───────\n if (!match && __configRewrites.fallback && __configRewrites.fallback.length) {\n const __fallbackRewritten = __applyConfigRewrites(cleanPathname, __configRewrites.fallback, __reqCtx);\n if (__fallbackRewritten) {\n if (__isExternalUrl(__fallbackRewritten)) {\n setHeadersContext(null);\n setNavigationContext(null);\n return __proxyExternalRequest(request, __fallbackRewritten);\n }\n cleanPathname = __fallbackRewritten;\n match = matchRoute(cleanPathname, routes);\n }\n }\n\n if (!match) {\n // Render custom not-found page if available, otherwise plain 404\n const notFoundResponse = await renderNotFoundPage(null, isRscRequest, request);\n if (notFoundResponse) return notFoundResponse;\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(\"Not Found\", { status: 404 });\n }\n\n const { route, params } = match;\n\n // Update navigation context with matched params\n setNavigationContext({\n pathname: cleanPathname,\n searchParams: url.searchParams,\n params,\n });\n\n // Handle route.ts API handlers\n if (route.routeHandler) {\n const handler = route.routeHandler;\n const method = request.method.toUpperCase();\n\n // Collect exported HTTP methods for OPTIONS auto-response and Allow header\n const HTTP_METHODS = [\"GET\", \"HEAD\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\", \"OPTIONS\"];\n const exportedMethods = HTTP_METHODS.filter((m) => typeof handler[m] === \"function\");\n // If GET is exported, HEAD is implicitly supported\n if (exportedMethods.includes(\"GET\") && !exportedMethods.includes(\"HEAD\")) {\n exportedMethods.push(\"HEAD\");\n }\n const hasDefault = typeof handler[\"default\"] === \"function\";\n\n // OPTIONS auto-implementation: respond with Allow header and 204\n if (method === \"OPTIONS\" && typeof handler[\"OPTIONS\"] !== \"function\") {\n const allowMethods = hasDefault ? HTTP_METHODS : exportedMethods;\n if (!allowMethods.includes(\"OPTIONS\")) allowMethods.push(\"OPTIONS\");\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(null, {\n status: 204,\n headers: { \"Allow\": allowMethods.join(\", \") },\n });\n }\n\n // HEAD auto-implementation: run GET handler and strip body\n let handlerFn = handler[method] || handler[\"default\"];\n let isAutoHead = false;\n if (method === \"HEAD\" && typeof handler[\"HEAD\"] !== \"function\" && typeof handler[\"GET\"] === \"function\") {\n handlerFn = handler[\"GET\"];\n isAutoHead = true;\n }\n\n if (typeof handlerFn === \"function\") {\n try {\n const response = await handlerFn(request, { params });\n\n // Collect any Set-Cookie headers from cookies().set()/delete() calls\n const pendingCookies = getAndClearPendingCookies();\n const draftCookie = getDraftModeCookieHeader();\n setHeadersContext(null);\n setNavigationContext(null);\n\n // If we have pending cookies, create a new response with them attached\n if (pendingCookies.length > 0 || draftCookie) {\n const newHeaders = new Headers(response.headers);\n for (const cookie of pendingCookies) {\n newHeaders.append(\"Set-Cookie\", cookie);\n }\n if (draftCookie) newHeaders.append(\"Set-Cookie\", draftCookie);\n\n if (isAutoHead) {\n return new Response(null, {\n status: response.status,\n statusText: response.statusText,\n headers: newHeaders,\n });\n }\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers: newHeaders,\n });\n }\n\n if (isAutoHead) {\n // Strip body for auto-HEAD, preserve headers and status\n return new Response(null, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n }\n return response;\n } catch (err) {\n getAndClearPendingCookies(); // Clear any pending cookies on error\n // Catch redirect() / notFound() thrown from route handlers\n if (err && typeof err === \"object\" && \"digest\" in err) {\n const digest = String(err.digest);\n if (digest.startsWith(\"NEXT_REDIRECT;\")) {\n const parts = digest.split(\";\");\n const redirectUrl = decodeURIComponent(parts[2]);\n const statusCode = parts[3] ? parseInt(parts[3], 10) : 307;\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(null, {\n status: statusCode,\n headers: { Location: new URL(redirectUrl, request.url).toString() },\n });\n }\n if (digest === \"NEXT_NOT_FOUND\" || digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")) {\n const statusCode = digest === \"NEXT_NOT_FOUND\" ? 404 : parseInt(digest.split(\";\")[1], 10);\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(null, { status: statusCode });\n }\n }\n setHeadersContext(null);\n setNavigationContext(null);\n console.error(\"[vinext] Route handler error:\", err);\n _reportRequestError(\n err instanceof Error ? err : new Error(String(err)),\n { path: cleanPathname, method: request.method, headers: Object.fromEntries(request.headers.entries()) },\n { routerKind: \"App Router\", routePath: route.pattern, routeType: \"route\" },\n ).catch((reportErr) => {\n console.error(\"[vinext] Failed to report route handler error:\", reportErr);\n });\n return new Response(null, { status: 500 });\n }\n }\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(null, {\n status: 405,\n headers: { Allow: exportedMethods.join(\", \") },\n });\n }\n\n // Build the component tree: layouts wrapping the page\n const PageComponent = route.page?.default;\n if (!PageComponent) {\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(\"Page has no default export\", { status: 500 });\n }\n\n // Read route segment config from page module exports\n let revalidateSeconds = typeof route.page?.revalidate === \"number\" ? route.page.revalidate : null;\n const dynamicConfig = route.page?.dynamic; // 'auto' | 'force-dynamic' | 'force-static' | 'error'\n const dynamicParamsConfig = route.page?.dynamicParams; // true (default) | false\n const isForceStatic = dynamicConfig === \"force-static\";\n const isDynamicError = dynamicConfig === \"error\";\n\n // force-static: replace headers/cookies context with empty values and\n // clear searchParams so dynamic APIs return defaults instead of real data\n if (isForceStatic) {\n setHeadersContext({ headers: new Headers(), cookies: new Map() });\n setNavigationContext({\n pathname: cleanPathname,\n searchParams: new URLSearchParams(),\n params,\n });\n }\n\n // dynamic = 'error': set a trap context that throws when headers/cookies are accessed\n if (isDynamicError) {\n const errorMsg = 'Page with \\`dynamic = \"error\"\\` used a dynamic API. ' +\n 'This page was expected to be fully static, but headers(), cookies(), ' +\n 'or searchParams was accessed. Remove the dynamic API usage or change ' +\n 'the dynamic config to \"auto\" or \"force-dynamic\".';\n const throwingHeaders = new Proxy(new Headers(), {\n get(target, prop) {\n if (typeof prop === \"string\" && prop !== \"then\") throw new Error(errorMsg);\n return Reflect.get(target, prop);\n },\n });\n const throwingCookies = new Proxy(new Map(), {\n get(target, prop) {\n if (typeof prop === \"string\" && prop !== \"then\") throw new Error(errorMsg);\n return Reflect.get(target, prop);\n },\n });\n setHeadersContext({ headers: throwingHeaders, cookies: throwingCookies });\n setNavigationContext({\n pathname: cleanPathname,\n searchParams: new URLSearchParams(),\n params,\n });\n }\n\n // dynamicParams = false: only params from generateStaticParams are allowed\n if (dynamicParamsConfig === false && route.isDynamic && typeof route.page?.generateStaticParams === \"function\") {\n try {\n // Pass parent params to generateStaticParams (Next.js top-down params passing).\n // Parent params = all matched params that DON'T belong to the leaf page's own dynamic segments.\n // We pass the full matched params; the function uses only what it needs.\n const staticParams = await route.page.generateStaticParams({ params });\n if (Array.isArray(staticParams)) {\n const paramKeys = Object.keys(params);\n const isAllowed = staticParams.some(sp =>\n paramKeys.every(key => {\n const val = params[key];\n const staticVal = sp[key];\n // Allow parent params to not be in the returned set (they're inherited)\n if (staticVal === undefined) return true;\n if (Array.isArray(val)) return JSON.stringify(val) === JSON.stringify(staticVal);\n return String(val) === String(staticVal);\n })\n );\n if (!isAllowed) {\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(\"Not Found\", { status: 404 });\n }\n }\n } catch (err) {\n console.error(\"[vinext] generateStaticParams error:\", err);\n }\n }\n\n // force-dynamic: set no-store Cache-Control\n const isForceDynamic = dynamicConfig === \"force-dynamic\";\n\n // Check for intercepting routes on RSC requests (client-side navigation).\n // If the target URL matches an intercepting route in a parallel slot,\n // render the source route with the intercepting page in the slot.\n let interceptOpts = undefined;\n if (isRscRequest) {\n const intercept = findIntercept(cleanPathname);\n if (intercept) {\n const sourceRoute = routes[intercept.sourceRouteIndex];\n if (sourceRoute && sourceRoute !== route) {\n // Render the source route (e.g. /feed) with the intercepting page in the slot\n const sourceMatch = matchRoute(sourceRoute.pattern, routes);\n const sourceParams = sourceMatch ? sourceMatch.params : {};\n setNavigationContext({\n pathname: cleanPathname,\n searchParams: url.searchParams,\n params: intercept.matchedParams,\n });\n const interceptElement = await buildPageElement(sourceRoute, sourceParams, {\n interceptSlot: intercept.slotName,\n interceptPage: intercept.page,\n interceptParams: intercept.matchedParams,\n }, url.searchParams);\n const interceptStream = renderToReadableStream(interceptElement, { onError: rscOnError });\n setHeadersContext(null);\n setNavigationContext(null);\n return new Response(interceptStream, {\n headers: { \"Content-Type\": \"text/x-component; charset=utf-8\", \"Vary\": \"RSC, Accept\" },\n });\n }\n // If sourceRoute === route, apply intercept opts to the normal render\n interceptOpts = {\n interceptSlot: intercept.slotName,\n interceptPage: intercept.page,\n interceptParams: intercept.matchedParams,\n };\n }\n }\n\n let element;\n try {\n element = await buildPageElement(route, params, interceptOpts, url.searchParams);\n } catch (buildErr) {\n // Check for redirect/notFound/forbidden/unauthorized thrown during metadata resolution or async components\n if (buildErr && typeof buildErr === \"object\" && \"digest\" in buildErr) {\n const digest = String(buildErr.digest);\n if (digest.startsWith(\"NEXT_REDIRECT;\")) {\n const parts = digest.split(\";\");\n const redirectUrl = decodeURIComponent(parts[2]);\n const statusCode = parts[3] ? parseInt(parts[3], 10) : 307;\n setHeadersContext(null);\n setNavigationContext(null);\n return Response.redirect(new URL(redirectUrl, request.url), statusCode);\n }\n if (digest === \"NEXT_NOT_FOUND\" || digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")) {\n const statusCode = digest === \"NEXT_NOT_FOUND\" ? 404 : parseInt(digest.split(\";\")[1], 10);\n const fallbackResp = await renderHTTPAccessFallbackPage(route, statusCode, isRscRequest, request);\n if (fallbackResp) return fallbackResp;\n setHeadersContext(null);\n setNavigationContext(null);\n const statusText = statusCode === 403 ? \"Forbidden\" : statusCode === 401 ? \"Unauthorized\" : \"Not Found\";\n return new Response(statusText, { status: statusCode });\n }\n }\n // Non-special error (e.g. generateMetadata() threw) — render error.tsx if available\n const errorBoundaryResp = await renderErrorBoundaryPage(route, buildErr, isRscRequest, request);\n if (errorBoundaryResp) return errorBoundaryResp;\n throw buildErr;\n }\n\n // Note: CSS is automatically injected by @vitejs/plugin-rsc's\n // rscCssTransform — no manual loadCss() call needed.\n\n // Helper: check if an error is a redirect/notFound/forbidden/unauthorized thrown by the navigation shim\n async function handleRenderError(err) {\n if (err && typeof err === \"object\" && \"digest\" in err) {\n const digest = String(err.digest);\n if (digest.startsWith(\"NEXT_REDIRECT;\")) {\n const parts = digest.split(\";\");\n const redirectUrl = decodeURIComponent(parts[2]);\n const statusCode = parts[3] ? parseInt(parts[3], 10) : 307;\n setHeadersContext(null);\n setNavigationContext(null);\n return Response.redirect(new URL(redirectUrl, request.url), statusCode);\n }\n if (digest === \"NEXT_NOT_FOUND\" || digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")) {\n const statusCode = digest === \"NEXT_NOT_FOUND\" ? 404 : parseInt(digest.split(\";\")[1], 10);\n const fallbackResp = await renderHTTPAccessFallbackPage(route, statusCode, isRscRequest, request);\n if (fallbackResp) return fallbackResp;\n setHeadersContext(null);\n setNavigationContext(null);\n const statusText = statusCode === 403 ? \"Forbidden\" : statusCode === 401 ? \"Unauthorized\" : \"Not Found\";\n return new Response(statusText, { status: statusCode });\n }\n }\n return null;\n }\n\n // Pre-render layout components to catch notFound()/redirect() thrown from layouts.\n // In Next.js, each layout level has its own NotFoundBoundary. When a layout throws\n // notFound(), the parent layout's boundary catches it and renders the parent's\n // not-found.tsx. Since React Flight doesn't activate client error boundaries during\n // RSC rendering, we catch layout-level throws here and render the appropriate\n // fallback page with only the layouts above the throwing one.\n //\n // IMPORTANT: Layout pre-render runs BEFORE page pre-render. In Next.js, layouts\n // render before their children — if a layout throws notFound(), the page never\n // executes. By checking layouts first, we avoid a bug where the page's notFound()\n // triggers renderHTTPAccessFallbackPage with ALL route layouts, but one of those\n // layouts itself throws notFound() during the fallback rendering (causing a 500).\n if (route.layouts && route.layouts.length > 0) {\n const asyncParams = makeThenableParams(params);\n for (let li = route.layouts.length - 1; li >= 0; li--) {\n const LayoutComp = route.layouts[li]?.default;\n if (!LayoutComp) continue;\n try {\n const lr = LayoutComp({ params: asyncParams, children: null });\n if (lr && typeof lr === \"object\" && typeof lr.then === \"function\") await lr;\n } catch (layoutErr) {\n if (layoutErr && typeof layoutErr === \"object\" && \"digest\" in layoutErr) {\n const digest = String(layoutErr.digest);\n if (digest.startsWith(\"NEXT_REDIRECT;\")) {\n const parts = digest.split(\";\");\n const redirectUrl = decodeURIComponent(parts[2]);\n const statusCode = parts[3] ? parseInt(parts[3], 10) : 307;\n setHeadersContext(null);\n setNavigationContext(null);\n return Response.redirect(new URL(redirectUrl, request.url), statusCode);\n }\n if (digest === \"NEXT_NOT_FOUND\" || digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")) {\n const statusCode = digest === \"NEXT_NOT_FOUND\" ? 404 : parseInt(digest.split(\";\")[1], 10);\n // Find the not-found component from the parent level (the boundary that\n // would catch this in Next.js). Walk up from the throwing layout to find\n // the nearest not-found at a parent layout's directory.\n let parentNotFound = null;\n if (route.notFounds) {\n for (let pi = li - 1; pi >= 0; pi--) {\n if (route.notFounds[pi]?.default) {\n parentNotFound = route.notFounds[pi].default;\n break;\n }\n }\n }\n if (!parentNotFound) parentNotFound = ${rootNotFoundVar ? `${rootNotFoundVar}?.default` : \"null\"};\n // Wrap in only the layouts above the throwing one\n const parentLayouts = route.layouts.slice(0, li);\n const fallbackResp = await renderHTTPAccessFallbackPage(\n route, statusCode, isRscRequest, request,\n { boundaryComponent: parentNotFound, layouts: parentLayouts }\n );\n if (fallbackResp) return fallbackResp;\n setHeadersContext(null);\n setNavigationContext(null);\n const statusText = statusCode === 403 ? \"Forbidden\" : statusCode === 401 ? \"Unauthorized\" : \"Not Found\";\n return new Response(statusText, { status: statusCode });\n }\n }\n // Not a special error — let it propagate through normal RSC rendering\n }\n }\n }\n\n // Pre-render the page component to catch redirect()/notFound() thrown synchronously.\n // Server Components are just functions — we can call PageComponent directly to detect\n // these special throws before starting the RSC stream.\n //\n // For routes with a loading.tsx Suspense boundary, we skip awaiting async components.\n // The Suspense boundary + rscOnError will handle redirect/notFound thrown during\n // streaming, and blocking here would defeat streaming (the slow component's delay\n // would be hit before the RSC stream even starts).\n //\n // Because this calls the component outside React's render cycle, hooks like use()\n // trigger \"Invalid hook call\" console.error in dev. Suppress that expected warning.\n const _hasLoadingBoundary = !!(route.loading && route.loading.default);\n const _origConsoleError = console.error;\n console.error = (...args) => {\n if (typeof args[0] === \"string\" && args[0].includes(\"Invalid hook call\")) return;\n _origConsoleError.apply(console, args);\n };\n try {\n const testResult = PageComponent({ params });\n // If it's a promise (async component), only await if there's no loading boundary.\n // With a loading boundary, the Suspense streaming pipeline handles async resolution\n // and any redirect/notFound errors via rscOnError.\n if (testResult && typeof testResult === \"object\" && typeof testResult.then === \"function\") {\n if (!_hasLoadingBoundary) {\n await testResult;\n } else {\n // Suppress unhandled promise rejection — with a loading boundary,\n // redirect/notFound errors are handled by rscOnError during streaming.\n testResult.catch(() => {});\n }\n }\n } catch (preRenderErr) {\n const specialResponse = await handleRenderError(preRenderErr);\n if (specialResponse) return specialResponse;\n // Non-special errors from the pre-render test are expected (e.g. use() hook\n // fails outside React's render cycle, client references can't execute on server).\n // Only redirect/notFound/forbidden/unauthorized are actionable here — other\n // errors will be properly caught during actual RSC/SSR rendering below.\n } finally {\n console.error = _origConsoleError;\n }\n\n // Mark end of compile phase: route matching, middleware, tree building are done.\n if (process.env.NODE_ENV !== \"production\") __compileEnd = performance.now();\n\n // Render to RSC stream\n const rscStream = renderToReadableStream(element, { onError: rscOnError });\n\n if (isRscRequest) {\n // Direct RSC stream response (for client-side navigation)\n // NOTE: Do NOT clear headers/navigation context here!\n // The RSC stream is consumed lazily - components render when chunks are read.\n // If we clear context now, headers()/cookies() will fail during rendering.\n // Context will be cleared when the next request starts (via runWithHeadersContext).\n const responseHeaders = { \"Content-Type\": \"text/x-component; charset=utf-8\", \"Vary\": \"RSC, Accept\" };\n // Include matched route params so the client can hydrate useParams()\n if (params && Object.keys(params).length > 0) {\n responseHeaders[\"X-Vinext-Params\"] = JSON.stringify(params);\n }\n if (isForceDynamic) {\n responseHeaders[\"Cache-Control\"] = \"no-store, must-revalidate\";\n } else if ((isForceStatic || isDynamicError) && !revalidateSeconds) {\n responseHeaders[\"Cache-Control\"] = \"s-maxage=31536000, stale-while-revalidate\";\n responseHeaders[\"X-Vinext-Cache\"] = \"STATIC\";\n } else if (revalidateSeconds) {\n responseHeaders[\"Cache-Control\"] = \"s-maxage=\" + revalidateSeconds + \", stale-while-revalidate\";\n }\n // Middleware response headers are merged by the handler() wrapper.\n // Attach internal timing header so the dev server middleware can log it.\n // Format: \"handlerStart,compileMs,renderMs\"\n // handlerStart - absolute performance.now() when _handleRequest began,\n // used by the logging middleware to compute true compile\n // time as (handlerStart - middlewareReqStart).\n // compileMs - time inside the handler before renderToReadableStream.\n // -1 sentinel means compile time is not measured.\n // renderMs - -1 sentinel for RSC-only (soft-nav) responses, since\n // rendering is handled asynchronously by the client. The\n // logging middleware computes render time as totalMs - compileMs.\n if (process.env.NODE_ENV !== \"production\") {\n const handlerStart = Math.round(__reqStart);\n const compileMs = __compileEnd !== undefined ? Math.round(__compileEnd - __reqStart) : -1;\n responseHeaders[\"x-vinext-timing\"] = handlerStart + \",\" + compileMs + \",-1\";\n }\n return new Response(rscStream, { status: _mwCtx.status || 200, headers: responseHeaders });\n }\n\n // Collect font data from RSC environment before passing to SSR\n // (Fonts are loaded during RSC rendering when layout.tsx calls Geist() etc.)\n const fontData = {\n links: _getSSRFontLinks(),\n styles: _getSSRFontStyles(),\n preloads: _getSSRFontPreloads(),\n };\n\n // Build HTTP Link header for font preloading.\n // This lets the browser (and CDN) start fetching font files before parsing HTML,\n // eliminating the CSS → woff2 download waterfall.\n const fontPreloads = fontData.preloads || [];\n const fontLinkHeaderParts = [];\n for (const preload of fontPreloads) {\n fontLinkHeaderParts.push(\"<\" + preload.href + \">; rel=preload; as=font; type=\" + preload.type + \"; crossorigin\");\n }\n const fontLinkHeader = fontLinkHeaderParts.length > 0 ? fontLinkHeaderParts.join(\", \") : \"\";\n\n // Delegate to SSR environment for HTML rendering\n let htmlStream;\n try {\n const ssrEntry = await import.meta.viteRsc.loadModule(\"ssr\", \"index\");\n htmlStream = await ssrEntry.handleSsr(rscStream, _getNavigationContext(), fontData);\n // Shell render complete; Suspense boundaries stream asynchronously\n if (process.env.NODE_ENV !== \"production\") __renderEnd = performance.now();\n } catch (ssrErr) {\n const specialResponse = await handleRenderError(ssrErr);\n if (specialResponse) return specialResponse;\n // Non-special error during SSR — render error.tsx if available\n const errorBoundaryResp = await renderErrorBoundaryPage(route, ssrErr, isRscRequest, request);\n if (errorBoundaryResp) return errorBoundaryResp;\n throw ssrErr;\n }\n\n // Check for draftMode Set-Cookie header (from draftMode().enable()/disable())\n const draftCookie = getDraftModeCookieHeader();\n\n setHeadersContext(null);\n setNavigationContext(null);\n\n // Helper to attach draftMode cookie, middleware headers, font Link header, and rewrite status to a response\n function attachMiddlewareContext(response) {\n if (draftCookie) {\n response.headers.append(\"Set-Cookie\", draftCookie);\n }\n // Set HTTP Link header for font preloading\n if (fontLinkHeader) {\n response.headers.set(\"Link\", fontLinkHeader);\n }\n // Middleware response headers are merged by the handler() wrapper.\n // Attach internal timing header so the dev server middleware can log it.\n // Format: \"handlerStart,compileMs,renderMs\"\n // handlerStart - absolute performance.now() when _handleRequest began,\n // used by the logging middleware to compute true compile\n // time as (handlerStart - middlewareReqStart).\n // compileMs - time inside the handler before renderToReadableStream.\n // renderMs - time from renderToReadableStream to handleSsr completion,\n // or -1 sentinel if not measured (falls back to totalMs - compileMs).\n if (process.env.NODE_ENV !== \"production\") {\n const handlerStart = Math.round(__reqStart);\n const compileMs = __compileEnd !== undefined ? Math.round(__compileEnd - __reqStart) : -1;\n const renderMs = __renderEnd !== undefined && __compileEnd !== undefined\n ? Math.round(__renderEnd - __compileEnd)\n : -1;\n response.headers.set(\"x-vinext-timing\", handlerStart + \",\" + compileMs + \",\" + renderMs);\n }\n // Apply custom status code from middleware rewrite\n if (_mwCtx.status) {\n return new Response(response.body, {\n status: _mwCtx.status,\n headers: response.headers,\n });\n }\n return response;\n }\n\n // Check if any component called connection(), cookies(), headers(), or noStore()\n // during rendering. If so, treat as dynamic (skip ISR, set no-store).\n const dynamicUsedDuringRender = consumeDynamicUsage();\n\n // Check if cacheLife() was called during rendering (e.g., page with file-level \"use cache\").\n // If so, use its revalidation period for the Cache-Control header.\n const requestCacheLife = _consumeRequestScopedCacheLife();\n if (requestCacheLife && requestCacheLife.revalidate !== undefined && revalidateSeconds === null) {\n revalidateSeconds = requestCacheLife.revalidate;\n }\n\n // force-dynamic: always return no-store (highest priority)\n if (isForceDynamic) {\n return attachMiddlewareContext(new Response(htmlStream, {\n headers: {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store, must-revalidate\",\n \"Vary\": \"RSC, Accept\",\n },\n }));\n }\n\n // force-static / error: treat as static regardless of dynamic usage.\n // force-static intentionally provides empty headers/cookies context so\n // dynamic APIs return safe defaults; we ignore the dynamic usage signal.\n // dynamic='error' should have already thrown (via throwing Proxy) if user\n // code accessed dynamic APIs, so reaching here means rendering succeeded.\n if ((isForceStatic || isDynamicError) && (revalidateSeconds === null || revalidateSeconds === 0)) {\n return attachMiddlewareContext(new Response(htmlStream, {\n headers: {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"s-maxage=31536000, stale-while-revalidate\",\n \"X-Vinext-Cache\": \"STATIC\",\n \"Vary\": \"RSC, Accept\",\n },\n }));\n }\n\n // auto mode: dynamic API usage (headers(), cookies(), connection(), noStore(),\n // searchParams access) opts the page into dynamic rendering with no-store.\n if (dynamicUsedDuringRender) {\n return attachMiddlewareContext(new Response(htmlStream, {\n headers: {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store, must-revalidate\",\n \"Vary\": \"RSC, Accept\",\n },\n }));\n }\n\n // Emit Cache-Control for ISR pages so tests can verify revalidate values,\n // but skip actual caching in dev — every request renders fresh.\n if (revalidateSeconds !== null && revalidateSeconds > 0) {\n return attachMiddlewareContext(new Response(htmlStream, {\n headers: {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"s-maxage=\" + revalidateSeconds + \", stale-while-revalidate\",\n \"Vary\": \"RSC, Accept\",\n },\n }));\n }\n\n return attachMiddlewareContext(new Response(htmlStream, {\n headers: { \"Content-Type\": \"text/html; charset=utf-8\", \"Vary\": \"RSC, Accept\" },\n }));\n}\n\nif (import.meta.hot) {\n import.meta.hot.accept();\n}\n`;\n}\n\n/**\n * Generate the virtual SSR entry module.\n *\n * This runs in the `ssr` Vite environment. It receives an RSC stream,\n * deserializes it to a React tree, and renders to HTML.\n */\nexport function generateSsrEntry(): string {\n return `\nimport { createFromReadableStream } from \"@vitejs/plugin-rsc/ssr\";\nimport { renderToReadableStream, renderToStaticMarkup } from \"react-dom/server.edge\";\nimport { setNavigationContext, ServerInsertedHTMLContext } from \"next/navigation\";\nimport { runWithNavigationContext as _runWithNavCtx } from \"vinext/navigation-state\";\nimport { safeJsonStringify } from \"vinext/html\";\nimport { createElement as _ssrCE } from \"react\";\n\n/**\n * Collect all chunks from a ReadableStream into an array of text strings.\n * Used to capture the RSC payload for embedding in HTML.\n * The RSC flight protocol is text-based (line-delimited key:value pairs),\n * so we decode to text strings instead of byte arrays — this is dramatically\n * more compact when JSON-serialized into inline <script> tags.\n */\nasync function collectStreamChunks(stream) {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n const chunks = [];\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n // Decode Uint8Array to text string for compact JSON serialization\n chunks.push(decoder.decode(value, { stream: true }));\n }\n return chunks;\n}\n\n// React 19 dev-mode workaround (see VinextFlightRoot in handleSsr):\n//\n// In dev, Flight error decoding in react-server-dom-webpack/client.edge\n// can hit resolveErrorDev() which (via React's dev error stack capture)\n// expects a non-null hooks dispatcher.\n//\n// Vinext previously called createFromReadableStream() outside of any React render.\n// When an RSC stream contains an error, dev-mode decoding could crash with:\n// - \"Invalid hook call\"\n// - \"Cannot read properties of null (reading 'useContext')\"\n//\n// Fix: call createFromReadableStream() lazily inside a React component render.\n// This mirrors Next.js behavior and ensures the dispatcher is set.\n\n/**\n * Create a TransformStream that appends RSC chunks as inline <script> tags\n * to the HTML stream. This allows progressive hydration — the browser receives\n * RSC data incrementally as Suspense boundaries resolve, rather than waiting\n * for the entire RSC payload before hydration can begin.\n *\n * Each chunk is written as:\n * <script>self.__VINEXT_RSC_CHUNKS__=self.__VINEXT_RSC_CHUNKS__||[];self.__VINEXT_RSC_CHUNKS__.push(\"...\")</script>\n *\n * Chunks are embedded as text strings (not byte arrays) since the RSC flight\n * protocol is text-based. The browser entry encodes them back to Uint8Array.\n * This is ~3x more compact than the previous byte-array format.\n */\nfunction createRscEmbedTransform(embedStream) {\n const reader = embedStream.getReader();\n const _decoder = new TextDecoder();\n let done = false;\n let pendingChunks = [];\n let reading = false;\n\n // Fix invalid preload \"as\" values in RSC Flight hint lines before\n // they reach the client. React Flight emits HL hints with\n // as=\"stylesheet\" for CSS, but the HTML spec requires as=\"style\"\n // for <link rel=\"preload\">. The fixPreloadAs() below only fixes the\n // server-rendered HTML stream; this fixes the raw Flight data that\n // gets embedded as __VINEXT_RSC_CHUNKS__ and processed client-side.\n function fixFlightHints(text) {\n // Flight hint format: <id>:HL[\"url\",\"stylesheet\"] or with options\n return text.replace(/(\\\\d+:HL\\\\[.*?),\"stylesheet\"(\\\\]|,)/g, '$1,\"style\"$2');\n }\n\n // Start reading RSC chunks in the background, accumulating them as text strings.\n // The RSC flight protocol is text-based, so decoding to strings and embedding\n // as JSON strings is ~3x more compact than the byte-array format.\n async function pumpReader() {\n if (reading) return;\n reading = true;\n try {\n while (true) {\n const result = await reader.read();\n if (result.done) {\n done = true;\n break;\n }\n const text = _decoder.decode(result.value, { stream: true });\n pendingChunks.push(fixFlightHints(text));\n }\n } catch (err) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[vinext] RSC embed stream read error:\", err);\n }\n done = true;\n }\n reading = false;\n }\n\n // Fire off the background reader immediately\n const pumpPromise = pumpReader();\n\n return {\n /**\n * Flush any accumulated RSC chunks as <script> tags.\n * Called after each HTML chunk is enqueued.\n */\n flush() {\n if (pendingChunks.length === 0) return \"\";\n const chunks = pendingChunks;\n pendingChunks = [];\n let scripts = \"\";\n for (const chunk of chunks) {\n scripts += \"<script>self.__VINEXT_RSC_CHUNKS__=self.__VINEXT_RSC_CHUNKS__||[];self.__VINEXT_RSC_CHUNKS__.push(\" + safeJsonStringify(chunk) + \")</script>\";\n }\n return scripts;\n },\n\n /**\n * Wait for the RSC stream to fully complete and return any final\n * script tags plus the closing signal.\n */\n async finalize() {\n await pumpPromise;\n let scripts = this.flush();\n // Signal that all RSC chunks have been sent.\n // Params are already embedded in <head> — no need to include here.\n scripts += \"<script>self.__VINEXT_RSC_DONE__=true</script>\";\n return scripts;\n },\n };\n}\n\n/**\n * Render the RSC stream to HTML.\n *\n * @param rscStream - The RSC payload stream from the RSC environment\n * @param navContext - Navigation context for client component SSR hooks.\n * \"use client\" components like those using usePathname() need the current\n * request URL during SSR, and they run in this SSR environment (separate\n * from the RSC environment where the context was originally set).\n * @param fontData - Font links and styles collected from the RSC environment.\n * Fonts are loaded during RSC rendering (when layout calls Geist() etc.),\n * and the data needs to be passed to SSR since they're separate module instances.\n */\nexport async function handleSsr(rscStream, navContext, fontData) {\n // Wrap in a navigation ALS scope for per-request isolation in the SSR\n // environment. The SSR environment has separate module instances from RSC,\n // so it needs its own ALS scope.\n return _runWithNavCtx(async () => {\n // Set navigation context so hooks like usePathname() work during SSR\n // of \"use client\" components\n if (navContext) {\n setNavigationContext(navContext);\n }\n\n // Clear any stale callbacks from previous requests\n const { clearServerInsertedHTML, flushServerInsertedHTML, useServerInsertedHTML: _addInsertedHTML } = await import(\"next/navigation\");\n clearServerInsertedHTML();\n\n try {\n // Tee the RSC stream - one for SSR rendering, one for embedding in HTML.\n // This ensures the browser uses the SAME RSC payload for hydration that\n // was used to generate the HTML, avoiding hydration mismatches (React #418).\n const [ssrStream, embedStream] = rscStream.tee();\n\n // Create the progressive RSC embed helper — it reads the embed stream\n // in the background and provides script tags to inject into the HTML stream.\n const rscEmbed = createRscEmbedTransform(embedStream);\n\n // Deserialize RSC stream back to React VDOM.\n // IMPORTANT: Do NOT await this — createFromReadableStream returns a thenable\n // that React's renderToReadableStream can consume progressively. By passing\n // the unresolved thenable, React will render Suspense fallbacks (loading.tsx)\n // immediately in the HTML shell, then stream in resolved content as RSC\n // chunks arrive. Awaiting here would block until all async server components\n // complete, collapsing the streaming behavior.\n // Lazily create the Flight root inside render so React's hook dispatcher is set\n // (avoids React 19 dev-mode resolveErrorDev() crash). VinextFlightRoot returns\n // a thenable (not a ReactNode), which React 19 consumes via its internal\n // thenable-as-child suspend/resume behavior. This matches Next.js's approach.\n let flightRoot;\n function VinextFlightRoot() {\n if (!flightRoot) {\n flightRoot = createFromReadableStream(ssrStream);\n }\n return flightRoot;\n }\n const root = _ssrCE(VinextFlightRoot);\n\n // Wrap with ServerInsertedHTMLContext.Provider so libraries that use\n // useContext(ServerInsertedHTMLContext) (Apollo Client, styled-components,\n // etc.) get a working callback registration function during SSR.\n // The provider value is useServerInsertedHTML — same function that direct\n // callers use — so both paths push to the same ALS-backed callback array.\n const ssrRoot = ServerInsertedHTMLContext\n ? _ssrCE(ServerInsertedHTMLContext.Provider, { value: _addInsertedHTML }, root)\n : root;\n\n // Get the bootstrap script content for the browser entry\n const bootstrapScriptContent =\n await import.meta.viteRsc.loadBootstrapScriptContent(\"index\");\n\n // djb2 hash for digest generation in the SSR environment.\n // Matches the RSC environment's __errorDigest function.\n function ssrErrorDigest(str) {\n let hash = 5381;\n for (let i = str.length - 1; i >= 0; i--) {\n hash = (hash * 33) ^ str.charCodeAt(i);\n }\n return (hash >>> 0).toString();\n }\n\n // Render HTML (streaming SSR)\n // useServerInsertedHTML callbacks are registered during this render.\n // The onError callback preserves the digest for Next.js navigation errors\n // (redirect, notFound, forbidden, unauthorized) thrown inside Suspense\n // boundaries during RSC streaming. Without this, React's default onError\n // returns undefined and the digest is lost in the $RX() call, preventing\n // client-side error boundaries from identifying the error type.\n // In production, non-navigation errors also get a digest hash so they\n // can be correlated with server logs without leaking details to clients.\n const htmlStream = await renderToReadableStream(ssrRoot, {\n bootstrapScriptContent,\n onError(error) {\n if (error && typeof error === \"object\" && \"digest\" in error) {\n return String(error.digest);\n }\n // In production, generate a digest hash for non-navigation errors\n if (process.env.NODE_ENV === \"production\" && error) {\n const msg = error instanceof Error ? error.message : String(error);\n const stack = error instanceof Error ? (error.stack || \"\") : \"\";\n return ssrErrorDigest(msg + stack);\n }\n return undefined;\n },\n });\n\n\n // Flush useServerInsertedHTML callbacks (CSS-in-JS style injection)\n const insertedElements = flushServerInsertedHTML();\n\n // Render the inserted elements to HTML strings\n const { Fragment } = await import(\"react\");\n let insertedHTML = \"\";\n for (const el of insertedElements) {\n try {\n insertedHTML += renderToStaticMarkup(_ssrCE(Fragment, null, el));\n } catch {\n // Skip elements that can't be rendered\n }\n }\n\n // Escape HTML attribute values (defense-in-depth for font URLs/types).\n function _escAttr(s) { return s.replace(/&/g, \"&\").replace(/\"/g, \""\"); }\n\n // Build font HTML from data passed from RSC environment\n // (Fonts are loaded during RSC rendering, and RSC/SSR are separate module instances)\n let fontHTML = \"\";\n if (fontData) {\n if (fontData.links && fontData.links.length > 0) {\n for (const url of fontData.links) {\n fontHTML += '<link rel=\"stylesheet\" href=\"' + _escAttr(url) + '\" />\\\\n';\n }\n }\n // Emit <link rel=\"preload\"> for local font files\n if (fontData.preloads && fontData.preloads.length > 0) {\n for (const preload of fontData.preloads) {\n fontHTML += '<link rel=\"preload\" href=\"' + _escAttr(preload.href) + '\" as=\"font\" type=\"' + _escAttr(preload.type) + '\" crossorigin />\\\\n';\n }\n }\n if (fontData.styles && fontData.styles.length > 0) {\n fontHTML += '<style data-vinext-fonts>' + fontData.styles.join(\"\\\\n\") + '</style>\\\\n';\n }\n }\n\n // Extract client entry module URL from bootstrapScriptContent to emit\n // a <link rel=\"modulepreload\"> hint. The RSC plugin formats bootstrap\n // content as: import(\"URL\") — we extract the URL so the browser can\n // speculatively fetch and parse the JS module while still processing\n // the HTML body, instead of waiting until it reaches the inline script.\n let modulePreloadHTML = \"\";\n if (bootstrapScriptContent) {\n const m = bootstrapScriptContent.match(/import\\\\(\"([^\"]+)\"\\\\)/);\n if (m && m[1]) {\n modulePreloadHTML = '<link rel=\"modulepreload\" href=\"' + _escAttr(m[1]) + '\" />\\\\n';\n }\n }\n\n // Head-injected HTML: server-inserted HTML, font HTML, route params,\n // and modulepreload hints.\n // RSC payload is now embedded progressively via script tags in the body stream.\n // Params are embedded eagerly in <head> so they're available before client\n // hydration starts, avoiding the need for polling on the client.\n const paramsScript = '<script>self.__VINEXT_RSC_PARAMS__=' + safeJsonStringify(navContext?.params || {}) + '</script>';\n const injectHTML = paramsScript + modulePreloadHTML + insertedHTML + fontHTML;\n\n // Inject the collected HTML before </head> and progressively embed RSC\n // chunks as script tags throughout the HTML body stream.\n const decoder = new TextDecoder();\n const encoder = new TextEncoder();\n let injected = false;\n\n // Fix invalid preload \"as\" values in server-rendered HTML.\n // React Fizz emits <link rel=\"preload\" as=\"stylesheet\"> for CSS,\n // but the HTML spec requires as=\"style\" for <link rel=\"preload\">.\n // Note: fixFlightHints() in createRscEmbedTransform handles the\n // complementary case — fixing the raw Flight stream data before\n // it's embedded as __VINEXT_RSC_CHUNKS__ for client-side processing.\n // See: https://html.spec.whatwg.org/multipage/links.html#link-type-preload\n function fixPreloadAs(html) {\n // Match <link ...rel=\"preload\"... as=\"stylesheet\"...> in any attribute order\n return html.replace(/<link(?=[^>]*\\\\srel=\"preload\")[^>]*>/g, function(tag) {\n return tag.replace(' as=\"stylesheet\"', ' as=\"style\"');\n });\n }\n\n // Tick-buffered RSC script injection.\n //\n // React's renderToReadableStream (Fizz) flushes chunks synchronously\n // within one microtask — all chunks from a single flushCompletedQueues\n // call arrive in the same macrotask. We buffer HTML chunks as they\n // arrive, then use setTimeout(0) to defer emitting them plus any\n // accumulated RSC scripts to the next macrotask. This guarantees we\n // never inject <script> tags between partial HTML chunks (which would\n // corrupt split elements like \"<linearGradi\" + \"ent>\"), while still\n // delivering RSC data progressively as Suspense boundaries resolve.\n //\n // Reference: rsc-html-stream by Devon Govett (credited by Next.js)\n // https://github.com/devongovett/rsc-html-stream\n let buffered = [];\n let timeoutId = null;\n\n const transform = new TransformStream({\n transform(chunk, controller) {\n const text = decoder.decode(chunk, { stream: true });\n const fixed = fixPreloadAs(text);\n buffered.push(fixed);\n\n if (timeoutId !== null) return;\n\n timeoutId = setTimeout(() => {\n // Flush all buffered HTML chunks from this React flush cycle\n for (const buf of buffered) {\n if (!injected) {\n const headEnd = buf.indexOf(\"</head>\");\n if (headEnd !== -1) {\n const before = buf.slice(0, headEnd);\n const after = buf.slice(headEnd);\n controller.enqueue(encoder.encode(before + injectHTML + after));\n injected = true;\n continue;\n }\n }\n controller.enqueue(encoder.encode(buf));\n }\n buffered = [];\n\n // Now safe to inject any accumulated RSC scripts — we're between\n // React flush cycles, so no partial HTML chunks can follow until\n // the next macrotask.\n const rscScripts = rscEmbed.flush();\n if (rscScripts) {\n controller.enqueue(encoder.encode(rscScripts));\n }\n\n timeoutId = null;\n }, 0);\n },\n async flush(controller) {\n // Cancel any pending setTimeout callback — flush() drains\n // everything itself, so the callback would be a no-op but\n // cancelling makes the code obviously correct.\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n // Flush any remaining buffered HTML chunks\n for (const buf of buffered) {\n if (!injected) {\n const headEnd = buf.indexOf(\"</head>\");\n if (headEnd !== -1) {\n const before = buf.slice(0, headEnd);\n const after = buf.slice(headEnd);\n controller.enqueue(encoder.encode(before + injectHTML + after));\n injected = true;\n continue;\n }\n }\n controller.enqueue(encoder.encode(buf));\n }\n buffered = [];\n\n if (!injected && injectHTML) {\n controller.enqueue(encoder.encode(injectHTML));\n }\n // Finalize: wait for the RSC stream to complete and emit remaining\n // chunks plus the __VINEXT_RSC_DONE__ signal.\n const finalScripts = await rscEmbed.finalize();\n if (finalScripts) {\n controller.enqueue(encoder.encode(finalScripts));\n }\n },\n });\n\n return htmlStream.pipeThrough(transform);\n } finally {\n // Clean up so we don't leak context between requests\n setNavigationContext(null);\n clearServerInsertedHTML();\n }\n }); // end _runWithNavCtx\n}\n\nexport default {\n async fetch(request) {\n const url = new URL(request.url);\n if (url.pathname.startsWith(\"//\")) {\n return new Response(\"404 Not Found\", { status: 404 });\n }\n const rscModule = await import.meta.viteRsc.loadModule(\"rsc\", \"index\");\n const result = await rscModule.default(request);\n if (result instanceof Response) {\n return result;\n }\n if (result === null || result === undefined) {\n return new Response(\"Not Found\", { status: 404 });\n }\n return new Response(String(result), { status: 200 });\n },\n};\n`;\n}\n\n/**\n * Generate the virtual browser entry module.\n *\n * This runs in the client (browser). It hydrates the page from the\n * embedded RSC payload and handles client-side navigation by re-fetching\n * RSC streams.\n */\nexport function generateBrowserEntry(): string {\n return `\nimport {\n createFromReadableStream,\n createFromFetch,\n setServerCallback,\n encodeReply,\n createTemporaryReferenceSet,\n} from \"@vitejs/plugin-rsc/browser\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport { flushSync } from \"react-dom\";\nimport { setClientParams, toRscUrl, getPrefetchCache, getPrefetchedUrls, PREFETCH_CACHE_TTL } from \"next/navigation\";\n\nlet reactRoot;\n\n/**\n * Convert the embedded RSC chunks back to a ReadableStream.\n * Each chunk is a text string that needs to be encoded back to Uint8Array.\n */\nfunction chunksToReadableStream(chunks) {\n const encoder = new TextEncoder();\n return new ReadableStream({\n start(controller) {\n for (const chunk of chunks) {\n controller.enqueue(encoder.encode(chunk));\n }\n controller.close();\n }\n });\n}\n\n/**\n * Create a ReadableStream from progressively-embedded RSC chunks.\n * The server injects RSC data as <script> tags that push to\n * self.__VINEXT_RSC_CHUNKS__ throughout the HTML stream, and sets\n * self.__VINEXT_RSC_DONE__ = true when complete.\n *\n * Instead of polling with setTimeout, we monkey-patch the array's\n * push() method so new chunks are delivered immediately when the\n * server's <script> tags execute. This eliminates unnecessary\n * wakeups and reduces latency — same pattern Next.js uses with\n * __next_f. The stream closes on DOMContentLoaded (when all\n * server-injected scripts have executed) or when __VINEXT_RSC_DONE__\n * is set, whichever comes first.\n */\nfunction createProgressiveRscStream() {\n const encoder = new TextEncoder();\n return new ReadableStream({\n start(controller) {\n const chunks = self.__VINEXT_RSC_CHUNKS__ || [];\n\n // Deliver any chunks that arrived before this code ran\n // (from <script> tags that executed before the browser entry loaded)\n for (const chunk of chunks) {\n controller.enqueue(encoder.encode(chunk));\n }\n\n // If the stream is already complete, close immediately\n if (self.__VINEXT_RSC_DONE__) {\n controller.close();\n return;\n }\n\n // Monkey-patch push() so future chunks stream in immediately\n // when the server's <script> tags execute\n let closed = false;\n function closeOnce() {\n if (!closed) {\n closed = true;\n controller.close();\n }\n }\n\n const arr = self.__VINEXT_RSC_CHUNKS__ = self.__VINEXT_RSC_CHUNKS__ || [];\n arr.push = function(chunk) {\n Array.prototype.push.call(this, chunk);\n if (!closed) {\n controller.enqueue(encoder.encode(chunk));\n if (self.__VINEXT_RSC_DONE__) {\n closeOnce();\n }\n }\n return this.length;\n };\n\n // Safety net: if the server crashes mid-stream and __VINEXT_RSC_DONE__\n // never arrives, close the stream when all server-injected scripts\n // have executed (DOMContentLoaded). Without this, a truncated response\n // leaves the ReadableStream open forever, hanging hydration.\n if (typeof document !== \"undefined\") {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", closeOnce);\n } else {\n // Document already loaded — close immediately if not already done\n closeOnce();\n }\n }\n }\n });\n}\n\n// Register the server action callback — React calls this internally\n// when a \"use server\" function is invoked from client code.\nsetServerCallback(async (id, args) => {\n const temporaryReferences = createTemporaryReferenceSet();\n const body = await encodeReply(args, { temporaryReferences });\n\n const fetchResponse = await fetch(toRscUrl(window.location.pathname + window.location.search), {\n method: \"POST\",\n headers: { \"x-rsc-action\": id },\n body,\n });\n\n // Check for redirect signal from server action that called redirect()\n const actionRedirect = fetchResponse.headers.get(\"x-action-redirect\");\n if (actionRedirect) {\n // External URLs (different origin) need a hard redirect — client-side\n // RSC navigation only works for same-origin paths.\n try {\n const redirectUrl = new URL(actionRedirect, window.location.origin);\n if (redirectUrl.origin !== window.location.origin) {\n window.location.href = actionRedirect;\n return undefined;\n }\n } catch {\n // If URL parsing fails, fall through to client-side navigation\n }\n\n // Navigate to the redirect target using client-side navigation\n const redirectType = fetchResponse.headers.get(\"x-action-redirect-type\") || \"replace\";\n if (redirectType === \"push\") {\n window.history.pushState(null, \"\", actionRedirect);\n } else {\n window.history.replaceState(null, \"\", actionRedirect);\n }\n // Trigger RSC navigation to the redirect target\n if (typeof window.__VINEXT_RSC_NAVIGATE__ === \"function\") {\n window.__VINEXT_RSC_NAVIGATE__(actionRedirect);\n }\n return undefined;\n }\n\n const result = await createFromFetch(Promise.resolve(fetchResponse), { temporaryReferences });\n\n // The RSC response for actions contains { root, returnValue }.\n // Re-render the page with the updated tree.\n if (result && typeof result === \"object\" && \"root\" in result) {\n reactRoot.render(result.root);\n // Return the action's return value to the caller\n if (result.returnValue) {\n if (!result.returnValue.ok) throw result.returnValue.data;\n return result.returnValue.data;\n }\n return undefined;\n }\n\n // Fallback: render the entire result as the tree\n reactRoot.render(result);\n return result;\n});\n\nasync function main() {\n let rscStream;\n\n // Use embedded RSC data for initial hydration if available.\n // This ensures we use the SAME RSC payload that generated the HTML,\n // avoiding hydration mismatches (React error #418).\n //\n // The server embeds RSC chunks progressively as <script> tags that push\n // to self.__VINEXT_RSC_CHUNKS__. When complete, self.__VINEXT_RSC_DONE__\n // is set and self.__VINEXT_RSC_PARAMS__ contains route params.\n // For backwards compat, also check the legacy self.__VINEXT_RSC__ format.\n if (self.__VINEXT_RSC_CHUNKS__ || self.__VINEXT_RSC_DONE__ || self.__VINEXT_RSC__) {\n if (self.__VINEXT_RSC__) {\n // Legacy format: single object with all chunks\n const embedData = self.__VINEXT_RSC__;\n delete self.__VINEXT_RSC__;\n if (embedData.params) {\n setClientParams(embedData.params);\n }\n rscStream = chunksToReadableStream(embedData.rsc);\n } else {\n // Progressive format: chunks arrive incrementally via script tags.\n // Params are embedded in <head> so they're always available by this point.\n if (self.__VINEXT_RSC_PARAMS__) {\n setClientParams(self.__VINEXT_RSC_PARAMS__);\n }\n rscStream = createProgressiveRscStream();\n }\n } else {\n // Fallback: fetch fresh RSC (shouldn't happen on initial page load)\n const rscResponse = await fetch(toRscUrl(window.location.pathname + window.location.search));\n\n // Hydrate useParams() with route params from the server before React hydration\n const paramsHeader = rscResponse.headers.get(\"X-Vinext-Params\");\n if (paramsHeader) {\n try { setClientParams(JSON.parse(paramsHeader)); } catch (_e) { /* ignore */ }\n }\n\n rscStream = rscResponse.body;\n }\n\n const root = await createFromReadableStream(rscStream);\n\n // Hydrate the document\n // In development, suppress Vite's error overlay for errors caught by React error\n // boundaries. Without this, React re-throws caught errors to the global handler,\n // which triggers Vite's overlay even though the error was handled by an error.tsx.\n // In production, preserve React's default onCaughtError (console.error) so\n // boundary-caught errors remain visible to error monitoring.\n reactRoot = hydrateRoot(document, root, import.meta.env.DEV ? {\n onCaughtError: function() {},\n } : undefined);\n\n // Store for client-side navigation\n window.__VINEXT_RSC_ROOT__ = reactRoot;\n\n // Client-side navigation handler\n // Checks the prefetch cache (populated by <Link> IntersectionObserver and\n // router.prefetch()) before making a network request. This makes navigation\n // near-instant for prefetched routes.\n window.__VINEXT_RSC_NAVIGATE__ = async function navigateRsc(href, __redirectDepth) {\n if ((__redirectDepth || 0) > 10) {\n console.error(\"[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.\");\n window.location.href = href;\n return;\n }\n try {\n const url = new URL(href, window.location.origin);\n const rscUrl = toRscUrl(url.pathname + url.search);\n\n // Check the in-memory prefetch cache first\n let navResponse;\n const prefetchCache = getPrefetchCache();\n const cached = prefetchCache.get(rscUrl);\n if (cached && (Date.now() - cached.timestamp) < PREFETCH_CACHE_TTL) {\n navResponse = cached.response;\n prefetchCache.delete(rscUrl); // Consume the cached entry (one-time use)\n getPrefetchedUrls().delete(rscUrl); // Allow re-prefetch when link is visible again\n } else if (cached) {\n prefetchCache.delete(rscUrl); // Expired, clean up\n getPrefetchedUrls().delete(rscUrl);\n }\n\n // Fallback to network fetch if not in cache\n if (!navResponse) {\n navResponse = await fetch(rscUrl, {\n headers: { Accept: \"text/x-component\" },\n credentials: \"include\",\n });\n }\n\n // Detect if fetch followed a redirect: compare the final response URL to\n // what we requested. If they differ, the server issued a 3xx — push the\n // canonical destination URL into history before rendering.\n const __finalUrl = new URL(navResponse.url);\n const __requestedUrl = new URL(rscUrl, window.location.origin);\n if (__finalUrl.pathname !== __requestedUrl.pathname) {\n // Strip .rsc suffix from the final URL to get the page path for history.\n // Use replaceState instead of pushState: the caller (navigateImpl) already\n // pushed the pre-redirect URL; replacing it avoids a stale history entry.\n const __destPath = __finalUrl.pathname.replace(/\\\\.rsc$/, \"\") + __finalUrl.search;\n window.history.replaceState(null, \"\", __destPath);\n return window.__VINEXT_RSC_NAVIGATE__(__destPath, (__redirectDepth || 0) + 1);\n }\n\n // Update useParams() with route params from the server before re-rendering\n const navParamsHeader = navResponse.headers.get(\"X-Vinext-Params\");\n if (navParamsHeader) {\n try { setClientParams(JSON.parse(navParamsHeader)); } catch (_e) { /* ignore */ }\n } else {\n setClientParams({});\n }\n\n const rscPayload = await createFromFetch(Promise.resolve(navResponse));\n // Use flushSync to guarantee React commits the new tree to the DOM\n // synchronously before this function returns. Callers scroll to top\n // after awaiting, so the new content must be painted first.\n flushSync(function () { reactRoot.render(rscPayload); });\n } catch (err) {\n console.error(\"[vinext] RSC navigation error:\", err);\n // Fallback to full page load\n window.location.href = href;\n }\n };\n\n // Handle popstate (browser back/forward)\n // Store the navigation promise on a well-known property so that\n // restoreScrollPosition (in navigation.ts) can await it before scrolling.\n // This prevents a flash where the old content is visible at the restored\n // scroll position before the new RSC payload has rendered.\n window.addEventListener(\"popstate\", () => {\n const p = window.__VINEXT_RSC_NAVIGATE__(window.location.href);\n window.__VINEXT_RSC_PENDING__ = p;\n p.finally(() => {\n // Clear once settled so stale promises aren't awaited later\n if (window.__VINEXT_RSC_PENDING__ === p) {\n window.__VINEXT_RSC_PENDING__ = null;\n }\n });\n });\n\n // HMR: re-render on server module updates\n if (import.meta.hot) {\n import.meta.hot.on(\"rsc:update\", async () => {\n try {\n const rscPayload = await createFromFetch(\n fetch(toRscUrl(window.location.pathname + window.location.search))\n );\n reactRoot.render(rscPayload);\n } catch (err) {\n console.error(\"[vinext] RSC HMR error:\", err);\n }\n });\n }\n}\n\nmain();\n`;\n}\n"]}
|