vinext 0.0.53 → 0.0.54

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 (188) hide show
  1. package/dist/build/inline-css.d.ts +7 -0
  2. package/dist/build/inline-css.js +50 -0
  3. package/dist/build/inline-css.js.map +1 -0
  4. package/dist/build/prerender.js +2 -1
  5. package/dist/build/prerender.js.map +1 -1
  6. package/dist/check.js +4 -0
  7. package/dist/check.js.map +1 -1
  8. package/dist/client/navigation-runtime.d.ts +2 -1
  9. package/dist/client/navigation-runtime.js.map +1 -1
  10. package/dist/client/window-next.d.ts +7 -0
  11. package/dist/client/window-next.js.map +1 -1
  12. package/dist/config/next-config.d.ts +83 -1
  13. package/dist/config/next-config.js +131 -2
  14. package/dist/config/next-config.js.map +1 -1
  15. package/dist/deploy.js +13 -0
  16. package/dist/deploy.js.map +1 -1
  17. package/dist/entries/app-browser-entry.d.ts +11 -1
  18. package/dist/entries/app-browser-entry.js +16 -6
  19. package/dist/entries/app-browser-entry.js.map +1 -1
  20. package/dist/entries/app-rsc-entry.d.ts +8 -1
  21. package/dist/entries/app-rsc-entry.js +18 -5
  22. package/dist/entries/app-rsc-entry.js.map +1 -1
  23. package/dist/entries/app-rsc-manifest.d.ts +21 -1
  24. package/dist/entries/app-rsc-manifest.js +6 -4
  25. package/dist/entries/app-rsc-manifest.js.map +1 -1
  26. package/dist/entries/pages-client-entry.d.ts +4 -1
  27. package/dist/entries/pages-client-entry.js +18 -2
  28. package/dist/entries/pages-client-entry.js.map +1 -1
  29. package/dist/entries/pages-server-entry.js +82 -4
  30. package/dist/entries/pages-server-entry.js.map +1 -1
  31. package/dist/entries/runtime-entry-module.d.ts +1 -10
  32. package/dist/entries/runtime-entry-module.js +2 -12
  33. package/dist/entries/runtime-entry-module.js.map +1 -1
  34. package/dist/index.js +63 -5
  35. package/dist/index.js.map +1 -1
  36. package/dist/plugins/remove-console.d.ts +16 -0
  37. package/dist/plugins/remove-console.js +176 -0
  38. package/dist/plugins/remove-console.js.map +1 -0
  39. package/dist/routing/app-route-graph.d.ts +24 -1
  40. package/dist/routing/app-route-graph.js +52 -4
  41. package/dist/routing/app-route-graph.js.map +1 -1
  42. package/dist/routing/app-router.d.ts +2 -2
  43. package/dist/routing/app-router.js +2 -2
  44. package/dist/routing/app-router.js.map +1 -1
  45. package/dist/routing/file-matcher.d.ts +21 -1
  46. package/dist/routing/file-matcher.js +39 -1
  47. package/dist/routing/file-matcher.js.map +1 -1
  48. package/dist/routing/pages-router.d.ts +1 -1
  49. package/dist/routing/pages-router.js +10 -3
  50. package/dist/routing/pages-router.js.map +1 -1
  51. package/dist/server/api-handler.js +1 -1
  52. package/dist/server/app-browser-entry.js +25 -16
  53. package/dist/server/app-browser-entry.js.map +1 -1
  54. package/dist/server/app-browser-navigation-controller.d.ts +2 -0
  55. package/dist/server/app-browser-navigation-controller.js +4 -0
  56. package/dist/server/app-browser-navigation-controller.js.map +1 -1
  57. package/dist/server/app-elements-wire.d.ts +13 -4
  58. package/dist/server/app-elements-wire.js +10 -1
  59. package/dist/server/app-elements-wire.js.map +1 -1
  60. package/dist/server/app-elements.d.ts +2 -2
  61. package/dist/server/app-elements.js +2 -2
  62. package/dist/server/app-elements.js.map +1 -1
  63. package/dist/server/app-fallback-renderer.d.ts +15 -5
  64. package/dist/server/app-fallback-renderer.js +10 -4
  65. package/dist/server/app-fallback-renderer.js.map +1 -1
  66. package/dist/server/app-inline-css-client.d.ts +7 -0
  67. package/dist/server/app-inline-css-client.js +37 -0
  68. package/dist/server/app-inline-css-client.js.map +1 -0
  69. package/dist/server/app-page-boundary.d.ts +21 -1
  70. package/dist/server/app-page-boundary.js +28 -3
  71. package/dist/server/app-page-boundary.js.map +1 -1
  72. package/dist/server/app-page-cache.d.ts +7 -3
  73. package/dist/server/app-page-cache.js +7 -7
  74. package/dist/server/app-page-cache.js.map +1 -1
  75. package/dist/server/app-page-dispatch.d.ts +10 -1
  76. package/dist/server/app-page-dispatch.js +126 -79
  77. package/dist/server/app-page-dispatch.js.map +1 -1
  78. package/dist/server/app-page-element-builder.js +12 -28
  79. package/dist/server/app-page-element-builder.js.map +1 -1
  80. package/dist/server/app-page-render-identity.d.ts +22 -0
  81. package/dist/server/app-page-render-identity.js +42 -0
  82. package/dist/server/app-page-render-identity.js.map +1 -0
  83. package/dist/server/app-page-render.d.ts +8 -1
  84. package/dist/server/app-page-render.js +4 -1
  85. package/dist/server/app-page-render.js.map +1 -1
  86. package/dist/server/app-page-request.d.ts +6 -3
  87. package/dist/server/app-page-request.js +5 -2
  88. package/dist/server/app-page-request.js.map +1 -1
  89. package/dist/server/app-page-response.js +2 -2
  90. package/dist/server/app-page-response.js.map +1 -1
  91. package/dist/server/app-page-route-wiring.d.ts +15 -0
  92. package/dist/server/app-page-route-wiring.js +7 -5
  93. package/dist/server/app-page-route-wiring.js.map +1 -1
  94. package/dist/server/app-page-stream.d.ts +11 -0
  95. package/dist/server/app-page-stream.js +1 -0
  96. package/dist/server/app-page-stream.js.map +1 -1
  97. package/dist/server/app-route-handler-response.js +37 -5
  98. package/dist/server/app-route-handler-response.js.map +1 -1
  99. package/dist/server/app-rsc-handler.d.ts +14 -3
  100. package/dist/server/app-rsc-handler.js +45 -5
  101. package/dist/server/app-rsc-handler.js.map +1 -1
  102. package/dist/server/app-rsc-request-normalization.d.ts +2 -1
  103. package/dist/server/app-rsc-request-normalization.js +3 -2
  104. package/dist/server/app-rsc-request-normalization.js.map +1 -1
  105. package/dist/server/app-server-action-execution.d.ts +21 -3
  106. package/dist/server/app-server-action-execution.js +42 -7
  107. package/dist/server/app-server-action-execution.js.map +1 -1
  108. package/dist/server/app-ssr-entry.d.ts +6 -0
  109. package/dist/server/app-ssr-entry.js +22 -7
  110. package/dist/server/app-ssr-entry.js.map +1 -1
  111. package/dist/server/app-ssr-error-meta.js +3 -3
  112. package/dist/server/app-ssr-error-meta.js.map +1 -1
  113. package/dist/server/app-ssr-stream.d.ts +2 -1
  114. package/dist/server/app-ssr-stream.js +176 -31
  115. package/dist/server/app-ssr-stream.js.map +1 -1
  116. package/dist/server/client-trace-metadata.d.ts +31 -0
  117. package/dist/server/client-trace-metadata.js +83 -0
  118. package/dist/server/client-trace-metadata.js.map +1 -0
  119. package/dist/server/cookie-utils.d.ts +13 -0
  120. package/dist/server/cookie-utils.js +20 -0
  121. package/dist/server/cookie-utils.js.map +1 -0
  122. package/dist/server/dev-server.d.ts +8 -1
  123. package/dist/server/dev-server.js +34 -5
  124. package/dist/server/dev-server.js.map +1 -1
  125. package/dist/server/html.d.ts +2 -1
  126. package/dist/server/html.js +6 -1
  127. package/dist/server/html.js.map +1 -1
  128. package/dist/server/isr-cache.d.ts +7 -5
  129. package/dist/server/isr-cache.js +17 -6
  130. package/dist/server/isr-cache.js.map +1 -1
  131. package/dist/server/middleware-runtime.js +1 -2
  132. package/dist/server/middleware-runtime.js.map +1 -1
  133. package/dist/server/pages-document-initial-props.d.ts +7 -0
  134. package/dist/server/pages-document-initial-props.js +14 -0
  135. package/dist/server/pages-document-initial-props.js.map +1 -0
  136. package/dist/server/pages-page-data.js +3 -0
  137. package/dist/server/pages-page-data.js.map +1 -1
  138. package/dist/server/pages-page-method.d.ts +48 -0
  139. package/dist/server/pages-page-method.js +19 -0
  140. package/dist/server/pages-page-method.js.map +1 -0
  141. package/dist/server/pages-page-response.d.ts +6 -0
  142. package/dist/server/pages-page-response.js +10 -3
  143. package/dist/server/pages-page-response.js.map +1 -1
  144. package/dist/server/pages-serializable-props.d.ts +25 -0
  145. package/dist/server/pages-serializable-props.js +69 -0
  146. package/dist/server/pages-serializable-props.js.map +1 -0
  147. package/dist/server/prod-server.js +3 -0
  148. package/dist/server/prod-server.js.map +1 -1
  149. package/dist/server/server-action-not-found.js +3 -2
  150. package/dist/server/server-action-not-found.js.map +1 -1
  151. package/dist/server/static-file-cache.js +2 -1
  152. package/dist/server/static-file-cache.js.map +1 -1
  153. package/dist/shims/app-router-scroll-state.d.ts +4 -2
  154. package/dist/shims/app-router-scroll-state.js +16 -3
  155. package/dist/shims/app-router-scroll-state.js.map +1 -1
  156. package/dist/shims/app-router-scroll.d.ts +16 -2
  157. package/dist/shims/app-router-scroll.js +18 -3
  158. package/dist/shims/app-router-scroll.js.map +1 -1
  159. package/dist/shims/cache.d.ts +6 -0
  160. package/dist/shims/cache.js +7 -0
  161. package/dist/shims/cache.js.map +1 -1
  162. package/dist/shims/error.js +3 -0
  163. package/dist/shims/error.js.map +1 -1
  164. package/dist/shims/headers.d.ts +7 -0
  165. package/dist/shims/headers.js +9 -1
  166. package/dist/shims/headers.js.map +1 -1
  167. package/dist/shims/internal/app-route-detection.d.ts +37 -0
  168. package/dist/shims/internal/app-route-detection.js +69 -0
  169. package/dist/shims/internal/app-route-detection.js.map +1 -0
  170. package/dist/shims/link.d.ts +18 -2
  171. package/dist/shims/link.js +70 -6
  172. package/dist/shims/link.js.map +1 -1
  173. package/dist/shims/metadata.d.ts +7 -6
  174. package/dist/shims/metadata.js +9 -5
  175. package/dist/shims/metadata.js.map +1 -1
  176. package/dist/shims/navigation.d.ts +1 -2
  177. package/dist/shims/navigation.js +63 -12
  178. package/dist/shims/navigation.js.map +1 -1
  179. package/dist/shims/router.d.ts +5 -0
  180. package/dist/shims/router.js +14 -4
  181. package/dist/shims/router.js.map +1 -1
  182. package/dist/shims/script.d.ts +11 -1
  183. package/dist/shims/script.js +75 -6
  184. package/dist/shims/script.js.map +1 -1
  185. package/dist/utils/path.d.ts +13 -0
  186. package/dist/utils/path.js +16 -0
  187. package/dist/utils/path.js.map +1 -0
  188. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"app-fallback-renderer.js","names":[],"sources":["../../src/server/app-fallback-renderer.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { AppPageParams } from \"./app-page-boundary.js\";\nimport {\n renderAppPageErrorBoundary,\n renderAppPageHttpAccessFallback,\n type AppPageBoundaryRoute,\n} from \"./app-page-boundary-render.js\";\nimport { DEFAULT_GLOBAL_ERROR_MODULE } from \"./default-global-error-module.js\";\nimport { DEFAULT_NOT_FOUND_MODULE } from \"./default-not-found-module.js\";\nimport type { AppPageFontPreload } from \"./app-page-execution.js\";\nimport type { AppPageMiddlewareContext } from \"./app-page-response.js\";\nimport type { AppPageSsrHandler } from \"./app-page-stream.js\";\nimport type { MetadataFileRoute } from \"./metadata-routes.js\";\nimport type { AppElements } from \"./app-elements.js\";\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\ntype AppPageComponent = import(\"react\").ComponentType<any>;\ntype AppPageModule = Record<string, unknown> & {\n default?: AppPageComponent | null | undefined;\n};\ntype AppPageBoundaryOnError = (\n error: unknown,\n requestInfo: unknown,\n errorContext: unknown,\n) => unknown;\n\ntype AppFallbackRendererRootBoundaries<TModule extends AppPageModule = AppPageModule> = {\n rootForbiddenModule?: TModule | null;\n rootLayouts: readonly (TModule | null | undefined)[];\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n};\n\ntype AppFallbackRendererFontProviders = {\n buildFontLinkHeader: (preloads: readonly AppPageFontPreload[] | null | undefined) => string;\n getFontLinks: () => string[];\n getFontPreloads: () => AppPageFontPreload[];\n getFontStyles: () => string[];\n};\n\ntype AppFallbackRendererOptions<TModule extends AppPageModule = AppPageModule> = {\n clearRequestContext: () => void;\n createRscOnErrorHandler: (\n request: Request,\n pathname: string,\n routePath: string,\n ) => AppPageBoundaryOnError;\n fontProviders: AppFallbackRendererFontProviders;\n getNavigationContext: () => unknown;\n globalErrorModule?: TModule | null;\n /**\n * Optional `app/global-not-found.tsx` module. When provided, route-miss 404s\n * render this module as a standalone document (skipping the root layout)\n * because it ships its own `<html>` and `<body>`. Page-triggered `notFound()`\n * calls continue to use the regular `not-found.tsx` boundary inside layouts.\n * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/app-render.tsx\n */\n globalNotFoundModule?: TModule | null;\n makeThenableParams: (params: AppPageParams) => unknown;\n metadataRoutes: MetadataFileRoute[];\n /** Configured next.config `basePath`, threaded into file-based metadata href emission. */\n basePath?: string;\n resolveChildSegments: (\n routeSegments: readonly string[],\n treePosition: number,\n params: AppPageParams,\n ) => string[];\n rootBoundaries: AppFallbackRendererRootBoundaries<TModule>;\n rscRenderer: (\n element: ReactNode | AppElements,\n options: { onError: AppPageBoundaryOnError },\n ) => ReadableStream<Uint8Array>;\n sanitizer: (error: Error) => Error;\n ssrLoader: () => Promise<AppPageSsrHandler>;\n};\n\ntype AppFallbackRendererCallContext = {\n /**\n * Whether the matched (or invoking) route opts into Next.js' edge runtime via\n * `export const runtime = \"edge\"`. Propagated so boundary/error/not-found\n * responses carry `x-edge-runtime: 1` for edge routes, matching the page\n * render path. Defaults to `false` when no route is matched.\n */\n isEdgeRuntime?: boolean;\n};\n\ntype AppFallbackRenderer<TModule extends AppPageModule = AppPageModule> = {\n renderErrorBoundary: (\n route: AppPageBoundaryRoute<TModule> | null,\n error: unknown,\n isRscRequest: boolean,\n request: Request,\n matchedParams: AppPageParams | undefined,\n scriptNonce: string | undefined,\n middlewareContext: AppPageMiddlewareContext,\n callContext?: AppFallbackRendererCallContext,\n ) => Promise<Response | null>;\n renderHttpAccessFallback: (\n route: AppPageBoundaryRoute<TModule> | null,\n statusCode: number,\n isRscRequest: boolean,\n request: Request,\n opts: {\n boundaryComponent?: AppPageComponent | null;\n layouts?: readonly (TModule | null | undefined)[] | null;\n matchedParams?: AppPageParams;\n },\n scriptNonce: string | undefined,\n middlewareContext: AppPageMiddlewareContext,\n callContext?: AppFallbackRendererCallContext,\n ) => Promise<Response | null>;\n renderNotFound: (\n route: AppPageBoundaryRoute<TModule> | null,\n isRscRequest: boolean,\n request: Request,\n matchedParams: AppPageParams | undefined,\n scriptNonce: string | undefined,\n middlewareContext: AppPageMiddlewareContext,\n callContext?: AppFallbackRendererCallContext,\n ) => Promise<Response | null>;\n};\n\nconst EMPTY_MW_CTX: AppPageMiddlewareContext = { headers: null, status: null };\n\nexport function createAppFallbackRenderer<TModule extends AppPageModule>(\n options: AppFallbackRendererOptions<TModule>,\n): AppFallbackRenderer<TModule> {\n const {\n basePath = \"\",\n clearRequestContext,\n createRscOnErrorHandler: buildRscOnErrorHandler,\n fontProviders,\n getNavigationContext,\n globalErrorModule,\n globalNotFoundModule,\n makeThenableParams,\n metadataRoutes,\n resolveChildSegments,\n rootBoundaries,\n rscRenderer,\n sanitizer,\n ssrLoader,\n } = options;\n\n const { rootForbiddenModule, rootLayouts, rootNotFoundModule, rootUnauthorizedModule } =\n rootBoundaries;\n\n // When the app does not define `app/global-error.tsx`, fall back to vinext's\n // built-in default global error component so that uncaught render errors\n // produce the same UI Next.js ships out of the box (matching markup, inline\n // styles, theme CSS, and the \"ERROR <digest>\" footer for server errors).\n // See packages/vinext/src/shims/default-global-error.tsx and\n // packages/vinext/src/server/default-global-error-module.ts.\n const effectiveGlobalErrorModule: TModule | null =\n globalErrorModule ?? (DEFAULT_GLOBAL_ERROR_MODULE as unknown as TModule);\n\n // When the app does not define `app/not-found.tsx` (and has not opted into\n // `app/global-not-found.tsx`), fall back to vinext's built-in default\n // not-found component so route-miss 404s render the canonical Next.js\n // markup (status + \"This page could not be found.\" message). Matches the\n // default not-found UI shipped with Next.js's app loader.\n // See packages/vinext/src/shims/default-not-found.tsx and\n // packages/vinext/src/server/default-not-found-module.ts.\n const effectiveRootNotFoundModule: TModule | null =\n rootNotFoundModule ?? (DEFAULT_NOT_FOUND_MODULE as unknown as TModule);\n\n return {\n renderHttpAccessFallback(\n route,\n statusCode,\n isRscRequest,\n request,\n opts,\n scriptNonce,\n middlewareContext,\n callContext,\n ) {\n // global-not-found.tsx replaces the root layout for route-miss 404s.\n // Only applies when:\n // - The user defined app/global-not-found.tsx\n // - The 404 originates from a route miss (no matched route)\n // - The caller did not already pick a specific boundary component\n // Page-triggered notFound() calls (route is non-null) keep using the\n // regular not-found.tsx boundary inside the route's layouts.\n // See https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/app-render.tsx#L495-L520\n const useGlobalNotFound =\n statusCode === 404 && !!globalNotFoundModule && !route && !opts?.boundaryComponent;\n\n if (useGlobalNotFound) {\n const globalNotFoundComponent = globalNotFoundModule?.default ?? null;\n if (globalNotFoundComponent) {\n return renderAppPageHttpAccessFallback({\n boundaryComponent: globalNotFoundComponent,\n buildFontLinkHeader: fontProviders.buildFontLinkHeader,\n clearRequestContext,\n createRscOnErrorHandler(pathname, routePath) {\n return buildRscOnErrorHandler(request, pathname, routePath);\n },\n getFontLinks: fontProviders.getFontLinks,\n getFontPreloads: fontProviders.getFontPreloads,\n getFontStyles: fontProviders.getFontStyles,\n getNavigationContext,\n globalErrorModule: effectiveGlobalErrorModule,\n isEdgeRuntime: callContext?.isEdgeRuntime,\n isRscRequest,\n layoutModules: [],\n loadSsrHandler: ssrLoader,\n makeThenableParams,\n matchedParams: opts?.matchedParams ?? {},\n middlewareContext: middlewareContext ?? EMPTY_MW_CTX,\n metadataRoutes,\n requestUrl: request.url,\n resolveChildSegments,\n rootForbiddenModule: null,\n rootLayouts: [],\n rootNotFoundModule: null,\n rootUnauthorizedModule: null,\n route: null,\n renderToReadableStream: rscRenderer,\n scriptNonce,\n skipLayoutWrapping: true,\n statusCode,\n });\n }\n }\n\n return renderAppPageHttpAccessFallback({\n basePath,\n boundaryComponent: opts?.boundaryComponent ?? null,\n buildFontLinkHeader: fontProviders.buildFontLinkHeader,\n clearRequestContext,\n createRscOnErrorHandler(pathname, routePath) {\n return buildRscOnErrorHandler(request, pathname, routePath);\n },\n getFontLinks: fontProviders.getFontLinks,\n getFontPreloads: fontProviders.getFontPreloads,\n getFontStyles: fontProviders.getFontStyles,\n getNavigationContext,\n globalErrorModule: effectiveGlobalErrorModule,\n isEdgeRuntime: callContext?.isEdgeRuntime,\n isRscRequest,\n layoutModules: opts?.layouts ?? null,\n loadSsrHandler: ssrLoader,\n makeThenableParams,\n matchedParams: opts?.matchedParams ?? route?.params ?? {},\n middlewareContext: middlewareContext ?? EMPTY_MW_CTX,\n metadataRoutes,\n requestUrl: request.url,\n resolveChildSegments,\n rootForbiddenModule,\n rootLayouts,\n rootNotFoundModule: effectiveRootNotFoundModule,\n rootUnauthorizedModule,\n route,\n renderToReadableStream: rscRenderer,\n scriptNonce,\n statusCode,\n });\n },\n\n renderNotFound(\n route,\n isRscRequest,\n request,\n matchedParams,\n scriptNonce,\n middlewareContext,\n callContext,\n ) {\n return this.renderHttpAccessFallback(\n route,\n 404,\n isRscRequest,\n request,\n { matchedParams },\n scriptNonce,\n middlewareContext,\n callContext,\n );\n },\n\n renderErrorBoundary(\n route,\n error,\n isRscRequest,\n request,\n matchedParams,\n scriptNonce,\n middlewareContext,\n callContext,\n ) {\n return renderAppPageErrorBoundary({\n basePath,\n buildFontLinkHeader: fontProviders.buildFontLinkHeader,\n clearRequestContext,\n createRscOnErrorHandler(pathname, routePath) {\n return buildRscOnErrorHandler(request, pathname, routePath);\n },\n error,\n getFontLinks: fontProviders.getFontLinks,\n getFontPreloads: fontProviders.getFontPreloads,\n getFontStyles: fontProviders.getFontStyles,\n getNavigationContext,\n globalErrorModule: effectiveGlobalErrorModule,\n isEdgeRuntime: callContext?.isEdgeRuntime,\n isRscRequest,\n loadSsrHandler: ssrLoader,\n makeThenableParams,\n matchedParams: matchedParams ?? route?.params ?? {},\n middlewareContext: middlewareContext ?? EMPTY_MW_CTX,\n metadataRoutes,\n requestUrl: request.url,\n resolveChildSegments,\n rootLayouts,\n route,\n renderToReadableStream: rscRenderer,\n sanitizeErrorForClient: sanitizer,\n scriptNonce,\n });\n },\n };\n}\n"],"mappings":";;;;AA0HA,MAAM,eAAyC;CAAE,SAAS;CAAM,QAAQ;CAAM;AAE9E,SAAgB,0BACd,SAC8B;CAC9B,MAAM,EACJ,WAAW,IACX,qBACA,yBAAyB,wBACzB,eACA,sBACA,mBACA,sBACA,oBACA,gBACA,sBACA,gBACA,aACA,WACA,cACE;CAEJ,MAAM,EAAE,qBAAqB,aAAa,oBAAoB,2BAC5D;CAQF,MAAM,6BACJ,qBAAsB;CASxB,MAAM,8BACJ,sBAAuB;CAEzB,OAAO;EACL,yBACE,OACA,YACA,cACA,SACA,MACA,aACA,mBACA,aACA;GAYA,IAFE,eAAe,OAAO,CAAC,CAAC,wBAAwB,CAAC,SAAS,CAAC,MAAM,mBAE5C;IACrB,MAAM,0BAA0B,sBAAsB,WAAW;IACjE,IAAI,yBACF,OAAO,gCAAgC;KACrC,mBAAmB;KACnB,qBAAqB,cAAc;KACnC;KACA,wBAAwB,UAAU,WAAW;MAC3C,OAAO,uBAAuB,SAAS,UAAU,UAAU;;KAE7D,cAAc,cAAc;KAC5B,iBAAiB,cAAc;KAC/B,eAAe,cAAc;KAC7B;KACA,mBAAmB;KACnB,eAAe,aAAa;KAC5B;KACA,eAAe,EAAE;KACjB,gBAAgB;KAChB;KACA,eAAe,MAAM,iBAAiB,EAAE;KACxC,mBAAmB,qBAAqB;KACxC;KACA,YAAY,QAAQ;KACpB;KACA,qBAAqB;KACrB,aAAa,EAAE;KACf,oBAAoB;KACpB,wBAAwB;KACxB,OAAO;KACP,wBAAwB;KACxB;KACA,oBAAoB;KACpB;KACD,CAAC;;GAIN,OAAO,gCAAgC;IACrC;IACA,mBAAmB,MAAM,qBAAqB;IAC9C,qBAAqB,cAAc;IACnC;IACA,wBAAwB,UAAU,WAAW;KAC3C,OAAO,uBAAuB,SAAS,UAAU,UAAU;;IAE7D,cAAc,cAAc;IAC5B,iBAAiB,cAAc;IAC/B,eAAe,cAAc;IAC7B;IACA,mBAAmB;IACnB,eAAe,aAAa;IAC5B;IACA,eAAe,MAAM,WAAW;IAChC,gBAAgB;IAChB;IACA,eAAe,MAAM,iBAAiB,OAAO,UAAU,EAAE;IACzD,mBAAmB,qBAAqB;IACxC;IACA,YAAY,QAAQ;IACpB;IACA;IACA;IACA,oBAAoB;IACpB;IACA;IACA,wBAAwB;IACxB;IACA;IACD,CAAC;;EAGJ,eACE,OACA,cACA,SACA,eACA,aACA,mBACA,aACA;GACA,OAAO,KAAK,yBACV,OACA,KACA,cACA,SACA,EAAE,eAAe,EACjB,aACA,mBACA,YACD;;EAGH,oBACE,OACA,OACA,cACA,SACA,eACA,aACA,mBACA,aACA;GACA,OAAO,2BAA2B;IAChC;IACA,qBAAqB,cAAc;IACnC;IACA,wBAAwB,UAAU,WAAW;KAC3C,OAAO,uBAAuB,SAAS,UAAU,UAAU;;IAE7D;IACA,cAAc,cAAc;IAC5B,iBAAiB,cAAc;IAC/B,eAAe,cAAc;IAC7B;IACA,mBAAmB;IACnB,eAAe,aAAa;IAC5B;IACA,gBAAgB;IAChB;IACA,eAAe,iBAAiB,OAAO,UAAU,EAAE;IACnD,mBAAmB,qBAAqB;IACxC;IACA,YAAY,QAAQ;IACpB;IACA;IACA;IACA,wBAAwB;IACxB,wBAAwB;IACxB;IACD,CAAC;;EAEL"}
