vinext 0.0.50 → 0.0.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build/google-fonts/fallback-metrics-data.js +14031 -0
- package/dist/build/google-fonts/fallback-metrics-data.js.map +1 -0
- package/dist/build/google-fonts/fallback-metrics.d.ts +13 -0
- package/dist/build/google-fonts/fallback-metrics.js +46 -0
- package/dist/build/google-fonts/fallback-metrics.js.map +1 -0
- package/dist/build/precompress.d.ts +13 -2
- package/dist/build/precompress.js +23 -13
- package/dist/build/precompress.js.map +1 -1
- package/dist/build/prerender.d.ts +4 -15
- package/dist/build/prerender.js +83 -53
- package/dist/build/prerender.js.map +1 -1
- package/dist/build/report.d.ts +5 -4
- package/dist/build/report.js +196 -348
- package/dist/build/report.js.map +1 -1
- package/dist/check.js +5 -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 +99 -3
- package/dist/cli.js.map +1 -1
- package/dist/client/navigation-runtime.d.ts +47 -0
- package/dist/client/navigation-runtime.js +156 -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 +12 -2
- 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 +3 -1
- 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/config/config-matchers.d.ts +63 -16
- package/dist/config/config-matchers.js +143 -8
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/config/dotenv.d.ts +11 -1
- package/dist/config/dotenv.js.map +1 -1
- package/dist/config/next-config.d.ts +107 -5
- package/dist/config/next-config.js +233 -7
- package/dist/config/next-config.js.map +1 -1
- package/dist/config/tsconfig-paths.d.ts +13 -0
- package/dist/config/tsconfig-paths.js +117 -0
- package/dist/config/tsconfig-paths.js.map +1 -0
- package/dist/deploy.js +104 -41
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-browser-entry.d.ts +2 -2
- package/dist/entries/app-browser-entry.js +34 -3
- package/dist/entries/app-browser-entry.js.map +1 -1
- package/dist/entries/app-rsc-entry.d.ts +19 -1
- package/dist/entries/app-rsc-entry.js +89 -23
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.d.ts +10 -0
- package/dist/entries/app-rsc-manifest.js +57 -7
- 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 +21 -7
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-server-entry.js +77 -9
- 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 +260 -75
- package/dist/index.js.map +1 -1
- package/dist/plugins/client-reference-dedup.d.ts +15 -2
- package/dist/plugins/client-reference-dedup.js +138 -16
- package/dist/plugins/client-reference-dedup.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.d.ts +2 -2
- package/dist/plugins/fonts.js +20 -9
- 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/sass.d.ts +34 -0
- package/dist/plugins/sass.js +22 -0
- package/dist/plugins/sass.js.map +1 -0
- 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 +50 -2
- package/dist/routing/app-route-graph.js +140 -16
- 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-pattern.d.ts +56 -1
- package/dist/routing/route-pattern.js +60 -1
- package/dist/routing/route-pattern.js.map +1 -1
- package/dist/routing/utils.d.ts +2 -1
- package/dist/routing/utils.js +4 -1
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/api-handler.js +139 -37
- package/dist/server/api-handler.js.map +1 -1
- package/dist/server/app-browser-action-result.d.ts +27 -2
- package/dist/server/app-browser-action-result.js +63 -2
- package/dist/server/app-browser-action-result.js.map +1 -1
- package/dist/server/app-browser-entry.js +493 -195
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-hydration.d.ts +13 -1
- package/dist/server/app-browser-hydration.js +9 -1
- package/dist/server/app-browser-hydration.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 +17 -2
- package/dist/server/app-browser-navigation-controller.js +33 -10
- package/dist/server/app-browser-navigation-controller.js.map +1 -1
- package/dist/server/app-browser-popstate.d.ts +16 -0
- package/dist/server/app-browser-popstate.js +17 -0
- package/dist/server/app-browser-popstate.js.map +1 -0
- package/dist/server/app-browser-rsc-redirect.d.ts +29 -0
- package/dist/server/app-browser-rsc-redirect.js +37 -0
- package/dist/server/app-browser-rsc-redirect.js.map +1 -0
- package/dist/server/app-browser-state.d.ts +28 -7
- package/dist/server/app-browser-state.js +63 -27
- package/dist/server/app-browser-state.js.map +1 -1
- package/dist/server/app-browser-stream.d.ts +9 -17
- package/dist/server/app-browser-stream.js +18 -13
- package/dist/server/app-browser-stream.js.map +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +7 -1
- package/dist/server/app-browser-visible-commit.js +39 -5
- package/dist/server/app-browser-visible-commit.js.map +1 -1
- package/dist/server/app-elements-wire.d.ts +43 -6
- package/dist/server/app-elements-wire.js +189 -7
- 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 +10 -1
- package/dist/server/app-fallback-renderer.js +41 -3
- package/dist/server/app-fallback-renderer.js.map +1 -1
- package/dist/server/app-history-state.d.ts +26 -0
- package/dist/server/app-history-state.js +53 -0
- package/dist/server/app-history-state.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-optimistic-routing.d.ts +54 -0
- package/dist/server/app-optimistic-routing.js +200 -0
- package/dist/server/app-optimistic-routing.js.map +1 -0
- package/dist/server/app-page-boundary-render.d.ts +10 -1
- package/dist/server/app-page-boundary-render.js +13 -6
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-boundary.js +3 -2
- package/dist/server/app-page-boundary.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +26 -1
- package/dist/server/app-page-cache.js +86 -14
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-dispatch.d.ts +7 -0
- package/dist/server/app-page-dispatch.js +96 -12
- package/dist/server/app-page-dispatch.js.map +1 -1
- package/dist/server/app-page-element-builder.d.ts +7 -0
- package/dist/server/app-page-element-builder.js +34 -5
- package/dist/server/app-page-element-builder.js.map +1 -1
- package/dist/server/app-page-execution.d.ts +28 -1
- package/dist/server/app-page-execution.js +91 -7
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-head.d.ts +7 -0
- package/dist/server/app-page-head.js +23 -3
- package/dist/server/app-page-head.js.map +1 -1
- package/dist/server/app-page-probe.d.ts +23 -1
- package/dist/server/app-page-probe.js +29 -1
- package/dist/server/app-page-probe.js.map +1 -1
- package/dist/server/app-page-render-observation.d.ts +35 -0
- package/dist/server/app-page-render-observation.js +68 -0
- package/dist/server/app-page-render-observation.js.map +1 -0
- package/dist/server/app-page-render.d.ts +7 -1
- package/dist/server/app-page-render.js +81 -4
- package/dist/server/app-page-render.js.map +1 -1
- package/dist/server/app-page-request.d.ts +1 -0
- package/dist/server/app-page-request.js.map +1 -1
- package/dist/server/app-page-response.js +7 -5
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +3 -1
- package/dist/server/app-page-route-wiring.js +59 -24
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-page-stream.d.ts +5 -0
- package/dist/server/app-page-stream.js +2 -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 +6 -1
- package/dist/server/app-route-handler-dispatch.js +1 -1
- package/dist/server/app-route-handler-dispatch.js.map +1 -1
- package/dist/server/app-route-handler-execution.d.ts +17 -2
- package/dist/server/app-route-handler-execution.js.map +1 -1
- package/dist/server/app-route-handler-response.js +5 -4
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-router-entry.js +7 -15
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +19 -1
- package/dist/server/app-rsc-cache-busting.js +36 -1
- package/dist/server/app-rsc-cache-busting.js.map +1 -1
- package/dist/server/app-rsc-embedded-chunks.d.ts +9 -0
- package/dist/server/app-rsc-embedded-chunks.js +34 -0
- package/dist/server/app-rsc-embedded-chunks.js.map +1 -0
- package/dist/server/app-rsc-errors.d.ts +4 -1
- package/dist/server/app-rsc-errors.js +1 -1
- package/dist/server/app-rsc-errors.js.map +1 -1
- package/dist/server/app-rsc-handler.d.ts +21 -5
- package/dist/server/app-rsc-handler.js +38 -15
- 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 +4 -1
- 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.d.ts +23 -0
- package/dist/server/app-rsc-route-matching.js +47 -25
- package/dist/server/app-rsc-route-matching.js.map +1 -1
- package/dist/server/app-server-action-execution.d.ts +35 -3
- package/dist/server/app-server-action-execution.js +87 -33
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/app-ssr-entry.d.ts +3 -0
- package/dist/server/app-ssr-entry.js +83 -58
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/app-ssr-error-meta.d.ts +14 -0
- package/dist/server/app-ssr-error-meta.js +50 -0
- package/dist/server/app-ssr-error-meta.js.map +1 -0
- package/dist/server/app-ssr-stream.d.ts +7 -2
- package/dist/server/app-ssr-stream.js +26 -15
- package/dist/server/app-ssr-stream.js.map +1 -1
- package/dist/server/artifact-compatibility.d.ts +13 -3
- package/dist/server/artifact-compatibility.js +12 -8
- 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 +170 -5
- package/dist/server/cache-proof.js +472 -18
- 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/dev-lockfile.d.ts +110 -0
- package/dist/server/dev-lockfile.js +180 -0
- package/dist/server/dev-lockfile.js.map +1 -0
- package/dist/server/dev-server.d.ts +9 -1
- package/dist/server/dev-server.js +76 -19
- 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/file-based-metadata.d.ts +13 -0
- package/dist/server/file-based-metadata.js +49 -2
- package/dist/server/file-based-metadata.js.map +1 -1
- package/dist/server/headers.d.ts +20 -1
- package/dist/server/headers.js +22 -2
- package/dist/server/headers.js.map +1 -1
- package/dist/server/html.js +1 -1
- package/dist/server/html.js.map +1 -1
- package/dist/server/http-error-responses.d.ts +26 -1
- package/dist/server/http-error-responses.js +32 -2
- package/dist/server/http-error-responses.js.map +1 -1
- package/dist/server/isr-cache.d.ts +8 -3
- package/dist/server/isr-cache.js +24 -6
- package/dist/server/isr-cache.js.map +1 -1
- package/dist/server/metadata-route-response.js +22 -5
- package/dist/server/metadata-route-response.js.map +1 -1
- package/dist/server/metadata-routes.js +27 -8
- package/dist/server/metadata-routes.js.map +1 -1
- package/dist/server/middleware-runtime.d.ts +15 -0
- package/dist/server/middleware-runtime.js +60 -7
- package/dist/server/middleware-runtime.js.map +1 -1
- package/dist/server/middleware.d.ts +13 -1
- package/dist/server/middleware.js +16 -2
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/navigation-planner.d.ts +26 -6
- package/dist/server/navigation-planner.js +358 -24
- package/dist/server/navigation-planner.js.map +1 -1
- package/dist/server/navigation-trace.d.ts +9 -1
- package/dist/server/navigation-trace.js +8 -0
- package/dist/server/navigation-trace.js.map +1 -1
- package/dist/server/normalize-path.d.ts +2 -1
- package/dist/server/normalize-path.js +4 -1
- package/dist/server/normalize-path.js.map +1 -1
- package/dist/server/pages-api-route.d.ts +27 -1
- package/dist/server/pages-api-route.js +25 -3
- package/dist/server/pages-api-route.js.map +1 -1
- package/dist/server/pages-data-route.d.ts +77 -0
- package/dist/server/pages-data-route.js +97 -0
- package/dist/server/pages-data-route.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-page-data.d.ts +32 -4
- package/dist/server/pages-page-data.js +52 -19
- package/dist/server/pages-page-data.js.map +1 -1
- package/dist/server/pages-page-response.d.ts +11 -1
- package/dist/server/pages-page-response.js +6 -4
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/prod-server.d.ts +26 -1
- package/dist/server/prod-server.js +150 -44
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +11 -2
- package/dist/server/request-pipeline.js +28 -11
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/server/seed-cache.d.ts +12 -31
- package/dist/server/seed-cache.js +22 -35
- package/dist/server/seed-cache.js.map +1 -1
- package/dist/server/server-action-not-found.d.ts +16 -3
- package/dist/server/server-action-not-found.js +27 -4
- package/dist/server/server-action-not-found.js.map +1 -1
- package/dist/server/server-globals.d.ts +5 -0
- package/dist/server/server-globals.js +37 -0
- package/dist/server/server-globals.js.map +1 -0
- 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 +7 -6
- package/dist/server/static-file-cache.js.map +1 -1
- package/dist/shims/cache-runtime.d.ts +19 -2
- package/dist/shims/cache-runtime.js +67 -11
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.d.ts +5 -18
- package/dist/shims/cache.js +2 -0
- package/dist/shims/cache.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/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/error-boundary.js +6 -8
- package/dist/shims/error-boundary.js.map +1 -1
- package/dist/shims/error.d.ts +18 -1
- package/dist/shims/error.js +56 -1
- package/dist/shims/error.js.map +1 -1
- package/dist/shims/fetch-cache.d.ts +4 -1
- package/dist/shims/fetch-cache.js +40 -5
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/font-google-base.d.ts +22 -8
- package/dist/shims/font-google-base.js +41 -71
- package/dist/shims/font-google-base.js.map +1 -1
- package/dist/shims/font-local.d.ts +3 -20
- package/dist/shims/font-local.js +23 -75
- package/dist/shims/font-local.js.map +1 -1
- package/dist/shims/font-utils.d.ts +51 -0
- package/dist/shims/font-utils.js +97 -0
- package/dist/shims/font-utils.js.map +1 -0
- package/dist/shims/form.js +13 -6
- package/dist/shims/form.js.map +1 -1
- package/dist/shims/hash-scroll.d.ts +7 -0
- package/dist/shims/hash-scroll.js +30 -0
- package/dist/shims/hash-scroll.js.map +1 -0
- package/dist/shims/headers.d.ts +8 -11
- package/dist/shims/headers.js +22 -2
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/image.d.ts +1 -0
- package/dist/shims/image.js +144 -78
- package/dist/shims/image.js.map +1 -1
- package/dist/shims/internal/app-router-context.d.ts +6 -6
- package/dist/shims/internal/app-router-context.js +17 -6
- package/dist/shims/internal/app-router-context.js.map +1 -1
- package/dist/shims/link-prefetch.d.ts +9 -1
- package/dist/shims/link-prefetch.js +11 -6
- package/dist/shims/link-prefetch.js.map +1 -1
- package/dist/shims/link.d.ts +33 -5
- package/dist/shims/link.js +205 -50
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +16 -30
- package/dist/shims/metadata.js +91 -32
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation.d.ts +164 -17
- package/dist/shims/navigation.js +355 -84
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/navigation.react-server.d.ts +3 -2
- package/dist/shims/navigation.react-server.js +5 -2
- package/dist/shims/navigation.react-server.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/pages-router-runtime.d.ts +7 -0
- package/dist/shims/pages-router-runtime.js +16 -0
- package/dist/shims/pages-router-runtime.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 +40 -7
- package/dist/shims/router.js +355 -250
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/script.js +110 -32
- package/dist/shims/script.js.map +1 -1
- package/dist/shims/server.d.ts +21 -4
- package/dist/shims/server.js +31 -10
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/slot.d.ts +1 -0
- package/dist/shims/slot.js +45 -1
- package/dist/shims/slot.js.map +1 -1
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +2 -0
- package/dist/shims/unified-request-context.js.map +1 -1
- package/dist/shims/unrecognized-action-error.d.ts +35 -0
- package/dist/shims/unrecognized-action-error.js +41 -0
- package/dist/shims/unrecognized-action-error.js.map +1 -0
- 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 +21 -1
- package/dist/shims/url-utils.js +67 -3
- 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 +97 -0
- package/dist/utils/asset-prefix.js +124 -0
- package/dist/utils/asset-prefix.js.map +1 -0
- package/dist/utils/base-path.d.ts +7 -1
- package/dist/utils/base-path.js +10 -1
- package/dist/utils/base-path.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/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/navigation-signal.d.ts +1 -2
- package/dist/utils/navigation-signal.js +1 -1
- package/dist/utils/navigation-signal.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 +17 -1
- package/dist/utils/query.js +36 -1
- 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/dist/utils/sorted-array.d.ts +9 -0
- package/dist/utils/sorted-array.js +22 -0
- package/dist/utils/sorted-array.js.map +1 -0
- package/package.json +13 -5
|
@@ -2,9 +2,11 @@ import { runWithFetchDedupe } from "../shims/fetch-cache.js";
|
|
|
2
2
|
import { createArtifactCompatibilityEnvelope, createArtifactCompatibilityGraphVersion } from "./artifact-compatibility.js";
|
|
3
3
|
import { AppElementsWire, isAppElementsRecord } from "./app-elements-wire.js";
|
|
4
4
|
import "./app-elements.js";
|
|
5
|
+
import { buildAppPageFontLinkHeader, readAppPageBinaryStream, resolveAppPageSpecialError, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
|
|
5
6
|
import { createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery, shouldRerenderAppPageWithGlobalError } from "./app-page-stream.js";
|
|
7
|
+
import { createAppPageHtmlOutputScope, createAppPageRenderObservation, createAppPageRscOutputScope, createEmptyAppPageRenderObservationState } from "./app-page-render-observation.js";
|
|
6
8
|
import { finalizeAppPageHtmlCacheResponse, finalizeAppPageRscCacheResponse } from "./app-page-cache.js";
|
|
7
|
-
import {
|
|
9
|
+
import { hasDigest } from "./app-rsc-errors.js";
|
|
8
10
|
import { probeAppPageBeforeRender } from "./app-page-probe.js";
|
|
9
11
|
import { buildAppPageHtmlResponse, buildAppPageRscResponse, resolveAppPageHtmlResponsePolicy, resolveAppPageRscResponsePolicy } from "./app-page-response.js";
|
|
10
12
|
//#region src/server/app-page-render.ts
|
|
@@ -53,7 +55,15 @@ function createAppPageArtifactCompatibility(element, routePattern) {
|
|
|
53
55
|
* "use cache" may be caught by user try/catch and silently swallowed — this
|
|
54
56
|
* wrapper waits for the stream to drain and surfaces any recorded error to the
|
|
55
57
|
* terminal (and, via HMR, the browser dev overlay).
|
|
56
|
-
*
|
|
58
|
+
*
|
|
59
|
+
* Dedups against React's Flight error chunk: if the recorded error already
|
|
60
|
+
* carries a `digest`, React's serverComponentsErrorHandler has already stamped
|
|
61
|
+
* it and emitted it into the RSC stream. Skipping `console.error` prevents
|
|
62
|
+
* double-logging. Caught cases (no digest) still surface here.
|
|
63
|
+
*
|
|
64
|
+
* Ported from Next.js:
|
|
65
|
+
* https://github.com/vercel/next.js/commit/f5e54c06726b571a042fce67417e40a29f6b8689
|
|
66
|
+
* https://github.com/vercel/next.js/pull/93706
|
|
57
67
|
*/
|
|
58
68
|
function wrapRscResponseForDevErrorReporting(response, consumeInvalidDynamicUsageError) {
|
|
59
69
|
const originalBody = response.body;
|
|
@@ -63,7 +73,8 @@ function wrapRscResponseForDevErrorReporting(response, consumeInvalidDynamicUsag
|
|
|
63
73
|
if (consumed) return;
|
|
64
74
|
consumed = true;
|
|
65
75
|
const error = consumeInvalidDynamicUsageError();
|
|
66
|
-
if (error)
|
|
76
|
+
if (!error) return;
|
|
77
|
+
if (!hasDigest(error)) console.error("[vinext] Invalid dynamic usage:", error);
|
|
67
78
|
};
|
|
68
79
|
const cleanup = new TransformStream({ flush() {
|
|
69
80
|
onConsumed();
|
|
@@ -115,10 +126,36 @@ async function renderAppPageLifecycle(options) {
|
|
|
115
126
|
if (preRenderResult.response) return preRenderResult.response;
|
|
116
127
|
const layoutFlags = preRenderResult.layoutFlags;
|
|
117
128
|
const artifactCompatibility = createAppPageArtifactCompatibility(options.element, options.routePattern);
|
|
129
|
+
const rootBoundaryId = artifactCompatibility?.rootBoundaryId ?? null;
|
|
130
|
+
const renderEpoch = artifactCompatibility?.renderEpoch ?? null;
|
|
131
|
+
const rscOutputScope = createAppPageRscOutputScope({
|
|
132
|
+
element: options.element,
|
|
133
|
+
mountedSlotsHeader: options.mountedSlotsHeader,
|
|
134
|
+
renderEpoch,
|
|
135
|
+
rootBoundaryId,
|
|
136
|
+
routePattern: options.routePattern
|
|
137
|
+
});
|
|
138
|
+
const htmlOutputScope = createAppPageHtmlOutputScope({
|
|
139
|
+
element: options.element,
|
|
140
|
+
renderEpoch,
|
|
141
|
+
rootBoundaryId,
|
|
142
|
+
routePattern: options.routePattern
|
|
143
|
+
});
|
|
144
|
+
const payloadRenderObservation = createAppPageRenderObservation({
|
|
145
|
+
boundaryOutcome: { kind: "unknown" },
|
|
146
|
+
cacheability: "unknown",
|
|
147
|
+
cacheTags: options.getPageTags(),
|
|
148
|
+
cleanPathname: options.cleanPathname,
|
|
149
|
+
completeness: "partial",
|
|
150
|
+
output: rscOutputScope,
|
|
151
|
+
params: options.params,
|
|
152
|
+
state: options.peekRenderObservationState?.() ?? createEmptyAppPageRenderObservationState()
|
|
153
|
+
});
|
|
118
154
|
const outgoingElement = AppElementsWire.encodeOutgoingPayload({
|
|
119
155
|
element: options.element,
|
|
120
156
|
layoutFlags,
|
|
121
|
-
...artifactCompatibility ? { artifactCompatibility } : {}
|
|
157
|
+
...artifactCompatibility ? { artifactCompatibility } : {},
|
|
158
|
+
renderObservation: payloadRenderObservation
|
|
122
159
|
});
|
|
123
160
|
const compileEnd = options.isProduction ? void 0 : performance.now();
|
|
124
161
|
const rscErrorTracker = createAppPageRscErrorTracker(options.createRscOnErrorHandler(options.cleanPathname, options.routePattern));
|
|
@@ -166,6 +203,19 @@ async function renderAppPageLifecycle(options) {
|
|
|
166
203
|
capturedRscDataPromise: options.isProduction && shouldCaptureRscForCacheMetadata ? capturedRscDataRef.value : null,
|
|
167
204
|
cleanPathname: options.cleanPathname,
|
|
168
205
|
consumeDynamicUsage: options.consumeDynamicUsage,
|
|
206
|
+
consumeRenderObservationState: options.consumeRenderObservationState,
|
|
207
|
+
createRscRenderObservation(input) {
|
|
208
|
+
return createAppPageRenderObservation({
|
|
209
|
+
boundaryOutcome: { kind: "success" },
|
|
210
|
+
cacheability: "public",
|
|
211
|
+
cacheTags: input.cacheTags,
|
|
212
|
+
cleanPathname: options.cleanPathname,
|
|
213
|
+
completeness: "complete",
|
|
214
|
+
output: rscOutputScope,
|
|
215
|
+
params: options.params,
|
|
216
|
+
state: input.state
|
|
217
|
+
});
|
|
218
|
+
},
|
|
169
219
|
dynamicUsedDuringBuild,
|
|
170
220
|
getPageTags() {
|
|
171
221
|
return options.getPageTags();
|
|
@@ -206,6 +256,8 @@ async function renderAppPageLifecycle(options) {
|
|
|
206
256
|
capturedRscDataRef,
|
|
207
257
|
fontData,
|
|
208
258
|
navigationContext: options.getNavigationContext(),
|
|
259
|
+
basePath: options.basePath,
|
|
260
|
+
rootParams: options.rootParams,
|
|
209
261
|
formState: options.formState ?? null,
|
|
210
262
|
rscStream: rscForResponse,
|
|
211
263
|
scriptNonce: options.scriptNonce,
|
|
@@ -290,6 +342,31 @@ async function renderAppPageLifecycle(options) {
|
|
|
290
342
|
capturedRscDataPromise: capturedRscDataRef.value,
|
|
291
343
|
cleanPathname: options.cleanPathname,
|
|
292
344
|
consumeDynamicUsage: options.consumeDynamicUsage,
|
|
345
|
+
consumeRenderObservationState: options.consumeRenderObservationState,
|
|
346
|
+
createHtmlRenderObservation(input) {
|
|
347
|
+
return createAppPageRenderObservation({
|
|
348
|
+
boundaryOutcome: { kind: "success" },
|
|
349
|
+
cacheability: "public",
|
|
350
|
+
cacheTags: input.cacheTags,
|
|
351
|
+
cleanPathname: options.cleanPathname,
|
|
352
|
+
completeness: "complete",
|
|
353
|
+
output: htmlOutputScope,
|
|
354
|
+
params: options.params,
|
|
355
|
+
state: input.state
|
|
356
|
+
});
|
|
357
|
+
},
|
|
358
|
+
createRscRenderObservation(input) {
|
|
359
|
+
return createAppPageRenderObservation({
|
|
360
|
+
boundaryOutcome: { kind: "success" },
|
|
361
|
+
cacheability: "public",
|
|
362
|
+
cacheTags: input.cacheTags,
|
|
363
|
+
cleanPathname: options.cleanPathname,
|
|
364
|
+
completeness: "complete",
|
|
365
|
+
output: rscOutputScope,
|
|
366
|
+
params: options.params,
|
|
367
|
+
state: input.state
|
|
368
|
+
});
|
|
369
|
+
},
|
|
293
370
|
getPageTags() {
|
|
294
371
|
return options.getPageTags();
|
|
295
372
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-page-render.js","names":[],"sources":["../../src/server/app-page-render.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { ReactFormState } from \"react-dom/client\";\nimport type { CachedAppPageValue } from \"vinext/shims/cache\";\nimport { runWithFetchDedupe } from \"vinext/shims/fetch-cache\";\nimport { AppElementsWire, isAppElementsRecord, type AppOutgoingElements } from \"./app-elements.js\";\nimport {\n finalizeAppPageHtmlCacheResponse,\n finalizeAppPageRscCacheResponse,\n} from \"./app-page-cache.js\";\nimport {\n buildAppPageFontLinkHeader,\n readAppPageBinaryStream,\n resolveAppPageSpecialError,\n teeAppPageRscStreamForCapture,\n type AppPageFontPreload,\n type AppPageSpecialError,\n type LayoutClassificationOptions,\n} from \"./app-page-execution.js\";\nimport { probeAppPageBeforeRender } from \"./app-page-probe.js\";\nimport {\n buildAppPageHtmlResponse,\n buildAppPageRscResponse,\n resolveAppPageHtmlResponsePolicy,\n resolveAppPageRscResponsePolicy,\n type AppPageMiddlewareContext,\n type AppPageResponseTiming,\n} from \"./app-page-response.js\";\nimport {\n createAppPageFontData,\n createAppPageRscErrorTracker,\n deferUntilStreamConsumed,\n renderAppPageHtmlStream,\n renderAppPageHtmlStreamWithRecovery,\n shouldRerenderAppPageWithGlobalError,\n type AppPageSsrHandler,\n} from \"./app-page-stream.js\";\nimport type { AppRscRenderMode } from \"./app-rsc-render-mode.js\";\nimport {\n createArtifactCompatibilityEnvelope,\n createArtifactCompatibilityGraphVersion,\n type ArtifactCompatibilityEnvelope,\n} from \"./artifact-compatibility.js\";\n\ntype AppPageBoundaryOnError = (\n error: unknown,\n requestInfo: unknown,\n errorContext: unknown,\n) => unknown;\ntype AppPageDebugLogger = (event: string, detail: string) => void;\ntype AppPageCacheSetter = (\n key: string,\n data: CachedAppPageValue,\n revalidateSeconds: number,\n tags: string[],\n expireSeconds?: number,\n) => Promise<void>;\n\ntype AppPageRequestCacheLife = {\n revalidate?: number;\n expire?: number;\n};\n\ntype RenderAppPageLifecycleOptions = {\n cleanPathname: string;\n clearRequestContext: () => void;\n consumeDynamicUsage: () => boolean;\n /** Read and clear any invalid dynamic usage error recorded during render (dev-only). */\n consumeInvalidDynamicUsageError?: () => unknown;\n createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;\n getFontLinks: () => string[];\n getFontPreloads: () => AppPageFontPreload[];\n getFontStyles: () => string[];\n getNavigationContext: () => unknown;\n getPageTags: () => string[];\n getRequestCacheLife: () => AppPageRequestCacheLife | null;\n peekRequestCacheLife?: () => AppPageRequestCacheLife | null;\n getDraftModeCookieHeader: () => string | null | undefined;\n handlerStart: number;\n hasLoadingBoundary: boolean;\n isDynamicError: boolean;\n isDraftMode: boolean;\n isForceDynamic: boolean;\n isForceStatic: boolean;\n isProgressiveActionRender?: boolean;\n isPrerender?: boolean;\n isProduction: boolean;\n isRscRequest: boolean;\n isrDebug?: AppPageDebugLogger;\n isrHtmlKey: (pathname: string) => string;\n isrRscKey: (\n pathname: string,\n mountedSlotsHeader?: string | null,\n renderMode?: AppRscRenderMode,\n ) => string;\n isrSet: AppPageCacheSetter;\n layoutCount: number;\n loadSsrHandler: () => Promise<AppPageSsrHandler>;\n middlewareContext: AppPageMiddlewareContext;\n params: Record<string, unknown>;\n probeLayoutAt: (layoutIndex: number) => unknown;\n probePage: () => unknown;\n expireSeconds?: number;\n formState?: ReactFormState | null;\n revalidateSeconds: number | null;\n renderErrorBoundaryResponse: (error: unknown) => Promise<Response | null>;\n renderLayoutSpecialError: (\n specialError: AppPageSpecialError,\n layoutIndex: number,\n ) => Promise<Response>;\n renderPageSpecialError: (specialError: AppPageSpecialError) => Promise<Response>;\n renderToReadableStream: (\n element: ReactNode | AppOutgoingElements,\n options: { onError: AppPageBoundaryOnError },\n ) => ReadableStream<Uint8Array>;\n routeHasLocalBoundary: boolean;\n routePattern: string;\n runWithSuppressedHookWarning<T>(probe: () => Promise<T>): Promise<T>;\n scriptNonce?: string;\n mountedSlotsHeader?: string | null;\n renderMode?: AppRscRenderMode;\n waitUntil?: (promise: Promise<void>) => void;\n element: ReactNode | Readonly<Record<string, ReactNode>>;\n classification?: LayoutClassificationOptions | null;\n};\n\nfunction buildResponseTiming(\n options: Pick<RenderAppPageLifecycleOptions, \"handlerStart\" | \"isProduction\"> & {\n compileEnd?: number;\n renderEnd?: number;\n responseKind: AppPageResponseTiming[\"responseKind\"];\n },\n): AppPageResponseTiming | undefined {\n if (options.isProduction) {\n return undefined;\n }\n\n return {\n compileEnd: options.compileEnd,\n handlerStart: options.handlerStart,\n renderEnd: options.renderEnd,\n responseKind: options.responseKind,\n };\n}\n\nfunction readRequestCacheLifeForPrerender(\n options: Pick<RenderAppPageLifecycleOptions, \"getRequestCacheLife\" | \"peekRequestCacheLife\">,\n): AppPageRequestCacheLife | null {\n // Prefer the non-destructive reader so prerender.ts can consume metadata\n // after the handler returns. The consume fallback supports older entry glue\n // and is only safe because this path reads at most once per prerender.\n return options.peekRequestCacheLife?.() ?? options.getRequestCacheLife();\n}\n\nfunction applyRequestCacheLife(options: {\n expireSeconds?: number;\n requestCacheLife: AppPageRequestCacheLife | null;\n revalidateSeconds: number | null;\n}): { expireSeconds?: number; revalidateSeconds: number | null } {\n let revalidateSeconds = options.revalidateSeconds;\n let expireSeconds = options.expireSeconds;\n const requestCacheLife = options.requestCacheLife;\n\n if (requestCacheLife?.revalidate !== undefined) {\n revalidateSeconds =\n revalidateSeconds === null\n ? requestCacheLife.revalidate\n : Math.min(revalidateSeconds, requestCacheLife.revalidate);\n }\n if (requestCacheLife?.expire !== undefined) {\n // cacheLife() supplies the effective hard-expire ceiling for this render,\n // so it replaces the config fallback instead of min-merging with it.\n expireSeconds = requestCacheLife.expire;\n }\n\n return { expireSeconds, revalidateSeconds };\n}\n\nfunction readRootBoundaryId(element: Readonly<Record<string, unknown>>): string | null {\n const rootLayoutTreePath = element[AppElementsWire.keys.rootLayout];\n return typeof rootLayoutTreePath === \"string\" ? rootLayoutTreePath : null;\n}\n\nfunction createAppPageArtifactCompatibility(\n element: ReactNode | Readonly<Record<string, ReactNode>>,\n routePattern: string,\n): ArtifactCompatibilityEnvelope | undefined {\n if (!isAppElementsRecord(element)) {\n return undefined;\n }\n\n const rootBoundaryId = readRootBoundaryId(element);\n return createArtifactCompatibilityEnvelope({\n graphVersion: createArtifactCompatibilityGraphVersion({\n routePattern,\n rootBoundaryId,\n }),\n deploymentVersion: process.env.__VINEXT_BUILD_ID ?? null,\n rootBoundaryId,\n });\n}\n\n/**\n * Wraps an RSC response body to report invalid dynamic usage errors after the\n * stream is fully consumed. In dev mode, errors from cookies()/headers() inside\n * \"use cache\" may be caught by user try/catch and silently swallowed — this\n * wrapper waits for the stream to drain and surfaces any recorded error to the\n * terminal (and, via HMR, the browser dev overlay).\n * Ported from Next.js: https://github.com/vercel/next.js/commit/f5e54c06726b571a042fce67417e40a29f6b8689\n */\nfunction wrapRscResponseForDevErrorReporting(\n response: Response,\n consumeInvalidDynamicUsageError: () => unknown,\n): Response {\n const originalBody = response.body;\n if (!originalBody) return response;\n\n let consumed = false;\n const onConsumed = () => {\n if (consumed) return;\n consumed = true;\n const error = consumeInvalidDynamicUsageError();\n if (error) {\n console.error(\"[vinext] Invalid dynamic usage:\", error);\n }\n };\n\n const cleanup = new TransformStream<Uint8Array, Uint8Array>({\n flush() {\n onConsumed();\n },\n });\n\n const piped = originalBody.pipeThrough(cleanup);\n const reader = piped.getReader();\n const wrappedStream = 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 (streamError) => {\n onConsumed();\n controller.error(streamError);\n },\n );\n },\n cancel(reason) {\n onConsumed();\n return reader.cancel(reason);\n },\n });\n\n return new Response(wrappedStream, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n}\n\nexport async function renderAppPageLifecycle(\n options: RenderAppPageLifecycleOptions,\n): Promise<Response> {\n const preRenderResult = await probeAppPageBeforeRender({\n hasLoadingBoundary: options.hasLoadingBoundary,\n layoutCount: options.layoutCount,\n probeLayoutAt(layoutIndex) {\n return options.probeLayoutAt(layoutIndex);\n },\n probePage() {\n return options.probePage();\n },\n renderLayoutSpecialError(specialError, layoutIndex) {\n return options.renderLayoutSpecialError(specialError, layoutIndex);\n },\n renderPageSpecialError(specialError) {\n return options.renderPageSpecialError(specialError);\n },\n resolveSpecialError: resolveAppPageSpecialError,\n runWithSuppressedHookWarning(probe) {\n return options.runWithSuppressedHookWarning(probe);\n },\n classification: options.classification,\n });\n if (preRenderResult.response) {\n return preRenderResult.response;\n }\n\n const layoutFlags = preRenderResult.layoutFlags;\n\n // Render the CANONICAL element. The outgoing payload carries per-layout\n // static/dynamic flags under `__layoutFlags` so the client can later tell\n // which layouts are safe to skip on subsequent navigations.\n const artifactCompatibility = createAppPageArtifactCompatibility(\n options.element,\n options.routePattern,\n );\n const outgoingElement = AppElementsWire.encodeOutgoingPayload({\n element: options.element,\n layoutFlags,\n ...(artifactCompatibility ? { artifactCompatibility } : {}),\n });\n\n const compileEnd = options.isProduction ? undefined : performance.now();\n const baseOnError = options.createRscOnErrorHandler(options.cleanPathname, options.routePattern);\n const rscErrorTracker = createAppPageRscErrorTracker(baseOnError);\n // Defensive wrap for standalone callers. In the normal dispatch path this is\n // a no-op since dispatchAppPage already activated dedupe. Note that\n // renderToReadableStream returns synchronously — the actual fetch calls\n // happen later during async stream consumption — so the dedupe map a\n // standalone call would establish here is only effective if the caller has\n // an outer runWithRequestContext / runWithFetchDedupe scope keeping the ALS\n // store alive across that consumption.\n const rscStream = runWithFetchDedupe(() =>\n options.renderToReadableStream(outgoingElement, {\n onError: rscErrorTracker.onRenderError,\n }),\n );\n\n let revalidateSeconds = options.revalidateSeconds;\n let expireSeconds = options.expireSeconds;\n const shouldCaptureRscForCacheMetadata =\n options.isProgressiveActionRender !== true &&\n (options.isProduction || options.isPrerender === true) &&\n (revalidateSeconds === null || (revalidateSeconds > 0 && revalidateSeconds !== Infinity)) &&\n !options.isDraftMode &&\n !options.isForceDynamic;\n const rscCapture = teeAppPageRscStreamForCapture(rscStream, shouldCaptureRscForCacheMetadata);\n const rscForResponse = rscCapture.ssrStream;\n\n // When the fused tee (#981) is active, the sideStream carries both the embed\n // transform AND the raw RSC byte accumulation. For RSC requests, we consume\n // the sideStream directly. For HTML requests, handleSsr creates an embed\n // transform from it and fills capturedRscDataRef. The ref object is threaded\n // through so .value is read lazily after handleSsr completes.\n const capturedRscDataRef: { value: Promise<ArrayBuffer> | null } = { value: null };\n if (rscCapture.sideStream && options.isRscRequest) {\n capturedRscDataRef.value = readAppPageBinaryStream(rscCapture.sideStream);\n }\n\n if (options.isRscRequest) {\n if (options.isPrerender === true) {\n await settleCapturedRscRenderForCacheMetadata(capturedRscDataRef.value);\n ({ expireSeconds, revalidateSeconds } = applyRequestCacheLife({\n expireSeconds,\n requestCacheLife: readRequestCacheLifeForPrerender(options),\n revalidateSeconds,\n }));\n }\n\n const dynamicUsedDuringBuild = options.consumeDynamicUsage();\n const rscResponsePolicy = resolveAppPageRscResponsePolicy({\n dynamicUsedDuringBuild,\n isDraftMode: options.isDraftMode,\n isDynamicError: options.isDynamicError,\n isForceDynamic: options.isForceDynamic,\n isForceStatic: options.isForceStatic,\n isProduction: options.isProduction,\n expireSeconds,\n revalidateSeconds,\n });\n const rscResponse = buildAppPageRscResponse(rscForResponse, {\n middlewareContext: options.middlewareContext,\n mountedSlotsHeader: options.mountedSlotsHeader,\n params: options.params,\n policy: rscResponsePolicy,\n timing: buildResponseTiming({\n compileEnd,\n handlerStart: options.handlerStart,\n isProduction: options.isProduction,\n responseKind: \"rsc\",\n }),\n });\n\n // In dev mode, wrap the RSC response body to forward invalid dynamic usage\n // errors after the stream is consumed. This mirrors Next.js behavior where\n // workStore.invalidDynamicUsageError is checked after the accumulated chunks\n // promise resolves (app-render.tsx generateDynamicFlightRenderResultWithStagesInDev).\n // Ported from Next.js: https://github.com/vercel/next.js/commit/f5e54c06726b571a042fce67417e40a29f6b8689\n //\n // Note: This only covers RSC responses (client-side navigations). The HTML path\n // (initial page loads) intentionally defers this coverage — the error is still\n // thrown through the RSC pipeline and captured by rscErrorTracker.onRenderError\n // if uncaught by user code. Full parity with Next.js would require checking\n // invalidDynamicUsageError after SSR rendering, which is deferred as out of scope\n // for this PR focused on client-side navigations.\n const devRscResponse =\n !options.isProduction && rscResponse.body && options.consumeInvalidDynamicUsageError\n ? wrapRscResponseForDevErrorReporting(rscResponse, options.consumeInvalidDynamicUsageError)\n : rscResponse;\n\n return finalizeAppPageRscCacheResponse(devRscResponse, {\n capturedRscDataPromise:\n options.isProduction && shouldCaptureRscForCacheMetadata ? capturedRscDataRef.value : null,\n cleanPathname: options.cleanPathname,\n consumeDynamicUsage: options.consumeDynamicUsage,\n dynamicUsedDuringBuild,\n getPageTags() {\n return options.getPageTags();\n },\n getRequestCacheLife() {\n return options.getRequestCacheLife();\n },\n isrDebug: options.isrDebug,\n isrRscKey: options.isrRscKey,\n isrSet: options.isrSet,\n mountedSlotsHeader: options.mountedSlotsHeader,\n renderMode: options.renderMode,\n preserveClientResponseHeaders: rscResponsePolicy.cacheState !== \"MISS\",\n expireSeconds,\n revalidateSeconds,\n waitUntil(promise) {\n options.waitUntil?.(promise);\n },\n });\n }\n\n const fontData = createAppPageFontData({\n getLinks: options.getFontLinks,\n getPreloads: options.getFontPreloads,\n getStyles: options.getFontStyles,\n });\n const fontLinkHeader = buildAppPageFontLinkHeader(fontData.preloads);\n let renderEnd: number | undefined;\n\n const htmlRender = await renderAppPageHtmlStreamWithRecovery({\n onShellRendered() {\n if (!options.isProduction) {\n renderEnd = performance.now();\n }\n },\n renderErrorBoundaryResponse(error) {\n return options.renderErrorBoundaryResponse(error);\n },\n async renderHtmlStream() {\n const ssrHandler = await options.loadSsrHandler();\n return renderAppPageHtmlStream({\n capturedRscDataRef,\n fontData,\n navigationContext: options.getNavigationContext(),\n formState: options.formState ?? null,\n rscStream: rscForResponse,\n scriptNonce: options.scriptNonce,\n sideStream: rscCapture.sideStream,\n ssrHandler,\n waitForAllReady: options.isPrerender,\n });\n },\n renderSpecialErrorResponse(specialError) {\n return options.renderPageSpecialError(specialError);\n },\n resolveSpecialError: resolveAppPageSpecialError,\n });\n if (htmlRender.response) {\n return htmlRender.response;\n }\n const htmlStream = htmlRender.htmlStream;\n if (!htmlStream) {\n throw new Error(\"[vinext] Expected an HTML stream when no fallback response was returned\");\n }\n\n // Routes with a route-level Suspense boundary (loading.tsx) skip the page\n // probe — the page render happens once, inside the RSC stream. Mirror\n // Next.js's `app-render.tsx:4293` catch shape: by the time the SSR shell\n // promise has resolved, any redirect()/notFound() throw whose async work\n // settles in microtasks during shell rendering has already fired through\n // React's onError and been captured by the tracker. Convert that to a\n // 307/404 before any bytes are flushed.\n //\n // Late rejections — ones that settle after macrotask boundaries (real\n // I/O, setTimeout, etc.) — fall through to the streamed body, exactly\n // as Next.js does. The digest survives in the Flight payload for the\n // client router to consume.\n if (options.hasLoadingBoundary) {\n const captured = rscErrorTracker.getCapturedSpecialError();\n if (captured) {\n const specialError = resolveAppPageSpecialError(captured);\n if (specialError) {\n void htmlStream.cancel().catch(() => {});\n return options.renderPageSpecialError(specialError);\n }\n }\n }\n\n if (\n shouldRerenderAppPageWithGlobalError({\n capturedError: rscErrorTracker.getCapturedError(),\n hasLocalBoundary: options.routeHasLocalBoundary,\n })\n ) {\n const cleanResponse = await options.renderErrorBoundaryResponse(\n rscErrorTracker.getCapturedError(),\n );\n if (cleanResponse) {\n return cleanResponse;\n }\n }\n\n // Eagerly read values that must be captured before the stream is consumed.\n if (options.isPrerender === true) {\n await settleCapturedRscRenderForCacheMetadata(capturedRscDataRef.value);\n ({ expireSeconds, revalidateSeconds } = applyRequestCacheLife({\n expireSeconds,\n requestCacheLife: readRequestCacheLifeForPrerender(options),\n revalidateSeconds,\n }));\n }\n const draftCookie = options.getDraftModeCookieHeader();\n const dynamicUsedDuringRender = options.consumeDynamicUsage();\n let dynamicUsedBeforeContextCleanup = dynamicUsedDuringRender;\n\n // Defer clearRequestContext() until the HTML stream is fully consumed by the\n // HTTP layer. The RSC/SSR pipeline is lazy — Server Components execute while\n // the response body is being pulled, not when the stream handle is returned.\n // Clearing the context synchronously here would race those executions, causing\n // headers()/cookies() to see a null context on warm (module-cached) requests.\n // See: https://github.com/cloudflare/vinext/issues/660\n const safeHtmlStream = deferUntilStreamConsumed(htmlStream, () => {\n dynamicUsedBeforeContextCleanup =\n dynamicUsedBeforeContextCleanup || options.consumeDynamicUsage();\n options.clearRequestContext();\n });\n\n const htmlResponsePolicy = resolveAppPageHtmlResponsePolicy({\n dynamicUsedDuringRender,\n isProgressiveActionRender: options.isProgressiveActionRender === true,\n hasScriptNonce: Boolean(options.scriptNonce),\n isDraftMode: options.isDraftMode,\n isDynamicError: options.isDynamicError,\n isForceDynamic: options.isForceDynamic,\n isForceStatic: options.isForceStatic,\n isProduction: options.isProduction,\n expireSeconds,\n revalidateSeconds,\n });\n const htmlResponseTiming = buildResponseTiming({\n compileEnd,\n handlerStart: options.handlerStart,\n isProduction: options.isProduction,\n renderEnd,\n responseKind: \"html\",\n });\n\n const shouldSpeculativelyWriteCache =\n options.isProduction &&\n shouldCaptureRscForCacheMetadata &&\n revalidateSeconds === null &&\n !options.isDynamicError &&\n !options.isForceStatic &&\n !options.scriptNonce &&\n options.isProgressiveActionRender !== true &&\n !dynamicUsedDuringRender;\n\n if (htmlResponsePolicy.shouldWriteToCache || shouldSpeculativelyWriteCache) {\n const isrResponse = buildAppPageHtmlResponse(safeHtmlStream, {\n draftCookie,\n fontLinkHeader,\n middlewareContext: options.middlewareContext,\n policy: htmlResponsePolicy,\n timing: htmlResponseTiming,\n });\n\n if (options.isPrerender === true) {\n return isrResponse;\n }\n\n return finalizeAppPageHtmlCacheResponse(isrResponse, {\n capturedDynamicUsageBeforeContextCleanup() {\n return dynamicUsedBeforeContextCleanup;\n },\n capturedRscDataPromise: capturedRscDataRef.value,\n cleanPathname: options.cleanPathname,\n consumeDynamicUsage: options.consumeDynamicUsage,\n getPageTags() {\n return options.getPageTags();\n },\n getRequestCacheLife() {\n return options.getRequestCacheLife();\n },\n isrDebug: options.isrDebug,\n isrHtmlKey: options.isrHtmlKey,\n isrRscKey: options.isrRscKey,\n isrSet: options.isrSet,\n preserveClientResponseHeaders: !htmlResponsePolicy.shouldWriteToCache,\n expireSeconds,\n revalidateSeconds,\n waitUntil(cachePromise) {\n options.waitUntil?.(cachePromise);\n },\n });\n }\n\n return buildAppPageHtmlResponse(safeHtmlStream, {\n draftCookie,\n fontLinkHeader,\n middlewareContext: options.middlewareContext,\n policy: htmlResponsePolicy,\n timing: htmlResponseTiming,\n });\n}\n\nasync function settleCapturedRscRenderForCacheMetadata(\n capturedRscDataPromise: Promise<ArrayBuffer> | null,\n): Promise<void> {\n if (!capturedRscDataPromise) {\n return;\n }\n\n try {\n await capturedRscDataPromise;\n } catch {\n // The response stream and cache-write path own render error propagation.\n // This pre-read only makes \"use cache\" metadata available before headers\n // and ISR seed metadata are finalized.\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-page-render.js","names":[],"sources":["../../src/server/app-page-render.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { ReactFormState } from \"react-dom/client\";\nimport type { CachedAppPageValue } from \"vinext/shims/cache\";\nimport type { RootParams } from \"vinext/shims/root-params\";\nimport { runWithFetchDedupe } from \"vinext/shims/fetch-cache\";\nimport { AppElementsWire, isAppElementsRecord, type AppOutgoingElements } from \"./app-elements.js\";\nimport { hasDigest } from \"./app-rsc-errors.js\";\nimport {\n finalizeAppPageHtmlCacheResponse,\n finalizeAppPageRscCacheResponse,\n} from \"./app-page-cache.js\";\nimport {\n buildAppPageFontLinkHeader,\n readAppPageBinaryStream,\n resolveAppPageSpecialError,\n teeAppPageRscStreamForCapture,\n type AppPageFontPreload,\n type AppPageSpecialError,\n type LayoutClassificationOptions,\n} from \"./app-page-execution.js\";\nimport { probeAppPageBeforeRender } from \"./app-page-probe.js\";\nimport {\n buildAppPageHtmlResponse,\n buildAppPageRscResponse,\n resolveAppPageHtmlResponsePolicy,\n resolveAppPageRscResponsePolicy,\n type AppPageMiddlewareContext,\n type AppPageResponseTiming,\n} from \"./app-page-response.js\";\nimport {\n createAppPageFontData,\n createAppPageRscErrorTracker,\n deferUntilStreamConsumed,\n renderAppPageHtmlStream,\n renderAppPageHtmlStreamWithRecovery,\n shouldRerenderAppPageWithGlobalError,\n type AppPageSsrHandler,\n} from \"./app-page-stream.js\";\nimport type { AppRscRenderMode } from \"./app-rsc-render-mode.js\";\nimport {\n createArtifactCompatibilityEnvelope,\n createArtifactCompatibilityGraphVersion,\n type ArtifactCompatibilityEnvelope,\n} from \"./artifact-compatibility.js\";\nimport {\n createAppPageHtmlOutputScope,\n createAppPageRenderObservation,\n createAppPageRscOutputScope,\n createEmptyAppPageRenderObservationState,\n type AppPageRenderObservationState,\n} from \"./app-page-render-observation.js\";\n\ntype AppPageBoundaryOnError = (\n error: unknown,\n requestInfo: unknown,\n errorContext: unknown,\n) => unknown;\ntype AppPageDebugLogger = (event: string, detail: string) => void;\ntype AppPageCacheSetter = (\n key: string,\n data: CachedAppPageValue,\n revalidateSeconds: number,\n tags: string[],\n expireSeconds?: number,\n) => Promise<void>;\n\ntype AppPageRequestCacheLife = {\n revalidate?: number;\n expire?: number;\n};\n\ntype RenderAppPageLifecycleOptions = {\n basePath?: string;\n cleanPathname: string;\n clearRequestContext: () => void;\n consumeDynamicUsage: () => boolean;\n consumeRenderObservationState?: () => AppPageRenderObservationState;\n /** Read and clear any invalid dynamic usage error recorded during render (dev-only). */\n consumeInvalidDynamicUsageError?: () => unknown;\n createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;\n getFontLinks: () => string[];\n getFontPreloads: () => AppPageFontPreload[];\n getFontStyles: () => string[];\n getNavigationContext: () => unknown;\n getPageTags: () => string[];\n getRequestCacheLife: () => AppPageRequestCacheLife | null;\n peekRequestCacheLife?: () => AppPageRequestCacheLife | null;\n getDraftModeCookieHeader: () => string | null | undefined;\n handlerStart: number;\n hasLoadingBoundary: boolean;\n isDynamicError: boolean;\n isDraftMode: boolean;\n isForceDynamic: boolean;\n isForceStatic: boolean;\n isProgressiveActionRender?: boolean;\n isPrerender?: boolean;\n isProduction: boolean;\n isRscRequest: boolean;\n isrDebug?: AppPageDebugLogger;\n isrHtmlKey: (pathname: string) => string;\n isrRscKey: (\n pathname: string,\n mountedSlotsHeader?: string | null,\n renderMode?: AppRscRenderMode,\n ) => string;\n isrSet: AppPageCacheSetter;\n layoutCount: number;\n loadSsrHandler: () => Promise<AppPageSsrHandler>;\n middlewareContext: AppPageMiddlewareContext;\n params: Record<string, unknown>;\n rootParams?: RootParams;\n peekRenderObservationState?: () => AppPageRenderObservationState;\n probeLayoutAt: (layoutIndex: number) => unknown;\n probePage: () => unknown;\n expireSeconds?: number;\n formState?: ReactFormState | null;\n revalidateSeconds: number | null;\n renderErrorBoundaryResponse: (error: unknown) => Promise<Response | null>;\n renderLayoutSpecialError: (\n specialError: AppPageSpecialError,\n layoutIndex: number,\n ) => Promise<Response>;\n renderPageSpecialError: (specialError: AppPageSpecialError) => Promise<Response>;\n renderToReadableStream: (\n element: ReactNode | AppOutgoingElements,\n options: { onError: AppPageBoundaryOnError },\n ) => ReadableStream<Uint8Array>;\n routeHasLocalBoundary: boolean;\n routePattern: string;\n runWithSuppressedHookWarning<T>(probe: () => Promise<T>): Promise<T>;\n scriptNonce?: string;\n mountedSlotsHeader?: string | null;\n renderMode?: AppRscRenderMode;\n waitUntil?: (promise: Promise<void>) => void;\n element: ReactNode | Readonly<Record<string, ReactNode>>;\n classification?: LayoutClassificationOptions | null;\n};\n\nfunction buildResponseTiming(\n options: Pick<RenderAppPageLifecycleOptions, \"handlerStart\" | \"isProduction\"> & {\n compileEnd?: number;\n renderEnd?: number;\n responseKind: AppPageResponseTiming[\"responseKind\"];\n },\n): AppPageResponseTiming | undefined {\n if (options.isProduction) {\n return undefined;\n }\n\n return {\n compileEnd: options.compileEnd,\n handlerStart: options.handlerStart,\n renderEnd: options.renderEnd,\n responseKind: options.responseKind,\n };\n}\n\nfunction readRequestCacheLifeForPrerender(\n options: Pick<RenderAppPageLifecycleOptions, \"getRequestCacheLife\" | \"peekRequestCacheLife\">,\n): AppPageRequestCacheLife | null {\n // Prefer the non-destructive reader so prerender.ts can consume metadata\n // after the handler returns. The consume fallback supports older entry glue\n // and is only safe because this path reads at most once per prerender.\n return options.peekRequestCacheLife?.() ?? options.getRequestCacheLife();\n}\n\nfunction applyRequestCacheLife(options: {\n expireSeconds?: number;\n requestCacheLife: AppPageRequestCacheLife | null;\n revalidateSeconds: number | null;\n}): { expireSeconds?: number; revalidateSeconds: number | null } {\n let revalidateSeconds = options.revalidateSeconds;\n let expireSeconds = options.expireSeconds;\n const requestCacheLife = options.requestCacheLife;\n\n if (requestCacheLife?.revalidate !== undefined) {\n revalidateSeconds =\n revalidateSeconds === null\n ? requestCacheLife.revalidate\n : Math.min(revalidateSeconds, requestCacheLife.revalidate);\n }\n if (requestCacheLife?.expire !== undefined) {\n // cacheLife() supplies the effective hard-expire ceiling for this render,\n // so it replaces the config fallback instead of min-merging with it.\n expireSeconds = requestCacheLife.expire;\n }\n\n return { expireSeconds, revalidateSeconds };\n}\n\nfunction readRootBoundaryId(element: Readonly<Record<string, unknown>>): string | null {\n const rootLayoutTreePath = element[AppElementsWire.keys.rootLayout];\n return typeof rootLayoutTreePath === \"string\" ? rootLayoutTreePath : null;\n}\n\nfunction createAppPageArtifactCompatibility(\n element: ReactNode | Readonly<Record<string, ReactNode>>,\n routePattern: string,\n): ArtifactCompatibilityEnvelope | undefined {\n if (!isAppElementsRecord(element)) {\n return undefined;\n }\n\n const rootBoundaryId = readRootBoundaryId(element);\n return createArtifactCompatibilityEnvelope({\n graphVersion: createArtifactCompatibilityGraphVersion({\n routePattern,\n rootBoundaryId,\n }),\n deploymentVersion: process.env.__VINEXT_BUILD_ID ?? null,\n rootBoundaryId,\n });\n}\n\n/**\n * Wraps an RSC response body to report invalid dynamic usage errors after the\n * stream is fully consumed. In dev mode, errors from cookies()/headers() inside\n * \"use cache\" may be caught by user try/catch and silently swallowed — this\n * wrapper waits for the stream to drain and surfaces any recorded error to the\n * terminal (and, via HMR, the browser dev overlay).\n *\n * Dedups against React's Flight error chunk: if the recorded error already\n * carries a `digest`, React's serverComponentsErrorHandler has already stamped\n * it and emitted it into the RSC stream. Skipping `console.error` prevents\n * double-logging. Caught cases (no digest) still surface here.\n *\n * Ported from Next.js:\n * https://github.com/vercel/next.js/commit/f5e54c06726b571a042fce67417e40a29f6b8689\n * https://github.com/vercel/next.js/pull/93706\n */\nfunction wrapRscResponseForDevErrorReporting(\n response: Response,\n consumeInvalidDynamicUsageError: () => unknown,\n): Response {\n const originalBody = response.body;\n if (!originalBody) return response;\n\n let consumed = false;\n const onConsumed = () => {\n if (consumed) return;\n consumed = true;\n const error = consumeInvalidDynamicUsageError();\n if (!error) return;\n // Dedup: React already emitted this error as a Flight error chunk.\n if (!hasDigest(error)) {\n console.error(\"[vinext] Invalid dynamic usage:\", error);\n }\n };\n\n const cleanup = new TransformStream<Uint8Array, Uint8Array>({\n flush() {\n onConsumed();\n },\n });\n\n const piped = originalBody.pipeThrough(cleanup);\n const reader = piped.getReader();\n const wrappedStream = 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 (streamError) => {\n onConsumed();\n controller.error(streamError);\n },\n );\n },\n cancel(reason) {\n onConsumed();\n return reader.cancel(reason);\n },\n });\n\n return new Response(wrappedStream, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n}\n\nexport async function renderAppPageLifecycle(\n options: RenderAppPageLifecycleOptions,\n): Promise<Response> {\n const preRenderResult = await probeAppPageBeforeRender({\n hasLoadingBoundary: options.hasLoadingBoundary,\n layoutCount: options.layoutCount,\n probeLayoutAt(layoutIndex) {\n return options.probeLayoutAt(layoutIndex);\n },\n probePage() {\n return options.probePage();\n },\n renderLayoutSpecialError(specialError, layoutIndex) {\n return options.renderLayoutSpecialError(specialError, layoutIndex);\n },\n renderPageSpecialError(specialError) {\n return options.renderPageSpecialError(specialError);\n },\n resolveSpecialError: resolveAppPageSpecialError,\n runWithSuppressedHookWarning(probe) {\n return options.runWithSuppressedHookWarning(probe);\n },\n classification: options.classification,\n });\n if (preRenderResult.response) {\n return preRenderResult.response;\n }\n\n const layoutFlags = preRenderResult.layoutFlags;\n\n // Render the CANONICAL element. The outgoing payload carries per-layout\n // static/dynamic flags under `__layoutFlags` so the client can later tell\n // which layouts are safe to skip on subsequent navigations.\n const artifactCompatibility = createAppPageArtifactCompatibility(\n options.element,\n options.routePattern,\n );\n const rootBoundaryId = artifactCompatibility?.rootBoundaryId ?? null;\n const renderEpoch = artifactCompatibility?.renderEpoch ?? null;\n const rscOutputScope = createAppPageRscOutputScope({\n element: options.element,\n mountedSlotsHeader: options.mountedSlotsHeader,\n renderEpoch,\n rootBoundaryId,\n routePattern: options.routePattern,\n });\n const htmlOutputScope = createAppPageHtmlOutputScope({\n element: options.element,\n renderEpoch,\n rootBoundaryId,\n routePattern: options.routePattern,\n });\n // Partial payload metadata is a pre-stream snapshot. Fetch tags may still\n // accumulate while the RSC/HTML streams are consumed; complete cache artifact\n // observations below rebuild this field after the stream drains.\n const payloadRenderObservation = createAppPageRenderObservation({\n boundaryOutcome: { kind: \"unknown\" },\n cacheability: \"unknown\",\n cacheTags: options.getPageTags(),\n cleanPathname: options.cleanPathname,\n completeness: \"partial\",\n output: rscOutputScope,\n params: options.params,\n state: options.peekRenderObservationState?.() ?? createEmptyAppPageRenderObservationState(),\n });\n const outgoingElement = AppElementsWire.encodeOutgoingPayload({\n element: options.element,\n layoutFlags,\n ...(artifactCompatibility ? { artifactCompatibility } : {}),\n renderObservation: payloadRenderObservation,\n });\n\n const compileEnd = options.isProduction ? undefined : performance.now();\n const baseOnError = options.createRscOnErrorHandler(options.cleanPathname, options.routePattern);\n const rscErrorTracker = createAppPageRscErrorTracker(baseOnError);\n // Defensive wrap for standalone callers. In the normal dispatch path this is\n // a no-op since dispatchAppPage already activated dedupe. Note that\n // renderToReadableStream returns synchronously — the actual fetch calls\n // happen later during async stream consumption — so the dedupe map a\n // standalone call would establish here is only effective if the caller has\n // an outer runWithRequestContext / runWithFetchDedupe scope keeping the ALS\n // store alive across that consumption.\n const rscStream = runWithFetchDedupe(() =>\n options.renderToReadableStream(outgoingElement, {\n onError: rscErrorTracker.onRenderError,\n }),\n );\n\n let revalidateSeconds = options.revalidateSeconds;\n let expireSeconds = options.expireSeconds;\n const shouldCaptureRscForCacheMetadata =\n options.isProgressiveActionRender !== true &&\n (options.isProduction || options.isPrerender === true) &&\n (revalidateSeconds === null || (revalidateSeconds > 0 && revalidateSeconds !== Infinity)) &&\n !options.isDraftMode &&\n !options.isForceDynamic;\n const rscCapture = teeAppPageRscStreamForCapture(rscStream, shouldCaptureRscForCacheMetadata);\n const rscForResponse = rscCapture.ssrStream;\n\n // When the fused tee (#981) is active, the sideStream carries both the embed\n // transform AND the raw RSC byte accumulation. For RSC requests, we consume\n // the sideStream directly. For HTML requests, handleSsr creates an embed\n // transform from it and fills capturedRscDataRef. The ref object is threaded\n // through so .value is read lazily after handleSsr completes.\n const capturedRscDataRef: { value: Promise<ArrayBuffer> | null } = { value: null };\n if (rscCapture.sideStream && options.isRscRequest) {\n capturedRscDataRef.value = readAppPageBinaryStream(rscCapture.sideStream);\n }\n\n if (options.isRscRequest) {\n if (options.isPrerender === true) {\n await settleCapturedRscRenderForCacheMetadata(capturedRscDataRef.value);\n ({ expireSeconds, revalidateSeconds } = applyRequestCacheLife({\n expireSeconds,\n requestCacheLife: readRequestCacheLifeForPrerender(options),\n revalidateSeconds,\n }));\n }\n\n const dynamicUsedDuringBuild = options.consumeDynamicUsage();\n const rscResponsePolicy = resolveAppPageRscResponsePolicy({\n dynamicUsedDuringBuild,\n isDraftMode: options.isDraftMode,\n isDynamicError: options.isDynamicError,\n isForceDynamic: options.isForceDynamic,\n isForceStatic: options.isForceStatic,\n isProduction: options.isProduction,\n expireSeconds,\n revalidateSeconds,\n });\n const rscResponse = buildAppPageRscResponse(rscForResponse, {\n middlewareContext: options.middlewareContext,\n mountedSlotsHeader: options.mountedSlotsHeader,\n params: options.params,\n policy: rscResponsePolicy,\n timing: buildResponseTiming({\n compileEnd,\n handlerStart: options.handlerStart,\n isProduction: options.isProduction,\n responseKind: \"rsc\",\n }),\n });\n\n // In dev mode, wrap the RSC response body to forward invalid dynamic usage\n // errors after the stream is consumed. This mirrors Next.js behavior where\n // workStore.invalidDynamicUsageError is checked after the accumulated chunks\n // promise resolves (app-render.tsx generateDynamicFlightRenderResultWithStagesInDev).\n // Ported from Next.js: https://github.com/vercel/next.js/commit/f5e54c06726b571a042fce67417e40a29f6b8689\n //\n // Note: This only covers RSC responses (client-side navigations). The HTML path\n // (initial page loads) intentionally defers this coverage — the error is still\n // thrown through the RSC pipeline and captured by rscErrorTracker.onRenderError\n // if uncaught by user code. Full parity with Next.js would require checking\n // invalidDynamicUsageError after SSR rendering, which is deferred as out of scope\n // for this PR focused on client-side navigations.\n const devRscResponse =\n !options.isProduction && rscResponse.body && options.consumeInvalidDynamicUsageError\n ? wrapRscResponseForDevErrorReporting(rscResponse, options.consumeInvalidDynamicUsageError)\n : rscResponse;\n\n return finalizeAppPageRscCacheResponse(devRscResponse, {\n capturedRscDataPromise:\n options.isProduction && shouldCaptureRscForCacheMetadata ? capturedRscDataRef.value : null,\n cleanPathname: options.cleanPathname,\n consumeDynamicUsage: options.consumeDynamicUsage,\n consumeRenderObservationState: options.consumeRenderObservationState,\n createRscRenderObservation(input) {\n return createAppPageRenderObservation({\n boundaryOutcome: { kind: \"success\" },\n cacheability: \"public\",\n cacheTags: input.cacheTags,\n cleanPathname: options.cleanPathname,\n completeness: \"complete\",\n output: rscOutputScope,\n params: options.params,\n state: input.state,\n });\n },\n dynamicUsedDuringBuild,\n getPageTags() {\n return options.getPageTags();\n },\n getRequestCacheLife() {\n return options.getRequestCacheLife();\n },\n isrDebug: options.isrDebug,\n isrRscKey: options.isrRscKey,\n isrSet: options.isrSet,\n mountedSlotsHeader: options.mountedSlotsHeader,\n renderMode: options.renderMode,\n preserveClientResponseHeaders: rscResponsePolicy.cacheState !== \"MISS\",\n expireSeconds,\n revalidateSeconds,\n waitUntil(promise) {\n options.waitUntil?.(promise);\n },\n });\n }\n\n const fontData = createAppPageFontData({\n getLinks: options.getFontLinks,\n getPreloads: options.getFontPreloads,\n getStyles: options.getFontStyles,\n });\n const fontLinkHeader = buildAppPageFontLinkHeader(fontData.preloads);\n let renderEnd: number | undefined;\n\n const htmlRender = await renderAppPageHtmlStreamWithRecovery({\n onShellRendered() {\n if (!options.isProduction) {\n renderEnd = performance.now();\n }\n },\n renderErrorBoundaryResponse(error) {\n return options.renderErrorBoundaryResponse(error);\n },\n async renderHtmlStream() {\n const ssrHandler = await options.loadSsrHandler();\n return renderAppPageHtmlStream({\n capturedRscDataRef,\n fontData,\n navigationContext: options.getNavigationContext(),\n basePath: options.basePath,\n rootParams: options.rootParams,\n formState: options.formState ?? null,\n rscStream: rscForResponse,\n scriptNonce: options.scriptNonce,\n sideStream: rscCapture.sideStream,\n ssrHandler,\n waitForAllReady: options.isPrerender,\n });\n },\n renderSpecialErrorResponse(specialError) {\n return options.renderPageSpecialError(specialError);\n },\n resolveSpecialError: resolveAppPageSpecialError,\n });\n if (htmlRender.response) {\n return htmlRender.response;\n }\n const htmlStream = htmlRender.htmlStream;\n if (!htmlStream) {\n throw new Error(\"[vinext] Expected an HTML stream when no fallback response was returned\");\n }\n\n // Routes with a route-level Suspense boundary (loading.tsx) skip the page\n // probe — the page render happens once, inside the RSC stream. Mirror\n // Next.js's `app-render.tsx:4293` catch shape: by the time the SSR shell\n // promise has resolved, any redirect()/notFound() throw whose async work\n // settles in microtasks during shell rendering has already fired through\n // React's onError and been captured by the tracker. Convert that to a\n // 307/404 before any bytes are flushed.\n //\n // Late rejections — ones that settle after macrotask boundaries (real\n // I/O, setTimeout, etc.) — fall through to the streamed body, exactly\n // as Next.js does. The digest survives in the Flight payload for the\n // client router to consume.\n if (options.hasLoadingBoundary) {\n const captured = rscErrorTracker.getCapturedSpecialError();\n if (captured) {\n const specialError = resolveAppPageSpecialError(captured);\n if (specialError) {\n void htmlStream.cancel().catch(() => {});\n return options.renderPageSpecialError(specialError);\n }\n }\n }\n\n if (\n shouldRerenderAppPageWithGlobalError({\n capturedError: rscErrorTracker.getCapturedError(),\n hasLocalBoundary: options.routeHasLocalBoundary,\n })\n ) {\n const cleanResponse = await options.renderErrorBoundaryResponse(\n rscErrorTracker.getCapturedError(),\n );\n if (cleanResponse) {\n return cleanResponse;\n }\n }\n\n // Eagerly read values that must be captured before the stream is consumed.\n if (options.isPrerender === true) {\n await settleCapturedRscRenderForCacheMetadata(capturedRscDataRef.value);\n ({ expireSeconds, revalidateSeconds } = applyRequestCacheLife({\n expireSeconds,\n requestCacheLife: readRequestCacheLifeForPrerender(options),\n revalidateSeconds,\n }));\n }\n const draftCookie = options.getDraftModeCookieHeader();\n const dynamicUsedDuringRender = options.consumeDynamicUsage();\n let dynamicUsedBeforeContextCleanup = dynamicUsedDuringRender;\n\n // Defer clearRequestContext() until the HTML stream is fully consumed by the\n // HTTP layer. The RSC/SSR pipeline is lazy — Server Components execute while\n // the response body is being pulled, not when the stream handle is returned.\n // Clearing the context synchronously here would race those executions, causing\n // headers()/cookies() to see a null context on warm (module-cached) requests.\n // See: https://github.com/cloudflare/vinext/issues/660\n const safeHtmlStream = deferUntilStreamConsumed(htmlStream, () => {\n dynamicUsedBeforeContextCleanup =\n dynamicUsedBeforeContextCleanup || options.consumeDynamicUsage();\n options.clearRequestContext();\n });\n\n const htmlResponsePolicy = resolveAppPageHtmlResponsePolicy({\n dynamicUsedDuringRender,\n isProgressiveActionRender: options.isProgressiveActionRender === true,\n hasScriptNonce: Boolean(options.scriptNonce),\n isDraftMode: options.isDraftMode,\n isDynamicError: options.isDynamicError,\n isForceDynamic: options.isForceDynamic,\n isForceStatic: options.isForceStatic,\n isProduction: options.isProduction,\n expireSeconds,\n revalidateSeconds,\n });\n const htmlResponseTiming = buildResponseTiming({\n compileEnd,\n handlerStart: options.handlerStart,\n isProduction: options.isProduction,\n renderEnd,\n responseKind: \"html\",\n });\n\n const shouldSpeculativelyWriteCache =\n options.isProduction &&\n shouldCaptureRscForCacheMetadata &&\n revalidateSeconds === null &&\n !options.isDynamicError &&\n !options.isForceStatic &&\n !options.scriptNonce &&\n options.isProgressiveActionRender !== true &&\n !dynamicUsedDuringRender;\n\n if (htmlResponsePolicy.shouldWriteToCache || shouldSpeculativelyWriteCache) {\n const isrResponse = buildAppPageHtmlResponse(safeHtmlStream, {\n draftCookie,\n fontLinkHeader,\n middlewareContext: options.middlewareContext,\n policy: htmlResponsePolicy,\n timing: htmlResponseTiming,\n });\n\n if (options.isPrerender === true) {\n return isrResponse;\n }\n\n return finalizeAppPageHtmlCacheResponse(isrResponse, {\n capturedDynamicUsageBeforeContextCleanup() {\n return dynamicUsedBeforeContextCleanup;\n },\n capturedRscDataPromise: capturedRscDataRef.value,\n cleanPathname: options.cleanPathname,\n consumeDynamicUsage: options.consumeDynamicUsage,\n consumeRenderObservationState: options.consumeRenderObservationState,\n createHtmlRenderObservation(input) {\n return createAppPageRenderObservation({\n boundaryOutcome: { kind: \"success\" },\n cacheability: \"public\",\n cacheTags: input.cacheTags,\n cleanPathname: options.cleanPathname,\n completeness: \"complete\",\n output: htmlOutputScope,\n params: options.params,\n state: input.state,\n });\n },\n createRscRenderObservation(input) {\n return createAppPageRenderObservation({\n boundaryOutcome: { kind: \"success\" },\n cacheability: \"public\",\n cacheTags: input.cacheTags,\n cleanPathname: options.cleanPathname,\n completeness: \"complete\",\n output: rscOutputScope,\n params: options.params,\n state: input.state,\n });\n },\n getPageTags() {\n return options.getPageTags();\n },\n getRequestCacheLife() {\n return options.getRequestCacheLife();\n },\n isrDebug: options.isrDebug,\n isrHtmlKey: options.isrHtmlKey,\n isrRscKey: options.isrRscKey,\n isrSet: options.isrSet,\n preserveClientResponseHeaders: !htmlResponsePolicy.shouldWriteToCache,\n expireSeconds,\n revalidateSeconds,\n waitUntil(cachePromise) {\n options.waitUntil?.(cachePromise);\n },\n });\n }\n\n return buildAppPageHtmlResponse(safeHtmlStream, {\n draftCookie,\n fontLinkHeader,\n middlewareContext: options.middlewareContext,\n policy: htmlResponsePolicy,\n timing: htmlResponseTiming,\n });\n}\n\nasync function settleCapturedRscRenderForCacheMetadata(\n capturedRscDataPromise: Promise<ArrayBuffer> | null,\n): Promise<void> {\n if (!capturedRscDataPromise) {\n return;\n }\n\n try {\n await capturedRscDataPromise;\n } catch {\n // The response stream and cache-write path own render error propagation.\n // This pre-read only makes \"use cache\" metadata available before headers\n // and ISR seed metadata are finalized.\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-page-request.js","names":[],"sources":["../../src/server/app-page-request.ts"],"sourcesContent":["import type { AppPageSpecialError } from \"./app-page-execution.js\";\nimport { runWithFetchDedupe } from \"vinext/shims/fetch-cache\";\nimport { getAppPageSegmentParamName } from \"./app-page-params.js\";\nimport { notFoundResponse } from \"./http-error-responses.js\";\n\ntype AppPageParams = Record<string, string | string[]>;\ntype GenerateStaticParams = (args: { params: AppPageParams }) => unknown;\n\ntype GenerateStaticParamsModule = {\n generateStaticParams?: GenerateStaticParams | null;\n};\n\ntype GenerateStaticParamsSource = {\n generateStaticParams: GenerateStaticParams;\n parentParamNames: readonly string[];\n};\n\nexport type ValidateAppPageDynamicParamsOptions = {\n clearRequestContext: () => void;\n enforceStaticParamsOnly: boolean;\n generateStaticParams?:\n | GenerateStaticParams\n | GenerateStaticParamsSource\n | readonly (GenerateStaticParams | GenerateStaticParamsSource | null | undefined)[]\n | null;\n isDynamicRoute: boolean;\n params: AppPageParams;\n};\n\ntype ResolveAppPageGenerateStaticParamsSourcesOptions = {\n layouts?: readonly (GenerateStaticParamsModule | null | undefined)[];\n layoutTreePositions?: readonly number[];\n page?: GenerateStaticParamsModule | null;\n routeSegments: readonly string[];\n};\n\ntype BuildAppPageElementOptions<TElement> = {\n buildPageElement: () => Promise<TElement>;\n renderErrorBoundaryPage: (error: unknown) => Promise<Response | null>;\n renderSpecialError: (specialError: AppPageSpecialError) => Promise<Response>;\n resolveSpecialError: (error: unknown) => AppPageSpecialError | null;\n};\n\ntype BuildAppPageElementResult<TElement> = {\n element: TElement | null;\n response: Response | null;\n};\n\ntype AppPageInterceptMatch<TPage = unknown> = {\n matchedParams: AppPageParams;\n page: TPage;\n slotKey: string;\n sourceRouteIndex: number;\n};\n\ntype ResolveAppPageInterceptMatchOptions<TRoute, TPage, TInterceptOpts> = {\n cleanPathname: string;\n currentRoute: TRoute;\n findIntercept: (pathname: string) => AppPageInterceptMatch<TPage> | null;\n getRouteParamNames: (route: TRoute) => readonly string[];\n getSourceRoute: (sourceRouteIndex: number) => TRoute | undefined;\n isRscRequest: boolean;\n toInterceptOpts: (intercept: AppPageInterceptMatch<TPage>) => TInterceptOpts;\n};\n\ntype ResolveAppPageInterceptMatchResult<TRoute, TInterceptOpts> = {\n interceptOpts: TInterceptOpts;\n matchedParams: AppPageParams;\n sourceParams: AppPageParams;\n sourceRoute: TRoute;\n};\n\ntype AppPageInterceptState<TRoute, TPage> =\n | { kind: \"none\" }\n | { kind: \"current-route\"; intercept: AppPageInterceptMatch<TPage> }\n | { kind: \"source-route\"; intercept: AppPageInterceptMatch<TPage>; sourceRoute: TRoute };\n\ntype ResolveAppPageActionRerenderTargetOptions<TRoute, TPage, TInterceptOpts> = {\n cleanPathname: string;\n currentParams: AppPageParams;\n currentRoute: TRoute;\n findIntercept: (pathname: string) => AppPageInterceptMatch<TPage> | null;\n getRouteParamNames: (route: TRoute) => readonly string[];\n getSourceRoute: (sourceRouteIndex: number) => TRoute | undefined;\n isRscRequest: boolean;\n toInterceptOpts: (intercept: AppPageInterceptMatch<TPage>) => TInterceptOpts;\n};\n\ntype ResolveAppPageActionRerenderTargetResult<TRoute, TInterceptOpts> = {\n interceptOpts: TInterceptOpts | undefined;\n navigationParams: AppPageParams;\n params: AppPageParams;\n route: TRoute;\n};\n\ntype ResolveAppPageInterceptOptions<TRoute, TPage, TInterceptOpts, TElement> = {\n buildPageElement: (\n route: TRoute,\n params: AppPageParams,\n interceptOpts: TInterceptOpts | undefined,\n searchParams: URLSearchParams,\n ) => Promise<TElement>;\n cleanPathname: string;\n currentRoute: TRoute;\n findIntercept: (pathname: string) => AppPageInterceptMatch<TPage> | null;\n getRouteParamNames: (route: TRoute) => readonly string[];\n getSourceRoute: (sourceRouteIndex: number) => TRoute | undefined;\n isRscRequest: boolean;\n renderInterceptResponse: (route: TRoute, element: TElement) => Promise<Response> | Response;\n searchParams: URLSearchParams;\n setNavigationContext: (context: {\n params: AppPageParams;\n pathname: string;\n searchParams: URLSearchParams;\n }) => void;\n toInterceptOpts: (intercept: AppPageInterceptMatch<TPage>) => TInterceptOpts;\n};\n\ntype ResolveAppPageInterceptResult<TInterceptOpts> = {\n interceptOpts: TInterceptOpts | undefined;\n response: Response | null;\n};\n\nfunction pickRouteParams(\n matchedParams: AppPageParams,\n routeParamNames: readonly string[],\n): AppPageParams {\n const params: AppPageParams = {};\n\n for (const paramName of routeParamNames) {\n const value = matchedParams[paramName];\n if (value !== undefined) {\n params[paramName] = value;\n }\n }\n\n return params;\n}\n\nfunction collectParentParamNames(\n routeSegments: readonly string[],\n boundaryPosition: number,\n): string[] {\n const limit = Math.max(0, Math.min(boundaryPosition, routeSegments.length));\n const names: string[] = [];\n\n for (const segment of routeSegments.slice(0, limit)) {\n const name = getAppPageSegmentParamName(segment);\n if (name && !names.includes(name)) {\n names.push(name);\n }\n }\n\n return names;\n}\n\nfunction getLayoutGenerateStaticParamsBoundary(layoutTreePosition: number | undefined): number {\n // A layout at app/[id]/layout.tsx has tree position 1, but its\n // generateStaticParams belongs to the [id] segment and receives only parent\n // params from segments before [id].\n return (layoutTreePosition ?? 0) - 1;\n}\n\nexport function resolveAppPageGenerateStaticParamsSources(\n options: ResolveAppPageGenerateStaticParamsSourcesOptions,\n): GenerateStaticParamsSource[] {\n const sources: GenerateStaticParamsSource[] = [];\n\n options.layouts?.forEach((layout, index) => {\n if (typeof layout?.generateStaticParams !== \"function\") return;\n\n sources.push({\n generateStaticParams: layout.generateStaticParams,\n parentParamNames: collectParentParamNames(\n options.routeSegments,\n getLayoutGenerateStaticParamsBoundary(options.layoutTreePositions?.[index]),\n ),\n });\n });\n\n if (typeof options.page?.generateStaticParams === \"function\") {\n sources.push({\n generateStaticParams: options.page.generateStaticParams,\n parentParamNames: collectParentParamNames(\n options.routeSegments,\n Math.max(0, options.routeSegments.length - 1),\n ),\n });\n }\n\n return sources;\n}\n\nfunction areStaticParamsAllowed(\n params: AppPageParams,\n staticParams: readonly Record<string, unknown>[],\n): boolean {\n const paramKeys = Object.keys(params);\n\n return staticParams.some((staticParamSet) =>\n paramKeys.every((key) => {\n const value = params[key];\n const staticValue = staticParamSet[key];\n\n // Parent params may not appear in the leaf route's returned set because\n // Next.js passes them top-down through nested generateStaticParams calls.\n if (staticValue === undefined) {\n return true;\n }\n\n if (Array.isArray(value)) {\n return JSON.stringify(value) === JSON.stringify(staticValue);\n }\n\n if (\n typeof staticValue === \"string\" ||\n typeof staticValue === \"number\" ||\n typeof staticValue === \"boolean\"\n ) {\n return String(value) === String(staticValue);\n }\n\n return JSON.stringify(value) === JSON.stringify(staticValue);\n }),\n );\n}\n\nfunction normalizeGenerateStaticParams(\n generateStaticParams: ValidateAppPageDynamicParamsOptions[\"generateStaticParams\"],\n): GenerateStaticParamsSource[] {\n const sources = Array.isArray(generateStaticParams)\n ? generateStaticParams\n : [generateStaticParams];\n\n return sources.flatMap((source) => {\n if (typeof source === \"function\") {\n return [{ generateStaticParams: source, parentParamNames: [] }];\n }\n\n if (typeof source?.generateStaticParams === \"function\") {\n return [source];\n }\n\n return [];\n });\n}\n\nexport async function validateAppPageDynamicParams(\n options: ValidateAppPageDynamicParamsOptions,\n): Promise<Response | null> {\n if (!options.enforceStaticParamsOnly || !options.isDynamicRoute) {\n return null;\n }\n\n const generateStaticParamsSources = normalizeGenerateStaticParams(options.generateStaticParams);\n if (generateStaticParamsSources.length === 0) {\n options.clearRequestContext();\n return notFoundResponse();\n }\n\n for (const source of generateStaticParamsSources) {\n const staticParams = await runWithFetchDedupe(() =>\n source.generateStaticParams({\n params: pickRouteParams(options.params, source.parentParamNames),\n }),\n );\n if (Array.isArray(staticParams) && !areStaticParamsAllowed(options.params, staticParams)) {\n options.clearRequestContext();\n return notFoundResponse();\n }\n }\n\n return null;\n}\n\n/**\n * Pure: decides whether the incoming request should re-render an intercepted\n * source-route tree, and if so returns the source route, the source-route's\n * param slice, the full matched param set (the URL params the client sees),\n * and an opaque `interceptOpts` bag for the caller's render pipeline.\n *\n * Returns `null` in three decision-fallthrough cases:\n * - non-RSC requests (server rendering the direct page for a full HTML load)\n * - no intercepting route matches the path\n * - the match's source route IS the current route (the same branch today\n * returns `interceptOpts` for the direct render)\n *\n * Shared by both the GET path (resolveAppPageIntercept, which layers on\n * `setNavigationContext` + element build + Response wrap) and the server-action\n * POST path (entries/app-rsc-entry.ts), which runs its own response pipeline.\n */\nexport function resolveAppPageInterceptMatch<TRoute, TPage, TInterceptOpts>(\n options: ResolveAppPageInterceptMatchOptions<TRoute, TPage, TInterceptOpts>,\n): ResolveAppPageInterceptMatchResult<TRoute, TInterceptOpts> | null {\n const interceptState = resolveAppPageInterceptState(options);\n if (interceptState.kind !== \"source-route\") {\n return null;\n }\n\n return {\n interceptOpts: options.toInterceptOpts(interceptState.intercept),\n matchedParams: interceptState.intercept.matchedParams,\n sourceParams: pickRouteParams(\n interceptState.intercept.matchedParams,\n options.getRouteParamNames(interceptState.sourceRoute),\n ),\n sourceRoute: interceptState.sourceRoute,\n };\n}\n\nfunction resolveAppPageInterceptState<TRoute, TPage, TInterceptOpts>(\n options: ResolveAppPageInterceptMatchOptions<TRoute, TPage, TInterceptOpts>,\n): AppPageInterceptState<TRoute, TPage> {\n if (!options.isRscRequest) {\n return { kind: \"none\" };\n }\n\n const intercept = options.findIntercept(options.cleanPathname);\n if (!intercept) {\n return { kind: \"none\" };\n }\n\n const sourceRoute = options.getSourceRoute(intercept.sourceRouteIndex);\n if (!sourceRoute) {\n return { kind: \"none\" };\n }\n\n if (sourceRoute === options.currentRoute) {\n return { kind: \"current-route\", intercept };\n }\n\n return { kind: \"source-route\", intercept, sourceRoute };\n}\n\nexport function resolveAppPageActionRerenderTarget<TRoute, TPage, TInterceptOpts>(\n options: ResolveAppPageActionRerenderTargetOptions<TRoute, TPage, TInterceptOpts>,\n): ResolveAppPageActionRerenderTargetResult<TRoute, TInterceptOpts> {\n const interceptState = resolveAppPageInterceptState({\n cleanPathname: options.cleanPathname,\n currentRoute: options.currentRoute,\n findIntercept: options.findIntercept,\n getRouteParamNames: options.getRouteParamNames,\n getSourceRoute: options.getSourceRoute,\n isRscRequest: options.isRscRequest,\n toInterceptOpts: options.toInterceptOpts,\n });\n\n if (interceptState.kind === \"source-route\") {\n return {\n interceptOpts: options.toInterceptOpts(interceptState.intercept),\n navigationParams: interceptState.intercept.matchedParams,\n params: pickRouteParams(\n interceptState.intercept.matchedParams,\n options.getRouteParamNames(interceptState.sourceRoute),\n ),\n route: interceptState.sourceRoute,\n };\n }\n\n return {\n interceptOpts:\n interceptState.kind === \"current-route\"\n ? options.toInterceptOpts(interceptState.intercept)\n : undefined,\n navigationParams: options.currentParams,\n params: options.currentParams,\n route: options.currentRoute,\n };\n}\n\nexport async function resolveAppPageIntercept<TRoute, TPage, TInterceptOpts, TElement>(\n options: ResolveAppPageInterceptOptions<TRoute, TPage, TInterceptOpts, TElement>,\n): Promise<ResolveAppPageInterceptResult<TInterceptOpts>> {\n const interceptState = resolveAppPageInterceptState({\n cleanPathname: options.cleanPathname,\n currentRoute: options.currentRoute,\n findIntercept: options.findIntercept,\n getRouteParamNames: options.getRouteParamNames,\n getSourceRoute: options.getSourceRoute,\n isRscRequest: options.isRscRequest,\n toInterceptOpts: options.toInterceptOpts,\n });\n\n if (interceptState.kind === \"source-route\") {\n options.setNavigationContext({\n params: interceptState.intercept.matchedParams,\n pathname: options.cleanPathname,\n searchParams: options.searchParams,\n });\n const interceptElement = await options.buildPageElement(\n interceptState.sourceRoute,\n pickRouteParams(\n interceptState.intercept.matchedParams,\n options.getRouteParamNames(interceptState.sourceRoute),\n ),\n options.toInterceptOpts(interceptState.intercept),\n options.searchParams,\n );\n\n return {\n interceptOpts: undefined,\n response: await options.renderInterceptResponse(interceptState.sourceRoute, interceptElement),\n };\n }\n\n // Reproduce the current-route-is-source branch where we still need the opts\n // bag even though we did not render a separate intercepted response.\n return {\n interceptOpts:\n interceptState.kind === \"current-route\"\n ? options.toInterceptOpts(interceptState.intercept)\n : undefined,\n response: null,\n };\n}\n\nexport async function buildAppPageElement<TElement>(\n options: BuildAppPageElementOptions<TElement>,\n): Promise<BuildAppPageElementResult<TElement>> {\n try {\n return {\n element: await options.buildPageElement(),\n response: null,\n };\n } catch (error) {\n const specialError = options.resolveSpecialError(error);\n if (specialError) {\n return {\n element: null,\n response: await options.renderSpecialError(specialError),\n };\n }\n\n const errorBoundaryResponse = await options.renderErrorBoundaryPage(error);\n if (errorBoundaryResponse) {\n return {\n element: null,\n response: errorBoundaryResponse,\n };\n }\n\n throw error;\n }\n}\n"],"mappings":";;;;AA2HA,SAAS,gBACP,eACA,iBACe;CACf,MAAM,SAAwB,EAAE;CAEhC,KAAK,MAAM,aAAa,iBAAiB;EACvC,MAAM,QAAQ,cAAc;EAC5B,IAAI,UAAU,KAAA,GACZ,OAAO,aAAa;;CAIxB,OAAO;;AAGT,SAAS,wBACP,eACA,kBACU;CACV,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,kBAAkB,cAAc,OAAO,CAAC;CAC3E,MAAM,QAAkB,EAAE;CAE1B,KAAK,MAAM,WAAW,cAAc,MAAM,GAAG,MAAM,EAAE;EACnD,MAAM,OAAO,2BAA2B,QAAQ;EAChD,IAAI,QAAQ,CAAC,MAAM,SAAS,KAAK,EAC/B,MAAM,KAAK,KAAK;;CAIpB,OAAO;;AAGT,SAAS,sCAAsC,oBAAgD;CAI7F,QAAQ,sBAAsB,KAAK;;AAGrC,SAAgB,0CACd,SAC8B;CAC9B,MAAM,UAAwC,EAAE;CAEhD,QAAQ,SAAS,SAAS,QAAQ,UAAU;EAC1C,IAAI,OAAO,QAAQ,yBAAyB,YAAY;EAExD,QAAQ,KAAK;GACX,sBAAsB,OAAO;GAC7B,kBAAkB,wBAChB,QAAQ,eACR,sCAAsC,QAAQ,sBAAsB,OAAO,CAC5E;GACF,CAAC;GACF;CAEF,IAAI,OAAO,QAAQ,MAAM,yBAAyB,YAChD,QAAQ,KAAK;EACX,sBAAsB,QAAQ,KAAK;EACnC,kBAAkB,wBAChB,QAAQ,eACR,KAAK,IAAI,GAAG,QAAQ,cAAc,SAAS,EAAE,CAC9C;EACF,CAAC;CAGJ,OAAO;;AAGT,SAAS,uBACP,QACA,cACS;CACT,MAAM,YAAY,OAAO,KAAK,OAAO;CAErC,OAAO,aAAa,MAAM,mBACxB,UAAU,OAAO,QAAQ;EACvB,MAAM,QAAQ,OAAO;EACrB,MAAM,cAAc,eAAe;EAInC,IAAI,gBAAgB,KAAA,GAClB,OAAO;EAGT,IAAI,MAAM,QAAQ,MAAM,EACtB,OAAO,KAAK,UAAU,MAAM,KAAK,KAAK,UAAU,YAAY;EAG9D,IACE,OAAO,gBAAgB,YACvB,OAAO,gBAAgB,YACvB,OAAO,gBAAgB,WAEvB,OAAO,OAAO,MAAM,KAAK,OAAO,YAAY;EAG9C,OAAO,KAAK,UAAU,MAAM,KAAK,KAAK,UAAU,YAAY;GAC5D,CACH;;AAGH,SAAS,8BACP,sBAC8B;CAK9B,QAJgB,MAAM,QAAQ,qBAAqB,GAC/C,uBACA,CAAC,qBAAqB,EAEX,SAAS,WAAW;EACjC,IAAI,OAAO,WAAW,YACpB,OAAO,CAAC;GAAE,sBAAsB;GAAQ,kBAAkB,EAAE;GAAE,CAAC;EAGjE,IAAI,OAAO,QAAQ,yBAAyB,YAC1C,OAAO,CAAC,OAAO;EAGjB,OAAO,EAAE;GACT;;AAGJ,eAAsB,6BACpB,SAC0B;CAC1B,IAAI,CAAC,QAAQ,2BAA2B,CAAC,QAAQ,gBAC/C,OAAO;CAGT,MAAM,8BAA8B,8BAA8B,QAAQ,qBAAqB;CAC/F,IAAI,4BAA4B,WAAW,GAAG;EAC5C,QAAQ,qBAAqB;EAC7B,OAAO,kBAAkB;;CAG3B,KAAK,MAAM,UAAU,6BAA6B;EAChD,MAAM,eAAe,MAAM,yBACzB,OAAO,qBAAqB,EAC1B,QAAQ,gBAAgB,QAAQ,QAAQ,OAAO,iBAAiB,EACjE,CAAC,CACH;EACD,IAAI,MAAM,QAAQ,aAAa,IAAI,CAAC,uBAAuB,QAAQ,QAAQ,aAAa,EAAE;GACxF,QAAQ,qBAAqB;GAC7B,OAAO,kBAAkB;;;CAI7B,OAAO;;;;;;;;;;;;;;;;;;AAmBT,SAAgB,6BACd,SACmE;CACnE,MAAM,iBAAiB,6BAA6B,QAAQ;CAC5D,IAAI,eAAe,SAAS,gBAC1B,OAAO;CAGT,OAAO;EACL,eAAe,QAAQ,gBAAgB,eAAe,UAAU;EAChE,eAAe,eAAe,UAAU;EACxC,cAAc,gBACZ,eAAe,UAAU,eACzB,QAAQ,mBAAmB,eAAe,YAAY,CACvD;EACD,aAAa,eAAe;EAC7B;;AAGH,SAAS,6BACP,SACsC;CACtC,IAAI,CAAC,QAAQ,cACX,OAAO,EAAE,MAAM,QAAQ;CAGzB,MAAM,YAAY,QAAQ,cAAc,QAAQ,cAAc;CAC9D,IAAI,CAAC,WACH,OAAO,EAAE,MAAM,QAAQ;CAGzB,MAAM,cAAc,QAAQ,eAAe,UAAU,iBAAiB;CACtE,IAAI,CAAC,aACH,OAAO,EAAE,MAAM,QAAQ;CAGzB,IAAI,gBAAgB,QAAQ,cAC1B,OAAO;EAAE,MAAM;EAAiB;EAAW;CAG7C,OAAO;EAAE,MAAM;EAAgB;EAAW;EAAa;;AAGzD,SAAgB,mCACd,SACkE;CAClE,MAAM,iBAAiB,6BAA6B;EAClD,eAAe,QAAQ;EACvB,cAAc,QAAQ;EACtB,eAAe,QAAQ;EACvB,oBAAoB,QAAQ;EAC5B,gBAAgB,QAAQ;EACxB,cAAc,QAAQ;EACtB,iBAAiB,QAAQ;EAC1B,CAAC;CAEF,IAAI,eAAe,SAAS,gBAC1B,OAAO;EACL,eAAe,QAAQ,gBAAgB,eAAe,UAAU;EAChE,kBAAkB,eAAe,UAAU;EAC3C,QAAQ,gBACN,eAAe,UAAU,eACzB,QAAQ,mBAAmB,eAAe,YAAY,CACvD;EACD,OAAO,eAAe;EACvB;CAGH,OAAO;EACL,eACE,eAAe,SAAS,kBACpB,QAAQ,gBAAgB,eAAe,UAAU,GACjD,KAAA;EACN,kBAAkB,QAAQ;EAC1B,QAAQ,QAAQ;EAChB,OAAO,QAAQ;EAChB;;AAGH,eAAsB,wBACpB,SACwD;CACxD,MAAM,iBAAiB,6BAA6B;EAClD,eAAe,QAAQ;EACvB,cAAc,QAAQ;EACtB,eAAe,QAAQ;EACvB,oBAAoB,QAAQ;EAC5B,gBAAgB,QAAQ;EACxB,cAAc,QAAQ;EACtB,iBAAiB,QAAQ;EAC1B,CAAC;CAEF,IAAI,eAAe,SAAS,gBAAgB;EAC1C,QAAQ,qBAAqB;GAC3B,QAAQ,eAAe,UAAU;GACjC,UAAU,QAAQ;GAClB,cAAc,QAAQ;GACvB,CAAC;EACF,MAAM,mBAAmB,MAAM,QAAQ,iBACrC,eAAe,aACf,gBACE,eAAe,UAAU,eACzB,QAAQ,mBAAmB,eAAe,YAAY,CACvD,EACD,QAAQ,gBAAgB,eAAe,UAAU,EACjD,QAAQ,aACT;EAED,OAAO;GACL,eAAe,KAAA;GACf,UAAU,MAAM,QAAQ,wBAAwB,eAAe,aAAa,iBAAiB;GAC9F;;CAKH,OAAO;EACL,eACE,eAAe,SAAS,kBACpB,QAAQ,gBAAgB,eAAe,UAAU,GACjD,KAAA;EACN,UAAU;EACX;;AAGH,eAAsB,oBACpB,SAC8C;CAC9C,IAAI;EACF,OAAO;GACL,SAAS,MAAM,QAAQ,kBAAkB;GACzC,UAAU;GACX;UACM,OAAO;EACd,MAAM,eAAe,QAAQ,oBAAoB,MAAM;EACvD,IAAI,cACF,OAAO;GACL,SAAS;GACT,UAAU,MAAM,QAAQ,mBAAmB,aAAa;GACzD;EAGH,MAAM,wBAAwB,MAAM,QAAQ,wBAAwB,MAAM;EAC1E,IAAI,uBACF,OAAO;GACL,SAAS;GACT,UAAU;GACX;EAGH,MAAM"}
|
|
1
|
+
{"version":3,"file":"app-page-request.js","names":[],"sources":["../../src/server/app-page-request.ts"],"sourcesContent":["import type { AppPageSpecialError } from \"./app-page-execution.js\";\nimport { runWithFetchDedupe } from \"vinext/shims/fetch-cache\";\nimport { getAppPageSegmentParamName } from \"./app-page-params.js\";\nimport { notFoundResponse } from \"./http-error-responses.js\";\n\ntype AppPageParams = Record<string, string | string[]>;\ntype GenerateStaticParams = (args: { params: AppPageParams }) => unknown;\n\ntype GenerateStaticParamsModule = {\n generateStaticParams?: GenerateStaticParams | null;\n};\n\ntype GenerateStaticParamsSource = {\n generateStaticParams: GenerateStaticParams;\n parentParamNames: readonly string[];\n};\n\nexport type ValidateAppPageDynamicParamsOptions = {\n clearRequestContext: () => void;\n enforceStaticParamsOnly: boolean;\n generateStaticParams?:\n | GenerateStaticParams\n | GenerateStaticParamsSource\n | readonly (GenerateStaticParams | GenerateStaticParamsSource | null | undefined)[]\n | null;\n isDynamicRoute: boolean;\n params: AppPageParams;\n};\n\ntype ResolveAppPageGenerateStaticParamsSourcesOptions = {\n layouts?: readonly (GenerateStaticParamsModule | null | undefined)[];\n layoutTreePositions?: readonly number[];\n page?: GenerateStaticParamsModule | null;\n routeSegments: readonly string[];\n};\n\ntype BuildAppPageElementOptions<TElement> = {\n buildPageElement: () => Promise<TElement>;\n renderErrorBoundaryPage: (error: unknown) => Promise<Response | null>;\n renderSpecialError: (specialError: AppPageSpecialError) => Promise<Response>;\n resolveSpecialError: (error: unknown) => AppPageSpecialError | null;\n};\n\ntype BuildAppPageElementResult<TElement> = {\n element: TElement | null;\n response: Response | null;\n};\n\ntype AppPageInterceptMatch<TPage = unknown> = {\n matchedParams: AppPageParams;\n page: TPage;\n slotId?: string | null;\n slotKey: string;\n sourceRouteIndex: number;\n};\n\ntype ResolveAppPageInterceptMatchOptions<TRoute, TPage, TInterceptOpts> = {\n cleanPathname: string;\n currentRoute: TRoute;\n findIntercept: (pathname: string) => AppPageInterceptMatch<TPage> | null;\n getRouteParamNames: (route: TRoute) => readonly string[];\n getSourceRoute: (sourceRouteIndex: number) => TRoute | undefined;\n isRscRequest: boolean;\n toInterceptOpts: (intercept: AppPageInterceptMatch<TPage>) => TInterceptOpts;\n};\n\ntype ResolveAppPageInterceptMatchResult<TRoute, TInterceptOpts> = {\n interceptOpts: TInterceptOpts;\n matchedParams: AppPageParams;\n sourceParams: AppPageParams;\n sourceRoute: TRoute;\n};\n\ntype AppPageInterceptState<TRoute, TPage> =\n | { kind: \"none\" }\n | { kind: \"current-route\"; intercept: AppPageInterceptMatch<TPage> }\n | { kind: \"source-route\"; intercept: AppPageInterceptMatch<TPage>; sourceRoute: TRoute };\n\ntype ResolveAppPageActionRerenderTargetOptions<TRoute, TPage, TInterceptOpts> = {\n cleanPathname: string;\n currentParams: AppPageParams;\n currentRoute: TRoute;\n findIntercept: (pathname: string) => AppPageInterceptMatch<TPage> | null;\n getRouteParamNames: (route: TRoute) => readonly string[];\n getSourceRoute: (sourceRouteIndex: number) => TRoute | undefined;\n isRscRequest: boolean;\n toInterceptOpts: (intercept: AppPageInterceptMatch<TPage>) => TInterceptOpts;\n};\n\ntype ResolveAppPageActionRerenderTargetResult<TRoute, TInterceptOpts> = {\n interceptOpts: TInterceptOpts | undefined;\n navigationParams: AppPageParams;\n params: AppPageParams;\n route: TRoute;\n};\n\ntype ResolveAppPageInterceptOptions<TRoute, TPage, TInterceptOpts, TElement> = {\n buildPageElement: (\n route: TRoute,\n params: AppPageParams,\n interceptOpts: TInterceptOpts | undefined,\n searchParams: URLSearchParams,\n ) => Promise<TElement>;\n cleanPathname: string;\n currentRoute: TRoute;\n findIntercept: (pathname: string) => AppPageInterceptMatch<TPage> | null;\n getRouteParamNames: (route: TRoute) => readonly string[];\n getSourceRoute: (sourceRouteIndex: number) => TRoute | undefined;\n isRscRequest: boolean;\n renderInterceptResponse: (route: TRoute, element: TElement) => Promise<Response> | Response;\n searchParams: URLSearchParams;\n setNavigationContext: (context: {\n params: AppPageParams;\n pathname: string;\n searchParams: URLSearchParams;\n }) => void;\n toInterceptOpts: (intercept: AppPageInterceptMatch<TPage>) => TInterceptOpts;\n};\n\ntype ResolveAppPageInterceptResult<TInterceptOpts> = {\n interceptOpts: TInterceptOpts | undefined;\n response: Response | null;\n};\n\nfunction pickRouteParams(\n matchedParams: AppPageParams,\n routeParamNames: readonly string[],\n): AppPageParams {\n const params: AppPageParams = {};\n\n for (const paramName of routeParamNames) {\n const value = matchedParams[paramName];\n if (value !== undefined) {\n params[paramName] = value;\n }\n }\n\n return params;\n}\n\nfunction collectParentParamNames(\n routeSegments: readonly string[],\n boundaryPosition: number,\n): string[] {\n const limit = Math.max(0, Math.min(boundaryPosition, routeSegments.length));\n const names: string[] = [];\n\n for (const segment of routeSegments.slice(0, limit)) {\n const name = getAppPageSegmentParamName(segment);\n if (name && !names.includes(name)) {\n names.push(name);\n }\n }\n\n return names;\n}\n\nfunction getLayoutGenerateStaticParamsBoundary(layoutTreePosition: number | undefined): number {\n // A layout at app/[id]/layout.tsx has tree position 1, but its\n // generateStaticParams belongs to the [id] segment and receives only parent\n // params from segments before [id].\n return (layoutTreePosition ?? 0) - 1;\n}\n\nexport function resolveAppPageGenerateStaticParamsSources(\n options: ResolveAppPageGenerateStaticParamsSourcesOptions,\n): GenerateStaticParamsSource[] {\n const sources: GenerateStaticParamsSource[] = [];\n\n options.layouts?.forEach((layout, index) => {\n if (typeof layout?.generateStaticParams !== \"function\") return;\n\n sources.push({\n generateStaticParams: layout.generateStaticParams,\n parentParamNames: collectParentParamNames(\n options.routeSegments,\n getLayoutGenerateStaticParamsBoundary(options.layoutTreePositions?.[index]),\n ),\n });\n });\n\n if (typeof options.page?.generateStaticParams === \"function\") {\n sources.push({\n generateStaticParams: options.page.generateStaticParams,\n parentParamNames: collectParentParamNames(\n options.routeSegments,\n Math.max(0, options.routeSegments.length - 1),\n ),\n });\n }\n\n return sources;\n}\n\nfunction areStaticParamsAllowed(\n params: AppPageParams,\n staticParams: readonly Record<string, unknown>[],\n): boolean {\n const paramKeys = Object.keys(params);\n\n return staticParams.some((staticParamSet) =>\n paramKeys.every((key) => {\n const value = params[key];\n const staticValue = staticParamSet[key];\n\n // Parent params may not appear in the leaf route's returned set because\n // Next.js passes them top-down through nested generateStaticParams calls.\n if (staticValue === undefined) {\n return true;\n }\n\n if (Array.isArray(value)) {\n return JSON.stringify(value) === JSON.stringify(staticValue);\n }\n\n if (\n typeof staticValue === \"string\" ||\n typeof staticValue === \"number\" ||\n typeof staticValue === \"boolean\"\n ) {\n return String(value) === String(staticValue);\n }\n\n return JSON.stringify(value) === JSON.stringify(staticValue);\n }),\n );\n}\n\nfunction normalizeGenerateStaticParams(\n generateStaticParams: ValidateAppPageDynamicParamsOptions[\"generateStaticParams\"],\n): GenerateStaticParamsSource[] {\n const sources = Array.isArray(generateStaticParams)\n ? generateStaticParams\n : [generateStaticParams];\n\n return sources.flatMap((source) => {\n if (typeof source === \"function\") {\n return [{ generateStaticParams: source, parentParamNames: [] }];\n }\n\n if (typeof source?.generateStaticParams === \"function\") {\n return [source];\n }\n\n return [];\n });\n}\n\nexport async function validateAppPageDynamicParams(\n options: ValidateAppPageDynamicParamsOptions,\n): Promise<Response | null> {\n if (!options.enforceStaticParamsOnly || !options.isDynamicRoute) {\n return null;\n }\n\n const generateStaticParamsSources = normalizeGenerateStaticParams(options.generateStaticParams);\n if (generateStaticParamsSources.length === 0) {\n options.clearRequestContext();\n return notFoundResponse();\n }\n\n for (const source of generateStaticParamsSources) {\n const staticParams = await runWithFetchDedupe(() =>\n source.generateStaticParams({\n params: pickRouteParams(options.params, source.parentParamNames),\n }),\n );\n if (Array.isArray(staticParams) && !areStaticParamsAllowed(options.params, staticParams)) {\n options.clearRequestContext();\n return notFoundResponse();\n }\n }\n\n return null;\n}\n\n/**\n * Pure: decides whether the incoming request should re-render an intercepted\n * source-route tree, and if so returns the source route, the source-route's\n * param slice, the full matched param set (the URL params the client sees),\n * and an opaque `interceptOpts` bag for the caller's render pipeline.\n *\n * Returns `null` in three decision-fallthrough cases:\n * - non-RSC requests (server rendering the direct page for a full HTML load)\n * - no intercepting route matches the path\n * - the match's source route IS the current route (the same branch today\n * returns `interceptOpts` for the direct render)\n *\n * Shared by both the GET path (resolveAppPageIntercept, which layers on\n * `setNavigationContext` + element build + Response wrap) and the server-action\n * POST path (entries/app-rsc-entry.ts), which runs its own response pipeline.\n */\nexport function resolveAppPageInterceptMatch<TRoute, TPage, TInterceptOpts>(\n options: ResolveAppPageInterceptMatchOptions<TRoute, TPage, TInterceptOpts>,\n): ResolveAppPageInterceptMatchResult<TRoute, TInterceptOpts> | null {\n const interceptState = resolveAppPageInterceptState(options);\n if (interceptState.kind !== \"source-route\") {\n return null;\n }\n\n return {\n interceptOpts: options.toInterceptOpts(interceptState.intercept),\n matchedParams: interceptState.intercept.matchedParams,\n sourceParams: pickRouteParams(\n interceptState.intercept.matchedParams,\n options.getRouteParamNames(interceptState.sourceRoute),\n ),\n sourceRoute: interceptState.sourceRoute,\n };\n}\n\nfunction resolveAppPageInterceptState<TRoute, TPage, TInterceptOpts>(\n options: ResolveAppPageInterceptMatchOptions<TRoute, TPage, TInterceptOpts>,\n): AppPageInterceptState<TRoute, TPage> {\n if (!options.isRscRequest) {\n return { kind: \"none\" };\n }\n\n const intercept = options.findIntercept(options.cleanPathname);\n if (!intercept) {\n return { kind: \"none\" };\n }\n\n const sourceRoute = options.getSourceRoute(intercept.sourceRouteIndex);\n if (!sourceRoute) {\n return { kind: \"none\" };\n }\n\n if (sourceRoute === options.currentRoute) {\n return { kind: \"current-route\", intercept };\n }\n\n return { kind: \"source-route\", intercept, sourceRoute };\n}\n\nexport function resolveAppPageActionRerenderTarget<TRoute, TPage, TInterceptOpts>(\n options: ResolveAppPageActionRerenderTargetOptions<TRoute, TPage, TInterceptOpts>,\n): ResolveAppPageActionRerenderTargetResult<TRoute, TInterceptOpts> {\n const interceptState = resolveAppPageInterceptState({\n cleanPathname: options.cleanPathname,\n currentRoute: options.currentRoute,\n findIntercept: options.findIntercept,\n getRouteParamNames: options.getRouteParamNames,\n getSourceRoute: options.getSourceRoute,\n isRscRequest: options.isRscRequest,\n toInterceptOpts: options.toInterceptOpts,\n });\n\n if (interceptState.kind === \"source-route\") {\n return {\n interceptOpts: options.toInterceptOpts(interceptState.intercept),\n navigationParams: interceptState.intercept.matchedParams,\n params: pickRouteParams(\n interceptState.intercept.matchedParams,\n options.getRouteParamNames(interceptState.sourceRoute),\n ),\n route: interceptState.sourceRoute,\n };\n }\n\n return {\n interceptOpts:\n interceptState.kind === \"current-route\"\n ? options.toInterceptOpts(interceptState.intercept)\n : undefined,\n navigationParams: options.currentParams,\n params: options.currentParams,\n route: options.currentRoute,\n };\n}\n\nexport async function resolveAppPageIntercept<TRoute, TPage, TInterceptOpts, TElement>(\n options: ResolveAppPageInterceptOptions<TRoute, TPage, TInterceptOpts, TElement>,\n): Promise<ResolveAppPageInterceptResult<TInterceptOpts>> {\n const interceptState = resolveAppPageInterceptState({\n cleanPathname: options.cleanPathname,\n currentRoute: options.currentRoute,\n findIntercept: options.findIntercept,\n getRouteParamNames: options.getRouteParamNames,\n getSourceRoute: options.getSourceRoute,\n isRscRequest: options.isRscRequest,\n toInterceptOpts: options.toInterceptOpts,\n });\n\n if (interceptState.kind === \"source-route\") {\n options.setNavigationContext({\n params: interceptState.intercept.matchedParams,\n pathname: options.cleanPathname,\n searchParams: options.searchParams,\n });\n const interceptElement = await options.buildPageElement(\n interceptState.sourceRoute,\n pickRouteParams(\n interceptState.intercept.matchedParams,\n options.getRouteParamNames(interceptState.sourceRoute),\n ),\n options.toInterceptOpts(interceptState.intercept),\n options.searchParams,\n );\n\n return {\n interceptOpts: undefined,\n response: await options.renderInterceptResponse(interceptState.sourceRoute, interceptElement),\n };\n }\n\n // Reproduce the current-route-is-source branch where we still need the opts\n // bag even though we did not render a separate intercepted response.\n return {\n interceptOpts:\n interceptState.kind === \"current-route\"\n ? options.toInterceptOpts(interceptState.intercept)\n : undefined,\n response: null,\n };\n}\n\nexport async function buildAppPageElement<TElement>(\n options: BuildAppPageElementOptions<TElement>,\n): Promise<BuildAppPageElementResult<TElement>> {\n try {\n return {\n element: await options.buildPageElement(),\n response: null,\n };\n } catch (error) {\n const specialError = options.resolveSpecialError(error);\n if (specialError) {\n return {\n element: null,\n response: await options.renderSpecialError(specialError),\n };\n }\n\n const errorBoundaryResponse = await options.renderErrorBoundaryPage(error);\n if (errorBoundaryResponse) {\n return {\n element: null,\n response: errorBoundaryResponse,\n };\n }\n\n throw error;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_PARAMS_HEADER, VINEXT_TIMING_HEADER } from "./headers.js";
|
|
2
|
+
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
3
|
+
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
3
4
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
4
5
|
import { NO_STORE_CACHE_CONTROL, STATIC_CACHE_CONTROL, buildRevalidateCacheControl } from "./cache-control.js";
|
|
5
6
|
//#region src/server/app-page-response.ts
|
|
@@ -68,14 +69,15 @@ function resolveAppPageHtmlResponsePolicy(options) {
|
|
|
68
69
|
}
|
|
69
70
|
function buildAppPageRscResponse(body, options) {
|
|
70
71
|
const headers = new Headers({
|
|
71
|
-
"Content-Type":
|
|
72
|
+
"Content-Type": VINEXT_RSC_CONTENT_TYPE,
|
|
72
73
|
Vary: VINEXT_RSC_VARY_HEADER
|
|
73
74
|
});
|
|
74
75
|
if (options.params && Object.keys(options.params).length > 0) headers.set(VINEXT_PARAMS_HEADER, encodeURIComponent(JSON.stringify(options.params)));
|
|
75
76
|
if (options.mountedSlotsHeader) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);
|
|
76
77
|
if (options.policy.cacheControl) headers.set("Cache-Control", options.policy.cacheControl);
|
|
77
|
-
if (options.policy.cacheState) headers
|
|
78
|
+
if (options.policy.cacheState) setCacheStateHeaders(headers, options.policy.cacheState);
|
|
78
79
|
mergeMiddlewareResponseHeaders(headers, options.middlewareContext.headers);
|
|
80
|
+
applyRscCompatibilityIdHeader(headers);
|
|
79
81
|
applyTimingHeader(headers, options.timing);
|
|
80
82
|
return new Response(body, {
|
|
81
83
|
status: options.middlewareContext.status ?? 200,
|
|
@@ -88,7 +90,7 @@ function buildAppPageHtmlResponse(body, options) {
|
|
|
88
90
|
Vary: VINEXT_RSC_VARY_HEADER
|
|
89
91
|
});
|
|
90
92
|
if (options.policy.cacheControl) headers.set("Cache-Control", options.policy.cacheControl);
|
|
91
|
-
if (options.policy.cacheState) headers
|
|
93
|
+
if (options.policy.cacheState) setCacheStateHeaders(headers, options.policy.cacheState);
|
|
92
94
|
if (options.draftCookie) headers.append("Set-Cookie", options.draftCookie);
|
|
93
95
|
if (options.fontLinkHeader) headers.set("Link", options.fontLinkHeader);
|
|
94
96
|
mergeMiddlewareResponseHeaders(headers, options.middlewareContext.headers);
|
|
@@ -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 { VINEXT_RSC_VARY_HEADER } 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\": \"text/x-component; charset=utf-8\",\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\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\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 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 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 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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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AppRouteSemanticIds } from "../routing/app-route-graph.js";
|
|
2
|
-
import { AppElements } from "./app-elements-wire.js";
|
|
2
|
+
import { AppElements, AppElementsInterception } from "./app-elements-wire.js";
|
|
3
3
|
import { AppPageParams } from "./app-page-boundary.js";
|
|
4
4
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
5
5
|
import { Metadata, Viewport } from "../shims/metadata.js";
|
|
@@ -93,6 +93,7 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
|
|
|
93
93
|
makeThenableParams: (params: AppPageParams) => unknown;
|
|
94
94
|
matchedParams: AppPageParams;
|
|
95
95
|
resolvedMetadata: Metadata | null;
|
|
96
|
+
resolvedMetadataPathname?: string;
|
|
96
97
|
resolvedViewport: Viewport;
|
|
97
98
|
rootForbiddenModule?: TModule | null;
|
|
98
99
|
rootNotFoundModule?: TModule | null;
|
|
@@ -101,6 +102,7 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
|
|
|
101
102
|
slotOverrides?: Readonly<Record<string, AppPageSlotOverride<TModule>>> | null;
|
|
102
103
|
};
|
|
103
104
|
type BuildAppPageElementsOptions<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule> = BuildAppPageRouteElementOptions<TModule, TErrorModule> & {
|
|
105
|
+
interception?: AppElementsInterception | null;
|
|
104
106
|
interceptionContext?: string | null;
|
|
105
107
|
isRscRequest?: boolean;
|
|
106
108
|
mountedSlotIds?: ReadonlySet<string> | null;
|