vinext 0.0.51 → 0.0.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/build/clean-output.d.ts +14 -0
- package/dist/build/clean-output.js +36 -0
- package/dist/build/clean-output.js.map +1 -0
- package/dist/build/precompress.d.ts +7 -7
- package/dist/build/precompress.js +18 -17
- package/dist/build/precompress.js.map +1 -1
- package/dist/build/prerender.d.ts +9 -16
- package/dist/build/prerender.js +88 -50
- package/dist/build/prerender.js.map +1 -1
- package/dist/build/run-prerender.js +10 -1
- package/dist/build/run-prerender.js.map +1 -1
- package/dist/build/static-export.d.ts +5 -0
- package/dist/build/static-export.js +8 -3
- package/dist/build/static-export.js.map +1 -1
- package/dist/check.js +4 -0
- package/dist/check.js.map +1 -1
- package/dist/cli-args.d.ts +1 -0
- package/dist/cli-args.js +5 -0
- package/dist/cli-args.js.map +1 -1
- package/dist/cli.js +58 -4
- package/dist/cli.js.map +1 -1
- package/dist/client/instrumentation-client-inject.d.ts +34 -0
- package/dist/client/instrumentation-client-inject.js +57 -0
- package/dist/client/instrumentation-client-inject.js.map +1 -0
- package/dist/client/navigation-runtime.d.ts +60 -0
- package/dist/client/navigation-runtime.js +171 -0
- package/dist/client/navigation-runtime.js.map +1 -0
- package/dist/client/pages-router-link-navigation.d.ts +26 -0
- package/dist/client/pages-router-link-navigation.js +14 -0
- package/dist/client/pages-router-link-navigation.js.map +1 -0
- package/dist/client/vinext-next-data.d.ts +14 -3
- package/dist/client/vinext-next-data.js +50 -1
- package/dist/client/vinext-next-data.js.map +1 -0
- package/dist/client/window-next.d.ts +10 -2
- package/dist/client/window-next.js.map +1 -1
- package/dist/cloudflare/kv-cache-handler.js +2 -1
- package/dist/cloudflare/kv-cache-handler.js.map +1 -1
- package/dist/cloudflare/tpr.js +1 -1
- package/dist/cloudflare/tpr.js.map +1 -1
- package/dist/config/config-matchers.d.ts +63 -16
- package/dist/config/config-matchers.js +145 -9
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/config/next-config.d.ts +32 -5
- package/dist/config/next-config.js +55 -15
- package/dist/config/next-config.js.map +1 -1
- package/dist/deploy.js +130 -46
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-browser-entry.js +9 -3
- package/dist/entries/app-browser-entry.js.map +1 -1
- package/dist/entries/app-rsc-entry.d.ts +4 -2
- package/dist/entries/app-rsc-entry.js +76 -16
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.d.ts +1 -0
- package/dist/entries/app-rsc-manifest.js +53 -6
- package/dist/entries/app-rsc-manifest.js.map +1 -1
- package/dist/entries/app-ssr-entry.d.ts +3 -3
- package/dist/entries/app-ssr-entry.js +4 -4
- package/dist/entries/app-ssr-entry.js.map +1 -1
- package/dist/entries/pages-client-entry.js +40 -3
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-server-entry.js +261 -31
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.d.ts +2 -1
- package/dist/entries/runtime-entry-module.js +9 -3
- package/dist/entries/runtime-entry-module.js.map +1 -1
- package/dist/index.js +161 -46
- package/dist/index.js.map +1 -1
- package/dist/plugins/css-data-url.d.ts +7 -0
- package/dist/plugins/css-data-url.js +81 -0
- package/dist/plugins/css-data-url.js.map +1 -0
- package/dist/plugins/fonts.js +30 -5
- package/dist/plugins/fonts.js.map +1 -1
- package/dist/plugins/middleware-server-only.d.ts +54 -0
- package/dist/plugins/middleware-server-only.js +91 -0
- package/dist/plugins/middleware-server-only.js.map +1 -0
- package/dist/plugins/optimize-imports.js +4 -4
- package/dist/plugins/optimize-imports.js.map +1 -1
- package/dist/plugins/strip-server-exports.js +5 -8
- package/dist/plugins/strip-server-exports.js.map +1 -1
- package/dist/routing/app-route-graph.d.ts +20 -1
- package/dist/routing/app-route-graph.js +58 -6
- package/dist/routing/app-route-graph.js.map +1 -1
- package/dist/routing/app-router.d.ts +2 -2
- package/dist/routing/app-router.js +2 -2
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/route-trie.js +13 -18
- package/dist/routing/route-trie.js.map +1 -1
- package/dist/routing/utils.d.ts +12 -1
- package/dist/routing/utils.js +18 -1
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/api-handler.js +153 -42
- package/dist/server/api-handler.js.map +1 -1
- package/dist/server/app-browser-action-result.d.ts +16 -1
- package/dist/server/app-browser-action-result.js +15 -1
- package/dist/server/app-browser-action-result.js.map +1 -1
- package/dist/server/app-browser-entry.js +309 -155
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-interception-context.d.ts +24 -0
- package/dist/server/app-browser-interception-context.js +32 -0
- package/dist/server/app-browser-interception-context.js.map +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +3 -1
- package/dist/server/app-browser-navigation-controller.js +5 -1
- package/dist/server/app-browser-navigation-controller.js.map +1 -1
- package/dist/server/app-browser-rsc-redirect.d.ts +2 -1
- package/dist/server/app-browser-rsc-redirect.js +2 -2
- package/dist/server/app-browser-rsc-redirect.js.map +1 -1
- package/dist/server/app-browser-state.d.ts +18 -1
- package/dist/server/app-browser-state.js +19 -1
- package/dist/server/app-browser-state.js.map +1 -1
- package/dist/server/app-browser-stream.d.ts +5 -14
- package/dist/server/app-browser-stream.js +13 -7
- package/dist/server/app-browser-stream.js.map +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +2 -1
- package/dist/server/app-browser-visible-commit.js +1 -0
- package/dist/server/app-browser-visible-commit.js.map +1 -1
- package/dist/server/app-elements-wire.d.ts +10 -5
- package/dist/server/app-elements-wire.js +84 -2
- package/dist/server/app-elements-wire.js.map +1 -1
- package/dist/server/app-elements.d.ts +3 -2
- package/dist/server/app-elements.js +3 -2
- package/dist/server/app-elements.js.map +1 -1
- package/dist/server/app-fallback-renderer.d.ts +12 -3
- package/dist/server/app-fallback-renderer.js +15 -8
- package/dist/server/app-fallback-renderer.js.map +1 -1
- package/dist/server/app-history-state.js +6 -2
- package/dist/server/app-history-state.js.map +1 -1
- package/dist/server/app-interception-context-header.d.ts +33 -0
- package/dist/server/app-interception-context-header.js +44 -0
- package/dist/server/app-interception-context-header.js.map +1 -0
- package/dist/server/app-middleware.d.ts +13 -0
- package/dist/server/app-middleware.js +3 -1
- package/dist/server/app-middleware.js.map +1 -1
- package/dist/server/app-mounted-slots-header.d.ts +19 -0
- package/dist/server/app-mounted-slots-header.js +40 -1
- package/dist/server/app-mounted-slots-header.js.map +1 -1
- package/dist/server/app-optimistic-routing.d.ts +54 -0
- package/dist/server/app-optimistic-routing.js +208 -0
- package/dist/server/app-optimistic-routing.js.map +1 -0
- package/dist/server/app-page-boundary-render.d.ts +1 -0
- package/dist/server/app-page-boundary-render.js +2 -0
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-boundary.d.ts +1 -0
- package/dist/server/app-page-boundary.js +2 -0
- package/dist/server/app-page-boundary.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +15 -1
- package/dist/server/app-page-cache.js +68 -7
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-dispatch.d.ts +5 -0
- package/dist/server/app-page-dispatch.js +39 -5
- package/dist/server/app-page-dispatch.js.map +1 -1
- package/dist/server/app-page-element-builder.d.ts +2 -1
- package/dist/server/app-page-element-builder.js +7 -3
- package/dist/server/app-page-element-builder.js.map +1 -1
- package/dist/server/app-page-execution.d.ts +29 -1
- package/dist/server/app-page-execution.js +91 -4
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-head.d.ts +1 -0
- package/dist/server/app-page-head.js +29 -2
- package/dist/server/app-page-head.js.map +1 -1
- package/dist/server/app-page-probe.js +1 -1
- package/dist/server/app-page-render-observation.js +1 -1
- package/dist/server/app-page-render.d.ts +3 -0
- package/dist/server/app-page-render.js +7 -3
- package/dist/server/app-page-render.js.map +1 -1
- package/dist/server/app-page-response.d.ts +11 -1
- package/dist/server/app-page-response.js +18 -5
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +1 -0
- package/dist/server/app-page-route-wiring.js +35 -15
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-page-stream.d.ts +4 -0
- package/dist/server/app-page-stream.js +3 -0
- package/dist/server/app-page-stream.js.map +1 -1
- package/dist/server/app-prerender-static-params.d.ts +2 -1
- package/dist/server/app-prerender-static-params.js +44 -8
- package/dist/server/app-prerender-static-params.js.map +1 -1
- package/dist/server/app-route-handler-cache.d.ts +2 -2
- package/dist/server/app-route-handler-cache.js +3 -2
- package/dist/server/app-route-handler-cache.js.map +1 -1
- package/dist/server/app-route-handler-dispatch.d.ts +7 -1
- package/dist/server/app-route-handler-dispatch.js +4 -1
- package/dist/server/app-route-handler-dispatch.js.map +1 -1
- package/dist/server/app-route-handler-execution.d.ts +18 -2
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-execution.js.map +1 -1
- package/dist/server/app-route-handler-response.js +6 -5
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-router-entry.js +6 -2
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/app-rsc-handler.d.ts +11 -1
- package/dist/server/app-rsc-handler.js +48 -21
- package/dist/server/app-rsc-handler.js.map +1 -1
- package/dist/server/app-rsc-render-mode.d.ts +4 -3
- package/dist/server/app-rsc-render-mode.js +7 -1
- package/dist/server/app-rsc-render-mode.js.map +1 -1
- package/dist/server/app-rsc-request-normalization.d.ts +4 -1
- package/dist/server/app-rsc-request-normalization.js +6 -2
- package/dist/server/app-rsc-request-normalization.js.map +1 -1
- package/dist/server/app-rsc-response-finalizer.d.ts +8 -1
- package/dist/server/app-rsc-response-finalizer.js +10 -3
- package/dist/server/app-rsc-response-finalizer.js.map +1 -1
- package/dist/server/app-rsc-route-matching.js +2 -2
- package/dist/server/app-rsc-route-matching.js.map +1 -1
- package/dist/server/app-segment-config.d.ts +4 -1
- package/dist/server/app-segment-config.js +6 -1
- package/dist/server/app-segment-config.js.map +1 -1
- package/dist/server/app-server-action-execution.d.ts +1 -0
- package/dist/server/app-server-action-execution.js +5 -1
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +92 -55
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/app-ssr-stream.d.ts +30 -2
- package/dist/server/app-ssr-stream.js +95 -8
- package/dist/server/app-ssr-stream.js.map +1 -1
- package/dist/server/app-static-generation.d.ts +1 -0
- package/dist/server/app-static-generation.js +2 -1
- package/dist/server/app-static-generation.js.map +1 -1
- package/dist/server/artifact-compatibility.d.ts +1 -1
- package/dist/server/artifact-compatibility.js.map +1 -1
- package/dist/server/cache-headers.d.ts +7 -0
- package/dist/server/cache-headers.js +19 -0
- package/dist/server/cache-headers.js.map +1 -0
- package/dist/server/cache-proof.d.ts +49 -3
- package/dist/server/cache-proof.js +78 -22
- package/dist/server/cache-proof.js.map +1 -1
- package/dist/server/client-reuse-manifest.d.ts +99 -0
- package/dist/server/client-reuse-manifest.js +212 -0
- package/dist/server/client-reuse-manifest.js.map +1 -0
- package/dist/server/default-global-error-module.d.ts +20 -0
- package/dist/server/default-global-error-module.js +20 -0
- package/dist/server/default-global-error-module.js.map +1 -0
- package/dist/server/default-not-found-module.d.ts +20 -0
- package/dist/server/default-not-found-module.js +20 -0
- package/dist/server/default-not-found-module.js.map +1 -0
- package/dist/server/dev-server.d.ts +10 -2
- package/dist/server/dev-server.js +99 -36
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/edge-api-runtime.d.ts +5 -0
- package/dist/server/edge-api-runtime.js +8 -0
- package/dist/server/edge-api-runtime.js.map +1 -0
- package/dist/server/headers.d.ts +22 -1
- package/dist/server/headers.js +22 -1
- package/dist/server/headers.js.map +1 -1
- package/dist/server/http-error-responses.d.ts +16 -1
- package/dist/server/http-error-responses.js +21 -1
- package/dist/server/http-error-responses.js.map +1 -1
- package/dist/server/image-optimization.d.ts +13 -4
- package/dist/server/image-optimization.js +15 -4
- package/dist/server/image-optimization.js.map +1 -1
- package/dist/server/isr-cache.d.ts +6 -2
- package/dist/server/isr-cache.js +20 -4
- package/dist/server/isr-cache.js.map +1 -1
- package/dist/server/middleware-runtime.d.ts +15 -0
- package/dist/server/middleware-runtime.js +59 -7
- package/dist/server/middleware-runtime.js.map +1 -1
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +5 -3
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/navigation-planner.d.ts +9 -3
- package/dist/server/navigation-planner.js +98 -25
- package/dist/server/navigation-planner.js.map +1 -1
- package/dist/server/navigation-trace.d.ts +2 -1
- package/dist/server/navigation-trace.js +1 -0
- package/dist/server/navigation-trace.js.map +1 -1
- package/dist/server/pages-api-route.d.ts +45 -1
- package/dist/server/pages-api-route.js +27 -4
- package/dist/server/pages-api-route.js.map +1 -1
- package/dist/server/pages-body-parser-config.d.ts +60 -0
- package/dist/server/pages-body-parser-config.js +79 -0
- package/dist/server/pages-body-parser-config.js.map +1 -0
- package/dist/server/pages-data-route.d.ts +77 -0
- package/dist/server/pages-data-route.js +98 -0
- package/dist/server/pages-data-route.js.map +1 -0
- package/dist/server/pages-default-404.d.ts +31 -0
- package/dist/server/pages-default-404.js +40 -0
- package/dist/server/pages-default-404.js.map +1 -0
- package/dist/server/pages-i18n.d.ts +51 -1
- package/dist/server/pages-i18n.js +61 -1
- package/dist/server/pages-i18n.js.map +1 -1
- package/dist/server/pages-node-compat.d.ts +10 -0
- package/dist/server/pages-node-compat.js +12 -1
- package/dist/server/pages-node-compat.js.map +1 -1
- package/dist/server/pages-page-data.d.ts +69 -2
- package/dist/server/pages-page-data.js +47 -31
- package/dist/server/pages-page-data.js.map +1 -1
- package/dist/server/pages-page-response.d.ts +13 -1
- package/dist/server/pages-page-response.js +16 -11
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/prerender-route-params.d.ts +14 -0
- package/dist/server/prerender-route-params.js +94 -0
- package/dist/server/prerender-route-params.js.map +1 -0
- package/dist/server/prod-server.d.ts +15 -37
- package/dist/server/prod-server.js +143 -107
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/proxy-trust.d.ts +41 -0
- package/dist/server/proxy-trust.js +70 -0
- package/dist/server/proxy-trust.js.map +1 -0
- package/dist/server/request-pipeline.d.ts +13 -4
- package/dist/server/request-pipeline.js +32 -14
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/server/seed-cache.d.ts +12 -31
- package/dist/server/seed-cache.js +30 -37
- package/dist/server/seed-cache.js.map +1 -1
- package/dist/server/server-action-not-found.js +8 -3
- package/dist/server/server-action-not-found.js.map +1 -1
- package/dist/server/skip-cache-proof.d.ts +41 -0
- package/dist/server/skip-cache-proof.js +101 -0
- package/dist/server/skip-cache-proof.js.map +1 -0
- package/dist/server/static-file-cache.d.ts +1 -1
- package/dist/server/static-file-cache.js +8 -7
- package/dist/server/static-file-cache.js.map +1 -1
- package/dist/server/streaming-metadata.d.ts +5 -0
- package/dist/server/streaming-metadata.js +10 -0
- package/dist/server/streaming-metadata.js.map +1 -0
- package/dist/shims/app-router-scroll-state.d.ts +12 -0
- package/dist/shims/app-router-scroll-state.js +38 -0
- package/dist/shims/app-router-scroll-state.js.map +1 -0
- package/dist/shims/app-router-scroll.d.ts +14 -0
- package/dist/shims/app-router-scroll.js +100 -0
- package/dist/shims/app-router-scroll.js.map +1 -0
- package/dist/shims/before-interactive-context.d.ts +30 -0
- package/dist/shims/before-interactive-context.js +10 -0
- package/dist/shims/before-interactive-context.js.map +1 -0
- package/dist/shims/cache-runtime.d.ts +1 -1
- package/dist/shims/cache-runtime.js +14 -1
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/client-locale.d.ts +15 -0
- package/dist/shims/client-locale.js +13 -0
- package/dist/shims/client-locale.js.map +1 -0
- package/dist/shims/default-global-error.d.ts +32 -0
- package/dist/shims/default-global-error.js +181 -0
- package/dist/shims/default-global-error.js.map +1 -0
- package/dist/shims/default-not-found.d.ts +12 -0
- package/dist/shims/default-not-found.js +61 -0
- package/dist/shims/default-not-found.js.map +1 -0
- package/dist/shims/document.d.ts +59 -3
- package/dist/shims/document.js +36 -5
- package/dist/shims/document.js.map +1 -1
- package/dist/shims/error-boundary.d.ts +2 -2
- package/dist/shims/font-local.d.ts +5 -0
- package/dist/shims/font-local.js +6 -2
- package/dist/shims/font-local.js.map +1 -1
- package/dist/shims/form.js +13 -6
- package/dist/shims/form.js.map +1 -1
- package/dist/shims/head.js +4 -4
- package/dist/shims/head.js.map +1 -1
- package/dist/shims/headers.d.ts +6 -2
- package/dist/shims/headers.js +64 -21
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/image.d.ts +1 -1
- package/dist/shims/image.js +4 -4
- package/dist/shims/image.js.map +1 -1
- package/dist/shims/internal/pages-data-target.d.ts +58 -0
- package/dist/shims/internal/pages-data-target.js +91 -0
- package/dist/shims/internal/pages-data-target.js.map +1 -0
- package/dist/shims/internal/pages-data-url.d.ts +42 -0
- package/dist/shims/internal/pages-data-url.js +73 -0
- package/dist/shims/internal/pages-data-url.js.map +1 -0
- package/dist/shims/link.d.ts +21 -3
- package/dist/shims/link.js +189 -30
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +2 -1
- package/dist/shims/metadata.js +65 -6
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation.d.ts +8 -2
- package/dist/shims/navigation.js +67 -23
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/og.d.ts +18 -2
- package/dist/shims/og.js +49 -1
- package/dist/shims/og.js.map +1 -0
- package/dist/shims/request-state-types.d.ts +1 -1
- package/dist/shims/root-params.d.ts +3 -1
- package/dist/shims/root-params.js +11 -3
- package/dist/shims/root-params.js.map +1 -1
- package/dist/shims/router-state.d.ts +1 -0
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/router.d.ts +12 -5
- package/dist/shims/router.js +535 -86
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/script.js +86 -12
- package/dist/shims/script.js.map +1 -1
- package/dist/shims/server.d.ts +21 -4
- package/dist/shims/server.js +30 -9
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/slot.js +5 -1
- package/dist/shims/slot.js.map +1 -1
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/url-safety.d.ts +23 -1
- package/dist/shims/url-safety.js +29 -2
- package/dist/shims/url-safety.js.map +1 -1
- package/dist/shims/url-utils.d.ts +2 -1
- package/dist/shims/url-utils.js +15 -4
- package/dist/shims/url-utils.js.map +1 -1
- package/dist/typegen.d.ts +10 -0
- package/dist/typegen.js +242 -0
- package/dist/typegen.js.map +1 -0
- package/dist/utils/asset-prefix.d.ts +33 -5
- package/dist/utils/asset-prefix.js +39 -6
- package/dist/utils/asset-prefix.js.map +1 -1
- package/dist/utils/cache-control-metadata.d.ts +2 -1
- package/dist/utils/cache-control-metadata.js +1 -3
- package/dist/utils/cache-control-metadata.js.map +1 -1
- package/dist/utils/domain-locale.d.ts +2 -1
- package/dist/utils/domain-locale.js +9 -1
- package/dist/utils/domain-locale.js.map +1 -1
- package/dist/utils/html-limited-bots.d.ts +5 -0
- package/dist/utils/html-limited-bots.js +15 -0
- package/dist/utils/html-limited-bots.js.map +1 -0
- package/dist/utils/lazy-chunks.d.ts +1 -1
- package/dist/utils/lazy-chunks.js +1 -1
- package/dist/utils/lazy-chunks.js.map +1 -1
- package/dist/utils/prerender-output-paths.d.ts +15 -0
- package/dist/utils/prerender-output-paths.js +24 -0
- package/dist/utils/prerender-output-paths.js.map +1 -0
- package/dist/utils/query.d.ts +23 -1
- package/dist/utils/query.js +46 -2
- package/dist/utils/query.js.map +1 -1
- package/dist/utils/record.d.ts +5 -0
- package/dist/utils/record.js +8 -0
- package/dist/utils/record.js.map +1 -0
- package/package.json +11 -3
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_PARAMS_HEADER, VINEXT_TIMING_HEADER } from "./headers.js";
|
|
2
|
+
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
2
3
|
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
3
|
-
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
4
4
|
import { NO_STORE_CACHE_CONTROL, STATIC_CACHE_CONTROL, buildRevalidateCacheControl } from "./cache-control.js";
|
|
5
|
+
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
5
6
|
//#region src/server/app-page-response.ts
|
|
6
7
|
function applyTimingHeader(headers, timing) {
|
|
7
8
|
if (!timing) return;
|
|
@@ -66,15 +67,26 @@ function resolveAppPageHtmlResponsePolicy(options) {
|
|
|
66
67
|
};
|
|
67
68
|
return { shouldWriteToCache: false };
|
|
68
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Mirror Next.js' edge-runtime marker (set in edge-ssr-app.ts). Only routes
|
|
72
|
+
* whose resolved segment config is `runtime = "edge"` should advertise it —
|
|
73
|
+
* nodejs-runtime routes must not, otherwise downstream consumers can't tell
|
|
74
|
+
* the configured runtime from the response. Centralized so every response
|
|
75
|
+
* construction site can opt in without re-deriving the header name.
|
|
76
|
+
*/
|
|
77
|
+
function applyEdgeRuntimeHeader(headers, isEdgeRuntime) {
|
|
78
|
+
if (isEdgeRuntime) headers.set("x-edge-runtime", "1");
|
|
79
|
+
}
|
|
69
80
|
function buildAppPageRscResponse(body, options) {
|
|
70
81
|
const headers = new Headers({
|
|
71
82
|
"Content-Type": VINEXT_RSC_CONTENT_TYPE,
|
|
72
83
|
Vary: VINEXT_RSC_VARY_HEADER
|
|
73
84
|
});
|
|
85
|
+
applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);
|
|
74
86
|
if (options.params && Object.keys(options.params).length > 0) headers.set(VINEXT_PARAMS_HEADER, encodeURIComponent(JSON.stringify(options.params)));
|
|
75
87
|
if (options.mountedSlotsHeader) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);
|
|
76
88
|
if (options.policy.cacheControl) headers.set("Cache-Control", options.policy.cacheControl);
|
|
77
|
-
if (options.policy.cacheState) headers
|
|
89
|
+
if (options.policy.cacheState) setCacheStateHeaders(headers, options.policy.cacheState);
|
|
78
90
|
mergeMiddlewareResponseHeaders(headers, options.middlewareContext.headers);
|
|
79
91
|
applyRscCompatibilityIdHeader(headers);
|
|
80
92
|
applyTimingHeader(headers, options.timing);
|
|
@@ -88,8 +100,9 @@ function buildAppPageHtmlResponse(body, options) {
|
|
|
88
100
|
"Content-Type": "text/html; charset=utf-8",
|
|
89
101
|
Vary: VINEXT_RSC_VARY_HEADER
|
|
90
102
|
});
|
|
103
|
+
applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);
|
|
91
104
|
if (options.policy.cacheControl) headers.set("Cache-Control", options.policy.cacheControl);
|
|
92
|
-
if (options.policy.cacheState) headers
|
|
105
|
+
if (options.policy.cacheState) setCacheStateHeaders(headers, options.policy.cacheState);
|
|
93
106
|
if (options.draftCookie) headers.append("Set-Cookie", options.draftCookie);
|
|
94
107
|
if (options.fontLinkHeader) headers.set("Link", options.fontLinkHeader);
|
|
95
108
|
mergeMiddlewareResponseHeaders(headers, options.middlewareContext.headers);
|
|
@@ -100,6 +113,6 @@ function buildAppPageHtmlResponse(body, options) {
|
|
|
100
113
|
});
|
|
101
114
|
}
|
|
102
115
|
//#endregion
|
|
103
|
-
export { buildAppPageHtmlResponse, buildAppPageRscResponse, mergeMiddlewareResponseHeaders, resolveAppPageHtmlResponsePolicy, resolveAppPageRscResponsePolicy };
|
|
116
|
+
export { applyEdgeRuntimeHeader, buildAppPageHtmlResponse, buildAppPageRscResponse, mergeMiddlewareResponseHeaders, resolveAppPageHtmlResponsePolicy, resolveAppPageRscResponsePolicy };
|
|
104
117
|
|
|
105
118
|
//# sourceMappingURL=app-page-response.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-page-response.js","names":[],"sources":["../../src/server/app-page-response.ts"],"sourcesContent":["import {\n buildRevalidateCacheControl,\n NO_STORE_CACHE_CONTROL,\n STATIC_CACHE_CONTROL,\n} from \"./cache-control.js\";\nimport {\n VINEXT_CACHE_HEADER,\n VINEXT_MOUNTED_SLOTS_HEADER,\n VINEXT_PARAMS_HEADER,\n VINEXT_TIMING_HEADER,\n} from \"./headers.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\";\n\nexport type AppPageMiddlewareContext = {\n headers: Headers | null;\n status: number | null;\n};\n\nexport type AppPageResponseTiming = {\n compileEnd?: number;\n handlerStart: number;\n renderEnd?: number;\n responseKind: \"html\" | \"rsc\";\n};\n\ntype AppPageResponsePolicy = {\n cacheControl?: string;\n cacheState?: \"MISS\" | \"STATIC\";\n};\n\ntype ResolveAppPageResponsePolicyBaseOptions = {\n isDraftMode: boolean;\n isDynamicError: boolean;\n isForceDynamic: boolean;\n isForceStatic: boolean;\n isProduction: boolean;\n expireSeconds?: number;\n revalidateSeconds: number | null;\n};\n\ntype ResolveAppPageRscResponsePolicyOptions = {\n dynamicUsedDuringBuild: boolean;\n} & ResolveAppPageResponsePolicyBaseOptions;\n\ntype ResolveAppPageHtmlResponsePolicyOptions = {\n dynamicUsedDuringRender: boolean;\n isProgressiveActionRender?: boolean;\n hasScriptNonce: boolean;\n} & ResolveAppPageResponsePolicyBaseOptions;\n\ntype AppPageHtmlResponsePolicy = {\n shouldWriteToCache: boolean;\n} & AppPageResponsePolicy;\n\ntype BuildAppPageRscResponseOptions = {\n middlewareContext: AppPageMiddlewareContext;\n mountedSlotsHeader?: string | null;\n params?: Record<string, unknown>;\n policy: AppPageResponsePolicy;\n timing?: AppPageResponseTiming;\n};\n\ntype BuildAppPageHtmlResponseOptions = {\n draftCookie?: string | null;\n fontLinkHeader?: string;\n middlewareContext: AppPageMiddlewareContext;\n policy: AppPageResponsePolicy;\n timing?: AppPageResponseTiming;\n};\n\nfunction applyTimingHeader(headers: Headers, timing?: AppPageResponseTiming): void {\n if (!timing) {\n return;\n }\n\n const handlerStart = Math.round(timing.handlerStart);\n const compileMs =\n timing.compileEnd !== undefined ? Math.round(timing.compileEnd - timing.handlerStart) : -1;\n const renderMs =\n timing.responseKind === \"html\" &&\n timing.renderEnd !== undefined &&\n timing.compileEnd !== undefined\n ? Math.round(timing.renderEnd - timing.compileEnd)\n : -1;\n\n headers.set(VINEXT_TIMING_HEADER, `${handlerStart},${compileMs},${renderMs}`);\n}\n\nexport function resolveAppPageRscResponsePolicy(\n options: ResolveAppPageRscResponsePolicyOptions,\n): AppPageResponsePolicy {\n if (options.isDraftMode) {\n return { cacheControl: NO_STORE_CACHE_CONTROL };\n }\n\n if (options.isForceDynamic || options.dynamicUsedDuringBuild) {\n return { cacheControl: NO_STORE_CACHE_CONTROL };\n }\n\n // revalidate = 0 means \"always dynamic, never cache\" — equivalent to\n // force-dynamic for caching purposes. Must be checked before the\n // isForceStatic/isDynamicError branch below, which uses !revalidateSeconds\n // and would incorrectly catch 0 as a falsy value.\n if (options.revalidateSeconds === 0) {\n return { cacheControl: NO_STORE_CACHE_CONTROL };\n }\n\n if (\n ((options.isForceStatic || options.isDynamicError) && !options.revalidateSeconds) ||\n options.revalidateSeconds === Infinity\n ) {\n return {\n cacheControl: STATIC_CACHE_CONTROL,\n cacheState: \"STATIC\",\n };\n }\n\n if (options.revalidateSeconds) {\n return {\n cacheControl: buildRevalidateCacheControl(options.revalidateSeconds, options.expireSeconds),\n // Emit MISS as part of the initial RSC response shape rather than bolting\n // it on later in the cache-write block so response construction stays\n // centralized in this helper. This matches the eventual write path: the\n // first ISR-eligible production response is a cache miss.\n cacheState: options.isProduction ? \"MISS\" : undefined,\n };\n }\n\n return {};\n}\n\nexport function resolveAppPageHtmlResponsePolicy(\n options: ResolveAppPageHtmlResponsePolicyOptions,\n): AppPageHtmlResponsePolicy {\n if (options.isDraftMode) {\n return {\n cacheControl: NO_STORE_CACHE_CONTROL,\n shouldWriteToCache: false,\n };\n }\n\n if (options.isForceDynamic) {\n return {\n cacheControl: NO_STORE_CACHE_CONTROL,\n shouldWriteToCache: false,\n };\n }\n\n if (options.hasScriptNonce) {\n return {\n cacheControl: NO_STORE_CACHE_CONTROL,\n shouldWriteToCache: false,\n };\n }\n\n if (options.isProgressiveActionRender) {\n return {\n cacheControl: NO_STORE_CACHE_CONTROL,\n shouldWriteToCache: false,\n };\n }\n\n // revalidate = 0 means \"always dynamic, never cache\" — equivalent to\n // force-dynamic for caching purposes. Must be checked before the\n // isForceStatic/isDynamicError branch below, which matches revalidateSeconds\n // === 0 and would incorrectly return a static Cache-Control.\n if (options.revalidateSeconds === 0) {\n return {\n cacheControl: NO_STORE_CACHE_CONTROL,\n shouldWriteToCache: false,\n };\n }\n\n if ((options.isForceStatic || options.isDynamicError) && options.revalidateSeconds === null) {\n return {\n cacheControl: STATIC_CACHE_CONTROL,\n cacheState: \"STATIC\",\n shouldWriteToCache: false,\n };\n }\n\n if (options.dynamicUsedDuringRender) {\n return {\n cacheControl: NO_STORE_CACHE_CONTROL,\n shouldWriteToCache: false,\n };\n }\n\n if (\n options.revalidateSeconds !== null &&\n options.revalidateSeconds > 0 &&\n options.revalidateSeconds !== Infinity\n ) {\n return {\n cacheControl: buildRevalidateCacheControl(options.revalidateSeconds, options.expireSeconds),\n cacheState: options.isProduction ? \"MISS\" : undefined,\n shouldWriteToCache: options.isProduction,\n };\n }\n\n if (options.revalidateSeconds === Infinity) {\n return {\n cacheControl: STATIC_CACHE_CONTROL,\n cacheState: \"STATIC\",\n shouldWriteToCache: false,\n };\n }\n\n return { shouldWriteToCache: false };\n}\n\nexport { mergeMiddlewareResponseHeaders };\n\nexport function buildAppPageRscResponse(\n body: ReadableStream,\n options: BuildAppPageRscResponseOptions,\n): Response {\n const headers = new Headers({\n \"Content-Type\": VINEXT_RSC_CONTENT_TYPE,\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n\n if (options.params && Object.keys(options.params).length > 0) {\n // encodeURIComponent so non-ASCII params (e.g. Korean slugs) survive the\n // HTTP ByteString constraint — Headers.set() rejects chars above U+00FF.\n headers.set(VINEXT_PARAMS_HEADER, encodeURIComponent(JSON.stringify(options.params)));\n }\n if (options.mountedSlotsHeader) {\n headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);\n }\n if (options.policy.cacheControl) {\n headers.set(\"Cache-Control\", options.policy.cacheControl);\n }\n if (options.policy.cacheState) {\n headers.set(VINEXT_CACHE_HEADER, options.policy.cacheState);\n }\n mergeMiddlewareResponseHeaders(headers, options.middlewareContext.headers);\n applyRscCompatibilityIdHeader(headers);\n\n applyTimingHeader(headers, options.timing);\n\n return new Response(body, {\n status: options.middlewareContext.status ?? 200,\n headers,\n });\n}\n\nexport function buildAppPageHtmlResponse(\n body: ReadableStream,\n options: BuildAppPageHtmlResponseOptions,\n): Response {\n const headers = new Headers({\n \"Content-Type\": \"text/html; charset=utf-8\",\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n\n if (options.policy.cacheControl) {\n headers.set(\"Cache-Control\", options.policy.cacheControl);\n }\n if (options.policy.cacheState) {\n headers.set(VINEXT_CACHE_HEADER, options.policy.cacheState);\n }\n if (options.draftCookie) {\n headers.append(\"Set-Cookie\", options.draftCookie);\n }\n if (options.fontLinkHeader) {\n headers.set(\"Link\", options.fontLinkHeader);\n }\n\n mergeMiddlewareResponseHeaders(headers, options.middlewareContext.headers);\n\n applyTimingHeader(headers, options.timing);\n\n return new Response(body, {\n status: options.middlewareContext.status ?? 200,\n headers,\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-page-response.js","names":[],"sources":["../../src/server/app-page-response.ts"],"sourcesContent":["import {\n buildRevalidateCacheControl,\n NO_STORE_CACHE_CONTROL,\n STATIC_CACHE_CONTROL,\n} from \"./cache-control.js\";\nimport {\n VINEXT_MOUNTED_SLOTS_HEADER,\n VINEXT_PARAMS_HEADER,\n VINEXT_TIMING_HEADER,\n} from \"./headers.js\";\nimport { setCacheStateHeaders } from \"./cache-headers.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\";\n\nexport type AppPageMiddlewareContext = {\n headers: Headers | null;\n status: number | null;\n};\n\nexport type AppPageResponseTiming = {\n compileEnd?: number;\n handlerStart: number;\n renderEnd?: number;\n responseKind: \"html\" | \"rsc\";\n};\n\ntype AppPageResponsePolicy = {\n cacheControl?: string;\n cacheState?: \"MISS\" | \"STATIC\";\n};\n\ntype ResolveAppPageResponsePolicyBaseOptions = {\n isDraftMode: boolean;\n isDynamicError: boolean;\n isForceDynamic: boolean;\n isForceStatic: boolean;\n isProduction: boolean;\n expireSeconds?: number;\n revalidateSeconds: number | null;\n};\n\ntype ResolveAppPageRscResponsePolicyOptions = {\n dynamicUsedDuringBuild: boolean;\n} & ResolveAppPageResponsePolicyBaseOptions;\n\ntype ResolveAppPageHtmlResponsePolicyOptions = {\n dynamicUsedDuringRender: boolean;\n isProgressiveActionRender?: boolean;\n hasScriptNonce: boolean;\n} & ResolveAppPageResponsePolicyBaseOptions;\n\ntype AppPageHtmlResponsePolicy = {\n shouldWriteToCache: boolean;\n} & AppPageResponsePolicy;\n\ntype BuildAppPageRscResponseOptions = {\n isEdgeRuntime?: boolean;\n middlewareContext: AppPageMiddlewareContext;\n mountedSlotsHeader?: string | null;\n params?: Record<string, unknown>;\n policy: AppPageResponsePolicy;\n timing?: AppPageResponseTiming;\n};\n\ntype BuildAppPageHtmlResponseOptions = {\n draftCookie?: string | null;\n fontLinkHeader?: string;\n isEdgeRuntime?: boolean;\n middlewareContext: AppPageMiddlewareContext;\n policy: AppPageResponsePolicy;\n timing?: AppPageResponseTiming;\n};\n\nfunction applyTimingHeader(headers: Headers, timing?: AppPageResponseTiming): void {\n if (!timing) {\n return;\n }\n\n const handlerStart = Math.round(timing.handlerStart);\n const compileMs =\n timing.compileEnd !== undefined ? Math.round(timing.compileEnd - timing.handlerStart) : -1;\n const renderMs =\n timing.responseKind === \"html\" &&\n timing.renderEnd !== undefined &&\n timing.compileEnd !== undefined\n ? Math.round(timing.renderEnd - timing.compileEnd)\n : -1;\n\n headers.set(VINEXT_TIMING_HEADER, `${handlerStart},${compileMs},${renderMs}`);\n}\n\nexport function resolveAppPageRscResponsePolicy(\n options: ResolveAppPageRscResponsePolicyOptions,\n): AppPageResponsePolicy {\n if (options.isDraftMode) {\n return { cacheControl: NO_STORE_CACHE_CONTROL };\n }\n\n if (options.isForceDynamic || options.dynamicUsedDuringBuild) {\n return { cacheControl: NO_STORE_CACHE_CONTROL };\n }\n\n // revalidate = 0 means \"always dynamic, never cache\" — equivalent to\n // force-dynamic for caching purposes. Must be checked before the\n // isForceStatic/isDynamicError branch below, which uses !revalidateSeconds\n // and would incorrectly catch 0 as a falsy value.\n if (options.revalidateSeconds === 0) {\n return { cacheControl: NO_STORE_CACHE_CONTROL };\n }\n\n if (\n ((options.isForceStatic || options.isDynamicError) && !options.revalidateSeconds) ||\n options.revalidateSeconds === Infinity\n ) {\n return {\n cacheControl: STATIC_CACHE_CONTROL,\n cacheState: \"STATIC\",\n };\n }\n\n if (options.revalidateSeconds) {\n return {\n cacheControl: buildRevalidateCacheControl(options.revalidateSeconds, options.expireSeconds),\n // Emit MISS as part of the initial RSC response shape rather than bolting\n // it on later in the cache-write block so response construction stays\n // centralized in this helper. This matches the eventual write path: the\n // first ISR-eligible production response is a cache miss.\n cacheState: options.isProduction ? \"MISS\" : undefined,\n };\n }\n\n return {};\n}\n\nexport function resolveAppPageHtmlResponsePolicy(\n options: ResolveAppPageHtmlResponsePolicyOptions,\n): AppPageHtmlResponsePolicy {\n if (options.isDraftMode) {\n return {\n cacheControl: NO_STORE_CACHE_CONTROL,\n shouldWriteToCache: false,\n };\n }\n\n if (options.isForceDynamic) {\n return {\n cacheControl: NO_STORE_CACHE_CONTROL,\n shouldWriteToCache: false,\n };\n }\n\n if (options.hasScriptNonce) {\n return {\n cacheControl: NO_STORE_CACHE_CONTROL,\n shouldWriteToCache: false,\n };\n }\n\n if (options.isProgressiveActionRender) {\n return {\n cacheControl: NO_STORE_CACHE_CONTROL,\n shouldWriteToCache: false,\n };\n }\n\n // revalidate = 0 means \"always dynamic, never cache\" — equivalent to\n // force-dynamic for caching purposes. Must be checked before the\n // isForceStatic/isDynamicError branch below, which matches revalidateSeconds\n // === 0 and would incorrectly return a static Cache-Control.\n if (options.revalidateSeconds === 0) {\n return {\n cacheControl: NO_STORE_CACHE_CONTROL,\n shouldWriteToCache: false,\n };\n }\n\n if ((options.isForceStatic || options.isDynamicError) && options.revalidateSeconds === null) {\n return {\n cacheControl: STATIC_CACHE_CONTROL,\n cacheState: \"STATIC\",\n shouldWriteToCache: false,\n };\n }\n\n if (options.dynamicUsedDuringRender) {\n return {\n cacheControl: NO_STORE_CACHE_CONTROL,\n shouldWriteToCache: false,\n };\n }\n\n if (\n options.revalidateSeconds !== null &&\n options.revalidateSeconds > 0 &&\n options.revalidateSeconds !== Infinity\n ) {\n return {\n cacheControl: buildRevalidateCacheControl(options.revalidateSeconds, options.expireSeconds),\n cacheState: options.isProduction ? \"MISS\" : undefined,\n shouldWriteToCache: options.isProduction,\n };\n }\n\n if (options.revalidateSeconds === Infinity) {\n return {\n cacheControl: STATIC_CACHE_CONTROL,\n cacheState: \"STATIC\",\n shouldWriteToCache: false,\n };\n }\n\n return { shouldWriteToCache: false };\n}\n\nexport { mergeMiddlewareResponseHeaders };\n\n/**\n * Mirror Next.js' edge-runtime marker (set in edge-ssr-app.ts). Only routes\n * whose resolved segment config is `runtime = \"edge\"` should advertise it —\n * nodejs-runtime routes must not, otherwise downstream consumers can't tell\n * the configured runtime from the response. Centralized so every response\n * construction site can opt in without re-deriving the header name.\n */\nexport function applyEdgeRuntimeHeader(headers: Headers, isEdgeRuntime: boolean | undefined): void {\n if (isEdgeRuntime) {\n headers.set(\"x-edge-runtime\", \"1\");\n }\n}\n\nexport function buildAppPageRscResponse(\n body: ReadableStream,\n options: BuildAppPageRscResponseOptions,\n): Response {\n const headers = new Headers({\n \"Content-Type\": VINEXT_RSC_CONTENT_TYPE,\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n\n applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);\n\n if (options.params && Object.keys(options.params).length > 0) {\n // encodeURIComponent so non-ASCII params (e.g. Korean slugs) survive the\n // HTTP ByteString constraint — Headers.set() rejects chars above U+00FF.\n headers.set(VINEXT_PARAMS_HEADER, encodeURIComponent(JSON.stringify(options.params)));\n }\n if (options.mountedSlotsHeader) {\n headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);\n }\n if (options.policy.cacheControl) {\n headers.set(\"Cache-Control\", options.policy.cacheControl);\n }\n if (options.policy.cacheState) {\n setCacheStateHeaders(headers, options.policy.cacheState);\n }\n mergeMiddlewareResponseHeaders(headers, options.middlewareContext.headers);\n applyRscCompatibilityIdHeader(headers);\n\n applyTimingHeader(headers, options.timing);\n\n return new Response(body, {\n status: options.middlewareContext.status ?? 200,\n headers,\n });\n}\n\nexport function buildAppPageHtmlResponse(\n body: ReadableStream,\n options: BuildAppPageHtmlResponseOptions,\n): Response {\n const headers = new Headers({\n \"Content-Type\": \"text/html; charset=utf-8\",\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n\n applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);\n\n if (options.policy.cacheControl) {\n headers.set(\"Cache-Control\", options.policy.cacheControl);\n }\n if (options.policy.cacheState) {\n setCacheStateHeaders(headers, options.policy.cacheState);\n }\n if (options.draftCookie) {\n headers.append(\"Set-Cookie\", options.draftCookie);\n }\n if (options.fontLinkHeader) {\n headers.set(\"Link\", options.fontLinkHeader);\n }\n\n mergeMiddlewareResponseHeaders(headers, options.middlewareContext.headers);\n\n applyTimingHeader(headers, options.timing);\n\n return new Response(body, {\n status: options.middlewareContext.status ?? 200,\n headers,\n });\n}\n"],"mappings":"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"}
|
|
@@ -92,6 +92,7 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
|
|
|
92
92
|
globalErrorModule?: TErrorModule | null;
|
|
93
93
|
makeThenableParams: (params: AppPageParams) => unknown;
|
|
94
94
|
matchedParams: AppPageParams;
|
|
95
|
+
metadataPlacement?: "body" | "head";
|
|
95
96
|
resolvedMetadata: Metadata | null;
|
|
96
97
|
resolvedMetadataPathname?: string;
|
|
97
98
|
resolvedViewport: Viewport;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { shouldSuppressLoadingBoundaries } from "./app-rsc-render-mode.js";
|
|
2
1
|
import { AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
3
|
-
import "./app-
|
|
2
|
+
import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL, shouldSuppressLoadingBoundaries } from "./app-rsc-render-mode.js";
|
|
3
|
+
import { APP_PREFETCH_LOADING_SHELL_MARKER_KEY } from "./app-elements.js";
|
|
4
4
|
import { ErrorBoundary, ForbiddenBoundary, NotFoundBoundary, RedirectBoundary, UnauthorizedBoundary } from "../shims/error-boundary.js";
|
|
5
|
+
import { AppRouterScrollTarget } from "../shims/app-router-scroll.js";
|
|
5
6
|
import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
|
|
6
|
-
import { MetadataHead, ViewportHead } from "../shims/metadata.js";
|
|
7
|
+
import { MetadataHead, ViewportHead, renderMetadataToHtml } from "../shims/metadata.js";
|
|
7
8
|
import { Children as Children$1, ParallelSlot, Slot } from "../shims/slot.js";
|
|
8
9
|
import { createAppRenderDependency, renderAfterAppDependencies, renderWithAppDependencyBarrier } from "./app-render-dependency.js";
|
|
9
10
|
import { resolveAppPageSegmentParams } from "./app-page-params.js";
|
|
@@ -100,18 +101,26 @@ function createAppPageSlotBindings(route, layoutEntries, resolveSlotOverride) {
|
|
|
100
101
|
}
|
|
101
102
|
return normalizeAppElementsSlotBindings(bindings, { layoutIds: layoutEntries.map((entry) => entry.id) });
|
|
102
103
|
}
|
|
103
|
-
function createAppPageRouteHead(metadata, viewport, pathname) {
|
|
104
|
+
function createAppPageRouteHead(metadata, viewport, pathname, metadataPlacement) {
|
|
104
105
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
105
106
|
/* @__PURE__ */ jsx("meta", { charSet: "utf-8" }),
|
|
106
|
-
metadata ? /* @__PURE__ */ jsx(MetadataHead, {
|
|
107
|
+
metadata && metadataPlacement === "head" ? /* @__PURE__ */ jsx(MetadataHead, {
|
|
107
108
|
metadata,
|
|
108
109
|
pathname
|
|
109
110
|
}) : null,
|
|
110
111
|
/* @__PURE__ */ jsx(ViewportHead, { viewport })
|
|
111
112
|
] });
|
|
112
113
|
}
|
|
114
|
+
function createAppPageRouteBodyMetadata(metadata, pathname, metadataPlacement) {
|
|
115
|
+
if (!metadata || metadataPlacement !== "body") return null;
|
|
116
|
+
return /* @__PURE__ */ jsx("div", {
|
|
117
|
+
hidden: true,
|
|
118
|
+
dangerouslySetInnerHTML: { __html: renderMetadataToHtml(metadata, pathname) }
|
|
119
|
+
});
|
|
120
|
+
}
|
|
113
121
|
function buildAppPageElements(options) {
|
|
114
122
|
const interceptionContext = options.interceptionContext ?? null;
|
|
123
|
+
const renderMode = options.renderMode ?? "navigation";
|
|
115
124
|
const routeSegments = options.route.routeSegments ?? [];
|
|
116
125
|
const routeResetKey = resolveAppPageRouteStateKey(routeSegments, options.matchedParams);
|
|
117
126
|
const routeId = AppElementsWire.encodeRouteId(options.routePath, interceptionContext);
|
|
@@ -119,6 +128,7 @@ function buildAppPageElements(options) {
|
|
|
119
128
|
const layoutEntries = createAppPageLayoutEntries(options.route);
|
|
120
129
|
const templateEntries = createAppPageTemplateEntries(options.route);
|
|
121
130
|
const errorEntries = createAppPageErrorEntries(options.route);
|
|
131
|
+
const metadataPlacement = options.metadataPlacement ?? "head";
|
|
122
132
|
const layoutEntriesByTreePosition = /* @__PURE__ */ new Map();
|
|
123
133
|
const templateEntriesByTreePosition = /* @__PURE__ */ new Map();
|
|
124
134
|
const errorEntriesByTreePosition = /* @__PURE__ */ new Map();
|
|
@@ -177,7 +187,10 @@ function buildAppPageElements(options) {
|
|
|
177
187
|
templateDependenciesBeforeById.set(templateEntry.id, [...pageDependencies]);
|
|
178
188
|
pageDependencies.push(templateDependency);
|
|
179
189
|
}
|
|
180
|
-
|
|
190
|
+
const routeLoadingComponent = getDefaultExport(options.route.loading);
|
|
191
|
+
const isPrefetchLoadingShell = renderMode === APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL;
|
|
192
|
+
if (isPrefetchLoadingShell && routeLoadingComponent !== null) elements[APP_PREFETCH_LOADING_SHELL_MARKER_KEY] = "LoadingBoundary";
|
|
193
|
+
elements[pageId] = isPrefetchLoadingShell ? null : renderAfterAppDependencies(options.element, pageDependencies);
|
|
181
194
|
for (const templateEntry of templateEntries) {
|
|
182
195
|
const templateComponent = getDefaultExport(templateEntry.templateModule);
|
|
183
196
|
if (!templateComponent) continue;
|
|
@@ -247,7 +260,7 @@ function buildAppPageElements(options) {
|
|
|
247
260
|
children: slotElement
|
|
248
261
|
});
|
|
249
262
|
const slotLoadingComponent = getDefaultExport(slot.loading);
|
|
250
|
-
if (slotLoadingComponent && !shouldSuppressLoadingBoundaries(
|
|
263
|
+
if (slotLoadingComponent && !shouldSuppressLoadingBoundaries(renderMode)) slotElement = /* @__PURE__ */ jsx(Suspense, {
|
|
251
264
|
fallback: /* @__PURE__ */ jsx(slotLoadingComponent, {}),
|
|
252
265
|
children: slotElement
|
|
253
266
|
}, slotResetKey);
|
|
@@ -261,14 +274,17 @@ function buildAppPageElements(options) {
|
|
|
261
274
|
}
|
|
262
275
|
let routeChildren = /* @__PURE__ */ jsx(LayoutSegmentProvider, {
|
|
263
276
|
segmentMap: { children: [] },
|
|
264
|
-
children: /* @__PURE__ */ jsx(Slot, { id: pageId })
|
|
277
|
+
children: /* @__PURE__ */ jsx(AppRouterScrollTarget, { children: /* @__PURE__ */ jsx(Slot, { id: pageId }) })
|
|
265
278
|
});
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
279
|
+
if (isPrefetchLoadingShell) if (routeLoadingComponent === null) routeChildren = null;
|
|
280
|
+
else routeChildren = /* @__PURE__ */ jsx(routeLoadingComponent, {});
|
|
281
|
+
else {
|
|
282
|
+
routeChildren = /* @__PURE__ */ jsx(RedirectBoundary, { children: routeChildren });
|
|
283
|
+
if (routeLoadingComponent && !shouldSuppressLoadingBoundaries(renderMode)) routeChildren = /* @__PURE__ */ jsx(Suspense, {
|
|
284
|
+
fallback: /* @__PURE__ */ jsx(routeLoadingComponent, {}),
|
|
285
|
+
children: routeChildren
|
|
286
|
+
}, routeResetKey);
|
|
287
|
+
}
|
|
272
288
|
const lastLayoutErrorModule = errorEntries.length > 0 ? errorEntries[errorEntries.length - 1].errorModule : null;
|
|
273
289
|
const notFoundComponent = getDefaultExport(options.route.notFound) ?? getDefaultExport(options.rootNotFoundModule);
|
|
274
290
|
if (notFoundComponent) routeChildren = /* @__PURE__ */ jsx(NotFoundBoundary, {
|
|
@@ -358,7 +374,11 @@ function buildAppPageElements(options) {
|
|
|
358
374
|
fallback: globalErrorComponent,
|
|
359
375
|
children: routeChildren
|
|
360
376
|
});
|
|
361
|
-
elements[routeId] = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
377
|
+
elements[routeId] = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
378
|
+
createAppPageRouteHead(options.resolvedMetadata, options.resolvedViewport, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement),
|
|
379
|
+
routeChildren,
|
|
380
|
+
createAppPageRouteBodyMetadata(options.resolvedMetadata, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement)
|
|
381
|
+
] });
|
|
362
382
|
return elements;
|
|
363
383
|
}
|
|
364
384
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-page-route-wiring.js","names":["Children","SlotComponent","InterceptLayoutComponent","SlotLayoutComponent","SlotLoadingComponent","RouteLoadingComponent","NotFoundComponent","ForbiddenComponent","UnauthorizedComponent","LayoutNotFoundComponent","LayoutForbiddenComponent","LayoutUnauthorizedComponent"],"sources":["../../src/server/app-page-route-wiring.tsx"],"sourcesContent":["import { Suspense, type ComponentType, type ReactNode } from \"react\";\nimport {\n AppElementsWire,\n normalizeAppElementsSlotBindings,\n type AppElements,\n type AppElementsInterception,\n type AppElementsSlotBinding,\n} from \"./app-elements.js\";\nimport {\n ErrorBoundary,\n ForbiddenBoundary,\n NotFoundBoundary,\n RedirectBoundary,\n UnauthorizedBoundary,\n} from \"vinext/shims/error-boundary\";\nimport type { AppRouteSemanticIds } from \"../routing/app-route-graph.js\";\nimport { LayoutSegmentProvider } from \"vinext/shims/layout-segment-context\";\nimport { MetadataHead, ViewportHead, type Metadata, type Viewport } from \"vinext/shims/metadata\";\nimport { Children, ParallelSlot, Slot } from \"vinext/shims/slot\";\nimport type { AppPageParams } from \"./app-page-boundary.js\";\nimport {\n createAppRenderDependency,\n renderAfterAppDependencies,\n renderWithAppDependencyBarrier,\n type AppRenderDependency,\n} from \"./app-render-dependency.js\";\nimport { resolveAppPageSegmentParams } from \"./app-page-params.js\";\nimport {\n APP_RSC_RENDER_MODE_NAVIGATION,\n shouldSuppressLoadingBoundaries,\n type AppRscRenderMode,\n} from \"./app-rsc-render-mode.js\";\nimport {\n resolveAppPageChildSegments,\n resolveAppPageRouteStateKey,\n resolveAppPageSegmentStateKey,\n} from \"./app-page-segment-state.js\";\n\nexport { resolveAppPageChildSegments } from \"./app-page-segment-state.js\";\n\ntype AppPageComponentProps = {\n children?: ReactNode;\n error?: unknown;\n params?: unknown;\n reset?: () => void;\n} & Record<string, unknown>;\n\ntype AppPageComponent = ComponentType<AppPageComponentProps>;\ntype AppPageErrorComponent = ComponentType<{ error: unknown; reset: () => void }>;\n\nexport type AppPageModule = Record<string, unknown> & {\n default?: AppPageComponent | null | undefined;\n};\n\nexport type AppPageErrorModule = Record<string, unknown> & {\n default?: AppPageErrorComponent | null | undefined;\n};\n\ntype AppPageRouteWiringSlot<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n /** Graph-owned semantic slot identity. */\n id?: string | null;\n /** Slot prop name passed to the owning layout (e.g. \"modal\" from @modal). */\n name: string;\n default?: TModule | null;\n error?: TErrorModule | null;\n layout?: TModule | null;\n layoutIndex: number;\n loading?: TModule | null;\n page?: TModule | null;\n routeSegments?: readonly string[] | null;\n /**\n * Full URL pattern parts for the slot's mirrored sub-page. Set when the\n * slot's params may differ from the route's (e.g. inherited slot whose\n * dynamic markers have different names than the route's). The runtime\n * matches the request URL against these parts to extract slot params.\n */\n slotPatternParts?: readonly string[] | null;\n /** Param names captured by `slotPatternParts`, in order. */\n slotParamNames?: readonly string[] | null;\n};\n\nexport type AppPageRouteWiringRoute<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n ids?: AppRouteSemanticIds | null;\n error?: TErrorModule | null;\n errorPaths?: readonly TErrorModule[] | null;\n errors?: readonly (TErrorModule | null | undefined)[] | null;\n errorTreePositions?: readonly number[] | null;\n layoutTreePositions?: readonly number[] | null;\n layouts: readonly (TModule | null | undefined)[];\n loading?: TModule | null;\n notFound?: TModule | null;\n notFounds?: readonly (TModule | null | undefined)[] | null;\n forbidden?: TModule | null;\n forbiddens?: readonly (TModule | null | undefined)[] | null;\n unauthorized?: TModule | null;\n unauthorizeds?: readonly (TModule | null | undefined)[] | null;\n routeSegments?: readonly string[];\n /**\n * Keyed by stable slot id (name + owner path), not necessarily the slot prop name.\n */\n slots?: Readonly<Record<string, AppPageRouteWiringSlot<TModule, TErrorModule>>> | null;\n templateTreePositions?: readonly number[] | null;\n templates?: readonly (TModule | null | undefined)[] | null;\n};\n\nexport type AppPageSlotOverride<TModule extends AppPageModule = AppPageModule> = {\n layoutModules?: readonly (TModule | null | undefined)[] | null;\n /**\n * The page module to render for this slot. Optional — when omitted, the\n * slot's existing `page` is used (e.g. when the override only changes the\n * slot's `params` for an inherited mirror with distinct param names).\n */\n pageModule?: TModule | null;\n params?: AppPageParams;\n props?: Readonly<Record<string, unknown>>;\n};\n\ntype AppPageLayoutEntry<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n errorModule?: TErrorModule | null | undefined;\n forbiddenModule?: TModule | null | undefined;\n id: string;\n layoutModule?: TModule | null | undefined;\n notFoundModule?: TModule | null | undefined;\n unauthorizedModule?: TModule | null | undefined;\n treePath: string;\n treePosition: number;\n};\n\ntype BuildAppPageRouteElementOptions<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n element: ReactNode;\n globalErrorModule?: TErrorModule | null;\n makeThenableParams: (params: AppPageParams) => unknown;\n matchedParams: AppPageParams;\n resolvedMetadata: Metadata | null;\n resolvedMetadataPathname?: string;\n resolvedViewport: Viewport;\n rootForbiddenModule?: TModule | null;\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n route: AppPageRouteWiringRoute<TModule, TErrorModule>;\n slotOverrides?: Readonly<Record<string, AppPageSlotOverride<TModule>>> | null;\n};\n\ntype BuildAppPageElementsOptions<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = BuildAppPageRouteElementOptions<TModule, TErrorModule> & {\n interception?: AppElementsInterception | null;\n interceptionContext?: string | null;\n isRscRequest?: boolean;\n mountedSlotIds?: ReadonlySet<string> | null;\n renderMode?: AppRscRenderMode;\n routePath: string;\n};\n\ntype AppPageTemplateEntry<TModule extends AppPageModule = AppPageModule> = {\n id: string;\n templateModule?: TModule | null | undefined;\n treePath: string;\n treePosition: number;\n};\n\ntype AppPageErrorEntry<TErrorModule extends AppPageErrorModule = AppPageErrorModule> = {\n errorModule?: TErrorModule | null | undefined;\n treePosition: number;\n};\n\nfunction getDefaultExport<TModule extends AppPageModule>(\n module: TModule | null | undefined,\n): AppPageComponent | null {\n return module?.default ?? null;\n}\n\nfunction getErrorBoundaryExport<TModule extends AppPageErrorModule>(\n module: TModule | null | undefined,\n): AppPageErrorComponent | null {\n return module?.default ?? null;\n}\n\nexport function createAppPageTreePath(\n routeSegments: readonly string[] | null | undefined,\n treePosition: number,\n): string {\n const treePathSegments = routeSegments?.slice(0, treePosition) ?? [];\n if (treePathSegments.length === 0) {\n return \"/\";\n }\n return `/${treePathSegments.join(\"/\")}`;\n}\n\nexport function createAppPageLayoutEntries<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(\n route: Pick<\n AppPageRouteWiringRoute<TModule, TErrorModule>,\n | \"errors\"\n | \"errorTreePositions\"\n | \"layoutTreePositions\"\n | \"layouts\"\n | \"notFounds\"\n | \"routeSegments\"\n > & {\n forbiddens?: readonly (TModule | null | undefined)[] | null;\n unauthorizeds?: readonly (TModule | null | undefined)[] | null;\n },\n): AppPageLayoutEntry<TModule, TErrorModule>[] {\n return route.layouts.map((layoutModule, index) => {\n const treePosition = route.layoutTreePositions?.[index] ?? 0;\n const treePath = createAppPageTreePath(route.routeSegments, treePosition);\n return {\n errorModule: route.errorTreePositions ? null : (route.errors?.[index] ?? null),\n forbiddenModule: route.forbiddens?.[index] ?? null,\n id: AppElementsWire.encodeLayoutId(treePath),\n layoutModule,\n notFoundModule: route.notFounds?.[index] ?? null,\n unauthorizedModule: route.unauthorizeds?.[index] ?? null,\n treePath,\n treePosition,\n };\n });\n}\n\nfunction createAppPageTemplateEntries<TModule extends AppPageModule>(\n route: Pick<\n AppPageRouteWiringRoute<TModule>,\n \"routeSegments\" | \"templateTreePositions\" | \"templates\"\n >,\n): AppPageTemplateEntry<TModule>[] {\n return (route.templates ?? []).map((templateModule, index) => {\n const treePosition = route.templateTreePositions?.[index] ?? 0;\n const treePath = createAppPageTreePath(route.routeSegments, treePosition);\n return {\n id: AppElementsWire.encodeTemplateId(treePath),\n templateModule,\n treePath,\n treePosition,\n };\n });\n}\n\nfunction createAppPageErrorEntries<TErrorModule extends AppPageErrorModule>(\n route: Pick<\n AppPageRouteWiringRoute<AppPageModule, TErrorModule>,\n \"errorPaths\" | \"errors\" | \"errorTreePositions\"\n >,\n): AppPageErrorEntry<TErrorModule>[] {\n return (route.errorPaths ?? route.errors ?? []).flatMap((errorModule, index) => {\n if (!errorModule) return [];\n const treePosition = route.errorTreePositions?.[index];\n if (treePosition === undefined) return [];\n return [{ errorModule, treePosition }];\n });\n}\n\nfunction createAppPageParallelSlotEntries<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(\n layoutIndex: number,\n layoutEntries: readonly AppPageLayoutEntry<TModule, TErrorModule>[],\n route: AppPageRouteWiringRoute<TModule, TErrorModule>,\n getEffectiveSlotParams: (slotKey: string, slotName: string) => AppPageParams,\n): Readonly<Record<string, ReactNode>> | undefined {\n const parallelSlots: Record<string, ReactNode> = {};\n\n for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n if (targetIndex !== layoutIndex) {\n continue;\n }\n\n const layoutEntry = layoutEntries[targetIndex];\n const treePath = layoutEntry?.treePath ?? \"/\";\n const slotId = resolveAppPageSlotId(slot, treePath);\n const slotParams = getEffectiveSlotParams(slotKey, slotName);\n const slotSegments = slot.routeSegments\n ? resolveAppPageChildSegments(slot.routeSegments, 0, slotParams)\n : [];\n parallelSlots[slotName] = (\n <LayoutSegmentProvider segmentMap={{ children: slotSegments }}>\n <Slot id={slotId} />\n </LayoutSegmentProvider>\n );\n }\n\n return Object.keys(parallelSlots).length > 0 ? parallelSlots : undefined;\n}\n\nfunction resolveAppPageSlotId(slot: AppPageRouteWiringSlot, treePath: string): string {\n const slotId = AppElementsWire.encodeSlotId(slot.name, treePath);\n if (slot.id && slot.id !== slotId) {\n throw new Error(\n `[vinext] App Router slot id mismatch for @${slot.name}: graph id ${slot.id} does not match wire id ${slotId}`,\n );\n }\n return slotId;\n}\n\nfunction resolveAppPageSlotBindingState(\n slot: AppPageRouteWiringSlot,\n override: AppPageSlotOverride | undefined,\n): AppElementsSlotBinding[\"state\"] {\n const pageComponent = getDefaultExport(override?.pageModule) ?? getDefaultExport(slot.page);\n if (pageComponent) return \"active\";\n if (getDefaultExport(slot.default)) return \"default\";\n return \"unmatched\";\n}\n\nfunction createAppPageSlotBindings<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(\n route: AppPageRouteWiringRoute<TModule, TErrorModule>,\n layoutEntries: readonly AppPageLayoutEntry<TModule, TErrorModule>[],\n resolveSlotOverride: (\n slotKey: string,\n slotName: string,\n ) => AppPageSlotOverride<TModule> | undefined,\n): readonly AppElementsSlotBinding[] {\n const bindings: AppElementsSlotBinding[] = [];\n for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n const layoutEntry = layoutEntries[targetIndex] ?? null;\n const ownerLayoutId = layoutEntry?.id ?? null;\n const override = resolveSlotOverride(slotKey, slot.name);\n bindings.push({\n ownerLayoutId,\n slotId: resolveAppPageSlotId(slot, layoutEntry?.treePath ?? \"/\"),\n state: resolveAppPageSlotBindingState(slot, override),\n });\n }\n return normalizeAppElementsSlotBindings(bindings, {\n layoutIds: layoutEntries.map((entry) => entry.id),\n });\n}\n\nfunction createAppPageRouteHead(\n metadata: Metadata | null,\n viewport: Viewport,\n pathname: string,\n): ReactNode {\n return (\n <>\n <meta charSet=\"utf-8\" />\n {metadata ? <MetadataHead metadata={metadata} pathname={pathname} /> : null}\n <ViewportHead viewport={viewport} />\n </>\n );\n}\n\nexport function buildAppPageElements<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(options: BuildAppPageElementsOptions<TModule, TErrorModule>): AppElements {\n const interceptionContext = options.interceptionContext ?? null;\n const routeSegments = options.route.routeSegments ?? [];\n const routeResetKey = resolveAppPageRouteStateKey(routeSegments, options.matchedParams);\n const routeId = AppElementsWire.encodeRouteId(options.routePath, interceptionContext);\n const pageId = AppElementsWire.encodePageId(options.routePath, interceptionContext);\n const layoutEntries = createAppPageLayoutEntries(options.route);\n const templateEntries = createAppPageTemplateEntries(options.route);\n const errorEntries = createAppPageErrorEntries(options.route);\n const layoutEntriesByTreePosition = new Map<number, AppPageLayoutEntry<TModule, TErrorModule>>();\n const templateEntriesByTreePosition = new Map<number, AppPageTemplateEntry<TModule>>();\n const errorEntriesByTreePosition = new Map<number, AppPageErrorEntry<TErrorModule>>();\n for (const layoutEntry of layoutEntries) {\n layoutEntriesByTreePosition.set(layoutEntry.treePosition, layoutEntry);\n }\n for (const templateEntry of templateEntries) {\n templateEntriesByTreePosition.set(templateEntry.treePosition, templateEntry);\n }\n for (const errorEntry of errorEntries) {\n errorEntriesByTreePosition.set(errorEntry.treePosition, errorEntry);\n }\n const layoutIndicesByTreePosition = new Map<number, number>();\n for (let index = 0; index < layoutEntries.length; index++) {\n layoutIndicesByTreePosition.set(layoutEntries[index].treePosition, index);\n }\n const layoutDependenciesByIndex = new Map<number, AppRenderDependency>();\n const layoutDependenciesBefore: AppRenderDependency[][] = [];\n const slotDependenciesByLayoutIndex: AppRenderDependency[][] = [];\n const templateDependenciesById = new Map<string, AppRenderDependency>();\n const templateDependenciesBeforeById = new Map<string, AppRenderDependency[]>();\n const pageDependencies: AppRenderDependency[] = [];\n const rootLayoutTreePath = layoutEntries[0]?.treePath ?? null;\n const slotNameCounts = new Map<string, number>();\n for (const slot of Object.values(options.route.slots ?? {})) {\n const slotName = slot.name;\n slotNameCounts.set(slotName, (slotNameCounts.get(slotName) ?? 0) + 1);\n }\n const orderedTreePositions = Array.from(\n new Set<number>([\n ...layoutEntries.map((entry) => entry.treePosition),\n ...templateEntries.map((entry) => entry.treePosition),\n ...errorEntries.map((entry) => entry.treePosition),\n ]),\n ).sort((left, right) => left - right);\n const resolveSlotOverride = (slotKey: string, slotName: string) => {\n const overrideByKey = options.slotOverrides?.[slotKey];\n if (overrideByKey) {\n return overrideByKey;\n }\n\n // Legacy callers may still provide overrides by slot prop name.\n // Only allow that fallback when it is unambiguous.\n if (slotKey === slotName || (slotNameCounts.get(slotName) ?? 0) === 1) {\n return options.slotOverrides?.[slotName];\n }\n\n return undefined;\n };\n const elements: Record<\n string,\n ReactNode | string | null | AppElementsInterception | readonly AppElementsSlotBinding[]\n > = {\n ...AppElementsWire.createMetadataEntries({\n interception: options.interception ?? null,\n interceptionContext,\n layoutIds: options.route.ids?.layouts ?? layoutEntries.map((entry) => entry.id),\n rootLayoutTreePath,\n routeId,\n slotBindings: createAppPageSlotBindings(options.route, layoutEntries, resolveSlotOverride),\n }),\n };\n const getEffectiveSlotParams = (slotKey: string, slotName: string): AppPageParams =>\n resolveSlotOverride(slotKey, slotName)?.params ?? options.matchedParams;\n\n for (const treePosition of orderedTreePositions) {\n const layoutIndex = layoutIndicesByTreePosition.get(treePosition);\n if (layoutIndex !== undefined) {\n const layoutEntry = layoutEntries[layoutIndex];\n layoutDependenciesBefore[layoutIndex] = [...pageDependencies];\n if (getDefaultExport(layoutEntry.layoutModule)) {\n const layoutDependency = createAppRenderDependency();\n layoutDependenciesByIndex.set(layoutIndex, layoutDependency);\n pageDependencies.push(layoutDependency);\n }\n slotDependenciesByLayoutIndex[layoutIndex] = [...pageDependencies];\n }\n\n const templateEntry = templateEntriesByTreePosition.get(treePosition);\n if (!templateEntry || !getDefaultExport(templateEntry.templateModule)) {\n continue;\n }\n\n const templateDependency = createAppRenderDependency();\n templateDependenciesById.set(templateEntry.id, templateDependency);\n templateDependenciesBeforeById.set(templateEntry.id, [...pageDependencies]);\n pageDependencies.push(templateDependency);\n }\n\n elements[pageId] = renderAfterAppDependencies(options.element, pageDependencies);\n\n for (const templateEntry of templateEntries) {\n const templateComponent = getDefaultExport(templateEntry.templateModule);\n if (!templateComponent) {\n continue;\n }\n const TemplateComponent = templateComponent;\n const templateDependency = templateDependenciesById.get(templateEntry.id);\n const templateElement = templateDependency ? (\n renderWithAppDependencyBarrier(\n <TemplateComponent params={options.matchedParams}>\n <Children />\n </TemplateComponent>,\n templateDependency,\n )\n ) : (\n <TemplateComponent params={options.matchedParams}>\n <Children />\n </TemplateComponent>\n );\n elements[templateEntry.id] = renderAfterAppDependencies(\n templateElement,\n templateDependenciesBeforeById.get(templateEntry.id) ?? [],\n );\n }\n\n for (let index = 0; index < layoutEntries.length; index++) {\n const layoutEntry = layoutEntries[index];\n const layoutComponent = getDefaultExport(layoutEntry.layoutModule);\n if (!layoutComponent) {\n continue;\n }\n\n const layoutProps: Record<string, unknown> = {\n params: options.makeThenableParams(\n resolveAppPageSegmentParams(\n options.route.routeSegments,\n layoutEntry.treePosition,\n options.matchedParams,\n ),\n ),\n };\n\n for (const slot of Object.values(options.route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n if (targetIndex !== index) {\n continue;\n }\n layoutProps[slotName] = <ParallelSlot name={slotName} />;\n }\n\n const LayoutComponent = layoutComponent;\n const layoutDependency = layoutDependenciesByIndex.get(index);\n const layoutElement = layoutDependency ? (\n renderWithAppDependencyBarrier(\n <LayoutComponent {...layoutProps}>\n <Children />\n </LayoutComponent>,\n layoutDependency,\n )\n ) : (\n <LayoutComponent {...layoutProps}>\n <Children />\n </LayoutComponent>\n );\n elements[layoutEntry.id] = renderAfterAppDependencies(\n layoutElement,\n layoutDependenciesBefore[index] ?? [],\n );\n }\n\n for (const [slotKey, slot] of Object.entries(options.route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n const treePath = layoutEntries[targetIndex]?.treePath ?? \"/\";\n const slotId = resolveAppPageSlotId(slot, treePath);\n const slotOverride = resolveSlotOverride(slotKey, slotName);\n const slotParams = getEffectiveSlotParams(slotKey, slotName);\n const slotRouteSegments = slot.routeSegments ?? [];\n const slotResetKey = resolveAppPageRouteStateKey(slotRouteSegments, slotParams);\n const overrideOrPageComponent =\n getDefaultExport(slotOverride?.pageModule) ?? getDefaultExport(slot.page);\n const defaultComponent = getDefaultExport(slot.default);\n\n // On soft nav (RSC): omit key when only default.tsx exists and the slot is\n // already mounted on the client. Absent key means the browser retains prior\n // slot content rather than replacing it. When the slot is not yet mounted\n // (first entry into this layout), include the key so default.tsx renders.\n if (\n !overrideOrPageComponent &&\n defaultComponent &&\n options.isRscRequest &&\n options.mountedSlotIds?.has(slotId)\n ) {\n continue;\n }\n\n const slotComponent = overrideOrPageComponent ?? defaultComponent;\n\n if (!slotComponent) {\n elements[slotId] = AppElementsWire.unmatchedSlotValue;\n continue;\n }\n\n const slotThenableParams = options.makeThenableParams(slotParams);\n const slotProps: Record<string, unknown> = {\n params: slotThenableParams,\n };\n if (slotOverride?.props) {\n Object.assign(slotProps, slotOverride.props);\n }\n\n const SlotComponent = slotComponent;\n let slotElement: ReactNode = <SlotComponent {...slotProps} />;\n const interceptLayouts = slotOverride?.layoutModules ?? [];\n\n for (let layoutIndex = interceptLayouts.length - 1; layoutIndex >= 0; layoutIndex--) {\n const interceptLayoutComponent = getDefaultExport(interceptLayouts[layoutIndex]);\n if (!interceptLayoutComponent) {\n continue;\n }\n const InterceptLayoutComponent = interceptLayoutComponent;\n slotElement = (\n <InterceptLayoutComponent params={slotThenableParams}>\n {slotElement}\n </InterceptLayoutComponent>\n );\n }\n\n const slotLayoutComponent = getDefaultExport(slot.layout);\n if (slotLayoutComponent) {\n const SlotLayoutComponent = slotLayoutComponent;\n slotElement = (\n <SlotLayoutComponent params={slotThenableParams}>{slotElement}</SlotLayoutComponent>\n );\n }\n\n const slotLoadingComponent = getDefaultExport(slot.loading);\n if (\n slotLoadingComponent &&\n !shouldSuppressLoadingBoundaries(options.renderMode ?? APP_RSC_RENDER_MODE_NAVIGATION)\n ) {\n const SlotLoadingComponent = slotLoadingComponent;\n slotElement = (\n <Suspense key={slotResetKey} fallback={<SlotLoadingComponent />}>\n {slotElement}\n </Suspense>\n );\n }\n\n const slotErrorComponent = getErrorBoundaryExport(slot.error);\n if (slotErrorComponent) {\n slotElement = (\n <ErrorBoundary resetKey={slotResetKey} fallback={slotErrorComponent}>\n {slotElement}\n </ErrorBoundary>\n );\n }\n\n elements[slotId] = renderAfterAppDependencies(\n slotElement,\n targetIndex >= 0 ? (slotDependenciesByLayoutIndex[targetIndex] ?? []) : [],\n );\n }\n\n let routeChildren: ReactNode = (\n <LayoutSegmentProvider segmentMap={{ children: [] }}>\n <Slot id={pageId} />\n </LayoutSegmentProvider>\n );\n\n // Wrap the page slot in a per-segment RedirectBoundary so that a\n // redirect() thrown from a server component (or a client component\n // within the page subtree) is caught here — below the route's layouts —\n // rather than at the top-level boundary in app-browser-entry. Catching\n // at the top level unmounts the entire route tree including layouts,\n // which destroys client-side state in layout-hosted components\n // (counters, theme toggles, form drafts). Here, only the page subtree\n // is unmounted; the surrounding layouts stay mounted across the\n // boundary's null-render → router.replace transition, and segment\n // reuse keeps their React state intact.\n //\n // Placed inside the Suspense (loading) boundary to match Next.js nesting\n // for the redirect boundary specifically:\n // Error > AccessFallback > Loading (Suspense) > Redirect > content\n // (Note: Next.js places AccessFallback inside Loading, not outside — that\n // is a pre-existing nesting divergence tracked separately.)\n // This keeps the loading fallback visible during redirect-driven\n // transitions rather than unmounting it.\n routeChildren = <RedirectBoundary>{routeChildren}</RedirectBoundary>;\n\n const routeLoadingComponent = getDefaultExport(options.route.loading);\n if (\n routeLoadingComponent &&\n !shouldSuppressLoadingBoundaries(options.renderMode ?? APP_RSC_RENDER_MODE_NAVIGATION)\n ) {\n const RouteLoadingComponent = routeLoadingComponent;\n // Route-level wrappers cover the full page branch in vinext's flat element\n // transport, so their reset key includes the visible segment-state path.\n // Dynamic param changes reset the pending boundary, while search-only changes\n // preserve it.\n routeChildren = (\n <Suspense key={routeResetKey} fallback={<RouteLoadingComponent />}>\n {routeChildren}\n </Suspense>\n );\n }\n\n const lastLayoutErrorModule =\n errorEntries.length > 0 ? errorEntries[errorEntries.length - 1].errorModule : null;\n // Next.js nesting (outer to inner): Error > Unauthorized > Forbidden > NotFound > children.\n // Building bottom-up means NotFoundBoundary must wrap first, then Forbidden, Unauthorized, Error.\n const notFoundComponent =\n getDefaultExport(options.route.notFound) ?? getDefaultExport(options.rootNotFoundModule);\n if (notFoundComponent) {\n const NotFoundComponent = notFoundComponent;\n routeChildren = (\n <NotFoundBoundary resetKey={routeResetKey} fallback={<NotFoundComponent />}>\n {routeChildren}\n </NotFoundBoundary>\n );\n }\n\n const forbiddenComponent =\n getDefaultExport(options.route.forbidden) ?? getDefaultExport(options.rootForbiddenModule);\n if (forbiddenComponent) {\n const ForbiddenComponent = forbiddenComponent;\n routeChildren = (\n <ForbiddenBoundary resetKey={routeResetKey} fallback={<ForbiddenComponent />}>\n {routeChildren}\n </ForbiddenBoundary>\n );\n }\n\n const unauthorizedComponent =\n getDefaultExport(options.route.unauthorized) ??\n getDefaultExport(options.rootUnauthorizedModule);\n if (unauthorizedComponent) {\n const UnauthorizedComponent = unauthorizedComponent;\n routeChildren = (\n <UnauthorizedBoundary resetKey={routeResetKey} fallback={<UnauthorizedComponent />}>\n {routeChildren}\n </UnauthorizedBoundary>\n );\n }\n\n const pageErrorComponent = getErrorBoundaryExport(options.route.error);\n if (pageErrorComponent && options.route.error !== lastLayoutErrorModule) {\n routeChildren = (\n <ErrorBoundary resetKey={routeResetKey} fallback={pageErrorComponent}>\n {routeChildren}\n </ErrorBoundary>\n );\n }\n\n for (let index = orderedTreePositions.length - 1; index >= 0; index--) {\n const treePosition = orderedTreePositions[index];\n const segmentResetKey = resolveAppPageSegmentStateKey(\n routeSegments,\n treePosition,\n options.matchedParams,\n );\n let segmentChildren: ReactNode = routeChildren;\n const layoutEntry = layoutEntriesByTreePosition.get(treePosition);\n const templateEntry = templateEntriesByTreePosition.get(treePosition);\n const errorEntry = errorEntriesByTreePosition.get(treePosition);\n\n // Next.js nesting per segment (outer to inner): Layout > Template > Error > Unauthorized > Forbidden > NotFound > children.\n // Building bottom-up means NotFoundBoundary must wrap the leaf subtree first,\n // then ErrorBoundary, then Template, with the Layout slot outermost.\n if (layoutEntry) {\n const layoutNotFoundComponent = getDefaultExport(layoutEntry.notFoundModule);\n if (layoutNotFoundComponent) {\n const LayoutNotFoundComponent = layoutNotFoundComponent;\n segmentChildren = (\n <NotFoundBoundary resetKey={segmentResetKey} fallback={<LayoutNotFoundComponent />}>\n {segmentChildren}\n </NotFoundBoundary>\n );\n }\n\n const layoutForbiddenComponent = getDefaultExport(layoutEntry.forbiddenModule);\n if (layoutForbiddenComponent) {\n const LayoutForbiddenComponent = layoutForbiddenComponent;\n segmentChildren = (\n <ForbiddenBoundary resetKey={segmentResetKey} fallback={<LayoutForbiddenComponent />}>\n {segmentChildren}\n </ForbiddenBoundary>\n );\n }\n\n const layoutUnauthorizedComponent = getDefaultExport(layoutEntry.unauthorizedModule);\n if (layoutUnauthorizedComponent) {\n const LayoutUnauthorizedComponent = layoutUnauthorizedComponent;\n segmentChildren = (\n <UnauthorizedBoundary\n resetKey={segmentResetKey}\n fallback={<LayoutUnauthorizedComponent />}\n >\n {segmentChildren}\n </UnauthorizedBoundary>\n );\n }\n }\n\n const segmentErrorComponent = getErrorBoundaryExport(\n errorEntry?.errorModule ?? layoutEntry?.errorModule,\n );\n if (segmentErrorComponent) {\n segmentChildren = (\n <ErrorBoundary resetKey={segmentResetKey} fallback={segmentErrorComponent}>\n {segmentChildren}\n </ErrorBoundary>\n );\n }\n\n if (templateEntry && getDefaultExport(templateEntry.templateModule)) {\n segmentChildren = (\n <Slot id={templateEntry.id} key={segmentResetKey}>\n {segmentChildren}\n </Slot>\n );\n }\n\n if (!layoutEntry) {\n routeChildren = segmentChildren;\n continue;\n }\n const layoutHasElement = getDefaultExport(layoutEntry.layoutModule) !== null;\n const layoutIndex = layoutIndicesByTreePosition.get(treePosition) ?? -1;\n const segmentMap: { children: string[] } & Record<string, string[]> = {\n children: resolveAppPageChildSegments(\n routeSegments,\n layoutEntry.treePosition,\n options.matchedParams,\n ),\n };\n for (const [slotKey, slot] of Object.entries(options.route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n if (targetIndex !== layoutIndex) {\n continue;\n }\n const slotParams = getEffectiveSlotParams(slotKey, slotName);\n segmentMap[slotName] = slot.routeSegments\n ? resolveAppPageChildSegments(slot.routeSegments, 0, slotParams)\n : [];\n }\n\n routeChildren = (\n <LayoutSegmentProvider segmentMap={segmentMap}>\n {layoutHasElement ? (\n <Slot\n id={layoutEntry.id}\n parallelSlots={createAppPageParallelSlotEntries(\n layoutIndex,\n layoutEntries,\n options.route,\n getEffectiveSlotParams,\n )}\n >\n {segmentChildren}\n </Slot>\n ) : (\n segmentChildren\n )}\n </LayoutSegmentProvider>\n );\n }\n\n const globalErrorComponent = getErrorBoundaryExport(options.globalErrorModule);\n if (globalErrorComponent) {\n routeChildren = <ErrorBoundary fallback={globalErrorComponent}>{routeChildren}</ErrorBoundary>;\n }\n\n elements[routeId] = (\n <>\n {createAppPageRouteHead(\n options.resolvedMetadata,\n options.resolvedViewport,\n options.resolvedMetadataPathname ?? options.routePath,\n )}\n {routeChildren}\n </>\n );\n\n return elements;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-page-route-wiring.js","names":["Children","SlotComponent","InterceptLayoutComponent","SlotLayoutComponent","SlotLoadingComponent","RouteLoadingComponent","NotFoundComponent","ForbiddenComponent","UnauthorizedComponent","LayoutNotFoundComponent","LayoutForbiddenComponent","LayoutUnauthorizedComponent"],"sources":["../../src/server/app-page-route-wiring.tsx"],"sourcesContent":["import { Suspense, type ComponentType, type ReactNode } from \"react\";\nimport {\n AppElementsWire,\n APP_PREFETCH_LOADING_SHELL_MARKER_KEY,\n normalizeAppElementsSlotBindings,\n type AppElements,\n type AppElementsInterception,\n type AppElementsSlotBinding,\n} from \"./app-elements.js\";\nimport {\n ErrorBoundary,\n ForbiddenBoundary,\n NotFoundBoundary,\n RedirectBoundary,\n UnauthorizedBoundary,\n} from \"vinext/shims/error-boundary\";\nimport { AppRouterScrollTarget } from \"vinext/shims/app-router-scroll\";\nimport type { AppRouteSemanticIds } from \"../routing/app-route-graph.js\";\nimport { LayoutSegmentProvider } from \"vinext/shims/layout-segment-context\";\nimport {\n MetadataHead,\n ViewportHead,\n renderMetadataToHtml,\n type Metadata,\n type Viewport,\n} from \"vinext/shims/metadata\";\nimport { Children, ParallelSlot, Slot } from \"vinext/shims/slot\";\nimport type { AppPageParams } from \"./app-page-boundary.js\";\nimport {\n createAppRenderDependency,\n renderAfterAppDependencies,\n renderWithAppDependencyBarrier,\n type AppRenderDependency,\n} from \"./app-render-dependency.js\";\nimport { resolveAppPageSegmentParams } from \"./app-page-params.js\";\nimport {\n APP_RSC_RENDER_MODE_NAVIGATION,\n APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL,\n shouldSuppressLoadingBoundaries,\n type AppRscRenderMode,\n} from \"./app-rsc-render-mode.js\";\nimport {\n resolveAppPageChildSegments,\n resolveAppPageRouteStateKey,\n resolveAppPageSegmentStateKey,\n} from \"./app-page-segment-state.js\";\n\nexport { resolveAppPageChildSegments } from \"./app-page-segment-state.js\";\n\ntype AppPageComponentProps = {\n children?: ReactNode;\n error?: unknown;\n params?: unknown;\n reset?: () => void;\n} & Record<string, unknown>;\n\ntype AppPageComponent = ComponentType<AppPageComponentProps>;\ntype AppPageErrorComponent = ComponentType<{ error: unknown; reset: () => void }>;\n\nexport type AppPageModule = Record<string, unknown> & {\n default?: AppPageComponent | null | undefined;\n};\n\nexport type AppPageErrorModule = Record<string, unknown> & {\n default?: AppPageErrorComponent | null | undefined;\n};\n\ntype AppPageRouteWiringSlot<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n /** Graph-owned semantic slot identity. */\n id?: string | null;\n /** Slot prop name passed to the owning layout (e.g. \"modal\" from @modal). */\n name: string;\n default?: TModule | null;\n error?: TErrorModule | null;\n layout?: TModule | null;\n layoutIndex: number;\n loading?: TModule | null;\n page?: TModule | null;\n routeSegments?: readonly string[] | null;\n /**\n * Full URL pattern parts for the slot's mirrored sub-page. Set when the\n * slot's params may differ from the route's (e.g. inherited slot whose\n * dynamic markers have different names than the route's). The runtime\n * matches the request URL against these parts to extract slot params.\n */\n slotPatternParts?: readonly string[] | null;\n /** Param names captured by `slotPatternParts`, in order. */\n slotParamNames?: readonly string[] | null;\n};\n\nexport type AppPageRouteWiringRoute<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n ids?: AppRouteSemanticIds | null;\n error?: TErrorModule | null;\n errorPaths?: readonly TErrorModule[] | null;\n errors?: readonly (TErrorModule | null | undefined)[] | null;\n errorTreePositions?: readonly number[] | null;\n layoutTreePositions?: readonly number[] | null;\n layouts: readonly (TModule | null | undefined)[];\n loading?: TModule | null;\n notFound?: TModule | null;\n notFounds?: readonly (TModule | null | undefined)[] | null;\n forbidden?: TModule | null;\n forbiddens?: readonly (TModule | null | undefined)[] | null;\n unauthorized?: TModule | null;\n unauthorizeds?: readonly (TModule | null | undefined)[] | null;\n routeSegments?: readonly string[];\n /**\n * Keyed by stable slot id (name + owner path), not necessarily the slot prop name.\n */\n slots?: Readonly<Record<string, AppPageRouteWiringSlot<TModule, TErrorModule>>> | null;\n templateTreePositions?: readonly number[] | null;\n templates?: readonly (TModule | null | undefined)[] | null;\n};\n\nexport type AppPageSlotOverride<TModule extends AppPageModule = AppPageModule> = {\n layoutModules?: readonly (TModule | null | undefined)[] | null;\n /**\n * The page module to render for this slot. Optional — when omitted, the\n * slot's existing `page` is used (e.g. when the override only changes the\n * slot's `params` for an inherited mirror with distinct param names).\n */\n pageModule?: TModule | null;\n params?: AppPageParams;\n props?: Readonly<Record<string, unknown>>;\n};\n\ntype AppPageLayoutEntry<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n errorModule?: TErrorModule | null | undefined;\n forbiddenModule?: TModule | null | undefined;\n id: string;\n layoutModule?: TModule | null | undefined;\n notFoundModule?: TModule | null | undefined;\n unauthorizedModule?: TModule | null | undefined;\n treePath: string;\n treePosition: number;\n};\n\ntype BuildAppPageRouteElementOptions<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n element: ReactNode;\n globalErrorModule?: TErrorModule | null;\n makeThenableParams: (params: AppPageParams) => unknown;\n matchedParams: AppPageParams;\n metadataPlacement?: \"body\" | \"head\";\n resolvedMetadata: Metadata | null;\n resolvedMetadataPathname?: string;\n resolvedViewport: Viewport;\n rootForbiddenModule?: TModule | null;\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n route: AppPageRouteWiringRoute<TModule, TErrorModule>;\n slotOverrides?: Readonly<Record<string, AppPageSlotOverride<TModule>>> | null;\n};\n\ntype BuildAppPageElementsOptions<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = BuildAppPageRouteElementOptions<TModule, TErrorModule> & {\n interception?: AppElementsInterception | null;\n interceptionContext?: string | null;\n isRscRequest?: boolean;\n mountedSlotIds?: ReadonlySet<string> | null;\n renderMode?: AppRscRenderMode;\n routePath: string;\n};\n\ntype AppPageTemplateEntry<TModule extends AppPageModule = AppPageModule> = {\n id: string;\n templateModule?: TModule | null | undefined;\n treePath: string;\n treePosition: number;\n};\n\ntype AppPageErrorEntry<TErrorModule extends AppPageErrorModule = AppPageErrorModule> = {\n errorModule?: TErrorModule | null | undefined;\n treePosition: number;\n};\n\nfunction getDefaultExport<TModule extends AppPageModule>(\n module: TModule | null | undefined,\n): AppPageComponent | null {\n return module?.default ?? null;\n}\n\nfunction getErrorBoundaryExport<TModule extends AppPageErrorModule>(\n module: TModule | null | undefined,\n): AppPageErrorComponent | null {\n return module?.default ?? null;\n}\n\nexport function createAppPageTreePath(\n routeSegments: readonly string[] | null | undefined,\n treePosition: number,\n): string {\n const treePathSegments = routeSegments?.slice(0, treePosition) ?? [];\n if (treePathSegments.length === 0) {\n return \"/\";\n }\n return `/${treePathSegments.join(\"/\")}`;\n}\n\nexport function createAppPageLayoutEntries<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(\n route: Pick<\n AppPageRouteWiringRoute<TModule, TErrorModule>,\n | \"errors\"\n | \"errorTreePositions\"\n | \"layoutTreePositions\"\n | \"layouts\"\n | \"notFounds\"\n | \"routeSegments\"\n > & {\n forbiddens?: readonly (TModule | null | undefined)[] | null;\n unauthorizeds?: readonly (TModule | null | undefined)[] | null;\n },\n): AppPageLayoutEntry<TModule, TErrorModule>[] {\n return route.layouts.map((layoutModule, index) => {\n const treePosition = route.layoutTreePositions?.[index] ?? 0;\n const treePath = createAppPageTreePath(route.routeSegments, treePosition);\n return {\n errorModule: route.errorTreePositions ? null : (route.errors?.[index] ?? null),\n forbiddenModule: route.forbiddens?.[index] ?? null,\n id: AppElementsWire.encodeLayoutId(treePath),\n layoutModule,\n notFoundModule: route.notFounds?.[index] ?? null,\n unauthorizedModule: route.unauthorizeds?.[index] ?? null,\n treePath,\n treePosition,\n };\n });\n}\n\nfunction createAppPageTemplateEntries<TModule extends AppPageModule>(\n route: Pick<\n AppPageRouteWiringRoute<TModule>,\n \"routeSegments\" | \"templateTreePositions\" | \"templates\"\n >,\n): AppPageTemplateEntry<TModule>[] {\n return (route.templates ?? []).map((templateModule, index) => {\n const treePosition = route.templateTreePositions?.[index] ?? 0;\n const treePath = createAppPageTreePath(route.routeSegments, treePosition);\n return {\n id: AppElementsWire.encodeTemplateId(treePath),\n templateModule,\n treePath,\n treePosition,\n };\n });\n}\n\nfunction createAppPageErrorEntries<TErrorModule extends AppPageErrorModule>(\n route: Pick<\n AppPageRouteWiringRoute<AppPageModule, TErrorModule>,\n \"errorPaths\" | \"errors\" | \"errorTreePositions\"\n >,\n): AppPageErrorEntry<TErrorModule>[] {\n return (route.errorPaths ?? route.errors ?? []).flatMap((errorModule, index) => {\n if (!errorModule) return [];\n const treePosition = route.errorTreePositions?.[index];\n if (treePosition === undefined) return [];\n return [{ errorModule, treePosition }];\n });\n}\n\nfunction createAppPageParallelSlotEntries<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(\n layoutIndex: number,\n layoutEntries: readonly AppPageLayoutEntry<TModule, TErrorModule>[],\n route: AppPageRouteWiringRoute<TModule, TErrorModule>,\n getEffectiveSlotParams: (slotKey: string, slotName: string) => AppPageParams,\n): Readonly<Record<string, ReactNode>> | undefined {\n const parallelSlots: Record<string, ReactNode> = {};\n\n for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n if (targetIndex !== layoutIndex) {\n continue;\n }\n\n const layoutEntry = layoutEntries[targetIndex];\n const treePath = layoutEntry?.treePath ?? \"/\";\n const slotId = resolveAppPageSlotId(slot, treePath);\n const slotParams = getEffectiveSlotParams(slotKey, slotName);\n const slotSegments = slot.routeSegments\n ? resolveAppPageChildSegments(slot.routeSegments, 0, slotParams)\n : [];\n parallelSlots[slotName] = (\n <LayoutSegmentProvider segmentMap={{ children: slotSegments }}>\n <Slot id={slotId} />\n </LayoutSegmentProvider>\n );\n }\n\n return Object.keys(parallelSlots).length > 0 ? parallelSlots : undefined;\n}\n\nfunction resolveAppPageSlotId(slot: AppPageRouteWiringSlot, treePath: string): string {\n const slotId = AppElementsWire.encodeSlotId(slot.name, treePath);\n if (slot.id && slot.id !== slotId) {\n throw new Error(\n `[vinext] App Router slot id mismatch for @${slot.name}: graph id ${slot.id} does not match wire id ${slotId}`,\n );\n }\n return slotId;\n}\n\nfunction resolveAppPageSlotBindingState(\n slot: AppPageRouteWiringSlot,\n override: AppPageSlotOverride | undefined,\n): AppElementsSlotBinding[\"state\"] {\n const pageComponent = getDefaultExport(override?.pageModule) ?? getDefaultExport(slot.page);\n if (pageComponent) return \"active\";\n if (getDefaultExport(slot.default)) return \"default\";\n return \"unmatched\";\n}\n\nfunction createAppPageSlotBindings<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(\n route: AppPageRouteWiringRoute<TModule, TErrorModule>,\n layoutEntries: readonly AppPageLayoutEntry<TModule, TErrorModule>[],\n resolveSlotOverride: (\n slotKey: string,\n slotName: string,\n ) => AppPageSlotOverride<TModule> | undefined,\n): readonly AppElementsSlotBinding[] {\n const bindings: AppElementsSlotBinding[] = [];\n for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n const layoutEntry = layoutEntries[targetIndex] ?? null;\n const ownerLayoutId = layoutEntry?.id ?? null;\n const override = resolveSlotOverride(slotKey, slot.name);\n bindings.push({\n ownerLayoutId,\n slotId: resolveAppPageSlotId(slot, layoutEntry?.treePath ?? \"/\"),\n state: resolveAppPageSlotBindingState(slot, override),\n });\n }\n return normalizeAppElementsSlotBindings(bindings, {\n layoutIds: layoutEntries.map((entry) => entry.id),\n });\n}\n\nfunction createAppPageRouteHead(\n metadata: Metadata | null,\n viewport: Viewport,\n pathname: string,\n metadataPlacement: \"body\" | \"head\",\n): ReactNode {\n return (\n <>\n <meta charSet=\"utf-8\" />\n {metadata && metadataPlacement === \"head\" ? (\n <MetadataHead metadata={metadata} pathname={pathname} />\n ) : null}\n <ViewportHead viewport={viewport} />\n </>\n );\n}\n\nfunction createAppPageRouteBodyMetadata(\n metadata: Metadata | null,\n pathname: string,\n metadataPlacement: \"body\" | \"head\",\n): ReactNode {\n if (!metadata || metadataPlacement !== \"body\") return null;\n return (\n <div hidden dangerouslySetInnerHTML={{ __html: renderMetadataToHtml(metadata, pathname) }} />\n );\n}\n\nexport function buildAppPageElements<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(options: BuildAppPageElementsOptions<TModule, TErrorModule>): AppElements {\n const interceptionContext = options.interceptionContext ?? null;\n const renderMode = options.renderMode ?? APP_RSC_RENDER_MODE_NAVIGATION;\n const routeSegments = options.route.routeSegments ?? [];\n const routeResetKey = resolveAppPageRouteStateKey(routeSegments, options.matchedParams);\n const routeId = AppElementsWire.encodeRouteId(options.routePath, interceptionContext);\n const pageId = AppElementsWire.encodePageId(options.routePath, interceptionContext);\n const layoutEntries = createAppPageLayoutEntries(options.route);\n const templateEntries = createAppPageTemplateEntries(options.route);\n const errorEntries = createAppPageErrorEntries(options.route);\n const metadataPlacement = options.metadataPlacement ?? \"head\";\n const layoutEntriesByTreePosition = new Map<number, AppPageLayoutEntry<TModule, TErrorModule>>();\n const templateEntriesByTreePosition = new Map<number, AppPageTemplateEntry<TModule>>();\n const errorEntriesByTreePosition = new Map<number, AppPageErrorEntry<TErrorModule>>();\n for (const layoutEntry of layoutEntries) {\n layoutEntriesByTreePosition.set(layoutEntry.treePosition, layoutEntry);\n }\n for (const templateEntry of templateEntries) {\n templateEntriesByTreePosition.set(templateEntry.treePosition, templateEntry);\n }\n for (const errorEntry of errorEntries) {\n errorEntriesByTreePosition.set(errorEntry.treePosition, errorEntry);\n }\n const layoutIndicesByTreePosition = new Map<number, number>();\n for (let index = 0; index < layoutEntries.length; index++) {\n layoutIndicesByTreePosition.set(layoutEntries[index].treePosition, index);\n }\n const layoutDependenciesByIndex = new Map<number, AppRenderDependency>();\n const layoutDependenciesBefore: AppRenderDependency[][] = [];\n const slotDependenciesByLayoutIndex: AppRenderDependency[][] = [];\n const templateDependenciesById = new Map<string, AppRenderDependency>();\n const templateDependenciesBeforeById = new Map<string, AppRenderDependency[]>();\n const pageDependencies: AppRenderDependency[] = [];\n const rootLayoutTreePath = layoutEntries[0]?.treePath ?? null;\n const slotNameCounts = new Map<string, number>();\n for (const slot of Object.values(options.route.slots ?? {})) {\n const slotName = slot.name;\n slotNameCounts.set(slotName, (slotNameCounts.get(slotName) ?? 0) + 1);\n }\n const orderedTreePositions = Array.from(\n new Set<number>([\n ...layoutEntries.map((entry) => entry.treePosition),\n ...templateEntries.map((entry) => entry.treePosition),\n ...errorEntries.map((entry) => entry.treePosition),\n ]),\n ).sort((left, right) => left - right);\n const resolveSlotOverride = (slotKey: string, slotName: string) => {\n const overrideByKey = options.slotOverrides?.[slotKey];\n if (overrideByKey) {\n return overrideByKey;\n }\n\n // Legacy callers may still provide overrides by slot prop name.\n // Only allow that fallback when it is unambiguous.\n if (slotKey === slotName || (slotNameCounts.get(slotName) ?? 0) === 1) {\n return options.slotOverrides?.[slotName];\n }\n\n return undefined;\n };\n const elements: Record<\n string,\n ReactNode | string | null | AppElementsInterception | readonly AppElementsSlotBinding[]\n > = {\n ...AppElementsWire.createMetadataEntries({\n interception: options.interception ?? null,\n interceptionContext,\n layoutIds: options.route.ids?.layouts ?? layoutEntries.map((entry) => entry.id),\n rootLayoutTreePath,\n routeId,\n slotBindings: createAppPageSlotBindings(options.route, layoutEntries, resolveSlotOverride),\n }),\n };\n const getEffectiveSlotParams = (slotKey: string, slotName: string): AppPageParams =>\n resolveSlotOverride(slotKey, slotName)?.params ?? options.matchedParams;\n\n for (const treePosition of orderedTreePositions) {\n const layoutIndex = layoutIndicesByTreePosition.get(treePosition);\n if (layoutIndex !== undefined) {\n const layoutEntry = layoutEntries[layoutIndex];\n layoutDependenciesBefore[layoutIndex] = [...pageDependencies];\n if (getDefaultExport(layoutEntry.layoutModule)) {\n const layoutDependency = createAppRenderDependency();\n layoutDependenciesByIndex.set(layoutIndex, layoutDependency);\n pageDependencies.push(layoutDependency);\n }\n slotDependenciesByLayoutIndex[layoutIndex] = [...pageDependencies];\n }\n\n const templateEntry = templateEntriesByTreePosition.get(treePosition);\n if (!templateEntry || !getDefaultExport(templateEntry.templateModule)) {\n continue;\n }\n\n const templateDependency = createAppRenderDependency();\n templateDependenciesById.set(templateEntry.id, templateDependency);\n templateDependenciesBeforeById.set(templateEntry.id, [...pageDependencies]);\n pageDependencies.push(templateDependency);\n }\n\n const routeLoadingComponent = getDefaultExport(options.route.loading);\n const isPrefetchLoadingShell = renderMode === APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL;\n const shouldRenderPrefetchLoadingShell = isPrefetchLoadingShell && routeLoadingComponent !== null;\n if (shouldRenderPrefetchLoadingShell) {\n // Client loading components serialize as module references in Flight. Keep\n // a durable marker in the shell payload so external router tests and\n // diagnostics can recognize this as a loading-boundary response without\n // requiring source text to appear in client component references.\n elements[APP_PREFETCH_LOADING_SHELL_MARKER_KEY] = \"LoadingBoundary\";\n }\n\n elements[pageId] = isPrefetchLoadingShell\n ? null\n : renderAfterAppDependencies(options.element, pageDependencies);\n\n for (const templateEntry of templateEntries) {\n const templateComponent = getDefaultExport(templateEntry.templateModule);\n if (!templateComponent) {\n continue;\n }\n const TemplateComponent = templateComponent;\n const templateDependency = templateDependenciesById.get(templateEntry.id);\n const templateElement = templateDependency ? (\n renderWithAppDependencyBarrier(\n <TemplateComponent params={options.matchedParams}>\n <Children />\n </TemplateComponent>,\n templateDependency,\n )\n ) : (\n <TemplateComponent params={options.matchedParams}>\n <Children />\n </TemplateComponent>\n );\n elements[templateEntry.id] = renderAfterAppDependencies(\n templateElement,\n templateDependenciesBeforeById.get(templateEntry.id) ?? [],\n );\n }\n\n for (let index = 0; index < layoutEntries.length; index++) {\n const layoutEntry = layoutEntries[index];\n const layoutComponent = getDefaultExport(layoutEntry.layoutModule);\n if (!layoutComponent) {\n continue;\n }\n\n const layoutProps: Record<string, unknown> = {\n params: options.makeThenableParams(\n resolveAppPageSegmentParams(\n options.route.routeSegments,\n layoutEntry.treePosition,\n options.matchedParams,\n ),\n ),\n };\n\n for (const slot of Object.values(options.route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n if (targetIndex !== index) {\n continue;\n }\n layoutProps[slotName] = <ParallelSlot name={slotName} />;\n }\n\n const LayoutComponent = layoutComponent;\n const layoutDependency = layoutDependenciesByIndex.get(index);\n const layoutElement = layoutDependency ? (\n renderWithAppDependencyBarrier(\n <LayoutComponent {...layoutProps}>\n <Children />\n </LayoutComponent>,\n layoutDependency,\n )\n ) : (\n <LayoutComponent {...layoutProps}>\n <Children />\n </LayoutComponent>\n );\n elements[layoutEntry.id] = renderAfterAppDependencies(\n layoutElement,\n layoutDependenciesBefore[index] ?? [],\n );\n }\n\n for (const [slotKey, slot] of Object.entries(options.route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n const treePath = layoutEntries[targetIndex]?.treePath ?? \"/\";\n const slotId = resolveAppPageSlotId(slot, treePath);\n const slotOverride = resolveSlotOverride(slotKey, slotName);\n const slotParams = getEffectiveSlotParams(slotKey, slotName);\n const slotRouteSegments = slot.routeSegments ?? [];\n const slotResetKey = resolveAppPageRouteStateKey(slotRouteSegments, slotParams);\n const overrideOrPageComponent =\n getDefaultExport(slotOverride?.pageModule) ?? getDefaultExport(slot.page);\n const defaultComponent = getDefaultExport(slot.default);\n\n // On soft nav (RSC): omit key when only default.tsx exists and the slot is\n // already mounted on the client. Absent key means the browser retains prior\n // slot content rather than replacing it. When the slot is not yet mounted\n // (first entry into this layout), include the key so default.tsx renders.\n if (\n !overrideOrPageComponent &&\n defaultComponent &&\n options.isRscRequest &&\n options.mountedSlotIds?.has(slotId)\n ) {\n continue;\n }\n\n const slotComponent = overrideOrPageComponent ?? defaultComponent;\n\n if (!slotComponent) {\n elements[slotId] = AppElementsWire.unmatchedSlotValue;\n continue;\n }\n\n const slotThenableParams = options.makeThenableParams(slotParams);\n const slotProps: Record<string, unknown> = {\n params: slotThenableParams,\n };\n if (slotOverride?.props) {\n Object.assign(slotProps, slotOverride.props);\n }\n\n const SlotComponent = slotComponent;\n let slotElement: ReactNode = <SlotComponent {...slotProps} />;\n const interceptLayouts = slotOverride?.layoutModules ?? [];\n\n for (let layoutIndex = interceptLayouts.length - 1; layoutIndex >= 0; layoutIndex--) {\n const interceptLayoutComponent = getDefaultExport(interceptLayouts[layoutIndex]);\n if (!interceptLayoutComponent) {\n continue;\n }\n const InterceptLayoutComponent = interceptLayoutComponent;\n slotElement = (\n <InterceptLayoutComponent params={slotThenableParams}>\n {slotElement}\n </InterceptLayoutComponent>\n );\n }\n\n const slotLayoutComponent = getDefaultExport(slot.layout);\n if (slotLayoutComponent) {\n const SlotLayoutComponent = slotLayoutComponent;\n slotElement = (\n <SlotLayoutComponent params={slotThenableParams}>{slotElement}</SlotLayoutComponent>\n );\n }\n\n const slotLoadingComponent = getDefaultExport(slot.loading);\n if (slotLoadingComponent && !shouldSuppressLoadingBoundaries(renderMode)) {\n const SlotLoadingComponent = slotLoadingComponent;\n slotElement = (\n <Suspense key={slotResetKey} fallback={<SlotLoadingComponent />}>\n {slotElement}\n </Suspense>\n );\n }\n\n const slotErrorComponent = getErrorBoundaryExport(slot.error);\n if (slotErrorComponent) {\n slotElement = (\n <ErrorBoundary resetKey={slotResetKey} fallback={slotErrorComponent}>\n {slotElement}\n </ErrorBoundary>\n );\n }\n\n elements[slotId] = renderAfterAppDependencies(\n slotElement,\n targetIndex >= 0 ? (slotDependenciesByLayoutIndex[targetIndex] ?? []) : [],\n );\n }\n\n let routeChildren: ReactNode = (\n <LayoutSegmentProvider segmentMap={{ children: [] }}>\n <AppRouterScrollTarget>\n <Slot id={pageId} />\n </AppRouterScrollTarget>\n </LayoutSegmentProvider>\n );\n\n if (isPrefetchLoadingShell) {\n if (routeLoadingComponent === null) {\n routeChildren = null;\n } else {\n const RouteLoadingComponent = routeLoadingComponent;\n routeChildren = <RouteLoadingComponent />;\n }\n } else {\n // Wrap the page slot in a per-segment RedirectBoundary so that a\n // redirect() thrown from a server component (or a client component\n // within the page subtree) is caught here — below the route's layouts —\n // rather than at the top-level boundary in app-browser-entry. Catching\n // at the top level unmounts the entire route tree including layouts,\n // which destroys client-side state in layout-hosted components\n // (counters, theme toggles, form drafts). Here, only the page subtree\n // is unmounted; the surrounding layouts stay mounted across the\n // boundary's null-render → router.replace transition, and segment\n // reuse keeps their React state intact.\n //\n // Placed inside the Suspense (loading) boundary to match Next.js nesting\n // for the redirect boundary specifically:\n // Error > AccessFallback > Loading (Suspense) > Redirect > content\n // (Note: Next.js places AccessFallback inside Loading, not outside — that\n // is a pre-existing nesting divergence tracked separately.)\n // This keeps the loading fallback visible during redirect-driven\n // transitions rather than unmounting it.\n routeChildren = <RedirectBoundary>{routeChildren}</RedirectBoundary>;\n\n if (routeLoadingComponent && !shouldSuppressLoadingBoundaries(renderMode)) {\n const RouteLoadingComponent = routeLoadingComponent;\n // Route-level wrappers cover the full page branch in vinext's flat element\n // transport, so their reset key includes the visible segment-state path.\n // Dynamic param changes reset the pending boundary, while search-only changes\n // preserve it.\n routeChildren = (\n <Suspense key={routeResetKey} fallback={<RouteLoadingComponent />}>\n {routeChildren}\n </Suspense>\n );\n }\n }\n\n const lastLayoutErrorModule =\n errorEntries.length > 0 ? errorEntries[errorEntries.length - 1].errorModule : null;\n // Next.js nesting (outer to inner): Error > Unauthorized > Forbidden > NotFound > children.\n // Building bottom-up means NotFoundBoundary must wrap first, then Forbidden, Unauthorized, Error.\n const notFoundComponent =\n getDefaultExport(options.route.notFound) ?? getDefaultExport(options.rootNotFoundModule);\n if (notFoundComponent) {\n const NotFoundComponent = notFoundComponent;\n routeChildren = (\n <NotFoundBoundary resetKey={routeResetKey} fallback={<NotFoundComponent />}>\n {routeChildren}\n </NotFoundBoundary>\n );\n }\n\n const forbiddenComponent =\n getDefaultExport(options.route.forbidden) ?? getDefaultExport(options.rootForbiddenModule);\n if (forbiddenComponent) {\n const ForbiddenComponent = forbiddenComponent;\n routeChildren = (\n <ForbiddenBoundary resetKey={routeResetKey} fallback={<ForbiddenComponent />}>\n {routeChildren}\n </ForbiddenBoundary>\n );\n }\n\n const unauthorizedComponent =\n getDefaultExport(options.route.unauthorized) ??\n getDefaultExport(options.rootUnauthorizedModule);\n if (unauthorizedComponent) {\n const UnauthorizedComponent = unauthorizedComponent;\n routeChildren = (\n <UnauthorizedBoundary resetKey={routeResetKey} fallback={<UnauthorizedComponent />}>\n {routeChildren}\n </UnauthorizedBoundary>\n );\n }\n\n const pageErrorComponent = getErrorBoundaryExport(options.route.error);\n if (pageErrorComponent && options.route.error !== lastLayoutErrorModule) {\n routeChildren = (\n <ErrorBoundary resetKey={routeResetKey} fallback={pageErrorComponent}>\n {routeChildren}\n </ErrorBoundary>\n );\n }\n\n for (let index = orderedTreePositions.length - 1; index >= 0; index--) {\n const treePosition = orderedTreePositions[index];\n const segmentResetKey = resolveAppPageSegmentStateKey(\n routeSegments,\n treePosition,\n options.matchedParams,\n );\n let segmentChildren: ReactNode = routeChildren;\n const layoutEntry = layoutEntriesByTreePosition.get(treePosition);\n const templateEntry = templateEntriesByTreePosition.get(treePosition);\n const errorEntry = errorEntriesByTreePosition.get(treePosition);\n\n // Next.js nesting per segment (outer to inner): Layout > Template > Error > Unauthorized > Forbidden > NotFound > children.\n // Building bottom-up means NotFoundBoundary must wrap the leaf subtree first,\n // then ErrorBoundary, then Template, with the Layout slot outermost.\n if (layoutEntry) {\n const layoutNotFoundComponent = getDefaultExport(layoutEntry.notFoundModule);\n if (layoutNotFoundComponent) {\n const LayoutNotFoundComponent = layoutNotFoundComponent;\n segmentChildren = (\n <NotFoundBoundary resetKey={segmentResetKey} fallback={<LayoutNotFoundComponent />}>\n {segmentChildren}\n </NotFoundBoundary>\n );\n }\n\n const layoutForbiddenComponent = getDefaultExport(layoutEntry.forbiddenModule);\n if (layoutForbiddenComponent) {\n const LayoutForbiddenComponent = layoutForbiddenComponent;\n segmentChildren = (\n <ForbiddenBoundary resetKey={segmentResetKey} fallback={<LayoutForbiddenComponent />}>\n {segmentChildren}\n </ForbiddenBoundary>\n );\n }\n\n const layoutUnauthorizedComponent = getDefaultExport(layoutEntry.unauthorizedModule);\n if (layoutUnauthorizedComponent) {\n const LayoutUnauthorizedComponent = layoutUnauthorizedComponent;\n segmentChildren = (\n <UnauthorizedBoundary\n resetKey={segmentResetKey}\n fallback={<LayoutUnauthorizedComponent />}\n >\n {segmentChildren}\n </UnauthorizedBoundary>\n );\n }\n }\n\n const segmentErrorComponent = getErrorBoundaryExport(\n errorEntry?.errorModule ?? layoutEntry?.errorModule,\n );\n if (segmentErrorComponent) {\n segmentChildren = (\n <ErrorBoundary resetKey={segmentResetKey} fallback={segmentErrorComponent}>\n {segmentChildren}\n </ErrorBoundary>\n );\n }\n\n if (templateEntry && getDefaultExport(templateEntry.templateModule)) {\n segmentChildren = (\n <Slot id={templateEntry.id} key={segmentResetKey}>\n {segmentChildren}\n </Slot>\n );\n }\n\n if (!layoutEntry) {\n routeChildren = segmentChildren;\n continue;\n }\n const layoutHasElement = getDefaultExport(layoutEntry.layoutModule) !== null;\n const layoutIndex = layoutIndicesByTreePosition.get(treePosition) ?? -1;\n const segmentMap: { children: string[] } & Record<string, string[]> = {\n children: resolveAppPageChildSegments(\n routeSegments,\n layoutEntry.treePosition,\n options.matchedParams,\n ),\n };\n for (const [slotKey, slot] of Object.entries(options.route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n if (targetIndex !== layoutIndex) {\n continue;\n }\n const slotParams = getEffectiveSlotParams(slotKey, slotName);\n segmentMap[slotName] = slot.routeSegments\n ? resolveAppPageChildSegments(slot.routeSegments, 0, slotParams)\n : [];\n }\n\n routeChildren = (\n <LayoutSegmentProvider segmentMap={segmentMap}>\n {layoutHasElement ? (\n <Slot\n id={layoutEntry.id}\n parallelSlots={createAppPageParallelSlotEntries(\n layoutIndex,\n layoutEntries,\n options.route,\n getEffectiveSlotParams,\n )}\n >\n {segmentChildren}\n </Slot>\n ) : (\n segmentChildren\n )}\n </LayoutSegmentProvider>\n );\n }\n\n const globalErrorComponent = getErrorBoundaryExport(options.globalErrorModule);\n if (globalErrorComponent) {\n routeChildren = <ErrorBoundary fallback={globalErrorComponent}>{routeChildren}</ErrorBoundary>;\n }\n\n elements[routeId] = (\n <>\n {createAppPageRouteHead(\n options.resolvedMetadata,\n options.resolvedViewport,\n options.resolvedMetadataPathname ?? options.routePath,\n metadataPlacement,\n )}\n {routeChildren}\n {createAppPageRouteBodyMetadata(\n options.resolvedMetadata,\n options.resolvedMetadataPathname ?? options.routePath,\n metadataPlacement,\n )}\n </>\n );\n\n return elements;\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AppPageFontPreload } from "./app-page-execution.js";
|
|
2
|
+
import { RootParams } from "../shims/root-params.js";
|
|
2
3
|
import { ReactFormState } from "react-dom/client";
|
|
3
4
|
|
|
4
5
|
//#region src/server/app-page-stream.d.ts
|
|
@@ -17,6 +18,7 @@ type AppPageSsrHandler = {
|
|
|
17
18
|
formState?: ReactFormState | null;
|
|
18
19
|
scriptNonce?: string;
|
|
19
20
|
basePath?: string;
|
|
21
|
+
rootParams?: RootParams;
|
|
20
22
|
sideStream?: ReadableStream<Uint8Array>;
|
|
21
23
|
capturedRscDataRef?: {
|
|
22
24
|
value: Promise<ArrayBuffer> | null;
|
|
@@ -31,6 +33,7 @@ type RenderAppPageHtmlStreamOptions = {
|
|
|
31
33
|
rscStream: ReadableStream<Uint8Array>;
|
|
32
34
|
scriptNonce?: string;
|
|
33
35
|
basePath?: string;
|
|
36
|
+
rootParams?: RootParams;
|
|
34
37
|
ssrHandler: AppPageSsrHandler;
|
|
35
38
|
/** Pre-split side stream for fused embed+capture (#981). When set,
|
|
36
39
|
* handleSsr skips its internal tee and accumulates raw RSC bytes. */
|
|
@@ -43,6 +46,7 @@ type RenderAppPageHtmlStreamOptions = {
|
|
|
43
46
|
type RenderAppPageHtmlResponseOptions = {
|
|
44
47
|
clearRequestContext: () => void;
|
|
45
48
|
fontLinkHeader?: string;
|
|
49
|
+
isEdgeRuntime?: boolean;
|
|
46
50
|
middlewareHeaders?: Headers | null;
|
|
47
51
|
status: number;
|
|
48
52
|
} & RenderAppPageHtmlStreamOptions;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { VINEXT_RSC_VARY_HEADER } from "./app-rsc-cache-busting.js";
|
|
2
2
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
3
|
+
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
3
4
|
//#region src/server/app-page-stream.ts
|
|
4
5
|
function createAppPageFontData(options) {
|
|
5
6
|
return {
|
|
@@ -13,6 +14,7 @@ async function renderAppPageHtmlStream(options) {
|
|
|
13
14
|
formState: options.formState ?? null,
|
|
14
15
|
scriptNonce: options.scriptNonce,
|
|
15
16
|
basePath: options.basePath,
|
|
17
|
+
rootParams: options.rootParams,
|
|
16
18
|
sideStream: options.sideStream,
|
|
17
19
|
capturedRscDataRef: options.capturedRscDataRef,
|
|
18
20
|
waitForAllReady: options.waitForAllReady
|
|
@@ -62,6 +64,7 @@ async function renderAppPageHtmlResponse(options) {
|
|
|
62
64
|
"Content-Type": "text/html; charset=utf-8",
|
|
63
65
|
Vary: VINEXT_RSC_VARY_HEADER
|
|
64
66
|
});
|
|
67
|
+
applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);
|
|
65
68
|
if (options.fontLinkHeader) headers.set("Link", options.fontLinkHeader);
|
|
66
69
|
mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);
|
|
67
70
|
return new Response(safeStream, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-page-stream.js","names":[],"sources":["../../src/server/app-page-stream.ts"],"sourcesContent":["import type { AppPageFontPreload } from \"./app-page-execution.js\";\nimport type { ReactFormState } from \"react-dom/client\";\nimport { VINEXT_RSC_VARY_HEADER } from \"./app-rsc-cache-busting.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\n\nexport type AppPageFontData = {\n links: string[];\n preloads: readonly AppPageFontPreload[];\n styles: string[];\n};\n\ntype CreateAppPageFontDataOptions = {\n getLinks: () => string[];\n getPreloads: () => AppPageFontPreload[];\n getStyles: () => string[];\n};\n\nexport type AppPageSsrHandler = {\n handleSsr: (\n rscStream: ReadableStream<Uint8Array>,\n navigationContext: unknown,\n fontData: AppPageFontData,\n options?: {\n formState?: ReactFormState | null;\n scriptNonce?: string;\n basePath?: string;\n sideStream?: ReadableStream<Uint8Array>;\n capturedRscDataRef?: { value: Promise<ArrayBuffer> | null };\n /** When true, wait for the full React tree before emitting bytes. */\n waitForAllReady?: boolean;\n },\n ) => Promise<ReadableStream<Uint8Array>>;\n};\n\ntype RenderAppPageHtmlStreamOptions = {\n fontData: AppPageFontData;\n formState?: ReactFormState | null;\n navigationContext: unknown;\n rscStream: ReadableStream<Uint8Array>;\n scriptNonce?: string;\n basePath?: string;\n ssrHandler: AppPageSsrHandler;\n /** Pre-split side stream for fused embed+capture (#981). When set,\n * handleSsr skips its internal tee and accumulates raw RSC bytes. */\n sideStream?: ReadableStream<Uint8Array>;\n /** Out-parameter filled with accumulated raw RSC bytes after stream consumption. */\n capturedRscDataRef?: { value: Promise<ArrayBuffer> | null };\n /** When true, wait for the full React tree before emitting bytes. */\n waitForAllReady?: boolean;\n};\n\ntype RenderAppPageHtmlResponseOptions = {\n clearRequestContext: () => void;\n fontLinkHeader?: string;\n middlewareHeaders?: Headers | null;\n status: number;\n} & RenderAppPageHtmlStreamOptions;\n\ntype AppPageHtmlStreamRecoveryResult = {\n htmlStream: ReadableStream<Uint8Array> | null;\n response: Response | null;\n};\n\ntype RenderAppPageHtmlStreamWithRecoveryOptions<TSpecialError> = {\n onShellRendered?: () => void;\n renderErrorBoundaryResponse: (error: unknown) => Promise<Response | null>;\n renderHtmlStream: () => Promise<ReadableStream<Uint8Array>>;\n renderSpecialErrorResponse: (specialError: TSpecialError) => Promise<Response>;\n resolveSpecialError: (error: unknown) => TSpecialError | null;\n};\n\ntype AppPageRscErrorTracker = {\n getCapturedError: () => unknown;\n /**\n * Returns a NEXT_REDIRECT or NEXT_HTTP_ERROR_FALLBACK error captured during\n * the RSC render. Read after the SSR shell promise resolves to swap a\n * 307/404 in place of the streamed body when redirect()/notFound() throws\n * synchronously inside a route-level Suspense boundary (loading.tsx).\n */\n getCapturedSpecialError: () => unknown;\n onRenderError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;\n};\n\ntype ShouldRerenderAppPageWithGlobalErrorOptions = {\n capturedError: unknown;\n hasLocalBoundary: boolean;\n};\n\nexport function createAppPageFontData(options: CreateAppPageFontDataOptions): AppPageFontData {\n return {\n links: options.getLinks(),\n preloads: options.getPreloads(),\n styles: options.getStyles(),\n };\n}\n\nexport async function renderAppPageHtmlStream(\n options: RenderAppPageHtmlStreamOptions,\n): Promise<ReadableStream<Uint8Array>> {\n const ssrOptions = {\n formState: options.formState ?? null,\n scriptNonce: options.scriptNonce,\n basePath: options.basePath,\n sideStream: options.sideStream,\n capturedRscDataRef: options.capturedRscDataRef,\n waitForAllReady: options.waitForAllReady,\n };\n\n return options.ssrHandler.handleSsr(\n options.rscStream,\n options.navigationContext,\n options.fontData,\n ssrOptions,\n );\n}\n\n/**\n * Wraps a stream so that `onFlush` is called when the last byte has been read\n * by the downstream consumer (i.e. when the HTTP layer finishes draining the\n * response body). This is the correct place to clear per-request context,\n * because the RSC/SSR pipeline is lazy — components execute while the stream\n * is being consumed, not when the stream handle is first obtained.\n */\nexport function deferUntilStreamConsumed(\n stream: ReadableStream<Uint8Array>,\n onFlush: () => void,\n): ReadableStream<Uint8Array> {\n let called = false;\n const once = () => {\n if (!called) {\n called = true;\n onFlush();\n }\n };\n\n const cleanup = new TransformStream<Uint8Array, Uint8Array>({\n flush() {\n once();\n },\n });\n\n const piped = stream.pipeThrough(cleanup);\n\n // Wrap with a ReadableStream so we can intercept cancel() — the TransformStream\n // Transformer interface does not expose a cancel hook in the Web Streams spec.\n const reader = piped.getReader();\n return new ReadableStream<Uint8Array>({\n pull(controller) {\n return reader.read().then(\n ({ done, value }) => {\n if (done) {\n controller.close();\n } else {\n controller.enqueue(value);\n }\n },\n (error) => {\n once();\n controller.error(error);\n },\n );\n },\n cancel(reason) {\n // Stream cancelled before fully consumed (e.g. client disconnected).\n // Still clear per-request context to avoid leaks.\n once();\n return reader.cancel(reason);\n },\n });\n}\n\nexport async function renderAppPageHtmlResponse(\n options: RenderAppPageHtmlResponseOptions,\n): Promise<Response> {\n const htmlStream = await renderAppPageHtmlStream(options);\n\n // Defer clearRequestContext() until the stream is fully consumed by the HTTP\n // layer. Calling it synchronously here would race the lazy RSC/SSR pipeline:\n // components execute while the stream is being pulled, not when the handle\n // is first returned. See: https://github.com/cloudflare/vinext/issues/660\n const safeStream = deferUntilStreamConsumed(htmlStream, () => {\n options.clearRequestContext();\n });\n\n const headers = new Headers({\n \"Content-Type\": \"text/html; charset=utf-8\",\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n\n if (options.fontLinkHeader) {\n headers.set(\"Link\", options.fontLinkHeader);\n }\n\n mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);\n\n return new Response(safeStream, {\n status: options.status,\n headers,\n });\n}\n\nexport async function renderAppPageHtmlStreamWithRecovery<TSpecialError>(\n options: RenderAppPageHtmlStreamWithRecoveryOptions<TSpecialError>,\n): Promise<AppPageHtmlStreamRecoveryResult> {\n try {\n const htmlStream = await options.renderHtmlStream();\n options.onShellRendered?.();\n return {\n htmlStream,\n response: null,\n };\n } catch (error) {\n const specialError = options.resolveSpecialError(error);\n if (specialError) {\n return {\n htmlStream: null,\n response: await options.renderSpecialErrorResponse(specialError),\n };\n }\n\n const boundaryResponse = await options.renderErrorBoundaryResponse(error);\n if (boundaryResponse) {\n return {\n htmlStream: null,\n response: boundaryResponse,\n };\n }\n\n throw error;\n }\n}\n\nexport function createAppPageRscErrorTracker(\n baseOnError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown,\n): AppPageRscErrorTracker {\n let capturedError: unknown = null;\n let capturedSpecialError: unknown = null;\n\n return {\n getCapturedError() {\n return capturedError;\n },\n getCapturedSpecialError() {\n return capturedSpecialError;\n },\n onRenderError(error, requestInfo, errorContext) {\n if (error && typeof error === \"object\" && \"digest\" in error) {\n // Errors with a digest are signal throws (NEXT_REDIRECT,\n // NEXT_NOT_FOUND, NEXT_HTTP_ERROR_FALLBACK). They're not real\n // failures — keep the first one so the lifecycle can swap a\n // 307/404 in place of a streamed \"Switched to client rendering\"\n // body for routes with a route-level Suspense boundary.\n if (capturedSpecialError === null) {\n capturedSpecialError = error;\n }\n } else {\n capturedError = error;\n }\n return baseOnError(error, requestInfo, errorContext);\n },\n };\n}\n\nexport function shouldRerenderAppPageWithGlobalError(\n options: ShouldRerenderAppPageWithGlobalErrorOptions,\n): boolean {\n return Boolean(options.capturedError) && !options.hasLocalBoundary;\n}\n"],"mappings":";;;AAwFA,SAAgB,sBAAsB,SAAwD;CAC5F,OAAO;EACL,OAAO,QAAQ,UAAU;EACzB,UAAU,QAAQ,aAAa;EAC/B,QAAQ,QAAQ,WAAW;EAC5B;;AAGH,eAAsB,wBACpB,SACqC;CACrC,MAAM,aAAa;EACjB,WAAW,QAAQ,aAAa;EAChC,aAAa,QAAQ;EACrB,UAAU,QAAQ;EAClB,YAAY,QAAQ;EACpB,oBAAoB,QAAQ;EAC5B,iBAAiB,QAAQ;EAC1B;CAED,OAAO,QAAQ,WAAW,UACxB,QAAQ,WACR,QAAQ,mBACR,QAAQ,UACR,WACD;;;;;;;;;AAUH,SAAgB,yBACd,QACA,SAC4B;CAC5B,IAAI,SAAS;CACb,MAAM,aAAa;EACjB,IAAI,CAAC,QAAQ;GACX,SAAS;GACT,SAAS;;;CAIb,MAAM,UAAU,IAAI,gBAAwC,EAC1D,QAAQ;EACN,MAAM;IAET,CAAC;CAMF,MAAM,SAJQ,OAAO,YAAY,QAIb,CAAC,WAAW;CAChC,OAAO,IAAI,eAA2B;EACpC,KAAK,YAAY;GACf,OAAO,OAAO,MAAM,CAAC,MAClB,EAAE,MAAM,YAAY;IACnB,IAAI,MACF,WAAW,OAAO;SAElB,WAAW,QAAQ,MAAM;OAG5B,UAAU;IACT,MAAM;IACN,WAAW,MAAM,MAAM;KAE1B;;EAEH,OAAO,QAAQ;GAGb,MAAM;GACN,OAAO,OAAO,OAAO,OAAO;;EAE/B,CAAC;;AAGJ,eAAsB,0BACpB,SACmB;CAOnB,MAAM,aAAa,yBAAyB,MANnB,wBAAwB,QAAQ,QAMK;EAC5D,QAAQ,qBAAqB;GAC7B;CAEF,MAAM,UAAU,IAAI,QAAQ;EAC1B,gBAAgB;EAChB,MAAM;EACP,CAAC;CAEF,IAAI,QAAQ,gBACV,QAAQ,IAAI,QAAQ,QAAQ,eAAe;CAG7C,+BAA+B,SAAS,QAAQ,qBAAqB,KAAK;CAE1E,OAAO,IAAI,SAAS,YAAY;EAC9B,QAAQ,QAAQ;EAChB;EACD,CAAC;;AAGJ,eAAsB,oCACpB,SAC0C;CAC1C,IAAI;EACF,MAAM,aAAa,MAAM,QAAQ,kBAAkB;EACnD,QAAQ,mBAAmB;EAC3B,OAAO;GACL;GACA,UAAU;GACX;UACM,OAAO;EACd,MAAM,eAAe,QAAQ,oBAAoB,MAAM;EACvD,IAAI,cACF,OAAO;GACL,YAAY;GACZ,UAAU,MAAM,QAAQ,2BAA2B,aAAa;GACjE;EAGH,MAAM,mBAAmB,MAAM,QAAQ,4BAA4B,MAAM;EACzE,IAAI,kBACF,OAAO;GACL,YAAY;GACZ,UAAU;GACX;EAGH,MAAM;;;AAIV,SAAgB,6BACd,aACwB;CACxB,IAAI,gBAAyB;CAC7B,IAAI,uBAAgC;CAEpC,OAAO;EACL,mBAAmB;GACjB,OAAO;;EAET,0BAA0B;GACxB,OAAO;;EAET,cAAc,OAAO,aAAa,cAAc;GAC9C,IAAI,SAAS,OAAO,UAAU,YAAY,YAAY;QAMhD,yBAAyB,MAC3B,uBAAuB;UAGzB,gBAAgB;GAElB,OAAO,YAAY,OAAO,aAAa,aAAa;;EAEvD;;AAGH,SAAgB,qCACd,SACS;CACT,OAAO,QAAQ,QAAQ,cAAc,IAAI,CAAC,QAAQ"}
|
|
1
|
+
{"version":3,"file":"app-page-stream.js","names":[],"sources":["../../src/server/app-page-stream.ts"],"sourcesContent":["import type { AppPageFontPreload } from \"./app-page-execution.js\";\nimport type { ReactFormState } from \"react-dom/client\";\nimport { VINEXT_RSC_VARY_HEADER } from \"./app-rsc-cache-busting.js\";\nimport { applyEdgeRuntimeHeader } from \"./app-page-response.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport type { RootParams } from \"vinext/shims/root-params\";\n\nexport type AppPageFontData = {\n links: string[];\n preloads: readonly AppPageFontPreload[];\n styles: string[];\n};\n\ntype CreateAppPageFontDataOptions = {\n getLinks: () => string[];\n getPreloads: () => AppPageFontPreload[];\n getStyles: () => string[];\n};\n\nexport type AppPageSsrHandler = {\n handleSsr: (\n rscStream: ReadableStream<Uint8Array>,\n navigationContext: unknown,\n fontData: AppPageFontData,\n options?: {\n formState?: ReactFormState | null;\n scriptNonce?: string;\n basePath?: string;\n rootParams?: RootParams;\n sideStream?: ReadableStream<Uint8Array>;\n capturedRscDataRef?: { value: Promise<ArrayBuffer> | null };\n /** When true, wait for the full React tree before emitting bytes. */\n waitForAllReady?: boolean;\n },\n ) => Promise<ReadableStream<Uint8Array>>;\n};\n\ntype RenderAppPageHtmlStreamOptions = {\n fontData: AppPageFontData;\n formState?: ReactFormState | null;\n navigationContext: unknown;\n rscStream: ReadableStream<Uint8Array>;\n scriptNonce?: string;\n basePath?: string;\n rootParams?: RootParams;\n ssrHandler: AppPageSsrHandler;\n /** Pre-split side stream for fused embed+capture (#981). When set,\n * handleSsr skips its internal tee and accumulates raw RSC bytes. */\n sideStream?: ReadableStream<Uint8Array>;\n /** Out-parameter filled with accumulated raw RSC bytes after stream consumption. */\n capturedRscDataRef?: { value: Promise<ArrayBuffer> | null };\n /** When true, wait for the full React tree before emitting bytes. */\n waitForAllReady?: boolean;\n};\n\ntype RenderAppPageHtmlResponseOptions = {\n clearRequestContext: () => void;\n fontLinkHeader?: string;\n isEdgeRuntime?: boolean;\n middlewareHeaders?: Headers | null;\n status: number;\n} & RenderAppPageHtmlStreamOptions;\n\ntype AppPageHtmlStreamRecoveryResult = {\n htmlStream: ReadableStream<Uint8Array> | null;\n response: Response | null;\n};\n\ntype RenderAppPageHtmlStreamWithRecoveryOptions<TSpecialError> = {\n onShellRendered?: () => void;\n renderErrorBoundaryResponse: (error: unknown) => Promise<Response | null>;\n renderHtmlStream: () => Promise<ReadableStream<Uint8Array>>;\n renderSpecialErrorResponse: (specialError: TSpecialError) => Promise<Response>;\n resolveSpecialError: (error: unknown) => TSpecialError | null;\n};\n\ntype AppPageRscErrorTracker = {\n getCapturedError: () => unknown;\n /**\n * Returns a NEXT_REDIRECT or NEXT_HTTP_ERROR_FALLBACK error captured during\n * the RSC render. Read after the SSR shell promise resolves to swap a\n * 307/404 in place of the streamed body when redirect()/notFound() throws\n * synchronously inside a route-level Suspense boundary (loading.tsx).\n */\n getCapturedSpecialError: () => unknown;\n onRenderError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;\n};\n\ntype ShouldRerenderAppPageWithGlobalErrorOptions = {\n capturedError: unknown;\n hasLocalBoundary: boolean;\n};\n\nexport function createAppPageFontData(options: CreateAppPageFontDataOptions): AppPageFontData {\n return {\n links: options.getLinks(),\n preloads: options.getPreloads(),\n styles: options.getStyles(),\n };\n}\n\nexport async function renderAppPageHtmlStream(\n options: RenderAppPageHtmlStreamOptions,\n): Promise<ReadableStream<Uint8Array>> {\n const ssrOptions = {\n formState: options.formState ?? null,\n scriptNonce: options.scriptNonce,\n basePath: options.basePath,\n rootParams: options.rootParams,\n sideStream: options.sideStream,\n capturedRscDataRef: options.capturedRscDataRef,\n waitForAllReady: options.waitForAllReady,\n };\n\n return options.ssrHandler.handleSsr(\n options.rscStream,\n options.navigationContext,\n options.fontData,\n ssrOptions,\n );\n}\n\n/**\n * Wraps a stream so that `onFlush` is called when the last byte has been read\n * by the downstream consumer (i.e. when the HTTP layer finishes draining the\n * response body). This is the correct place to clear per-request context,\n * because the RSC/SSR pipeline is lazy — components execute while the stream\n * is being consumed, not when the stream handle is first obtained.\n */\nexport function deferUntilStreamConsumed(\n stream: ReadableStream<Uint8Array>,\n onFlush: () => void,\n): ReadableStream<Uint8Array> {\n let called = false;\n const once = () => {\n if (!called) {\n called = true;\n onFlush();\n }\n };\n\n const cleanup = new TransformStream<Uint8Array, Uint8Array>({\n flush() {\n once();\n },\n });\n\n const piped = stream.pipeThrough(cleanup);\n\n // Wrap with a ReadableStream so we can intercept cancel() — the TransformStream\n // Transformer interface does not expose a cancel hook in the Web Streams spec.\n const reader = piped.getReader();\n return new ReadableStream<Uint8Array>({\n pull(controller) {\n return reader.read().then(\n ({ done, value }) => {\n if (done) {\n controller.close();\n } else {\n controller.enqueue(value);\n }\n },\n (error) => {\n once();\n controller.error(error);\n },\n );\n },\n cancel(reason) {\n // Stream cancelled before fully consumed (e.g. client disconnected).\n // Still clear per-request context to avoid leaks.\n once();\n return reader.cancel(reason);\n },\n });\n}\n\nexport async function renderAppPageHtmlResponse(\n options: RenderAppPageHtmlResponseOptions,\n): Promise<Response> {\n const htmlStream = await renderAppPageHtmlStream(options);\n\n // Defer clearRequestContext() until the stream is fully consumed by the HTTP\n // layer. Calling it synchronously here would race the lazy RSC/SSR pipeline:\n // components execute while the stream is being pulled, not when the handle\n // is first returned. See: https://github.com/cloudflare/vinext/issues/660\n const safeStream = deferUntilStreamConsumed(htmlStream, () => {\n options.clearRequestContext();\n });\n\n const headers = new Headers({\n \"Content-Type\": \"text/html; charset=utf-8\",\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n\n applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);\n\n if (options.fontLinkHeader) {\n headers.set(\"Link\", options.fontLinkHeader);\n }\n\n mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);\n\n return new Response(safeStream, {\n status: options.status,\n headers,\n });\n}\n\nexport async function renderAppPageHtmlStreamWithRecovery<TSpecialError>(\n options: RenderAppPageHtmlStreamWithRecoveryOptions<TSpecialError>,\n): Promise<AppPageHtmlStreamRecoveryResult> {\n try {\n const htmlStream = await options.renderHtmlStream();\n options.onShellRendered?.();\n return {\n htmlStream,\n response: null,\n };\n } catch (error) {\n const specialError = options.resolveSpecialError(error);\n if (specialError) {\n return {\n htmlStream: null,\n response: await options.renderSpecialErrorResponse(specialError),\n };\n }\n\n const boundaryResponse = await options.renderErrorBoundaryResponse(error);\n if (boundaryResponse) {\n return {\n htmlStream: null,\n response: boundaryResponse,\n };\n }\n\n throw error;\n }\n}\n\nexport function createAppPageRscErrorTracker(\n baseOnError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown,\n): AppPageRscErrorTracker {\n let capturedError: unknown = null;\n let capturedSpecialError: unknown = null;\n\n return {\n getCapturedError() {\n return capturedError;\n },\n getCapturedSpecialError() {\n return capturedSpecialError;\n },\n onRenderError(error, requestInfo, errorContext) {\n if (error && typeof error === \"object\" && \"digest\" in error) {\n // Errors with a digest are signal throws (NEXT_REDIRECT,\n // NEXT_NOT_FOUND, NEXT_HTTP_ERROR_FALLBACK). They're not real\n // failures — keep the first one so the lifecycle can swap a\n // 307/404 in place of a streamed \"Switched to client rendering\"\n // body for routes with a route-level Suspense boundary.\n if (capturedSpecialError === null) {\n capturedSpecialError = error;\n }\n } else {\n capturedError = error;\n }\n return baseOnError(error, requestInfo, errorContext);\n },\n };\n}\n\nexport function shouldRerenderAppPageWithGlobalError(\n options: ShouldRerenderAppPageWithGlobalErrorOptions,\n): boolean {\n return Boolean(options.capturedError) && !options.hasLocalBoundary;\n}\n"],"mappings":";;;;AA6FA,SAAgB,sBAAsB,SAAwD;CAC5F,OAAO;EACL,OAAO,QAAQ,UAAU;EACzB,UAAU,QAAQ,aAAa;EAC/B,QAAQ,QAAQ,WAAW;EAC5B;;AAGH,eAAsB,wBACpB,SACqC;CACrC,MAAM,aAAa;EACjB,WAAW,QAAQ,aAAa;EAChC,aAAa,QAAQ;EACrB,UAAU,QAAQ;EAClB,YAAY,QAAQ;EACpB,YAAY,QAAQ;EACpB,oBAAoB,QAAQ;EAC5B,iBAAiB,QAAQ;EAC1B;CAED,OAAO,QAAQ,WAAW,UACxB,QAAQ,WACR,QAAQ,mBACR,QAAQ,UACR,WACD;;;;;;;;;AAUH,SAAgB,yBACd,QACA,SAC4B;CAC5B,IAAI,SAAS;CACb,MAAM,aAAa;EACjB,IAAI,CAAC,QAAQ;GACX,SAAS;GACT,SAAS;;;CAIb,MAAM,UAAU,IAAI,gBAAwC,EAC1D,QAAQ;EACN,MAAM;IAET,CAAC;CAMF,MAAM,SAJQ,OAAO,YAAY,QAIb,CAAC,WAAW;CAChC,OAAO,IAAI,eAA2B;EACpC,KAAK,YAAY;GACf,OAAO,OAAO,MAAM,CAAC,MAClB,EAAE,MAAM,YAAY;IACnB,IAAI,MACF,WAAW,OAAO;SAElB,WAAW,QAAQ,MAAM;OAG5B,UAAU;IACT,MAAM;IACN,WAAW,MAAM,MAAM;KAE1B;;EAEH,OAAO,QAAQ;GAGb,MAAM;GACN,OAAO,OAAO,OAAO,OAAO;;EAE/B,CAAC;;AAGJ,eAAsB,0BACpB,SACmB;CAOnB,MAAM,aAAa,yBAAyB,MANnB,wBAAwB,QAAQ,QAMK;EAC5D,QAAQ,qBAAqB;GAC7B;CAEF,MAAM,UAAU,IAAI,QAAQ;EAC1B,gBAAgB;EAChB,MAAM;EACP,CAAC;CAEF,uBAAuB,SAAS,QAAQ,cAAc;CAEtD,IAAI,QAAQ,gBACV,QAAQ,IAAI,QAAQ,QAAQ,eAAe;CAG7C,+BAA+B,SAAS,QAAQ,qBAAqB,KAAK;CAE1E,OAAO,IAAI,SAAS,YAAY;EAC9B,QAAQ,QAAQ;EAChB;EACD,CAAC;;AAGJ,eAAsB,oCACpB,SAC0C;CAC1C,IAAI;EACF,MAAM,aAAa,MAAM,QAAQ,kBAAkB;EACnD,QAAQ,mBAAmB;EAC3B,OAAO;GACL;GACA,UAAU;GACX;UACM,OAAO;EACd,MAAM,eAAe,QAAQ,oBAAoB,MAAM;EACvD,IAAI,cACF,OAAO;GACL,YAAY;GACZ,UAAU,MAAM,QAAQ,2BAA2B,aAAa;GACjE;EAGH,MAAM,mBAAmB,MAAM,QAAQ,4BAA4B,MAAM;EACzE,IAAI,kBACF,OAAO;GACL,YAAY;GACZ,UAAU;GACX;EAGH,MAAM;;;AAIV,SAAgB,6BACd,aACwB;CACxB,IAAI,gBAAyB;CAC7B,IAAI,uBAAgC;CAEpC,OAAO;EACL,mBAAmB;GACjB,OAAO;;EAET,0BAA0B;GACxB,OAAO;;EAET,cAAc,OAAO,aAAa,cAAc;GAC9C,IAAI,SAAS,OAAO,UAAU,YAAY,YAAY;QAMhD,yBAAyB,MAC3B,uBAAuB;UAGzB,gBAAgB;GAElB,OAAO,YAAY,OAAO,aAAa,aAAa;;EAEvD;;AAGH,SAAgB,qCACd,SACS;CACT,OAAO,QAAQ,QAAQ,cAAc,IAAI,CAAC,QAAQ"}
|
|
@@ -4,6 +4,7 @@ import { RootParams } from "../shims/root-params.js";
|
|
|
4
4
|
type GenerateStaticParamsFunction = (input: {
|
|
5
5
|
params: RootParams;
|
|
6
6
|
}) => unknown;
|
|
7
|
+
declare function createAppPrerenderStaticParamsResolver(sources: readonly unknown[], rootParamNames?: readonly string[]): GenerateStaticParamsFunction | null;
|
|
7
8
|
type CallAppPrerenderStaticParamsOptions = {
|
|
8
9
|
fn: GenerateStaticParamsFunction;
|
|
9
10
|
params: RootParams;
|
|
@@ -12,5 +13,5 @@ type CallAppPrerenderStaticParamsOptions = {
|
|
|
12
13
|
};
|
|
13
14
|
declare function callAppPrerenderStaticParams(options: CallAppPrerenderStaticParamsOptions): Promise<unknown>;
|
|
14
15
|
//#endregion
|
|
15
|
-
export { callAppPrerenderStaticParams };
|
|
16
|
+
export { callAppPrerenderStaticParams, createAppPrerenderStaticParamsResolver };
|
|
16
17
|
//# sourceMappingURL=app-prerender-static-params.d.ts.map
|