1
+ {"version":3,"file":"app-fallback-renderer.js","names":[],"sources":["../../src/server/app-fallback-renderer.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { AppPageParams } from \"./app-page-boundary.js\";\nimport {\n renderAppPageErrorBoundary,\n renderAppPageHttpAccessFallback,\n type AppPageBoundaryRoute,\n} from \"./app-page-boundary-render.js\";\nimport { DEFAULT_GLOBAL_ERROR_MODULE } from \"./default-global-error-module.js\";\nimport { DEFAULT_NOT_FOUND_MODULE } from \"./default-not-found-module.js\";\nimport type { AppPageFontPreload } from \"./app-page-execution.js\";\nimport type { AppPageMiddlewareContext } from \"./app-page-response.js\";\nimport type { AppPageSsrHandler } from \"./app-page-stream.js\";\nimport type { MetadataFileRoute } from \"./metadata-routes.js\";\nimport type { AppElements } from \"./app-elements.js\";\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\ntype AppPageComponent = import(\"react\").ComponentType<any>;\ntype AppPageModule = Record<string, unknown> & {\n default?: AppPageComponent | null | undefined;\n};\ntype AppPageBoundaryOnError = (\n error: unknown,\n requestInfo: unknown,\n errorContext: unknown,\n) => unknown;\n\ntype AppFallbackRendererRootBoundaries<TModule extends AppPageModule = AppPageModule> = {\n rootForbiddenModule?: TModule | null;\n rootLayouts: readonly (TModule | null | undefined)[];\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n};\n\ntype AppFallbackRendererFontProviders = {\n buildFontLinkHeader: (preloads: readonly AppPageFontPreload[] | null | undefined) => string;\n getFontLinks: () => string[];\n getFontPreloads: () => AppPageFontPreload[];\n getFontStyles: () => string[];\n};\n\ntype AppFallbackRendererOptions<TModule extends AppPageModule = AppPageModule> = {\n clearRequestContext: () => void;\n createRscOnErrorHandler: (\n request: Request,\n pathname: string,\n routePath: string,\n ) => AppPageBoundaryOnError;\n fontProviders: AppFallbackRendererFontProviders;\n getNavigationContext: () => unknown;\n globalErrorModule?: TModule | null;\n /**\n * Loader for the user's `app/global-not-found.tsx` module. When provided,\n * route-miss 404s render this module as a standalone document (skipping the\n * root layout) because it ships its own `<html>` and `<body>`. Page-triggered\n * `notFound()` calls continue to use the regular `not-found.tsx` boundary\n * inside layouts.\n *\n * Passed as a deferred loader (rather than the resolved module) so the\n * generated RSC entry can use `() => import(...)` for chunk isolation.\n * Without that isolation, the bundler co-locates global-not-found's CSS\n * with the root layout's CSS in a single chunk and the CSS minifier\n * (lightningcss) drops overlapping declarations as dead code — breaking\n * the cascade for route-miss 404s where only global-not-found is rendered.\n *\n * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/app-render.tsx\n * @see Next.js test: test/e2e/app-dir/initial-css-order/initial-css-order.test.ts\n */\n loadGlobalNotFoundModule?: (() => Promise<TModule | null | undefined>) | null;\n makeThenableParams: (params: AppPageParams) => unknown;\n metadataRoutes: MetadataFileRoute[];\n /** Configured next.config `basePath`, threaded into file-based metadata href emission. */\n basePath?: string;\n resolveChildSegments: (\n routeSegments: readonly string[],\n treePosition: number,\n params: AppPageParams,\n ) => string[];\n rootBoundaries: AppFallbackRendererRootBoundaries<TModule>;\n rscRenderer: (\n element: ReactNode | AppElements,\n options: { onError: AppPageBoundaryOnError },\n ) => ReadableStream<Uint8Array>;\n sanitizer: (error: Error) => Error;\n ssrLoader: () => Promise<AppPageSsrHandler>;\n};\n\ntype AppFallbackRendererCallContext = {\n /**\n * Whether the matched (or invoking) route opts into Next.js' edge runtime via\n * `export const runtime = \"edge\"`. Propagated so boundary/error/not-found\n * responses carry `x-edge-runtime: 1` for edge routes, matching the page\n * render path. Defaults to `false` when no route is matched.\n */\n isEdgeRuntime?: boolean;\n};\n\ntype AppFallbackRenderer<TModule extends AppPageModule = AppPageModule> = {\n renderErrorBoundary: (\n route: AppPageBoundaryRoute<TModule> | null,\n error: unknown,\n isRscRequest: boolean,\n request: Request,\n matchedParams: AppPageParams | undefined,\n scriptNonce: string | undefined,\n middlewareContext: AppPageMiddlewareContext,\n callContext?: AppFallbackRendererCallContext,\n ) => Promise<Response | null>;\n renderHttpAccessFallback: (\n route: AppPageBoundaryRoute<TModule> | null,\n statusCode: number,\n isRscRequest: boolean,\n request: Request,\n opts: {\n boundaryComponent?: AppPageComponent | null;\n layouts?: readonly (TModule | null | undefined)[] | null;\n matchedParams?: AppPageParams;\n },\n scriptNonce: string | undefined,\n middlewareContext: AppPageMiddlewareContext,\n callContext?: AppFallbackRendererCallContext,\n ) => Promise<Response | null>;\n renderNotFound: (\n route: AppPageBoundaryRoute<TModule> | null,\n isRscRequest: boolean,\n request: Request,\n matchedParams: AppPageParams | undefined,\n scriptNonce: string | undefined,\n middlewareContext: AppPageMiddlewareContext,\n callContext?: AppFallbackRendererCallContext,\n ) => Promise<Response | null>;\n};\n\nconst EMPTY_MW_CTX: AppPageMiddlewareContext = { headers: null, status: null };\n\nexport function createAppFallbackRenderer<TModule extends AppPageModule>(\n options: AppFallbackRendererOptions<TModule>,\n): AppFallbackRenderer<TModule> {\n const {\n basePath = \"\",\n clearRequestContext,\n createRscOnErrorHandler: buildRscOnErrorHandler,\n fontProviders,\n getNavigationContext,\n globalErrorModule,\n loadGlobalNotFoundModule,\n makeThenableParams,\n metadataRoutes,\n resolveChildSegments,\n rootBoundaries,\n rscRenderer,\n sanitizer,\n ssrLoader,\n } = options;\n\n const { rootForbiddenModule, rootLayouts, rootNotFoundModule, rootUnauthorizedModule } =\n rootBoundaries;\n\n // When the app does not define `app/global-error.tsx`, fall back to vinext's\n // built-in default global error component so that uncaught render errors\n // produce the same UI Next.js ships out of the box (matching markup, inline\n // styles, theme CSS, and the \"ERROR <digest>\" footer for server errors).\n // See packages/vinext/src/shims/default-global-error.tsx and\n // packages/vinext/src/server/default-global-error-module.ts.\n const effectiveGlobalErrorModule: TModule | null =\n globalErrorModule ?? (DEFAULT_GLOBAL_ERROR_MODULE as unknown as TModule);\n\n // When the app does not define `app/not-found.tsx` (and has not opted into\n // `app/global-not-found.tsx`), fall back to vinext's built-in default\n // not-found component so route-miss 404s render the canonical Next.js\n // markup (status + \"This page could not be found.\" message). Matches the\n // default not-found UI shipped with Next.js's app loader.\n // See packages/vinext/src/shims/default-not-found.tsx and\n // packages/vinext/src/server/default-not-found-module.ts.\n const effectiveRootNotFoundModule: TModule | null =\n rootNotFoundModule ?? (DEFAULT_NOT_FOUND_MODULE as unknown as TModule);\n\n // Cache the result of `loadGlobalNotFoundModule()` so subsequent route-miss\n // 404s in the same worker hit a warm import instead of re-resolving the\n // dynamic chunk. The loader itself is invoked at most once per worker;\n // failures are surfaced on every call so they don't get swallowed.\n let globalNotFoundModulePromise: Promise<TModule | null | undefined> | null = null;\n function resolveGlobalNotFoundModule(): Promise<TModule | null | undefined> | null {\n if (!loadGlobalNotFoundModule) return null;\n if (globalNotFoundModulePromise === null) {\n globalNotFoundModulePromise = Promise.resolve().then(loadGlobalNotFoundModule);\n }\n return globalNotFoundModulePromise;\n }\n\n return {\n async renderHttpAccessFallback(\n route,\n statusCode,\n isRscRequest,\n request,\n opts,\n scriptNonce,\n middlewareContext,\n callContext,\n ) {\n // global-not-found.tsx replaces the root layout for route-miss 404s.\n // Only applies when:\n // - The user defined app/global-not-found.tsx\n // - The 404 originates from a route miss (no matched route)\n // - The caller did not already pick a specific boundary component\n // Page-triggered notFound() calls (route is non-null) keep using the\n // regular not-found.tsx boundary inside the route's layouts.\n // See https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/app-render.tsx#L495-L520\n const useGlobalNotFound =\n statusCode === 404 && !!loadGlobalNotFoundModule && !route && !opts?.boundaryComponent;\n\n if (useGlobalNotFound) {\n const globalNotFoundModule = await resolveGlobalNotFoundModule();\n const globalNotFoundComponent = globalNotFoundModule?.default ?? null;\n if (globalNotFoundComponent) {\n return renderAppPageHttpAccessFallback({\n boundaryComponent: globalNotFoundComponent,\n buildFontLinkHeader: fontProviders.buildFontLinkHeader,\n clearRequestContext,\n createRscOnErrorHandler(pathname, routePath) {\n return buildRscOnErrorHandler(request, pathname, routePath);\n },\n getFontLinks: fontProviders.getFontLinks,\n getFontPreloads: fontProviders.getFontPreloads,\n getFontStyles: fontProviders.getFontStyles,\n getNavigationContext,\n globalErrorModule: effectiveGlobalErrorModule,\n isEdgeRuntime: callContext?.isEdgeRuntime,\n isRscRequest,\n layoutModules: [],\n loadSsrHandler: ssrLoader,\n makeThenableParams,\n matchedParams: opts?.matchedParams ?? {},\n middlewareContext: middlewareContext ?? EMPTY_MW_CTX,\n metadataRoutes,\n requestUrl: request.url,\n resolveChildSegments,\n rootForbiddenModule: null,\n rootLayouts: [],\n rootNotFoundModule: null,\n rootUnauthorizedModule: null,\n route: null,\n renderToReadableStream: rscRenderer,\n scriptNonce,\n skipLayoutWrapping: true,\n statusCode,\n });\n }\n }\n\n return renderAppPageHttpAccessFallback({\n basePath,\n boundaryComponent: opts?.boundaryComponent ?? null,\n buildFontLinkHeader: fontProviders.buildFontLinkHeader,\n clearRequestContext,\n createRscOnErrorHandler(pathname, routePath) {\n return buildRscOnErrorHandler(request, pathname, routePath);\n },\n getFontLinks: fontProviders.getFontLinks,\n getFontPreloads: fontProviders.getFontPreloads,\n getFontStyles: fontProviders.getFontStyles,\n getNavigationContext,\n globalErrorModule: effectiveGlobalErrorModule,\n isEdgeRuntime: callContext?.isEdgeRuntime,\n isRscRequest,\n layoutModules: opts?.layouts ?? null,\n loadSsrHandler: ssrLoader,\n makeThenableParams,\n matchedParams: opts?.matchedParams ?? route?.params ?? {},\n middlewareContext: middlewareContext ?? EMPTY_MW_CTX,\n metadataRoutes,\n requestUrl: request.url,\n resolveChildSegments,\n rootForbiddenModule,\n rootLayouts,\n rootNotFoundModule: effectiveRootNotFoundModule,\n rootUnauthorizedModule,\n route,\n renderToReadableStream: rscRenderer,\n scriptNonce,\n statusCode,\n });\n },\n\n renderNotFound(\n route,\n isRscRequest,\n request,\n matchedParams,\n scriptNonce,\n middlewareContext,\n callContext,\n ) {\n return this.renderHttpAccessFallback(\n route,\n 404,\n isRscRequest,\n request,\n { matchedParams },\n scriptNonce,\n middlewareContext,\n callContext,\n );\n },\n\n renderErrorBoundary(\n route,\n error,\n isRscRequest,\n request,\n matchedParams,\n scriptNonce,\n middlewareContext,\n callContext,\n ) {\n return renderAppPageErrorBoundary({\n basePath,\n buildFontLinkHeader: fontProviders.buildFontLinkHeader,\n clearRequestContext,\n createRscOnErrorHandler(pathname, routePath) {\n return buildRscOnErrorHandler(request, pathname, routePath);\n },\n error,\n getFontLinks: fontProviders.getFontLinks,\n getFontPreloads: fontProviders.getFontPreloads,\n getFontStyles: fontProviders.getFontStyles,\n getNavigationContext,\n globalErrorModule: effectiveGlobalErrorModule,\n isEdgeRuntime: callContext?.isEdgeRuntime,\n isRscRequest,\n loadSsrHandler: ssrLoader,\n makeThenableParams,\n matchedParams: matchedParams ?? route?.params ?? {},\n middlewareContext: middlewareContext ?? EMPTY_MW_CTX,\n metadataRoutes,\n requestUrl: request.url,\n resolveChildSegments,\n rootLayouts,\n route,\n renderToReadableStream: rscRenderer,\n sanitizeErrorForClient: sanitizer,\n scriptNonce,\n });\n },\n };\n}\n"],"mappings":";;;;AAoIA,MAAM,eAAyC;CAAE,SAAS;CAAM,QAAQ;CAAM;AAE9E,SAAgB,0BACd,SAC8B;CAC9B,MAAM,EACJ,WAAW,IACX,qBACA,yBAAyB,wBACzB,eACA,sBACA,mBACA,0BACA,oBACA,gBACA,sBACA,gBACA,aACA,WACA,cACE;CAEJ,MAAM,EAAE,qBAAqB,aAAa,oBAAoB,2BAC5D;CAQF,MAAM,6BACJ,qBAAsB;CASxB,MAAM,8BACJ,sBAAuB;CAMzB,IAAI,8BAA0E;CAC9E,SAAS,8BAA0E;EACjF,IAAI,CAAC,0BAA0B,OAAO;EACtC,IAAI,gCAAgC,MAClC,8BAA8B,QAAQ,SAAS,CAAC,KAAK,yBAAyB;EAEhF,OAAO;;CAGT,OAAO;EACL,MAAM,yBACJ,OACA,YACA,cACA,SACA,MACA,aACA,mBACA,aACA;GAYA,IAFE,eAAe,OAAO,CAAC,CAAC,4BAA4B,CAAC,SAAS,CAAC,MAAM,mBAEhD;IAErB,MAAM,2BAA0B,MADG,6BAA6B,GACV,WAAW;IACjE,IAAI,yBACF,OAAO,gCAAgC;KACrC,mBAAmB;KACnB,qBAAqB,cAAc;KACnC;KACA,wBAAwB,UAAU,WAAW;MAC3C,OAAO,uBAAuB,SAAS,UAAU,UAAU;;KAE7D,cAAc,cAAc;KAC5B,iBAAiB,cAAc;KAC/B,eAAe,cAAc;KAC7B;KACA,mBAAmB;KACnB,eAAe,aAAa;KAC5B;KACA,eAAe,EAAE;KACjB,gBAAgB;KAChB;KACA,eAAe,MAAM,iBAAiB,EAAE;KACxC,mBAAmB,qBAAqB;KACxC;KACA,YAAY,QAAQ;KACpB;KACA,qBAAqB;KACrB,aAAa,EAAE;KACf,oBAAoB;KACpB,wBAAwB;KACxB,OAAO;KACP,wBAAwB;KACxB;KACA,oBAAoB;KACpB;KACD,CAAC;;GAIN,OAAO,gCAAgC;IACrC;IACA,mBAAmB,MAAM,qBAAqB;IAC9C,qBAAqB,cAAc;IACnC;IACA,wBAAwB,UAAU,WAAW;KAC3C,OAAO,uBAAuB,SAAS,UAAU,UAAU;;IAE7D,cAAc,cAAc;IAC5B,iBAAiB,cAAc;IAC/B,eAAe,cAAc;IAC7B;IACA,mBAAmB;IACnB,eAAe,aAAa;IAC5B;IACA,eAAe,MAAM,WAAW;IAChC,gBAAgB;IAChB;IACA,eAAe,MAAM,iBAAiB,OAAO,UAAU,EAAE;IACzD,mBAAmB,qBAAqB;IACxC;IACA,YAAY,QAAQ;IACpB;IACA;IACA;IACA,oBAAoB;IACpB;IACA;IACA,wBAAwB;IACxB;IACA;IACD,CAAC;;EAGJ,eACE,OACA,cACA,SACA,eACA,aACA,mBACA,aACA;GACA,OAAO,KAAK,yBACV,OACA,KACA,cACA,SACA,EAAE,eAAe,EACjB,aACA,mBACA,YACD;;EAGH,oBACE,OACA,OACA,cACA,SACA,eACA,aACA,mBACA,aACA;GACA,OAAO,2BAA2B;IAChC;IACA,qBAAqB,cAAc;IACnC;IACA,wBAAwB,UAAU,WAAW;KAC3C,OAAO,uBAAuB,SAAS,UAAU,UAAU;;IAE7D;IACA,cAAc,cAAc;IAC5B,iBAAiB,cAAc;IAC/B,eAAe,cAAc;IAC7B;IACA,mBAAmB;IACnB,eAAe,aAAa;IAC5B;IACA,gBAAgB;IAChB;IACA,eAAe,iBAAiB,OAAO,UAAU,EAAE;IACnD,mBAAmB,qBAAqB;IACxC;IACA,YAAY,QAAQ;IACpB;IACA;IACA;IACA,wBAAwB;IACxB,wBAAwB;IACxB;IACD,CAAC;;EAEL"}
@@ -0,0 +1,7 @@
1
+ //#region src/server/app-inline-css-client.d.ts
2
+ type InlineCssStylesheetLinkElement = Pick<HTMLLinkElement, "getAttribute" | "hasAttribute">;
3
+ declare function isInlineCssStylesheetLinkElement(link: InlineCssStylesheetLinkElement): boolean;
4
+ declare function removeStylesheetLinksCoveredByInlineCss(): void;
5
+ //#endregion
6
+ export { isInlineCssStylesheetLinkElement, removeStylesheetLinksCoveredByInlineCss };
7
+ //# sourceMappingURL=app-inline-css-client.d.ts.map
@@ -0,0 +1,37 @@
1
+ import { htmlTokenListContains } from "./html.js";
2
+ //#region src/server/app-inline-css-client.ts
3
+ function inlineStyleCoversStylesheetHref(styleHref, linkHref) {
4
+ for (const candidate of styleHref.split(/\s+/)) {
5
+ if (candidate === linkHref) return true;
6
+ try {
7
+ const candidateUrl = new URL(candidate, window.location.href);
8
+ const linkUrl = new URL(linkHref, window.location.href);
9
+ if (candidateUrl.href === linkUrl.href) return true;
10
+ } catch {}
11
+ }
12
+ return false;
13
+ }
14
+ function isInlineCssStylesheetLinkElement(link) {
15
+ return htmlTokenListContains(link.getAttribute("rel"), "stylesheet") && link.hasAttribute("href") && (link.hasAttribute("data-precedence") || link.hasAttribute("precedence"));
16
+ }
17
+ function removeStylesheetLinksCoveredByInlineCss() {
18
+ const inlineStyles = document.head.querySelectorAll("style[data-vinext-inline-css][data-href]");
19
+ if (inlineStyles.length === 0) return;
20
+ const links = document.head.querySelectorAll("link[rel][href]");
21
+ for (const link of links) {
22
+ if (!isInlineCssStylesheetLinkElement(link)) continue;
23
+ const href = link.getAttribute("href");
24
+ if (!href) continue;
25
+ for (const style of inlineStyles) {
26
+ const styleHref = style.getAttribute("data-href");
27
+ if (styleHref && inlineStyleCoversStylesheetHref(styleHref, href)) {
28
+ link.remove();
29
+ break;
30
+ }
31
+ }
32
+ }
33
+ }
34
+ //#endregion
35
+ export { isInlineCssStylesheetLinkElement, removeStylesheetLinksCoveredByInlineCss };
36
+
37
+ //# sourceMappingURL=app-inline-css-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-inline-css-client.js","names":[],"sources":["../../src/server/app-inline-css-client.ts"],"sourcesContent":["import { htmlTokenListContains } from \"./html.js\";\n\ntype InlineCssStylesheetLinkElement = Pick<HTMLLinkElement, \"getAttribute\" | \"hasAttribute\">;\n\nfunction inlineStyleCoversStylesheetHref(styleHref: string, linkHref: string): boolean {\n for (const candidate of styleHref.split(/\\s+/)) {\n if (candidate === linkHref) return true;\n try {\n const candidateUrl = new URL(candidate, window.location.href);\n const linkUrl = new URL(linkHref, window.location.href);\n if (candidateUrl.href === linkUrl.href) return true;\n } catch {\n // If either value is not parseable, exact string comparison above is the\n // only safe comparison.\n }\n }\n\n return false;\n}\n\nexport function isInlineCssStylesheetLinkElement(link: InlineCssStylesheetLinkElement): boolean {\n return (\n htmlTokenListContains(link.getAttribute(\"rel\"), \"stylesheet\") &&\n link.hasAttribute(\"href\") &&\n (link.hasAttribute(\"data-precedence\") || link.hasAttribute(\"precedence\"))\n );\n}\n\nexport function removeStylesheetLinksCoveredByInlineCss(): void {\n const inlineStyles = document.head.querySelectorAll<HTMLStyleElement>(\n \"style[data-vinext-inline-css][data-href]\",\n );\n if (inlineStyles.length === 0) return;\n\n const links = document.head.querySelectorAll<HTMLLinkElement>(\"link[rel][href]\");\n for (const link of links) {\n if (!isInlineCssStylesheetLinkElement(link)) continue;\n\n const href = link.getAttribute(\"href\");\n if (!href) continue;\n\n for (const style of inlineStyles) {\n const styleHref = style.getAttribute(\"data-href\");\n if (styleHref && inlineStyleCoversStylesheetHref(styleHref, href)) {\n link.remove();\n break;\n }\n }\n }\n}\n"],"mappings":";;AAIA,SAAS,gCAAgC,WAAmB,UAA2B;CACrF,KAAK,MAAM,aAAa,UAAU,MAAM,MAAM,EAAE;EAC9C,IAAI,cAAc,UAAU,OAAO;EACnC,IAAI;GACF,MAAM,eAAe,IAAI,IAAI,WAAW,OAAO,SAAS,KAAK;GAC7D,MAAM,UAAU,IAAI,IAAI,UAAU,OAAO,SAAS,KAAK;GACvD,IAAI,aAAa,SAAS,QAAQ,MAAM,OAAO;UACzC;;CAMV,OAAO;;AAGT,SAAgB,iCAAiC,MAA+C;CAC9F,OACE,sBAAsB,KAAK,aAAa,MAAM,EAAE,aAAa,IAC7D,KAAK,aAAa,OAAO,KACxB,KAAK,aAAa,kBAAkB,IAAI,KAAK,aAAa,aAAa;;AAI5E,SAAgB,0CAAgD;CAC9D,MAAM,eAAe,SAAS,KAAK,iBACjC,2CACD;CACD,IAAI,aAAa,WAAW,GAAG;CAE/B,MAAM,QAAQ,SAAS,KAAK,iBAAkC,kBAAkB;CAChF,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,CAAC,iCAAiC,KAAK,EAAE;EAE7C,MAAM,OAAO,KAAK,aAAa,OAAO;EACtC,IAAI,CAAC,MAAM;EAEX,KAAK,MAAM,SAAS,cAAc;GAChC,MAAM,YAAY,MAAM,aAAa,YAAY;GACjD,IAAI,aAAa,gCAAgC,WAAW,KAAK,EAAE;IACjE,KAAK,QAAQ;IACb"}
@@ -65,9 +65,29 @@ type RenderAppPageBoundaryResponseOptions<TElement> = {
65
65
  };
