vinext 0.0.46 → 0.0.47

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.
Files changed (171) hide show
  1. package/README.md +7 -5
  2. package/dist/build/prerender.d.ts +2 -1
  3. package/dist/build/prerender.js +70 -14
  4. package/dist/build/prerender.js.map +1 -1
  5. package/dist/build/report.d.ts +1 -1
  6. package/dist/build/route-classification-injector.d.ts +35 -0
  7. package/dist/build/route-classification-injector.js +61 -0
  8. package/dist/build/route-classification-injector.js.map +1 -0
  9. package/dist/build/route-classification-manifest.d.ts +1 -1
  10. package/dist/build/static-export.d.ts +1 -1
  11. package/dist/cli-args.d.ts +31 -0
  12. package/dist/cli-args.js +104 -0
  13. package/dist/cli-args.js.map +1 -0
  14. package/dist/cli.js +2 -19
  15. package/dist/cli.js.map +1 -1
  16. package/dist/cloudflare/kv-cache-handler.js +29 -9
  17. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  18. package/dist/config/next-config.d.ts +4 -2
  19. package/dist/config/next-config.js +3 -0
  20. package/dist/config/next-config.js.map +1 -1
  21. package/dist/entries/app-rsc-entry.d.ts +4 -3
  22. package/dist/entries/app-rsc-entry.js +373 -854
  23. package/dist/entries/app-rsc-entry.js.map +1 -1
  24. package/dist/entries/app-rsc-manifest.d.ts +1 -1
  25. package/dist/entries/app-rsc-manifest.js +2 -0
  26. package/dist/entries/app-rsc-manifest.js.map +1 -1
  27. package/dist/entries/pages-server-entry.js +5 -2
  28. package/dist/entries/pages-server-entry.js.map +1 -1
  29. package/dist/index.js +28 -51
  30. package/dist/index.js.map +1 -1
  31. package/dist/plugins/fonts.js +54 -32
  32. package/dist/plugins/fonts.js.map +1 -1
  33. package/dist/plugins/rsc-client-shim-excludes.js +1 -0
  34. package/dist/plugins/rsc-client-shim-excludes.js.map +1 -1
  35. package/dist/routing/app-route-graph.d.ts +109 -0
  36. package/dist/routing/app-route-graph.js +819 -0
  37. package/dist/routing/app-route-graph.js.map +1 -0
  38. package/dist/routing/app-router.d.ts +2 -88
  39. package/dist/routing/app-router.js +6 -694
  40. package/dist/routing/app-router.js.map +1 -1
  41. package/dist/server/app-browser-entry.js +86 -252
  42. package/dist/server/app-browser-entry.js.map +1 -1
  43. package/dist/server/app-browser-error.d.ts +3 -4
  44. package/dist/server/app-browser-error.js +8 -4
  45. package/dist/server/app-browser-error.js.map +1 -1
  46. package/dist/server/app-browser-navigation-controller.d.ts +73 -0
  47. package/dist/server/app-browser-navigation-controller.js +282 -0
  48. package/dist/server/app-browser-navigation-controller.js.map +1 -0
  49. package/dist/server/app-browser-state.d.ts +1 -1
  50. package/dist/server/app-elements.js +1 -5
  51. package/dist/server/app-elements.js.map +1 -1
  52. package/dist/server/app-fallback-renderer.d.ts +57 -0
  53. package/dist/server/app-fallback-renderer.js +79 -0
  54. package/dist/server/app-fallback-renderer.js.map +1 -0
  55. package/dist/server/app-hook-warning-suppression.d.ts +7 -0
  56. package/dist/server/app-hook-warning-suppression.js +12 -0
  57. package/dist/server/app-hook-warning-suppression.js.map +1 -0
  58. package/dist/server/app-mounted-slots-header.d.ts +17 -0
  59. package/dist/server/app-mounted-slots-header.js +21 -0
  60. package/dist/server/app-mounted-slots-header.js.map +1 -0
  61. package/dist/server/app-page-boundary-render.d.ts +2 -2
  62. package/dist/server/app-page-boundary-render.js.map +1 -1
  63. package/dist/server/app-page-cache.d.ts +18 -4
  64. package/dist/server/app-page-cache.js +53 -10
  65. package/dist/server/app-page-cache.js.map +1 -1
  66. package/dist/server/app-page-dispatch.d.ts +7 -4
  67. package/dist/server/app-page-dispatch.js +24 -8
  68. package/dist/server/app-page-dispatch.js.map +1 -1
  69. package/dist/server/app-page-element-builder.d.ts +61 -0
  70. package/dist/server/app-page-element-builder.js +139 -0
  71. package/dist/server/app-page-element-builder.js.map +1 -0
  72. package/dist/server/app-page-params.d.ts +2 -1
  73. package/dist/server/app-page-params.js +3 -3
  74. package/dist/server/app-page-params.js.map +1 -1
  75. package/dist/server/app-page-render.d.ts +5 -1
  76. package/dist/server/app-page-render.js +80 -27
  77. package/dist/server/app-page-render.js.map +1 -1
  78. package/dist/server/app-page-request.d.ts +19 -4
  79. package/dist/server/app-page-request.js +51 -6
  80. package/dist/server/app-page-request.js.map +1 -1
  81. package/dist/server/app-page-response.d.ts +1 -0
  82. package/dist/server/app-page-response.js +3 -7
  83. package/dist/server/app-page-response.js.map +1 -1
  84. package/dist/server/app-page-route-wiring.d.ts +15 -2
  85. package/dist/server/app-page-route-wiring.js.map +1 -1
  86. package/dist/server/app-post-middleware-context.d.ts +16 -0
  87. package/dist/server/app-post-middleware-context.js +28 -0
  88. package/dist/server/app-post-middleware-context.js.map +1 -0
  89. package/dist/server/app-request-context.d.ts +22 -0
  90. package/dist/server/app-request-context.js +30 -0
  91. package/dist/server/app-request-context.js.map +1 -0
  92. package/dist/server/app-route-handler-cache.d.ts +1 -0
  93. package/dist/server/app-route-handler-cache.js +5 -1
  94. package/dist/server/app-route-handler-cache.js.map +1 -1
  95. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  96. package/dist/server/app-route-handler-dispatch.js +2 -0
  97. package/dist/server/app-route-handler-dispatch.js.map +1 -1
  98. package/dist/server/app-route-handler-execution.d.ts +2 -1
  99. package/dist/server/app-route-handler-execution.js +2 -2
  100. package/dist/server/app-route-handler-execution.js.map +1 -1
  101. package/dist/server/app-route-handler-response.d.ts +4 -2
  102. package/dist/server/app-route-handler-response.js +8 -7
  103. package/dist/server/app-route-handler-response.js.map +1 -1
  104. package/dist/server/app-rsc-error-handler.d.ts +21 -0
  105. package/dist/server/app-rsc-error-handler.js +30 -0
  106. package/dist/server/app-rsc-error-handler.js.map +1 -0
  107. package/dist/server/app-rsc-handler.d.ts +117 -0
  108. package/dist/server/app-rsc-handler.js +260 -0
  109. package/dist/server/app-rsc-handler.js.map +1 -0
  110. package/dist/server/app-rsc-request-normalization.d.ts +40 -0
  111. package/dist/server/app-rsc-request-normalization.js +63 -0
  112. package/dist/server/app-rsc-request-normalization.js.map +1 -0
  113. package/dist/server/app-rsc-response-finalizer.d.ts +30 -0
  114. package/dist/server/app-rsc-response-finalizer.js +38 -0
  115. package/dist/server/app-rsc-response-finalizer.js.map +1 -0
  116. package/dist/server/app-segment-config.d.ts +33 -0
  117. package/dist/server/app-segment-config.js +86 -0
  118. package/dist/server/app-segment-config.js.map +1 -0
  119. package/dist/server/app-server-action-execution.d.ts +2 -0
  120. package/dist/server/app-server-action-execution.js +2 -0
  121. package/dist/server/app-server-action-execution.js.map +1 -1
  122. package/dist/server/cache-control.d.ts +24 -0
  123. package/dist/server/cache-control.js +33 -0
  124. package/dist/server/cache-control.js.map +1 -0
  125. package/dist/server/dev-error-overlay-store.d.ts +23 -0
  126. package/dist/server/dev-error-overlay-store.js +67 -0
  127. package/dist/server/dev-error-overlay-store.js.map +1 -0
  128. package/dist/server/dev-error-overlay.d.ts +15 -0
  129. package/dist/server/dev-error-overlay.js +548 -0
  130. package/dist/server/dev-error-overlay.js.map +1 -0
  131. package/dist/server/instrumentation-runtime.d.ts +44 -0
  132. package/dist/server/instrumentation-runtime.js +29 -0
  133. package/dist/server/instrumentation-runtime.js.map +1 -0
  134. package/dist/server/isr-cache.d.ts +2 -7
  135. package/dist/server/isr-cache.js +7 -10
  136. package/dist/server/isr-cache.js.map +1 -1
  137. package/dist/server/pages-page-data.d.ts +2 -1
  138. package/dist/server/pages-page-data.js +6 -5
  139. package/dist/server/pages-page-data.js.map +1 -1
  140. package/dist/server/pages-page-response.d.ts +2 -1
  141. package/dist/server/pages-page-response.js +3 -2
  142. package/dist/server/pages-page-response.js.map +1 -1
  143. package/dist/server/rsc-stream-hints.d.ts +3 -1
  144. package/dist/server/rsc-stream-hints.js +4 -1
  145. package/dist/server/rsc-stream-hints.js.map +1 -1
  146. package/dist/server/seed-cache.js +19 -8
  147. package/dist/server/seed-cache.js.map +1 -1
  148. package/dist/shims/cache-runtime.js +28 -11
  149. package/dist/shims/cache-runtime.js.map +1 -1
  150. package/dist/shims/cache.d.ts +15 -3
  151. package/dist/shims/cache.js +42 -15
  152. package/dist/shims/cache.js.map +1 -1
  153. package/dist/shims/error-boundary.d.ts +17 -1
  154. package/dist/shims/error-boundary.js +31 -1
  155. package/dist/shims/error-boundary.js.map +1 -1
  156. package/dist/shims/fetch-cache.d.ts +4 -1
  157. package/dist/shims/fetch-cache.js +55 -13
  158. package/dist/shims/fetch-cache.js.map +1 -1
  159. package/dist/shims/image.js +93 -5
  160. package/dist/shims/image.js.map +1 -1
  161. package/dist/shims/request-state-types.d.ts +1 -1
  162. package/dist/shims/unified-request-context.d.ts +1 -1
  163. package/dist/shims/unified-request-context.js +1 -0
  164. package/dist/shims/unified-request-context.js.map +1 -1
  165. package/dist/shims/use-merged-ref.d.ts +7 -0
  166. package/dist/shims/use-merged-ref.js +40 -0
  167. package/dist/shims/use-merged-ref.js.map +1 -0
  168. package/dist/utils/cache-control-metadata.d.ts +6 -0
  169. package/dist/utils/cache-control-metadata.js +16 -0
  170. package/dist/utils/cache-control-metadata.js.map +1 -0
  171. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"app-page-dispatch.js","names":[],"sources":["../../src/server/app-page-dispatch.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { ClassificationReason } from \"../build/layout-classification-types.js\";\nimport { _consumeRequestScopedCacheLife, type CachedAppPageValue } from \"vinext/shims/cache\";\nimport {\n consumeDynamicUsage,\n consumeInvalidDynamicUsageError,\n getDraftModeCookieHeader,\n markDynamicUsage,\n setHeadersContext,\n} from \"vinext/shims/headers\";\nimport { getRequestExecutionContext } from \"vinext/shims/request-context\";\nimport { createRequestContext, runWithRequestContext } from \"vinext/shims/unified-request-context\";\nimport {\n ensureFetchPatch,\n getCollectedFetchTags,\n setCurrentFetchSoftTags,\n} from \"vinext/shims/fetch-cache\";\nimport type { AppOutgoingElements } from \"./app-elements.js\";\nimport { readAppPageCacheResponse } from \"./app-page-cache.js\";\nimport { resolveAppPageParentHttpAccessBoundaryModule } from \"./app-page-boundary.js\";\nimport {\n buildAppPageSpecialErrorResponse,\n readAppPageTextStream,\n resolveAppPageSpecialError,\n teeAppPageRscStreamForCapture,\n type AppPageFontPreload,\n type AppPageSpecialError,\n type LayoutClassificationOptions,\n} from \"./app-page-execution.js\";\nimport { resolveAppPageMethodResponse } from \"./app-page-method.js\";\nimport {\n buildAppPageElement,\n resolveAppPageIntercept,\n validateAppPageDynamicParams,\n} from \"./app-page-request.js\";\nimport { renderAppPageLifecycle } from \"./app-page-render.js\";\nimport {\n mergeMiddlewareResponseHeaders,\n type AppPageMiddlewareContext,\n} from \"./app-page-response.js\";\nimport { createAppPageTreePath } from \"./app-page-route-wiring.js\";\nimport type { AppPageSsrHandler } from \"./app-page-stream.js\";\nimport { createStaticGenerationHeadersContext } from \"./app-static-generation.js\";\nimport { buildPageCacheTags } from \"./implicit-tags.js\";\nimport type { ISRCacheEntry } from \"./isr-cache.js\";\n\ntype AppPageParams = Record<string, string | string[]>;\ntype AppPageElement = ReactNode | Readonly<Record<string, ReactNode>>;\ntype AppPageRenderableElement = ReactNode | AppOutgoingElements;\ntype AppPageBoundaryOnError = (\n error: unknown,\n requestInfo: unknown,\n errorContext: unknown,\n) => unknown;\ntype AppPageDebugLogger = (event: string, detail: string) => void;\ntype AppPageCacheSetter = (\n key: string,\n data: CachedAppPageValue,\n revalidateSeconds: number,\n tags: string[],\n) => Promise<void>;\ntype AppPageCacheGetter = (key: string) => Promise<ISRCacheEntry | null>;\ntype AppPageBackgroundRegenerationErrorContext = {\n routerKind: \"App Router\";\n routePath: string;\n routeType: \"render\";\n};\ntype AppPageBackgroundRegenerator = (\n key: string,\n renderFn: () => Promise<void>,\n errorContext?: AppPageBackgroundRegenerationErrorContext,\n) => void;\n\ntype AppPageDispatchIntercept<TPage = unknown> = {\n interceptLayouts?: readonly AppPageModule[] | null;\n matchedParams: AppPageParams;\n page: TPage;\n slotKey: string;\n sourceRouteIndex: number;\n};\n\ntype AppPageDispatchInterceptOptions<TPage = unknown> = {\n interceptionContext: string | null;\n interceptLayouts?: readonly AppPageModule[] | null;\n interceptPage: TPage;\n interceptParams: AppPageParams;\n interceptSlotKey: string;\n};\n\ntype AppPageModule = {\n default?: unknown;\n};\n\ntype AppPageDispatchRoute = {\n __buildTimeClassifications?: LayoutClassificationOptions[\"buildTimeClassifications\"];\n __buildTimeReasons?: LayoutClassificationOptions[\"buildTimeReasons\"];\n error?: AppPageModule | null;\n errors?: readonly (AppPageModule | null | undefined)[];\n forbiddens?: readonly (AppPageModule | null | undefined)[];\n isDynamic: boolean;\n layouts: readonly AppPageModule[];\n layoutTreePositions?: readonly number[];\n loading?: AppPageModule | null;\n notFounds?: readonly (AppPageModule | null | undefined)[];\n params: readonly string[];\n pattern: string;\n routeSegments: readonly string[];\n unauthorizeds?: readonly (AppPageModule | null | undefined)[];\n};\n\ntype DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {\n buildPageElement: (\n route: TRoute,\n params: AppPageParams,\n opts: AppPageDispatchInterceptOptions | undefined,\n searchParams: URLSearchParams,\n ) => Promise<AppPageElement>;\n cleanPathname: string;\n clearRequestContext: () => void;\n createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;\n debugClassification?: (layoutId: string, reason: ClassificationReason) => void;\n dynamicConfig?: string;\n dynamicParamsConfig?: boolean;\n findIntercept: (pathname: string) => AppPageDispatchIntercept | null;\n generateStaticParams?: ((args: { params: AppPageParams }) => unknown) | null;\n getFontLinks: () => string[];\n getFontPreloads: () => AppPageFontPreload[];\n getFontStyles: () => string[];\n getNavigationContext: () => unknown;\n getSourceRoute: (sourceRouteIndex: number) => TRoute | undefined;\n hasGenerateStaticParams: boolean;\n hasPageDefaultExport: boolean;\n hasPageModule: boolean;\n handlerStart: number;\n interceptionContext: string | null;\n isProduction: boolean;\n isRscRequest: boolean;\n isrDebug?: AppPageDebugLogger;\n isrGet: AppPageCacheGetter;\n isrHtmlKey: (pathname: string) => string;\n isrRscKey: (pathname: string, mountedSlotsHeader?: string | null) => string;\n isrSet: AppPageCacheSetter;\n loadSsrHandler: () => Promise<AppPageSsrHandler>;\n middlewareContext: AppPageMiddlewareContext;\n mountedSlotsHeader?: string | null;\n params: AppPageParams;\n probeLayoutAt: (layoutIndex: number) => unknown;\n probePage: () => unknown;\n renderErrorBoundaryPage: (error: unknown) => Promise<Response | null>;\n renderHttpAccessFallbackPage: (\n statusCode: number,\n opts: {\n boundaryComponent?: unknown;\n layouts?: readonly AppPageModule[];\n matchedParams: AppPageParams;\n },\n middlewareContext: AppPageMiddlewareContext | null,\n ) => Promise<Response | null>;\n renderToReadableStream: (\n element: AppPageRenderableElement,\n options: { onError: AppPageBoundaryOnError },\n ) => ReadableStream<Uint8Array>;\n request: Request;\n revalidateSeconds: number | null;\n rootForbiddenModule?: AppPageModule | null;\n rootNotFoundModule?: AppPageModule | null;\n rootUnauthorizedModule?: AppPageModule | null;\n route: TRoute;\n runWithSuppressedHookWarning<T>(probe: () => Promise<T>): Promise<T>;\n scheduleBackgroundRegeneration: AppPageBackgroundRegenerator;\n scriptNonce?: string;\n searchParams: URLSearchParams;\n setNavigationContext: (context: {\n params: AppPageParams;\n pathname: string;\n searchParams: URLSearchParams;\n }) => void;\n};\n\nfunction shouldReadAppPageCache(options: {\n isForceDynamic: boolean;\n isProduction: boolean;\n isRscRequest: boolean;\n revalidateSeconds: number | null;\n scriptNonce?: string;\n}): boolean {\n return (\n options.isProduction &&\n !options.isForceDynamic &&\n (options.isRscRequest || !options.scriptNonce) &&\n options.revalidateSeconds !== null &&\n options.revalidateSeconds > 0 &&\n options.revalidateSeconds !== Infinity\n );\n}\n\nfunction buildAppPageTags(\n cleanPathname: string,\n extraTags: string[],\n routeSegments: readonly string[],\n): string[] {\n return buildPageCacheTags(cleanPathname, extraTags, [...routeSegments], \"page\");\n}\n\nasync function runAppPageRevalidationContext(\n options: {\n cleanPathname: string;\n dynamicConfig?: string;\n params: AppPageParams;\n routePattern: string;\n routeSegments: readonly string[];\n setNavigationContext: DispatchAppPageOptions<AppPageDispatchRoute>[\"setNavigationContext\"];\n },\n renderFn: () => Promise<{\n html: string;\n rscData: ArrayBuffer;\n tags: string[];\n }>,\n): Promise<{\n html: string;\n rscData: ArrayBuffer;\n tags: string[];\n}> {\n const headersContext = createStaticGenerationHeadersContext({\n dynamicConfig: options.dynamicConfig,\n routeKind: \"page\",\n routePattern: options.routePattern,\n });\n const requestContext = createRequestContext({\n headersContext,\n executionContext: getRequestExecutionContext(),\n unstableCacheRevalidation: \"foreground\",\n });\n\n return runWithRequestContext(requestContext, async () => {\n ensureFetchPatch();\n setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], options.routeSegments));\n options.setNavigationContext({\n pathname: options.cleanPathname,\n searchParams: new URLSearchParams(),\n params: options.params,\n });\n return renderFn();\n });\n}\n\nfunction getCapturedRscDataPromise(\n capturedRscDataPromise: Promise<ArrayBuffer> | null,\n): Promise<ArrayBuffer> {\n if (!capturedRscDataPromise) {\n throw new Error(\n \"[vinext] Expected captured RSC data while regenerating an app page cache entry\",\n );\n }\n\n return capturedRscDataPromise;\n}\n\nfunction toInterceptOptions(\n interceptionContext: string | null,\n intercept: AppPageDispatchIntercept,\n): AppPageDispatchInterceptOptions {\n return {\n interceptionContext,\n interceptLayouts: intercept.interceptLayouts,\n interceptPage: intercept.page,\n interceptParams: intercept.matchedParams,\n interceptSlotKey: intercept.slotKey,\n };\n}\n\nexport async function dispatchAppPage<TRoute extends AppPageDispatchRoute>(\n options: DispatchAppPageOptions<TRoute>,\n): Promise<Response> {\n const route = options.route;\n const dynamicConfig = options.dynamicConfig;\n const currentRevalidateSeconds = options.revalidateSeconds;\n const isForceStatic = dynamicConfig === \"force-static\";\n const isDynamicError = dynamicConfig === \"error\";\n const isForceDynamic = dynamicConfig === \"force-dynamic\";\n\n setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], route.routeSegments));\n\n if (options.hasPageModule && !options.hasPageDefaultExport) {\n options.clearRequestContext();\n return new Response(\"Page has no default export\", { status: 500 });\n }\n\n const methodResponse = resolveAppPageMethodResponse({\n dynamicConfig,\n hasGenerateStaticParams: options.hasGenerateStaticParams,\n isDynamicRoute: route.isDynamic,\n middlewareHeaders: options.middlewareContext.headers,\n request: options.request,\n revalidateSeconds: currentRevalidateSeconds,\n });\n if (methodResponse) {\n options.clearRequestContext();\n return methodResponse;\n }\n\n if (isForceStatic || isDynamicError) {\n setHeadersContext(\n createStaticGenerationHeadersContext({\n dynamicConfig,\n routeKind: \"page\",\n routePattern: route.pattern,\n }),\n );\n options.setNavigationContext({\n pathname: options.cleanPathname,\n searchParams: new URLSearchParams(),\n params: options.params,\n });\n }\n\n if (\n shouldReadAppPageCache({\n isForceDynamic,\n isProduction: options.isProduction,\n isRscRequest: options.isRscRequest,\n revalidateSeconds: currentRevalidateSeconds,\n scriptNonce: options.scriptNonce,\n })\n ) {\n const cachedPageResponse = await readAppPageCacheResponse({\n cleanPathname: options.cleanPathname,\n clearRequestContext: options.clearRequestContext,\n isRscRequest: options.isRscRequest,\n isrDebug: options.isrDebug,\n isrGet: options.isrGet,\n isrHtmlKey: options.isrHtmlKey,\n isrRscKey: options.isrRscKey,\n isrSet: options.isrSet,\n mountedSlotsHeader: options.mountedSlotsHeader,\n revalidateSeconds: currentRevalidateSeconds ?? 0,\n renderFreshPageForCache: async () =>\n runAppPageRevalidationContext(\n {\n cleanPathname: options.cleanPathname,\n dynamicConfig,\n params: options.params,\n routePattern: route.pattern,\n routeSegments: route.routeSegments,\n setNavigationContext: options.setNavigationContext,\n },\n async () => {\n const revalidatedElement = await options.buildPageElement(\n route,\n options.params,\n undefined,\n new URLSearchParams(),\n );\n const revalidatedOnError = options.createRscOnErrorHandler(\n options.cleanPathname,\n route.pattern,\n );\n const revalidatedRscStream = options.renderToReadableStream(revalidatedElement, {\n onError: revalidatedOnError,\n });\n const revalidatedRscCapture = teeAppPageRscStreamForCapture(revalidatedRscStream, true);\n const revalidatedSsrEntry = await options.loadSsrHandler();\n const revalidatedCapturedRscRef: { value: Promise<ArrayBuffer> | null } = {\n value: null,\n };\n const revalidatedHtmlStream = await revalidatedSsrEntry.handleSsr(\n revalidatedRscCapture.ssrStream,\n options.getNavigationContext(),\n {\n links: options.getFontLinks(),\n styles: options.getFontStyles(),\n preloads: options.getFontPreloads(),\n },\n revalidatedRscCapture.sideStream\n ? {\n sideStream: revalidatedRscCapture.sideStream,\n capturedRscDataRef: revalidatedCapturedRscRef,\n }\n : undefined,\n );\n options.clearRequestContext();\n const html = await readAppPageTextStream(revalidatedHtmlStream);\n const rscData = await getCapturedRscDataPromise(revalidatedCapturedRscRef.value);\n const tags = buildAppPageTags(\n options.cleanPathname,\n getCollectedFetchTags(),\n route.routeSegments,\n );\n return { html, rscData, tags };\n },\n ),\n scheduleBackgroundRegeneration(key, renderFn) {\n options.scheduleBackgroundRegeneration(key, renderFn, {\n routerKind: \"App Router\",\n routePath: route.pattern,\n routeType: \"render\",\n });\n },\n });\n if (cachedPageResponse) {\n return cachedPageResponse;\n }\n }\n\n const dynamicParamsResponse = await validateAppPageDynamicParams({\n clearRequestContext: options.clearRequestContext,\n enforceStaticParamsOnly: options.dynamicParamsConfig === false,\n generateStaticParams: options.generateStaticParams,\n isDynamicRoute: route.isDynamic,\n logGenerateStaticParamsError(error) {\n console.error(\"[vinext] generateStaticParams error:\", error);\n },\n params: options.params,\n });\n if (dynamicParamsResponse) {\n return dynamicParamsResponse;\n }\n\n const interceptResult = await resolveAppPageIntercept<\n TRoute,\n unknown,\n AppPageDispatchInterceptOptions,\n AppPageElement\n >({\n buildPageElement(interceptRoute, interceptParams, interceptOpts, interceptSearchParams) {\n return options.buildPageElement(\n interceptRoute,\n interceptParams,\n interceptOpts,\n interceptSearchParams,\n );\n },\n cleanPathname: options.cleanPathname,\n currentRoute: route,\n findIntercept(pathname) {\n return options.findIntercept(pathname);\n },\n getRouteParamNames(sourceRoute) {\n return sourceRoute.params;\n },\n getSourceRoute(sourceRouteIndex) {\n return options.getSourceRoute(sourceRouteIndex);\n },\n isRscRequest: options.isRscRequest,\n renderInterceptResponse(sourceRoute, interceptElement) {\n const interceptOnError = options.createRscOnErrorHandler(\n options.cleanPathname,\n sourceRoute.pattern,\n );\n const interceptStream = options.renderToReadableStream(interceptElement, {\n onError: interceptOnError,\n });\n const interceptHeaders = new Headers({\n \"Content-Type\": \"text/x-component; charset=utf-8\",\n Vary: \"RSC, Accept\",\n });\n mergeMiddlewareResponseHeaders(interceptHeaders, options.middlewareContext.headers);\n return new Response(interceptStream, {\n status: options.middlewareContext.status ?? 200,\n headers: interceptHeaders,\n });\n },\n searchParams: options.searchParams,\n setNavigationContext: options.setNavigationContext,\n toInterceptOpts(intercept) {\n return toInterceptOptions(options.interceptionContext, intercept);\n },\n });\n if (interceptResult.response) {\n return interceptResult.response;\n }\n\n const pageBuildResult = await buildAppPageElement({\n buildPageElement() {\n return options.buildPageElement(\n route,\n options.params,\n interceptResult.interceptOpts,\n options.searchParams,\n );\n },\n renderErrorBoundaryPage(buildError) {\n return options.renderErrorBoundaryPage(buildError);\n },\n renderSpecialError(specialError) {\n return renderPageSpecialError(options, specialError);\n },\n resolveSpecialError: resolveAppPageSpecialError,\n });\n if (pageBuildResult.response) {\n return pageBuildResult.response;\n }\n\n return renderAppPageLifecycle({\n cleanPathname: options.cleanPathname,\n clearRequestContext: options.clearRequestContext,\n consumeDynamicUsage,\n consumeInvalidDynamicUsageError,\n createRscOnErrorHandler(pathname, routePath) {\n return options.createRscOnErrorHandler(pathname, routePath);\n },\n element: pageBuildResult.element,\n getDraftModeCookieHeader,\n getFontLinks: options.getFontLinks,\n getFontPreloads: options.getFontPreloads,\n getFontStyles: options.getFontStyles,\n getNavigationContext: options.getNavigationContext,\n getPageTags() {\n return buildAppPageTags(options.cleanPathname, getCollectedFetchTags(), route.routeSegments);\n },\n getRequestCacheLife() {\n return _consumeRequestScopedCacheLife();\n },\n handlerStart: options.handlerStart,\n hasLoadingBoundary: Boolean(route.loading?.default),\n isDynamicError,\n isForceDynamic,\n isForceStatic,\n isProduction: options.isProduction,\n isRscRequest: options.isRscRequest,\n isrDebug: options.isrDebug,\n isrHtmlKey: options.isrHtmlKey,\n isrRscKey: options.isrRscKey,\n isrSet: options.isrSet,\n layoutCount: route.layouts.length,\n loadSsrHandler: options.loadSsrHandler,\n middlewareContext: options.middlewareContext,\n params: options.params,\n probeLayoutAt(layoutIndex) {\n return options.probeLayoutAt(layoutIndex);\n },\n probePage() {\n return options.probePage();\n },\n classification: {\n getLayoutId(index) {\n const treePosition = route.layoutTreePositions?.[index] ?? 0;\n return \"layout:\" + createAppPageTreePath([...route.routeSegments], treePosition);\n },\n buildTimeClassifications: route.__buildTimeClassifications,\n buildTimeReasons: route.__buildTimeReasons,\n debugClassification: options.debugClassification,\n async runWithIsolatedDynamicScope(fn) {\n const priorDynamic = consumeDynamicUsage();\n try {\n const result = await fn();\n const dynamicDetected = consumeDynamicUsage();\n return { result, dynamicDetected };\n } finally {\n consumeDynamicUsage();\n if (priorDynamic) markDynamicUsage();\n }\n },\n },\n revalidateSeconds: currentRevalidateSeconds,\n mountedSlotsHeader: options.mountedSlotsHeader,\n renderErrorBoundaryResponse(renderError) {\n return options.renderErrorBoundaryPage(renderError);\n },\n renderLayoutSpecialError(specialError, layoutIndex) {\n return renderLayoutSpecialError(options, specialError, layoutIndex);\n },\n renderPageSpecialError(specialError) {\n return renderPageSpecialError(options, specialError);\n },\n renderToReadableStream: options.renderToReadableStream,\n routeHasLocalBoundary: Boolean(\n route.error?.default || route.errors?.some((errorModule) => errorModule?.default),\n ),\n routePattern: route.pattern,\n runWithSuppressedHookWarning(probe) {\n return options.runWithSuppressedHookWarning(probe);\n },\n scriptNonce: options.scriptNonce,\n waitUntil(cachePromise) {\n getRequestExecutionContext()?.waitUntil(cachePromise);\n },\n });\n}\n\nasync function renderLayoutSpecialError<TRoute extends AppPageDispatchRoute>(\n options: DispatchAppPageOptions<TRoute>,\n specialError: AppPageSpecialError,\n layoutIndex: number,\n): Promise<Response> {\n return buildAppPageSpecialErrorResponse({\n clearRequestContext: options.clearRequestContext,\n middlewareContext: options.middlewareContext,\n renderFallbackPage(statusCode) {\n const parentBoundary = resolveAppPageParentHttpAccessBoundaryModule({\n layoutIndex,\n rootForbiddenModule: options.rootForbiddenModule,\n rootNotFoundModule: options.rootNotFoundModule,\n rootUnauthorizedModule: options.rootUnauthorizedModule,\n routeForbiddenModules: options.route.forbiddens,\n routeNotFoundModules: options.route.notFounds,\n routeUnauthorizedModules: options.route.unauthorizeds,\n statusCode,\n })?.default;\n return options.renderHttpAccessFallbackPage(\n statusCode,\n {\n boundaryComponent: parentBoundary,\n layouts: options.route.layouts.slice(0, layoutIndex),\n matchedParams: options.params,\n },\n null,\n );\n },\n requestUrl: options.request.url,\n specialError,\n });\n}\n\nasync function renderPageSpecialError<TRoute extends AppPageDispatchRoute>(\n options: DispatchAppPageOptions<TRoute>,\n specialError: AppPageSpecialError,\n): Promise<Response> {\n return buildAppPageSpecialErrorResponse({\n clearRequestContext: options.clearRequestContext,\n middlewareContext: options.middlewareContext,\n renderFallbackPage(statusCode) {\n return options.renderHttpAccessFallbackPage(\n statusCode,\n { matchedParams: options.params },\n null,\n );\n },\n requestUrl: options.request.url,\n specialError,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"app-page-dispatch.js","names":[],"sources":["../../src/server/app-page-dispatch.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { ClassificationReason } from \"../build/layout-classification-types.js\";\nimport {\n _consumeRequestScopedCacheLife,\n _peekRequestScopedCacheLife,\n type CachedAppPageValue,\n} from \"vinext/shims/cache\";\nimport {\n consumeDynamicUsage,\n consumeInvalidDynamicUsageError,\n getDraftModeCookieHeader,\n markDynamicUsage,\n setHeadersContext,\n} from \"vinext/shims/headers\";\nimport { getRequestExecutionContext } from \"vinext/shims/request-context\";\nimport { createRequestContext, runWithRequestContext } from \"vinext/shims/unified-request-context\";\nimport {\n ensureFetchPatch,\n type FetchCacheMode,\n getCollectedFetchTags,\n setCurrentFetchCacheMode,\n setCurrentFetchSoftTags,\n} from \"vinext/shims/fetch-cache\";\nimport type { AppOutgoingElements } from \"./app-elements.js\";\nimport { readAppPageCacheResponse } from \"./app-page-cache.js\";\nimport { resolveAppPageParentHttpAccessBoundaryModule } from \"./app-page-boundary.js\";\nimport {\n buildAppPageSpecialErrorResponse,\n readAppPageTextStream,\n resolveAppPageSpecialError,\n teeAppPageRscStreamForCapture,\n type AppPageFontPreload,\n type AppPageSpecialError,\n type LayoutClassificationOptions,\n} from \"./app-page-execution.js\";\nimport { resolveAppPageMethodResponse } from \"./app-page-method.js\";\nimport {\n buildAppPageElement,\n resolveAppPageIntercept,\n validateAppPageDynamicParams,\n type ValidateAppPageDynamicParamsOptions,\n} from \"./app-page-request.js\";\nimport { renderAppPageLifecycle } from \"./app-page-render.js\";\nimport {\n mergeMiddlewareResponseHeaders,\n type AppPageMiddlewareContext,\n} from \"./app-page-response.js\";\nimport { createAppPageTreePath } from \"./app-page-route-wiring.js\";\nimport type { AppPageSsrHandler } from \"./app-page-stream.js\";\nimport { createStaticGenerationHeadersContext } from \"./app-static-generation.js\";\nimport { buildPageCacheTags } from \"./implicit-tags.js\";\nimport type { ISRCacheEntry } from \"./isr-cache.js\";\n\ntype AppPageParams = Record<string, string | string[]>;\ntype AppPageElement = ReactNode | Readonly<Record<string, ReactNode>>;\ntype AppPageRenderableElement = ReactNode | AppOutgoingElements;\ntype AppPageBoundaryOnError = (\n error: unknown,\n requestInfo: unknown,\n errorContext: unknown,\n) => unknown;\ntype AppPageDebugLogger = (event: string, detail: string) => void;\ntype AppPageCacheSetter = (\n key: string,\n data: CachedAppPageValue,\n revalidateSeconds: number,\n tags: string[],\n expireSeconds?: number,\n) => Promise<void>;\ntype AppPageCacheGetter = (key: string) => Promise<ISRCacheEntry | null>;\ntype AppPageBackgroundRegenerationErrorContext = {\n routerKind: \"App Router\";\n routePath: string;\n routeType: \"render\";\n};\ntype AppPageBackgroundRegenerator = (\n key: string,\n renderFn: () => Promise<void>,\n errorContext?: AppPageBackgroundRegenerationErrorContext,\n) => void;\n\ntype AppPageDispatchIntercept<TPage = unknown> = {\n interceptLayouts?: readonly AppPageModule[] | null;\n matchedParams: AppPageParams;\n page: TPage;\n slotKey: string;\n sourceRouteIndex: number;\n};\n\ntype AppPageDispatchInterceptOptions<TPage = unknown> = {\n interceptionContext: string | null;\n interceptLayouts?: readonly AppPageModule[] | null;\n interceptPage: TPage;\n interceptParams: AppPageParams;\n interceptSlotKey: string;\n};\n\ntype AppPageModule = {\n default?: unknown;\n};\n\ntype AppPageDispatchRoute = {\n __buildTimeClassifications?: LayoutClassificationOptions[\"buildTimeClassifications\"];\n __buildTimeReasons?: LayoutClassificationOptions[\"buildTimeReasons\"];\n error?: AppPageModule | null;\n errors?: readonly (AppPageModule | null | undefined)[];\n forbiddens?: readonly (AppPageModule | null | undefined)[];\n isDynamic: boolean;\n layouts: readonly AppPageModule[];\n layoutTreePositions?: readonly number[];\n loading?: AppPageModule | null;\n notFounds?: readonly (AppPageModule | null | undefined)[];\n params: readonly string[];\n pattern: string;\n routeSegments: readonly string[];\n unauthorizeds?: readonly (AppPageModule | null | undefined)[];\n};\n\ntype DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {\n buildPageElement: (\n route: TRoute,\n params: AppPageParams,\n opts: AppPageDispatchInterceptOptions | undefined,\n searchParams: URLSearchParams,\n ) => Promise<AppPageElement>;\n cleanPathname: string;\n clearRequestContext: () => void;\n createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;\n debugClassification?: (layoutId: string, reason: ClassificationReason) => void;\n dynamicConfig?: string;\n dynamicParamsConfig?: boolean;\n fetchCache?: FetchCacheMode | null;\n findIntercept: (pathname: string) => AppPageDispatchIntercept | null;\n generateStaticParams?: ValidateAppPageDynamicParamsOptions[\"generateStaticParams\"];\n getFontLinks: () => string[];\n getFontPreloads: () => AppPageFontPreload[];\n getFontStyles: () => string[];\n getNavigationContext: () => unknown;\n getSourceRoute: (sourceRouteIndex: number) => TRoute | undefined;\n hasGenerateStaticParams: boolean;\n hasPageDefaultExport: boolean;\n hasPageModule: boolean;\n handlerStart: number;\n interceptionContext: string | null;\n isProduction: boolean;\n isRscRequest: boolean;\n isrDebug?: AppPageDebugLogger;\n isrGet: AppPageCacheGetter;\n isrHtmlKey: (pathname: string) => string;\n isrRscKey: (pathname: string, mountedSlotsHeader?: string | null) => string;\n isrSet: AppPageCacheSetter;\n loadSsrHandler: () => Promise<AppPageSsrHandler>;\n middlewareContext: AppPageMiddlewareContext;\n mountedSlotsHeader?: string | null;\n params: AppPageParams;\n probeLayoutAt: (layoutIndex: number) => unknown;\n probePage: () => unknown;\n expireSeconds?: number;\n renderErrorBoundaryPage: (error: unknown) => Promise<Response | null>;\n renderHttpAccessFallbackPage: (\n statusCode: number,\n opts: {\n boundaryComponent?: unknown;\n layouts?: readonly AppPageModule[];\n matchedParams: AppPageParams;\n },\n middlewareContext: AppPageMiddlewareContext | null,\n ) => Promise<Response | null>;\n renderToReadableStream: (\n element: AppPageRenderableElement,\n options: { onError: AppPageBoundaryOnError },\n ) => ReadableStream<Uint8Array>;\n request: Request;\n revalidateSeconds: number | null;\n resolveRouteFetchCacheMode?: (route: TRoute) => FetchCacheMode | null;\n rootForbiddenModule?: AppPageModule | null;\n rootNotFoundModule?: AppPageModule | null;\n rootUnauthorizedModule?: AppPageModule | null;\n route: TRoute;\n runWithSuppressedHookWarning<T>(probe: () => Promise<T>): Promise<T>;\n scheduleBackgroundRegeneration: AppPageBackgroundRegenerator;\n scriptNonce?: string;\n searchParams: URLSearchParams;\n setNavigationContext: (context: {\n params: AppPageParams;\n pathname: string;\n searchParams: URLSearchParams;\n }) => void;\n};\n\nfunction shouldReadAppPageCache(options: {\n isForceDynamic: boolean;\n isProduction: boolean;\n isRscRequest: boolean;\n revalidateSeconds: number | null;\n scriptNonce?: string;\n}): boolean {\n return (\n options.isProduction &&\n !options.isForceDynamic &&\n (options.isRscRequest || !options.scriptNonce) &&\n (options.revalidateSeconds === null ||\n (options.revalidateSeconds > 0 && options.revalidateSeconds !== Infinity))\n );\n}\n\nfunction buildAppPageTags(\n cleanPathname: string,\n extraTags: string[],\n routeSegments: readonly string[],\n): string[] {\n return buildPageCacheTags(cleanPathname, extraTags, [...routeSegments], \"page\");\n}\n\nasync function runAppPageRevalidationContext(\n options: {\n cleanPathname: string;\n currentFetchCacheMode?: FetchCacheMode | null;\n dynamicConfig?: string;\n params: AppPageParams;\n routePattern: string;\n routeSegments: readonly string[];\n setNavigationContext: DispatchAppPageOptions<AppPageDispatchRoute>[\"setNavigationContext\"];\n },\n renderFn: () => Promise<{\n html: string;\n rscData: ArrayBuffer;\n tags: string[];\n }>,\n): Promise<{\n html: string;\n rscData: ArrayBuffer;\n tags: string[];\n}> {\n const headersContext = createStaticGenerationHeadersContext({\n dynamicConfig: options.dynamicConfig,\n routeKind: \"page\",\n routePattern: options.routePattern,\n });\n const requestContext = createRequestContext({\n headersContext,\n currentFetchCacheMode: options.currentFetchCacheMode ?? null,\n executionContext: getRequestExecutionContext(),\n unstableCacheRevalidation: \"foreground\",\n });\n\n return runWithRequestContext(requestContext, async () => {\n ensureFetchPatch();\n setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], options.routeSegments));\n options.setNavigationContext({\n pathname: options.cleanPathname,\n searchParams: new URLSearchParams(),\n params: options.params,\n });\n return renderFn();\n });\n}\n\nfunction getCapturedRscDataPromise(\n capturedRscDataPromise: Promise<ArrayBuffer> | null,\n): Promise<ArrayBuffer> {\n if (!capturedRscDataPromise) {\n throw new Error(\n \"[vinext] Expected captured RSC data while regenerating an app page cache entry\",\n );\n }\n\n return capturedRscDataPromise;\n}\n\nfunction toInterceptOptions(\n interceptionContext: string | null,\n intercept: AppPageDispatchIntercept,\n): AppPageDispatchInterceptOptions {\n return {\n interceptionContext,\n interceptLayouts: intercept.interceptLayouts,\n interceptPage: intercept.page,\n interceptParams: intercept.matchedParams,\n interceptSlotKey: intercept.slotKey,\n };\n}\n\nexport async function dispatchAppPage<TRoute extends AppPageDispatchRoute>(\n options: DispatchAppPageOptions<TRoute>,\n): Promise<Response> {\n const route = options.route;\n const dynamicConfig = options.dynamicConfig;\n const currentRevalidateSeconds = options.revalidateSeconds;\n const isForceStatic = dynamicConfig === \"force-static\";\n const isDynamicError = dynamicConfig === \"error\";\n const isForceDynamic = dynamicConfig === \"force-dynamic\";\n\n setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], route.routeSegments));\n setCurrentFetchCacheMode(options.fetchCache ?? null);\n\n if (options.hasPageModule && !options.hasPageDefaultExport) {\n options.clearRequestContext();\n return new Response(\"Page has no default export\", { status: 500 });\n }\n\n const methodResponse = resolveAppPageMethodResponse({\n dynamicConfig,\n hasGenerateStaticParams: options.hasGenerateStaticParams,\n isDynamicRoute: route.isDynamic,\n middlewareHeaders: options.middlewareContext.headers,\n request: options.request,\n revalidateSeconds: currentRevalidateSeconds,\n });\n if (methodResponse) {\n options.clearRequestContext();\n return methodResponse;\n }\n\n if (isForceStatic || isDynamicError) {\n setHeadersContext(\n createStaticGenerationHeadersContext({\n dynamicConfig,\n routeKind: \"page\",\n routePattern: route.pattern,\n }),\n );\n options.setNavigationContext({\n pathname: options.cleanPathname,\n searchParams: new URLSearchParams(),\n params: options.params,\n });\n }\n\n if (\n shouldReadAppPageCache({\n isForceDynamic,\n isProduction: options.isProduction,\n isRscRequest: options.isRscRequest,\n revalidateSeconds: currentRevalidateSeconds,\n scriptNonce: options.scriptNonce,\n })\n ) {\n const cachedPageResponse = await readAppPageCacheResponse({\n cleanPathname: options.cleanPathname,\n clearRequestContext: options.clearRequestContext,\n isRscRequest: options.isRscRequest,\n isrDebug: options.isrDebug,\n isrGet: options.isrGet,\n isrHtmlKey: options.isrHtmlKey,\n isrRscKey: options.isrRscKey,\n isrSet: options.isrSet,\n mountedSlotsHeader: options.mountedSlotsHeader,\n expireSeconds: options.expireSeconds,\n // cacheLife-only routes discover their actual revalidate during the\n // fresh render; this seed only gets them into the cache read path.\n revalidateSeconds: currentRevalidateSeconds ?? 0,\n renderFreshPageForCache: async () =>\n runAppPageRevalidationContext(\n {\n cleanPathname: options.cleanPathname,\n currentFetchCacheMode: options.fetchCache ?? null,\n dynamicConfig,\n params: options.params,\n routePattern: route.pattern,\n routeSegments: route.routeSegments,\n setNavigationContext: options.setNavigationContext,\n },\n async () => {\n const revalidatedElement = await options.buildPageElement(\n route,\n options.params,\n undefined,\n new URLSearchParams(),\n );\n const revalidatedOnError = options.createRscOnErrorHandler(\n options.cleanPathname,\n route.pattern,\n );\n const revalidatedRscStream = options.renderToReadableStream(revalidatedElement, {\n onError: revalidatedOnError,\n });\n const revalidatedRscCapture = teeAppPageRscStreamForCapture(revalidatedRscStream, true);\n const revalidatedSsrEntry = await options.loadSsrHandler();\n const revalidatedCapturedRscRef: { value: Promise<ArrayBuffer> | null } = {\n value: null,\n };\n const revalidatedHtmlStream = await revalidatedSsrEntry.handleSsr(\n revalidatedRscCapture.ssrStream,\n options.getNavigationContext(),\n {\n links: options.getFontLinks(),\n styles: options.getFontStyles(),\n preloads: options.getFontPreloads(),\n },\n revalidatedRscCapture.sideStream\n ? {\n sideStream: revalidatedRscCapture.sideStream,\n capturedRscDataRef: revalidatedCapturedRscRef,\n }\n : undefined,\n );\n const html = await readAppPageTextStream(revalidatedHtmlStream);\n const rscData = await getCapturedRscDataPromise(revalidatedCapturedRscRef.value);\n const cacheLife = _consumeRequestScopedCacheLife();\n options.clearRequestContext();\n const tags = buildAppPageTags(\n options.cleanPathname,\n getCollectedFetchTags(),\n route.routeSegments,\n );\n return {\n html,\n rscData,\n tags,\n cacheControl:\n typeof cacheLife?.revalidate === \"number\"\n ? { revalidate: cacheLife.revalidate, expire: cacheLife.expire }\n : undefined,\n };\n },\n ),\n scheduleBackgroundRegeneration(key, renderFn) {\n options.scheduleBackgroundRegeneration(key, renderFn, {\n routerKind: \"App Router\",\n routePath: route.pattern,\n routeType: \"render\",\n });\n },\n });\n if (cachedPageResponse) {\n return cachedPageResponse;\n }\n }\n\n const dynamicParamsResponse = await validateAppPageDynamicParams({\n clearRequestContext: options.clearRequestContext,\n enforceStaticParamsOnly: options.dynamicParamsConfig === false,\n generateStaticParams: options.generateStaticParams,\n isDynamicRoute: route.isDynamic,\n logGenerateStaticParamsError(error) {\n console.error(\"[vinext] generateStaticParams error:\", error);\n },\n params: options.params,\n });\n if (dynamicParamsResponse) {\n return dynamicParamsResponse;\n }\n\n const interceptResult = await resolveAppPageIntercept<\n TRoute,\n unknown,\n AppPageDispatchInterceptOptions,\n AppPageElement\n >({\n buildPageElement(interceptRoute, interceptParams, interceptOpts, interceptSearchParams) {\n setCurrentFetchCacheMode(options.resolveRouteFetchCacheMode?.(interceptRoute) ?? null);\n return options.buildPageElement(\n interceptRoute,\n interceptParams,\n interceptOpts,\n interceptSearchParams,\n );\n },\n cleanPathname: options.cleanPathname,\n currentRoute: route,\n findIntercept(pathname) {\n return options.findIntercept(pathname);\n },\n getRouteParamNames(sourceRoute) {\n return sourceRoute.params;\n },\n getSourceRoute(sourceRouteIndex) {\n return options.getSourceRoute(sourceRouteIndex);\n },\n isRscRequest: options.isRscRequest,\n renderInterceptResponse(sourceRoute, interceptElement) {\n const interceptOnError = options.createRscOnErrorHandler(\n options.cleanPathname,\n sourceRoute.pattern,\n );\n const interceptStream = options.renderToReadableStream(interceptElement, {\n onError: interceptOnError,\n });\n const interceptHeaders = new Headers({\n \"Content-Type\": \"text/x-component; charset=utf-8\",\n Vary: \"RSC, Accept\",\n });\n mergeMiddlewareResponseHeaders(interceptHeaders, options.middlewareContext.headers);\n return new Response(interceptStream, {\n status: options.middlewareContext.status ?? 200,\n headers: interceptHeaders,\n });\n },\n searchParams: options.searchParams,\n setNavigationContext: options.setNavigationContext,\n toInterceptOpts(intercept) {\n return toInterceptOptions(options.interceptionContext, intercept);\n },\n });\n if (interceptResult.response) {\n return interceptResult.response;\n }\n\n const pageBuildResult = await buildAppPageElement({\n buildPageElement() {\n return options.buildPageElement(\n route,\n options.params,\n interceptResult.interceptOpts,\n options.searchParams,\n );\n },\n renderErrorBoundaryPage(buildError) {\n return options.renderErrorBoundaryPage(buildError);\n },\n renderSpecialError(specialError) {\n return renderPageSpecialError(options, specialError);\n },\n resolveSpecialError: resolveAppPageSpecialError,\n });\n if (pageBuildResult.response) {\n return pageBuildResult.response;\n }\n\n return renderAppPageLifecycle({\n cleanPathname: options.cleanPathname,\n clearRequestContext: options.clearRequestContext,\n consumeDynamicUsage,\n consumeInvalidDynamicUsageError,\n createRscOnErrorHandler(pathname, routePath) {\n return options.createRscOnErrorHandler(pathname, routePath);\n },\n element: pageBuildResult.element,\n getDraftModeCookieHeader,\n getFontLinks: options.getFontLinks,\n getFontPreloads: options.getFontPreloads,\n getFontStyles: options.getFontStyles,\n getNavigationContext: options.getNavigationContext,\n getPageTags() {\n return buildAppPageTags(options.cleanPathname, getCollectedFetchTags(), route.routeSegments);\n },\n getRequestCacheLife() {\n return _consumeRequestScopedCacheLife();\n },\n peekRequestCacheLife() {\n return _peekRequestScopedCacheLife();\n },\n handlerStart: options.handlerStart,\n hasLoadingBoundary: Boolean(route.loading?.default),\n isDynamicError,\n isForceDynamic,\n isForceStatic,\n isPrerender: process.env.VINEXT_PRERENDER === \"1\",\n isProduction: options.isProduction,\n isRscRequest: options.isRscRequest,\n isrDebug: options.isrDebug,\n isrHtmlKey: options.isrHtmlKey,\n isrRscKey: options.isrRscKey,\n isrSet: options.isrSet,\n expireSeconds: options.expireSeconds,\n layoutCount: route.layouts.length,\n loadSsrHandler: options.loadSsrHandler,\n middlewareContext: options.middlewareContext,\n params: options.params,\n probeLayoutAt(layoutIndex) {\n return options.probeLayoutAt(layoutIndex);\n },\n probePage() {\n return options.probePage();\n },\n classification: {\n getLayoutId(index) {\n const treePosition = route.layoutTreePositions?.[index] ?? 0;\n return \"layout:\" + createAppPageTreePath([...route.routeSegments], treePosition);\n },\n buildTimeClassifications: route.__buildTimeClassifications,\n buildTimeReasons: route.__buildTimeReasons,\n debugClassification: options.debugClassification,\n async runWithIsolatedDynamicScope(fn) {\n const priorDynamic = consumeDynamicUsage();\n try {\n const result = await fn();\n const dynamicDetected = consumeDynamicUsage();\n return { result, dynamicDetected };\n } finally {\n consumeDynamicUsage();\n if (priorDynamic) markDynamicUsage();\n }\n },\n },\n revalidateSeconds: currentRevalidateSeconds,\n mountedSlotsHeader: options.mountedSlotsHeader,\n renderErrorBoundaryResponse(renderError) {\n return options.renderErrorBoundaryPage(renderError);\n },\n renderLayoutSpecialError(specialError, layoutIndex) {\n return renderLayoutSpecialError(options, specialError, layoutIndex);\n },\n renderPageSpecialError(specialError) {\n return renderPageSpecialError(options, specialError);\n },\n renderToReadableStream: options.renderToReadableStream,\n routeHasLocalBoundary: Boolean(\n route.error?.default || route.errors?.some((errorModule) => errorModule?.default),\n ),\n routePattern: route.pattern,\n runWithSuppressedHookWarning(probe) {\n return options.runWithSuppressedHookWarning(probe);\n },\n scriptNonce: options.scriptNonce,\n waitUntil(cachePromise) {\n getRequestExecutionContext()?.waitUntil(cachePromise);\n },\n });\n}\n\nasync function renderLayoutSpecialError<TRoute extends AppPageDispatchRoute>(\n options: DispatchAppPageOptions<TRoute>,\n specialError: AppPageSpecialError,\n layoutIndex: number,\n): Promise<Response> {\n return buildAppPageSpecialErrorResponse({\n clearRequestContext: options.clearRequestContext,\n middlewareContext: options.middlewareContext,\n renderFallbackPage(statusCode) {\n const parentBoundary = resolveAppPageParentHttpAccessBoundaryModule({\n layoutIndex,\n rootForbiddenModule: options.rootForbiddenModule,\n rootNotFoundModule: options.rootNotFoundModule,\n rootUnauthorizedModule: options.rootUnauthorizedModule,\n routeForbiddenModules: options.route.forbiddens,\n routeNotFoundModules: options.route.notFounds,\n routeUnauthorizedModules: options.route.unauthorizeds,\n statusCode,\n })?.default;\n return options.renderHttpAccessFallbackPage(\n statusCode,\n {\n boundaryComponent: parentBoundary,\n layouts: options.route.layouts.slice(0, layoutIndex),\n matchedParams: options.params,\n },\n null,\n );\n },\n requestUrl: options.request.url,\n specialError,\n });\n}\n\nasync function renderPageSpecialError<TRoute extends AppPageDispatchRoute>(\n options: DispatchAppPageOptions<TRoute>,\n specialError: AppPageSpecialError,\n): Promise<Response> {\n return buildAppPageSpecialErrorResponse({\n clearRequestContext: options.clearRequestContext,\n middlewareContext: options.middlewareContext,\n renderFallbackPage(statusCode) {\n return options.renderHttpAccessFallbackPage(\n statusCode,\n { matchedParams: options.params },\n null,\n );\n },\n requestUrl: options.request.url,\n specialError,\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import { MetadataFileRoute } from "./metadata-routes.js";
2
+ import { AppElements } from "./app-elements.js";
3
+ import { AppPageParams } from "./app-page-boundary.js";
4
+ import { AppPageErrorModule, AppPageModule, AppPageRouteWiringRoute } from "./app-page-route-wiring.js";
5
+
6
+ //#region src/server/app-page-element-builder.d.ts
7
+ /**
8
+ * Route shape passed from the generated entry. Extends the wiring route with
9
+ * the page module reference (used to extract the default export for the page
10
+ * element) and the URL pattern (used as the route path in head resolution).
11
+ */
12
+ type AppPageBuildRoute<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule> = AppPageRouteWiringRoute<TModule, TErrorModule> & {
13
+ page?: TModule | null;
14
+ pattern: string; /** Param names captured by the route's URL pattern, in order. */
15
+ params?: readonly string[] | null;
16
+ };
17
+ type AppPageInterceptOptions<TModule extends AppPageModule = AppPageModule> = {
18
+ interceptionContext?: string | null;
19
+ interceptLayouts?: readonly (TModule | null | undefined)[] | null;
20
+ interceptPage?: TModule | null;
21
+ interceptParams?: AppPageParams | null;
22
+ interceptSlotKey?: string | null;
23
+ };
24
+ type AppPagePageRequest<TModule extends AppPageModule = AppPageModule> = {
25
+ /** Interception context from current-route navigation (null for direct visits). */opts?: AppPageInterceptOptions<TModule> | null; /** URL search params from the incoming request (null when unavailable). */
26
+ searchParams?: URLSearchParams | null; /** Whether the incoming request is an RSC (client-side navigation) request. */
27
+ isRscRequest: boolean; /** The incoming HTTP request (available but unused by this module). */
28
+ request: Request; /** Normalized x-vinext-mounted-slots header value. */
29
+ mountedSlotsHeader: string | null;
30
+ };
31
+ type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule> = {
32
+ route: AppPageBuildRoute<TModule, TErrorModule>;
33
+ params: AppPageParams;
34
+ routePath: string;
35
+ pageRequest: AppPagePageRequest<TModule>; /** Root-level global-error.tsx module. Present when the app defines this file. */
36
+ globalErrorModule?: TErrorModule | null; /** Root-level not-found.tsx module. Present when the app defines this file. */
37
+ rootNotFoundModule?: TModule | null; /** Root-level forbidden.tsx module. Present when the app defines this file. */
38
+ rootForbiddenModule?: TModule | null; /** Root-level unauthorized.tsx module. Present when the app defines this file. */
39
+ rootUnauthorizedModule?: TModule | null; /** File-based metadata routes (favicon, manifest, sitemap, etc.). */
40
+ metadataRoutes: readonly MetadataFileRoute[];
41
+ };
42
+ /**
43
+ * Build the App Router element tree for a matched route.
44
+ *
45
+ * This is the central element-construction path for the App Router RSC
46
+ * handler. It resolves page head metadata (including parallel route metadata),
47
+ * creates the page React element, and wires it into the nested layout +
48
+ * boundary tree via {@link buildAppPageElements}.
49
+ *
50
+ * The function is extracted from the generated RSC entry template so it can
51
+ * be unit-tested independently of the code-generation machinery.
52
+ *
53
+ * Next.js equivalent: the component tree construction in
54
+ * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-component-tree.tsx|create-component-tree.tsx}
55
+ * and the page head resolution in
56
+ * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-metadata.tsx|create-metadata.tsx}.
57
+ */
58
+ declare function buildPageElements<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule>(options: BuildPageElementsOptions<TModule, TErrorModule>): Promise<AppElements>;
59
+ //#endregion
60
+ export { AppPageBuildRoute, type AppPageErrorModule, AppPageInterceptOptions, AppPagePageRequest, type AppPageRouteWiringRoute, BuildPageElementsOptions, buildPageElements };
61
+ //# sourceMappingURL=app-page-element-builder.d.ts.map
@@ -0,0 +1,139 @@
1
+ import { markDynamicUsage } from "../shims/headers.js";
2
+ import { APP_INTERCEPTION_CONTEXT_KEY, createAppPayloadRouteId } from "./app-elements.js";
3
+ import { matchRoutePattern } from "../routing/route-pattern.js";
4
+ import { makeThenableParams } from "../shims/thenable-params.js";
5
+ import { buildAppPageElements, createAppPageTreePath } from "./app-page-route-wiring.js";
6
+ import { resolveActiveParallelRouteHeadInputs, resolveAppPageHead } from "./app-page-head.js";
7
+ import { createElement } from "react";
8
+ //#region src/server/app-page-element-builder.ts
9
+ /**
10
+ * Build the App Router element tree for a matched route.
11
+ *
12
+ * This is the central element-construction path for the App Router RSC
13
+ * handler. It resolves page head metadata (including parallel route metadata),
14
+ * creates the page React element, and wires it into the nested layout +
15
+ * boundary tree via {@link buildAppPageElements}.
16
+ *
17
+ * The function is extracted from the generated RSC entry template so it can
18
+ * be unit-tested independently of the code-generation machinery.
19
+ *
20
+ * Next.js equivalent: the component tree construction in
21
+ * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-component-tree.tsx|create-component-tree.tsx}
22
+ * and the page head resolution in
23
+ * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-metadata.tsx|create-metadata.tsx}.
24
+ */
25
+ async function buildPageElements(options) {
26
+ const { route, params, routePath, pageRequest, globalErrorModule, rootNotFoundModule, rootForbiddenModule, rootUnauthorizedModule, metadataRoutes } = options;
27
+ const { opts, searchParams, isRscRequest, mountedSlotsHeader } = pageRequest;
28
+ const pageModule = route.page;
29
+ const PageComponent = pageModule?.default;
30
+ if (!!pageModule && !PageComponent) {
31
+ const interceptionContext = opts?.interceptionContext ?? null;
32
+ const noExportRouteId = createAppPayloadRouteId(routePath, interceptionContext);
33
+ let noExportRootLayout = null;
34
+ if (route.layouts?.length > 0) {
35
+ const treePosition = route.layoutTreePositions?.[0] ?? 0;
36
+ noExportRootLayout = createAppPageTreePath(route.routeSegments, treePosition);
37
+ }
38
+ return {
39
+ [APP_INTERCEPTION_CONTEXT_KEY]: interceptionContext,
40
+ __route: noExportRouteId,
41
+ __rootLayout: noExportRootLayout,
42
+ [noExportRouteId]: createElement("div", null, "Page has no default export")
43
+ };
44
+ }
45
+ const { hasSearchParams, metadata: resolvedMetadata, pageSearchParams, viewport: resolvedViewport } = await resolveAppPageHead({
46
+ layoutModules: route.layouts,
47
+ layoutTreePositions: route.layoutTreePositions,
48
+ metadataRoutes,
49
+ pageModule: route.page ?? null,
50
+ parallelRoutes: resolveActiveParallelRouteHeadInputs({
51
+ interceptLayouts: opts?.interceptLayouts ?? null,
52
+ interceptPage: opts?.interceptPage ?? null,
53
+ interceptParams: opts?.interceptParams ?? null,
54
+ interceptSlotKey: opts?.interceptSlotKey ?? null,
55
+ params,
56
+ routeSegments: route.routeSegments ?? [],
57
+ slots: route.slots ?? null
58
+ }),
59
+ params,
60
+ routePath: route.pattern,
61
+ routeSegments: route.routeSegments ?? null,
62
+ searchParams
63
+ });
64
+ const pageProps = { params: makeThenableParams(params) };
65
+ if (searchParams) {
66
+ pageProps.searchParams = makeThenableParams(pageSearchParams);
67
+ if (hasSearchParams) markDynamicUsage();
68
+ }
69
+ const mountedSlotIds = mountedSlotsHeader ? new Set(mountedSlotsHeader.split(" ")) : null;
70
+ const slotOverrides = buildSlotOverrides(route, params, routePath, opts);
71
+ return buildAppPageElements({
72
+ element: PageComponent ? createElement(PageComponent, pageProps) : null,
73
+ globalErrorModule: globalErrorModule ?? null,
74
+ isRscRequest,
75
+ mountedSlotIds,
76
+ makeThenableParams,
77
+ matchedParams: params,
78
+ resolvedMetadata,
79
+ resolvedViewport,
80
+ interceptionContext: opts?.interceptionContext ?? null,
81
+ routePath,
82
+ rootNotFoundModule: rootNotFoundModule ?? null,
83
+ rootForbiddenModule: rootForbiddenModule ?? null,
84
+ rootUnauthorizedModule: rootUnauthorizedModule ?? null,
85
+ route,
86
+ slotOverrides
87
+ });
88
+ }
89
+ /**
90
+ * Build the per-request `slotOverrides` map. Combines:
91
+ * - Interception overrides (existing behavior — swap in the intercepting page
92
+ * and its layouts when the request is intercepted into this slot).
93
+ * - Slot-specific param extraction for inherited slots whose URL pattern
94
+ * has different param names than the route's. The runtime matches the
95
+ * cleaned request path against `slot.slotPatternParts` to produce
96
+ * slot-scoped params, which `app-page-route-wiring` then hands to the
97
+ * slot page instead of the route's matched params.
98
+ *
99
+ * `routePath` is the already-normalized request pathname (basePath stripped,
100
+ * RSC suffix removed). Re-parsing `request.url` here would re-introduce the
101
+ * basePath and silently break the match for any app that configures one.
102
+ */
103
+ function buildSlotOverrides(route, routeParams, routePath, opts) {
104
+ const overrides = {};
105
+ if (opts && opts.interceptSlotKey && opts.interceptPage) overrides[opts.interceptSlotKey] = {
106
+ layoutModules: opts.interceptLayouts || null,
107
+ pageModule: opts.interceptPage,
108
+ params: opts.interceptParams || routeParams
109
+ };
110
+ const slots = route.slots;
111
+ if (slots) {
112
+ let urlParts = null;
113
+ const routeParamSet = collectParamNameSet(route.params);
114
+ for (const [slotKey, slot] of Object.entries(slots)) {
115
+ const patternParts = slot.slotPatternParts;
116
+ const paramNames = slot.slotParamNames;
117
+ if (!patternParts || patternParts.length === 0) continue;
118
+ if (paramNames && paramNames.every((name) => routeParamSet.has(name))) continue;
119
+ if (urlParts === null) urlParts = routePath.split("/").filter(Boolean);
120
+ const matched = matchRoutePattern(urlParts, patternParts);
121
+ if (!matched) continue;
122
+ const existing = overrides[slotKey];
123
+ overrides[slotKey] = existing ? {
124
+ ...existing,
125
+ params: matched
126
+ } : { params: matched };
127
+ }
128
+ }
129
+ return Object.keys(overrides).length > 0 ? overrides : null;
130
+ }
131
+ function collectParamNameSet(params) {
132
+ const set = /* @__PURE__ */ new Set();
133
+ if (params) for (const name of params) set.add(name);
134
+ return set;
135
+ }
136
+ //#endregion
137
+ export { buildPageElements };
138
+
139
+ //# sourceMappingURL=app-page-element-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-page-element-builder.js","names":[],"sources":["../../src/server/app-page-element-builder.ts"],"sourcesContent":["import { createElement } from \"react\";\nimport { markDynamicUsage } from \"vinext/shims/headers\";\nimport { makeThenableParams } from \"vinext/shims/thenable-params\";\nimport { resolveActiveParallelRouteHeadInputs, resolveAppPageHead } from \"./app-page-head.js\";\nimport {\n buildAppPageElements,\n createAppPageTreePath,\n type AppPageErrorModule,\n type AppPageModule,\n type AppPageRouteWiringRoute,\n type AppPageSlotOverride,\n} from \"./app-page-route-wiring.js\";\nimport {\n APP_INTERCEPTION_CONTEXT_KEY,\n createAppPayloadRouteId,\n type AppElements,\n} from \"./app-elements.js\";\nimport type { AppPageParams } from \"./app-page-boundary.js\";\nimport { matchRoutePattern } from \"../routing/route-pattern.js\";\nimport type { MetadataFileRoute } from \"./metadata-routes.js\";\n\nexport type { AppPageErrorModule, AppPageRouteWiringRoute } from \"./app-page-route-wiring.js\";\n\n/**\n * Route shape passed from the generated entry. Extends the wiring route with\n * the page module reference (used to extract the default export for the page\n * element) and the URL pattern (used as the route path in head resolution).\n */\nexport type AppPageBuildRoute<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = AppPageRouteWiringRoute<TModule, TErrorModule> & {\n page?: TModule | null;\n pattern: string;\n /** Param names captured by the route's URL pattern, in order. */\n params?: readonly string[] | null;\n};\n\nexport type AppPageInterceptOptions<TModule extends AppPageModule = AppPageModule> = {\n interceptionContext?: string | null;\n interceptLayouts?: readonly (TModule | null | undefined)[] | null;\n interceptPage?: TModule | null;\n interceptParams?: AppPageParams | null;\n interceptSlotKey?: string | null;\n};\n\nexport type AppPagePageRequest<TModule extends AppPageModule = AppPageModule> = {\n /** Interception context from current-route navigation (null for direct visits). */\n opts?: AppPageInterceptOptions<TModule> | null;\n /** URL search params from the incoming request (null when unavailable). */\n searchParams?: URLSearchParams | null;\n /** Whether the incoming request is an RSC (client-side navigation) request. */\n isRscRequest: boolean;\n /** The incoming HTTP request (available but unused by this module). */\n request: Request;\n /** Normalized x-vinext-mounted-slots header value. */\n mountedSlotsHeader: string | null;\n};\n\nexport type BuildPageElementsOptions<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n route: AppPageBuildRoute<TModule, TErrorModule>;\n params: AppPageParams;\n routePath: string;\n pageRequest: AppPagePageRequest<TModule>;\n /** Root-level global-error.tsx module. Present when the app defines this file. */\n globalErrorModule?: TErrorModule | null;\n /** Root-level not-found.tsx module. Present when the app defines this file. */\n rootNotFoundModule?: TModule | null;\n /** Root-level forbidden.tsx module. Present when the app defines this file. */\n rootForbiddenModule?: TModule | null;\n /** Root-level unauthorized.tsx module. Present when the app defines this file. */\n rootUnauthorizedModule?: TModule | null;\n /** File-based metadata routes (favicon, manifest, sitemap, etc.). */\n metadataRoutes: readonly MetadataFileRoute[];\n};\n\n/**\n * Build the App Router element tree for a matched route.\n *\n * This is the central element-construction path for the App Router RSC\n * handler. It resolves page head metadata (including parallel route metadata),\n * creates the page React element, and wires it into the nested layout +\n * boundary tree via {@link buildAppPageElements}.\n *\n * The function is extracted from the generated RSC entry template so it can\n * be unit-tested independently of the code-generation machinery.\n *\n * Next.js equivalent: the component tree construction in\n * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-component-tree.tsx|create-component-tree.tsx}\n * and the page head resolution in\n * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-metadata.tsx|create-metadata.tsx}.\n */\nexport async function buildPageElements<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n>(options: BuildPageElementsOptions<TModule, TErrorModule>): Promise<AppElements> {\n const {\n route,\n params,\n routePath,\n pageRequest,\n globalErrorModule,\n rootNotFoundModule,\n rootForbiddenModule,\n rootUnauthorizedModule,\n metadataRoutes,\n } = options;\n const { opts, searchParams, isRscRequest, mountedSlotsHeader } = pageRequest;\n\n const pageModule: AppPageModule | null | undefined = route.page;\n const PageComponent = pageModule?.default;\n const hasPageModule = !!pageModule;\n\n if (hasPageModule && !PageComponent) {\n const interceptionContext = opts?.interceptionContext ?? null;\n const noExportRouteId = createAppPayloadRouteId(routePath, interceptionContext);\n let noExportRootLayout: string | null = null;\n if (route.layouts?.length > 0) {\n const treePosition = route.layoutTreePositions?.[0] ?? 0;\n noExportRootLayout = createAppPageTreePath(route.routeSegments, treePosition);\n }\n return {\n [APP_INTERCEPTION_CONTEXT_KEY]: interceptionContext,\n __route: noExportRouteId,\n __rootLayout: noExportRootLayout,\n [noExportRouteId]: createElement(\"div\", null, \"Page has no default export\"),\n };\n }\n\n const {\n hasSearchParams,\n metadata: resolvedMetadata,\n pageSearchParams,\n viewport: resolvedViewport,\n } = await resolveAppPageHead({\n layoutModules: route.layouts,\n layoutTreePositions: route.layoutTreePositions,\n metadataRoutes,\n pageModule: route.page ?? null,\n parallelRoutes: resolveActiveParallelRouteHeadInputs({\n interceptLayouts: opts?.interceptLayouts ?? null,\n interceptPage: opts?.interceptPage ?? null,\n interceptParams: opts?.interceptParams ?? null,\n interceptSlotKey: opts?.interceptSlotKey ?? null,\n params,\n routeSegments: route.routeSegments ?? [],\n slots: route.slots ?? null,\n }),\n params,\n routePath: route.pattern,\n routeSegments: route.routeSegments ?? null,\n searchParams,\n });\n\n const pageProps: Record<string, unknown> = { params: makeThenableParams(params) };\n if (searchParams) {\n pageProps.searchParams = makeThenableParams(pageSearchParams);\n if (hasSearchParams) markDynamicUsage();\n }\n\n const mountedSlotIds = mountedSlotsHeader ? new Set(mountedSlotsHeader.split(\" \")) : null;\n\n const slotOverrides = buildSlotOverrides(route, params, routePath, opts);\n\n return buildAppPageElements({\n element: PageComponent ? createElement(PageComponent, pageProps) : null,\n globalErrorModule: globalErrorModule ?? null,\n isRscRequest,\n mountedSlotIds,\n makeThenableParams,\n matchedParams: params,\n resolvedMetadata,\n resolvedViewport,\n interceptionContext: opts?.interceptionContext ?? null,\n routePath,\n rootNotFoundModule: rootNotFoundModule ?? null,\n rootForbiddenModule: rootForbiddenModule ?? null,\n rootUnauthorizedModule: rootUnauthorizedModule ?? null,\n route,\n slotOverrides,\n });\n}\n\n/**\n * Build the per-request `slotOverrides` map. Combines:\n * - Interception overrides (existing behavior — swap in the intercepting page\n * and its layouts when the request is intercepted into this slot).\n * - Slot-specific param extraction for inherited slots whose URL pattern\n * has different param names than the route's. The runtime matches the\n * cleaned request path against `slot.slotPatternParts` to produce\n * slot-scoped params, which `app-page-route-wiring` then hands to the\n * slot page instead of the route's matched params.\n *\n * `routePath` is the already-normalized request pathname (basePath stripped,\n * RSC suffix removed). Re-parsing `request.url` here would re-introduce the\n * basePath and silently break the match for any app that configures one.\n */\nfunction buildSlotOverrides<TModule extends AppPageModule, TErrorModule extends AppPageErrorModule>(\n route: AppPageBuildRoute<TModule, TErrorModule>,\n routeParams: AppPageParams,\n routePath: string,\n opts?: AppPageInterceptOptions<TModule> | null,\n): Readonly<Record<string, AppPageSlotOverride<TModule>>> | null {\n const overrides: Record<string, AppPageSlotOverride<TModule>> = {};\n\n if (opts && opts.interceptSlotKey && opts.interceptPage) {\n overrides[opts.interceptSlotKey] = {\n layoutModules: opts.interceptLayouts || null,\n pageModule: opts.interceptPage,\n params: opts.interceptParams || routeParams,\n };\n }\n\n const slots = route.slots;\n if (slots) {\n let urlParts: string[] | null = null;\n const routeParamSet = collectParamNameSet(route.params);\n for (const [slotKey, slot] of Object.entries(slots)) {\n const patternParts = slot.slotPatternParts;\n const paramNames = slot.slotParamNames;\n if (!patternParts || patternParts.length === 0) continue;\n // Skip when every slot param is already a route param — the route's\n // matched params already carry the values the slot page expects.\n // Empty `paramNames` (slot pattern has no dynamic markers) also skips:\n // there's nothing to extract, so the route's matched params suffice.\n if (paramNames && paramNames.every((name) => routeParamSet.has(name))) continue;\n\n if (urlParts === null) {\n urlParts = routePath.split(\"/\").filter(Boolean);\n }\n const matched = matchRoutePattern(urlParts, patternParts);\n if (!matched) continue;\n\n const existing = overrides[slotKey];\n overrides[slotKey] = existing ? { ...existing, params: matched } : { params: matched };\n }\n }\n\n return Object.keys(overrides).length > 0 ? overrides : null;\n}\n\nfunction collectParamNameSet(params: readonly string[] | undefined | null): Set<string> {\n const set = new Set<string>();\n if (params) {\n for (const name of params) set.add(name);\n }\n return set;\n}\n"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  import { AppPageParams } from "./app-page-boundary.js";
2
2
 
3
3
  //#region src/server/app-page-params.d.ts
4
+ declare function getAppPageSegmentParamName(segment: string): string | null;
4
5
  declare function resolveAppPageSegmentParams(routeSegments: readonly string[] | null | undefined, treePosition: number, matchedParams: AppPageParams): AppPageParams;
5
6
  //#endregion
6
- export { resolveAppPageSegmentParams };
7
+ export { getAppPageSegmentParamName, resolveAppPageSegmentParams };
7
8
  //# sourceMappingURL=app-page-params.d.ts.map
@@ -1,5 +1,5 @@
1
1
  //#region src/server/app-page-params.ts
2
- function getSegmentParamName(segment) {
2
+ function getAppPageSegmentParamName(segment) {
3
3
  if (segment.startsWith("[[...") && segment.endsWith("]]") && segment.length > 7) return segment.slice(5, -2);
4
4
  if (segment.startsWith("[...") && segment.endsWith("]") && segment.length > 5) return segment.slice(4, -1);
5
5
  if (segment.startsWith("[") && segment.endsWith("]") && !segment.includes(".") && segment.length > 2) return segment.slice(1, -1);
@@ -14,7 +14,7 @@ function resolveAppPageSegmentParams(routeSegments, treePosition, matchedParams)
14
14
  const end = Math.min(Math.max(treePosition, 0), segments.length);
15
15
  for (let index = 0; index < end; index++) {
16
16
  const segment = segments[index];
17
- const paramName = getSegmentParamName(segment);
17
+ const paramName = getAppPageSegmentParamName(segment);
18
18
  if (!paramName) continue;
19
19
  const paramValue = matchedParams[paramName];
20
20
  if (paramValue === void 0 || isEmptyOptionalCatchAll(segment, paramValue)) continue;
@@ -23,6 +23,6 @@ function resolveAppPageSegmentParams(routeSegments, treePosition, matchedParams)
23
23
  return segmentParams;
24
24
  }
25
25
  //#endregion
26
- export { resolveAppPageSegmentParams };
26
+ export { getAppPageSegmentParamName, resolveAppPageSegmentParams };
27
27
 
28
28
  //# sourceMappingURL=app-page-params.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-page-params.js","names":[],"sources":["../../src/server/app-page-params.ts"],"sourcesContent":["import type { AppPageParams } from \"./app-page-boundary.js\";\n\nfunction getSegmentParamName(segment: string): string | null {\n if (segment.startsWith(\"[[...\") && segment.endsWith(\"]]\") && segment.length > 7) {\n return segment.slice(5, -2);\n }\n\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\") && segment.length > 5) {\n return segment.slice(4, -1);\n }\n\n if (\n segment.startsWith(\"[\") &&\n segment.endsWith(\"]\") &&\n !segment.includes(\".\") &&\n segment.length > 2\n ) {\n return segment.slice(1, -1);\n }\n\n return null;\n}\n\nfunction isEmptyOptionalCatchAll(segment: string, paramValue: string | string[]): boolean {\n return segment.startsWith(\"[[...\") && Array.isArray(paramValue) && paramValue.length === 0;\n}\n\nexport function resolveAppPageSegmentParams(\n routeSegments: readonly string[] | null | undefined,\n treePosition: number,\n matchedParams: AppPageParams,\n): AppPageParams {\n const segmentParams: AppPageParams = {};\n const segments = routeSegments ?? [];\n const end = Math.min(Math.max(treePosition, 0), segments.length);\n\n for (let index = 0; index < end; index++) {\n const segment = segments[index];\n const paramName = getSegmentParamName(segment);\n if (!paramName) {\n continue;\n }\n\n const paramValue = matchedParams[paramName];\n if (paramValue === undefined || isEmptyOptionalCatchAll(segment, paramValue)) {\n continue;\n }\n\n segmentParams[paramName] = paramValue;\n }\n\n return segmentParams;\n}\n"],"mappings":";AAEA,SAAS,oBAAoB,SAAgC;AAC3D,KAAI,QAAQ,WAAW,QAAQ,IAAI,QAAQ,SAAS,KAAK,IAAI,QAAQ,SAAS,EAC5E,QAAO,QAAQ,MAAM,GAAG,GAAG;AAG7B,KAAI,QAAQ,WAAW,OAAO,IAAI,QAAQ,SAAS,IAAI,IAAI,QAAQ,SAAS,EAC1E,QAAO,QAAQ,MAAM,GAAG,GAAG;AAG7B,KACE,QAAQ,WAAW,IAAI,IACvB,QAAQ,SAAS,IAAI,IACrB,CAAC,QAAQ,SAAS,IAAI,IACtB,QAAQ,SAAS,EAEjB,QAAO,QAAQ,MAAM,GAAG,GAAG;AAG7B,QAAO;;AAGT,SAAS,wBAAwB,SAAiB,YAAwC;AACxF,QAAO,QAAQ,WAAW,QAAQ,IAAI,MAAM,QAAQ,WAAW,IAAI,WAAW,WAAW;;AAG3F,SAAgB,4BACd,eACA,cACA,eACe;CACf,MAAM,gBAA+B,EAAE;CACvC,MAAM,WAAW,iBAAiB,EAAE;CACpC,MAAM,MAAM,KAAK,IAAI,KAAK,IAAI,cAAc,EAAE,EAAE,SAAS,OAAO;AAEhE,MAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,SAAS;EACxC,MAAM,UAAU,SAAS;EACzB,MAAM,YAAY,oBAAoB,QAAQ;AAC9C,MAAI,CAAC,UACH;EAGF,MAAM,aAAa,cAAc;AACjC,MAAI,eAAe,KAAA,KAAa,wBAAwB,SAAS,WAAW,CAC1E;AAGF,gBAAc,aAAa;;AAG7B,QAAO"}
1
+ {"version":3,"file":"app-page-params.js","names":[],"sources":["../../src/server/app-page-params.ts"],"sourcesContent":["import type { AppPageParams } from \"./app-page-boundary.js\";\n\nexport function getAppPageSegmentParamName(segment: string): string | null {\n if (segment.startsWith(\"[[...\") && segment.endsWith(\"]]\") && segment.length > 7) {\n return segment.slice(5, -2);\n }\n\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\") && segment.length > 5) {\n return segment.slice(4, -1);\n }\n\n if (\n segment.startsWith(\"[\") &&\n segment.endsWith(\"]\") &&\n !segment.includes(\".\") &&\n segment.length > 2\n ) {\n return segment.slice(1, -1);\n }\n\n return null;\n}\n\nfunction isEmptyOptionalCatchAll(segment: string, paramValue: string | string[]): boolean {\n return segment.startsWith(\"[[...\") && Array.isArray(paramValue) && paramValue.length === 0;\n}\n\nexport function resolveAppPageSegmentParams(\n routeSegments: readonly string[] | null | undefined,\n treePosition: number,\n matchedParams: AppPageParams,\n): AppPageParams {\n const segmentParams: AppPageParams = {};\n const segments = routeSegments ?? [];\n const end = Math.min(Math.max(treePosition, 0), segments.length);\n\n for (let index = 0; index < end; index++) {\n const segment = segments[index];\n const paramName = getAppPageSegmentParamName(segment);\n if (!paramName) {\n continue;\n }\n\n const paramValue = matchedParams[paramName];\n if (paramValue === undefined || isEmptyOptionalCatchAll(segment, paramValue)) {\n continue;\n }\n\n segmentParams[paramName] = paramValue;\n }\n\n return segmentParams;\n}\n"],"mappings":";AAEA,SAAgB,2BAA2B,SAAgC;AACzE,KAAI,QAAQ,WAAW,QAAQ,IAAI,QAAQ,SAAS,KAAK,IAAI,QAAQ,SAAS,EAC5E,QAAO,QAAQ,MAAM,GAAG,GAAG;AAG7B,KAAI,QAAQ,WAAW,OAAO,IAAI,QAAQ,SAAS,IAAI,IAAI,QAAQ,SAAS,EAC1E,QAAO,QAAQ,MAAM,GAAG,GAAG;AAG7B,KACE,QAAQ,WAAW,IAAI,IACvB,QAAQ,SAAS,IAAI,IACrB,CAAC,QAAQ,SAAS,IAAI,IACtB,QAAQ,SAAS,EAEjB,QAAO,QAAQ,MAAM,GAAG,GAAG;AAG7B,QAAO;;AAGT,SAAS,wBAAwB,SAAiB,YAAwC;AACxF,QAAO,QAAQ,WAAW,QAAQ,IAAI,MAAM,QAAQ,WAAW,IAAI,WAAW,WAAW;;AAG3F,SAAgB,4BACd,eACA,cACA,eACe;CACf,MAAM,gBAA+B,EAAE;CACvC,MAAM,WAAW,iBAAiB,EAAE;CACpC,MAAM,MAAM,KAAK,IAAI,KAAK,IAAI,cAAc,EAAE,EAAE,SAAS,OAAO;AAEhE,MAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,SAAS;EACxC,MAAM,UAAU,SAAS;EACzB,MAAM,YAAY,2BAA2B,QAAQ;AACrD,MAAI,CAAC,UACH;EAGF,MAAM,aAAa,cAAc;AACjC,MAAI,eAAe,KAAA,KAAa,wBAAwB,SAAS,WAAW,CAC1E;AAGF,gBAAc,aAAa;;AAG7B,QAAO"}
@@ -8,9 +8,10 @@ import { ReactNode } from "react";
8
8
  //#region src/server/app-page-render.d.ts
9
9
  type AppPageBoundaryOnError = (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;
10
10
  type AppPageDebugLogger = (event: string, detail: string) => void;
11
- type AppPageCacheSetter = (key: string, data: CachedAppPageValue, revalidateSeconds: number, tags: string[]) => Promise<void>;
11
+ type AppPageCacheSetter = (key: string, data: CachedAppPageValue, revalidateSeconds: number, tags: string[], expireSeconds?: number) => Promise<void>;
12
12
  type AppPageRequestCacheLife = {
13
13
  revalidate?: number;
14
+ expire?: number;
14
15
  };
15
16
  type RenderAppPageLifecycleOptions = {
16
17
  cleanPathname: string;
@@ -24,12 +25,14 @@ type RenderAppPageLifecycleOptions = {
24
25
  getNavigationContext: () => unknown;
25
26
  getPageTags: () => string[];
26
27
  getRequestCacheLife: () => AppPageRequestCacheLife | null;
28
+ peekRequestCacheLife?: () => AppPageRequestCacheLife | null;
27
29
  getDraftModeCookieHeader: () => string | null | undefined;
28
30
  handlerStart: number;
29
31
  hasLoadingBoundary: boolean;
30
32
  isDynamicError: boolean;
31
33
  isForceDynamic: boolean;
32
34
  isForceStatic: boolean;
35
+ isPrerender?: boolean;
33
36
  isProduction: boolean;
34
37
  isRscRequest: boolean;
35
38
  isrDebug?: AppPageDebugLogger;
@@ -42,6 +45,7 @@ type RenderAppPageLifecycleOptions = {
42
45
  params: Record<string, unknown>;
43
46
  probeLayoutAt: (layoutIndex: number) => unknown;
44
47
  probePage: () => unknown;
48
+ expireSeconds?: number;
45
49
  revalidateSeconds: number | null;
46
50
  renderErrorBoundaryResponse: (error: unknown) => Promise<Response | null>;
47
51
  renderLayoutSpecialError: (specialError: AppPageSpecialError, layoutIndex: number) => Promise<Response>;
@@ -14,6 +14,20 @@ function buildResponseTiming(options) {
14
14
  responseKind: options.responseKind
15
15
  };
16
16
  }
17
+ function readRequestCacheLifeForPrerender(options) {
18
+ return options.peekRequestCacheLife?.() ?? options.getRequestCacheLife();
19
+ }
20
+ function applyRequestCacheLife(options) {
21
+ let revalidateSeconds = options.revalidateSeconds;
22
+ let expireSeconds = options.expireSeconds;
23
+ const requestCacheLife = options.requestCacheLife;
24
+ if (requestCacheLife?.revalidate !== void 0) revalidateSeconds = revalidateSeconds === null ? requestCacheLife.revalidate : Math.min(revalidateSeconds, requestCacheLife.revalidate);
25
+ if (requestCacheLife?.expire !== void 0) expireSeconds = requestCacheLife.expire;
26
+ return {
27
+ expireSeconds,
28
+ revalidateSeconds
29
+ };
30
+ }
17
31
  /**
18
32
  * Wraps an RSC response body to report invalid dynamic usage errors after the
19
33
  * stream is fully consumed. In dev mode, errors from cookies()/headers() inside
@@ -89,11 +103,21 @@ async function renderAppPageLifecycle(options) {
89
103
  const rscErrorTracker = createAppPageRscErrorTracker(options.createRscOnErrorHandler(options.cleanPathname, options.routePattern));
90
104
  const rscStream = options.renderToReadableStream(outgoingElement, { onError: rscErrorTracker.onRenderError });
91
105
  let revalidateSeconds = options.revalidateSeconds;
92
- const rscCapture = teeAppPageRscStreamForCapture(rscStream, options.isProduction && revalidateSeconds !== null && revalidateSeconds > 0 && revalidateSeconds !== Infinity && !options.isForceDynamic);
106
+ let expireSeconds = options.expireSeconds;
107
+ const shouldCaptureRscForCacheMetadata = (options.isProduction || options.isPrerender === true) && (revalidateSeconds === null || revalidateSeconds > 0 && revalidateSeconds !== Infinity) && !options.isForceDynamic;
108
+ const rscCapture = teeAppPageRscStreamForCapture(rscStream, shouldCaptureRscForCacheMetadata);
93
109
  const rscForResponse = rscCapture.ssrStream;
94
110
  const capturedRscDataRef = { value: null };
95
111
  if (rscCapture.sideStream && options.isRscRequest) capturedRscDataRef.value = readAppPageBinaryStream(rscCapture.sideStream);
96
112
  if (options.isRscRequest) {
113
+ if (options.isPrerender === true) {
114
+ await settleCapturedRscRenderForCacheMetadata(capturedRscDataRef.value);
115
+ ({expireSeconds, revalidateSeconds} = applyRequestCacheLife({
116
+ expireSeconds,
117
+ requestCacheLife: readRequestCacheLifeForPrerender(options),
118
+ revalidateSeconds
119
+ }));
120
+ }
97
121
  const dynamicUsedDuringBuild = options.consumeDynamicUsage();
98
122
  const rscResponsePolicy = resolveAppPageRscResponsePolicy({
99
123
  dynamicUsedDuringBuild,
@@ -101,6 +125,7 @@ async function renderAppPageLifecycle(options) {
101
125
  isForceDynamic: options.isForceDynamic,
102
126
  isForceStatic: options.isForceStatic,
103
127
  isProduction: options.isProduction,
128
+ expireSeconds,
104
129
  revalidateSeconds
105
130
  });
106
131
  const rscResponse = buildAppPageRscResponse(rscForResponse, {
@@ -116,18 +141,23 @@ async function renderAppPageLifecycle(options) {
116
141
  })
117
142
  });
118
143
  return finalizeAppPageRscCacheResponse(!options.isProduction && rscResponse.body && options.consumeInvalidDynamicUsageError ? wrapRscResponseForDevErrorReporting(rscResponse, options.consumeInvalidDynamicUsageError) : rscResponse, {
119
- capturedRscDataPromise: options.isProduction ? capturedRscDataRef.value : null,
144
+ capturedRscDataPromise: options.isProduction && shouldCaptureRscForCacheMetadata ? capturedRscDataRef.value : null,
120
145
  cleanPathname: options.cleanPathname,
121
146
  consumeDynamicUsage: options.consumeDynamicUsage,
122
147
  dynamicUsedDuringBuild,
123
148
  getPageTags() {
124
149
  return options.getPageTags();
125
150
  },
151
+ getRequestCacheLife() {
152
+ return options.getRequestCacheLife();
153
+ },
126
154
  isrDebug: options.isrDebug,
127
155
  isrRscKey: options.isrRscKey,
128
156
  isrSet: options.isrSet,
129
157
  mountedSlotsHeader: options.mountedSlotsHeader,
130
- revalidateSeconds: revalidateSeconds ?? 0,
158
+ preserveClientResponseHeaders: rscResponsePolicy.cacheState !== "MISS",
159
+ expireSeconds,
160
+ revalidateSeconds,
131
161
  waitUntil(promise) {
132
162
  options.waitUntil?.(promise);
133
163
  }
@@ -174,10 +204,16 @@ async function renderAppPageLifecycle(options) {
174
204
  const cleanResponse = await options.renderErrorBoundaryResponse(rscErrorTracker.getCapturedError());
175
205
  if (cleanResponse) return cleanResponse;
176
206
  }
207
+ if (options.isPrerender === true) {
208
+ await settleCapturedRscRenderForCacheMetadata(capturedRscDataRef.value);
209
+ ({expireSeconds, revalidateSeconds} = applyRequestCacheLife({
210
+ expireSeconds,
211
+ requestCacheLife: readRequestCacheLifeForPrerender(options),
212
+ revalidateSeconds
213
+ }));
214
+ }
177
215
  const draftCookie = options.getDraftModeCookieHeader();
178
216
  const dynamicUsedDuringRender = options.consumeDynamicUsage();
179
- const requestCacheLife = options.getRequestCacheLife();
180
- if (requestCacheLife?.revalidate !== void 0 && revalidateSeconds === null) revalidateSeconds = requestCacheLife.revalidate;
181
217
  const safeHtmlStream = deferUntilStreamConsumed(htmlStream, () => {
182
218
  options.clearRequestContext();
183
219
  });
@@ -188,6 +224,7 @@ async function renderAppPageLifecycle(options) {
188
224
  isForceDynamic: options.isForceDynamic,
189
225
  isForceStatic: options.isForceStatic,
190
226
  isProduction: options.isProduction,
227
+ expireSeconds,
191
228
  revalidateSeconds
192
229
  });
193
230
  const htmlResponseTiming = buildResponseTiming({
@@ -197,28 +234,38 @@ async function renderAppPageLifecycle(options) {
197
234
  renderEnd,
198
235
  responseKind: "html"
199
236
  });
200
- if (htmlResponsePolicy.shouldWriteToCache) return finalizeAppPageHtmlCacheResponse(buildAppPageHtmlResponse(safeHtmlStream, {
201
- draftCookie,
202
- fontLinkHeader,
203
- middlewareContext: options.middlewareContext,
204
- policy: htmlResponsePolicy,
205
- timing: htmlResponseTiming
206
- }), {
207
- capturedRscDataPromise: capturedRscDataRef.value,
208
- cleanPathname: options.cleanPathname,
209
- consumeDynamicUsage: options.consumeDynamicUsage,
210
- getPageTags() {
211
- return options.getPageTags();
212
- },
213
- isrDebug: options.isrDebug,
214
- isrHtmlKey: options.isrHtmlKey,
215
- isrRscKey: options.isrRscKey,
216
- isrSet: options.isrSet,
217
- revalidateSeconds: revalidateSeconds ?? 0,
218
- waitUntil(cachePromise) {
219
- options.waitUntil?.(cachePromise);
220
- }
221
- });
237
+ const shouldSpeculativelyWriteCache = options.isProduction && shouldCaptureRscForCacheMetadata && revalidateSeconds === null && !options.isDynamicError && !options.isForceStatic && !options.scriptNonce && !dynamicUsedDuringRender;
238
+ if (htmlResponsePolicy.shouldWriteToCache || shouldSpeculativelyWriteCache) {
239
+ const isrResponse = buildAppPageHtmlResponse(safeHtmlStream, {
240
+ draftCookie,
241
+ fontLinkHeader,
242
+ middlewareContext: options.middlewareContext,
243
+ policy: htmlResponsePolicy,
244
+ timing: htmlResponseTiming
245
+ });
246
+ if (options.isPrerender === true) return isrResponse;
247
+ return finalizeAppPageHtmlCacheResponse(isrResponse, {
248
+ capturedRscDataPromise: capturedRscDataRef.value,
249
+ cleanPathname: options.cleanPathname,
250
+ consumeDynamicUsage: options.consumeDynamicUsage,
251
+ getPageTags() {
252
+ return options.getPageTags();
253
+ },
254
+ getRequestCacheLife() {
255
+ return options.getRequestCacheLife();
256
+ },
257
+ isrDebug: options.isrDebug,
258
+ isrHtmlKey: options.isrHtmlKey,
259
+ isrRscKey: options.isrRscKey,
260
+ isrSet: options.isrSet,
261
+ preserveClientResponseHeaders: !htmlResponsePolicy.shouldWriteToCache,
262
+ expireSeconds,
263
+ revalidateSeconds,
264
+ waitUntil(cachePromise) {
265
+ options.waitUntil?.(cachePromise);
266
+ }
267
+ });
268
+ }
222
269
  return buildAppPageHtmlResponse(safeHtmlStream, {
223
270
  draftCookie,
224
271
  fontLinkHeader,
@@ -227,6 +274,12 @@ async function renderAppPageLifecycle(options) {
227
274
  timing: htmlResponseTiming
228
275
  });
229
276
  }
277
+ async function settleCapturedRscRenderForCacheMetadata(capturedRscDataPromise) {
278
+ if (!capturedRscDataPromise) return;
279
+ try {
280
+ await capturedRscDataPromise;
281
+ } catch {}
282
+ }
230
283
  //#endregion
231
284
  export { renderAppPageLifecycle };
232
285