vinext 0.0.51 → 0.0.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/build/clean-output.d.ts +14 -0
- package/dist/build/clean-output.js +36 -0
- package/dist/build/clean-output.js.map +1 -0
- package/dist/build/precompress.d.ts +7 -7
- package/dist/build/precompress.js +18 -17
- package/dist/build/precompress.js.map +1 -1
- package/dist/build/prerender.d.ts +9 -16
- package/dist/build/prerender.js +88 -50
- package/dist/build/prerender.js.map +1 -1
- package/dist/build/run-prerender.js +10 -1
- package/dist/build/run-prerender.js.map +1 -1
- package/dist/build/static-export.d.ts +5 -0
- package/dist/build/static-export.js +8 -3
- package/dist/build/static-export.js.map +1 -1
- package/dist/check.js +4 -0
- package/dist/check.js.map +1 -1
- package/dist/cli-args.d.ts +1 -0
- package/dist/cli-args.js +5 -0
- package/dist/cli-args.js.map +1 -1
- package/dist/cli.js +58 -4
- package/dist/cli.js.map +1 -1
- package/dist/client/instrumentation-client-inject.d.ts +34 -0
- package/dist/client/instrumentation-client-inject.js +57 -0
- package/dist/client/instrumentation-client-inject.js.map +1 -0
- package/dist/client/navigation-runtime.d.ts +60 -0
- package/dist/client/navigation-runtime.js +171 -0
- package/dist/client/navigation-runtime.js.map +1 -0
- package/dist/client/pages-router-link-navigation.d.ts +26 -0
- package/dist/client/pages-router-link-navigation.js +14 -0
- package/dist/client/pages-router-link-navigation.js.map +1 -0
- package/dist/client/vinext-next-data.d.ts +14 -3
- package/dist/client/vinext-next-data.js +50 -1
- package/dist/client/vinext-next-data.js.map +1 -0
- package/dist/client/window-next.d.ts +10 -2
- package/dist/client/window-next.js.map +1 -1
- package/dist/cloudflare/kv-cache-handler.js +2 -1
- package/dist/cloudflare/kv-cache-handler.js.map +1 -1
- package/dist/cloudflare/tpr.js +1 -1
- package/dist/cloudflare/tpr.js.map +1 -1
- package/dist/config/config-matchers.d.ts +63 -16
- package/dist/config/config-matchers.js +145 -9
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/config/next-config.d.ts +32 -5
- package/dist/config/next-config.js +55 -15
- package/dist/config/next-config.js.map +1 -1
- package/dist/deploy.js +130 -46
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-browser-entry.js +9 -3
- package/dist/entries/app-browser-entry.js.map +1 -1
- package/dist/entries/app-rsc-entry.d.ts +4 -2
- package/dist/entries/app-rsc-entry.js +76 -16
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.d.ts +1 -0
- package/dist/entries/app-rsc-manifest.js +53 -6
- package/dist/entries/app-rsc-manifest.js.map +1 -1
- package/dist/entries/app-ssr-entry.d.ts +3 -3
- package/dist/entries/app-ssr-entry.js +4 -4
- package/dist/entries/app-ssr-entry.js.map +1 -1
- package/dist/entries/pages-client-entry.js +40 -3
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-server-entry.js +261 -31
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.d.ts +2 -1
- package/dist/entries/runtime-entry-module.js +9 -3
- package/dist/entries/runtime-entry-module.js.map +1 -1
- package/dist/index.js +161 -46
- package/dist/index.js.map +1 -1
- package/dist/plugins/css-data-url.d.ts +7 -0
- package/dist/plugins/css-data-url.js +81 -0
- package/dist/plugins/css-data-url.js.map +1 -0
- package/dist/plugins/fonts.js +30 -5
- package/dist/plugins/fonts.js.map +1 -1
- package/dist/plugins/middleware-server-only.d.ts +54 -0
- package/dist/plugins/middleware-server-only.js +91 -0
- package/dist/plugins/middleware-server-only.js.map +1 -0
- package/dist/plugins/optimize-imports.js +4 -4
- package/dist/plugins/optimize-imports.js.map +1 -1
- package/dist/plugins/strip-server-exports.js +5 -8
- package/dist/plugins/strip-server-exports.js.map +1 -1
- package/dist/routing/app-route-graph.d.ts +20 -1
- package/dist/routing/app-route-graph.js +58 -6
- package/dist/routing/app-route-graph.js.map +1 -1
- package/dist/routing/app-router.d.ts +2 -2
- package/dist/routing/app-router.js +2 -2
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/route-trie.js +13 -18
- package/dist/routing/route-trie.js.map +1 -1
- package/dist/routing/utils.d.ts +12 -1
- package/dist/routing/utils.js +18 -1
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/api-handler.js +153 -42
- package/dist/server/api-handler.js.map +1 -1
- package/dist/server/app-browser-action-result.d.ts +16 -1
- package/dist/server/app-browser-action-result.js +15 -1
- package/dist/server/app-browser-action-result.js.map +1 -1
- package/dist/server/app-browser-entry.js +309 -155
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-interception-context.d.ts +24 -0
- package/dist/server/app-browser-interception-context.js +32 -0
- package/dist/server/app-browser-interception-context.js.map +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +3 -1
- package/dist/server/app-browser-navigation-controller.js +5 -1
- package/dist/server/app-browser-navigation-controller.js.map +1 -1
- package/dist/server/app-browser-rsc-redirect.d.ts +2 -1
- package/dist/server/app-browser-rsc-redirect.js +2 -2
- package/dist/server/app-browser-rsc-redirect.js.map +1 -1
- package/dist/server/app-browser-state.d.ts +18 -1
- package/dist/server/app-browser-state.js +19 -1
- package/dist/server/app-browser-state.js.map +1 -1
- package/dist/server/app-browser-stream.d.ts +5 -14
- package/dist/server/app-browser-stream.js +13 -7
- package/dist/server/app-browser-stream.js.map +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +2 -1
- package/dist/server/app-browser-visible-commit.js +1 -0
- package/dist/server/app-browser-visible-commit.js.map +1 -1
- package/dist/server/app-elements-wire.d.ts +10 -5
- package/dist/server/app-elements-wire.js +84 -2
- package/dist/server/app-elements-wire.js.map +1 -1
- package/dist/server/app-elements.d.ts +3 -2
- package/dist/server/app-elements.js +3 -2
- package/dist/server/app-elements.js.map +1 -1
- package/dist/server/app-fallback-renderer.d.ts +12 -3
- package/dist/server/app-fallback-renderer.js +15 -8
- package/dist/server/app-fallback-renderer.js.map +1 -1
- package/dist/server/app-history-state.js +6 -2
- package/dist/server/app-history-state.js.map +1 -1
- package/dist/server/app-interception-context-header.d.ts +33 -0
- package/dist/server/app-interception-context-header.js +44 -0
- package/dist/server/app-interception-context-header.js.map +1 -0
- package/dist/server/app-middleware.d.ts +13 -0
- package/dist/server/app-middleware.js +3 -1
- package/dist/server/app-middleware.js.map +1 -1
- package/dist/server/app-mounted-slots-header.d.ts +19 -0
- package/dist/server/app-mounted-slots-header.js +40 -1
- package/dist/server/app-mounted-slots-header.js.map +1 -1
- package/dist/server/app-optimistic-routing.d.ts +54 -0
- package/dist/server/app-optimistic-routing.js +208 -0
- package/dist/server/app-optimistic-routing.js.map +1 -0
- package/dist/server/app-page-boundary-render.d.ts +1 -0
- package/dist/server/app-page-boundary-render.js +2 -0
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-boundary.d.ts +1 -0
- package/dist/server/app-page-boundary.js +2 -0
- package/dist/server/app-page-boundary.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +15 -1
- package/dist/server/app-page-cache.js +68 -7
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-dispatch.d.ts +5 -0
- package/dist/server/app-page-dispatch.js +39 -5
- package/dist/server/app-page-dispatch.js.map +1 -1
- package/dist/server/app-page-element-builder.d.ts +2 -1
- package/dist/server/app-page-element-builder.js +7 -3
- package/dist/server/app-page-element-builder.js.map +1 -1
- package/dist/server/app-page-execution.d.ts +29 -1
- package/dist/server/app-page-execution.js +91 -4
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-head.d.ts +1 -0
- package/dist/server/app-page-head.js +29 -2
- package/dist/server/app-page-head.js.map +1 -1
- package/dist/server/app-page-probe.js +1 -1
- package/dist/server/app-page-render-observation.js +1 -1
- package/dist/server/app-page-render.d.ts +3 -0
- package/dist/server/app-page-render.js +7 -3
- package/dist/server/app-page-render.js.map +1 -1
- package/dist/server/app-page-response.d.ts +11 -1
- package/dist/server/app-page-response.js +18 -5
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +1 -0
- package/dist/server/app-page-route-wiring.js +35 -15
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-page-stream.d.ts +4 -0
- package/dist/server/app-page-stream.js +3 -0
- package/dist/server/app-page-stream.js.map +1 -1
- package/dist/server/app-prerender-static-params.d.ts +2 -1
- package/dist/server/app-prerender-static-params.js +44 -8
- package/dist/server/app-prerender-static-params.js.map +1 -1
- package/dist/server/app-route-handler-cache.d.ts +2 -2
- package/dist/server/app-route-handler-cache.js +3 -2
- package/dist/server/app-route-handler-cache.js.map +1 -1
- package/dist/server/app-route-handler-dispatch.d.ts +7 -1
- package/dist/server/app-route-handler-dispatch.js +4 -1
- package/dist/server/app-route-handler-dispatch.js.map +1 -1
- package/dist/server/app-route-handler-execution.d.ts +18 -2
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-execution.js.map +1 -1
- package/dist/server/app-route-handler-response.js +6 -5
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-router-entry.js +6 -2
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/app-rsc-handler.d.ts +11 -1
- package/dist/server/app-rsc-handler.js +48 -21
- package/dist/server/app-rsc-handler.js.map +1 -1
- package/dist/server/app-rsc-render-mode.d.ts +4 -3
- package/dist/server/app-rsc-render-mode.js +7 -1
- package/dist/server/app-rsc-render-mode.js.map +1 -1
- package/dist/server/app-rsc-request-normalization.d.ts +4 -1
- package/dist/server/app-rsc-request-normalization.js +6 -2
- package/dist/server/app-rsc-request-normalization.js.map +1 -1
- package/dist/server/app-rsc-response-finalizer.d.ts +8 -1
- package/dist/server/app-rsc-response-finalizer.js +10 -3
- package/dist/server/app-rsc-response-finalizer.js.map +1 -1
- package/dist/server/app-rsc-route-matching.js +2 -2
- package/dist/server/app-rsc-route-matching.js.map +1 -1
- package/dist/server/app-segment-config.d.ts +4 -1
- package/dist/server/app-segment-config.js +6 -1
- package/dist/server/app-segment-config.js.map +1 -1
- package/dist/server/app-server-action-execution.d.ts +1 -0
- package/dist/server/app-server-action-execution.js +5 -1
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +92 -55
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/app-ssr-stream.d.ts +30 -2
- package/dist/server/app-ssr-stream.js +95 -8
- package/dist/server/app-ssr-stream.js.map +1 -1
- package/dist/server/app-static-generation.d.ts +1 -0
- package/dist/server/app-static-generation.js +2 -1
- package/dist/server/app-static-generation.js.map +1 -1
- package/dist/server/artifact-compatibility.d.ts +1 -1
- package/dist/server/artifact-compatibility.js.map +1 -1
- package/dist/server/cache-headers.d.ts +7 -0
- package/dist/server/cache-headers.js +19 -0
- package/dist/server/cache-headers.js.map +1 -0
- package/dist/server/cache-proof.d.ts +49 -3
- package/dist/server/cache-proof.js +78 -22
- package/dist/server/cache-proof.js.map +1 -1
- package/dist/server/client-reuse-manifest.d.ts +99 -0
- package/dist/server/client-reuse-manifest.js +212 -0
- package/dist/server/client-reuse-manifest.js.map +1 -0
- package/dist/server/default-global-error-module.d.ts +20 -0
- package/dist/server/default-global-error-module.js +20 -0
- package/dist/server/default-global-error-module.js.map +1 -0
- package/dist/server/default-not-found-module.d.ts +20 -0
- package/dist/server/default-not-found-module.js +20 -0
- package/dist/server/default-not-found-module.js.map +1 -0
- package/dist/server/dev-server.d.ts +10 -2
- package/dist/server/dev-server.js +99 -36
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/edge-api-runtime.d.ts +5 -0
- package/dist/server/edge-api-runtime.js +8 -0
- package/dist/server/edge-api-runtime.js.map +1 -0
- package/dist/server/headers.d.ts +22 -1
- package/dist/server/headers.js +22 -1
- package/dist/server/headers.js.map +1 -1
- package/dist/server/http-error-responses.d.ts +16 -1
- package/dist/server/http-error-responses.js +21 -1
- package/dist/server/http-error-responses.js.map +1 -1
- package/dist/server/image-optimization.d.ts +13 -4
- package/dist/server/image-optimization.js +15 -4
- package/dist/server/image-optimization.js.map +1 -1
- package/dist/server/isr-cache.d.ts +6 -2
- package/dist/server/isr-cache.js +20 -4
- package/dist/server/isr-cache.js.map +1 -1
- package/dist/server/middleware-runtime.d.ts +15 -0
- package/dist/server/middleware-runtime.js +59 -7
- package/dist/server/middleware-runtime.js.map +1 -1
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +5 -3
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/navigation-planner.d.ts +9 -3
- package/dist/server/navigation-planner.js +98 -25
- package/dist/server/navigation-planner.js.map +1 -1
- package/dist/server/navigation-trace.d.ts +2 -1
- package/dist/server/navigation-trace.js +1 -0
- package/dist/server/navigation-trace.js.map +1 -1
- package/dist/server/pages-api-route.d.ts +45 -1
- package/dist/server/pages-api-route.js +27 -4
- package/dist/server/pages-api-route.js.map +1 -1
- package/dist/server/pages-body-parser-config.d.ts +60 -0
- package/dist/server/pages-body-parser-config.js +79 -0
- package/dist/server/pages-body-parser-config.js.map +1 -0
- package/dist/server/pages-data-route.d.ts +77 -0
- package/dist/server/pages-data-route.js +98 -0
- package/dist/server/pages-data-route.js.map +1 -0
- package/dist/server/pages-default-404.d.ts +31 -0
- package/dist/server/pages-default-404.js +40 -0
- package/dist/server/pages-default-404.js.map +1 -0
- package/dist/server/pages-i18n.d.ts +51 -1
- package/dist/server/pages-i18n.js +61 -1
- package/dist/server/pages-i18n.js.map +1 -1
- package/dist/server/pages-node-compat.d.ts +10 -0
- package/dist/server/pages-node-compat.js +12 -1
- package/dist/server/pages-node-compat.js.map +1 -1
- package/dist/server/pages-page-data.d.ts +69 -2
- package/dist/server/pages-page-data.js +47 -31
- package/dist/server/pages-page-data.js.map +1 -1
- package/dist/server/pages-page-response.d.ts +13 -1
- package/dist/server/pages-page-response.js +16 -11
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/prerender-route-params.d.ts +14 -0
- package/dist/server/prerender-route-params.js +94 -0
- package/dist/server/prerender-route-params.js.map +1 -0
- package/dist/server/prod-server.d.ts +15 -37
- package/dist/server/prod-server.js +143 -107
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/proxy-trust.d.ts +41 -0
- package/dist/server/proxy-trust.js +70 -0
- package/dist/server/proxy-trust.js.map +1 -0
- package/dist/server/request-pipeline.d.ts +13 -4
- package/dist/server/request-pipeline.js +32 -14
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/server/seed-cache.d.ts +12 -31
- package/dist/server/seed-cache.js +30 -37
- package/dist/server/seed-cache.js.map +1 -1
- package/dist/server/server-action-not-found.js +8 -3
- package/dist/server/server-action-not-found.js.map +1 -1
- package/dist/server/skip-cache-proof.d.ts +41 -0
- package/dist/server/skip-cache-proof.js +101 -0
- package/dist/server/skip-cache-proof.js.map +1 -0
- package/dist/server/static-file-cache.d.ts +1 -1
- package/dist/server/static-file-cache.js +8 -7
- package/dist/server/static-file-cache.js.map +1 -1
- package/dist/server/streaming-metadata.d.ts +5 -0
- package/dist/server/streaming-metadata.js +10 -0
- package/dist/server/streaming-metadata.js.map +1 -0
- package/dist/shims/app-router-scroll-state.d.ts +12 -0
- package/dist/shims/app-router-scroll-state.js +38 -0
- package/dist/shims/app-router-scroll-state.js.map +1 -0
- package/dist/shims/app-router-scroll.d.ts +14 -0
- package/dist/shims/app-router-scroll.js +100 -0
- package/dist/shims/app-router-scroll.js.map +1 -0
- package/dist/shims/before-interactive-context.d.ts +30 -0
- package/dist/shims/before-interactive-context.js +10 -0
- package/dist/shims/before-interactive-context.js.map +1 -0
- package/dist/shims/cache-runtime.d.ts +1 -1
- package/dist/shims/cache-runtime.js +14 -1
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/client-locale.d.ts +15 -0
- package/dist/shims/client-locale.js +13 -0
- package/dist/shims/client-locale.js.map +1 -0
- package/dist/shims/default-global-error.d.ts +32 -0
- package/dist/shims/default-global-error.js +181 -0
- package/dist/shims/default-global-error.js.map +1 -0
- package/dist/shims/default-not-found.d.ts +12 -0
- package/dist/shims/default-not-found.js +61 -0
- package/dist/shims/default-not-found.js.map +1 -0
- package/dist/shims/document.d.ts +59 -3
- package/dist/shims/document.js +36 -5
- package/dist/shims/document.js.map +1 -1
- package/dist/shims/error-boundary.d.ts +2 -2
- package/dist/shims/font-local.d.ts +5 -0
- package/dist/shims/font-local.js +6 -2
- package/dist/shims/font-local.js.map +1 -1
- package/dist/shims/form.js +13 -6
- package/dist/shims/form.js.map +1 -1
- package/dist/shims/head.js +4 -4
- package/dist/shims/head.js.map +1 -1
- package/dist/shims/headers.d.ts +6 -2
- package/dist/shims/headers.js +64 -21
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/image.d.ts +1 -1
- package/dist/shims/image.js +4 -4
- package/dist/shims/image.js.map +1 -1
- package/dist/shims/internal/pages-data-target.d.ts +58 -0
- package/dist/shims/internal/pages-data-target.js +91 -0
- package/dist/shims/internal/pages-data-target.js.map +1 -0
- package/dist/shims/internal/pages-data-url.d.ts +42 -0
- package/dist/shims/internal/pages-data-url.js +73 -0
- package/dist/shims/internal/pages-data-url.js.map +1 -0
- package/dist/shims/link.d.ts +21 -3
- package/dist/shims/link.js +189 -30
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +2 -1
- package/dist/shims/metadata.js +65 -6
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation.d.ts +8 -2
- package/dist/shims/navigation.js +67 -23
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/og.d.ts +18 -2
- package/dist/shims/og.js +49 -1
- package/dist/shims/og.js.map +1 -0
- package/dist/shims/request-state-types.d.ts +1 -1
- package/dist/shims/root-params.d.ts +3 -1
- package/dist/shims/root-params.js +11 -3
- package/dist/shims/root-params.js.map +1 -1
- package/dist/shims/router-state.d.ts +1 -0
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/router.d.ts +12 -5
- package/dist/shims/router.js +535 -86
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/script.js +86 -12
- package/dist/shims/script.js.map +1 -1
- package/dist/shims/server.d.ts +21 -4
- package/dist/shims/server.js +30 -9
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/slot.js +5 -1
- package/dist/shims/slot.js.map +1 -1
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/url-safety.d.ts +23 -1
- package/dist/shims/url-safety.js +29 -2
- package/dist/shims/url-safety.js.map +1 -1
- package/dist/shims/url-utils.d.ts +2 -1
- package/dist/shims/url-utils.js +15 -4
- package/dist/shims/url-utils.js.map +1 -1
- package/dist/typegen.d.ts +10 -0
- package/dist/typegen.js +242 -0
- package/dist/typegen.js.map +1 -0
- package/dist/utils/asset-prefix.d.ts +33 -5
- package/dist/utils/asset-prefix.js +39 -6
- package/dist/utils/asset-prefix.js.map +1 -1
- package/dist/utils/cache-control-metadata.d.ts +2 -1
- package/dist/utils/cache-control-metadata.js +1 -3
- package/dist/utils/cache-control-metadata.js.map +1 -1
- package/dist/utils/domain-locale.d.ts +2 -1
- package/dist/utils/domain-locale.js +9 -1
- package/dist/utils/domain-locale.js.map +1 -1
- package/dist/utils/html-limited-bots.d.ts +5 -0
- package/dist/utils/html-limited-bots.js +15 -0
- package/dist/utils/html-limited-bots.js.map +1 -0
- package/dist/utils/lazy-chunks.d.ts +1 -1
- package/dist/utils/lazy-chunks.js +1 -1
- package/dist/utils/lazy-chunks.js.map +1 -1
- package/dist/utils/prerender-output-paths.d.ts +15 -0
- package/dist/utils/prerender-output-paths.js +24 -0
- package/dist/utils/prerender-output-paths.js.map +1 -0
- package/dist/utils/query.d.ts +23 -1
- package/dist/utils/query.js +46 -2
- package/dist/utils/query.js.map +1 -1
- package/dist/utils/record.d.ts +5 -0
- package/dist/utils/record.js +8 -0
- package/dist/utils/record.js.map +1 -0
- package/package.json +11 -3
|
@@ -25,6 +25,40 @@ type PagesI18nRequestInfo = {
|
|
|
25
25
|
domainLocale?: DomainLocale;
|
|
26
26
|
redirectUrl?: string;
|
|
27
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* Prepend the default locale prefix to a pathname when i18n is configured and
|
|
30
|
+
* the path does not already carry a locale prefix. Mirrors Next.js's
|
|
31
|
+
* server-side path normalisation in `resolve-routes.ts` (lines ~250-263):
|
|
32
|
+
*
|
|
33
|
+
* if (!initialLocaleResult.detectedLocale && !pathname.startsWith('/_next/')) {
|
|
34
|
+
* parsedUrl.pathname = `/${defaultLocale}${pathname === '/' ? '' : pathname}`
|
|
35
|
+
* }
|
|
36
|
+
*
|
|
37
|
+
* Run this **before** matching against `next.config.js` redirects/rewrites
|
|
38
|
+
* (which are emitted by `applyLocaleToRoutes` in locale-prefixed forms) so
|
|
39
|
+
* that requests arriving without a locale prefix still match those rules.
|
|
40
|
+
*
|
|
41
|
+
* Skips internal paths that Next.js leaves alone:
|
|
42
|
+
* - `/_next/*` (build assets, prerender manifests, image optimisation)
|
|
43
|
+
* - `/__vinext/*` (vinext-internal endpoints)
|
|
44
|
+
*
|
|
45
|
+
* Returns the input unchanged when i18n is not configured or when the path
|
|
46
|
+
* already starts with one of the configured locales. The host-based default
|
|
47
|
+
* locale (i18n.domains[].defaultLocale) is preferred over the global default
|
|
48
|
+
* when supplied, matching Next.js's `domainLocale.defaultLocale` branch.
|
|
49
|
+
*
|
|
50
|
+
* Item 4 of issue #1336: without this normalisation, requests like
|
|
51
|
+
* `/to-sv` (default locale = en) against a rule `source: '/:locale/to-sv'`
|
|
52
|
+
* with `locale: false` do not match because there is no segment for
|
|
53
|
+
* `:locale`. After normalisation the request looks like `/en/to-sv` and
|
|
54
|
+
* the rule matches with `:locale=en`.
|
|
55
|
+
*
|
|
56
|
+
* Ported from Next.js: packages/next/src/server/lib/router-utils/resolve-routes.ts
|
|
57
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/router-utils/resolve-routes.ts
|
|
58
|
+
*/
|
|
59
|
+
declare function normalizeDefaultLocalePathname(pathname: string, i18n: NextI18nConfig | null | undefined, options?: {
|
|
60
|
+
hostname?: string | null;
|
|
61
|
+
}): string;
|
|
28
62
|
/**
|
|
29
63
|
* Extract locale prefix from a URL path.
|
|
30
64
|
* e.g. /fr/about -> { locale: "fr", url: "/about", hadPrefix: true }
|
|
@@ -35,6 +69,22 @@ declare function extractLocaleFromUrl(url: string, i18nConfig: NextI18nConfig, d
|
|
|
35
69
|
url: string;
|
|
36
70
|
hadPrefix: boolean;
|
|
37
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* Strip a leading i18n locale segment from a URL so the result can be used for
|
|
74
|
+
* API route matching. Mirrors Next.js's base-server behaviour for Pages
|
|
75
|
+
* Router API routes: `normalizeLocalePath(pathname, i18n.locales).pathname`
|
|
76
|
+
* runs before the `/api/*` check so `/fr/api/ok` resolves to the
|
|
77
|
+
* `pages/api/ok` handler instead of 404'ing.
|
|
78
|
+
*
|
|
79
|
+
* Returns the original URL untouched when:
|
|
80
|
+
* - `i18nConfig` is null/undefined (no i18n configured)
|
|
81
|
+
* - the URL does not start with a configured locale
|
|
82
|
+
*
|
|
83
|
+
* The query string is preserved verbatim — only the path segment is stripped.
|
|
84
|
+
*
|
|
85
|
+
* Reference: packages/next/src/shared/lib/i18n/normalize-locale-path.ts.
|
|
86
|
+
*/
|
|
87
|
+
declare function stripI18nLocaleForApiRoute(url: string, i18nConfig: NextI18nConfig | null | undefined): string;
|
|
38
88
|
/**
|
|
39
89
|
* Detect the preferred locale from the Accept-Language header.
|
|
40
90
|
* Returns the best matching locale or null.
|
|
@@ -53,5 +103,5 @@ declare function getLocaleRedirect({
|
|
|
53
103
|
}: LocaleRedirectOptions): string | undefined;
|
|
54
104
|
declare function resolvePagesI18nRequest(url: string, i18nConfig: NextI18nConfig, headers?: HeaderBag, hostname?: string | null, basePath?: string, trailingSlash?: boolean): PagesI18nRequestInfo;
|
|
55
105
|
//#endregion
|
|
56
|
-
export { detectDomainLocale, detectLocaleFromAcceptLanguage, extractLocaleFromUrl, getLocaleRedirect, parseCookieLocaleFromHeader, resolvePagesI18nRequest };
|
|
106
|
+
export { detectDomainLocale, detectLocaleFromAcceptLanguage, extractLocaleFromUrl, getLocaleRedirect, normalizeDefaultLocalePathname, parseCookieLocaleFromHeader, resolvePagesI18nRequest, stripI18nLocaleForApiRoute };
|
|
57
107
|
//# sourceMappingURL=pages-i18n.d.ts.map
|
|
@@ -9,6 +9,46 @@ function readHeader(headers, name) {
|
|
|
9
9
|
}
|
|
10
10
|
const normalizeHostname = normalizeDomainHostname;
|
|
11
11
|
/**
|
|
12
|
+
* Prepend the default locale prefix to a pathname when i18n is configured and
|
|
13
|
+
* the path does not already carry a locale prefix. Mirrors Next.js's
|
|
14
|
+
* server-side path normalisation in `resolve-routes.ts` (lines ~250-263):
|
|
15
|
+
*
|
|
16
|
+
* if (!initialLocaleResult.detectedLocale && !pathname.startsWith('/_next/')) {
|
|
17
|
+
* parsedUrl.pathname = `/${defaultLocale}${pathname === '/' ? '' : pathname}`
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* Run this **before** matching against `next.config.js` redirects/rewrites
|
|
21
|
+
* (which are emitted by `applyLocaleToRoutes` in locale-prefixed forms) so
|
|
22
|
+
* that requests arriving without a locale prefix still match those rules.
|
|
23
|
+
*
|
|
24
|
+
* Skips internal paths that Next.js leaves alone:
|
|
25
|
+
* - `/_next/*` (build assets, prerender manifests, image optimisation)
|
|
26
|
+
* - `/__vinext/*` (vinext-internal endpoints)
|
|
27
|
+
*
|
|
28
|
+
* Returns the input unchanged when i18n is not configured or when the path
|
|
29
|
+
* already starts with one of the configured locales. The host-based default
|
|
30
|
+
* locale (i18n.domains[].defaultLocale) is preferred over the global default
|
|
31
|
+
* when supplied, matching Next.js's `domainLocale.defaultLocale` branch.
|
|
32
|
+
*
|
|
33
|
+
* Item 4 of issue #1336: without this normalisation, requests like
|
|
34
|
+
* `/to-sv` (default locale = en) against a rule `source: '/:locale/to-sv'`
|
|
35
|
+
* with `locale: false` do not match because there is no segment for
|
|
36
|
+
* `:locale`. After normalisation the request looks like `/en/to-sv` and
|
|
37
|
+
* the rule matches with `:locale=en`.
|
|
38
|
+
*
|
|
39
|
+
* Ported from Next.js: packages/next/src/server/lib/router-utils/resolve-routes.ts
|
|
40
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/router-utils/resolve-routes.ts
|
|
41
|
+
*/
|
|
42
|
+
function normalizeDefaultLocalePathname(pathname, i18n, options = {}) {
|
|
43
|
+
if (!i18n) return pathname;
|
|
44
|
+
if (pathname.startsWith("/_next/") || pathname.startsWith("/__vinext/")) return pathname;
|
|
45
|
+
const parts = pathname.split("/", 3);
|
|
46
|
+
if (parts[1] && i18n.locales.includes(parts[1])) return pathname;
|
|
47
|
+
const defaultLocale = detectDomainLocale(i18n.domains, options.hostname ?? void 0)?.defaultLocale ?? i18n.defaultLocale;
|
|
48
|
+
if (pathname === "/") return `/${defaultLocale}`;
|
|
49
|
+
return `/${defaultLocale}${pathname}`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
12
52
|
* Extract locale prefix from a URL path.
|
|
13
53
|
* e.g. /fr/about -> { locale: "fr", url: "/about", hadPrefix: true }
|
|
14
54
|
* /about -> { locale: defaultLocale, url: "/about", hadPrefix: false }
|
|
@@ -28,6 +68,26 @@ function extractLocaleFromUrl(url, i18nConfig, defaultLocale = i18nConfig.defaul
|
|
|
28
68
|
};
|
|
29
69
|
}
|
|
30
70
|
/**
|
|
71
|
+
* Strip a leading i18n locale segment from a URL so the result can be used for
|
|
72
|
+
* API route matching. Mirrors Next.js's base-server behaviour for Pages
|
|
73
|
+
* Router API routes: `normalizeLocalePath(pathname, i18n.locales).pathname`
|
|
74
|
+
* runs before the `/api/*` check so `/fr/api/ok` resolves to the
|
|
75
|
+
* `pages/api/ok` handler instead of 404'ing.
|
|
76
|
+
*
|
|
77
|
+
* Returns the original URL untouched when:
|
|
78
|
+
* - `i18nConfig` is null/undefined (no i18n configured)
|
|
79
|
+
* - the URL does not start with a configured locale
|
|
80
|
+
*
|
|
81
|
+
* The query string is preserved verbatim — only the path segment is stripped.
|
|
82
|
+
*
|
|
83
|
+
* Reference: packages/next/src/shared/lib/i18n/normalize-locale-path.ts.
|
|
84
|
+
*/
|
|
85
|
+
function stripI18nLocaleForApiRoute(url, i18nConfig) {
|
|
86
|
+
if (!i18nConfig) return url;
|
|
87
|
+
const { url: stripped, hadPrefix } = extractLocaleFromUrl(url, i18nConfig);
|
|
88
|
+
return hadPrefix ? stripped : url;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
31
91
|
* Detect the preferred locale from the Accept-Language header.
|
|
32
92
|
* Returns the best matching locale or null.
|
|
33
93
|
*/
|
|
@@ -120,6 +180,6 @@ function resolvePagesI18nRequest(url, i18nConfig, headers, hostname, basePath =
|
|
|
120
180
|
};
|
|
121
181
|
}
|
|
122
182
|
//#endregion
|
|
123
|
-
export { detectDomainLocale, detectLocaleFromAcceptLanguage, extractLocaleFromUrl, getLocaleRedirect, parseCookieLocaleFromHeader, resolvePagesI18nRequest };
|
|
183
|
+
export { detectDomainLocale, detectLocaleFromAcceptLanguage, extractLocaleFromUrl, getLocaleRedirect, normalizeDefaultLocalePathname, parseCookieLocaleFromHeader, resolvePagesI18nRequest, stripI18nLocaleForApiRoute };
|
|
124
184
|
|
|
125
185
|
//# sourceMappingURL=pages-i18n.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages-i18n.js","names":[],"sources":["../../src/server/pages-i18n.ts"],"sourcesContent":["import type { NextI18nConfig } from \"../config/next-config.js\";\nimport {\n detectDomainLocale,\n normalizeDomainHostname,\n type DomainLocale,\n} from \"../utils/domain-locale.js\";\n\ntype HeaderValue = string | string[] | undefined;\ntype HeaderBag = Headers | Record<string, HeaderValue> | undefined;\n\ntype LocaleRedirectOptions = {\n headers?: HeaderBag;\n nextConfig: {\n basePath?: string;\n i18n?: NextI18nConfig | null;\n trailingSlash?: boolean;\n };\n pathLocale?: string;\n urlParsed: {\n hostname?: string | null;\n pathname: string;\n search?: string;\n };\n};\n\ntype PagesI18nRequestInfo = {\n locale: string;\n url: string;\n hadPrefix: boolean;\n domainLocale?: DomainLocale;\n redirectUrl?: string;\n};\n\nfunction readHeader(headers: HeaderBag, name: string): string | undefined {\n if (!headers) return undefined;\n if (headers instanceof Headers) {\n return headers.get(name) ?? undefined;\n }\n\n // For Record headers, callers must pass lowercase names. Node's\n // IncomingMessage.headers are already lowercased by the HTTP parser.\n const direct = headers[name];\n if (Array.isArray(direct)) return direct.join(\", \");\n return direct;\n}\n\nconst normalizeHostname = normalizeDomainHostname;\nexport { detectDomainLocale };\n\n/**\n * Extract locale prefix from a URL path.\n * e.g. /fr/about -> { locale: \"fr\", url: \"/about\", hadPrefix: true }\n * /about -> { locale: defaultLocale, url: \"/about\", hadPrefix: false }\n */\nexport function extractLocaleFromUrl(\n url: string,\n i18nConfig: NextI18nConfig,\n defaultLocale = i18nConfig.defaultLocale,\n): { locale: string; url: string; hadPrefix: boolean } {\n const pathname = url.split(\"?\")[0];\n const parts = pathname.split(\"/\").filter(Boolean);\n const query = url.includes(\"?\") ? url.slice(url.indexOf(\"?\")) : \"\";\n\n if (parts.length > 0 && i18nConfig.locales.includes(parts[0])) {\n const locale = parts[0];\n const rest = \"/\" + parts.slice(1).join(\"/\");\n return { locale, url: (rest || \"/\") + query, hadPrefix: true };\n }\n\n return { locale: defaultLocale, url, hadPrefix: false };\n}\n\n/**\n * Detect the preferred locale from the Accept-Language header.\n * Returns the best matching locale or null.\n */\nexport function detectLocaleFromAcceptLanguage(\n acceptLang: string | null | undefined,\n i18nConfig: NextI18nConfig,\n): string | null {\n if (!acceptLang) return null;\n\n const langs = acceptLang\n .split(\",\")\n .map((part) => {\n const [lang, qPart] = part.trim().split(\";\");\n const q = qPart ? parseFloat(qPart.replace(\"q=\", \"\")) : 1;\n return { lang: lang.trim().toLowerCase(), q };\n })\n .sort((a, b) => b.q - a.q);\n\n for (const { lang } of langs) {\n const exactMatch = i18nConfig.locales.find((locale) => locale.toLowerCase() === lang);\n if (exactMatch) return exactMatch;\n\n const prefix = lang.split(\"-\")[0];\n const prefixMatch = i18nConfig.locales.find((locale) => {\n const lowered = locale.toLowerCase();\n return lowered === prefix || lowered.startsWith(prefix + \"-\");\n });\n if (prefixMatch) return prefixMatch;\n }\n\n return null;\n}\n\n/**\n * Parse the NEXT_LOCALE cookie.\n * Returns the cookie value if it matches a configured locale, otherwise null.\n */\nexport function parseCookieLocaleFromHeader(\n cookieHeader: string | null | undefined,\n i18nConfig: NextI18nConfig,\n): string | null {\n if (!cookieHeader) return null;\n\n const match = cookieHeader.match(/(?:^|;\\s*)NEXT_LOCALE=([^;]*)/);\n if (!match) return null;\n\n let value: string;\n try {\n value = decodeURIComponent(match[1].trim());\n } catch {\n return null;\n }\n\n if (i18nConfig.locales.includes(value)) return value;\n return null;\n}\n\nfunction formatLocalizedRootPath(\n locale: string,\n defaultLocale: string,\n basePath = \"\",\n trailingSlash = false,\n search = \"\",\n): string | undefined {\n if (locale.toLowerCase() === defaultLocale.toLowerCase()) return undefined;\n const rootPath = `${basePath}/${locale}${trailingSlash ? \"/\" : \"\"}`;\n return `${rootPath.replace(/\\/{2,}/g, \"/\")}${search}`;\n}\n\nexport function getLocaleRedirect({\n headers,\n nextConfig,\n pathLocale,\n urlParsed,\n}: LocaleRedirectOptions): string | undefined {\n const i18n = nextConfig.i18n;\n // Next.js treats localeDetection as the global auto-redirect switch, so\n // disabling it also disables root domain-locale redirects, including\n // cross-domain redirects driven by the current host or Accept-Language.\n if (!i18n || i18n.localeDetection === false || urlParsed.pathname !== \"/\") return undefined;\n\n const domainLocale = detectDomainLocale(i18n.domains, urlParsed.hostname ?? undefined);\n const defaultLocale = domainLocale?.defaultLocale || i18n.defaultLocale;\n const preferredLocale =\n detectLocaleFromAcceptLanguage(readHeader(headers, \"accept-language\"), i18n) ?? undefined;\n const detectedLocale =\n pathLocale ||\n domainLocale?.defaultLocale ||\n (parseCookieLocaleFromHeader(readHeader(headers, \"cookie\"), i18n) ?? undefined) ||\n preferredLocale ||\n i18n.defaultLocale;\n const search = urlParsed.search ?? \"\";\n\n const preferredDomain = detectDomainLocale(i18n.domains, undefined, preferredLocale);\n if (domainLocale && preferredDomain) {\n const sameDomain =\n normalizeHostname(domainLocale.domain) === normalizeHostname(preferredDomain.domain);\n const sameLocale =\n preferredLocale !== undefined &&\n preferredDomain.defaultLocale.toLowerCase() === preferredLocale.toLowerCase();\n\n if (!sameDomain || !sameLocale) {\n // sameDomain && !sameLocale yields a locale-prefixed redirect on the same\n // host (for example /nl-BE). This matches Next.js and doesn't loop because\n // the next request is prefixed and therefore skips getLocaleRedirect().\n const scheme = `http${preferredDomain.http ? \"\" : \"s\"}`;\n const localePath = sameLocale || preferredLocale === undefined ? \"\" : `/${preferredLocale}`;\n const basePath = nextConfig.basePath ?? \"\";\n const rootPath = `${basePath}${localePath}${nextConfig.trailingSlash ? \"/\" : \"\"}` || \"/\";\n const normalizedPath = rootPath.startsWith(\"/\") ? rootPath : `/${rootPath}`;\n return `${scheme}://${preferredDomain.domain}${normalizedPath}${search}`;\n }\n }\n\n return formatLocalizedRootPath(\n detectedLocale,\n defaultLocale,\n nextConfig.basePath,\n nextConfig.trailingSlash,\n search,\n );\n}\n\nexport function resolvePagesI18nRequest(\n url: string,\n i18nConfig: NextI18nConfig,\n headers?: HeaderBag,\n hostname?: string | null,\n basePath = \"\",\n trailingSlash = false,\n): PagesI18nRequestInfo {\n const domainLocale = detectDomainLocale(i18nConfig.domains, hostname ?? undefined);\n const defaultLocale = domainLocale?.defaultLocale || i18nConfig.defaultLocale;\n const localeInfo = extractLocaleFromUrl(url, i18nConfig, defaultLocale);\n\n let redirectUrl: string | undefined;\n if (!localeInfo.hadPrefix) {\n redirectUrl = getLocaleRedirect({\n headers,\n nextConfig: {\n basePath,\n i18n: i18nConfig,\n trailingSlash,\n },\n urlParsed: {\n hostname,\n pathname: localeInfo.url.split(\"?\")[0] || \"/\",\n search: localeInfo.url.includes(\"?\")\n ? localeInfo.url.slice(localeInfo.url.indexOf(\"?\"))\n : \"\",\n },\n });\n }\n\n return {\n ...localeInfo,\n domainLocale,\n redirectUrl,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pages-i18n.js","names":[],"sources":["../../src/server/pages-i18n.ts"],"sourcesContent":["import type { NextI18nConfig } from \"../config/next-config.js\";\nimport {\n detectDomainLocale,\n normalizeDomainHostname,\n type DomainLocale,\n} from \"../utils/domain-locale.js\";\n\ntype HeaderValue = string | string[] | undefined;\ntype HeaderBag = Headers | Record<string, HeaderValue> | undefined;\n\ntype LocaleRedirectOptions = {\n headers?: HeaderBag;\n nextConfig: {\n basePath?: string;\n i18n?: NextI18nConfig | null;\n trailingSlash?: boolean;\n };\n pathLocale?: string;\n urlParsed: {\n hostname?: string | null;\n pathname: string;\n search?: string;\n };\n};\n\ntype PagesI18nRequestInfo = {\n locale: string;\n url: string;\n hadPrefix: boolean;\n domainLocale?: DomainLocale;\n redirectUrl?: string;\n};\n\nfunction readHeader(headers: HeaderBag, name: string): string | undefined {\n if (!headers) return undefined;\n if (headers instanceof Headers) {\n return headers.get(name) ?? undefined;\n }\n\n // For Record headers, callers must pass lowercase names. Node's\n // IncomingMessage.headers are already lowercased by the HTTP parser.\n const direct = headers[name];\n if (Array.isArray(direct)) return direct.join(\", \");\n return direct;\n}\n\nconst normalizeHostname = normalizeDomainHostname;\nexport { detectDomainLocale };\n\n/**\n * Prepend the default locale prefix to a pathname when i18n is configured and\n * the path does not already carry a locale prefix. Mirrors Next.js's\n * server-side path normalisation in `resolve-routes.ts` (lines ~250-263):\n *\n * if (!initialLocaleResult.detectedLocale && !pathname.startsWith('/_next/')) {\n * parsedUrl.pathname = `/${defaultLocale}${pathname === '/' ? '' : pathname}`\n * }\n *\n * Run this **before** matching against `next.config.js` redirects/rewrites\n * (which are emitted by `applyLocaleToRoutes` in locale-prefixed forms) so\n * that requests arriving without a locale prefix still match those rules.\n *\n * Skips internal paths that Next.js leaves alone:\n * - `/_next/*` (build assets, prerender manifests, image optimisation)\n * - `/__vinext/*` (vinext-internal endpoints)\n *\n * Returns the input unchanged when i18n is not configured or when the path\n * already starts with one of the configured locales. The host-based default\n * locale (i18n.domains[].defaultLocale) is preferred over the global default\n * when supplied, matching Next.js's `domainLocale.defaultLocale` branch.\n *\n * Item 4 of issue #1336: without this normalisation, requests like\n * `/to-sv` (default locale = en) against a rule `source: '/:locale/to-sv'`\n * with `locale: false` do not match because there is no segment for\n * `:locale`. After normalisation the request looks like `/en/to-sv` and\n * the rule matches with `:locale=en`.\n *\n * Ported from Next.js: packages/next/src/server/lib/router-utils/resolve-routes.ts\n * https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/router-utils/resolve-routes.ts\n */\nexport function normalizeDefaultLocalePathname(\n pathname: string,\n i18n: NextI18nConfig | null | undefined,\n options: { hostname?: string | null } = {},\n): string {\n if (!i18n) return pathname;\n // Don't touch internal paths.\n if (pathname.startsWith(\"/_next/\") || pathname.startsWith(\"/__vinext/\")) return pathname;\n // If the path already starts with a known locale, leave it alone.\n const parts = pathname.split(\"/\", 3);\n // parts[0] is the empty string before the leading \"/\", parts[1] is the first segment.\n if (parts[1] && i18n.locales.includes(parts[1])) return pathname;\n\n // Pick the default locale: prefer the domain-mapped one when host matches.\n const domainLocale = detectDomainLocale(i18n.domains, options.hostname ?? undefined);\n const defaultLocale = domainLocale?.defaultLocale ?? i18n.defaultLocale;\n\n if (pathname === \"/\") return `/${defaultLocale}`;\n return `/${defaultLocale}${pathname}`;\n}\n\n/**\n * Extract locale prefix from a URL path.\n * e.g. /fr/about -> { locale: \"fr\", url: \"/about\", hadPrefix: true }\n * /about -> { locale: defaultLocale, url: \"/about\", hadPrefix: false }\n */\nexport function extractLocaleFromUrl(\n url: string,\n i18nConfig: NextI18nConfig,\n defaultLocale = i18nConfig.defaultLocale,\n): { locale: string; url: string; hadPrefix: boolean } {\n const pathname = url.split(\"?\")[0];\n const parts = pathname.split(\"/\").filter(Boolean);\n const query = url.includes(\"?\") ? url.slice(url.indexOf(\"?\")) : \"\";\n\n if (parts.length > 0 && i18nConfig.locales.includes(parts[0])) {\n const locale = parts[0];\n const rest = \"/\" + parts.slice(1).join(\"/\");\n return { locale, url: (rest || \"/\") + query, hadPrefix: true };\n }\n\n return { locale: defaultLocale, url, hadPrefix: false };\n}\n\n/**\n * Strip a leading i18n locale segment from a URL so the result can be used for\n * API route matching. Mirrors Next.js's base-server behaviour for Pages\n * Router API routes: `normalizeLocalePath(pathname, i18n.locales).pathname`\n * runs before the `/api/*` check so `/fr/api/ok` resolves to the\n * `pages/api/ok` handler instead of 404'ing.\n *\n * Returns the original URL untouched when:\n * - `i18nConfig` is null/undefined (no i18n configured)\n * - the URL does not start with a configured locale\n *\n * The query string is preserved verbatim — only the path segment is stripped.\n *\n * Reference: packages/next/src/shared/lib/i18n/normalize-locale-path.ts.\n */\nexport function stripI18nLocaleForApiRoute(\n url: string,\n i18nConfig: NextI18nConfig | null | undefined,\n): string {\n if (!i18nConfig) return url;\n const { url: stripped, hadPrefix } = extractLocaleFromUrl(url, i18nConfig);\n return hadPrefix ? stripped : url;\n}\n\n/**\n * Detect the preferred locale from the Accept-Language header.\n * Returns the best matching locale or null.\n */\nexport function detectLocaleFromAcceptLanguage(\n acceptLang: string | null | undefined,\n i18nConfig: NextI18nConfig,\n): string | null {\n if (!acceptLang) return null;\n\n const langs = acceptLang\n .split(\",\")\n .map((part) => {\n const [lang, qPart] = part.trim().split(\";\");\n const q = qPart ? parseFloat(qPart.replace(\"q=\", \"\")) : 1;\n return { lang: lang.trim().toLowerCase(), q };\n })\n .sort((a, b) => b.q - a.q);\n\n for (const { lang } of langs) {\n const exactMatch = i18nConfig.locales.find((locale) => locale.toLowerCase() === lang);\n if (exactMatch) return exactMatch;\n\n const prefix = lang.split(\"-\")[0];\n const prefixMatch = i18nConfig.locales.find((locale) => {\n const lowered = locale.toLowerCase();\n return lowered === prefix || lowered.startsWith(prefix + \"-\");\n });\n if (prefixMatch) return prefixMatch;\n }\n\n return null;\n}\n\n/**\n * Parse the NEXT_LOCALE cookie.\n * Returns the cookie value if it matches a configured locale, otherwise null.\n */\nexport function parseCookieLocaleFromHeader(\n cookieHeader: string | null | undefined,\n i18nConfig: NextI18nConfig,\n): string | null {\n if (!cookieHeader) return null;\n\n const match = cookieHeader.match(/(?:^|;\\s*)NEXT_LOCALE=([^;]*)/);\n if (!match) return null;\n\n let value: string;\n try {\n value = decodeURIComponent(match[1].trim());\n } catch {\n return null;\n }\n\n if (i18nConfig.locales.includes(value)) return value;\n return null;\n}\n\nfunction formatLocalizedRootPath(\n locale: string,\n defaultLocale: string,\n basePath = \"\",\n trailingSlash = false,\n search = \"\",\n): string | undefined {\n if (locale.toLowerCase() === defaultLocale.toLowerCase()) return undefined;\n const rootPath = `${basePath}/${locale}${trailingSlash ? \"/\" : \"\"}`;\n return `${rootPath.replace(/\\/{2,}/g, \"/\")}${search}`;\n}\n\nexport function getLocaleRedirect({\n headers,\n nextConfig,\n pathLocale,\n urlParsed,\n}: LocaleRedirectOptions): string | undefined {\n const i18n = nextConfig.i18n;\n // Next.js treats localeDetection as the global auto-redirect switch, so\n // disabling it also disables root domain-locale redirects, including\n // cross-domain redirects driven by the current host or Accept-Language.\n if (!i18n || i18n.localeDetection === false || urlParsed.pathname !== \"/\") return undefined;\n\n const domainLocale = detectDomainLocale(i18n.domains, urlParsed.hostname ?? undefined);\n const defaultLocale = domainLocale?.defaultLocale || i18n.defaultLocale;\n const preferredLocale =\n detectLocaleFromAcceptLanguage(readHeader(headers, \"accept-language\"), i18n) ?? undefined;\n const detectedLocale =\n pathLocale ||\n domainLocale?.defaultLocale ||\n (parseCookieLocaleFromHeader(readHeader(headers, \"cookie\"), i18n) ?? undefined) ||\n preferredLocale ||\n i18n.defaultLocale;\n const search = urlParsed.search ?? \"\";\n\n const preferredDomain = detectDomainLocale(i18n.domains, undefined, preferredLocale);\n if (domainLocale && preferredDomain) {\n const sameDomain =\n normalizeHostname(domainLocale.domain) === normalizeHostname(preferredDomain.domain);\n const sameLocale =\n preferredLocale !== undefined &&\n preferredDomain.defaultLocale.toLowerCase() === preferredLocale.toLowerCase();\n\n if (!sameDomain || !sameLocale) {\n // sameDomain && !sameLocale yields a locale-prefixed redirect on the same\n // host (for example /nl-BE). This matches Next.js and doesn't loop because\n // the next request is prefixed and therefore skips getLocaleRedirect().\n const scheme = `http${preferredDomain.http ? \"\" : \"s\"}`;\n const localePath = sameLocale || preferredLocale === undefined ? \"\" : `/${preferredLocale}`;\n const basePath = nextConfig.basePath ?? \"\";\n const rootPath = `${basePath}${localePath}${nextConfig.trailingSlash ? \"/\" : \"\"}` || \"/\";\n const normalizedPath = rootPath.startsWith(\"/\") ? rootPath : `/${rootPath}`;\n return `${scheme}://${preferredDomain.domain}${normalizedPath}${search}`;\n }\n }\n\n return formatLocalizedRootPath(\n detectedLocale,\n defaultLocale,\n nextConfig.basePath,\n nextConfig.trailingSlash,\n search,\n );\n}\n\nexport function resolvePagesI18nRequest(\n url: string,\n i18nConfig: NextI18nConfig,\n headers?: HeaderBag,\n hostname?: string | null,\n basePath = \"\",\n trailingSlash = false,\n): PagesI18nRequestInfo {\n const domainLocale = detectDomainLocale(i18nConfig.domains, hostname ?? undefined);\n const defaultLocale = domainLocale?.defaultLocale || i18nConfig.defaultLocale;\n const localeInfo = extractLocaleFromUrl(url, i18nConfig, defaultLocale);\n\n let redirectUrl: string | undefined;\n if (!localeInfo.hadPrefix) {\n redirectUrl = getLocaleRedirect({\n headers,\n nextConfig: {\n basePath,\n i18n: i18nConfig,\n trailingSlash,\n },\n urlParsed: {\n hostname,\n pathname: localeInfo.url.split(\"?\")[0] || \"/\",\n search: localeInfo.url.includes(\"?\")\n ? localeInfo.url.slice(localeInfo.url.indexOf(\"?\"))\n : \"\",\n },\n });\n }\n\n return {\n ...localeInfo,\n domainLocale,\n redirectUrl,\n };\n}\n"],"mappings":"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"}
|
|
@@ -37,6 +37,16 @@ type CreatePagesReqResResult = {
|
|
|
37
37
|
res: PagesReqResResponse;
|
|
38
38
|
responsePromise: Promise<Response>;
|
|
39
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* Read and parse a Pages Router API request body for the Workers/prod path.
|
|
42
|
+
*
|
|
43
|
+
* `maxBytes` defaults to the 1 MB Next.js default but may be overridden by
|
|
44
|
+
* `export const config = { api: { bodyParser: { sizeLimit: '4mb' } } }` on
|
|
45
|
+
* the route module. Handlers that opt out entirely (`bodyParser: false`)
|
|
46
|
+
* MUST skip this function so the body stream stays intact for user code.
|
|
47
|
+
*
|
|
48
|
+
* @see https://nextjs.org/docs/pages/building-your-application/routing/api-routes#custom-config
|
|
49
|
+
*/
|
|
40
50
|
declare function parsePagesApiBody(request: Request, maxBytes?: number): Promise<unknown>;
|
|
41
51
|
declare function createPagesReqRes(options: CreatePagesReqResOptions): CreatePagesReqResResult;
|
|
42
52
|
//#endregion
|
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import { parseCookies } from "../config/config-matchers.js";
|
|
2
2
|
import { PagesBodyParseError, getMediaType, isJsonMediaType } from "./pages-media-type.js";
|
|
3
|
+
import { DEFAULT_PAGES_API_BODY_SIZE_LIMIT } from "./pages-body-parser-config.js";
|
|
3
4
|
import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
|
|
4
5
|
import { decode } from "node:querystring";
|
|
5
6
|
//#region src/server/pages-node-compat.ts
|
|
6
|
-
const MAX_PAGES_API_BODY_SIZE =
|
|
7
|
+
const MAX_PAGES_API_BODY_SIZE = DEFAULT_PAGES_API_BODY_SIZE_LIMIT;
|
|
7
8
|
async function readPagesRequestBodyWithLimit(request, maxBytes) {
|
|
8
9
|
if (!request.body) return "";
|
|
9
10
|
return readStreamAsTextWithLimit(request.body, maxBytes, () => {
|
|
10
11
|
throw new PagesBodyParseError("Request body too large", 413);
|
|
11
12
|
});
|
|
12
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Read and parse a Pages Router API request body for the Workers/prod path.
|
|
16
|
+
*
|
|
17
|
+
* `maxBytes` defaults to the 1 MB Next.js default but may be overridden by
|
|
18
|
+
* `export const config = { api: { bodyParser: { sizeLimit: '4mb' } } }` on
|
|
19
|
+
* the route module. Handlers that opt out entirely (`bodyParser: false`)
|
|
20
|
+
* MUST skip this function so the body stream stays intact for user code.
|
|
21
|
+
*
|
|
22
|
+
* @see https://nextjs.org/docs/pages/building-your-application/routing/api-routes#custom-config
|
|
23
|
+
*/
|
|
13
24
|
async function parsePagesApiBody(request, maxBytes = MAX_PAGES_API_BODY_SIZE) {
|
|
14
25
|
if (Number.parseInt(request.headers.get("content-length") || "0", 10) > maxBytes) throw new PagesBodyParseError("Request body too large", 413);
|
|
15
26
|
let rawBody = "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages-node-compat.js","names":["decodeQueryString"],"sources":["../../src/server/pages-node-compat.ts"],"sourcesContent":["import { decode as decodeQueryString } from \"node:querystring\";\nimport { parseCookies } from \"../config/config-matchers.js\";\nimport { readStreamAsTextWithLimit } from \"../utils/text-stream.js\";\nimport { PagesBodyParseError, getMediaType, isJsonMediaType } from \"./pages-media-type.js\";\n\nconst MAX_PAGES_API_BODY_SIZE = 1 * 1024 * 1024;\n\n/**\n * @deprecated Use PagesBodyParseError from pages-media-type.ts instead.\n * Kept for backwards compatibility.\n */\nexport { PagesBodyParseError as PagesApiBodyParseError };\n\nexport type PagesRequestQuery = Record<string, string | string[]>;\n\nexport type PagesReqResRequest = {\n method: string;\n url: string;\n headers: Record<string, string>;\n query: PagesRequestQuery;\n body: unknown;\n cookies: Record<string, string>;\n};\n\nexport type PagesReqResHeaders = {\n [key: string]: string | number | boolean | string[];\n};\n\nexport type PagesReqResResponse = {\n statusCode: number;\n readonly headersSent: boolean;\n writeHead: (code: number, headers?: PagesReqResHeaders) => PagesReqResResponse;\n setHeader: (name: string, value: string | number | boolean | string[]) => PagesReqResResponse;\n getHeader: (name: string) => string | number | boolean | string[] | undefined;\n end: (data?: BodyInit | null) => void;\n status: (code: number) => PagesReqResResponse;\n json: (data: unknown) => void;\n send: (data: unknown) => void;\n redirect: (statusOrUrl: number | string, url?: string) => void;\n getHeaders: () => PagesReqResHeaders;\n};\n\ntype CreatePagesReqResOptions = {\n body: unknown;\n query: PagesRequestQuery;\n request: Request;\n url: string;\n};\n\ntype CreatePagesReqResResult = {\n req: PagesReqResRequest;\n res: PagesReqResResponse;\n responsePromise: Promise<Response>;\n};\n\nasync function readPagesRequestBodyWithLimit(request: Request, maxBytes: number): Promise<string> {\n if (!request.body) {\n return \"\";\n }\n\n return readStreamAsTextWithLimit(request.body, maxBytes, () => {\n throw new PagesBodyParseError(\"Request body too large\", 413);\n });\n}\n\nexport async function parsePagesApiBody(\n request: Request,\n maxBytes = MAX_PAGES_API_BODY_SIZE,\n): Promise<unknown> {\n const contentLength = Number.parseInt(request.headers.get(\"content-length\") || \"0\", 10);\n if (contentLength > maxBytes) {\n throw new PagesBodyParseError(\"Request body too large\", 413);\n }\n\n let rawBody = \"\";\n try {\n rawBody = await readPagesRequestBodyWithLimit(request, maxBytes);\n } catch (err) {\n if (err instanceof PagesBodyParseError) {\n throw err;\n }\n throw new PagesBodyParseError(\"Request body too large\", 413);\n }\n\n const mediaType = getMediaType(request.headers.get(\"content-type\"));\n if (!rawBody) {\n return isJsonMediaType(mediaType)\n ? {}\n : mediaType === \"application/x-www-form-urlencoded\"\n ? decodeQueryString(rawBody)\n : undefined;\n }\n\n if (isJsonMediaType(mediaType)) {\n try {\n return JSON.parse(rawBody);\n } catch {\n throw new PagesBodyParseError(\"Invalid JSON\", 400);\n }\n }\n\n if (mediaType === \"application/x-www-form-urlencoded\") {\n return decodeQueryString(rawBody);\n }\n\n return rawBody;\n}\n\nexport function createPagesReqRes(options: CreatePagesReqResOptions): CreatePagesReqResResult {\n const headersObj: Record<string, string> = {};\n for (const [key, value] of options.request.headers) {\n headersObj[key.toLowerCase()] = value;\n }\n\n const req: PagesReqResRequest = {\n method: options.request.method,\n url: options.url,\n headers: headersObj,\n query: options.query,\n body: options.body,\n cookies: parseCookies(options.request.headers.get(\"cookie\")),\n };\n\n let resStatusCode = 200;\n const resHeaders: Record<string, string | number | boolean> = {};\n const setCookieHeaders: string[] = [];\n let resBody: BodyInit | null = null;\n let ended = false;\n let resolveResponse!: (value: Response) => void;\n const responsePromise = new Promise<Response>((resolve) => {\n resolveResponse = resolve;\n });\n\n const res: PagesReqResResponse = {\n get statusCode() {\n return resStatusCode;\n },\n set statusCode(code) {\n resStatusCode = code;\n },\n get headersSent() {\n return ended;\n },\n writeHead(code, headers) {\n resStatusCode = code;\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === \"set-cookie\") {\n if (Array.isArray(value)) {\n setCookieHeaders.push(...value.map(String));\n } else {\n setCookieHeaders.push(String(value));\n }\n } else {\n resHeaders[key.toLowerCase()] = Array.isArray(value) ? value.join(\", \") : value;\n }\n }\n }\n return res;\n },\n setHeader(name, value) {\n if (name.toLowerCase() === \"set-cookie\") {\n // Node.js res.setHeader() replaces the existing value entirely.\n setCookieHeaders.length = 0;\n if (Array.isArray(value)) {\n setCookieHeaders.push(...value.map(String));\n } else {\n setCookieHeaders.push(String(value));\n }\n } else {\n resHeaders[name.toLowerCase()] = Array.isArray(value) ? value.join(\", \") : value;\n }\n return res;\n },\n getHeader(name) {\n if (name.toLowerCase() === \"set-cookie\") {\n return setCookieHeaders.length > 0 ? setCookieHeaders : undefined;\n }\n return resHeaders[name.toLowerCase()];\n },\n end(data) {\n if (ended) {\n return;\n }\n ended = true;\n if (data !== undefined && data !== null) {\n resBody = data;\n }\n const headers = new Headers();\n for (const [key, value] of Object.entries(resHeaders)) {\n headers.set(key, String(value));\n }\n for (const cookie of setCookieHeaders) {\n headers.append(\"set-cookie\", cookie);\n }\n resolveResponse(new Response(resBody, { status: resStatusCode, headers }));\n },\n status(code) {\n resStatusCode = code;\n return res;\n },\n json(data) {\n resHeaders[\"content-type\"] = \"application/json\";\n res.end(JSON.stringify(data));\n },\n send(data) {\n if (Buffer.isBuffer(data)) {\n if (!resHeaders[\"content-type\"]) {\n resHeaders[\"content-type\"] = \"application/octet-stream\";\n }\n resHeaders[\"content-length\"] = String(data.length);\n res.end(new Uint8Array(data));\n return;\n }\n\n if (typeof data === \"object\" && data !== null) {\n resHeaders[\"content-type\"] = \"application/json\";\n res.end(JSON.stringify(data));\n return;\n }\n\n if (!resHeaders[\"content-type\"]) {\n resHeaders[\"content-type\"] = \"text/plain\";\n }\n res.end(String(data));\n },\n redirect(statusOrUrl, url) {\n if (typeof statusOrUrl === \"string\") {\n res.writeHead(307, { Location: statusOrUrl });\n } else {\n res.writeHead(statusOrUrl, { Location: url ?? \"\" });\n }\n res.end();\n },\n getHeaders() {\n const headers: PagesReqResHeaders = { ...resHeaders };\n if (setCookieHeaders.length > 0) {\n headers[\"set-cookie\"] = setCookieHeaders;\n }\n return headers;\n },\n };\n\n return { req, res, responsePromise };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pages-node-compat.js","names":["decodeQueryString"],"sources":["../../src/server/pages-node-compat.ts"],"sourcesContent":["import { decode as decodeQueryString } from \"node:querystring\";\nimport { parseCookies } from \"../config/config-matchers.js\";\nimport { readStreamAsTextWithLimit } from \"../utils/text-stream.js\";\nimport { DEFAULT_PAGES_API_BODY_SIZE_LIMIT } from \"./pages-body-parser-config.js\";\nimport { PagesBodyParseError, getMediaType, isJsonMediaType } from \"./pages-media-type.js\";\n\nconst MAX_PAGES_API_BODY_SIZE = DEFAULT_PAGES_API_BODY_SIZE_LIMIT;\n\n/**\n * @deprecated Use PagesBodyParseError from pages-media-type.ts instead.\n * Kept for backwards compatibility.\n */\nexport { PagesBodyParseError as PagesApiBodyParseError };\n\nexport type PagesRequestQuery = Record<string, string | string[]>;\n\nexport type PagesReqResRequest = {\n method: string;\n url: string;\n headers: Record<string, string>;\n query: PagesRequestQuery;\n body: unknown;\n cookies: Record<string, string>;\n};\n\nexport type PagesReqResHeaders = {\n [key: string]: string | number | boolean | string[];\n};\n\nexport type PagesReqResResponse = {\n statusCode: number;\n readonly headersSent: boolean;\n writeHead: (code: number, headers?: PagesReqResHeaders) => PagesReqResResponse;\n setHeader: (name: string, value: string | number | boolean | string[]) => PagesReqResResponse;\n getHeader: (name: string) => string | number | boolean | string[] | undefined;\n end: (data?: BodyInit | null) => void;\n status: (code: number) => PagesReqResResponse;\n json: (data: unknown) => void;\n send: (data: unknown) => void;\n redirect: (statusOrUrl: number | string, url?: string) => void;\n getHeaders: () => PagesReqResHeaders;\n};\n\ntype CreatePagesReqResOptions = {\n body: unknown;\n query: PagesRequestQuery;\n request: Request;\n url: string;\n};\n\ntype CreatePagesReqResResult = {\n req: PagesReqResRequest;\n res: PagesReqResResponse;\n responsePromise: Promise<Response>;\n};\n\nasync function readPagesRequestBodyWithLimit(request: Request, maxBytes: number): Promise<string> {\n if (!request.body) {\n return \"\";\n }\n\n return readStreamAsTextWithLimit(request.body, maxBytes, () => {\n throw new PagesBodyParseError(\"Request body too large\", 413);\n });\n}\n\n/**\n * Read and parse a Pages Router API request body for the Workers/prod path.\n *\n * `maxBytes` defaults to the 1 MB Next.js default but may be overridden by\n * `export const config = { api: { bodyParser: { sizeLimit: '4mb' } } }` on\n * the route module. Handlers that opt out entirely (`bodyParser: false`)\n * MUST skip this function so the body stream stays intact for user code.\n *\n * @see https://nextjs.org/docs/pages/building-your-application/routing/api-routes#custom-config\n */\nexport async function parsePagesApiBody(\n request: Request,\n maxBytes = MAX_PAGES_API_BODY_SIZE,\n): Promise<unknown> {\n const contentLength = Number.parseInt(request.headers.get(\"content-length\") || \"0\", 10);\n if (contentLength > maxBytes) {\n throw new PagesBodyParseError(\"Request body too large\", 413);\n }\n\n let rawBody = \"\";\n try {\n rawBody = await readPagesRequestBodyWithLimit(request, maxBytes);\n } catch (err) {\n if (err instanceof PagesBodyParseError) {\n throw err;\n }\n throw new PagesBodyParseError(\"Request body too large\", 413);\n }\n\n const mediaType = getMediaType(request.headers.get(\"content-type\"));\n if (!rawBody) {\n return isJsonMediaType(mediaType)\n ? {}\n : mediaType === \"application/x-www-form-urlencoded\"\n ? decodeQueryString(rawBody)\n : undefined;\n }\n\n if (isJsonMediaType(mediaType)) {\n try {\n return JSON.parse(rawBody);\n } catch {\n throw new PagesBodyParseError(\"Invalid JSON\", 400);\n }\n }\n\n if (mediaType === \"application/x-www-form-urlencoded\") {\n return decodeQueryString(rawBody);\n }\n\n return rawBody;\n}\n\nexport function createPagesReqRes(options: CreatePagesReqResOptions): CreatePagesReqResResult {\n const headersObj: Record<string, string> = {};\n for (const [key, value] of options.request.headers) {\n headersObj[key.toLowerCase()] = value;\n }\n\n const req: PagesReqResRequest = {\n method: options.request.method,\n url: options.url,\n headers: headersObj,\n query: options.query,\n body: options.body,\n cookies: parseCookies(options.request.headers.get(\"cookie\")),\n };\n\n let resStatusCode = 200;\n const resHeaders: Record<string, string | number | boolean> = {};\n const setCookieHeaders: string[] = [];\n let resBody: BodyInit | null = null;\n let ended = false;\n let resolveResponse!: (value: Response) => void;\n const responsePromise = new Promise<Response>((resolve) => {\n resolveResponse = resolve;\n });\n\n const res: PagesReqResResponse = {\n get statusCode() {\n return resStatusCode;\n },\n set statusCode(code) {\n resStatusCode = code;\n },\n get headersSent() {\n return ended;\n },\n writeHead(code, headers) {\n resStatusCode = code;\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === \"set-cookie\") {\n if (Array.isArray(value)) {\n setCookieHeaders.push(...value.map(String));\n } else {\n setCookieHeaders.push(String(value));\n }\n } else {\n resHeaders[key.toLowerCase()] = Array.isArray(value) ? value.join(\", \") : value;\n }\n }\n }\n return res;\n },\n setHeader(name, value) {\n if (name.toLowerCase() === \"set-cookie\") {\n // Node.js res.setHeader() replaces the existing value entirely.\n setCookieHeaders.length = 0;\n if (Array.isArray(value)) {\n setCookieHeaders.push(...value.map(String));\n } else {\n setCookieHeaders.push(String(value));\n }\n } else {\n resHeaders[name.toLowerCase()] = Array.isArray(value) ? value.join(\", \") : value;\n }\n return res;\n },\n getHeader(name) {\n if (name.toLowerCase() === \"set-cookie\") {\n return setCookieHeaders.length > 0 ? setCookieHeaders : undefined;\n }\n return resHeaders[name.toLowerCase()];\n },\n end(data) {\n if (ended) {\n return;\n }\n ended = true;\n if (data !== undefined && data !== null) {\n resBody = data;\n }\n const headers = new Headers();\n for (const [key, value] of Object.entries(resHeaders)) {\n headers.set(key, String(value));\n }\n for (const cookie of setCookieHeaders) {\n headers.append(\"set-cookie\", cookie);\n }\n resolveResponse(new Response(resBody, { status: resStatusCode, headers }));\n },\n status(code) {\n resStatusCode = code;\n return res;\n },\n json(data) {\n resHeaders[\"content-type\"] = \"application/json\";\n res.end(JSON.stringify(data));\n },\n send(data) {\n if (Buffer.isBuffer(data)) {\n if (!resHeaders[\"content-type\"]) {\n resHeaders[\"content-type\"] = \"application/octet-stream\";\n }\n resHeaders[\"content-length\"] = String(data.length);\n res.end(new Uint8Array(data));\n return;\n }\n\n if (typeof data === \"object\" && data !== null) {\n resHeaders[\"content-type\"] = \"application/json\";\n res.end(JSON.stringify(data));\n return;\n }\n\n if (!resHeaders[\"content-type\"]) {\n resHeaders[\"content-type\"] = \"text/plain\";\n }\n res.end(String(data));\n },\n redirect(statusOrUrl, url) {\n if (typeof statusOrUrl === \"string\") {\n res.writeHead(307, { Location: statusOrUrl });\n } else {\n res.writeHead(statusOrUrl, { Location: url ?? \"\" });\n }\n res.end();\n },\n getHeaders() {\n const headers: PagesReqResHeaders = { ...resHeaders };\n if (setCookieHeaders.length > 0) {\n headers[\"set-cookie\"] = setCookieHeaders;\n }\n return headers;\n },\n };\n\n return { req, res, responsePromise };\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Route } from "../routing/pages-router.js";
|
|
2
|
+
import { VinextNextData } from "../client/vinext-next-data.js";
|
|
2
3
|
import { CachedPagesValue } from "../shims/cache.js";
|
|
3
4
|
import { ISRCacheEntry } from "./isr-cache.js";
|
|
4
5
|
import { PagesGsspResponse, PagesI18nRenderContext } from "./pages-page-response.js";
|
|
@@ -38,8 +39,19 @@ type PagesPageModule = {
|
|
|
38
39
|
locales: string[];
|
|
39
40
|
defaultLocale: string;
|
|
40
41
|
}) => Promise<PagesStaticPathsResult> | PagesStaticPathsResult;
|
|
42
|
+
/**
|
|
43
|
+
* Pages Router data-fetching context.
|
|
44
|
+
*
|
|
45
|
+
* `params` is `null` for non-dynamic routes (no `[param]` segments) to
|
|
46
|
+
* match Next.js. User code typically falls back via `params || null`, so
|
|
47
|
+
* passing `null` (rather than `{}`) is required for the value to be
|
|
48
|
+
* observable as `null` once the data flows through to the page props.
|
|
49
|
+
*
|
|
50
|
+
* See: test/e2e/edge-pages-support/index.test.ts in Next.js for the
|
|
51
|
+
* authoritative assertion (`expect(props.params).toBe(null)`).
|
|
52
|
+
*/
|
|
41
53
|
getServerSideProps?: (context: {
|
|
42
|
-
params: Record<string, unknown
|
|
54
|
+
params: Record<string, unknown> | null;
|
|
43
55
|
req: unknown;
|
|
44
56
|
res: PagesMutableGsspResponse;
|
|
45
57
|
query: Record<string, unknown>;
|
|
@@ -49,10 +61,22 @@ type PagesPageModule = {
|
|
|
49
61
|
defaultLocale?: string;
|
|
50
62
|
}) => Promise<PagesPagePropsResult> | PagesPagePropsResult;
|
|
51
63
|
getStaticProps?: (context: {
|
|
52
|
-
params: Record<string, unknown
|
|
64
|
+
params: Record<string, unknown> | null;
|
|
53
65
|
locale?: string;
|
|
54
66
|
locales?: string[];
|
|
55
67
|
defaultLocale?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Indicates why `getStaticProps` was invoked.
|
|
70
|
+
*
|
|
71
|
+
* - `"build"`: initial build-time prerender (before runtime traffic).
|
|
72
|
+
* - `"on-demand"`: triggered by `res.revalidate()` from an API route.
|
|
73
|
+
* - `"stale"`: stale-while-revalidate background regeneration.
|
|
74
|
+
*
|
|
75
|
+
* Mirrors Next.js `render.tsx`'s `revalidateReason` on the
|
|
76
|
+
* `GetStaticPropsContext` type — see
|
|
77
|
+
* `.nextjs-ref/packages/next/src/types.ts`.
|
|
78
|
+
*/
|
|
79
|
+
revalidateReason?: "build" | "on-demand" | "stale";
|
|
56
80
|
}) => Promise<PagesPagePropsResult> | PagesPagePropsResult;
|
|
57
81
|
};
|
|
58
82
|
type RenderPagesIsrHtmlOptions = {
|
|
@@ -65,10 +89,20 @@ type RenderPagesIsrHtmlOptions = {
|
|
|
65
89
|
renderIsrPassToStringAsync: (element: ReactNode) => Promise<string>;
|
|
66
90
|
routePattern: string;
|
|
67
91
|
safeJsonStringify: (value: unknown) => string;
|
|
92
|
+
vinext?: VinextNextData["__vinext"];
|
|
68
93
|
};
|
|
69
94
|
type ResolvePagesPageDataOptions = {
|
|
70
95
|
applyRequestContexts: () => void;
|
|
71
96
|
buildId: string | null;
|
|
97
|
+
/**
|
|
98
|
+
* When true, this is a `/_next/data/<buildId>/<page>.json` request. Callers
|
|
99
|
+
* that respond with a JSON envelope (`{ pageProps }`) instead of HTML must
|
|
100
|
+
* bypass the HTML ISR cache: a cached HTML body cannot be reshaped into the
|
|
101
|
+
* expected JSON shape, and storing JSON in the HTML cache would corrupt
|
|
102
|
+
* subsequent HTML hits. Next.js handles this the same way — see
|
|
103
|
+
* `isNextDataRequest` checks in `packages/next/src/server/base-server.ts`.
|
|
104
|
+
*/
|
|
105
|
+
isDataReq?: boolean;
|
|
72
106
|
createGsspReqRes: () => PagesGsspContextResponse;
|
|
73
107
|
createPageElement: (pageProps: Record<string, unknown>) => ReactNode;
|
|
74
108
|
fontLinkHeader: string;
|
|
@@ -77,6 +111,30 @@ type ResolvePagesPageDataOptions = {
|
|
|
77
111
|
isrGet: (key: string) => Promise<ISRCacheEntry | null>;
|
|
78
112
|
isrSet: (key: string, data: CachedPagesValue, revalidateSeconds: number, tags?: string[], expireSeconds?: number) => Promise<void>;
|
|
79
113
|
expireSeconds?: number;
|
|
114
|
+
/**
|
|
115
|
+
* When true, this dispatch corresponds to a build-time prerender (the
|
|
116
|
+
* `vinext` build phase fetches each statically generated page through the
|
|
117
|
+
* production server). Maps to `revalidateReason: "build"` when
|
|
118
|
+
* `getStaticProps` is invoked. Mirrors Next.js's
|
|
119
|
+
* `renderOpts.isBuildTimePrerendering` flag — see
|
|
120
|
+
* `.nextjs-ref/packages/next/src/server/render.tsx`.
|
|
121
|
+
*/
|
|
122
|
+
isBuildTimePrerendering?: boolean;
|
|
123
|
+
/**
|
|
124
|
+
* When true, this dispatch was triggered by an on-demand revalidation
|
|
125
|
+
* request (e.g. `res.revalidate()` in a Pages Router API route, or an
|
|
126
|
+
* equivalent webhook). Maps to `revalidateReason: "on-demand"` when
|
|
127
|
+
* `getStaticProps` is invoked. Mirrors Next.js's
|
|
128
|
+
* `renderOpts.isOnDemandRevalidate` flag — see
|
|
129
|
+
* `.nextjs-ref/packages/next/src/server/render.tsx`.
|
|
130
|
+
*
|
|
131
|
+
* Forward-looking plumbing: no caller currently sets this — `res.revalidate()`
|
|
132
|
+
* is not yet implemented in vinext. The `"on-demand"` branch in the
|
|
133
|
+
* `revalidateReason` resolver is intentionally unreachable today; keeping the
|
|
134
|
+
* typed contract here means wiring it up will be a one-line change once the
|
|
135
|
+
* trigger lands.
|
|
136
|
+
*/
|
|
137
|
+
isOnDemandRevalidate?: boolean;
|
|
80
138
|
pageModule: PagesPageModule;
|
|
81
139
|
params: Record<string, unknown>;
|
|
82
140
|
query: Record<string, unknown>;
|
|
@@ -87,18 +145,27 @@ type ResolvePagesPageDataOptions = {
|
|
|
87
145
|
safeJsonStringify: (value: unknown) => string;
|
|
88
146
|
sanitizeDestination: (destination: string) => string;
|
|
89
147
|
scriptNonce?: string;
|
|
148
|
+
statusCode?: number;
|
|
90
149
|
triggerBackgroundRegeneration: (key: string, renderFn: () => Promise<void>, errorContext?: {
|
|
91
150
|
routerKind: "Pages Router";
|
|
92
151
|
routePath: string;
|
|
93
152
|
routeType: "render";
|
|
94
153
|
}) => void;
|
|
95
154
|
renderIsrPassToStringAsync: (element: ReactNode) => Promise<string>;
|
|
155
|
+
vinext?: VinextNextData["__vinext"];
|
|
96
156
|
};
|
|
97
157
|
type ResolvePagesPageDataRenderResult = {
|
|
98
158
|
kind: "render";
|
|
99
159
|
gsspRes: PagesGsspResponse | null;
|
|
100
160
|
isrRevalidateSeconds: number | null;
|
|
101
161
|
pageProps: Record<string, unknown>;
|
|
162
|
+
/**
|
|
163
|
+
* True when `getStaticPaths` returned `fallback: true` AND the requested path
|
|
164
|
+
* is not in the pre-rendered list. The caller renders a loading shell with
|
|
165
|
+
* empty props and `useRouter().isFallback === true` (matching Next.js's
|
|
166
|
+
* `render.tsx` — `getStaticProps` is skipped on the fallback render).
|
|
167
|
+
*/
|
|
168
|
+
isFallback: boolean;
|
|
102
169
|
};
|
|
103
170
|
type ResolvePagesPageDataResponseResult = {
|
|
104
171
|
kind: "response";
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import { VINEXT_CACHE_HEADER } from "./headers.js";
|
|
2
1
|
import { normalizeStaticPathname } from "../routing/route-pattern.js";
|
|
2
|
+
import { buildCacheStateHeaders } from "./cache-headers.js";
|
|
3
3
|
import { buildPagesCacheValue } from "./isr-cache.js";
|
|
4
|
+
import { buildDefaultPagesNotFoundResponse } from "./pages-default-404.js";
|
|
4
5
|
import { buildCachedRevalidateCacheControl } from "./cache-control.js";
|
|
5
6
|
import { buildPagesNextDataScript } from "./pages-page-response.js";
|
|
6
7
|
//#region src/server/pages-page-data.ts
|
|
7
8
|
function buildPagesNotFoundResponse() {
|
|
8
|
-
return
|
|
9
|
-
status: 404,
|
|
10
|
-
headers: { "Content-Type": "text/html" }
|
|
11
|
-
});
|
|
9
|
+
return buildDefaultPagesNotFoundResponse();
|
|
12
10
|
}
|
|
13
11
|
function buildPagesDataNotFoundResponse() {
|
|
14
|
-
return new Response("
|
|
12
|
+
return new Response("{}", {
|
|
13
|
+
status: 404,
|
|
14
|
+
headers: { "Content-Type": "application/json" }
|
|
15
|
+
});
|
|
15
16
|
}
|
|
16
17
|
function resolvePagesRedirectStatus(redirect) {
|
|
17
18
|
return redirect.statusCode != null ? redirect.statusCode : redirect.permanent ? 308 : 307;
|
|
@@ -41,17 +42,17 @@ function matchesPagesStaticPath(pathEntry, params, routeUrl) {
|
|
|
41
42
|
return String(value) === String(actual);
|
|
42
43
|
});
|
|
43
44
|
}
|
|
44
|
-
function buildPagesCacheResponse(html, cacheState, fontLinkHeader, revalidateSeconds, expireSeconds, cacheControl) {
|
|
45
|
+
function buildPagesCacheResponse(html, cacheState, fontLinkHeader, revalidateSeconds, expireSeconds, cacheControl, status) {
|
|
45
46
|
const effectiveRevalidateSeconds = cacheControl?.revalidate ?? revalidateSeconds ?? 60;
|
|
46
47
|
const effectiveExpireSeconds = cacheControl === void 0 ? void 0 : cacheControl.expire ?? expireSeconds;
|
|
47
48
|
const headers = {
|
|
48
49
|
"Content-Type": "text/html",
|
|
49
|
-
|
|
50
|
+
...buildCacheStateHeaders(cacheState),
|
|
50
51
|
"Cache-Control": buildCachedRevalidateCacheControl(cacheState, effectiveRevalidateSeconds, effectiveExpireSeconds)
|
|
51
52
|
};
|
|
52
53
|
if (fontLinkHeader) headers.Link = fontLinkHeader;
|
|
53
54
|
return new Response(html, {
|
|
54
|
-
status: 200,
|
|
55
|
+
status: status ?? 200,
|
|
55
56
|
headers
|
|
56
57
|
});
|
|
57
58
|
}
|
|
@@ -77,29 +78,40 @@ async function renderPagesIsrHtml(options) {
|
|
|
77
78
|
pageProps: options.pageProps,
|
|
78
79
|
params: options.params,
|
|
79
80
|
routePattern: options.routePattern,
|
|
80
|
-
safeJsonStringify: options.safeJsonStringify
|
|
81
|
+
safeJsonStringify: options.safeJsonStringify,
|
|
82
|
+
vinext: options.vinext
|
|
81
83
|
});
|
|
82
84
|
return rewritePagesCachedHtml(options.cachedHtml, freshBody, nextDataScript);
|
|
83
85
|
}
|
|
84
86
|
async function resolvePagesPageData(options) {
|
|
87
|
+
const userFacingParams = options.route.isDynamic ? options.params : null;
|
|
88
|
+
let isFallback = false;
|
|
85
89
|
if (typeof options.pageModule.getStaticPaths === "function" && options.route.isDynamic) {
|
|
86
90
|
const pathsResult = await options.pageModule.getStaticPaths({
|
|
87
91
|
locales: options.i18n.locales ?? [],
|
|
88
92
|
defaultLocale: options.i18n.defaultLocale ?? ""
|
|
89
93
|
});
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
94
|
+
const fallback = pathsResult?.fallback ?? false;
|
|
95
|
+
const isValidPath = (pathsResult?.paths ?? []).some((pathEntry) => matchesPagesStaticPath(pathEntry, options.params, options.routeUrl));
|
|
96
|
+
if (fallback === false && !isValidPath) return {
|
|
97
|
+
kind: "response",
|
|
98
|
+
response: options.isDataReq ? buildPagesDataNotFoundResponse() : buildPagesNotFoundResponse()
|
|
99
|
+
};
|
|
100
|
+
if (fallback === true && !isValidPath && !options.isDataReq) isFallback = true;
|
|
96
101
|
}
|
|
97
102
|
let pageProps = {};
|
|
98
103
|
let gsspRes = null;
|
|
104
|
+
if (isFallback) return {
|
|
105
|
+
kind: "render",
|
|
106
|
+
gsspRes: null,
|
|
107
|
+
isrRevalidateSeconds: null,
|
|
108
|
+
pageProps,
|
|
109
|
+
isFallback: true
|
|
110
|
+
};
|
|
99
111
|
if (typeof options.pageModule.getServerSideProps === "function") {
|
|
100
112
|
const { req, res, responsePromise } = options.createGsspReqRes();
|
|
101
113
|
const result = await options.pageModule.getServerSideProps({
|
|
102
|
-
params:
|
|
114
|
+
params: userFacingParams,
|
|
103
115
|
req,
|
|
104
116
|
res,
|
|
105
117
|
query: options.query,
|
|
@@ -112,7 +124,7 @@ async function resolvePagesPageData(options) {
|
|
|
112
124
|
kind: "response",
|
|
113
125
|
response: await responsePromise
|
|
114
126
|
};
|
|
115
|
-
if (result?.props) pageProps = result.props;
|
|
127
|
+
if (result?.props) pageProps = await Promise.resolve(result.props);
|
|
116
128
|
if (result?.redirect) return {
|
|
117
129
|
kind: "response",
|
|
118
130
|
response: new Response(null, {
|
|
@@ -122,7 +134,7 @@ async function resolvePagesPageData(options) {
|
|
|
122
134
|
};
|
|
123
135
|
if (result?.notFound) return {
|
|
124
136
|
kind: "response",
|
|
125
|
-
response: buildPagesDataNotFoundResponse()
|
|
137
|
+
response: options.isDataReq ? buildPagesDataNotFoundResponse() : buildPagesNotFoundResponse()
|
|
126
138
|
};
|
|
127
139
|
gsspRes = res;
|
|
128
140
|
}
|
|
@@ -132,18 +144,19 @@ async function resolvePagesPageData(options) {
|
|
|
132
144
|
const cacheKey = options.isrCacheKey("pages", pathname);
|
|
133
145
|
const cached = await options.isrGet(cacheKey);
|
|
134
146
|
const cachedValue = cached?.value.value;
|
|
135
|
-
if (cachedValue?.kind === "PAGES" && cached && !cached.isStale && !options.scriptNonce) return {
|
|
147
|
+
if (cachedValue?.kind === "PAGES" && cached && !cached.isStale && !options.scriptNonce && !options.isDataReq) return {
|
|
136
148
|
kind: "response",
|
|
137
|
-
response: buildPagesCacheResponse(cachedValue.html, "HIT", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl)
|
|
149
|
+
response: buildPagesCacheResponse(cachedValue.html, "HIT", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl, cachedValue.status)
|
|
138
150
|
};
|
|
139
|
-
if (cachedValue?.kind === "PAGES" && cached && cached.isStale && !options.scriptNonce) {
|
|
151
|
+
if (cachedValue?.kind === "PAGES" && cached && cached.isStale && !options.scriptNonce && !options.isDataReq) {
|
|
140
152
|
options.triggerBackgroundRegeneration(cacheKey, async function() {
|
|
141
153
|
return options.runInFreshUnifiedContext(async () => {
|
|
142
154
|
const freshResult = await options.pageModule.getStaticProps?.({
|
|
143
|
-
params:
|
|
155
|
+
params: userFacingParams,
|
|
144
156
|
locale: options.i18n.locale,
|
|
145
157
|
locales: options.i18n.locales,
|
|
146
|
-
defaultLocale: options.i18n.defaultLocale
|
|
158
|
+
defaultLocale: options.i18n.defaultLocale,
|
|
159
|
+
revalidateReason: "stale"
|
|
147
160
|
});
|
|
148
161
|
if (freshResult?.props && typeof freshResult.revalidate === "number" && freshResult.revalidate > 0) {
|
|
149
162
|
options.applyRequestContexts();
|
|
@@ -156,9 +169,10 @@ async function resolvePagesPageData(options) {
|
|
|
156
169
|
params: options.params,
|
|
157
170
|
renderIsrPassToStringAsync: options.renderIsrPassToStringAsync,
|
|
158
171
|
routePattern: options.routePattern,
|
|
159
|
-
safeJsonStringify: options.safeJsonStringify
|
|
172
|
+
safeJsonStringify: options.safeJsonStringify,
|
|
173
|
+
vinext: options.vinext
|
|
160
174
|
});
|
|
161
|
-
await options.isrSet(cacheKey, buildPagesCacheValue(freshHtml, freshResult.props), freshResult.revalidate, void 0, options.expireSeconds);
|
|
175
|
+
await options.isrSet(cacheKey, buildPagesCacheValue(freshHtml, freshResult.props, options.statusCode), freshResult.revalidate, void 0, options.expireSeconds);
|
|
162
176
|
}
|
|
163
177
|
});
|
|
164
178
|
}, {
|
|
@@ -168,14 +182,15 @@ async function resolvePagesPageData(options) {
|
|
|
168
182
|
});
|
|
169
183
|
return {
|
|
170
184
|
kind: "response",
|
|
171
|
-
response: buildPagesCacheResponse(cachedValue.html, "STALE", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl)
|
|
185
|
+
response: buildPagesCacheResponse(cachedValue.html, "STALE", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl, cachedValue.status)
|
|
172
186
|
};
|
|
173
187
|
}
|
|
174
188
|
const result = await options.pageModule.getStaticProps({
|
|
175
|
-
params:
|
|
189
|
+
params: userFacingParams,
|
|
176
190
|
locale: options.i18n.locale,
|
|
177
191
|
locales: options.i18n.locales,
|
|
178
|
-
defaultLocale: options.i18n.defaultLocale
|
|
192
|
+
defaultLocale: options.i18n.defaultLocale,
|
|
193
|
+
revalidateReason: options.isOnDemandRevalidate ? "on-demand" : options.isBuildTimePrerendering ? "build" : "stale"
|
|
179
194
|
});
|
|
180
195
|
if (result?.props) pageProps = result.props;
|
|
181
196
|
if (result?.redirect) return {
|
|
@@ -187,7 +202,7 @@ async function resolvePagesPageData(options) {
|
|
|
187
202
|
};
|
|
188
203
|
if (result?.notFound) return {
|
|
189
204
|
kind: "response",
|
|
190
|
-
response: buildPagesDataNotFoundResponse()
|
|
205
|
+
response: options.isDataReq ? buildPagesDataNotFoundResponse() : buildPagesNotFoundResponse()
|
|
191
206
|
};
|
|
192
207
|
if (typeof result?.revalidate === "number" && result.revalidate > 0) isrRevalidateSeconds = result.revalidate;
|
|
193
208
|
}
|
|
@@ -195,7 +210,8 @@ async function resolvePagesPageData(options) {
|
|
|
195
210
|
kind: "render",
|
|
196
211
|
gsspRes,
|
|
197
212
|
isrRevalidateSeconds,
|
|
198
|
-
pageProps
|
|
213
|
+
pageProps,
|
|
214
|
+
isFallback: false
|
|
199
215
|
};
|
|
200
216
|
}
|
|
201
217
|
//#endregion
|