66
66
  declare function resolveAppPageHttpAccessBoundaryComponent<TModule, TComponent>(options: ResolveAppPageHttpAccessBoundaryComponentOptions<TModule, TComponent>): TComponent | null;
67
67
  declare function resolveAppPageParentHttpAccessBoundaryModule<TModule>(options: ResolveAppPageParentHttpAccessBoundaryModuleOptions<TModule>): TModule | null;
68
+ /**
69
+ * Like {@link resolveAppPageParentHttpAccessBoundaryModule}, but also returns
70
+ * the layout index that owns the resolved boundary so callers can slice the
71
+ * layouts array to skip rendering layouts below the boundary owner.
72
+ *
73
+ * `layoutIndex` is the per-layout index where the boundary lives, or `null` if
74
+ * the resolved boundary is the root module (which conceptually sits above all
75
+ * layouts when no layout-level boundary is present).
76
+ *
77
+ * Used by the page-error fast path to make `forbidden()` / `unauthorized()` /
78
+ * `notFound()` escalate past intermediate layouts that lack a boundary file,
79
+ * matching Next.js's `create-component-tree.tsx` behavior where the nearest
80
+ * ancestor boundary owns the fallback subtree.
81
+ *
82
+ * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-component-tree.tsx
83
+ */
84
+ declare function resolveAppPageParentHttpAccessBoundary<TModule>(options: ResolveAppPageParentHttpAccessBoundaryModuleOptions<TModule>): {
85
+ module: TModule | null;
86
+ layoutIndex: number | null;
87
+ };
68
88
  declare function resolveAppPageErrorBoundary<TModule, TComponent>(options: ResolveAppPageErrorBoundaryOptions<TModule, TComponent>): ResolveAppPageErrorBoundaryResult<TComponent>;
69
89
  declare function wrapAppPageBoundaryElement<TElement, TLayoutModule, TLayoutComponent, TChildSegments, TGlobalErrorComponent>(options: WrapAppPageBoundaryElementOptions<TElement, TLayoutModule, TLayoutComponent, TChildSegments, TGlobalErrorComponent>): TElement;
70
90
  declare function renderAppPageBoundaryResponse<TElement>(options: RenderAppPageBoundaryResponseOptions<TElement>): Promise<Response>;
71
91
  //#endregion
