vinext 0.0.49 → 0.0.51
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/client-build-config.js.map +1 -1
- package/dist/build/google-fonts/build-url.js.map +1 -1
- 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/google-fonts/get-axes.js.map +1 -1
- package/dist/build/google-fonts/sort-variants.js.map +1 -1
- package/dist/build/google-fonts/validate.js.map +1 -1
- package/dist/build/layout-classification.js.map +1 -1
- package/dist/build/nitro-route-rules.js.map +1 -1
- package/dist/build/precompress.d.ts +13 -2
- package/dist/build/precompress.js +12 -3
- package/dist/build/precompress.js.map +1 -1
- package/dist/build/prerender.d.ts +17 -1
- package/dist/build/prerender.js +114 -23
- 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/build/route-classification-injector.js.map +1 -1
- package/dist/build/route-classification-manifest.js.map +1 -1
- package/dist/build/run-prerender.js.map +1 -1
- package/dist/build/server-manifest.js.map +1 -1
- package/dist/build/ssr-manifest.js.map +1 -1
- package/dist/build/standalone.js.map +1 -1
- package/dist/build/static-export.js.map +1 -1
- package/dist/check.js +2 -1
- package/dist/check.js.map +1 -1
- package/dist/cli-args.js.map +1 -1
- package/dist/cli.js +68 -7
- package/dist/cli.js.map +1 -1
- package/dist/client/instrumentation-client-state.js.map +1 -1
- package/dist/client/validate-module-path.js.map +1 -1
- package/dist/client/vinext-next-data.d.ts +5 -1
- package/dist/client/window-next.d.ts +151 -0
- package/dist/client/window-next.js +48 -0
- package/dist/client/window-next.js.map +1 -0
- package/dist/cloudflare/kv-cache-handler.js.map +1 -1
- package/dist/cloudflare/tpr.js +2 -1
- package/dist/cloudflare/tpr.js.map +1 -1
- package/dist/config/config-matchers.d.ts +3 -1
- package/dist/config/config-matchers.js +5 -4
- 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 +93 -6
- package/dist/config/next-config.js +233 -6
- 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 +16 -7
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-browser-entry.d.ts +3 -1
- package/dist/entries/app-browser-entry.js +36 -2
- 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 +49 -12
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.d.ts +9 -0
- package/dist/entries/app-rsc-manifest.js +8 -1
- package/dist/entries/app-rsc-manifest.js.map +1 -1
- package/dist/entries/app-ssr-entry.js.map +1 -1
- package/dist/entries/pages-client-entry.js +3 -5
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-entry-helpers.js.map +1 -1
- package/dist/entries/pages-server-entry.js +34 -1
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.js.map +1 -1
- package/dist/index.js +204 -53
- package/dist/index.js.map +1 -1
- package/dist/init.js.map +1 -1
- package/dist/plugins/async-hooks-stub.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/fonts.d.ts +2 -2
- package/dist/plugins/fonts.js +15 -6
- package/dist/plugins/fonts.js.map +1 -1
- package/dist/plugins/instrumentation-client.js.map +1 -1
- package/dist/plugins/og-assets.js.map +1 -1
- package/dist/plugins/optimize-imports.js.map +1 -1
- package/dist/plugins/postcss.js.map +1 -1
- package/dist/plugins/rsc-client-reference-loaders.d.ts +7 -0
- package/dist/plugins/rsc-client-reference-loaders.js +48 -0
- package/dist/plugins/rsc-client-reference-loaders.js.map +1 -0
- package/dist/plugins/rsc-client-shim-excludes.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/server-externals-manifest.js.map +1 -1
- package/dist/plugins/strip-server-exports.js.map +1 -1
- package/dist/routing/app-route-graph.d.ts +78 -6
- package/dist/routing/app-route-graph.js +241 -25
- package/dist/routing/app-route-graph.js.map +1 -1
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/file-matcher.js.map +1 -1
- package/dist/routing/pages-router.js.map +1 -1
- package/dist/routing/route-matching.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/route-trie.js.map +1 -1
- package/dist/routing/route-validation.js.map +1 -1
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/api-handler.js.map +1 -1
- package/dist/server/app-browser-action-result.d.ts +44 -0
- package/dist/server/app-browser-action-result.js +79 -0
- package/dist/server/app-browser-action-result.js.map +1 -0
- package/dist/server/app-browser-entry.js +330 -133
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-error.js.map +1 -1
- package/dist/server/app-browser-hydration.d.ts +31 -0
- package/dist/server/app-browser-hydration.js +30 -0
- package/dist/server/app-browser-hydration.js.map +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +20 -4
- package/dist/server/app-browser-navigation-controller.js +90 -23
- 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 +28 -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 +27 -23
- package/dist/server/app-browser-state.js +158 -54
- package/dist/server/app-browser-state.js.map +1 -1
- package/dist/server/app-browser-stream.d.ts +9 -4
- package/dist/server/app-browser-stream.js +29 -8
- package/dist/server/app-browser-stream.js.map +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +11 -1
- package/dist/server/app-browser-visible-commit.js +69 -21
- package/dist/server/app-browser-visible-commit.js.map +1 -1
- package/dist/server/app-client-reference-preloader.js.map +1 -1
- package/dist/server/app-elements-wire.d.ts +43 -6
- package/dist/server/app-elements-wire.js +121 -5
- package/dist/server/app-elements-wire.js.map +1 -1
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -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 +37 -1
- 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-hook-warning-suppression.js.map +1 -1
- package/dist/server/app-middleware.d.ts +1 -1
- package/dist/server/app-middleware.js +4 -9
- package/dist/server/app-middleware.js.map +1 -1
- package/dist/server/app-mounted-slots-header.js.map +1 -1
- package/dist/server/app-page-boundary-render.d.ts +11 -1
- package/dist/server/app-page-boundary-render.js +27 -19
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-boundary.d.ts +1 -0
- package/dist/server/app-page-boundary.js +10 -7
- package/dist/server/app-page-boundary.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +23 -3
- package/dist/server/app-page-cache.js +63 -27
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-dispatch.d.ts +11 -1
- package/dist/server/app-page-dispatch.js +85 -14
- package/dist/server/app-page-dispatch.js.map +1 -1
- package/dist/server/app-page-element-builder.d.ts +10 -1
- package/dist/server/app-page-element-builder.js +38 -6
- package/dist/server/app-page-element-builder.js.map +1 -1
- package/dist/server/app-page-execution.js +2 -3
- 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 +6 -1
- package/dist/server/app-page-head.js.map +1 -1
- package/dist/server/app-page-method.js.map +1 -1
- package/dist/server/app-page-params.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 +12 -2
- package/dist/server/app-page-render.js +90 -7
- 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 +2 -1
- package/dist/server/app-page-request.js.map +1 -1
- package/dist/server/app-page-response.d.ts +2 -0
- package/dist/server/app-page-response.js +18 -7
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +9 -3
- package/dist/server/app-page-route-wiring.js +91 -62
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-page-segment-state.d.ts +10 -0
- package/dist/server/app-page-segment-state.js +87 -0
- package/dist/server/app-page-segment-state.js.map +1 -0
- package/dist/server/app-page-stream.d.ts +9 -2
- package/dist/server/app-page-stream.js +4 -1
- package/dist/server/app-page-stream.js.map +1 -1
- package/dist/server/app-post-middleware-context.js.map +1 -1
- package/dist/server/app-prerender-endpoints.js.map +1 -1
- package/dist/server/app-prerender-static-params.js.map +1 -1
- package/dist/server/app-render-dependency.js.map +1 -1
- package/dist/server/app-request-context.js.map +1 -1
- package/dist/server/app-route-handler-cache.js.map +1 -1
- package/dist/server/app-route-handler-dispatch.js +3 -1
- package/dist/server/app-route-handler-dispatch.js.map +1 -1
- package/dist/server/app-route-handler-execution.js.map +1 -1
- package/dist/server/app-route-handler-policy.js +1 -0
- package/dist/server/app-route-handler-policy.js.map +1 -1
- package/dist/server/app-route-handler-response.js +4 -3
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-route-handler-runtime.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 +23 -2
- package/dist/server/app-rsc-cache-busting.js +75 -19
- 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-error-handler.js.map +1 -1
- 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 +18 -1
- package/dist/server/app-rsc-handler.js +55 -16
- package/dist/server/app-rsc-handler.js.map +1 -1
- package/dist/server/app-rsc-render-mode.d.ts +11 -0
- package/dist/server/app-rsc-render-mode.js +21 -0
- package/dist/server/app-rsc-render-mode.js.map +1 -0
- package/dist/server/app-rsc-request-normalization.d.ts +4 -1
- package/dist/server/app-rsc-request-normalization.js +7 -2
- package/dist/server/app-rsc-request-normalization.js.map +1 -1
- package/dist/server/app-rsc-response-finalizer.d.ts +2 -1
- package/dist/server/app-rsc-response-finalizer.js +6 -1
- 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 +45 -23
- package/dist/server/app-rsc-route-matching.js.map +1 -1
- package/dist/server/app-segment-config.js.map +1 -1
- package/dist/server/app-server-action-execution.d.ts +51 -5
- package/dist/server/app-server-action-execution.js +161 -51
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/app-ssr-entry.d.ts +7 -0
- package/dist/server/app-ssr-entry.js +44 -14
- 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 +1 -1
- package/dist/server/app-ssr-stream.js +9 -12
- package/dist/server/app-ssr-stream.js.map +1 -1
- package/dist/server/app-static-generation.js.map +1 -1
- package/dist/server/artifact-compatibility.d.ts +12 -2
- package/dist/server/artifact-compatibility.js +12 -8
- package/dist/server/artifact-compatibility.js.map +1 -1
- package/dist/server/cache-control.js +1 -0
- package/dist/server/cache-control.js.map +1 -1
- package/dist/server/cache-proof.d.ts +124 -5
- package/dist/server/cache-proof.js +416 -18
- package/dist/server/cache-proof.js.map +1 -1
- package/dist/server/csp.js.map +1 -1
- package/dist/server/dev-error-overlay-store.js.map +1 -1
- package/dist/server/dev-error-overlay.js +5 -0
- package/dist/server/dev-error-overlay.js.map +1 -1
- 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-module-runner.js.map +1 -1
- package/dist/server/dev-origin-check.js.map +1 -1
- package/dist/server/dev-route-files.js.map +1 -1
- package/dist/server/dev-server.js +23 -10
- package/dist/server/dev-server.js.map +1 -1
- 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 +81 -0
- package/dist/server/headers.js +104 -0
- package/dist/server/headers.js.map +1 -0
- package/dist/server/html.js +1 -1
- package/dist/server/html.js.map +1 -1
- package/dist/server/http-error-responses.d.ts +10 -0
- package/dist/server/http-error-responses.js +11 -1
- package/dist/server/http-error-responses.js.map +1 -1
- package/dist/server/image-optimization.d.ts +11 -1
- package/dist/server/image-optimization.js.map +1 -1
- package/dist/server/implicit-tags.js +2 -1
- package/dist/server/implicit-tags.js.map +1 -1
- package/dist/server/instrumentation-runtime.js.map +1 -1
- package/dist/server/instrumentation.js.map +1 -1
- package/dist/server/isr-cache.d.ts +12 -2
- package/dist/server/isr-cache.js +16 -5
- package/dist/server/isr-cache.js.map +1 -1
- package/dist/server/metadata-route-build-data.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-matcher.js.map +1 -1
- package/dist/server/middleware-request-headers.d.ts +4 -1
- package/dist/server/middleware-request-headers.js +15 -8
- package/dist/server/middleware-request-headers.js.map +1 -1
- package/dist/server/middleware-response-headers.d.ts +2 -1
- package/dist/server/middleware-response-headers.js +1 -1
- package/dist/server/middleware-response-headers.js.map +1 -1
- package/dist/server/middleware-runtime.d.ts +1 -0
- package/dist/server/middleware-runtime.js +7 -3
- package/dist/server/middleware-runtime.js.map +1 -1
- package/dist/server/middleware.d.ts +12 -0
- package/dist/server/middleware.js +12 -0
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/navigation-planner.d.ts +133 -0
- package/dist/server/navigation-planner.js +432 -0
- package/dist/server/navigation-planner.js.map +1 -0
- package/dist/server/navigation-trace.d.ts +19 -2
- package/dist/server/navigation-trace.js +20 -1
- package/dist/server/navigation-trace.js.map +1 -1
- package/dist/server/next-error-digest.d.ts +3 -2
- package/dist/server/next-error-digest.js +4 -2
- package/dist/server/next-error-digest.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.js +1 -0
- package/dist/server/pages-api-route.js.map +1 -1
- package/dist/server/pages-i18n.js.map +1 -1
- package/dist/server/pages-media-type.js.map +1 -1
- package/dist/server/pages-node-compat.js.map +1 -1
- package/dist/server/pages-page-data.d.ts +3 -2
- package/dist/server/pages-page-data.js +27 -5
- package/dist/server/pages-page-data.js.map +1 -1
- package/dist/server/pages-page-response.js +2 -1
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/prerender-work-unit-setup.js +1 -1
- package/dist/server/prerender-work-unit-setup.js.map +1 -1
- package/dist/server/prod-server.d.ts +28 -1
- package/dist/server/prod-server.js +97 -22
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-log.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +1 -13
- package/dist/server/request-pipeline.js +3 -25
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/server/rsc-stream-hints.js.map +1 -1
- 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 +22 -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/socket-error-backstop.js.map +1 -1
- package/dist/server/static-file-cache.js +1 -1
- package/dist/server/static-file-cache.js.map +1 -1
- package/dist/server/worker-utils.d.ts +0 -7
- package/dist/server/worker-utils.js +3 -2
- package/dist/server/worker-utils.js.map +1 -1
- package/dist/shims/amp.js.map +1 -1
- package/dist/shims/app.d.ts +37 -4
- package/dist/shims/app.js +50 -1
- package/dist/shims/app.js.map +1 -0
- package/dist/shims/cache-for-request.js.map +1 -1
- package/dist/shims/cache-runtime.d.ts +19 -2
- package/dist/shims/cache-runtime.js +87 -19
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.d.ts +20 -21
- package/dist/shims/cache.js +101 -15
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/client-hook-error.js.map +1 -1
- package/dist/shims/compat-router.js.map +1 -1
- package/dist/shims/config.js.map +1 -1
- package/dist/shims/constants.js.map +1 -1
- package/dist/shims/document.js.map +1 -1
- package/dist/shims/dynamic.d.ts +18 -10
- package/dist/shims/dynamic.js +107 -51
- package/dist/shims/dynamic.js.map +1 -1
- package/dist/shims/error-boundary.d.ts +35 -6
- package/dist/shims/error-boundary.js +116 -33
- 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 +25 -1
- package/dist/shims/fetch-cache.js +159 -13
- 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 +3 -1
- 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/head-state.js.map +1 -1
- package/dist/shims/head.d.ts +3 -1
- package/dist/shims/head.js +28 -16
- package/dist/shims/head.js.map +1 -1
- package/dist/shims/headers.d.ts +11 -12
- package/dist/shims/headers.js +45 -8
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/i18n-context.js.map +1 -1
- package/dist/shims/i18n-state.js.map +1 -1
- package/dist/shims/image-config.d.ts +14 -1
- package/dist/shims/image-config.js +24 -1
- package/dist/shims/image-config.js.map +1 -1
- package/dist/shims/image.d.ts +1 -0
- package/dist/shims/image.js +159 -80
- package/dist/shims/image.js.map +1 -1
- package/dist/shims/internal/als-registry.js.map +1 -1
- package/dist/shims/internal/app-router-context.d.ts +7 -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/internal/cookie-serialize.js.map +1 -1
- package/dist/shims/internal/make-hanging-promise.d.ts +1 -1
- package/dist/shims/internal/make-hanging-promise.js +1 -1
- package/dist/shims/internal/make-hanging-promise.js.map +1 -1
- package/dist/shims/internal/parse-cookie-header.js.map +1 -1
- package/dist/shims/internal/utils.js.map +1 -1
- package/dist/shims/internal/work-unit-async-storage.js +2 -2
- package/dist/shims/internal/work-unit-async-storage.js.map +1 -1
- package/dist/shims/layout-segment-context.js.map +1 -1
- package/dist/shims/legacy-image.js.map +1 -1
- package/dist/shims/link-prefetch.d.ts +42 -0
- package/dist/shims/link-prefetch.js +45 -0
- package/dist/shims/link-prefetch.js.map +1 -0
- package/dist/shims/link.d.ts +37 -4
- package/dist/shims/link.js +156 -46
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +16 -30
- package/dist/shims/metadata.js +87 -28
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation-state.js.map +1 -1
- package/dist/shims/navigation.d.ts +172 -10
- package/dist/shims/navigation.js +335 -70
- 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/offline.js.map +1 -1
- 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/readonly-url-search-params.js.map +1 -1
- package/dist/shims/request-context.js.map +1 -1
- package/dist/shims/root-params.js.map +1 -1
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/router.d.ts +69 -7
- package/dist/shims/router.js +232 -249
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/script-nonce-context.js.map +1 -1
- package/dist/shims/script.js +110 -32
- package/dist/shims/script.js.map +1 -1
- package/dist/shims/server.js +12 -15
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/slot.d.ts +7 -1
- package/dist/shims/slot.js +60 -7
- package/dist/shims/slot.js.map +1 -1
- package/dist/shims/thenable-params.js.map +1 -1
- package/dist/shims/unified-request-context.js +5 -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.js.map +1 -1
- package/dist/shims/url-utils.d.ts +22 -1
- package/dist/shims/url-utils.js +76 -3
- package/dist/shims/url-utils.js.map +1 -1
- package/dist/shims/use-merged-ref.js.map +1 -1
- package/dist/shims/web-vitals.d.ts +4 -21
- package/dist/shims/web-vitals.js +19 -6
- package/dist/shims/web-vitals.js.map +1 -1
- package/dist/utils/asset-prefix.d.ts +69 -0
- package/dist/utils/asset-prefix.js +91 -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.js.map +1 -1
- package/dist/utils/domain-locale.js.map +1 -1
- package/dist/utils/encode-cache-tag.d.ts +31 -0
- package/dist/utils/encode-cache-tag.js +38 -0
- package/dist/utils/encode-cache-tag.js.map +1 -0
- package/dist/utils/error-cause.js.map +1 -1
- package/dist/utils/hash.js.map +1 -1
- package/dist/utils/lazy-chunks.js.map +1 -1
- package/dist/utils/manifest-paths.js.map +1 -1
- package/dist/utils/mdx-scan.js.map +1 -1
- package/dist/utils/navigation-signal.d.ts +5 -0
- package/dist/utils/navigation-signal.js +14 -0
- package/dist/utils/navigation-signal.js.map +1 -0
- package/dist/utils/project.js.map +1 -1
- package/dist/utils/public-routes.js.map +1 -1
- package/dist/utils/query.js.map +1 -1
- package/dist/utils/safe-json-file.js.map +1 -1
- 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/dist/utils/text-stream.js.map +1 -1
- package/dist/utils/vinext-root.js.map +1 -1
- package/package.json +8 -6
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
2
|
+
import { isInterceptionMatchedUrlPath, normalizePath } from "./normalize-path.js";
|
|
3
|
+
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
4
|
+
import { markDynamicUsage, markRenderRequestApiUsage } from "../shims/headers.js";
|
|
5
|
+
import { APP_RSC_RENDER_MODE_NAVIGATION } from "./app-rsc-render-mode.js";
|
|
2
6
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
3
7
|
import "./app-elements.js";
|
|
4
|
-
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
5
8
|
import { makeThenableParams } from "../shims/thenable-params.js";
|
|
6
9
|
import { buildAppPageElements, createAppPageTreePath } from "./app-page-route-wiring.js";
|
|
7
10
|
import { resolveActiveParallelRouteHeadInputs, resolveAppPageHead } from "./app-page-head.js";
|
|
@@ -25,20 +28,25 @@ import { createElement } from "react";
|
|
|
25
28
|
*/
|
|
26
29
|
async function buildPageElements(options) {
|
|
27
30
|
const { route, params, routePath, pageRequest, globalErrorModule, rootNotFoundModule, rootForbiddenModule, rootUnauthorizedModule, metadataRoutes } = options;
|
|
28
|
-
const { opts, searchParams, isRscRequest, mountedSlotsHeader } = pageRequest;
|
|
31
|
+
const { opts, searchParams, isRscRequest, mountedSlotsHeader, renderMode = APP_RSC_RENDER_MODE_NAVIGATION } = pageRequest;
|
|
29
32
|
const pageModule = route.page;
|
|
30
33
|
const PageComponent = pageModule?.default;
|
|
31
|
-
|
|
34
|
+
const hasPageModule = !!pageModule;
|
|
35
|
+
const interception = createAppPageInterceptionProof(routePath, opts);
|
|
36
|
+
if (hasPageModule && !PageComponent) {
|
|
32
37
|
const interceptionContext = opts?.interceptionContext ?? null;
|
|
33
38
|
const noExportRouteId = AppElementsWire.encodeRouteId(routePath, interceptionContext);
|
|
34
39
|
let noExportRootLayout = null;
|
|
40
|
+
const noExportLayoutIds = route.ids?.layouts ?? route.layouts.map((_, index) => AppElementsWire.encodeLayoutId(createAppPageTreePath(route.routeSegments, route.layoutTreePositions?.[index] ?? 0)));
|
|
35
41
|
if (route.layouts?.length > 0) {
|
|
36
42
|
const treePosition = route.layoutTreePositions?.[0] ?? 0;
|
|
37
43
|
noExportRootLayout = createAppPageTreePath(route.routeSegments, treePosition);
|
|
38
44
|
}
|
|
39
45
|
return {
|
|
40
46
|
...AppElementsWire.createMetadataEntries({
|
|
47
|
+
interception,
|
|
41
48
|
interceptionContext,
|
|
49
|
+
layoutIds: noExportLayoutIds,
|
|
42
50
|
rootLayoutTreePath: noExportRootLayout,
|
|
43
51
|
routeId: noExportRouteId
|
|
44
52
|
}),
|
|
@@ -46,6 +54,7 @@ async function buildPageElements(options) {
|
|
|
46
54
|
};
|
|
47
55
|
}
|
|
48
56
|
const { hasSearchParams, metadata: resolvedMetadata, pageSearchParams, viewport: resolvedViewport } = await resolveAppPageHead({
|
|
57
|
+
basePath: options.basePath ?? "",
|
|
49
58
|
layoutModules: route.layouts,
|
|
50
59
|
layoutTreePositions: route.layoutTreePositions,
|
|
51
60
|
metadataRoutes,
|
|
@@ -67,7 +76,10 @@ async function buildPageElements(options) {
|
|
|
67
76
|
const pageProps = { params: makeThenableParams(params) };
|
|
68
77
|
if (searchParams) {
|
|
69
78
|
pageProps.searchParams = makeThenableParams(pageSearchParams);
|
|
70
|
-
if (hasSearchParams)
|
|
79
|
+
if (hasSearchParams) {
|
|
80
|
+
markDynamicUsage();
|
|
81
|
+
markRenderRequestApiUsage("searchParams");
|
|
82
|
+
}
|
|
71
83
|
}
|
|
72
84
|
const mountedSlotIds = mountedSlotsHeader ? new Set(mountedSlotsHeader.split(" ")) : null;
|
|
73
85
|
const slotOverrides = buildSlotOverrides(route, params, routePath, opts);
|
|
@@ -79,16 +91,36 @@ async function buildPageElements(options) {
|
|
|
79
91
|
makeThenableParams,
|
|
80
92
|
matchedParams: params,
|
|
81
93
|
resolvedMetadata,
|
|
94
|
+
resolvedMetadataPathname: routePath,
|
|
82
95
|
resolvedViewport,
|
|
83
96
|
interceptionContext: opts?.interceptionContext ?? null,
|
|
97
|
+
interception,
|
|
84
98
|
routePath,
|
|
85
99
|
rootNotFoundModule: rootNotFoundModule ?? null,
|
|
86
100
|
rootForbiddenModule: rootForbiddenModule ?? null,
|
|
87
101
|
rootUnauthorizedModule: rootUnauthorizedModule ?? null,
|
|
88
102
|
route,
|
|
89
|
-
slotOverrides
|
|
103
|
+
slotOverrides,
|
|
104
|
+
renderMode
|
|
90
105
|
});
|
|
91
106
|
}
|
|
107
|
+
function createAppPageInterceptionProof(routePath, opts) {
|
|
108
|
+
const sourceMatchedUrl = normalizeInterceptionProofMatchedUrl(opts?.interceptSourceMatchedUrl ?? null);
|
|
109
|
+
const targetMatchedUrl = normalizeInterceptionProofMatchedUrl(routePath);
|
|
110
|
+
const slotId = opts?.interceptSlotId ?? null;
|
|
111
|
+
if (sourceMatchedUrl === null || targetMatchedUrl === null || slotId === null) return null;
|
|
112
|
+
return {
|
|
113
|
+
sourceMatchedUrl,
|
|
114
|
+
sourceRouteId: AppElementsWire.encodeRouteId(sourceMatchedUrl, null),
|
|
115
|
+
slotId,
|
|
116
|
+
targetMatchedUrl,
|
|
117
|
+
targetRouteId: AppElementsWire.encodeRouteId(targetMatchedUrl, null)
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function normalizeInterceptionProofMatchedUrl(value) {
|
|
121
|
+
if (value === null || !isInterceptionMatchedUrlPath(value)) return null;
|
|
122
|
+
return normalizePath(normalizePathnameForRouteMatch(value));
|
|
123
|
+
}
|
|
92
124
|
/**
|
|
93
125
|
* Build the per-request `slotOverrides` map. Combines:
|
|
94
126
|
* - Interception overrides (existing behavior — swap in the intercepting page
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-page-element-builder.js","names":[],"sources":["../../src/server/app-page-element-builder.ts"],"sourcesContent":["import { createElement } from \"react\";\nimport { markDynamicUsage } from \"vinext/shims/headers\";\nimport { makeThenableParams } from \"vinext/shims/thenable-params\";\nimport { resolveActiveParallelRouteHeadInputs, resolveAppPageHead } from \"./app-page-head.js\";\nimport {\n buildAppPageElements,\n createAppPageTreePath,\n type AppPageErrorModule,\n type AppPageModule,\n type AppPageRouteWiringRoute,\n type AppPageSlotOverride,\n} from \"./app-page-route-wiring.js\";\nimport { AppElementsWire, type AppElements } from \"./app-elements.js\";\nimport type { AppPageParams } from \"./app-page-boundary.js\";\nimport { matchRoutePattern } from \"../routing/route-pattern.js\";\nimport type { MetadataFileRoute } from \"./metadata-routes.js\";\n\nexport type { AppPageErrorModule, AppPageRouteWiringRoute } from \"./app-page-route-wiring.js\";\n\n/**\n * Route shape passed from the generated entry. Extends the wiring route with\n * the page module reference (used to extract the default export for the page\n * element) and the URL pattern (used as the route path in head resolution).\n */\nexport type AppPageBuildRoute<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = AppPageRouteWiringRoute<TModule, TErrorModule> & {\n page?: TModule | null;\n pattern: string;\n /** Param names captured by the route's URL pattern, in order. */\n params?: readonly string[] | null;\n};\n\nexport type AppPageInterceptOptions<TModule extends AppPageModule = AppPageModule> = {\n interceptionContext?: string | null;\n interceptLayouts?: readonly (TModule | null | undefined)[] | null;\n interceptPage?: TModule | null;\n interceptParams?: AppPageParams | null;\n interceptSlotKey?: string | null;\n};\n\nexport type AppPagePageRequest<TModule extends AppPageModule = AppPageModule> = {\n /** Interception context from current-route navigation (null for direct visits). */\n opts?: AppPageInterceptOptions<TModule> | null;\n /** URL search params from the incoming request (null when unavailable). */\n searchParams?: URLSearchParams | null;\n /** Whether the incoming request is an RSC (client-side navigation) request. */\n isRscRequest: boolean;\n /** The incoming HTTP request (available but unused by this module). */\n request: Request;\n /** Normalized x-vinext-mounted-slots header value. */\n mountedSlotsHeader: string | null;\n};\n\nexport type BuildPageElementsOptions<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n route: AppPageBuildRoute<TModule, TErrorModule>;\n params: AppPageParams;\n routePath: string;\n pageRequest: AppPagePageRequest<TModule>;\n /** Root-level global-error.tsx module. Present when the app defines this file. */\n globalErrorModule?: TErrorModule | null;\n /** Root-level not-found.tsx module. Present when the app defines this file. */\n rootNotFoundModule?: TModule | null;\n /** Root-level forbidden.tsx module. Present when the app defines this file. */\n rootForbiddenModule?: TModule | null;\n /** Root-level unauthorized.tsx module. Present when the app defines this file. */\n rootUnauthorizedModule?: TModule | null;\n /** File-based metadata routes (favicon, manifest, sitemap, etc.). */\n metadataRoutes: readonly MetadataFileRoute[];\n};\n\n/**\n * Build the App Router element tree for a matched route.\n *\n * This is the central element-construction path for the App Router RSC\n * handler. It resolves page head metadata (including parallel route metadata),\n * creates the page React element, and wires it into the nested layout +\n * boundary tree via {@link buildAppPageElements}.\n *\n * The function is extracted from the generated RSC entry template so it can\n * be unit-tested independently of the code-generation machinery.\n *\n * Next.js equivalent: the component tree construction in\n * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-component-tree.tsx|create-component-tree.tsx}\n * and the page head resolution in\n * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-metadata.tsx|create-metadata.tsx}.\n */\nexport async function buildPageElements<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n>(options: BuildPageElementsOptions<TModule, TErrorModule>): Promise<AppElements> {\n const {\n route,\n params,\n routePath,\n pageRequest,\n globalErrorModule,\n rootNotFoundModule,\n rootForbiddenModule,\n rootUnauthorizedModule,\n metadataRoutes,\n } = options;\n const { opts, searchParams, isRscRequest, mountedSlotsHeader } = pageRequest;\n\n const pageModule: AppPageModule | null | undefined = route.page;\n const PageComponent = pageModule?.default;\n const hasPageModule = !!pageModule;\n\n if (hasPageModule && !PageComponent) {\n const interceptionContext = opts?.interceptionContext ?? null;\n const noExportRouteId = AppElementsWire.encodeRouteId(routePath, interceptionContext);\n let noExportRootLayout: string | null = null;\n if (route.layouts?.length > 0) {\n const treePosition = route.layoutTreePositions?.[0] ?? 0;\n noExportRootLayout = createAppPageTreePath(route.routeSegments, treePosition);\n }\n return {\n ...AppElementsWire.createMetadataEntries({\n interceptionContext,\n rootLayoutTreePath: noExportRootLayout,\n routeId: noExportRouteId,\n }),\n [noExportRouteId]: createElement(\"div\", null, \"Page has no default export\"),\n };\n }\n\n const {\n hasSearchParams,\n metadata: resolvedMetadata,\n pageSearchParams,\n viewport: resolvedViewport,\n } = await resolveAppPageHead({\n layoutModules: route.layouts,\n layoutTreePositions: route.layoutTreePositions,\n metadataRoutes,\n pageModule: route.page ?? null,\n parallelRoutes: resolveActiveParallelRouteHeadInputs({\n interceptLayouts: opts?.interceptLayouts ?? null,\n interceptPage: opts?.interceptPage ?? null,\n interceptParams: opts?.interceptParams ?? null,\n interceptSlotKey: opts?.interceptSlotKey ?? null,\n params,\n routeSegments: route.routeSegments ?? [],\n slots: route.slots ?? null,\n }),\n params,\n routePath: route.pattern,\n routeSegments: route.routeSegments ?? null,\n searchParams,\n });\n\n const pageProps: Record<string, unknown> = { params: makeThenableParams(params) };\n if (searchParams) {\n pageProps.searchParams = makeThenableParams(pageSearchParams);\n if (hasSearchParams) markDynamicUsage();\n }\n\n const mountedSlotIds = mountedSlotsHeader ? new Set(mountedSlotsHeader.split(\" \")) : null;\n\n const slotOverrides = buildSlotOverrides(route, params, routePath, opts);\n\n return buildAppPageElements({\n element: PageComponent ? createElement(PageComponent, pageProps) : null,\n globalErrorModule: globalErrorModule ?? null,\n isRscRequest,\n mountedSlotIds,\n makeThenableParams,\n matchedParams: params,\n resolvedMetadata,\n resolvedViewport,\n interceptionContext: opts?.interceptionContext ?? null,\n routePath,\n rootNotFoundModule: rootNotFoundModule ?? null,\n rootForbiddenModule: rootForbiddenModule ?? null,\n rootUnauthorizedModule: rootUnauthorizedModule ?? null,\n route,\n slotOverrides,\n });\n}\n\n/**\n * Build the per-request `slotOverrides` map. Combines:\n * - Interception overrides (existing behavior — swap in the intercepting page\n * and its layouts when the request is intercepted into this slot).\n * - Slot-specific param extraction for inherited slots whose URL pattern\n * has different param names than the route's. The runtime matches the\n * cleaned request path against `slot.slotPatternParts` to produce\n * slot-scoped params, which `app-page-route-wiring` then hands to the\n * slot page instead of the route's matched params.\n *\n * `routePath` is the already-normalized request pathname (basePath stripped,\n * RSC suffix removed). Re-parsing `request.url` here would re-introduce the\n * basePath and silently break the match for any app that configures one.\n */\nfunction buildSlotOverrides<TModule extends AppPageModule, TErrorModule extends AppPageErrorModule>(\n route: AppPageBuildRoute<TModule, TErrorModule>,\n routeParams: AppPageParams,\n routePath: string,\n opts?: AppPageInterceptOptions<TModule> | null,\n): Readonly<Record<string, AppPageSlotOverride<TModule>>> | null {\n const overrides: Record<string, AppPageSlotOverride<TModule>> = {};\n\n if (opts && opts.interceptSlotKey && opts.interceptPage) {\n overrides[opts.interceptSlotKey] = {\n layoutModules: opts.interceptLayouts || null,\n pageModule: opts.interceptPage,\n params: opts.interceptParams || routeParams,\n };\n }\n\n const slots = route.slots;\n if (slots) {\n let urlParts: string[] | null = null;\n const routeParamSet = collectParamNameSet(route.params);\n for (const [slotKey, slot] of Object.entries(slots)) {\n const patternParts = slot.slotPatternParts;\n const paramNames = slot.slotParamNames;\n if (!patternParts || patternParts.length === 0) continue;\n // Skip when every slot param is already a route param — the route's\n // matched params already carry the values the slot page expects.\n // Empty `paramNames` (slot pattern has no dynamic markers) also skips:\n // there's nothing to extract, so the route's matched params suffice.\n if (paramNames && paramNames.every((name) => routeParamSet.has(name))) continue;\n\n if (urlParts === null) {\n urlParts = routePath.split(\"/\").filter(Boolean);\n }\n const matched = matchRoutePattern(urlParts, patternParts);\n if (!matched) continue;\n\n const existing = overrides[slotKey];\n overrides[slotKey] = existing ? { ...existing, params: matched } : { params: matched };\n }\n }\n\n return Object.keys(overrides).length > 0 ? overrides : null;\n}\n\nfunction collectParamNameSet(params: readonly string[] | undefined | null): Set<string> {\n const set = new Set<string>();\n if (params) {\n for (const name of params) set.add(name);\n }\n return set;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-page-element-builder.js","names":[],"sources":["../../src/server/app-page-element-builder.ts"],"sourcesContent":["import { createElement } from \"react\";\nimport { markDynamicUsage, markRenderRequestApiUsage } from \"vinext/shims/headers\";\nimport { makeThenableParams } from \"vinext/shims/thenable-params\";\nimport { resolveActiveParallelRouteHeadInputs, resolveAppPageHead } from \"./app-page-head.js\";\nimport {\n buildAppPageElements,\n createAppPageTreePath,\n type AppPageErrorModule,\n type AppPageModule,\n type AppPageRouteWiringRoute,\n type AppPageSlotOverride,\n} from \"./app-page-route-wiring.js\";\nimport { AppElementsWire, type AppElements, type AppElementsInterception } from \"./app-elements.js\";\nimport type { AppPageParams } from \"./app-page-boundary.js\";\nimport { matchRoutePattern } from \"../routing/route-pattern.js\";\nimport { normalizePathnameForRouteMatch } from \"../routing/utils.js\";\nimport type { MetadataFileRoute } from \"./metadata-routes.js\";\nimport { APP_RSC_RENDER_MODE_NAVIGATION, type AppRscRenderMode } from \"./app-rsc-render-mode.js\";\nimport { isInterceptionMatchedUrlPath, normalizePath } from \"./normalize-path.js\";\n\nexport type { AppPageErrorModule, AppPageRouteWiringRoute } from \"./app-page-route-wiring.js\";\n\n/**\n * Route shape passed from the generated entry. Extends the wiring route with\n * the page module reference (used to extract the default export for the page\n * element) and the URL pattern (used as the route path in head resolution).\n */\nexport type AppPageBuildRoute<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = AppPageRouteWiringRoute<TModule, TErrorModule> & {\n page?: TModule | null;\n pattern: string;\n /** Param names captured by the route's URL pattern, in order. */\n params?: readonly string[] | null;\n};\n\nexport type AppPageInterceptOptions<TModule extends AppPageModule = AppPageModule> = {\n interceptionContext?: string | null;\n interceptLayouts?: readonly (TModule | null | undefined)[] | null;\n interceptPage?: TModule | null;\n interceptParams?: AppPageParams | null;\n interceptSlotId?: string | null;\n interceptSlotKey?: string | null;\n interceptSourceMatchedUrl?: string | null;\n};\n\nexport type AppPagePageRequest<TModule extends AppPageModule = AppPageModule> = {\n /** Interception context from current-route navigation (null for direct visits). */\n opts?: AppPageInterceptOptions<TModule> | null;\n /** URL search params from the incoming request (null when unavailable). */\n searchParams?: URLSearchParams | null;\n /** Whether the incoming request is an RSC (client-side navigation) request. */\n isRscRequest: boolean;\n /** The incoming HTTP request (available but unused by this module). */\n request: Request;\n /** Normalized x-vinext-mounted-slots header value. */\n mountedSlotsHeader: string | null;\n /** Semantic RSC payload mode for this page render. */\n renderMode?: AppRscRenderMode;\n};\n\nexport type BuildPageElementsOptions<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n route: AppPageBuildRoute<TModule, TErrorModule>;\n params: AppPageParams;\n routePath: string;\n pageRequest: AppPagePageRequest<TModule>;\n /** Root-level global-error.tsx module. Present when the app defines this file. */\n globalErrorModule?: TErrorModule | null;\n /** Root-level not-found.tsx module. Present when the app defines this file. */\n rootNotFoundModule?: TModule | null;\n /** Root-level forbidden.tsx module. Present when the app defines this file. */\n rootForbiddenModule?: TModule | null;\n /** Root-level unauthorized.tsx module. Present when the app defines this file. */\n rootUnauthorizedModule?: TModule | null;\n /** File-based metadata routes (favicon, manifest, sitemap, etc.). */\n metadataRoutes: readonly MetadataFileRoute[];\n /**\n * Configured next.config `basePath`. Threaded through `resolveAppPageHead`\n * so file-based metadata route URLs emitted in <head> are prefixed.\n */\n basePath?: string;\n};\n\n/**\n * Build the App Router element tree for a matched route.\n *\n * This is the central element-construction path for the App Router RSC\n * handler. It resolves page head metadata (including parallel route metadata),\n * creates the page React element, and wires it into the nested layout +\n * boundary tree via {@link buildAppPageElements}.\n *\n * The function is extracted from the generated RSC entry template so it can\n * be unit-tested independently of the code-generation machinery.\n *\n * Next.js equivalent: the component tree construction in\n * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-component-tree.tsx|create-component-tree.tsx}\n * and the page head resolution in\n * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-metadata.tsx|create-metadata.tsx}.\n */\nexport async function buildPageElements<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n>(options: BuildPageElementsOptions<TModule, TErrorModule>): Promise<AppElements> {\n const {\n route,\n params,\n routePath,\n pageRequest,\n globalErrorModule,\n rootNotFoundModule,\n rootForbiddenModule,\n rootUnauthorizedModule,\n metadataRoutes,\n } = options;\n const {\n opts,\n searchParams,\n isRscRequest,\n mountedSlotsHeader,\n renderMode = APP_RSC_RENDER_MODE_NAVIGATION,\n } = pageRequest;\n\n const pageModule: AppPageModule | null | undefined = route.page;\n const PageComponent = pageModule?.default;\n const hasPageModule = !!pageModule;\n const interception = createAppPageInterceptionProof(routePath, opts);\n\n if (hasPageModule && !PageComponent) {\n const interceptionContext = opts?.interceptionContext ?? null;\n const noExportRouteId = AppElementsWire.encodeRouteId(routePath, interceptionContext);\n let noExportRootLayout: string | null = null;\n const noExportLayoutIds =\n route.ids?.layouts ??\n route.layouts.map((_, index) =>\n AppElementsWire.encodeLayoutId(\n createAppPageTreePath(route.routeSegments, route.layoutTreePositions?.[index] ?? 0),\n ),\n );\n if (route.layouts?.length > 0) {\n const treePosition = route.layoutTreePositions?.[0] ?? 0;\n noExportRootLayout = createAppPageTreePath(route.routeSegments, treePosition);\n }\n return {\n ...AppElementsWire.createMetadataEntries({\n interception,\n interceptionContext,\n layoutIds: noExportLayoutIds,\n rootLayoutTreePath: noExportRootLayout,\n routeId: noExportRouteId,\n }),\n [noExportRouteId]: createElement(\"div\", null, \"Page has no default export\"),\n };\n }\n\n const {\n hasSearchParams,\n metadata: resolvedMetadata,\n pageSearchParams,\n viewport: resolvedViewport,\n } = await resolveAppPageHead({\n basePath: options.basePath ?? \"\",\n layoutModules: route.layouts,\n layoutTreePositions: route.layoutTreePositions,\n metadataRoutes,\n pageModule: route.page ?? null,\n parallelRoutes: resolveActiveParallelRouteHeadInputs({\n interceptLayouts: opts?.interceptLayouts ?? null,\n interceptPage: opts?.interceptPage ?? null,\n interceptParams: opts?.interceptParams ?? null,\n interceptSlotKey: opts?.interceptSlotKey ?? null,\n params,\n routeSegments: route.routeSegments ?? [],\n slots: route.slots ?? null,\n }),\n params,\n routePath: route.pattern,\n routeSegments: route.routeSegments ?? null,\n searchParams,\n });\n\n const pageProps: Record<string, unknown> = { params: makeThenableParams(params) };\n if (searchParams) {\n pageProps.searchParams = makeThenableParams(pageSearchParams);\n if (hasSearchParams) {\n markDynamicUsage();\n markRenderRequestApiUsage(\"searchParams\");\n }\n }\n\n const mountedSlotIds = mountedSlotsHeader ? new Set(mountedSlotsHeader.split(\" \")) : null;\n\n const slotOverrides = buildSlotOverrides(route, params, routePath, opts);\n\n return buildAppPageElements({\n element: PageComponent ? createElement(PageComponent, pageProps) : null,\n globalErrorModule: globalErrorModule ?? null,\n isRscRequest,\n mountedSlotIds,\n makeThenableParams,\n matchedParams: params,\n resolvedMetadata,\n resolvedMetadataPathname: routePath,\n resolvedViewport,\n interceptionContext: opts?.interceptionContext ?? null,\n interception,\n routePath,\n rootNotFoundModule: rootNotFoundModule ?? null,\n rootForbiddenModule: rootForbiddenModule ?? null,\n rootUnauthorizedModule: rootUnauthorizedModule ?? null,\n route,\n slotOverrides,\n renderMode,\n });\n}\n\nfunction createAppPageInterceptionProof<TModule extends AppPageModule>(\n routePath: string,\n opts?: AppPageInterceptOptions<TModule> | null,\n): AppElementsInterception | null {\n const sourceMatchedUrl = normalizeInterceptionProofMatchedUrl(\n opts?.interceptSourceMatchedUrl ?? null,\n );\n const targetMatchedUrl = normalizeInterceptionProofMatchedUrl(routePath);\n const slotId = opts?.interceptSlotId ?? null;\n if (sourceMatchedUrl === null || targetMatchedUrl === null || slotId === null) return null;\n\n return {\n sourceMatchedUrl,\n sourceRouteId: AppElementsWire.encodeRouteId(sourceMatchedUrl, null),\n slotId,\n targetMatchedUrl,\n targetRouteId: AppElementsWire.encodeRouteId(targetMatchedUrl, null),\n };\n}\n\nfunction normalizeInterceptionProofMatchedUrl(value: string | null): string | null {\n if (value === null || !isInterceptionMatchedUrlPath(value)) return null;\n\n return normalizePath(normalizePathnameForRouteMatch(value));\n}\n\n/**\n * Build the per-request `slotOverrides` map. Combines:\n * - Interception overrides (existing behavior — swap in the intercepting page\n * and its layouts when the request is intercepted into this slot).\n * - Slot-specific param extraction for inherited slots whose URL pattern\n * has different param names than the route's. The runtime matches the\n * cleaned request path against `slot.slotPatternParts` to produce\n * slot-scoped params, which `app-page-route-wiring` then hands to the\n * slot page instead of the route's matched params.\n *\n * `routePath` is the already-normalized request pathname (basePath stripped,\n * RSC suffix removed). Re-parsing `request.url` here would re-introduce the\n * basePath and silently break the match for any app that configures one.\n */\nfunction buildSlotOverrides<TModule extends AppPageModule, TErrorModule extends AppPageErrorModule>(\n route: AppPageBuildRoute<TModule, TErrorModule>,\n routeParams: AppPageParams,\n routePath: string,\n opts?: AppPageInterceptOptions<TModule> | null,\n): Readonly<Record<string, AppPageSlotOverride<TModule>>> | null {\n const overrides: Record<string, AppPageSlotOverride<TModule>> = {};\n\n if (opts && opts.interceptSlotKey && opts.interceptPage) {\n overrides[opts.interceptSlotKey] = {\n layoutModules: opts.interceptLayouts || null,\n pageModule: opts.interceptPage,\n params: opts.interceptParams || routeParams,\n };\n }\n\n const slots = route.slots;\n if (slots) {\n let urlParts: string[] | null = null;\n const routeParamSet = collectParamNameSet(route.params);\n for (const [slotKey, slot] of Object.entries(slots)) {\n const patternParts = slot.slotPatternParts;\n const paramNames = slot.slotParamNames;\n if (!patternParts || patternParts.length === 0) continue;\n // Skip when every slot param is already a route param — the route's\n // matched params already carry the values the slot page expects.\n // Empty `paramNames` (slot pattern has no dynamic markers) also skips:\n // there's nothing to extract, so the route's matched params suffice.\n if (paramNames && paramNames.every((name) => routeParamSet.has(name))) continue;\n\n if (urlParts === null) {\n urlParts = routePath.split(\"/\").filter(Boolean);\n }\n const matched = matchRoutePattern(urlParts, patternParts);\n if (!matched) continue;\n\n const existing = overrides[slotKey];\n overrides[slotKey] = existing ? { ...existing, params: matched } : { params: matched };\n }\n }\n\n return Object.keys(overrides).length > 0 ? overrides : null;\n}\n\nfunction collectParamNameSet(params: readonly string[] | undefined | null): Set<string> {\n const set = new Set<string>();\n if (params) {\n for (const name of params) set.add(name);\n }\n return set;\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { addBasePathToPathname } from "../utils/base-path.js";
|
|
2
2
|
import { createRscRedirectLocation } from "./app-rsc-cache-busting.js";
|
|
3
3
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
4
4
|
import { parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
|
|
@@ -51,8 +51,7 @@ function applyAppPageRedirectBasePath(location, requestUrl, basePath) {
|
|
|
51
51
|
const resolved = new URL(location, requestUrl);
|
|
52
52
|
const requestOrigin = new URL(requestUrl).origin;
|
|
53
53
|
if (!basePath || resolved.origin !== requestOrigin) return resolved.toString();
|
|
54
|
-
|
|
55
|
-
resolved.pathname = resolved.pathname === "/" ? basePath : `${basePath}${resolved.pathname}`;
|
|
54
|
+
resolved.pathname = addBasePathToPathname(resolved.pathname, basePath);
|
|
56
55
|
return resolved.toString();
|
|
57
56
|
}
|
|
58
57
|
async function buildAppPageSpecialErrorResponse(options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-page-execution.js","names":[],"sources":["../../src/server/app-page-execution.ts"],"sourcesContent":["import type { LayoutFlags } from \"./app-elements.js\";\nimport type { ClassificationReason } from \"../build/layout-classification-types.js\";\nimport { createRscRedirectLocation } from \"./app-rsc-cache-busting.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport { parseNextHttpErrorDigest, parseNextRedirectDigest } from \"./next-error-digest.js\";\nimport { hasBasePath } from \"../utils/base-path.js\";\n\nexport type { LayoutFlags };\nexport type { ClassificationReason };\n\nexport type AppPageSpecialError =\n | { kind: \"redirect\"; location: string; statusCode: number }\n | { kind: \"http-access-fallback\"; statusCode: number };\n\nexport type AppPageFontPreload = {\n href: string;\n type: string;\n};\n\ntype AppPageRscStreamCapture = {\n /** Stream for createFromReadableStream (SSR). Always set. */\n ssrStream: ReadableStream<Uint8Array>;\n /** When capturing, the combined embed+capture stream. handleSsr consumes this. */\n sideStream?: ReadableStream<Uint8Array>;\n};\n\ntype BuildAppPageSpecialErrorResponseOptions = {\n /**\n * Optional configured basePath (e.g. \"/blog\"). When set, redirect Locations\n * pointing at app-internal paths get prefixed so callers see e.g.\n * `Location: /blog/about` for `redirect(\"/about\")`. Mirrors Next.js's\n * `addPathPrefix(getURLFromRedirectError(err), basePath)` in app-render.tsx.\n * External URLs (those that resolve to a different origin than the request)\n * are left untouched.\n */\n basePath?: string;\n clearRequestContext: () => void;\n /**\n * Drains and returns Set-Cookie header values that were accumulated during\n * this render via cookies().set() / cookies().delete(). Appended to redirect\n * responses so an auth flow that does `cookies().set(\"session\", \"...\");\n * redirect(\"/\")` preserves the cookie on the 307. Mirrors Next.js's\n * `appendMutableCookies(headers, requestStore.mutableCookies)` in\n * app-render.tsx. Only applied to redirect responses to match Next.js;\n * the http-access-fallback path leaves cookies to the rendered boundary.\n */\n getAndClearPendingCookies?: () => string[];\n isRscRequest: boolean;\n middlewareContext?: { headers: Headers | null };\n renderFallbackPage?: (statusCode: number) => Promise<Response | null>;\n request: Request;\n specialError: AppPageSpecialError;\n};\n\ntype ProbeAppPageLayoutsResult = {\n response: Response | null;\n layoutFlags: LayoutFlags;\n};\n\nexport type LayoutClassificationOptions = {\n /** Build-time classifications from segment config or module graph, keyed by layout index. */\n buildTimeClassifications?: ReadonlyMap<number, \"static\" | \"dynamic\"> | null;\n /**\n * Per-layout classification reasons keyed by layout index. Requires\n * `VINEXT_DEBUG_CLASSIFICATION` at BOTH lifecycle points: at build time so\n * the plugin patches the `__VINEXT_CLASS_REASONS` dispatch stub, and at\n * runtime so the route object actually calls it. Setting the flag only at\n * runtime leaves the stub returning `null`, and every build-time classified\n * layout will fall through to `{ layer: \"no-classifier\" }` in the debug\n * channel. The hot path never reads this and the wire payload is unchanged.\n */\n buildTimeReasons?: ReadonlyMap<number, ClassificationReason> | null;\n /**\n * Emits one log line per layout with the classification reason, keyed by\n * layout ID. Set by the generator when `VINEXT_DEBUG_CLASSIFICATION` is\n * active. When undefined, the probe loop skips debug emission entirely.\n */\n debugClassification?: (layoutId: string, reason: ClassificationReason) => void;\n /** Maps layout index to its layout ID (e.g. \"layout:/blog\"). */\n getLayoutId: (layoutIndex: number) => string;\n /** Runs a function with isolated dynamic usage tracking per layout. */\n runWithIsolatedDynamicScope: <T>(fn: () => T) => Promise<{ result: T; dynamicDetected: boolean }>;\n};\n\ntype ProbeAppPageLayoutsOptions = {\n layoutCount: number;\n onLayoutError: (error: unknown, layoutIndex: number) => Promise<Response | null>;\n probeLayoutAt: (layoutIndex: number) => unknown;\n runWithSuppressedHookWarning<T>(probe: () => Promise<T>): Promise<T>;\n /** When provided, enables per-layout static/dynamic classification. */\n classification?: LayoutClassificationOptions | null;\n};\n\ntype ProbeAppPageComponentOptions = {\n awaitAsyncResult: boolean;\n onError: (error: unknown) => Promise<Response | null>;\n probePage: () => unknown;\n runWithSuppressedHookWarning<T>(probe: () => Promise<T>): Promise<T>;\n};\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return Boolean(\n value &&\n (typeof value === \"object\" || typeof value === \"function\") &&\n \"then\" in value &&\n typeof value.then === \"function\",\n );\n}\n\nfunction getAppPageStatusText(statusCode: number): string {\n return statusCode === 403 ? \"Forbidden\" : statusCode === 401 ? \"Unauthorized\" : \"Not Found\";\n}\n\nfunction mergeAppPageSpecialErrorHeaders(\n response: Response,\n middlewareContext: { headers: Headers | null } | undefined,\n): Response {\n const headers = new Headers(response.headers);\n mergeMiddlewareResponseHeaders(headers, middlewareContext?.headers ?? null);\n\n return new Response(response.body, {\n headers,\n status: response.status,\n statusText: response.statusText,\n });\n}\n\nexport function resolveAppPageSpecialError(error: unknown): AppPageSpecialError | null {\n if (!(error && typeof error === \"object\" && \"digest\" in error)) {\n return null;\n }\n\n const digest = String(error.digest);\n\n const redirect = parseNextRedirectDigest(digest);\n if (redirect) {\n return {\n kind: \"redirect\",\n location: redirect.url,\n statusCode: redirect.status,\n };\n }\n\n const httpError = parseNextHttpErrorDigest(digest);\n if (httpError) {\n return {\n kind: \"http-access-fallback\",\n statusCode: httpError.status,\n };\n }\n\n return null;\n}\n\n/**\n * Resolves a redirect() target against the request URL and prepends the\n * configured basePath when the target is an app-internal absolute path.\n *\n * Mirrors Next.js's `addPathPrefix(getURLFromRedirectError(err), basePath)`\n * in `app-render.tsx`: a `redirect(\"/about\")` call from a page mounted at\n * `/blog` (basePath) produces `Location: /blog/about`.\n *\n * Skips prefixing when:\n * - basePath is unset / empty\n * - the target is a full URL pointing at a different origin (external redirect)\n * - the target already starts with the basePath (caller did the work themselves)\n */\nfunction applyAppPageRedirectBasePath(\n location: string,\n requestUrl: string,\n basePath: string | undefined,\n): string {\n const resolved = new URL(location, requestUrl);\n const requestOrigin = new URL(requestUrl).origin;\n if (!basePath || resolved.origin !== requestOrigin) {\n return resolved.toString();\n }\n if (hasBasePath(resolved.pathname, basePath)) {\n return resolved.toString();\n }\n resolved.pathname = resolved.pathname === \"/\" ? basePath : `${basePath}${resolved.pathname}`;\n return resolved.toString();\n}\n\nexport async function buildAppPageSpecialErrorResponse(\n options: BuildAppPageSpecialErrorResponseOptions,\n): Promise<Response> {\n if (options.specialError.kind === \"redirect\") {\n options.clearRequestContext();\n // Apply configured basePath first so app-internal targets land at\n // /<basePath>/<target> before the RSC cache-busting transform sees them.\n const prefixedLocation = applyAppPageRedirectBasePath(\n options.specialError.location,\n options.request.url,\n options.basePath,\n );\n const location = options.isRscRequest\n ? await createRscRedirectLocation(prefixedLocation, options.request)\n : prefixedLocation;\n const headers = new Headers({\n Location: location,\n });\n // Middleware may contribute response headers here, but redirect() owns the\n // status. Do not apply middlewareContext.status on special-error responses.\n mergeMiddlewareResponseHeaders(headers, options.middlewareContext?.headers ?? null);\n // Preserve cookies set via cookies().set() / cookies().delete() during the\n // page render — auth flows commonly set a session cookie and immediately\n // redirect, and those Set-Cookie values must ride on the 307.\n const pendingCookies = options.getAndClearPendingCookies?.() ?? [];\n for (const cookie of pendingCookies) {\n headers.append(\"Set-Cookie\", cookie);\n }\n\n return new Response(null, {\n headers,\n status: options.specialError.statusCode,\n });\n }\n\n if (options.renderFallbackPage) {\n const fallbackResponse = await options.renderFallbackPage(options.specialError.statusCode);\n if (fallbackResponse) {\n return mergeAppPageSpecialErrorHeaders(fallbackResponse, options.middlewareContext);\n }\n }\n\n options.clearRequestContext();\n return mergeAppPageSpecialErrorHeaders(\n new Response(getAppPageStatusText(options.specialError.statusCode), {\n status: options.specialError.statusCode,\n }),\n options.middlewareContext,\n );\n}\n\n/** See `LayoutFlags` type docblock in app-elements.ts for lifecycle. */\nexport async function probeAppPageLayouts(\n options: ProbeAppPageLayoutsOptions,\n): Promise<ProbeAppPageLayoutsResult> {\n const layoutFlags: Record<string, \"s\" | \"d\"> = {};\n const cls = options.classification ?? null;\n\n const response = await options.runWithSuppressedHookWarning(async () => {\n for (let layoutIndex = options.layoutCount - 1; layoutIndex >= 0; layoutIndex--) {\n const buildTimeResult = cls?.buildTimeClassifications?.get(layoutIndex);\n\n if (cls && buildTimeResult) {\n // Build-time classified (Layer 1 or Layer 2): skip dynamic isolation,\n // but still probe for special errors (redirects, not-found).\n layoutFlags[cls.getLayoutId(layoutIndex)] = buildTimeResult === \"static\" ? \"s\" : \"d\";\n if (cls.debugClassification) {\n // `no-classifier` is the documented fallback for a layout that was\n // build-time classified but whose reason payload is absent — either\n // because the build was run without `VINEXT_DEBUG_CLASSIFICATION` or\n // because no Layer 1/2 classifier attached a reason. This is the sole\n // producer of the variant; see `layout-classification-types.ts`.\n cls.debugClassification(\n cls.getLayoutId(layoutIndex),\n cls.buildTimeReasons?.get(layoutIndex) ?? { layer: \"no-classifier\" },\n );\n }\n const errorResponse = await probeLayoutForErrors(options, layoutIndex);\n if (errorResponse) return errorResponse;\n continue;\n }\n\n if (cls) {\n // Layer 3: probe with isolated dynamic scope to detect per-layout\n // dynamic API usage (headers(), cookies(), connection(), etc.)\n try {\n const { dynamicDetected } = await cls.runWithIsolatedDynamicScope(() =>\n options.probeLayoutAt(layoutIndex),\n );\n layoutFlags[cls.getLayoutId(layoutIndex)] = dynamicDetected ? \"d\" : \"s\";\n if (cls.debugClassification) {\n cls.debugClassification(cls.getLayoutId(layoutIndex), {\n layer: \"runtime-probe\",\n outcome: dynamicDetected ? \"dynamic\" : \"static\",\n });\n }\n } catch (error) {\n // Probe failed — conservatively treat as dynamic.\n layoutFlags[cls.getLayoutId(layoutIndex)] = \"d\";\n if (cls.debugClassification) {\n cls.debugClassification(cls.getLayoutId(layoutIndex), {\n layer: \"runtime-probe\",\n outcome: \"dynamic\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n const errorResponse = await options.onLayoutError(error, layoutIndex);\n if (errorResponse) return errorResponse;\n }\n continue;\n }\n\n // No classification options — original behavior\n const errorResponse = await probeLayoutForErrors(options, layoutIndex);\n if (errorResponse) return errorResponse;\n }\n\n return null;\n });\n\n return { response, layoutFlags };\n}\n\nasync function probeLayoutForErrors(\n options: ProbeAppPageLayoutsOptions,\n layoutIndex: number,\n): Promise<Response | null> {\n try {\n const layoutResult = options.probeLayoutAt(layoutIndex);\n if (isPromiseLike(layoutResult)) {\n await layoutResult;\n }\n } catch (error) {\n return options.onLayoutError(error, layoutIndex);\n }\n return null;\n}\n\nexport async function probeAppPageComponent(\n options: ProbeAppPageComponentOptions,\n): Promise<Response | null> {\n return options.runWithSuppressedHookWarning(async () => {\n try {\n const pageResult = options.probePage();\n if (isPromiseLike(pageResult)) {\n if (options.awaitAsyncResult) {\n await pageResult;\n } else {\n void Promise.resolve(pageResult).catch(() => {});\n }\n }\n } catch (error) {\n return options.onError(error);\n }\n\n return null;\n });\n}\n\nexport async function readAppPageBinaryStream(\n stream: ReadableStream<Uint8Array>,\n): Promise<ArrayBuffer> {\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n let totalLength = 0;\n\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n chunks.push(value);\n totalLength += value.byteLength;\n }\n\n const buffer = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n buffer.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return buffer.buffer;\n}\n\nexport function teeAppPageRscStreamForCapture(\n stream: ReadableStream<Uint8Array>,\n shouldCapture: boolean,\n): AppPageRscStreamCapture {\n if (!shouldCapture) {\n return {\n ssrStream: stream,\n };\n }\n\n const [ssrStream, sideStream] = stream.tee();\n return {\n ssrStream,\n sideStream,\n };\n}\n\nexport function buildAppPageFontLinkHeader(\n preloads: readonly AppPageFontPreload[] | null | undefined,\n): string {\n if (!preloads || preloads.length === 0) {\n return \"\";\n }\n\n return preloads\n .map((preload) => `<${preload.href}>; rel=preload; as=font; type=${preload.type}; crossorigin`)\n .join(\", \");\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-page-execution.js","names":[],"sources":["../../src/server/app-page-execution.ts"],"sourcesContent":["import type { LayoutFlags } from \"./app-elements.js\";\nimport type { ClassificationReason } from \"../build/layout-classification-types.js\";\nimport { createRscRedirectLocation } from \"./app-rsc-cache-busting.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport { parseNextHttpErrorDigest, parseNextRedirectDigest } from \"./next-error-digest.js\";\nimport { addBasePathToPathname } from \"../utils/base-path.js\";\n\nexport type { LayoutFlags };\nexport type { ClassificationReason };\n\nexport type AppPageSpecialError =\n | { kind: \"redirect\"; location: string; statusCode: number }\n | { kind: \"http-access-fallback\"; statusCode: number };\n\nexport type AppPageFontPreload = {\n href: string;\n type: string;\n};\n\ntype AppPageRscStreamCapture = {\n /** Stream for createFromReadableStream (SSR). Always set. */\n ssrStream: ReadableStream<Uint8Array>;\n /** When capturing, the combined embed+capture stream. handleSsr consumes this. */\n sideStream?: ReadableStream<Uint8Array>;\n};\n\ntype BuildAppPageSpecialErrorResponseOptions = {\n /**\n * Optional configured basePath (e.g. \"/blog\"). When set, redirect Locations\n * pointing at app-internal paths get prefixed so callers see e.g.\n * `Location: /blog/about` for `redirect(\"/about\")`. Mirrors Next.js's\n * `addPathPrefix(getURLFromRedirectError(err), basePath)` in app-render.tsx.\n * External URLs (those that resolve to a different origin than the request)\n * are left untouched.\n */\n basePath?: string;\n clearRequestContext: () => void;\n /**\n * Drains and returns Set-Cookie header values that were accumulated during\n * this render via cookies().set() / cookies().delete(). Appended to redirect\n * responses so an auth flow that does `cookies().set(\"session\", \"...\");\n * redirect(\"/\")` preserves the cookie on the 307. Mirrors Next.js's\n * `appendMutableCookies(headers, requestStore.mutableCookies)` in\n * app-render.tsx. Only applied to redirect responses to match Next.js;\n * the http-access-fallback path leaves cookies to the rendered boundary.\n */\n getAndClearPendingCookies?: () => string[];\n isRscRequest: boolean;\n middlewareContext?: { headers: Headers | null };\n renderFallbackPage?: (statusCode: number) => Promise<Response | null>;\n request: Request;\n specialError: AppPageSpecialError;\n};\n\ntype ProbeAppPageLayoutsResult = {\n response: Response | null;\n layoutFlags: LayoutFlags;\n};\n\nexport type LayoutClassificationOptions = {\n /** Build-time classifications from segment config or module graph, keyed by layout index. */\n buildTimeClassifications?: ReadonlyMap<number, \"static\" | \"dynamic\"> | null;\n /**\n * Per-layout classification reasons keyed by layout index. Requires\n * `VINEXT_DEBUG_CLASSIFICATION` at BOTH lifecycle points: at build time so\n * the plugin patches the `__VINEXT_CLASS_REASONS` dispatch stub, and at\n * runtime so the route object actually calls it. Setting the flag only at\n * runtime leaves the stub returning `null`, and every build-time classified\n * layout will fall through to `{ layer: \"no-classifier\" }` in the debug\n * channel. The hot path never reads this and the wire payload is unchanged.\n */\n buildTimeReasons?: ReadonlyMap<number, ClassificationReason> | null;\n /**\n * Emits one log line per layout with the classification reason, keyed by\n * layout ID. Set by the generator when `VINEXT_DEBUG_CLASSIFICATION` is\n * active. When undefined, the probe loop skips debug emission entirely.\n */\n debugClassification?: (layoutId: string, reason: ClassificationReason) => void;\n /** Maps layout index to its layout ID (e.g. \"layout:/blog\"). */\n getLayoutId: (layoutIndex: number) => string;\n /** Runs a function with isolated dynamic usage tracking per layout. */\n runWithIsolatedDynamicScope: <T>(fn: () => T) => Promise<{ result: T; dynamicDetected: boolean }>;\n};\n\ntype ProbeAppPageLayoutsOptions = {\n layoutCount: number;\n onLayoutError: (error: unknown, layoutIndex: number) => Promise<Response | null>;\n probeLayoutAt: (layoutIndex: number) => unknown;\n runWithSuppressedHookWarning<T>(probe: () => Promise<T>): Promise<T>;\n /** When provided, enables per-layout static/dynamic classification. */\n classification?: LayoutClassificationOptions | null;\n};\n\ntype ProbeAppPageComponentOptions = {\n awaitAsyncResult: boolean;\n onError: (error: unknown) => Promise<Response | null>;\n probePage: () => unknown;\n runWithSuppressedHookWarning<T>(probe: () => Promise<T>): Promise<T>;\n};\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return Boolean(\n value &&\n (typeof value === \"object\" || typeof value === \"function\") &&\n \"then\" in value &&\n typeof value.then === \"function\",\n );\n}\n\nfunction getAppPageStatusText(statusCode: number): string {\n return statusCode === 403 ? \"Forbidden\" : statusCode === 401 ? \"Unauthorized\" : \"Not Found\";\n}\n\nfunction mergeAppPageSpecialErrorHeaders(\n response: Response,\n middlewareContext: { headers: Headers | null } | undefined,\n): Response {\n const headers = new Headers(response.headers);\n mergeMiddlewareResponseHeaders(headers, middlewareContext?.headers ?? null);\n\n return new Response(response.body, {\n headers,\n status: response.status,\n statusText: response.statusText,\n });\n}\n\nexport function resolveAppPageSpecialError(error: unknown): AppPageSpecialError | null {\n if (!(error && typeof error === \"object\" && \"digest\" in error)) {\n return null;\n }\n\n const digest = String(error.digest);\n\n const redirect = parseNextRedirectDigest(digest);\n if (redirect) {\n return {\n kind: \"redirect\",\n location: redirect.url,\n statusCode: redirect.status,\n };\n }\n\n const httpError = parseNextHttpErrorDigest(digest);\n if (httpError) {\n return {\n kind: \"http-access-fallback\",\n statusCode: httpError.status,\n };\n }\n\n return null;\n}\n\n/**\n * Resolves a redirect() target against the request URL and prepends the\n * configured basePath when the target is an app-internal absolute path.\n *\n * Mirrors Next.js's `addPathPrefix(getURLFromRedirectError(err), basePath)`\n * in `app-render.tsx`: a `redirect(\"/about\")` call from a page mounted at\n * `/blog` (basePath) produces `Location: /blog/about`.\n *\n * Skips prefixing when:\n * - basePath is unset / empty\n * - the target is a full URL pointing at a different origin (external redirect)\n * - the target already starts with the basePath (caller did the work themselves)\n */\nfunction applyAppPageRedirectBasePath(\n location: string,\n requestUrl: string,\n basePath: string | undefined,\n): string {\n const resolved = new URL(location, requestUrl);\n const requestOrigin = new URL(requestUrl).origin;\n if (!basePath || resolved.origin !== requestOrigin) {\n return resolved.toString();\n }\n resolved.pathname = addBasePathToPathname(resolved.pathname, basePath);\n return resolved.toString();\n}\n\nexport async function buildAppPageSpecialErrorResponse(\n options: BuildAppPageSpecialErrorResponseOptions,\n): Promise<Response> {\n if (options.specialError.kind === \"redirect\") {\n options.clearRequestContext();\n // Apply configured basePath first so app-internal targets land at\n // /<basePath>/<target> before the RSC cache-busting transform sees them.\n const prefixedLocation = applyAppPageRedirectBasePath(\n options.specialError.location,\n options.request.url,\n options.basePath,\n );\n const location = options.isRscRequest\n ? await createRscRedirectLocation(prefixedLocation, options.request)\n : prefixedLocation;\n const headers = new Headers({\n Location: location,\n });\n // Middleware may contribute response headers here, but redirect() owns the\n // status. Do not apply middlewareContext.status on special-error responses.\n mergeMiddlewareResponseHeaders(headers, options.middlewareContext?.headers ?? null);\n // Preserve cookies set via cookies().set() / cookies().delete() during the\n // page render — auth flows commonly set a session cookie and immediately\n // redirect, and those Set-Cookie values must ride on the 307.\n const pendingCookies = options.getAndClearPendingCookies?.() ?? [];\n for (const cookie of pendingCookies) {\n headers.append(\"Set-Cookie\", cookie);\n }\n\n return new Response(null, {\n headers,\n status: options.specialError.statusCode,\n });\n }\n\n if (options.renderFallbackPage) {\n const fallbackResponse = await options.renderFallbackPage(options.specialError.statusCode);\n if (fallbackResponse) {\n return mergeAppPageSpecialErrorHeaders(fallbackResponse, options.middlewareContext);\n }\n }\n\n options.clearRequestContext();\n return mergeAppPageSpecialErrorHeaders(\n new Response(getAppPageStatusText(options.specialError.statusCode), {\n status: options.specialError.statusCode,\n }),\n options.middlewareContext,\n );\n}\n\n/** See `LayoutFlags` type docblock in app-elements.ts for lifecycle. */\nexport async function probeAppPageLayouts(\n options: ProbeAppPageLayoutsOptions,\n): Promise<ProbeAppPageLayoutsResult> {\n const layoutFlags: Record<string, \"s\" | \"d\"> = {};\n const cls = options.classification ?? null;\n\n const response = await options.runWithSuppressedHookWarning(async () => {\n for (let layoutIndex = options.layoutCount - 1; layoutIndex >= 0; layoutIndex--) {\n const buildTimeResult = cls?.buildTimeClassifications?.get(layoutIndex);\n\n if (cls && buildTimeResult) {\n // Build-time classified (Layer 1 or Layer 2): skip dynamic isolation,\n // but still probe for special errors (redirects, not-found).\n layoutFlags[cls.getLayoutId(layoutIndex)] = buildTimeResult === \"static\" ? \"s\" : \"d\";\n if (cls.debugClassification) {\n // `no-classifier` is the documented fallback for a layout that was\n // build-time classified but whose reason payload is absent — either\n // because the build was run without `VINEXT_DEBUG_CLASSIFICATION` or\n // because no Layer 1/2 classifier attached a reason. This is the sole\n // producer of the variant; see `layout-classification-types.ts`.\n cls.debugClassification(\n cls.getLayoutId(layoutIndex),\n cls.buildTimeReasons?.get(layoutIndex) ?? { layer: \"no-classifier\" },\n );\n }\n const errorResponse = await probeLayoutForErrors(options, layoutIndex);\n if (errorResponse) return errorResponse;\n continue;\n }\n\n if (cls) {\n // Layer 3: probe with isolated dynamic scope to detect per-layout\n // dynamic API usage (headers(), cookies(), connection(), etc.)\n try {\n const { dynamicDetected } = await cls.runWithIsolatedDynamicScope(() =>\n options.probeLayoutAt(layoutIndex),\n );\n layoutFlags[cls.getLayoutId(layoutIndex)] = dynamicDetected ? \"d\" : \"s\";\n if (cls.debugClassification) {\n cls.debugClassification(cls.getLayoutId(layoutIndex), {\n layer: \"runtime-probe\",\n outcome: dynamicDetected ? \"dynamic\" : \"static\",\n });\n }\n } catch (error) {\n // Probe failed — conservatively treat as dynamic.\n layoutFlags[cls.getLayoutId(layoutIndex)] = \"d\";\n if (cls.debugClassification) {\n cls.debugClassification(cls.getLayoutId(layoutIndex), {\n layer: \"runtime-probe\",\n outcome: \"dynamic\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n const errorResponse = await options.onLayoutError(error, layoutIndex);\n if (errorResponse) return errorResponse;\n }\n continue;\n }\n\n // No classification options — original behavior\n const errorResponse = await probeLayoutForErrors(options, layoutIndex);\n if (errorResponse) return errorResponse;\n }\n\n return null;\n });\n\n return { response, layoutFlags };\n}\n\nasync function probeLayoutForErrors(\n options: ProbeAppPageLayoutsOptions,\n layoutIndex: number,\n): Promise<Response | null> {\n try {\n const layoutResult = options.probeLayoutAt(layoutIndex);\n if (isPromiseLike(layoutResult)) {\n await layoutResult;\n }\n } catch (error) {\n return options.onLayoutError(error, layoutIndex);\n }\n return null;\n}\n\nexport async function probeAppPageComponent(\n options: ProbeAppPageComponentOptions,\n): Promise<Response | null> {\n return options.runWithSuppressedHookWarning(async () => {\n try {\n const pageResult = options.probePage();\n if (isPromiseLike(pageResult)) {\n if (options.awaitAsyncResult) {\n await pageResult;\n } else {\n void Promise.resolve(pageResult).catch(() => {});\n }\n }\n } catch (error) {\n return options.onError(error);\n }\n\n return null;\n });\n}\n\nexport async function readAppPageBinaryStream(\n stream: ReadableStream<Uint8Array>,\n): Promise<ArrayBuffer> {\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n let totalLength = 0;\n\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n chunks.push(value);\n totalLength += value.byteLength;\n }\n\n const buffer = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n buffer.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return buffer.buffer;\n}\n\nexport function teeAppPageRscStreamForCapture(\n stream: ReadableStream<Uint8Array>,\n shouldCapture: boolean,\n): AppPageRscStreamCapture {\n if (!shouldCapture) {\n return {\n ssrStream: stream,\n };\n }\n\n const [ssrStream, sideStream] = stream.tee();\n return {\n ssrStream,\n sideStream,\n };\n}\n\nexport function buildAppPageFontLinkHeader(\n preloads: readonly AppPageFontPreload[] | null | undefined,\n): string {\n if (!preloads || preloads.length === 0) {\n return \"\";\n }\n\n return preloads\n .map((preload) => `<${preload.href}>; rel=preload; as=font; type=${preload.type}; crossorigin`)\n .join(\", \");\n}\n"],"mappings":"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"}
|
|
@@ -26,6 +26,13 @@ type ResolveActiveParallelRouteHeadInputsOptions<TModule extends AppPageHeadModu
|
|
|
26
26
|
slots?: Record<string, AppPageHeadSlot<TModule>> | null;
|
|
27
27
|
};
|
|
28
28
|
type ResolveAppPageHeadOptions<TModule extends AppPageHeadModule = AppPageHeadModule> = {
|
|
29
|
+
/**
|
|
30
|
+
* Configured next.config `basePath`. Threaded into `applyFileBasedMetadata`
|
|
31
|
+
* so file-based metadata route URLs (icon, opengraph-image, manifest, ...)
|
|
32
|
+
* emitted in <head> are prefixed with the basePath. Empty string when no
|
|
33
|
+
* basePath is configured.
|
|
34
|
+
*/
|
|
35
|
+
basePath?: string;
|
|
29
36
|
fallbackOnFileMetadataError?: boolean;
|
|
30
37
|
layoutModules: readonly (TModule | null | undefined)[];
|
|
31
38
|
layoutTreePositions?: readonly number[] | null;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { runWithFetchDedupe } from "../shims/fetch-cache.js";
|
|
1
2
|
import { mergeMetadataEntries, mergeViewport, postProcessMetadata, resolveModuleMetadata, resolveModuleViewport } from "../shims/metadata.js";
|
|
2
3
|
import { resolveAppPageSegmentParams } from "./app-page-params.js";
|
|
3
4
|
import { applyFileBasedMetadata } from "./file-based-metadata.js";
|
|
@@ -130,6 +131,9 @@ async function resolveParallelRouteHead(parallelRoute, fallbackParams, fallbackR
|
|
|
130
131
|
};
|
|
131
132
|
}
|
|
132
133
|
async function resolveAppPageHead(options) {
|
|
134
|
+
return await runWithFetchDedupe(() => resolveAppPageHeadInner(options));
|
|
135
|
+
}
|
|
136
|
+
async function resolveAppPageHeadInner(options) {
|
|
133
137
|
const routeSegments = options.routeSegments ?? [];
|
|
134
138
|
const layoutTreePositions = options.layoutTreePositions ?? [];
|
|
135
139
|
const layoutInputs = createLayoutInputs(options.layoutModules, layoutTreePositions);
|
|
@@ -177,7 +181,8 @@ async function resolveAppPageHead(options) {
|
|
|
177
181
|
try {
|
|
178
182
|
metadata = await applyFileBasedMetadata(resolvedMetadataBase, options.routePath, options.params, options.metadataRoutes, {
|
|
179
183
|
routeSegments,
|
|
180
|
-
metadataSources
|
|
184
|
+
metadataSources,
|
|
185
|
+
basePath: options.basePath ?? ""
|
|
181
186
|
});
|
|
182
187
|
} catch (error) {
|
|
183
188
|
if (!options.fallbackOnFileMetadataError) throw error;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-page-head.js","names":[],"sources":["../../src/server/app-page-head.ts"],"sourcesContent":["import {\n mergeMetadataEntries,\n mergeViewport,\n postProcessMetadata,\n resolveModuleMetadata,\n resolveModuleViewport,\n type Metadata,\n type MetadataMergeEntry,\n type Viewport,\n} from \"vinext/shims/metadata\";\nimport { applyFileBasedMetadata } from \"./file-based-metadata.js\";\nimport type { AppPageParams } from \"./app-page-boundary.js\";\nimport { resolveAppPageSegmentParams } from \"./app-page-params.js\";\nimport type { MetadataFileRoute } from \"./metadata-routes.js\";\n\ntype AppPageSearchParams = Record<string, string | string[]>;\n\ntype AppPageHeadModule = Record<string, unknown>;\n\ntype AppPageHeadSource = {\n metadata: Metadata | null;\n routeSegments: readonly string[];\n};\n\ntype AppPageHeadLayout<TModule extends AppPageHeadModule> = {\n module: TModule;\n treePosition: number;\n};\n\ntype AppPageHeadParallelRoute<TModule extends AppPageHeadModule = AppPageHeadModule> = {\n layoutModule?: TModule | null;\n layoutModules?: readonly (TModule | null | undefined)[] | null;\n pageModule?: TModule | null;\n params?: AppPageParams | null;\n routeSegments?: readonly string[] | null;\n};\n\ntype AppPageHeadSlot<TModule extends AppPageHeadModule = AppPageHeadModule> = {\n layout?: TModule | null;\n page?: TModule | null;\n};\n\ntype ResolveActiveParallelRouteHeadInputsOptions<\n TModule extends AppPageHeadModule = AppPageHeadModule,\n> = {\n interceptLayouts?: readonly (TModule | null | undefined)[] | null;\n interceptPage?: TModule | null;\n interceptParams?: AppPageParams | null;\n interceptSlotKey?: string | null;\n params: AppPageParams;\n routeSegments: readonly string[];\n slots?: Record<string, AppPageHeadSlot<TModule>> | null;\n};\n\ntype ResolveAppPageHeadOptions<TModule extends AppPageHeadModule = AppPageHeadModule> = {\n fallbackOnFileMetadataError?: boolean;\n layoutModules: readonly (TModule | null | undefined)[];\n layoutTreePositions?: readonly number[] | null;\n metadataRoutes: readonly MetadataFileRoute[];\n pageModule?: TModule | null;\n parallelRoutes?: readonly AppPageHeadParallelRoute<TModule>[] | null;\n params: AppPageParams;\n routePath: string;\n routeSegments?: readonly string[] | null;\n searchParams?: URLSearchParams | null;\n};\n\ntype ResolveAppPageHeadResult = {\n hasSearchParams: boolean;\n metadata: Metadata | null;\n pageSearchParams: AppPageSearchParams;\n viewport: Viewport;\n};\n\ntype AppPageSearchParamsCollection = {\n hasSearchParams: boolean;\n pageSearchParams: AppPageSearchParams;\n};\n\ntype ResolvedParallelRouteHead = {\n metadataResults: (Metadata | null)[];\n metadataSources: AppPageHeadSource[];\n viewportResults: (Viewport | null)[];\n};\n\nexport function resolveActiveParallelRouteHeadInputs<TModule extends AppPageHeadModule>(\n options: ResolveActiveParallelRouteHeadInputsOptions<TModule>,\n): AppPageHeadParallelRoute<TModule>[] {\n return Object.entries(options.slots ?? {}).map(([slotKey, slot]) => {\n if (options.interceptSlotKey === slotKey && options.interceptPage) {\n return {\n layoutModules: options.interceptLayouts ?? [],\n pageModule: options.interceptPage,\n params: options.interceptParams ?? options.params,\n routeSegments: options.routeSegments,\n };\n }\n\n return {\n layoutModules: slot.layout ? [slot.layout] : [],\n pageModule: slot.page,\n params: options.params,\n routeSegments: options.routeSegments,\n };\n });\n}\n\nfunction isPresent<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined;\n}\n\nexport function collectAppPageSearchParams(\n searchParams: URLSearchParams | null | undefined,\n): AppPageSearchParamsCollection {\n const pageSearchParams: AppPageSearchParams = Object.create(null);\n let hasSearchParams = false;\n\n searchParams?.forEach((value, key) => {\n hasSearchParams = true;\n const currentValue = pageSearchParams[key];\n if (Array.isArray(currentValue)) {\n pageSearchParams[key] = [...currentValue, value];\n return;\n }\n if (currentValue !== undefined) {\n pageSearchParams[key] = [currentValue, value];\n return;\n }\n pageSearchParams[key] = value;\n });\n\n return { hasSearchParams, pageSearchParams };\n}\n\nfunction createMetadataSources(\n metadataResults: readonly (Metadata | null)[],\n routeSegments: readonly string[],\n layoutTreePositions: readonly number[],\n pageMetadata: Metadata | null,\n includePageSource: boolean,\n): AppPageHeadSource[] {\n const metadataSources: AppPageHeadSource[] = metadataResults.map((metadata, index) => ({\n routeSegments: routeSegments.slice(0, layoutTreePositions[index] ?? 0),\n metadata,\n }));\n\n if (includePageSource) {\n metadataSources.push({\n routeSegments,\n metadata: pageMetadata,\n });\n }\n\n return metadataSources;\n}\n\nfunction createLayoutInputs<TModule extends AppPageHeadModule>(\n layoutModules: readonly (TModule | null | undefined)[],\n layoutTreePositions: readonly number[],\n): AppPageHeadLayout<TModule>[] {\n const layoutInputs: AppPageHeadLayout<TModule>[] = [];\n\n for (let index = 0; index < layoutModules.length; index++) {\n const layoutModule = layoutModules[index];\n if (!isPresent(layoutModule)) {\n continue;\n }\n layoutInputs.push({\n module: layoutModule,\n treePosition: layoutTreePositions[index] ?? 0,\n });\n }\n\n return layoutInputs;\n}\n\nasync function resolveLayoutMetadata<TModule extends AppPageHeadModule>(\n layoutInputs: readonly AppPageHeadLayout<TModule>[],\n params: AppPageParams,\n routeSegments: readonly string[],\n): Promise<(Metadata | null)[]> {\n const layoutMetadataPromises: Promise<Metadata | null>[] = [];\n let accumulatedMetadata = Promise.resolve<Metadata>({});\n\n for (const layoutInput of layoutInputs) {\n const parentForLayout = accumulatedMetadata;\n const layoutParams = resolveAppPageSegmentParams(\n routeSegments,\n layoutInput.treePosition,\n params,\n );\n const metadataPromise = resolveModuleMetadata(\n layoutInput.module,\n layoutParams,\n undefined,\n parentForLayout,\n );\n layoutMetadataPromises.push(metadataPromise);\n void metadataPromise.catch(() => null);\n\n accumulatedMetadata = metadataPromise.then(async (metadataResult) => {\n if (metadataResult) {\n return mergeMetadataEntries([\n { metadata: await parentForLayout },\n { metadata: metadataResult },\n ]);\n }\n return parentForLayout;\n });\n void accumulatedMetadata.catch(() => null);\n }\n\n return Promise.all(layoutMetadataPromises);\n}\n\nasync function resolveLayoutViewport<TModule extends AppPageHeadModule>(\n layoutInputs: readonly AppPageHeadLayout<TModule>[],\n params: AppPageParams,\n routeSegments: readonly string[],\n): Promise<(Viewport | null)[]> {\n return Promise.all(\n layoutInputs.map((layoutInput) => {\n const layoutParams = resolveAppPageSegmentParams(\n routeSegments,\n layoutInput.treePosition,\n params,\n );\n return resolveModuleViewport(layoutInput.module, layoutParams);\n }),\n );\n}\n\nasync function resolveParallelRouteHead<TModule extends AppPageHeadModule>(\n parallelRoute: AppPageHeadParallelRoute<TModule>,\n fallbackParams: AppPageParams,\n fallbackRouteSegments: readonly string[],\n pageSearchParams: AppPageSearchParams,\n parent: Promise<Metadata>,\n): Promise<ResolvedParallelRouteHead> {\n const params = parallelRoute.params ?? fallbackParams;\n const routeSegments = parallelRoute.routeSegments ?? fallbackRouteSegments;\n const metadataResults: (Metadata | null)[] = [];\n const viewportResults: (Viewport | null)[] = [];\n const metadataSources: AppPageHeadSource[] = [];\n let accumulatedMetadata = parent;\n const layoutModules = [...(parallelRoute.layoutModules ?? []), parallelRoute.layoutModule].filter(\n isPresent,\n );\n const layoutViewportPromises = layoutModules.map((layoutModule) =>\n resolveModuleViewport(layoutModule, params),\n );\n const pageViewportPromise = parallelRoute.pageModule\n ? resolveModuleViewport(parallelRoute.pageModule, params)\n : Promise.resolve(null);\n for (const layoutViewportPromise of layoutViewportPromises) {\n void layoutViewportPromise.catch(() => null);\n }\n void pageViewportPromise.catch(() => null);\n\n for (const layoutModule of layoutModules) {\n const layoutMetadata = await resolveModuleMetadata(\n layoutModule,\n params,\n undefined,\n accumulatedMetadata,\n );\n metadataResults.push(layoutMetadata);\n // Parallel route metadata sources are scoped to the active slot branch because\n // the route tree input does not carry per-layout segment positions inside that branch.\n metadataSources.push({ metadata: layoutMetadata, routeSegments });\n if (layoutMetadata) {\n const parentForLayout = accumulatedMetadata;\n accumulatedMetadata = parentForLayout.then(async (parentMetadata) =>\n mergeMetadataEntries([{ metadata: parentMetadata }, { metadata: layoutMetadata }]),\n );\n void accumulatedMetadata.catch(() => null);\n }\n }\n\n if (parallelRoute.pageModule) {\n const pageMetadata = await resolveModuleMetadata(\n parallelRoute.pageModule,\n params,\n pageSearchParams,\n accumulatedMetadata,\n );\n metadataResults.push(pageMetadata);\n // Keep the page source scoped to the same active slot branch as its layouts.\n metadataSources.push({ metadata: pageMetadata, routeSegments });\n }\n\n viewportResults.push(...(await Promise.all(layoutViewportPromises)));\n const pageViewport = await pageViewportPromise;\n if (parallelRoute.pageModule) {\n viewportResults.push(pageViewport);\n }\n\n return { metadataResults, metadataSources, viewportResults };\n}\n\nexport async function resolveAppPageHead<TModule extends AppPageHeadModule>(\n options: ResolveAppPageHeadOptions<TModule>,\n): Promise<ResolveAppPageHeadResult> {\n const routeSegments = options.routeSegments ?? [];\n const layoutTreePositions = options.layoutTreePositions ?? [];\n const layoutInputs = createLayoutInputs(options.layoutModules, layoutTreePositions);\n const layoutSourcePositions = layoutInputs.map((input) => input.treePosition);\n const { hasSearchParams, pageSearchParams } = collectAppPageSearchParams(options.searchParams);\n const layoutMetadataPromise = resolveLayoutMetadata(layoutInputs, options.params, routeSegments);\n const layoutViewportPromise = resolveLayoutViewport(layoutInputs, options.params, routeSegments);\n\n const layoutMetadataResultsForParent = layoutMetadataPromise.then((metadataResults) =>\n metadataResults.filter(isPresent),\n );\n void layoutMetadataResultsForParent.catch(() => null);\n const pageParentPromise = layoutMetadataResultsForParent.then((metadataResults) =>\n metadataResults.length > 0\n ? mergeMetadataEntries(metadataResults.map((metadata) => ({ metadata })))\n : {},\n );\n void pageParentPromise.catch(() => null);\n const pageMetadataPromise = options.pageModule\n ? resolveModuleMetadata(options.pageModule, options.params, pageSearchParams, pageParentPromise)\n : Promise.resolve(null);\n const pageViewportPromise = options.pageModule\n ? resolveModuleViewport(options.pageModule, options.params)\n : Promise.resolve(null);\n const parallelRouteHeadPromise = Promise.all(\n (options.parallelRoutes ?? []).map((parallelRoute) =>\n resolveParallelRouteHead(\n parallelRoute,\n options.params,\n routeSegments,\n pageSearchParams,\n pageParentPromise,\n ),\n ),\n );\n\n const [\n layoutMetadataResults,\n layoutViewportResults,\n pageMetadata,\n pageViewport,\n parallelRouteHeads,\n ] = await Promise.all([\n layoutMetadataPromise,\n layoutViewportPromise,\n pageMetadataPromise,\n pageViewportPromise,\n parallelRouteHeadPromise,\n ]);\n const parallelMetadataResults = parallelRouteHeads.flatMap((head) => head.metadataResults);\n const parallelViewportResults = parallelRouteHeads.flatMap((head) => head.viewportResults);\n const parallelMetadataSources = parallelRouteHeads.flatMap((head) => head.metadataSources);\n\n const metadataEntries: MetadataMergeEntry[] = [\n ...layoutMetadataResults.filter(isPresent).map((metadata) => ({ metadata })),\n ...(pageMetadata ? [{ isPage: true, metadata: pageMetadata }] : []),\n ...parallelMetadataResults\n .filter(isPresent)\n .map((metadata) => ({ contributesTitle: false, metadata })),\n ];\n const viewportList = [\n ...layoutViewportResults.filter(isPresent),\n ...(pageViewport ? [pageViewport] : []),\n ...parallelViewportResults.filter(isPresent),\n ];\n\n const resolvedMetadataBase =\n metadataEntries.length > 0 ? mergeMetadataEntries(metadataEntries) : null;\n const metadataSources = createMetadataSources(\n layoutMetadataResults,\n routeSegments,\n layoutSourcePositions,\n pageMetadata,\n Boolean(options.pageModule),\n );\n metadataSources.push(...parallelMetadataSources);\n let metadata = resolvedMetadataBase;\n\n try {\n metadata = await applyFileBasedMetadata(\n resolvedMetadataBase,\n options.routePath,\n options.params,\n options.metadataRoutes,\n {\n routeSegments,\n metadataSources,\n },\n );\n } catch (error) {\n if (!options.fallbackOnFileMetadataError) {\n throw error;\n }\n console.error(\n `[vinext] File-based metadata resolution failed while rendering error boundary for ${options.routePath}:`,\n error,\n );\n }\n\n if (metadata) {\n metadata = postProcessMetadata(metadata);\n }\n\n return {\n hasSearchParams,\n metadata,\n pageSearchParams,\n viewport: mergeViewport(viewportList),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-page-head.js","names":["parentForLayout"],"sources":["../../src/server/app-page-head.ts"],"sourcesContent":["import {\n mergeMetadataEntries,\n mergeViewport,\n postProcessMetadata,\n resolveModuleMetadata,\n resolveModuleViewport,\n type Metadata,\n type MetadataMergeEntry,\n type Viewport,\n} from \"vinext/shims/metadata\";\nimport { runWithFetchDedupe } from \"vinext/shims/fetch-cache\";\nimport { applyFileBasedMetadata } from \"./file-based-metadata.js\";\nimport type { AppPageParams } from \"./app-page-boundary.js\";\nimport { resolveAppPageSegmentParams } from \"./app-page-params.js\";\nimport type { MetadataFileRoute } from \"./metadata-routes.js\";\n\ntype AppPageSearchParams = Record<string, string | string[]>;\n\ntype AppPageHeadModule = Record<string, unknown>;\n\ntype AppPageHeadSource = {\n metadata: Metadata | null;\n routeSegments: readonly string[];\n};\n\ntype AppPageHeadLayout<TModule extends AppPageHeadModule> = {\n module: TModule;\n treePosition: number;\n};\n\ntype AppPageHeadParallelRoute<TModule extends AppPageHeadModule = AppPageHeadModule> = {\n layoutModule?: TModule | null;\n layoutModules?: readonly (TModule | null | undefined)[] | null;\n pageModule?: TModule | null;\n params?: AppPageParams | null;\n routeSegments?: readonly string[] | null;\n};\n\ntype AppPageHeadSlot<TModule extends AppPageHeadModule = AppPageHeadModule> = {\n layout?: TModule | null;\n page?: TModule | null;\n};\n\ntype ResolveActiveParallelRouteHeadInputsOptions<\n TModule extends AppPageHeadModule = AppPageHeadModule,\n> = {\n interceptLayouts?: readonly (TModule | null | undefined)[] | null;\n interceptPage?: TModule | null;\n interceptParams?: AppPageParams | null;\n interceptSlotKey?: string | null;\n params: AppPageParams;\n routeSegments: readonly string[];\n slots?: Record<string, AppPageHeadSlot<TModule>> | null;\n};\n\ntype ResolveAppPageHeadOptions<TModule extends AppPageHeadModule = AppPageHeadModule> = {\n /**\n * Configured next.config `basePath`. Threaded into `applyFileBasedMetadata`\n * so file-based metadata route URLs (icon, opengraph-image, manifest, ...)\n * emitted in <head> are prefixed with the basePath. Empty string when no\n * basePath is configured.\n */\n basePath?: string;\n fallbackOnFileMetadataError?: boolean;\n layoutModules: readonly (TModule | null | undefined)[];\n layoutTreePositions?: readonly number[] | null;\n metadataRoutes: readonly MetadataFileRoute[];\n pageModule?: TModule | null;\n parallelRoutes?: readonly AppPageHeadParallelRoute<TModule>[] | null;\n params: AppPageParams;\n routePath: string;\n routeSegments?: readonly string[] | null;\n searchParams?: URLSearchParams | null;\n};\n\ntype ResolveAppPageHeadResult = {\n hasSearchParams: boolean;\n metadata: Metadata | null;\n pageSearchParams: AppPageSearchParams;\n viewport: Viewport;\n};\n\ntype AppPageSearchParamsCollection = {\n hasSearchParams: boolean;\n pageSearchParams: AppPageSearchParams;\n};\n\ntype ResolvedParallelRouteHead = {\n metadataResults: (Metadata | null)[];\n metadataSources: AppPageHeadSource[];\n viewportResults: (Viewport | null)[];\n};\n\nexport function resolveActiveParallelRouteHeadInputs<TModule extends AppPageHeadModule>(\n options: ResolveActiveParallelRouteHeadInputsOptions<TModule>,\n): AppPageHeadParallelRoute<TModule>[] {\n return Object.entries(options.slots ?? {}).map(([slotKey, slot]) => {\n if (options.interceptSlotKey === slotKey && options.interceptPage) {\n return {\n layoutModules: options.interceptLayouts ?? [],\n pageModule: options.interceptPage,\n params: options.interceptParams ?? options.params,\n routeSegments: options.routeSegments,\n };\n }\n\n return {\n layoutModules: slot.layout ? [slot.layout] : [],\n pageModule: slot.page,\n params: options.params,\n routeSegments: options.routeSegments,\n };\n });\n}\n\nfunction isPresent<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined;\n}\n\nexport function collectAppPageSearchParams(\n searchParams: URLSearchParams | null | undefined,\n): AppPageSearchParamsCollection {\n const pageSearchParams: AppPageSearchParams = Object.create(null);\n let hasSearchParams = false;\n\n searchParams?.forEach((value, key) => {\n hasSearchParams = true;\n const currentValue = pageSearchParams[key];\n if (Array.isArray(currentValue)) {\n pageSearchParams[key] = [...currentValue, value];\n return;\n }\n if (currentValue !== undefined) {\n pageSearchParams[key] = [currentValue, value];\n return;\n }\n pageSearchParams[key] = value;\n });\n\n return { hasSearchParams, pageSearchParams };\n}\n\nfunction createMetadataSources(\n metadataResults: readonly (Metadata | null)[],\n routeSegments: readonly string[],\n layoutTreePositions: readonly number[],\n pageMetadata: Metadata | null,\n includePageSource: boolean,\n): AppPageHeadSource[] {\n const metadataSources: AppPageHeadSource[] = metadataResults.map((metadata, index) => ({\n routeSegments: routeSegments.slice(0, layoutTreePositions[index] ?? 0),\n metadata,\n }));\n\n if (includePageSource) {\n metadataSources.push({\n routeSegments,\n metadata: pageMetadata,\n });\n }\n\n return metadataSources;\n}\n\nfunction createLayoutInputs<TModule extends AppPageHeadModule>(\n layoutModules: readonly (TModule | null | undefined)[],\n layoutTreePositions: readonly number[],\n): AppPageHeadLayout<TModule>[] {\n const layoutInputs: AppPageHeadLayout<TModule>[] = [];\n\n for (let index = 0; index < layoutModules.length; index++) {\n const layoutModule = layoutModules[index];\n if (!isPresent(layoutModule)) {\n continue;\n }\n layoutInputs.push({\n module: layoutModule,\n treePosition: layoutTreePositions[index] ?? 0,\n });\n }\n\n return layoutInputs;\n}\n\nasync function resolveLayoutMetadata<TModule extends AppPageHeadModule>(\n layoutInputs: readonly AppPageHeadLayout<TModule>[],\n params: AppPageParams,\n routeSegments: readonly string[],\n): Promise<(Metadata | null)[]> {\n const layoutMetadataPromises: Promise<Metadata | null>[] = [];\n let accumulatedMetadata = Promise.resolve<Metadata>({});\n\n for (const layoutInput of layoutInputs) {\n const parentForLayout = accumulatedMetadata;\n const layoutParams = resolveAppPageSegmentParams(\n routeSegments,\n layoutInput.treePosition,\n params,\n );\n const metadataPromise = resolveModuleMetadata(\n layoutInput.module,\n layoutParams,\n undefined,\n parentForLayout,\n );\n layoutMetadataPromises.push(metadataPromise);\n void metadataPromise.catch(() => null);\n\n accumulatedMetadata = metadataPromise.then(async (metadataResult) => {\n if (metadataResult) {\n return mergeMetadataEntries([\n { metadata: await parentForLayout },\n { metadata: metadataResult },\n ]);\n }\n return parentForLayout;\n });\n void accumulatedMetadata.catch(() => null);\n }\n\n return Promise.all(layoutMetadataPromises);\n}\n\nasync function resolveLayoutViewport<TModule extends AppPageHeadModule>(\n layoutInputs: readonly AppPageHeadLayout<TModule>[],\n params: AppPageParams,\n routeSegments: readonly string[],\n): Promise<(Viewport | null)[]> {\n return Promise.all(\n layoutInputs.map((layoutInput) => {\n const layoutParams = resolveAppPageSegmentParams(\n routeSegments,\n layoutInput.treePosition,\n params,\n );\n return resolveModuleViewport(layoutInput.module, layoutParams);\n }),\n );\n}\n\nasync function resolveParallelRouteHead<TModule extends AppPageHeadModule>(\n parallelRoute: AppPageHeadParallelRoute<TModule>,\n fallbackParams: AppPageParams,\n fallbackRouteSegments: readonly string[],\n pageSearchParams: AppPageSearchParams,\n parent: Promise<Metadata>,\n): Promise<ResolvedParallelRouteHead> {\n const params = parallelRoute.params ?? fallbackParams;\n const routeSegments = parallelRoute.routeSegments ?? fallbackRouteSegments;\n const metadataResults: (Metadata | null)[] = [];\n const viewportResults: (Viewport | null)[] = [];\n const metadataSources: AppPageHeadSource[] = [];\n let accumulatedMetadata = parent;\n const layoutModules = [...(parallelRoute.layoutModules ?? []), parallelRoute.layoutModule].filter(\n isPresent,\n );\n const layoutViewportPromises = layoutModules.map((layoutModule) =>\n resolveModuleViewport(layoutModule, params),\n );\n const pageViewportPromise = parallelRoute.pageModule\n ? resolveModuleViewport(parallelRoute.pageModule, params)\n : Promise.resolve(null);\n for (const layoutViewportPromise of layoutViewportPromises) {\n void layoutViewportPromise.catch(() => null);\n }\n void pageViewportPromise.catch(() => null);\n\n for (const layoutModule of layoutModules) {\n const layoutMetadata = await resolveModuleMetadata(\n layoutModule,\n params,\n undefined,\n accumulatedMetadata,\n );\n metadataResults.push(layoutMetadata);\n // Parallel route metadata sources are scoped to the active slot branch because\n // the route tree input does not carry per-layout segment positions inside that branch.\n metadataSources.push({ metadata: layoutMetadata, routeSegments });\n if (layoutMetadata) {\n const parentForLayout = accumulatedMetadata;\n accumulatedMetadata = parentForLayout.then(async (parentMetadata) =>\n mergeMetadataEntries([{ metadata: parentMetadata }, { metadata: layoutMetadata }]),\n );\n void accumulatedMetadata.catch(() => null);\n }\n }\n\n if (parallelRoute.pageModule) {\n const pageMetadata = await resolveModuleMetadata(\n parallelRoute.pageModule,\n params,\n pageSearchParams,\n accumulatedMetadata,\n );\n metadataResults.push(pageMetadata);\n // Keep the page source scoped to the same active slot branch as its layouts.\n metadataSources.push({ metadata: pageMetadata, routeSegments });\n }\n\n viewportResults.push(...(await Promise.all(layoutViewportPromises)));\n const pageViewport = await pageViewportPromise;\n if (parallelRoute.pageModule) {\n viewportResults.push(pageViewport);\n }\n\n return { metadataResults, metadataSources, viewportResults };\n}\n\nexport async function resolveAppPageHead<TModule extends AppPageHeadModule>(\n options: ResolveAppPageHeadOptions<TModule>,\n): Promise<ResolveAppPageHeadResult> {\n return await runWithFetchDedupe(() => resolveAppPageHeadInner(options));\n}\n\nasync function resolveAppPageHeadInner<TModule extends AppPageHeadModule>(\n options: ResolveAppPageHeadOptions<TModule>,\n): Promise<ResolveAppPageHeadResult> {\n const routeSegments = options.routeSegments ?? [];\n const layoutTreePositions = options.layoutTreePositions ?? [];\n const layoutInputs = createLayoutInputs(options.layoutModules, layoutTreePositions);\n const layoutSourcePositions = layoutInputs.map((input) => input.treePosition);\n const { hasSearchParams, pageSearchParams } = collectAppPageSearchParams(options.searchParams);\n const layoutMetadataPromise = resolveLayoutMetadata(layoutInputs, options.params, routeSegments);\n const layoutViewportPromise = resolveLayoutViewport(layoutInputs, options.params, routeSegments);\n\n const layoutMetadataResultsForParent = layoutMetadataPromise.then((metadataResults) =>\n metadataResults.filter(isPresent),\n );\n void layoutMetadataResultsForParent.catch(() => null);\n const pageParentPromise = layoutMetadataResultsForParent.then((metadataResults) =>\n metadataResults.length > 0\n ? mergeMetadataEntries(metadataResults.map((metadata) => ({ metadata })))\n : {},\n );\n void pageParentPromise.catch(() => null);\n const pageMetadataPromise = options.pageModule\n ? resolveModuleMetadata(options.pageModule, options.params, pageSearchParams, pageParentPromise)\n : Promise.resolve(null);\n const pageViewportPromise = options.pageModule\n ? resolveModuleViewport(options.pageModule, options.params)\n : Promise.resolve(null);\n const parallelRouteHeadPromise = Promise.all(\n (options.parallelRoutes ?? []).map((parallelRoute) =>\n resolveParallelRouteHead(\n parallelRoute,\n options.params,\n routeSegments,\n pageSearchParams,\n pageParentPromise,\n ),\n ),\n );\n\n const [\n layoutMetadataResults,\n layoutViewportResults,\n pageMetadata,\n pageViewport,\n parallelRouteHeads,\n ] = await Promise.all([\n layoutMetadataPromise,\n layoutViewportPromise,\n pageMetadataPromise,\n pageViewportPromise,\n parallelRouteHeadPromise,\n ]);\n const parallelMetadataResults = parallelRouteHeads.flatMap((head) => head.metadataResults);\n const parallelViewportResults = parallelRouteHeads.flatMap((head) => head.viewportResults);\n const parallelMetadataSources = parallelRouteHeads.flatMap((head) => head.metadataSources);\n\n const metadataEntries: MetadataMergeEntry[] = [\n ...layoutMetadataResults.filter(isPresent).map((metadata) => ({ metadata })),\n ...(pageMetadata ? [{ isPage: true, metadata: pageMetadata }] : []),\n ...parallelMetadataResults\n .filter(isPresent)\n .map((metadata) => ({ contributesTitle: false, metadata })),\n ];\n const viewportList = [\n ...layoutViewportResults.filter(isPresent),\n ...(pageViewport ? [pageViewport] : []),\n ...parallelViewportResults.filter(isPresent),\n ];\n\n const resolvedMetadataBase =\n metadataEntries.length > 0 ? mergeMetadataEntries(metadataEntries) : null;\n const metadataSources = createMetadataSources(\n layoutMetadataResults,\n routeSegments,\n layoutSourcePositions,\n pageMetadata,\n Boolean(options.pageModule),\n );\n metadataSources.push(...parallelMetadataSources);\n let metadata = resolvedMetadataBase;\n\n try {\n metadata = await applyFileBasedMetadata(\n resolvedMetadataBase,\n options.routePath,\n options.params,\n options.metadataRoutes,\n {\n routeSegments,\n metadataSources,\n basePath: options.basePath ?? \"\",\n },\n );\n } catch (error) {\n if (!options.fallbackOnFileMetadataError) {\n throw error;\n }\n console.error(\n `[vinext] File-based metadata resolution failed while rendering error boundary for ${options.routePath}:`,\n error,\n );\n }\n\n if (metadata) {\n metadata = postProcessMetadata(metadata);\n }\n\n return {\n hasSearchParams,\n metadata,\n pageSearchParams,\n viewport: mergeViewport(viewportList),\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-page-method.js","names":[],"sources":["../../src/server/app-page-method.ts"],"sourcesContent":["import { isPossibleAppRouteActionRequest } from \"./app-route-handler-policy.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport { methodNotAllowedResponse } from \"./http-error-responses.js\";\n\ntype AppPageMethodPolicyOptions = {\n dynamicConfig?: string;\n hasGenerateStaticParams: boolean;\n isDynamicRoute: boolean;\n revalidateSeconds: number | null;\n};\n\ntype ResolveAppPageMethodResponseOptions = {\n middlewareHeaders?: Headers | null;\n request: Pick<Request, \"headers\" | \"method\">;\n} & AppPageMethodPolicyOptions;\n\nfunction isNonGetOrHead(method: string): boolean {\n const normalizedMethod = method.toUpperCase();\n return normalizedMethod !== \"GET\" && normalizedMethod !== \"HEAD\";\n}\n\nexport function isStaticOrSsgAppPageCandidate(options: AppPageMethodPolicyOptions): boolean {\n if (options.dynamicConfig === \"force-dynamic\" || options.revalidateSeconds === 0) {\n return false;\n }\n\n if (options.dynamicConfig === \"force-static\" || options.dynamicConfig === \"error\") {\n return true;\n }\n\n if (options.revalidateSeconds !== null && options.revalidateSeconds > 0) {\n return true;\n }\n\n if (options.hasGenerateStaticParams) {\n return true;\n }\n\n return !options.isDynamicRoute;\n}\n\nexport function resolveAppPageMethodResponse(\n options: ResolveAppPageMethodResponseOptions,\n): Response | null {\n if (!isNonGetOrHead(options.request.method)) {\n return null;\n }\n\n if (isPossibleAppRouteActionRequest(options.request)) {\n return null;\n }\n\n if (!isStaticOrSsgAppPageCandidate(options)) {\n return null;\n }\n\n const headers = new Headers();\n mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);\n\n return methodNotAllowedResponse(\"GET, HEAD\", { headers });\n}\n"],"mappings":";;;;AAgBA,SAAS,eAAe,QAAyB;CAC/C,MAAM,mBAAmB,OAAO,aAAa;
|
|
1
|
+
{"version":3,"file":"app-page-method.js","names":[],"sources":["../../src/server/app-page-method.ts"],"sourcesContent":["import { isPossibleAppRouteActionRequest } from \"./app-route-handler-policy.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport { methodNotAllowedResponse } from \"./http-error-responses.js\";\n\ntype AppPageMethodPolicyOptions = {\n dynamicConfig?: string;\n hasGenerateStaticParams: boolean;\n isDynamicRoute: boolean;\n revalidateSeconds: number | null;\n};\n\ntype ResolveAppPageMethodResponseOptions = {\n middlewareHeaders?: Headers | null;\n request: Pick<Request, \"headers\" | \"method\">;\n} & AppPageMethodPolicyOptions;\n\nfunction isNonGetOrHead(method: string): boolean {\n const normalizedMethod = method.toUpperCase();\n return normalizedMethod !== \"GET\" && normalizedMethod !== \"HEAD\";\n}\n\nexport function isStaticOrSsgAppPageCandidate(options: AppPageMethodPolicyOptions): boolean {\n if (options.dynamicConfig === \"force-dynamic\" || options.revalidateSeconds === 0) {\n return false;\n }\n\n if (options.dynamicConfig === \"force-static\" || options.dynamicConfig === \"error\") {\n return true;\n }\n\n if (options.revalidateSeconds !== null && options.revalidateSeconds > 0) {\n return true;\n }\n\n if (options.hasGenerateStaticParams) {\n return true;\n }\n\n return !options.isDynamicRoute;\n}\n\nexport function resolveAppPageMethodResponse(\n options: ResolveAppPageMethodResponseOptions,\n): Response | null {\n if (!isNonGetOrHead(options.request.method)) {\n return null;\n }\n\n if (isPossibleAppRouteActionRequest(options.request)) {\n return null;\n }\n\n if (!isStaticOrSsgAppPageCandidate(options)) {\n return null;\n }\n\n const headers = new Headers();\n mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);\n\n return methodNotAllowedResponse(\"GET, HEAD\", { headers });\n}\n"],"mappings":";;;;AAgBA,SAAS,eAAe,QAAyB;CAC/C,MAAM,mBAAmB,OAAO,aAAa;CAC7C,OAAO,qBAAqB,SAAS,qBAAqB;;AAG5D,SAAgB,8BAA8B,SAA8C;CAC1F,IAAI,QAAQ,kBAAkB,mBAAmB,QAAQ,sBAAsB,GAC7E,OAAO;CAGT,IAAI,QAAQ,kBAAkB,kBAAkB,QAAQ,kBAAkB,SACxE,OAAO;CAGT,IAAI,QAAQ,sBAAsB,QAAQ,QAAQ,oBAAoB,GACpE,OAAO;CAGT,IAAI,QAAQ,yBACV,OAAO;CAGT,OAAO,CAAC,QAAQ;;AAGlB,SAAgB,6BACd,SACiB;CACjB,IAAI,CAAC,eAAe,QAAQ,QAAQ,OAAO,EACzC,OAAO;CAGT,IAAI,gCAAgC,QAAQ,QAAQ,EAClD,OAAO;CAGT,IAAI,CAAC,8BAA8B,QAAQ,EACzC,OAAO;CAGT,MAAM,UAAU,IAAI,SAAS;CAC7B,+BAA+B,SAAS,QAAQ,qBAAqB,KAAK;CAE1E,OAAO,yBAAyB,aAAa,EAAE,SAAS,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-page-params.js","names":[],"sources":["../../src/server/app-page-params.ts"],"sourcesContent":["import type { AppPageParams } from \"./app-page-boundary.js\";\n\nexport function getAppPageSegmentParamName(segment: string): string | null {\n if (segment.startsWith(\"[[...\") && segment.endsWith(\"]]\") && segment.length > 7) {\n return segment.slice(5, -2);\n }\n\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\") && segment.length > 5) {\n return segment.slice(4, -1);\n }\n\n if (\n segment.startsWith(\"[\") &&\n segment.endsWith(\"]\") &&\n !segment.includes(\".\") &&\n segment.length > 2\n ) {\n return segment.slice(1, -1);\n }\n\n return null;\n}\n\nfunction isEmptyOptionalCatchAll(segment: string, paramValue: string | string[]): boolean {\n return segment.startsWith(\"[[...\") && Array.isArray(paramValue) && paramValue.length === 0;\n}\n\nexport function resolveAppPageSegmentParams(\n routeSegments: readonly string[] | null | undefined,\n treePosition: number,\n matchedParams: AppPageParams,\n): AppPageParams {\n const segmentParams: AppPageParams = {};\n const segments = routeSegments ?? [];\n const end = Math.min(Math.max(treePosition, 0), segments.length);\n\n for (let index = 0; index < end; index++) {\n const segment = segments[index];\n const paramName = getAppPageSegmentParamName(segment);\n if (!paramName) {\n continue;\n }\n\n const paramValue = matchedParams[paramName];\n if (paramValue === undefined || isEmptyOptionalCatchAll(segment, paramValue)) {\n continue;\n }\n\n segmentParams[paramName] = paramValue;\n }\n\n return segmentParams;\n}\n"],"mappings":";AAEA,SAAgB,2BAA2B,SAAgC;
|
|
1
|
+
{"version":3,"file":"app-page-params.js","names":[],"sources":["../../src/server/app-page-params.ts"],"sourcesContent":["import type { AppPageParams } from \"./app-page-boundary.js\";\n\nexport function getAppPageSegmentParamName(segment: string): string | null {\n if (segment.startsWith(\"[[...\") && segment.endsWith(\"]]\") && segment.length > 7) {\n return segment.slice(5, -2);\n }\n\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\") && segment.length > 5) {\n return segment.slice(4, -1);\n }\n\n if (\n segment.startsWith(\"[\") &&\n segment.endsWith(\"]\") &&\n !segment.includes(\".\") &&\n segment.length > 2\n ) {\n return segment.slice(1, -1);\n }\n\n return null;\n}\n\nfunction isEmptyOptionalCatchAll(segment: string, paramValue: string | string[]): boolean {\n return segment.startsWith(\"[[...\") && Array.isArray(paramValue) && paramValue.length === 0;\n}\n\nexport function resolveAppPageSegmentParams(\n routeSegments: readonly string[] | null | undefined,\n treePosition: number,\n matchedParams: AppPageParams,\n): AppPageParams {\n const segmentParams: AppPageParams = {};\n const segments = routeSegments ?? [];\n const end = Math.min(Math.max(treePosition, 0), segments.length);\n\n for (let index = 0; index < end; index++) {\n const segment = segments[index];\n const paramName = getAppPageSegmentParamName(segment);\n if (!paramName) {\n continue;\n }\n\n const paramValue = matchedParams[paramName];\n if (paramValue === undefined || isEmptyOptionalCatchAll(segment, paramValue)) {\n continue;\n }\n\n segmentParams[paramName] = paramValue;\n }\n\n return segmentParams;\n}\n"],"mappings":";AAEA,SAAgB,2BAA2B,SAAgC;CACzE,IAAI,QAAQ,WAAW,QAAQ,IAAI,QAAQ,SAAS,KAAK,IAAI,QAAQ,SAAS,GAC5E,OAAO,QAAQ,MAAM,GAAG,GAAG;CAG7B,IAAI,QAAQ,WAAW,OAAO,IAAI,QAAQ,SAAS,IAAI,IAAI,QAAQ,SAAS,GAC1E,OAAO,QAAQ,MAAM,GAAG,GAAG;CAG7B,IACE,QAAQ,WAAW,IAAI,IACvB,QAAQ,SAAS,IAAI,IACrB,CAAC,QAAQ,SAAS,IAAI,IACtB,QAAQ,SAAS,GAEjB,OAAO,QAAQ,MAAM,GAAG,GAAG;CAG7B,OAAO;;AAGT,SAAS,wBAAwB,SAAiB,YAAwC;CACxF,OAAO,QAAQ,WAAW,QAAQ,IAAI,MAAM,QAAQ,WAAW,IAAI,WAAW,WAAW;;AAG3F,SAAgB,4BACd,eACA,cACA,eACe;CACf,MAAM,gBAA+B,EAAE;CACvC,MAAM,WAAW,iBAAiB,EAAE;CACpC,MAAM,MAAM,KAAK,IAAI,KAAK,IAAI,cAAc,EAAE,EAAE,SAAS,OAAO;CAEhE,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,SAAS;EACxC,MAAM,UAAU,SAAS;EACzB,MAAM,YAAY,2BAA2B,QAAQ;EACrD,IAAI,CAAC,WACH;EAGF,MAAM,aAAa,cAAc;EACjC,IAAI,eAAe,KAAA,KAAa,wBAAwB,SAAS,WAAW,EAC1E;EAGF,cAAc,aAAa;;CAG7B,OAAO"}
|
|
@@ -2,6 +2,28 @@ import { LayoutFlags } from "./app-elements-wire.js";
|
|
|
2
2
|
import { AppPageSpecialError, LayoutClassificationOptions } from "./app-page-execution.js";
|
|
3
3
|
|
|
4
4
|
//#region src/server/app-page-probe.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Build a probePage() invocation for the App Router request lifecycle.
|
|
7
|
+
*
|
|
8
|
+
* The generated RSC entry calls this once per request after route matching to
|
|
9
|
+
* eagerly invoke the page component. Surfacing redirect()/notFound() throws
|
|
10
|
+
* here lets the probe lifecycle turn them into proper HTTP responses before
|
|
11
|
+
* RSC streaming begins (see `probeAppPageBeforeRender`).
|
|
12
|
+
*
|
|
13
|
+
* The helper exists to keep the generated entry thin (a single delegation
|
|
14
|
+
* call) and to make the search-params wiring directly unit-testable. A bug
|
|
15
|
+
* here previously slipped through because the entry hand-rolled the call and
|
|
16
|
+
* read a non-existent key off `collectAppPageSearchParams`'s return value
|
|
17
|
+
* (see https://github.com/cloudflare/vinext/issues/1235).
|
|
18
|
+
*
|
|
19
|
+
* Returns `null` when the route has no page component (eg. interception-only
|
|
20
|
+
* routes), matching the caller contract on `probePage`.
|
|
21
|
+
*/
|
|
22
|
+
declare function probeAppPage(options: {
|
|
23
|
+
pageComponent: unknown;
|
|
24
|
+
asyncRouteParams: unknown;
|
|
25
|
+
searchParams: URLSearchParams | null | undefined;
|
|
26
|
+
}): unknown;
|
|
5
27
|
type ProbeAppPageBeforeRenderResult = {
|
|
6
28
|
response: Response | null;
|
|
7
29
|
layoutFlags: LayoutFlags;
|
|
@@ -19,5 +41,5 @@ type ProbeAppPageBeforeRenderOptions = {
|
|
|
19
41
|
};
|
|
20
42
|
declare function probeAppPageBeforeRender(options: ProbeAppPageBeforeRenderOptions): Promise<ProbeAppPageBeforeRenderResult>;
|
|
21
43
|
//#endregion
|
|
22
|
-
export { probeAppPageBeforeRender };
|
|
44
|
+
export { probeAppPage, probeAppPageBeforeRender };
|
|
23
45
|
//# sourceMappingURL=app-page-probe.d.ts.map
|
|
@@ -1,5 +1,33 @@
|
|
|
1
|
+
import { makeThenableParams } from "../shims/thenable-params.js";
|
|
2
|
+
import { collectAppPageSearchParams } from "./app-page-head.js";
|
|
1
3
|
import { probeAppPageComponent, probeAppPageLayouts } from "./app-page-execution.js";
|
|
2
4
|
//#region src/server/app-page-probe.ts
|
|
5
|
+
/**
|
|
6
|
+
* Build a probePage() invocation for the App Router request lifecycle.
|
|
7
|
+
*
|
|
8
|
+
* The generated RSC entry calls this once per request after route matching to
|
|
9
|
+
* eagerly invoke the page component. Surfacing redirect()/notFound() throws
|
|
10
|
+
* here lets the probe lifecycle turn them into proper HTTP responses before
|
|
11
|
+
* RSC streaming begins (see `probeAppPageBeforeRender`).
|
|
12
|
+
*
|
|
13
|
+
* The helper exists to keep the generated entry thin (a single delegation
|
|
14
|
+
* call) and to make the search-params wiring directly unit-testable. A bug
|
|
15
|
+
* here previously slipped through because the entry hand-rolled the call and
|
|
16
|
+
* read a non-existent key off `collectAppPageSearchParams`'s return value
|
|
17
|
+
* (see https://github.com/cloudflare/vinext/issues/1235).
|
|
18
|
+
*
|
|
19
|
+
* Returns `null` when the route has no page component (eg. interception-only
|
|
20
|
+
* routes), matching the caller contract on `probePage`.
|
|
21
|
+
*/
|
|
22
|
+
function probeAppPage(options) {
|
|
23
|
+
const { pageComponent, asyncRouteParams, searchParams } = options;
|
|
24
|
+
if (typeof pageComponent !== "function") return null;
|
|
25
|
+
const { pageSearchParams } = collectAppPageSearchParams(searchParams);
|
|
26
|
+
return pageComponent({
|
|
27
|
+
params: asyncRouteParams,
|
|
28
|
+
searchParams: makeThenableParams(pageSearchParams)
|
|
29
|
+
});
|
|
30
|
+
}
|
|
3
31
|
async function probeAppPageBeforeRender(options) {
|
|
4
32
|
let layoutFlags = {};
|
|
5
33
|
if (options.layoutCount > 0) {
|
|
@@ -43,6 +71,6 @@ async function probeAppPageBeforeRender(options) {
|
|
|
43
71
|
};
|
|
44
72
|
}
|
|
45
73
|
//#endregion
|
|
46
|
-
export { probeAppPageBeforeRender };
|
|
74
|
+
export { probeAppPage, probeAppPageBeforeRender };
|
|
47
75
|
|
|
48
76
|
//# sourceMappingURL=app-page-probe.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-page-probe.js","names":[],"sources":["../../src/server/app-page-probe.ts"],"sourcesContent":["import {\n probeAppPageComponent,\n probeAppPageLayouts,\n type AppPageSpecialError,\n type LayoutClassificationOptions,\n type LayoutFlags,\n} from \"./app-page-execution.js\";\n\ntype ProbeAppPageBeforeRenderResult = {\n response: Response | null;\n layoutFlags: LayoutFlags;\n};\n\ntype ProbeAppPageBeforeRenderOptions = {\n hasLoadingBoundary: boolean;\n layoutCount: number;\n probeLayoutAt: (layoutIndex: number) => unknown;\n probePage: () => unknown;\n renderLayoutSpecialError: (\n specialError: AppPageSpecialError,\n layoutIndex: number,\n ) => Promise<Response>;\n renderPageSpecialError: (specialError: AppPageSpecialError) => Promise<Response>;\n resolveSpecialError: (error: unknown) => AppPageSpecialError | null;\n runWithSuppressedHookWarning<T>(probe: () => Promise<T>): Promise<T>;\n /** When provided, enables per-layout static/dynamic classification. */\n classification?: LayoutClassificationOptions | null;\n};\n\nexport async function probeAppPageBeforeRender(\n options: ProbeAppPageBeforeRenderOptions,\n): Promise<ProbeAppPageBeforeRenderResult> {\n let layoutFlags: LayoutFlags = {};\n\n // Layouts render before their children in Next.js, so layout-level special\n // errors must be handled before probing the page component itself.\n if (options.layoutCount > 0) {\n const layoutProbeResult = await probeAppPageLayouts({\n layoutCount: options.layoutCount,\n async onLayoutError(layoutError, layoutIndex) {\n const specialError = options.resolveSpecialError(layoutError);\n if (!specialError) {\n return null;\n }\n\n return options.renderLayoutSpecialError(specialError, layoutIndex);\n },\n probeLayoutAt: options.probeLayoutAt,\n runWithSuppressedHookWarning(probe) {\n return options.runWithSuppressedHookWarning(probe);\n },\n classification: options.classification,\n });\n\n layoutFlags = layoutProbeResult.layoutFlags;\n\n if (layoutProbeResult.response) {\n return { response: layoutProbeResult.response, layoutFlags };\n }\n }\n\n // When a route-level loading.tsx is present, the page renders inside a\n // route-level Suspense boundary, so a thrown redirect()/notFound() during\n // page render becomes an error inside that boundary. We can't catch it\n // here without serializing on the page promise — which would defeat the\n // streaming benefit of loading.tsx for slow non-redirecting pages.\n //\n // Recovery for the redirect/notFound case happens later in\n // renderAppPageLifecycle: rscErrorTracker captures the digest from React's\n // onError callback, and a short race window after shell-ready lets the\n // lifecycle swap the response to a 307/404 before bytes are flushed.\n // This mirrors Next.js's \"until-first-byte-is-flushed\" swap behavior.\n if (options.hasLoadingBoundary) {\n return { response: null, layoutFlags };\n }\n\n // Server Components are functions, so we can probe the page ahead of stream\n // creation and only turn special throws into immediate responses.\n const pageResponse = await probeAppPageComponent({\n awaitAsyncResult: true,\n async onError(pageError) {\n const specialError = options.resolveSpecialError(pageError);\n if (specialError) {\n return options.renderPageSpecialError(specialError);\n }\n\n // Non-special probe failures (for example use() outside React's render\n // cycle or client references executing on the server) are expected here.\n // The real RSC/SSR render path will surface those properly below.\n return null;\n },\n probePage: options.probePage,\n runWithSuppressedHookWarning(probe) {\n return options.runWithSuppressedHookWarning(probe);\n },\n });\n\n return { response: pageResponse, layoutFlags };\n}\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"app-page-probe.js","names":[],"sources":["../../src/server/app-page-probe.ts"],"sourcesContent":["import { makeThenableParams } from \"vinext/shims/thenable-params\";\nimport { collectAppPageSearchParams } from \"./app-page-head.js\";\nimport {\n probeAppPageComponent,\n probeAppPageLayouts,\n type AppPageSpecialError,\n type LayoutClassificationOptions,\n type LayoutFlags,\n} from \"./app-page-execution.js\";\n\n/**\n * Build a probePage() invocation for the App Router request lifecycle.\n *\n * The generated RSC entry calls this once per request after route matching to\n * eagerly invoke the page component. Surfacing redirect()/notFound() throws\n * here lets the probe lifecycle turn them into proper HTTP responses before\n * RSC streaming begins (see `probeAppPageBeforeRender`).\n *\n * The helper exists to keep the generated entry thin (a single delegation\n * call) and to make the search-params wiring directly unit-testable. A bug\n * here previously slipped through because the entry hand-rolled the call and\n * read a non-existent key off `collectAppPageSearchParams`'s return value\n * (see https://github.com/cloudflare/vinext/issues/1235).\n *\n * Returns `null` when the route has no page component (eg. interception-only\n * routes), matching the caller contract on `probePage`.\n */\nexport function probeAppPage(options: {\n pageComponent: unknown;\n asyncRouteParams: unknown;\n searchParams: URLSearchParams | null | undefined;\n}): unknown {\n const { pageComponent, asyncRouteParams, searchParams } = options;\n if (typeof pageComponent !== \"function\") {\n return null;\n }\n const { pageSearchParams } = collectAppPageSearchParams(searchParams);\n const asyncSearchParams = makeThenableParams(pageSearchParams);\n return (pageComponent as (props: Record<string, unknown>) => unknown)({\n params: asyncRouteParams,\n searchParams: asyncSearchParams,\n });\n}\n\ntype ProbeAppPageBeforeRenderResult = {\n response: Response | null;\n layoutFlags: LayoutFlags;\n};\n\ntype ProbeAppPageBeforeRenderOptions = {\n hasLoadingBoundary: boolean;\n layoutCount: number;\n probeLayoutAt: (layoutIndex: number) => unknown;\n probePage: () => unknown;\n renderLayoutSpecialError: (\n specialError: AppPageSpecialError,\n layoutIndex: number,\n ) => Promise<Response>;\n renderPageSpecialError: (specialError: AppPageSpecialError) => Promise<Response>;\n resolveSpecialError: (error: unknown) => AppPageSpecialError | null;\n runWithSuppressedHookWarning<T>(probe: () => Promise<T>): Promise<T>;\n /** When provided, enables per-layout static/dynamic classification. */\n classification?: LayoutClassificationOptions | null;\n};\n\nexport async function probeAppPageBeforeRender(\n options: ProbeAppPageBeforeRenderOptions,\n): Promise<ProbeAppPageBeforeRenderResult> {\n let layoutFlags: LayoutFlags = {};\n\n // Layouts render before their children in Next.js, so layout-level special\n // errors must be handled before probing the page component itself.\n if (options.layoutCount > 0) {\n const layoutProbeResult = await probeAppPageLayouts({\n layoutCount: options.layoutCount,\n async onLayoutError(layoutError, layoutIndex) {\n const specialError = options.resolveSpecialError(layoutError);\n if (!specialError) {\n return null;\n }\n\n return options.renderLayoutSpecialError(specialError, layoutIndex);\n },\n probeLayoutAt: options.probeLayoutAt,\n runWithSuppressedHookWarning(probe) {\n return options.runWithSuppressedHookWarning(probe);\n },\n classification: options.classification,\n });\n\n layoutFlags = layoutProbeResult.layoutFlags;\n\n if (layoutProbeResult.response) {\n return { response: layoutProbeResult.response, layoutFlags };\n }\n }\n\n // When a route-level loading.tsx is present, the page renders inside a\n // route-level Suspense boundary, so a thrown redirect()/notFound() during\n // page render becomes an error inside that boundary. We can't catch it\n // here without serializing on the page promise — which would defeat the\n // streaming benefit of loading.tsx for slow non-redirecting pages.\n //\n // Recovery for the redirect/notFound case happens later in\n // renderAppPageLifecycle: rscErrorTracker captures the digest from React's\n // onError callback, and a short race window after shell-ready lets the\n // lifecycle swap the response to a 307/404 before bytes are flushed.\n // This mirrors Next.js's \"until-first-byte-is-flushed\" swap behavior.\n if (options.hasLoadingBoundary) {\n return { response: null, layoutFlags };\n }\n\n // Server Components are functions, so we can probe the page ahead of stream\n // creation and only turn special throws into immediate responses.\n const pageResponse = await probeAppPageComponent({\n awaitAsyncResult: true,\n async onError(pageError) {\n const specialError = options.resolveSpecialError(pageError);\n if (specialError) {\n return options.renderPageSpecialError(specialError);\n }\n\n // Non-special probe failures (for example use() outside React's render\n // cycle or client references executing on the server) are expected here.\n // The real RSC/SSR render path will surface those properly below.\n return null;\n },\n probePage: options.probePage,\n runWithSuppressedHookWarning(probe) {\n return options.runWithSuppressedHookWarning(probe);\n },\n });\n\n return { response: pageResponse, layoutFlags };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,aAAa,SAIjB;CACV,MAAM,EAAE,eAAe,kBAAkB,iBAAiB;CAC1D,IAAI,OAAO,kBAAkB,YAC3B,OAAO;CAET,MAAM,EAAE,qBAAqB,2BAA2B,aAAa;CAErE,OAAQ,cAA8D;EACpE,QAAQ;EACR,cAHwB,mBAAmB,iBAGZ;EAChC,CAAC;;AAwBJ,eAAsB,yBACpB,SACyC;CACzC,IAAI,cAA2B,EAAE;CAIjC,IAAI,QAAQ,cAAc,GAAG;EAC3B,MAAM,oBAAoB,MAAM,oBAAoB;GAClD,aAAa,QAAQ;GACrB,MAAM,cAAc,aAAa,aAAa;IAC5C,MAAM,eAAe,QAAQ,oBAAoB,YAAY;IAC7D,IAAI,CAAC,cACH,OAAO;IAGT,OAAO,QAAQ,yBAAyB,cAAc,YAAY;;GAEpE,eAAe,QAAQ;GACvB,6BAA6B,OAAO;IAClC,OAAO,QAAQ,6BAA6B,MAAM;;GAEpD,gBAAgB,QAAQ;GACzB,CAAC;EAEF,cAAc,kBAAkB;EAEhC,IAAI,kBAAkB,UACpB,OAAO;GAAE,UAAU,kBAAkB;GAAU;GAAa;;CAehE,IAAI,QAAQ,oBACV,OAAO;EAAE,UAAU;EAAM;EAAa;CAwBxC,OAAO;EAAE,UAAU,MAnBQ,sBAAsB;GAC/C,kBAAkB;GAClB,MAAM,QAAQ,WAAW;IACvB,MAAM,eAAe,QAAQ,oBAAoB,UAAU;IAC3D,IAAI,cACF,OAAO,QAAQ,uBAAuB,aAAa;IAMrD,OAAO;;GAET,WAAW,QAAQ;GACnB,6BAA6B,OAAO;IAClC,OAAO,QAAQ,6BAA6B,MAAM;;GAErD,CAAC;EAE+B;EAAa"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { BoundaryOutcome, CacheProofOutputScope, RenderCacheability, RenderObservation, RenderObservationCompleteness, RenderRequestApiKind } from "./cache-proof.js";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/server/app-page-render-observation.d.ts
|
|
5
|
+
type AppPageRenderObservationState = Readonly<{
|
|
6
|
+
dynamicFetches: readonly string[];
|
|
7
|
+
requestApis: readonly RenderRequestApiKind[];
|
|
8
|
+
}>;
|
|
9
|
+
declare function createEmptyAppPageRenderObservationState(): AppPageRenderObservationState;
|
|
10
|
+
declare function createAppPageRenderObservation(options: {
|
|
11
|
+
boundaryOutcome: BoundaryOutcome;
|
|
12
|
+
cacheTags: readonly string[];
|
|
13
|
+
cacheability: RenderCacheability;
|
|
14
|
+
cleanPathname: string;
|
|
15
|
+
completeness: RenderObservationCompleteness;
|
|
16
|
+
output: CacheProofOutputScope;
|
|
17
|
+
params: Record<string, unknown>;
|
|
18
|
+
state: AppPageRenderObservationState;
|
|
19
|
+
}): RenderObservation;
|
|
20
|
+
declare function createAppPageRscOutputScope(options: {
|
|
21
|
+
element: ReactNode | Readonly<Record<string, ReactNode>>;
|
|
22
|
+
mountedSlotsHeader?: string | null;
|
|
23
|
+
renderEpoch: string | null;
|
|
24
|
+
rootBoundaryId: string | null;
|
|
25
|
+
routePattern: string;
|
|
26
|
+
}): CacheProofOutputScope;
|
|
27
|
+
declare function createAppPageHtmlOutputScope(options: {
|
|
28
|
+
element: ReactNode | Readonly<Record<string, ReactNode>>;
|
|
29
|
+
renderEpoch: string | null;
|
|
30
|
+
rootBoundaryId: string | null;
|
|
31
|
+
routePattern: string;
|
|
32
|
+
}): CacheProofOutputScope;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { AppPageRenderObservationState, createAppPageHtmlOutputScope, createAppPageRenderObservation, createAppPageRscOutputScope, createEmptyAppPageRenderObservationState };
|
|
35
|
+
//# sourceMappingURL=app-page-render-observation.d.ts.map
|