72
- export { AppPageParams, renderAppPageBoundaryResponse, resolveAppPageErrorBoundary, resolveAppPageHttpAccessBoundaryComponent, resolveAppPageParentHttpAccessBoundaryModule, wrapAppPageBoundaryElement };
92
+ export { AppPageParams, renderAppPageBoundaryResponse, resolveAppPageErrorBoundary, resolveAppPageHttpAccessBoundaryComponent, resolveAppPageParentHttpAccessBoundary, resolveAppPageParentHttpAccessBoundaryModule, wrapAppPageBoundaryElement };
73
93
  //# sourceMappingURL=app-page-boundary.d.ts.map
@@ -12,6 +12,25 @@ function resolveAppPageHttpAccessBoundaryComponent(options) {
12
12
  return options.getDefaultExport(boundaryModule) ?? null;
13
13
  }
14
14
  function resolveAppPageParentHttpAccessBoundaryModule(options) {
15
+ return resolveAppPageParentHttpAccessBoundary(options).module;
16
+ }
17
+ /**
18
+ * Like {@link resolveAppPageParentHttpAccessBoundaryModule}, but also returns
19
+ * the layout index that owns the resolved boundary so callers can slice the
20
+ * layouts array to skip rendering layouts below the boundary owner.
21
+ *
22
+ * `layoutIndex` is the per-layout index where the boundary lives, or `null` if
23
+ * the resolved boundary is the root module (which conceptually sits above all
24
+ * layouts when no layout-level boundary is present).
25
+ *
26
+ * Used by the page-error fast path to make `forbidden()` / `unauthorized()` /
27
+ * `notFound()` escalate past intermediate layouts that lack a boundary file,
28
+ * matching Next.js's `create-component-tree.tsx` behavior where the nearest
29
+ * ancestor boundary owns the fallback subtree.
30
+ *
31
+ * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-component-tree.tsx
32
+ */
33
+ function resolveAppPageParentHttpAccessBoundary(options) {
15
34
  let routeModules = options.routeNotFoundModules;
16
35
  let rootModule = options.rootNotFoundModule;
17
36
  if (options.statusCode === 403) {
@@ -23,9 +42,15 @@ function resolveAppPageParentHttpAccessBoundaryModule(options) {
23
42
  }
24
43
  if (routeModules) for (let index = options.layoutIndex - 1; index >= 0; index--) {
25
44
  const module = routeModules[index];
26
- if (module) return module;
45
+ if (module) return {
46
+ module,
47
+ layoutIndex: index
48
+ };
27
49
  }
28
- return rootModule ?? null;
50
+ return {
51
+ module: rootModule ?? null,
52
+ layoutIndex: null
53
+ };
29
54
  }
30
55
  function resolveAppPageErrorBoundary(options) {
31
56
  const pageErrorComponent = options.getDefaultExport(options.pageErrorModule);
@@ -81,6 +106,6 @@ async function renderAppPageBoundaryResponse(options) {
81
106
  return options.createHtmlResponse(rscStream, options.status);
82
107
  }
83
108
  //#endregion
84
- export { renderAppPageBoundaryResponse, resolveAppPageErrorBoundary, resolveAppPageHttpAccessBoundaryComponent, resolveAppPageParentHttpAccessBoundaryModule, wrapAppPageBoundaryElement };
109
+ export { renderAppPageBoundaryResponse, resolveAppPageErrorBoundary, resolveAppPageHttpAccessBoundaryComponent, resolveAppPageParentHttpAccessBoundary, resolveAppPageParentHttpAccessBoundaryModule, wrapAppPageBoundaryElement };
85
110
 
86
111
  //# sourceMappingURL=app-page-boundary.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-page-boundary.js","names":[],"sources":["../../src/server/app-page-boundary.ts"],"sourcesContent":["import { runWithFetchDedupe } from \"vinext/shims/fetch-cache\";\nimport { applyEdgeRuntimeHeader } from \"./app-page-response.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport {\n VINEXT_RSC_CONTENT_TYPE,\n VINEXT_RSC_VARY_HEADER,\n applyRscCompatibilityIdHeader,\n} from \"./app-rsc-cache-busting.js\";\nimport { resolveAppPageSegmentParams } from \"./app-page-params.js\";\n\nexport type AppPageParams = Record<string, string | string[]>;\n\ntype ResolveAppPageHttpAccessBoundaryComponentOptions<TModule, TComponent> = {\n getDefaultExport: (module: TModule | null | undefined) => TComponent | null | undefined;\n rootForbiddenModule?: TModule | null;\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n routeForbiddenModule?: TModule | null;\n routeNotFoundModule?: TModule | null;\n routeUnauthorizedModule?: TModule | null;\n statusCode: number;\n};\n\ntype ResolveAppPageParentHttpAccessBoundaryModuleOptions<TModule> = {\n layoutIndex: number;\n rootForbiddenModule?: TModule | null;\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n routeForbiddenModules?: readonly (TModule | null | undefined)[] | null;\n routeNotFoundModules?: readonly (TModule | null | undefined)[] | null;\n routeUnauthorizedModules?: readonly (TModule | null | undefined)[] | null;\n statusCode: number;\n};\n\ntype ResolveAppPageErrorBoundaryOptions<TModule, TComponent> = {\n getDefaultExport: (module: TModule | null | undefined) => TComponent | null | undefined;\n globalErrorModule?: TModule | null;\n errorModules?: readonly (TModule | null | undefined)[] | null;\n layoutErrorModules?: readonly (TModule | null | undefined)[] | null;\n pageErrorModule?: TModule | null;\n};\n\ntype ResolveAppPageErrorBoundaryResult<TComponent> = {\n component: TComponent | null;\n isGlobalError: boolean;\n};\n\ntype WrapAppPageBoundaryElementOptions<\n TElement,\n TLayoutModule,\n TLayoutComponent,\n TChildSegments,\n TGlobalErrorComponent,\n> = {\n element: TElement;\n getDefaultExport: (\n module: TLayoutModule | null | undefined,\n ) => TLayoutComponent | null | undefined;\n globalErrorComponent?: TGlobalErrorComponent | null;\n includeGlobalErrorBoundary: boolean;\n isRscRequest: boolean;\n layoutModules: readonly (TLayoutModule | null | undefined)[];\n layoutTreePositions?: readonly number[] | null;\n makeThenableParams: (params: AppPageParams) => unknown;\n matchedParams: AppPageParams;\n renderErrorBoundary: (component: TGlobalErrorComponent, children: TElement) => TElement;\n renderLayout: (component: TLayoutComponent, children: TElement, params: unknown) => TElement;\n renderLayoutSegmentProvider?: (\n segmentMap: { children: TChildSegments },\n children: TElement,\n ) => TElement;\n resolveChildSegments?: (\n routeSegments: readonly string[],\n treePosition: number,\n params: AppPageParams,\n ) => TChildSegments;\n routeSegments?: readonly string[];\n skipLayoutWrapping?: boolean;\n};\n\ntype AppPageBoundaryOnError = (\n error: unknown,\n requestInfo: unknown,\n errorContext: unknown,\n) => unknown;\n\ntype RenderAppPageBoundaryResponseOptions<TElement> = {\n createHtmlResponse: (rscStream: ReadableStream<Uint8Array>, status: number) => Promise<Response>;\n createRscOnErrorHandler: () => AppPageBoundaryOnError;\n element: TElement;\n isEdgeRuntime?: boolean;\n isRscRequest: boolean;\n middlewareHeaders?: Headers | null;\n renderToReadableStream: (\n element: TElement,\n options: { onError: AppPageBoundaryOnError },\n ) => ReadableStream<Uint8Array>;\n status: number;\n};\n\nexport function resolveAppPageHttpAccessBoundaryComponent<TModule, TComponent>(\n options: ResolveAppPageHttpAccessBoundaryComponentOptions<TModule, TComponent>,\n): TComponent | null {\n let boundaryModule: TModule | null | undefined;\n\n if (options.statusCode === 403) {\n boundaryModule = options.routeForbiddenModule ?? options.rootForbiddenModule;\n } else if (options.statusCode === 401) {\n boundaryModule = options.routeUnauthorizedModule ?? options.rootUnauthorizedModule;\n } else {\n boundaryModule = options.routeNotFoundModule ?? options.rootNotFoundModule;\n }\n\n return options.getDefaultExport(boundaryModule) ?? null;\n}\n\nexport function resolveAppPageParentHttpAccessBoundaryModule<TModule>(\n options: ResolveAppPageParentHttpAccessBoundaryModuleOptions<TModule>,\n): TModule | null {\n let routeModules = options.routeNotFoundModules;\n let rootModule = options.rootNotFoundModule;\n\n if (options.statusCode === 403) {\n routeModules = options.routeForbiddenModules;\n rootModule = options.rootForbiddenModule;\n } else if (options.statusCode === 401) {\n routeModules = options.routeUnauthorizedModules;\n rootModule = options.rootUnauthorizedModule;\n }\n\n if (routeModules) {\n for (let index = options.layoutIndex - 1; index >= 0; index--) {\n const module = routeModules[index];\n if (module) {\n return module;\n }\n }\n }\n\n return rootModule ?? null;\n}\n\nexport function resolveAppPageErrorBoundary<TModule, TComponent>(\n options: ResolveAppPageErrorBoundaryOptions<TModule, TComponent>,\n): ResolveAppPageErrorBoundaryResult<TComponent> {\n const pageErrorComponent = options.getDefaultExport(options.pageErrorModule);\n if (pageErrorComponent) {\n return {\n component: pageErrorComponent,\n isGlobalError: false,\n };\n }\n\n const segmentErrorModules = options.errorModules ?? options.layoutErrorModules;\n if (segmentErrorModules) {\n for (let index = segmentErrorModules.length - 1; index >= 0; index--) {\n const segmentErrorComponent = options.getDefaultExport(segmentErrorModules[index]);\n if (segmentErrorComponent) {\n return {\n component: segmentErrorComponent,\n isGlobalError: false,\n };\n }\n }\n }\n\n const globalErrorComponent = options.getDefaultExport(options.globalErrorModule);\n return {\n component: globalErrorComponent ?? null,\n isGlobalError: Boolean(globalErrorComponent),\n };\n}\n\nexport function wrapAppPageBoundaryElement<\n TElement,\n TLayoutModule,\n TLayoutComponent,\n TChildSegments,\n TGlobalErrorComponent,\n>(\n options: WrapAppPageBoundaryElementOptions<\n TElement,\n TLayoutModule,\n TLayoutComponent,\n TChildSegments,\n TGlobalErrorComponent\n >,\n): TElement {\n let element = options.element;\n\n if (!options.skipLayoutWrapping) {\n for (let index = options.layoutModules.length - 1; index >= 0; index--) {\n const layoutComponent = options.getDefaultExport(options.layoutModules[index]);\n if (!layoutComponent) {\n continue;\n }\n\n const treePosition = options.layoutTreePositions ? options.layoutTreePositions[index] : 0;\n const asyncParams = options.makeThenableParams(\n resolveAppPageSegmentParams(options.routeSegments, treePosition, options.matchedParams),\n );\n element = options.renderLayout(layoutComponent, element, asyncParams);\n\n if (\n options.isRscRequest &&\n options.renderLayoutSegmentProvider &&\n options.resolveChildSegments\n ) {\n const childSegments = options.resolveChildSegments(\n options.routeSegments ?? [],\n treePosition,\n options.matchedParams,\n );\n element = options.renderLayoutSegmentProvider({ children: childSegments }, element);\n }\n }\n }\n\n if (options.isRscRequest && options.includeGlobalErrorBoundary && options.globalErrorComponent) {\n element = options.renderErrorBoundary(options.globalErrorComponent, element);\n }\n\n return element;\n}\n\nexport async function renderAppPageBoundaryResponse<TElement>(\n options: RenderAppPageBoundaryResponseOptions<TElement>,\n): Promise<Response> {\n // Defensive wrap for standalone callers; idempotent under dispatchAppPage.\n // The async stream consumption that follows relies on the surrounding\n // runWithRequestContext to keep ALS state alive after this synchronous call\n // returns. See app-page-render.ts for the same pattern.\n const rscStream = runWithFetchDedupe(() =>\n options.renderToReadableStream(options.element, {\n onError: options.createRscOnErrorHandler(),\n }),\n );\n\n if (options.isRscRequest) {\n // Do NOT clear request-scoped context here. RSC responses are consumed lazily\n // by the client, so headers()/cookies() and async server components still need\n // their ALS-backed state while the stream is being read.\n const headers = new Headers({\n \"Content-Type\": VINEXT_RSC_CONTENT_TYPE,\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);\n mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);\n applyRscCompatibilityIdHeader(headers);\n\n return new Response(rscStream, {\n status: options.status,\n headers,\n });\n }\n\n return options.createHtmlResponse(rscStream, options.status);\n}\n"],"mappings":";;;;;;AAoGA,SAAgB,0CACd,SACmB;CACnB,IAAI;CAEJ,IAAI,QAAQ,eAAe,KACzB,iBAAiB,QAAQ,wBAAwB,QAAQ;MACpD,IAAI,QAAQ,eAAe,KAChC,iBAAiB,QAAQ,2BAA2B,QAAQ;MAE5D,iBAAiB,QAAQ,uBAAuB,QAAQ;CAG1D,OAAO,QAAQ,iBAAiB,eAAe,IAAI;;AAGrD,SAAgB,6CACd,SACgB;CAChB,IAAI,eAAe,QAAQ;CAC3B,IAAI,aAAa,QAAQ;CAEzB,IAAI,QAAQ,eAAe,KAAK;EAC9B,eAAe,QAAQ;EACvB,aAAa,QAAQ;QAChB,IAAI,QAAQ,eAAe,KAAK;EACrC,eAAe,QAAQ;EACvB,aAAa,QAAQ;;CAGvB,IAAI,cACF,KAAK,IAAI,QAAQ,QAAQ,cAAc,GAAG,SAAS,GAAG,SAAS;EAC7D,MAAM,SAAS,aAAa;EAC5B,IAAI,QACF,OAAO;;CAKb,OAAO,cAAc;;AAGvB,SAAgB,4BACd,SAC+C;CAC/C,MAAM,qBAAqB,QAAQ,iBAAiB,QAAQ,gBAAgB;CAC5E,IAAI,oBACF,OAAO;EACL,WAAW;EACX,eAAe;EAChB;CAGH,MAAM,sBAAsB,QAAQ,gBAAgB,QAAQ;CAC5D,IAAI,qBACF,KAAK,IAAI,QAAQ,oBAAoB,SAAS,GAAG,SAAS,GAAG,SAAS;EACpE,MAAM,wBAAwB,QAAQ,iBAAiB,oBAAoB,OAAO;EAClF,IAAI,uBACF,OAAO;GACL,WAAW;GACX,eAAe;GAChB;;CAKP,MAAM,uBAAuB,QAAQ,iBAAiB,QAAQ,kBAAkB;CAChF,OAAO;EACL,WAAW,wBAAwB;EACnC,eAAe,QAAQ,qBAAqB;EAC7C;;AAGH,SAAgB,2BAOd,SAOU;CACV,IAAI,UAAU,QAAQ;CAEtB,IAAI,CAAC,QAAQ,oBACX,KAAK,IAAI,QAAQ,QAAQ,cAAc,SAAS,GAAG,SAAS,GAAG,SAAS;EACtE,MAAM,kBAAkB,QAAQ,iBAAiB,QAAQ,cAAc,OAAO;EAC9E,IAAI,CAAC,iBACH;EAGF,MAAM,eAAe,QAAQ,sBAAsB,QAAQ,oBAAoB,SAAS;EACxF,MAAM,cAAc,QAAQ,mBAC1B,4BAA4B,QAAQ,eAAe,cAAc,QAAQ,cAAc,CACxF;EACD,UAAU,QAAQ,aAAa,iBAAiB,SAAS,YAAY;EAErE,IACE,QAAQ,gBACR,QAAQ,+BACR,QAAQ,sBACR;GACA,MAAM,gBAAgB,QAAQ,qBAC5B,QAAQ,iBAAiB,EAAE,EAC3B,cACA,QAAQ,cACT;GACD,UAAU,QAAQ,4BAA4B,EAAE,UAAU,eAAe,EAAE,QAAQ;;;CAKzF,IAAI,QAAQ,gBAAgB,QAAQ,8BAA8B,QAAQ,sBACxE,UAAU,QAAQ,oBAAoB,QAAQ,sBAAsB,QAAQ;CAG9E,OAAO;;AAGT,eAAsB,8BACpB,SACmB;CAKnB,MAAM,YAAY,yBAChB,QAAQ,uBAAuB,QAAQ,SAAS,EAC9C,SAAS,QAAQ,yBAAyB,EAC3C,CAAC,CACH;CAED,IAAI,QAAQ,cAAc;EAIxB,MAAM,UAAU,IAAI,QAAQ;GAC1B,gBAAgB;GAChB,MAAM;GACP,CAAC;EACF,uBAAuB,SAAS,QAAQ,cAAc;EACtD,+BAA+B,SAAS,QAAQ,qBAAqB,KAAK;EAC1E,8BAA8B,QAAQ;EAEtC,OAAO,IAAI,SAAS,WAAW;GAC7B,QAAQ,QAAQ;GAChB;GACD,CAAC;;CAGJ,OAAO,QAAQ,mBAAmB,WAAW,QAAQ,OAAO"}
1
+ {"version":3,"file":"app-page-boundary.js","names":[],"sources":["../../src/server/app-page-boundary.ts"],"sourcesContent":["import { runWithFetchDedupe } from \"vinext/shims/fetch-cache\";\nimport { applyEdgeRuntimeHeader } from \"./app-page-response.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport {\n VINEXT_RSC_CONTENT_TYPE,\n VINEXT_RSC_VARY_HEADER,\n applyRscCompatibilityIdHeader,\n} from \"./app-rsc-cache-busting.js\";\nimport { resolveAppPageSegmentParams } from \"./app-page-params.js\";\n\nexport type AppPageParams = Record<string, string | string[]>;\n\ntype ResolveAppPageHttpAccessBoundaryComponentOptions<TModule, TComponent> = {\n getDefaultExport: (module: TModule | null | undefined) => TComponent | null | undefined;\n rootForbiddenModule?: TModule | null;\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n routeForbiddenModule?: TModule | null;\n routeNotFoundModule?: TModule | null;\n routeUnauthorizedModule?: TModule | null;\n statusCode: number;\n};\n\ntype ResolveAppPageParentHttpAccessBoundaryModuleOptions<TModule> = {\n layoutIndex: number;\n rootForbiddenModule?: TModule | null;\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n routeForbiddenModules?: readonly (TModule | null | undefined)[] | null;\n routeNotFoundModules?: readonly (TModule | null | undefined)[] | null;\n routeUnauthorizedModules?: readonly (TModule | null | undefined)[] | null;\n statusCode: number;\n};\n\ntype ResolveAppPageErrorBoundaryOptions<TModule, TComponent> = {\n getDefaultExport: (module: TModule | null | undefined) => TComponent | null | undefined;\n globalErrorModule?: TModule | null;\n errorModules?: readonly (TModule | null | undefined)[] | null;\n layoutErrorModules?: readonly (TModule | null | undefined)[] | null;\n pageErrorModule?: TModule | null;\n};\n\ntype ResolveAppPageErrorBoundaryResult<TComponent> = {\n component: TComponent | null;\n isGlobalError: boolean;\n};\n\ntype WrapAppPageBoundaryElementOptions<\n TElement,\n TLayoutModule,\n TLayoutComponent,\n TChildSegments,\n TGlobalErrorComponent,\n> = {\n element: TElement;\n getDefaultExport: (\n module: TLayoutModule | null | undefined,\n ) => TLayoutComponent | null | undefined;\n globalErrorComponent?: TGlobalErrorComponent | null;\n includeGlobalErrorBoundary: boolean;\n isRscRequest: boolean;\n layoutModules: readonly (TLayoutModule | null | undefined)[];\n layoutTreePositions?: readonly number[] | null;\n makeThenableParams: (params: AppPageParams) => unknown;\n matchedParams: AppPageParams;\n renderErrorBoundary: (component: TGlobalErrorComponent, children: TElement) => TElement;\n renderLayout: (component: TLayoutComponent, children: TElement, params: unknown) => TElement;\n renderLayoutSegmentProvider?: (\n segmentMap: { children: TChildSegments },\n children: TElement,\n ) => TElement;\n resolveChildSegments?: (\n routeSegments: readonly string[],\n treePosition: number,\n params: AppPageParams,\n ) => TChildSegments;\n routeSegments?: readonly string[];\n skipLayoutWrapping?: boolean;\n};\n\ntype AppPageBoundaryOnError = (\n error: unknown,\n requestInfo: unknown,\n errorContext: unknown,\n) => unknown;\n\ntype RenderAppPageBoundaryResponseOptions<TElement> = {\n createHtmlResponse: (rscStream: ReadableStream<Uint8Array>, status: number) => Promise<Response>;\n createRscOnErrorHandler: () => AppPageBoundaryOnError;\n element: TElement;\n isEdgeRuntime?: boolean;\n isRscRequest: boolean;\n middlewareHeaders?: Headers | null;\n renderToReadableStream: (\n element: TElement,\n options: { onError: AppPageBoundaryOnError },\n ) => ReadableStream<Uint8Array>;\n status: number;\n};\n\nexport function resolveAppPageHttpAccessBoundaryComponent<TModule, TComponent>(\n options: ResolveAppPageHttpAccessBoundaryComponentOptions<TModule, TComponent>,\n): TComponent | null {\n let boundaryModule: TModule | null | undefined;\n\n if (options.statusCode === 403) {\n boundaryModule = options.routeForbiddenModule ?? options.rootForbiddenModule;\n } else if (options.statusCode === 401) {\n boundaryModule = options.routeUnauthorizedModule ?? options.rootUnauthorizedModule;\n } else {\n boundaryModule = options.routeNotFoundModule ?? options.rootNotFoundModule;\n }\n\n return options.getDefaultExport(boundaryModule) ?? null;\n}\n\nexport function resolveAppPageParentHttpAccessBoundaryModule<TModule>(\n options: ResolveAppPageParentHttpAccessBoundaryModuleOptions<TModule>,\n): TModule | null {\n return resolveAppPageParentHttpAccessBoundary(options).module;\n}\n\n/**\n * Like {@link resolveAppPageParentHttpAccessBoundaryModule}, but also returns\n * the layout index that owns the resolved boundary so callers can slice the\n * layouts array to skip rendering layouts below the boundary owner.\n *\n * `layoutIndex` is the per-layout index where the boundary lives, or `null` if\n * the resolved boundary is the root module (which conceptually sits above all\n * layouts when no layout-level boundary is present).\n *\n * Used by the page-error fast path to make `forbidden()` / `unauthorized()` /\n * `notFound()` escalate past intermediate layouts that lack a boundary file,\n * matching Next.js's `create-component-tree.tsx` behavior where the nearest\n * ancestor boundary owns the fallback subtree.\n *\n * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-component-tree.tsx\n */\nexport function resolveAppPageParentHttpAccessBoundary<TModule>(\n options: ResolveAppPageParentHttpAccessBoundaryModuleOptions<TModule>,\n): { module: TModule | null; layoutIndex: number | null } {\n let routeModules = options.routeNotFoundModules;\n let rootModule = options.rootNotFoundModule;\n\n if (options.statusCode === 403) {\n routeModules = options.routeForbiddenModules;\n rootModule = options.rootForbiddenModule;\n } else if (options.statusCode === 401) {\n routeModules = options.routeUnauthorizedModules;\n rootModule = options.rootUnauthorizedModule;\n }\n\n if (routeModules) {\n for (let index = options.layoutIndex - 1; index >= 0; index--) {\n const module = routeModules[index];\n if (module) {\n return { module, layoutIndex: index };\n }\n }\n }\n\n return { module: rootModule ?? null, layoutIndex: null };\n}\n\nexport function resolveAppPageErrorBoundary<TModule, TComponent>(\n options: ResolveAppPageErrorBoundaryOptions<TModule, TComponent>,\n): ResolveAppPageErrorBoundaryResult<TComponent> {\n const pageErrorComponent = options.getDefaultExport(options.pageErrorModule);\n if (pageErrorComponent) {\n return {\n component: pageErrorComponent,\n isGlobalError: false,\n };\n }\n\n const segmentErrorModules = options.errorModules ?? options.layoutErrorModules;\n if (segmentErrorModules) {\n for (let index = segmentErrorModules.length - 1; index >= 0; index--) {\n const segmentErrorComponent = options.getDefaultExport(segmentErrorModules[index]);\n if (segmentErrorComponent) {\n return {\n component: segmentErrorComponent,\n isGlobalError: false,\n };\n }\n }\n }\n\n const globalErrorComponent = options.getDefaultExport(options.globalErrorModule);\n return {\n component: globalErrorComponent ?? null,\n isGlobalError: Boolean(globalErrorComponent),\n };\n}\n\nexport function wrapAppPageBoundaryElement<\n TElement,\n TLayoutModule,\n TLayoutComponent,\n TChildSegments,\n TGlobalErrorComponent,\n>(\n options: WrapAppPageBoundaryElementOptions<\n TElement,\n TLayoutModule,\n TLayoutComponent,\n TChildSegments,\n TGlobalErrorComponent\n >,\n): TElement {\n let element = options.element;\n\n if (!options.skipLayoutWrapping) {\n for (let index = options.layoutModules.length - 1; index >= 0; index--) {\n const layoutComponent = options.getDefaultExport(options.layoutModules[index]);\n if (!layoutComponent) {\n continue;\n }\n\n const treePosition = options.layoutTreePositions ? options.layoutTreePositions[index] : 0;\n const asyncParams = options.makeThenableParams(\n resolveAppPageSegmentParams(options.routeSegments, treePosition, options.matchedParams),\n );\n element = options.renderLayout(layoutComponent, element, asyncParams);\n\n if (\n options.isRscRequest &&\n options.renderLayoutSegmentProvider &&\n options.resolveChildSegments\n ) {\n const childSegments = options.resolveChildSegments(\n options.routeSegments ?? [],\n treePosition,\n options.matchedParams,\n );\n element = options.renderLayoutSegmentProvider({ children: childSegments }, element);\n }\n }\n }\n\n if (options.isRscRequest && options.includeGlobalErrorBoundary && options.globalErrorComponent) {\n element = options.renderErrorBoundary(options.globalErrorComponent, element);\n }\n\n return element;\n}\n\nexport async function renderAppPageBoundaryResponse<TElement>(\n options: RenderAppPageBoundaryResponseOptions<TElement>,\n): Promise<Response> {\n // Defensive wrap for standalone callers; idempotent under dispatchAppPage.\n // The async stream consumption that follows relies on the surrounding\n // runWithRequestContext to keep ALS state alive after this synchronous call\n // returns. See app-page-render.ts for the same pattern.\n const rscStream = runWithFetchDedupe(() =>\n options.renderToReadableStream(options.element, {\n onError: options.createRscOnErrorHandler(),\n }),\n );\n\n if (options.isRscRequest) {\n // Do NOT clear request-scoped context here. RSC responses are consumed lazily\n // by the client, so headers()/cookies() and async server components still need\n // their ALS-backed state while the stream is being read.\n const headers = new Headers({\n \"Content-Type\": VINEXT_RSC_CONTENT_TYPE,\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);\n mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);\n applyRscCompatibilityIdHeader(headers);\n\n return new Response(rscStream, {\n status: options.status,\n headers,\n });\n }\n\n return options.createHtmlResponse(rscStream, options.status);\n}\n"],"mappings":";;;;;;AAoGA,SAAgB,0CACd,SACmB;CACnB,IAAI;CAEJ,IAAI,QAAQ,eAAe,KACzB,iBAAiB,QAAQ,wBAAwB,QAAQ;MACpD,IAAI,QAAQ,eAAe,KAChC,iBAAiB,QAAQ,2BAA2B,QAAQ;MAE5D,iBAAiB,QAAQ,uBAAuB,QAAQ;CAG1D,OAAO,QAAQ,iBAAiB,eAAe,IAAI;;AAGrD,SAAgB,6CACd,SACgB;CAChB,OAAO,uCAAuC,QAAQ,CAAC;;;;;;;;;;;;;;;;;;AAmBzD,SAAgB,uCACd,SACwD;CACxD,IAAI,eAAe,QAAQ;CAC3B,IAAI,aAAa,QAAQ;CAEzB,IAAI,QAAQ,eAAe,KAAK;EAC9B,eAAe,QAAQ;EACvB,aAAa,QAAQ;QAChB,IAAI,QAAQ,eAAe,KAAK;EACrC,eAAe,QAAQ;EACvB,aAAa,QAAQ;;CAGvB,IAAI,cACF,KAAK,IAAI,QAAQ,QAAQ,cAAc,GAAG,SAAS,GAAG,SAAS;EAC7D,MAAM,SAAS,aAAa;EAC5B,IAAI,QACF,OAAO;GAAE;GAAQ,aAAa;GAAO;;CAK3C,OAAO;EAAE,QAAQ,cAAc;EAAM,aAAa;EAAM;;AAG1D,SAAgB,4BACd,SAC+C;CAC/C,MAAM,qBAAqB,QAAQ,iBAAiB,QAAQ,gBAAgB;CAC5E,IAAI,oBACF,OAAO;EACL,WAAW;EACX,eAAe;EAChB;CAGH,MAAM,sBAAsB,QAAQ,gBAAgB,QAAQ;CAC5D,IAAI,qBACF,KAAK,IAAI,QAAQ,oBAAoB,SAAS,GAAG,SAAS,GAAG,SAAS;EACpE,MAAM,wBAAwB,QAAQ,iBAAiB,oBAAoB,OAAO;EAClF,IAAI,uBACF,OAAO;GACL,WAAW;GACX,eAAe;GAChB;;CAKP,MAAM,uBAAuB,QAAQ,iBAAiB,QAAQ,kBAAkB;CAChF,OAAO;EACL,WAAW,wBAAwB;EACnC,eAAe,QAAQ,qBAAqB;EAC7C;;AAGH,SAAgB,2BAOd,SAOU;CACV,IAAI,UAAU,QAAQ;CAEtB,IAAI,CAAC,QAAQ,oBACX,KAAK,IAAI,QAAQ,QAAQ,cAAc,SAAS,GAAG,SAAS,GAAG,SAAS;EACtE,MAAM,kBAAkB,QAAQ,iBAAiB,QAAQ,cAAc,OAAO;EAC9E,IAAI,CAAC,iBACH;EAGF,MAAM,eAAe,QAAQ,sBAAsB,QAAQ,oBAAoB,SAAS;EACxF,MAAM,cAAc,QAAQ,mBAC1B,4BAA4B,QAAQ,eAAe,cAAc,QAAQ,cAAc,CACxF;EACD,UAAU,QAAQ,aAAa,iBAAiB,SAAS,YAAY;EAErE,IACE,QAAQ,gBACR,QAAQ,+BACR,QAAQ,sBACR;GACA,MAAM,gBAAgB,QAAQ,qBAC5B,QAAQ,iBAAiB,EAAE,EAC3B,cACA,QAAQ,cACT;GACD,UAAU,QAAQ,4BAA4B,EAAE,UAAU,eAAe,EAAE,QAAQ;;;CAKzF,IAAI,QAAQ,gBAAgB,QAAQ,8BAA8B,QAAQ,sBACxE,UAAU,QAAQ,oBAAoB,QAAQ,sBAAsB,QAAQ;CAG9E,OAAO;;AAGT,eAAsB,8BACpB,SACmB;CAKnB,MAAM,YAAY,yBAChB,QAAQ,uBAAuB,QAAQ,SAAS,EAC9C,SAAS,QAAQ,yBAAyB,EAC3C,CAAC,CACH;CAED,IAAI,QAAQ,cAAc;EAIxB,MAAM,UAAU,IAAI,QAAQ;GAC1B,gBAAgB;GAChB,MAAM;GACP,CAAC;EACF,uBAAuB,SAAS,QAAQ,cAAc;EACtD,+BAA+B,SAAS,QAAQ,qBAAqB,KAAK;EAC1E,8BAA8B,QAAQ;EAEtC,OAAO,IAAI,SAAS,WAAW;GAC7B,QAAQ,QAAQ;GAChB;GACD,CAAC;;CAGJ,OAAO,QAAQ,mBAAmB,WAAW,QAAQ,OAAO"}
@@ -9,6 +9,7 @@ type AppPageDebugLogger = (event: string, detail: string) => void;
9
9
  type AppPageCacheGetter = (key: string) => Promise<ISRCacheEntry | null>;
10
10
  type AppPageCacheSetter = (key: string, data: CachedAppPageValue, revalidateSeconds: number, tags: string[], expireSeconds?: number) => Promise<void>;
11
11
  type AppPageBackgroundRegenerator = (key: string, renderFn: () => Promise<void>) => void;
12
+ type AppPageRscCacheKeyBuilder = (pathname: string, mountedSlotsHeader?: string | null, renderMode?: AppRscRenderMode, interceptionContext?: string | null) => string;
12
13
  type AppPageRequestCacheLife = {
13
14
  revalidate?: number;
14
15
  expire?: number;
@@ -55,8 +56,9 @@ type ReadAppPageCacheResponseOptions = {
55
56
  isrDebug?: AppPageDebugLogger;
56
57
  isrGet: AppPageCacheGetter;
57
58
  isrHtmlKey: (pathname: string) => string;
58
- isrRscKey: (pathname: string, mountedSlotsHeader?: string | null, renderMode?: AppRscRenderMode) => string;
59
+ isrRscKey: AppPageRscCacheKeyBuilder;
59
60
  isrSet: AppPageCacheSetter;
61
+ interceptionContext?: string | null;
60
62
  middlewareHeaders?: Headers | null;
61
63
  middlewareStatus?: number | null;
62
64
  mountedSlotsHeader?: string | null;
@@ -79,8 +81,9 @@ type FinalizeAppPageHtmlCacheResponseOptions = {
79
81
  getRequestCacheLife?: () => AppPageRequestCacheLife | null;
80
82
  isrDebug?: AppPageDebugLogger;
81
83
  isrHtmlKey: (pathname: string) => string;
82
- isrRscKey: (pathname: string, mountedSlotsHeader?: string | null, renderMode?: AppRscRenderMode) => string;
84
+ isrRscKey: AppPageRscCacheKeyBuilder;
83
85
  isrSet: AppPageCacheSetter;
86
+ interceptionContext?: string | null;
84
87
  preserveClientResponseHeaders?: boolean;
85
88
  expireSeconds?: number;
86
89
  revalidateSeconds: number | null;
@@ -96,8 +99,9 @@ type ScheduleAppPageRscCacheWriteOptions = {
96
99
  getPageTags: () => string[];
97
100
  getRequestCacheLife?: () => AppPageRequestCacheLife | null;
98
101
  isrDebug?: AppPageDebugLogger;
99
- isrRscKey: (pathname: string, mountedSlotsHeader?: string | null, renderMode?: AppRscRenderMode) => string;
102
+ isrRscKey: AppPageRscCacheKeyBuilder;
100
103
  isrSet: AppPageCacheSetter;
104
+ interceptionContext?: string | null;
101
105
  mountedSlotsHeader?: string | null;
102
106
  renderMode?: AppRscRenderMode;
103
107
  preserveClientResponseHeaders?: boolean;
@@ -3,10 +3,10 @@ import { setCacheStateHeaders } from "./cache-headers.js";
3
3
  import { encodeCacheTag } from "../utils/encode-cache-tag.js";
4
4
  import { buildAppPageCacheValue } from "./isr-cache.js";
5
5
  import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
6
+ import { readStreamAsText } from "../utils/text-stream.js";
6
7
  import { buildCachedRevalidateCacheControl } from "./cache-control.js";
7
8
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
8
9
  import { applyEdgeRuntimeHeader } from "./app-page-response.js";
9
- import { readStreamAsText } from "../utils/text-stream.js";
10
10
  import { createEmptyAppPageRenderObservationState } from "./app-page-render-observation.js";
11
11
  //#region src/server/app-page-cache.ts
12
12
  const NO_STORE_CACHE_CONTROL = "no-store, must-revalidate";
@@ -58,7 +58,7 @@ function resolveAppPageCacheWritePolicy(options) {
58
58
  const requestCacheLife = options.requestCacheLife;
59
59
  if (requestCacheLife?.revalidate !== void 0) revalidateSeconds = revalidateSeconds === null ? requestCacheLife.revalidate : Math.min(revalidateSeconds, requestCacheLife.revalidate);
60
60
  if (requestCacheLife?.expire !== void 0) expireSeconds = requestCacheLife.expire;
61
- if (revalidateSeconds === null || revalidateSeconds <= 0 || !Number.isFinite(revalidateSeconds)) return null;
61
+ if (revalidateSeconds === null || Number.isNaN(revalidateSeconds) || revalidateSeconds <= 0) return null;
62
62
  return {
63
63
  expireSeconds,
64
64
  revalidateSeconds
@@ -99,7 +99,7 @@ function buildAppPageCachedResponse(cachedValue, options) {
99
99
  });
100
100
  }
101
101
  async function readAppPageCacheResponse(options) {
102
- const isrKey = options.isRscRequest ? options.isrRscKey(options.cleanPathname, options.mountedSlotsHeader, options.renderMode) : options.isrHtmlKey(options.cleanPathname);
102
+ const isrKey = options.isRscRequest ? options.isrRscKey(options.cleanPathname, options.mountedSlotsHeader, options.renderMode, options.interceptionContext) : options.isrHtmlKey(options.cleanPathname);
103
103
  const artifact = options.isRscRequest ? "rsc" : "html";
104
104
  try {
105
105
  const cached = await options.isrGet(isrKey);
@@ -146,12 +146,12 @@ async function readAppPageCacheResponse(options) {
146
146
  options.isrDebug?.("MISS (empty cached entry)", options.cleanPathname);
147
147
  }
148
148
  if (cached?.isStale && cachedValue) {
149
- const regenerationKey = options.isRscRequest ? options.isrRscKey(options.cleanPathname, options.mountedSlotsHeader, options.renderMode) : options.isrHtmlKey(options.cleanPathname);
149
+ const regenerationKey = options.isRscRequest ? options.isrRscKey(options.cleanPathname, options.mountedSlotsHeader, options.renderMode, options.interceptionContext) : options.isrHtmlKey(options.cleanPathname);
150
150
  options.scheduleBackgroundRegeneration(regenerationKey, async () => {
151
151
  const revalidatedPage = await options.renderFreshPageForCache();
152
152
  const revalidateSeconds = revalidatedPage.cacheControl?.revalidate ?? options.revalidateSeconds;
153
153
  const expireSeconds = revalidatedPage.cacheControl?.expire ?? options.expireSeconds;
154
- const writes = [options.isrSet(options.isrRscKey(options.cleanPathname, options.mountedSlotsHeader, options.renderMode), buildAppPageCacheValue("", revalidatedPage.rscData, 200, revalidatedPage.rscRenderObservation), revalidateSeconds, revalidatedPage.tags, expireSeconds)];
154
+ const writes = [options.isrSet(options.isrRscKey(options.cleanPathname, options.mountedSlotsHeader, options.renderMode, options.interceptionContext), buildAppPageCacheValue("", revalidatedPage.rscData, 200, revalidatedPage.rscRenderObservation), revalidateSeconds, revalidatedPage.tags, expireSeconds)];
155
155
  if (!options.isRscRequest) writes.push(options.isrSet(options.isrHtmlKey(options.cleanPathname), buildAppPageCacheValue(revalidatedPage.html, void 0, 200, revalidatedPage.htmlRenderObservation), revalidateSeconds, revalidatedPage.tags, expireSeconds));
156
156
  await Promise.all(writes);
157
157
  options.isrDebug?.("regen complete", options.cleanPathname);
@@ -210,7 +210,7 @@ function finalizeAppPageHtmlCacheResponse(response, options) {
210
210
  if (!response.body) return response;
211
211
  const [streamForClient, streamForCache] = response.body.tee();
212
212
  const htmlKey = options.isrHtmlKey(options.cleanPathname);
213
- const rscKey = options.isrRscKey(options.cleanPathname, null);
213
+ const rscKey = options.isrRscKey(options.cleanPathname, null, void 0, options.interceptionContext);
214
214
  const clientHeaders = new Headers(response.headers);
215
215
  if (options.preserveClientResponseHeaders !== true) {
216
216
  clientHeaders.set("Cache-Control", NO_STORE_CACHE_CONTROL);
@@ -272,7 +272,7 @@ function finalizeAppPageRscCacheResponse(response, options) {
272
272
  function scheduleAppPageRscCacheWrite(options) {
273
273
  const capturedRscDataPromise = options.capturedRscDataPromise;
274
274
  if (!capturedRscDataPromise || options.dynamicUsedDuringBuild) return false;
275
- const rscKey = options.isrRscKey(options.cleanPathname, options.mountedSlotsHeader, options.renderMode);
275
+ const rscKey = options.isrRscKey(options.cleanPathname, options.mountedSlotsHeader, options.renderMode, options.interceptionContext);
276
276
  const cachePromise = (async () => {
277
277
  try {
278
278
  const rscData = await capturedRscDataPromise;
@@ -1 +1 @@
1
- {"version":3,"file":"app-page-cache.js","names":[],"sources":["../../src/server/app-page-cache.ts"],"sourcesContent":["import type { CachedAppPageValue, CacheControlMetadata } from \"vinext/shims/cache\";\nimport {\n VINEXT_RSC_CONTENT_TYPE,\n VINEXT_RSC_VARY_HEADER,\n applyRscCompatibilityIdHeader,\n} from \"./app-rsc-cache-busting.js\";\nimport { buildCachedRevalidateCacheControl } from \"./cache-control.js\";\nimport { VINEXT_MOUNTED_SLOTS_HEADER } from \"./headers.js\";\nimport { applyEdgeRuntimeHeader } from \"./app-page-response.js\";\nimport { setCacheStateHeaders } from \"./cache-headers.js\";\nimport { buildAppPageCacheValue, type ISRCacheEntry } from \"./isr-cache.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport { readStreamAsText } from \"../utils/text-stream.js\";\nimport { encodeCacheTag } from \"../utils/encode-cache-tag.js\";\nimport type { AppRscRenderMode } from \"./app-rsc-render-mode.js\";\nimport {\n createEmptyAppPageRenderObservationState,\n type AppPageRenderObservationState,\n} from \"./app-page-render-observation.js\";\nimport type { RenderObservation } from \"./cache-proof.js\";\n\ntype AppPageDebugLogger = (event: string, detail: string) => void;\ntype AppPageCacheGetter = (key: string) => Promise<ISRCacheEntry | null>;\ntype AppPageCacheSetter = (\n key: string,\n data: CachedAppPageValue,\n revalidateSeconds: number,\n tags: string[],\n expireSeconds?: number,\n) => Promise<void>;\ntype AppPageBackgroundRegenerator = (key: string, renderFn: () => Promise<void>) => void;\ntype AppPageRequestCacheLife = {\n revalidate?: number;\n expire?: number;\n};\nexport type AppPageCacheOutcomeMetric = Readonly<{\n artifact: \"html\" | \"rsc\";\n /**\n * Internal cache lookup key for debugging and tests. Runtime telemetry sinks should hash or\n * redact this value before export to avoid high-cardinality or user-derived labels.\n */\n cacheKey: string;\n outcome: \"hit\" | \"miss\" | \"stale\";\n reason:\n | \"empty-entry\"\n | \"no-entry\"\n | \"non-app-page-entry\"\n | \"read-error\"\n | \"served\"\n | \"stale-empty-entry\";\n}>;\ntype AppPageCacheOutcomeRecorder = (metric: AppPageCacheOutcomeMetric) => void;\n\ntype BuildAppPageCacheRenderObservation = (input: {\n cacheTags: readonly string[];\n state: AppPageRenderObservationState;\n}) => RenderObservation;\n\ntype AppPageCacheRenderResult = {\n cacheControl?: CacheControlMetadata;\n html: string;\n htmlRenderObservation?: RenderObservation;\n rscData: ArrayBuffer;\n rscRenderObservation?: RenderObservation;\n tags: string[];\n};\n\ntype BuildAppPageCachedResponseOptions = {\n cacheControl?: CacheControlMetadata;\n cacheState: \"HIT\" | \"STALE\";\n expireSeconds?: number;\n isEdgeRuntime?: boolean;\n isRscRequest: boolean;\n middlewareHeaders?: Headers | null;\n middlewareStatus?: number | null;\n mountedSlotsHeader?: string | null;\n revalidateSeconds: number;\n};\n\ntype ReadAppPageCacheResponseOptions = {\n cleanPathname: string;\n clearRequestContext: () => void;\n isEdgeRuntime?: boolean;\n isRscRequest: boolean;\n isrDebug?: AppPageDebugLogger;\n isrGet: AppPageCacheGetter;\n isrHtmlKey: (pathname: string) => string;\n isrRscKey: (\n pathname: string,\n mountedSlotsHeader?: string | null,\n renderMode?: AppRscRenderMode,\n ) => string;\n isrSet: AppPageCacheSetter;\n middlewareHeaders?: Headers | null;\n middlewareStatus?: number | null;\n mountedSlotsHeader?: string | null;\n recordCacheOutcome?: AppPageCacheOutcomeRecorder;\n renderMode?: AppRscRenderMode;\n expireSeconds?: number;\n revalidateSeconds: number;\n renderFreshPageForCache: () => Promise<AppPageCacheRenderResult>;\n scheduleBackgroundRegeneration: AppPageBackgroundRegenerator;\n};\n\ntype FinalizeAppPageHtmlCacheResponseOptions = {\n capturedDynamicUsageBeforeContextCleanup?: () => boolean;\n capturedRscDataPromise: Promise<ArrayBuffer> | null;\n cleanPathname: string;\n consumeDynamicUsage: () => boolean;\n consumeRenderObservationState?: () => AppPageRenderObservationState;\n createHtmlRenderObservation?: BuildAppPageCacheRenderObservation;\n createRscRenderObservation?: BuildAppPageCacheRenderObservation;\n getPageTags: () => string[];\n getRequestCacheLife?: () => AppPageRequestCacheLife | null;\n isrDebug?: AppPageDebugLogger;\n isrHtmlKey: (pathname: string) => string;\n isrRscKey: (\n pathname: string,\n mountedSlotsHeader?: string | null,\n renderMode?: AppRscRenderMode,\n ) => string;\n isrSet: AppPageCacheSetter;\n preserveClientResponseHeaders?: boolean;\n expireSeconds?: number;\n revalidateSeconds: number | null;\n waitUntil?: (promise: Promise<void>) => void;\n};\n\ntype ScheduleAppPageRscCacheWriteOptions = {\n capturedRscDataPromise: Promise<ArrayBuffer> | null;\n cleanPathname: string;\n consumeDynamicUsage: () => boolean;\n consumeRenderObservationState?: () => AppPageRenderObservationState;\n createRscRenderObservation?: BuildAppPageCacheRenderObservation;\n dynamicUsedDuringBuild: boolean;\n getPageTags: () => string[];\n getRequestCacheLife?: () => AppPageRequestCacheLife | null;\n isrDebug?: AppPageDebugLogger;\n isrRscKey: (\n pathname: string,\n mountedSlotsHeader?: string | null,\n renderMode?: AppRscRenderMode,\n ) => string;\n isrSet: AppPageCacheSetter;\n mountedSlotsHeader?: string | null;\n renderMode?: AppRscRenderMode;\n preserveClientResponseHeaders?: boolean;\n expireSeconds?: number;\n revalidateSeconds: number | null;\n waitUntil?: (promise: Promise<void>) => void;\n};\n\nconst NO_STORE_CACHE_CONTROL = \"no-store, must-revalidate\";\n\nfunction recordAppPageCacheOutcome(\n recordCacheOutcome: AppPageCacheOutcomeRecorder | undefined,\n input: AppPageCacheOutcomeMetric,\n): void {\n try {\n recordCacheOutcome?.(input);\n } catch {\n // Metrics are observational only; telemetry failures must not alter cache serving behavior.\n }\n}\n\nexport function buildAppPageCacheTags(pathname: string, extraTags: readonly string[]): string[] {\n const tags = [pathname, `_N_T_${pathname}`, \"_N_T_/layout\"];\n const segments = pathname.split(\"/\");\n let built = \"\";\n for (let index = 1; index < segments.length; index++) {\n const segment = segments[index];\n if (segment) {\n built += `/${segment}`;\n tags.push(`_N_T_${built}/layout`);\n }\n }\n\n tags.push(`_N_T_${built}/page`);\n for (const tag of extraTags) {\n if (!tags.includes(tag)) {\n tags.push(tag);\n }\n }\n // Canonicalise to ASCII-safe form so path-derived tags from non-ASCII\n // pathnames match what `revalidatePath`/`revalidateTag` produce after\n // their own encoding pass.\n return tags.map(encodeCacheTag);\n}\n\nfunction buildAppPageCacheControl(\n cacheState: BuildAppPageCachedResponseOptions[\"cacheState\"],\n revalidateSeconds: number,\n expireSeconds?: number,\n): string {\n return buildCachedRevalidateCacheControl(cacheState, revalidateSeconds, expireSeconds);\n}\n\nfunction buildAppPageCachedHeaders(options: {\n cacheControl: string;\n cacheState: BuildAppPageCachedResponseOptions[\"cacheState\"];\n contentType: string;\n isEdgeRuntime?: boolean;\n middlewareHeaders?: Headers | null;\n mountedSlotsHeader?: string | null;\n}): Headers {\n const headers = new Headers({\n \"Cache-Control\": options.cacheControl,\n \"Content-Type\": options.contentType,\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n setCacheStateHeaders(headers, options.cacheState);\n applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);\n\n if (options.mountedSlotsHeader) {\n headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);\n }\n\n mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);\n return headers;\n}\n\nfunction getCachedAppPageValue(entry: ISRCacheEntry | null): CachedAppPageValue | null {\n return entry?.value.value && entry.value.value.kind === \"APP_PAGE\" ? entry.value.value : null;\n}\n\nfunction resolveAppPageCacheWritePolicy(options: {\n expireSeconds?: number;\n requestCacheLife?: AppPageRequestCacheLife | null;\n revalidateSeconds: number | null;\n}): { expireSeconds?: number; revalidateSeconds: number } | null {\n let revalidateSeconds = options.revalidateSeconds;\n let expireSeconds = options.expireSeconds;\n const requestCacheLife = options.requestCacheLife;\n\n if (requestCacheLife?.revalidate !== undefined) {\n revalidateSeconds =\n revalidateSeconds === null\n ? requestCacheLife.revalidate\n : Math.min(revalidateSeconds, requestCacheLife.revalidate);\n }\n if (requestCacheLife?.expire !== undefined) {\n expireSeconds = requestCacheLife.expire;\n }\n\n if (revalidateSeconds === null || revalidateSeconds <= 0 || !Number.isFinite(revalidateSeconds)) {\n return null;\n }\n\n return { expireSeconds, revalidateSeconds };\n}\n\nexport function buildAppPageCachedResponse(\n cachedValue: CachedAppPageValue,\n options: BuildAppPageCachedResponseOptions,\n): Response | null {\n // Preserve the legacy fallback semantics from the generated entry: invalid\n // falsy statuses still fall back to 200 rather than being forwarded through.\n const status = options.middlewareStatus ?? (cachedValue.status || 200);\n const revalidateSeconds = options.cacheControl?.revalidate ?? options.revalidateSeconds;\n const expireSeconds =\n options.cacheControl === undefined\n ? undefined\n : (options.cacheControl.expire ?? options.expireSeconds);\n const cacheControl = buildAppPageCacheControl(\n options.cacheState,\n revalidateSeconds,\n expireSeconds,\n );\n if (options.isRscRequest) {\n if (!cachedValue.rscData) {\n return null;\n }\n\n const rscHeaders = buildAppPageCachedHeaders({\n cacheControl,\n cacheState: options.cacheState,\n contentType: VINEXT_RSC_CONTENT_TYPE,\n isEdgeRuntime: options.isEdgeRuntime,\n middlewareHeaders: options.middlewareHeaders,\n mountedSlotsHeader: options.mountedSlotsHeader,\n });\n applyRscCompatibilityIdHeader(rscHeaders);\n\n return new Response(cachedValue.rscData, {\n status,\n headers: rscHeaders,\n });\n }\n\n if (typeof cachedValue.html !== \"string\" || cachedValue.html.length === 0) {\n return null;\n }\n\n const htmlHeaders = buildAppPageCachedHeaders({\n cacheControl,\n cacheState: options.cacheState,\n contentType: \"text/html; charset=utf-8\",\n isEdgeRuntime: options.isEdgeRuntime,\n middlewareHeaders: options.middlewareHeaders,\n });\n\n return new Response(cachedValue.html, {\n status,\n headers: htmlHeaders,\n });\n}\n\nexport async function readAppPageCacheResponse(\n options: ReadAppPageCacheResponseOptions,\n): Promise<Response | null> {\n const isrKey = options.isRscRequest\n ? options.isrRscKey(options.cleanPathname, options.mountedSlotsHeader, options.renderMode)\n : options.isrHtmlKey(options.cleanPathname);\n const artifact = options.isRscRequest ? \"rsc\" : \"html\";\n\n try {\n const cached = await options.isrGet(isrKey);\n const cachedValue = getCachedAppPageValue(cached);\n\n if (cached && !cachedValue) {\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"miss\",\n reason: \"non-app-page-entry\",\n });\n options.isrDebug?.(\"MISS (non app-page cache entry)\", options.cleanPathname);\n return null;\n }\n\n if (cachedValue && !cached?.isStale) {\n const hitResponse = buildAppPageCachedResponse(cachedValue, {\n cacheState: \"HIT\",\n cacheControl: cached?.value.cacheControl,\n expireSeconds: options.expireSeconds,\n isEdgeRuntime: options.isEdgeRuntime,\n isRscRequest: options.isRscRequest,\n middlewareHeaders: options.middlewareHeaders,\n middlewareStatus: options.middlewareStatus,\n mountedSlotsHeader: options.mountedSlotsHeader,\n revalidateSeconds: options.revalidateSeconds,\n });\n\n if (hitResponse) {\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"hit\",\n reason: \"served\",\n });\n options.isrDebug?.(\n options.isRscRequest ? \"HIT (RSC)\" : \"HIT (HTML)\",\n options.cleanPathname,\n );\n options.clearRequestContext();\n return hitResponse;\n }\n\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"miss\",\n reason: \"empty-entry\",\n });\n options.isrDebug?.(\"MISS (empty cached entry)\", options.cleanPathname);\n }\n\n if (cached?.isStale && cachedValue) {\n const regenerationKey = options.isRscRequest\n ? options.isrRscKey(options.cleanPathname, options.mountedSlotsHeader, options.renderMode)\n : options.isrHtmlKey(options.cleanPathname);\n\n // Preserve the legacy behavior from the inline generator: stale entries\n // still trigger background regeneration even if this request cannot use\n // the stale payload and will fall through to a fresh render.\n options.scheduleBackgroundRegeneration(regenerationKey, async () => {\n const revalidatedPage = await options.renderFreshPageForCache();\n const revalidateSeconds =\n revalidatedPage.cacheControl?.revalidate ?? options.revalidateSeconds;\n const expireSeconds = revalidatedPage.cacheControl?.expire ?? options.expireSeconds;\n const writes = [\n options.isrSet(\n options.isrRscKey(\n options.cleanPathname,\n options.mountedSlotsHeader,\n options.renderMode,\n ),\n buildAppPageCacheValue(\n \"\",\n revalidatedPage.rscData,\n 200,\n revalidatedPage.rscRenderObservation,\n ),\n revalidateSeconds,\n revalidatedPage.tags,\n expireSeconds,\n ),\n ];\n\n if (!options.isRscRequest) {\n // HTML cache is slot-state-independent (canonical), so only refresh it\n // during HTML-triggered regens. RSC-triggered regens only update the\n // requesting client's RSC slot variant; a stale HTML cache entry will\n // be regenerated independently by the next full-page HTML request.\n writes.push(\n options.isrSet(\n options.isrHtmlKey(options.cleanPathname),\n buildAppPageCacheValue(\n revalidatedPage.html,\n undefined,\n 200,\n revalidatedPage.htmlRenderObservation,\n ),\n revalidateSeconds,\n revalidatedPage.tags,\n expireSeconds,\n ),\n );\n }\n\n await Promise.all(writes);\n options.isrDebug?.(\"regen complete\", options.cleanPathname);\n });\n\n const staleResponse = buildAppPageCachedResponse(cachedValue, {\n cacheState: \"STALE\",\n cacheControl: cached.value.cacheControl,\n expireSeconds: options.expireSeconds,\n isEdgeRuntime: options.isEdgeRuntime,\n isRscRequest: options.isRscRequest,\n middlewareHeaders: options.middlewareHeaders,\n middlewareStatus: options.middlewareStatus,\n mountedSlotsHeader: options.mountedSlotsHeader,\n revalidateSeconds: options.revalidateSeconds,\n });\n\n if (staleResponse) {\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"stale\",\n reason: \"served\",\n });\n options.isrDebug?.(\n options.isRscRequest ? \"STALE (RSC)\" : \"STALE (HTML)\",\n options.cleanPathname,\n );\n options.clearRequestContext();\n return staleResponse;\n }\n\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"miss\",\n reason: \"stale-empty-entry\",\n });\n options.isrDebug?.(\"STALE MISS (empty stale entry)\", options.cleanPathname);\n }\n\n if (!cached) {\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"miss\",\n reason: \"no-entry\",\n });\n options.isrDebug?.(\"MISS (no cache entry)\", options.cleanPathname);\n }\n } catch (isrReadError) {\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"miss\",\n reason: \"read-error\",\n });\n console.error(\"[vinext] ISR cache read error:\", isrReadError);\n }\n\n return null;\n}\n\nexport function finalizeAppPageHtmlCacheResponse(\n response: Response,\n options: FinalizeAppPageHtmlCacheResponseOptions,\n): Response {\n if (!response.body) {\n return response;\n }\n\n const [streamForClient, streamForCache] = response.body.tee();\n const htmlKey = options.isrHtmlKey(options.cleanPathname);\n const rscKey = options.isrRscKey(options.cleanPathname, null);\n const clientHeaders = new Headers(response.headers);\n if (options.preserveClientResponseHeaders !== true) {\n // HTML Server Components can access request APIs while the stream is being\n // consumed. Until that late dynamic check finishes, downstream shared caches\n // must not cache a response whose ISR policy was known before streaming.\n clientHeaders.set(\"Cache-Control\", NO_STORE_CACHE_CONTROL);\n setCacheStateHeaders(clientHeaders, \"MISS\");\n }\n\n const cachePromise = (async () => {\n try {\n const cachedHtml = await readStreamAsText(streamForCache);\n\n if (\n options.capturedDynamicUsageBeforeContextCleanup?.() === true ||\n options.consumeDynamicUsage()\n ) {\n options.isrDebug?.(\"HTML cache write skipped (dynamic usage during render)\", htmlKey);\n return;\n }\n\n const cachePolicy = resolveAppPageCacheWritePolicy({\n expireSeconds: options.expireSeconds,\n requestCacheLife: options.getRequestCacheLife?.(),\n revalidateSeconds: options.revalidateSeconds,\n });\n if (!cachePolicy) {\n options.isrDebug?.(\"HTML cache write skipped (no cache policy)\", htmlKey);\n return;\n }\n\n const pageTags = options.getPageTags();\n // This continuation is scheduled while the request ALS scope is active.\n // It intentionally consumes observation state only after the HTML stream\n // drains, so late Server Component request API usage is included.\n // Consume once: HTML and captured RSC artifacts come from the same render\n // pass, so both cache artifacts share the same observation snapshot.\n const observationState =\n options.consumeRenderObservationState?.() ?? createEmptyAppPageRenderObservationState();\n const htmlRenderObservation = options.createHtmlRenderObservation?.({\n cacheTags: pageTags,\n state: observationState,\n });\n const rscRenderObservation = options.createRscRenderObservation?.({\n cacheTags: pageTags,\n state: observationState,\n });\n const writes = [\n options.isrSet(\n htmlKey,\n buildAppPageCacheValue(cachedHtml, undefined, 200, htmlRenderObservation),\n cachePolicy.revalidateSeconds,\n pageTags,\n cachePolicy.expireSeconds,\n ),\n ];\n\n if (options.capturedRscDataPromise) {\n writes.push(\n options.capturedRscDataPromise.then((rscData) =>\n options.isrSet(\n rscKey,\n buildAppPageCacheValue(\"\", rscData, 200, rscRenderObservation),\n cachePolicy.revalidateSeconds,\n pageTags,\n cachePolicy.expireSeconds,\n ),\n ),\n );\n }\n\n await Promise.all(writes);\n options.isrDebug?.(\"HTML cache written\", htmlKey);\n } catch (cacheError) {\n console.error(\"[vinext] ISR cache write error:\", cacheError);\n }\n })();\n\n options.waitUntil?.(cachePromise);\n\n return new Response(streamForClient, {\n status: response.status,\n statusText: response.statusText,\n headers: clientHeaders,\n });\n}\n\nexport function finalizeAppPageRscCacheResponse(\n response: Response,\n options: ScheduleAppPageRscCacheWriteOptions,\n): Response {\n const didSchedule = scheduleAppPageRscCacheWrite(options);\n if (!didSchedule) {\n return response;\n }\n\n if (options.preserveClientResponseHeaders === true) {\n return response;\n }\n\n const clientHeaders = new Headers(response.headers);\n // RSC payloads are also streamed lazily. Until the captured stream proves no\n // late request API was used, the client-facing MISS response must not enter a\n // shared cache when the ISR policy was known before streaming.\n clientHeaders.set(\"Cache-Control\", NO_STORE_CACHE_CONTROL);\n setCacheStateHeaders(clientHeaders, \"MISS\");\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers: clientHeaders,\n });\n}\n\nexport function scheduleAppPageRscCacheWrite(\n options: ScheduleAppPageRscCacheWriteOptions,\n): boolean {\n const capturedRscDataPromise = options.capturedRscDataPromise;\n if (!capturedRscDataPromise || options.dynamicUsedDuringBuild) {\n return false;\n }\n\n const rscKey = options.isrRscKey(\n options.cleanPathname,\n options.mountedSlotsHeader,\n options.renderMode,\n );\n const cachePromise = (async () => {\n try {\n const rscData = await capturedRscDataPromise;\n\n // Two-phase dynamic detection:\n // 1. dynamicUsedDuringBuild catches searchParams-driven opt-in before the\n // RSC response is sent.\n // 2. consumeDynamicUsage() here catches APIs that fire while the RSC\n // stream is consumed (headers(), cookies(), noStore()).\n if (options.consumeDynamicUsage()) {\n options.isrDebug?.(\"RSC cache write skipped (dynamic usage during render)\", rscKey);\n return;\n }\n\n const cachePolicy = resolveAppPageCacheWritePolicy({\n expireSeconds: options.expireSeconds,\n requestCacheLife: options.getRequestCacheLife?.(),\n revalidateSeconds: options.revalidateSeconds,\n });\n if (!cachePolicy) {\n options.isrDebug?.(\"RSC cache write skipped (no cache policy)\", rscKey);\n return;\n }\n\n const pageTags = options.getPageTags();\n // This continuation is scheduled while the request ALS scope is active.\n // It intentionally consumes observation state only after the captured RSC\n // stream resolves, so late Server Component request API usage is included.\n const observationState =\n options.consumeRenderObservationState?.() ?? createEmptyAppPageRenderObservationState();\n const rscRenderObservation = options.createRscRenderObservation?.({\n cacheTags: pageTags,\n state: observationState,\n });\n await options.isrSet(\n rscKey,\n buildAppPageCacheValue(\"\", rscData, 200, rscRenderObservation),\n cachePolicy.revalidateSeconds,\n pageTags,\n cachePolicy.expireSeconds,\n );\n options.isrDebug?.(\"RSC cache written\", rscKey);\n } catch (cacheError) {\n console.error(\"[vinext] ISR RSC cache write error:\", cacheError);\n }\n })();\n\n options.waitUntil?.(cachePromise);\n return true;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"app-page-cache.js","names":[],"sources":["../../src/server/app-page-cache.ts"],"sourcesContent":["import type { CachedAppPageValue, CacheControlMetadata } from \"vinext/shims/cache\";\nimport {\n VINEXT_RSC_CONTENT_TYPE,\n VINEXT_RSC_VARY_HEADER,\n applyRscCompatibilityIdHeader,\n} from \"./app-rsc-cache-busting.js\";\nimport { buildCachedRevalidateCacheControl } from \"./cache-control.js\";\nimport { VINEXT_MOUNTED_SLOTS_HEADER } from \"./headers.js\";\nimport { applyEdgeRuntimeHeader } from \"./app-page-response.js\";\nimport { setCacheStateHeaders } from \"./cache-headers.js\";\nimport { buildAppPageCacheValue, type ISRCacheEntry } from \"./isr-cache.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport { readStreamAsText } from \"../utils/text-stream.js\";\nimport { encodeCacheTag } from \"../utils/encode-cache-tag.js\";\nimport type { AppRscRenderMode } from \"./app-rsc-render-mode.js\";\nimport {\n createEmptyAppPageRenderObservationState,\n type AppPageRenderObservationState,\n} from \"./app-page-render-observation.js\";\nimport type { RenderObservation } from \"./cache-proof.js\";\n\ntype AppPageDebugLogger = (event: string, detail: string) => void;\ntype AppPageCacheGetter = (key: string) => Promise<ISRCacheEntry | null>;\ntype AppPageCacheSetter = (\n key: string,\n data: CachedAppPageValue,\n revalidateSeconds: number,\n tags: string[],\n expireSeconds?: number,\n) => Promise<void>;\ntype AppPageBackgroundRegenerator = (key: string, renderFn: () => Promise<void>) => void;\ntype AppPageRscCacheKeyBuilder = (\n pathname: string,\n mountedSlotsHeader?: string | null,\n renderMode?: AppRscRenderMode,\n interceptionContext?: string | null,\n) => string;\ntype AppPageRequestCacheLife = {\n revalidate?: number;\n expire?: number;\n};\nexport type AppPageCacheOutcomeMetric = Readonly<{\n artifact: \"html\" | \"rsc\";\n /**\n * Internal cache lookup key for debugging and tests. Runtime telemetry sinks should hash or\n * redact this value before export to avoid high-cardinality or user-derived labels.\n */\n cacheKey: string;\n outcome: \"hit\" | \"miss\" | \"stale\";\n reason:\n | \"empty-entry\"\n | \"no-entry\"\n | \"non-app-page-entry\"\n | \"read-error\"\n | \"served\"\n | \"stale-empty-entry\";\n}>;\ntype AppPageCacheOutcomeRecorder = (metric: AppPageCacheOutcomeMetric) => void;\n\ntype BuildAppPageCacheRenderObservation = (input: {\n cacheTags: readonly string[];\n state: AppPageRenderObservationState;\n}) => RenderObservation;\n\ntype AppPageCacheRenderResult = {\n cacheControl?: CacheControlMetadata;\n html: string;\n htmlRenderObservation?: RenderObservation;\n rscData: ArrayBuffer;\n rscRenderObservation?: RenderObservation;\n tags: string[];\n};\n\ntype BuildAppPageCachedResponseOptions = {\n cacheControl?: CacheControlMetadata;\n cacheState: \"HIT\" | \"STALE\";\n expireSeconds?: number;\n isEdgeRuntime?: boolean;\n isRscRequest: boolean;\n middlewareHeaders?: Headers | null;\n middlewareStatus?: number | null;\n mountedSlotsHeader?: string | null;\n revalidateSeconds: number;\n};\n\ntype ReadAppPageCacheResponseOptions = {\n cleanPathname: string;\n clearRequestContext: () => void;\n isEdgeRuntime?: boolean;\n isRscRequest: boolean;\n isrDebug?: AppPageDebugLogger;\n isrGet: AppPageCacheGetter;\n isrHtmlKey: (pathname: string) => string;\n isrRscKey: AppPageRscCacheKeyBuilder;\n isrSet: AppPageCacheSetter;\n interceptionContext?: string | null;\n middlewareHeaders?: Headers | null;\n middlewareStatus?: number | null;\n mountedSlotsHeader?: string | null;\n recordCacheOutcome?: AppPageCacheOutcomeRecorder;\n renderMode?: AppRscRenderMode;\n expireSeconds?: number;\n revalidateSeconds: number;\n renderFreshPageForCache: () => Promise<AppPageCacheRenderResult>;\n scheduleBackgroundRegeneration: AppPageBackgroundRegenerator;\n};\n\ntype FinalizeAppPageHtmlCacheResponseOptions = {\n capturedDynamicUsageBeforeContextCleanup?: () => boolean;\n capturedRscDataPromise: Promise<ArrayBuffer> | null;\n cleanPathname: string;\n consumeDynamicUsage: () => boolean;\n consumeRenderObservationState?: () => AppPageRenderObservationState;\n createHtmlRenderObservation?: BuildAppPageCacheRenderObservation;\n createRscRenderObservation?: BuildAppPageCacheRenderObservation;\n getPageTags: () => string[];\n getRequestCacheLife?: () => AppPageRequestCacheLife | null;\n isrDebug?: AppPageDebugLogger;\n isrHtmlKey: (pathname: string) => string;\n isrRscKey: AppPageRscCacheKeyBuilder;\n isrSet: AppPageCacheSetter;\n interceptionContext?: string | null;\n preserveClientResponseHeaders?: boolean;\n expireSeconds?: number;\n revalidateSeconds: number | null;\n waitUntil?: (promise: Promise<void>) => void;\n};\n\ntype ScheduleAppPageRscCacheWriteOptions = {\n capturedRscDataPromise: Promise<ArrayBuffer> | null;\n cleanPathname: string;\n consumeDynamicUsage: () => boolean;\n consumeRenderObservationState?: () => AppPageRenderObservationState;\n createRscRenderObservation?: BuildAppPageCacheRenderObservation;\n dynamicUsedDuringBuild: boolean;\n getPageTags: () => string[];\n getRequestCacheLife?: () => AppPageRequestCacheLife | null;\n isrDebug?: AppPageDebugLogger;\n isrRscKey: AppPageRscCacheKeyBuilder;\n isrSet: AppPageCacheSetter;\n interceptionContext?: string | null;\n mountedSlotsHeader?: string | null;\n renderMode?: AppRscRenderMode;\n preserveClientResponseHeaders?: boolean;\n expireSeconds?: number;\n revalidateSeconds: number | null;\n waitUntil?: (promise: Promise<void>) => void;\n};\n\nconst NO_STORE_CACHE_CONTROL = \"no-store, must-revalidate\";\n\nfunction recordAppPageCacheOutcome(\n recordCacheOutcome: AppPageCacheOutcomeRecorder | undefined,\n input: AppPageCacheOutcomeMetric,\n): void {\n try {\n recordCacheOutcome?.(input);\n } catch {\n // Metrics are observational only; telemetry failures must not alter cache serving behavior.\n }\n}\n\nexport function buildAppPageCacheTags(pathname: string, extraTags: readonly string[]): string[] {\n const tags = [pathname, `_N_T_${pathname}`, \"_N_T_/layout\"];\n const segments = pathname.split(\"/\");\n let built = \"\";\n for (let index = 1; index < segments.length; index++) {\n const segment = segments[index];\n if (segment) {\n built += `/${segment}`;\n tags.push(`_N_T_${built}/layout`);\n }\n }\n\n tags.push(`_N_T_${built}/page`);\n for (const tag of extraTags) {\n if (!tags.includes(tag)) {\n tags.push(tag);\n }\n }\n // Canonicalise to ASCII-safe form so path-derived tags from non-ASCII\n // pathnames match what `revalidatePath`/`revalidateTag` produce after\n // their own encoding pass.\n return tags.map(encodeCacheTag);\n}\n\nfunction buildAppPageCacheControl(\n cacheState: BuildAppPageCachedResponseOptions[\"cacheState\"],\n revalidateSeconds: number,\n expireSeconds?: number,\n): string {\n return buildCachedRevalidateCacheControl(cacheState, revalidateSeconds, expireSeconds);\n}\n\nfunction buildAppPageCachedHeaders(options: {\n cacheControl: string;\n cacheState: BuildAppPageCachedResponseOptions[\"cacheState\"];\n contentType: string;\n isEdgeRuntime?: boolean;\n middlewareHeaders?: Headers | null;\n mountedSlotsHeader?: string | null;\n}): Headers {\n const headers = new Headers({\n \"Cache-Control\": options.cacheControl,\n \"Content-Type\": options.contentType,\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n setCacheStateHeaders(headers, options.cacheState);\n applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);\n\n if (options.mountedSlotsHeader) {\n headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);\n }\n\n mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);\n return headers;\n}\n\nfunction getCachedAppPageValue(entry: ISRCacheEntry | null): CachedAppPageValue | null {\n return entry?.value.value && entry.value.value.kind === \"APP_PAGE\" ? entry.value.value : null;\n}\n\nfunction resolveAppPageCacheWritePolicy(options: {\n expireSeconds?: number;\n requestCacheLife?: AppPageRequestCacheLife | null;\n revalidateSeconds: number | null;\n}): { expireSeconds?: number; revalidateSeconds: number } | null {\n let revalidateSeconds = options.revalidateSeconds;\n let expireSeconds = options.expireSeconds;\n const requestCacheLife = options.requestCacheLife;\n\n if (requestCacheLife?.revalidate !== undefined) {\n revalidateSeconds =\n revalidateSeconds === null\n ? requestCacheLife.revalidate\n : Math.min(revalidateSeconds, requestCacheLife.revalidate);\n }\n if (requestCacheLife?.expire !== undefined) {\n expireSeconds = requestCacheLife.expire;\n }\n\n if (revalidateSeconds === null || Number.isNaN(revalidateSeconds) || revalidateSeconds <= 0) {\n return null;\n }\n\n return { expireSeconds, revalidateSeconds };\n}\n\nexport function buildAppPageCachedResponse(\n cachedValue: CachedAppPageValue,\n options: BuildAppPageCachedResponseOptions,\n): Response | null {\n // Preserve the legacy fallback semantics from the generated entry: invalid\n // falsy statuses still fall back to 200 rather than being forwarded through.\n const status = options.middlewareStatus ?? (cachedValue.status || 200);\n const revalidateSeconds = options.cacheControl?.revalidate ?? options.revalidateSeconds;\n const expireSeconds =\n options.cacheControl === undefined\n ? undefined\n : (options.cacheControl.expire ?? options.expireSeconds);\n const cacheControl = buildAppPageCacheControl(\n options.cacheState,\n revalidateSeconds,\n expireSeconds,\n );\n if (options.isRscRequest) {\n if (!cachedValue.rscData) {\n return null;\n }\n\n const rscHeaders = buildAppPageCachedHeaders({\n cacheControl,\n cacheState: options.cacheState,\n contentType: VINEXT_RSC_CONTENT_TYPE,\n isEdgeRuntime: options.isEdgeRuntime,\n middlewareHeaders: options.middlewareHeaders,\n mountedSlotsHeader: options.mountedSlotsHeader,\n });\n applyRscCompatibilityIdHeader(rscHeaders);\n\n return new Response(cachedValue.rscData, {\n status,\n headers: rscHeaders,\n });\n }\n\n if (typeof cachedValue.html !== \"string\" || cachedValue.html.length === 0) {\n return null;\n }\n\n const htmlHeaders = buildAppPageCachedHeaders({\n cacheControl,\n cacheState: options.cacheState,\n contentType: \"text/html; charset=utf-8\",\n isEdgeRuntime: options.isEdgeRuntime,\n middlewareHeaders: options.middlewareHeaders,\n });\n\n return new Response(cachedValue.html, {\n status,\n headers: htmlHeaders,\n });\n}\n\nexport async function readAppPageCacheResponse(\n options: ReadAppPageCacheResponseOptions,\n): Promise<Response | null> {\n const isrKey = options.isRscRequest\n ? options.isrRscKey(\n options.cleanPathname,\n options.mountedSlotsHeader,\n options.renderMode,\n options.interceptionContext,\n )\n : options.isrHtmlKey(options.cleanPathname);\n const artifact = options.isRscRequest ? \"rsc\" : \"html\";\n\n try {\n const cached = await options.isrGet(isrKey);\n const cachedValue = getCachedAppPageValue(cached);\n\n if (cached && !cachedValue) {\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"miss\",\n reason: \"non-app-page-entry\",\n });\n options.isrDebug?.(\"MISS (non app-page cache entry)\", options.cleanPathname);\n return null;\n }\n\n if (cachedValue && !cached?.isStale) {\n const hitResponse = buildAppPageCachedResponse(cachedValue, {\n cacheState: \"HIT\",\n cacheControl: cached?.value.cacheControl,\n expireSeconds: options.expireSeconds,\n isEdgeRuntime: options.isEdgeRuntime,\n isRscRequest: options.isRscRequest,\n middlewareHeaders: options.middlewareHeaders,\n middlewareStatus: options.middlewareStatus,\n mountedSlotsHeader: options.mountedSlotsHeader,\n revalidateSeconds: options.revalidateSeconds,\n });\n\n if (hitResponse) {\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"hit\",\n reason: \"served\",\n });\n options.isrDebug?.(\n options.isRscRequest ? \"HIT (RSC)\" : \"HIT (HTML)\",\n options.cleanPathname,\n );\n options.clearRequestContext();\n return hitResponse;\n }\n\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"miss\",\n reason: \"empty-entry\",\n });\n options.isrDebug?.(\"MISS (empty cached entry)\", options.cleanPathname);\n }\n\n if (cached?.isStale && cachedValue) {\n const regenerationKey = options.isRscRequest\n ? options.isrRscKey(\n options.cleanPathname,\n options.mountedSlotsHeader,\n options.renderMode,\n options.interceptionContext,\n )\n : options.isrHtmlKey(options.cleanPathname);\n\n // Preserve the legacy behavior from the inline generator: stale entries\n // still trigger background regeneration even if this request cannot use\n // the stale payload and will fall through to a fresh render.\n options.scheduleBackgroundRegeneration(regenerationKey, async () => {\n const revalidatedPage = await options.renderFreshPageForCache();\n const revalidateSeconds =\n revalidatedPage.cacheControl?.revalidate ?? options.revalidateSeconds;\n const expireSeconds = revalidatedPage.cacheControl?.expire ?? options.expireSeconds;\n const writes = [\n options.isrSet(\n options.isrRscKey(\n options.cleanPathname,\n options.mountedSlotsHeader,\n options.renderMode,\n options.interceptionContext,\n ),\n buildAppPageCacheValue(\n \"\",\n revalidatedPage.rscData,\n 200,\n revalidatedPage.rscRenderObservation,\n ),\n revalidateSeconds,\n revalidatedPage.tags,\n expireSeconds,\n ),\n ];\n\n if (!options.isRscRequest) {\n // HTML cache is slot-state-independent (canonical), so only refresh it\n // during HTML-triggered regens. RSC-triggered regens only update the\n // requesting client's RSC slot variant; a stale HTML cache entry will\n // be regenerated independently by the next full-page HTML request.\n writes.push(\n options.isrSet(\n options.isrHtmlKey(options.cleanPathname),\n buildAppPageCacheValue(\n revalidatedPage.html,\n undefined,\n 200,\n revalidatedPage.htmlRenderObservation,\n ),\n revalidateSeconds,\n revalidatedPage.tags,\n expireSeconds,\n ),\n );\n }\n\n await Promise.all(writes);\n options.isrDebug?.(\"regen complete\", options.cleanPathname);\n });\n\n const staleResponse = buildAppPageCachedResponse(cachedValue, {\n cacheState: \"STALE\",\n cacheControl: cached.value.cacheControl,\n expireSeconds: options.expireSeconds,\n isEdgeRuntime: options.isEdgeRuntime,\n isRscRequest: options.isRscRequest,\n middlewareHeaders: options.middlewareHeaders,\n middlewareStatus: options.middlewareStatus,\n mountedSlotsHeader: options.mountedSlotsHeader,\n revalidateSeconds: options.revalidateSeconds,\n });\n\n if (staleResponse) {\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"stale\",\n reason: \"served\",\n });\n options.isrDebug?.(\n options.isRscRequest ? \"STALE (RSC)\" : \"STALE (HTML)\",\n options.cleanPathname,\n );\n options.clearRequestContext();\n return staleResponse;\n }\n\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"miss\",\n reason: \"stale-empty-entry\",\n });\n options.isrDebug?.(\"STALE MISS (empty stale entry)\", options.cleanPathname);\n }\n\n if (!cached) {\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"miss\",\n reason: \"no-entry\",\n });\n options.isrDebug?.(\"MISS (no cache entry)\", options.cleanPathname);\n }\n } catch (isrReadError) {\n recordAppPageCacheOutcome(options.recordCacheOutcome, {\n artifact,\n cacheKey: isrKey,\n outcome: \"miss\",\n reason: \"read-error\",\n });\n console.error(\"[vinext] ISR cache read error:\", isrReadError);\n }\n\n return null;\n}\n\nexport function finalizeAppPageHtmlCacheResponse(\n response: Response,\n options: FinalizeAppPageHtmlCacheResponseOptions,\n): Response {\n if (!response.body) {\n return response;\n }\n\n const [streamForClient, streamForCache] = response.body.tee();\n const htmlKey = options.isrHtmlKey(options.cleanPathname);\n const rscKey = options.isrRscKey(\n options.cleanPathname,\n null,\n undefined,\n options.interceptionContext,\n );\n const clientHeaders = new Headers(response.headers);\n if (options.preserveClientResponseHeaders !== true) {\n // HTML Server Components can access request APIs while the stream is being\n // consumed. Until that late dynamic check finishes, downstream shared caches\n // must not cache a response whose ISR policy was known before streaming.\n clientHeaders.set(\"Cache-Control\", NO_STORE_CACHE_CONTROL);\n setCacheStateHeaders(clientHeaders, \"MISS\");\n }\n\n const cachePromise = (async () => {\n try {\n const cachedHtml = await readStreamAsText(streamForCache);\n\n if (\n options.capturedDynamicUsageBeforeContextCleanup?.() === true ||\n options.consumeDynamicUsage()\n ) {\n options.isrDebug?.(\"HTML cache write skipped (dynamic usage during render)\", htmlKey);\n return;\n }\n\n const cachePolicy = resolveAppPageCacheWritePolicy({\n expireSeconds: options.expireSeconds,\n requestCacheLife: options.getRequestCacheLife?.(),\n revalidateSeconds: options.revalidateSeconds,\n });\n if (!cachePolicy) {\n options.isrDebug?.(\"HTML cache write skipped (no cache policy)\", htmlKey);\n return;\n }\n\n const pageTags = options.getPageTags();\n // This continuation is scheduled while the request ALS scope is active.\n // It intentionally consumes observation state only after the HTML stream\n // drains, so late Server Component request API usage is included.\n // Consume once: HTML and captured RSC artifacts come from the same render\n // pass, so both cache artifacts share the same observation snapshot.\n const observationState =\n options.consumeRenderObservationState?.() ?? createEmptyAppPageRenderObservationState();\n const htmlRenderObservation = options.createHtmlRenderObservation?.({\n cacheTags: pageTags,\n state: observationState,\n });\n const rscRenderObservation = options.createRscRenderObservation?.({\n cacheTags: pageTags,\n state: observationState,\n });\n const writes = [\n options.isrSet(\n htmlKey,\n buildAppPageCacheValue(cachedHtml, undefined, 200, htmlRenderObservation),\n cachePolicy.revalidateSeconds,\n pageTags,\n cachePolicy.expireSeconds,\n ),\n ];\n\n if (options.capturedRscDataPromise) {\n writes.push(\n options.capturedRscDataPromise.then((rscData) =>\n options.isrSet(\n rscKey,\n buildAppPageCacheValue(\"\", rscData, 200, rscRenderObservation),\n cachePolicy.revalidateSeconds,\n pageTags,\n cachePolicy.expireSeconds,\n ),\n ),\n );\n }\n\n await Promise.all(writes);\n options.isrDebug?.(\"HTML cache written\", htmlKey);\n } catch (cacheError) {\n console.error(\"[vinext] ISR cache write error:\", cacheError);\n }\n })();\n\n options.waitUntil?.(cachePromise);\n\n return new Response(streamForClient, {\n status: response.status,\n statusText: response.statusText,\n headers: clientHeaders,\n });\n}\n\nexport function finalizeAppPageRscCacheResponse(\n response: Response,\n options: ScheduleAppPageRscCacheWriteOptions,\n): Response {\n const didSchedule = scheduleAppPageRscCacheWrite(options);\n if (!didSchedule) {\n return response;\n }\n\n if (options.preserveClientResponseHeaders === true) {\n return response;\n }\n\n const clientHeaders = new Headers(response.headers);\n // RSC payloads are also streamed lazily. Until the captured stream proves no\n // late request API was used, the client-facing MISS response must not enter a\n // shared cache when the ISR policy was known before streaming.\n clientHeaders.set(\"Cache-Control\", NO_STORE_CACHE_CONTROL);\n setCacheStateHeaders(clientHeaders, \"MISS\");\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers: clientHeaders,\n });\n}\n\nexport function scheduleAppPageRscCacheWrite(\n options: ScheduleAppPageRscCacheWriteOptions,\n): boolean {\n const capturedRscDataPromise = options.capturedRscDataPromise;\n if (!capturedRscDataPromise || options.dynamicUsedDuringBuild) {\n return false;\n }\n\n const rscKey = options.isrRscKey(\n options.cleanPathname,\n options.mountedSlotsHeader,\n options.renderMode,\n options.interceptionContext,\n );\n const cachePromise = (async () => {\n try {\n const rscData = await capturedRscDataPromise;\n\n // Two-phase dynamic detection:\n // 1. dynamicUsedDuringBuild catches searchParams-driven opt-in before the\n // RSC response is sent.\n // 2. consumeDynamicUsage() here catches APIs that fire while the RSC\n // stream is consumed (headers(), cookies(), noStore()).\n if (options.consumeDynamicUsage()) {\n options.isrDebug?.(\"RSC cache write skipped (dynamic usage during render)\", rscKey);\n return;\n }\n\n const cachePolicy = resolveAppPageCacheWritePolicy({\n expireSeconds: options.expireSeconds,\n requestCacheLife: options.getRequestCacheLife?.(),\n revalidateSeconds: options.revalidateSeconds,\n });\n if (!cachePolicy) {\n options.isrDebug?.(\"RSC cache write skipped (no cache policy)\", rscKey);\n return;\n }\n\n const pageTags = options.getPageTags();\n // This continuation is scheduled while the request ALS scope is active.\n // It intentionally consumes observation state only after the captured RSC\n // stream resolves, so late Server Component request API usage is included.\n const observationState =\n options.consumeRenderObservationState?.() ?? createEmptyAppPageRenderObservationState();\n const rscRenderObservation = options.createRscRenderObservation?.({\n cacheTags: pageTags,\n state: observationState,\n });\n await options.isrSet(\n rscKey,\n buildAppPageCacheValue(\"\", rscData, 200, rscRenderObservation),\n cachePolicy.revalidateSeconds,\n pageTags,\n cachePolicy.expireSeconds,\n );\n options.isrDebug?.(\"RSC cache written\", rscKey);\n } catch (cacheError) {\n console.error(\"[vinext] ISR RSC cache write error:\", cacheError);\n }\n })();\n\n options.waitUntil?.(cachePromise);\n return true;\n}\n"],"mappings":"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"}
@@ -51,19 +51,28 @@ type AppPageDispatchRoute = {
51
51
  __buildTimeReasons?: LayoutClassificationOptions["buildTimeReasons"];
52
52
  error?: AppPageModule | null;
53
53
  errors?: readonly (AppPageModule | null | undefined)[];
54
+ forbidden?: AppPageModule | null;
54
55
  forbiddens?: readonly (AppPageModule | null | undefined)[];
55
56
  isDynamic: boolean;
56
57
  layouts: readonly AppPageModule[];
57
58
  layoutTreePositions?: readonly number[];
58
59
  loading?: AppPageModule | null;
60
+ notFound?: AppPageModule | null;
59
61
  notFounds?: readonly (AppPageModule | null | undefined)[];
60
62
  params: readonly string[];
61
63
  pattern: string;
62
64
  routeSegments: readonly string[];
65
+ unauthorized?: AppPageModule | null;
63
66
  unauthorizeds?: readonly (AppPageModule | null | undefined)[];
64
67
  };
65
68
  type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
66
69
  /** Configured basePath (e.g. "/blog"). Used to prefix redirect Locations. */basePath?: string;
70
+ /**
71
+ * Allow-list of OpenTelemetry propagation keys (from
72
+ * `experimental.clientTraceMetadata`) to surface as `<meta>` tags in the
73
+ * SSR head. Undefined or empty disables emission entirely.
74
+ */
75
+ clientTraceMetadata?: readonly string[];
67
76
  buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams) => Promise<AppPageElement>;
68
77
  cleanPathname: string;
69
78
  clearRequestContext: () => void;
@@ -95,7 +104,7 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
95
104
  isrDebug?: AppPageDebugLogger;
96
105
  isrGet: AppPageCacheGetter;
97
106
  isrHtmlKey: (pathname: string) => string;
98
- isrRscKey: (pathname: string, mountedSlotsHeader?: string | null, renderMode?: AppRscRenderMode) => string;
107
+ isrRscKey: (pathname: string, mountedSlotsHeader?: string | null, renderMode?: AppRscRenderMode, interceptionContext?: string | null) => string;
99
108
  isrSet: AppPageCacheSetter;
100
109
  loadSsrHandler: () => Promise<AppPageSsrHandler>;
101
110
  middlewareContext: AppPageMiddlewareContext;