vinext 0.0.49 → 0.0.50
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/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.js.map +1 -1
- package/dist/build/prerender.d.ts +17 -1
- package/dist/build/prerender.js +77 -16
- package/dist/build/prerender.js.map +1 -1
- 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 +1 -1
- package/dist/check.js.map +1 -1
- package/dist/cli-args.js.map +1 -1
- package/dist/cli.js +8 -4
- 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 +149 -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.js.map +1 -1
- package/dist/config/next-config.d.ts +6 -3
- package/dist/config/next-config.js +13 -2
- package/dist/config/next-config.js.map +1 -1
- package/dist/deploy.js +13 -5
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-browser-entry.d.ts +3 -1
- package/dist/entries/app-browser-entry.js +11 -2
- package/dist/entries/app-browser-entry.js.map +1 -1
- package/dist/entries/app-rsc-entry.js +11 -0
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.js +4 -0
- 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.map +1 -1
- package/dist/entries/pages-entry-helpers.js.map +1 -1
- package/dist/entries/pages-server-entry.js +15 -0
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.js.map +1 -1
- package/dist/index.js +76 -18
- 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.js.map +1 -1
- 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/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 +48 -5
- package/dist/routing/app-route-graph.js +159 -15
- 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.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 +19 -0
- package/dist/server/app-browser-action-result.js +18 -0
- package/dist/server/app-browser-action-result.js.map +1 -0
- package/dist/server/app-browser-entry.js +91 -48
- 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 +19 -0
- package/dist/server/app-browser-hydration.js +22 -0
- package/dist/server/app-browser-hydration.js.map +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +6 -3
- package/dist/server/app-browser-navigation-controller.js +67 -19
- package/dist/server/app-browser-navigation-controller.js.map +1 -1
- package/dist/server/app-browser-state.d.ts +17 -17
- package/dist/server/app-browser-state.js +122 -36
- package/dist/server/app-browser-state.js.map +1 -1
- package/dist/server/app-browser-stream.d.ts +4 -0
- package/dist/server/app-browser-stream.js +24 -2
- package/dist/server/app-browser-stream.js.map +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +6 -1
- package/dist/server/app-browser-visible-commit.js +34 -19
- 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 +6 -1
- package/dist/server/app-elements-wire.js +17 -1
- 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.js.map +1 -1
- 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 +1 -0
- package/dist/server/app-page-boundary-render.js +14 -13
- 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 +7 -5
- package/dist/server/app-page-boundary.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +10 -3
- package/dist/server/app-page-cache.js +42 -23
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-dispatch.d.ts +6 -1
- package/dist/server/app-page-dispatch.js +21 -7
- package/dist/server/app-page-dispatch.js.map +1 -1
- package/dist/server/app-page-element-builder.d.ts +3 -1
- package/dist/server/app-page-element-builder.js +6 -2
- package/dist/server/app-page-element-builder.js.map +1 -1
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-head.js +4 -0
- 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.js.map +1 -1
- package/dist/server/app-page-render.d.ts +7 -1
- package/dist/server/app-page-render.js +11 -4
- package/dist/server/app-page-render.js.map +1 -1
- 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 +15 -5
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +6 -2
- package/dist/server/app-page-route-wiring.js +50 -49
- 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 +7 -2
- package/dist/server/app-page-stream.js +3 -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 +6 -2
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +5 -2
- package/dist/server/app-rsc-cache-busting.js +40 -19
- package/dist/server/app-rsc-cache-busting.js.map +1 -1
- package/dist/server/app-rsc-error-handler.js.map +1 -1
- package/dist/server/app-rsc-errors.js.map +1 -1
- package/dist/server/app-rsc-handler.d.ts +10 -1
- package/dist/server/app-rsc-handler.js +51 -17
- 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.js.map +1 -1
- package/dist/server/app-segment-config.js.map +1 -1
- package/dist/server/app-server-action-execution.d.ts +16 -2
- package/dist/server/app-server-action-execution.js +79 -23
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/app-ssr-entry.d.ts +6 -0
- package/dist/server/app-ssr-entry.js +10 -4
- package/dist/server/app-ssr-entry.js.map +1 -1
- 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.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.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-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 +8 -5
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/file-based-metadata.js.map +1 -1
- package/dist/server/headers.d.ts +79 -0
- package/dist/server/headers.js +101 -0
- package/dist/server/headers.js.map +1 -0
- package/dist/server/html.js.map +1 -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 +10 -1
- package/dist/server/isr-cache.js +12 -3
- 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.map +1 -1
- 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 +6 -3
- package/dist/server/middleware-runtime.js.map +1 -1
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/navigation-planner.d.ts +119 -0
- package/dist/server/navigation-planner.js +171 -0
- package/dist/server/navigation-planner.js.map +1 -0
- package/dist/server/navigation-trace.d.ts +12 -2
- package/dist/server/navigation-trace.js +13 -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.js.map +1 -1
- 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.js +5 -2
- package/dist/server/pages-page-data.js.map +1 -1
- package/dist/server/pages-page-response.js +3 -2
- 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.js +35 -13
- 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.js +3 -3
- package/dist/server/server-action-not-found.js.map +1 -1
- package/dist/server/socket-error-backstop.js.map +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.js +20 -8
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.d.ts +15 -3
- package/dist/shims/cache.js +99 -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 +118 -33
- package/dist/shims/error-boundary.js.map +1 -1
- package/dist/shims/error.js.map +1 -1
- package/dist/shims/fetch-cache.d.ts +22 -1
- package/dist/shims/fetch-cache.js +124 -13
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/font-google-base.js.map +1 -1
- package/dist/shims/font-local.js.map +1 -1
- package/dist/shims/form.js +3 -1
- package/dist/shims/form.js.map +1 -1
- 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 +4 -2
- package/dist/shims/headers.js +24 -7
- 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.js +15 -2
- 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 +1 -0
- 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 +34 -0
- package/dist/shims/link-prefetch.js +40 -0
- package/dist/shims/link-prefetch.js.map +1 -0
- package/dist/shims/link.d.ts +27 -4
- package/dist/shims/link.js +91 -27
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation-state.js.map +1 -1
- package/dist/shims/navigation.d.ts +22 -1
- package/dist/shims/navigation.js +30 -15
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/navigation.react-server.js.map +1 -1
- package/dist/shims/offline.js.map +1 -1
- 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 +38 -2
- package/dist/shims/router.js +45 -17
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/script-nonce-context.js.map +1 -1
- package/dist/shims/script.js.map +1 -1
- package/dist/shims/server.js +10 -14
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/slot.d.ts +6 -1
- package/dist/shims/slot.js +20 -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 +3 -0
- package/dist/shims/unified-request-context.js.map +1 -1
- package/dist/shims/url-safety.js.map +1 -1
- package/dist/shims/url-utils.d.ts +2 -1
- package/dist/shims/url-utils.js +10 -1
- 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/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 +6 -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/text-stream.js.map +1 -1
- package/dist/utils/vinext-root.js.map +1 -1
- package/package.json +6 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages-media-type.js","names":[],"sources":["../../src/server/pages-media-type.ts"],"sourcesContent":["/**\n * Shared media-type helpers and body-parse error for Pages API routes.\n *\n * Used by both api-handler.ts (Pages Router dev/prod with Node.js req/res) and\n * pages-node-compat.ts (Pages Router fetch-based facade for Cloudflare Workers).\n */\n\nexport class PagesBodyParseError extends Error {\n constructor(\n message: string,\n readonly statusCode: number,\n ) {\n super(message);\n this.name = \"PagesBodyParseError\";\n }\n}\n\nexport function getMediaType(contentType: string | null | undefined): string {\n const [type] = (contentType ?? \"text/plain\").split(\";\");\n return type?.trim().toLowerCase() || \"text/plain\";\n}\n\nexport function isJsonMediaType(mediaType: string): boolean {\n return mediaType === \"application/json\" || mediaType === \"application/ld+json\";\n}\n"],"mappings":";;;;;;;AAOA,IAAa,sBAAb,cAAyC,MAAM;CAC7C,YACE,SACA,YACA;
|
|
1
|
+
{"version":3,"file":"pages-media-type.js","names":[],"sources":["../../src/server/pages-media-type.ts"],"sourcesContent":["/**\n * Shared media-type helpers and body-parse error for Pages API routes.\n *\n * Used by both api-handler.ts (Pages Router dev/prod with Node.js req/res) and\n * pages-node-compat.ts (Pages Router fetch-based facade for Cloudflare Workers).\n */\n\nexport class PagesBodyParseError extends Error {\n constructor(\n message: string,\n readonly statusCode: number,\n ) {\n super(message);\n this.name = \"PagesBodyParseError\";\n }\n}\n\nexport function getMediaType(contentType: string | null | undefined): string {\n const [type] = (contentType ?? \"text/plain\").split(\";\");\n return type?.trim().toLowerCase() || \"text/plain\";\n}\n\nexport function isJsonMediaType(mediaType: string): boolean {\n return mediaType === \"application/json\" || mediaType === \"application/ld+json\";\n}\n"],"mappings":";;;;;;;AAOA,IAAa,sBAAb,cAAyC,MAAM;CAC7C,YACE,SACA,YACA;EACA,MAAM,QAAQ;EAFL,KAAA,aAAA;EAGT,KAAK,OAAO;;;AAIhB,SAAgB,aAAa,aAAgD;CAC3E,MAAM,CAAC,SAAS,eAAe,cAAc,MAAM,IAAI;CACvD,OAAO,MAAM,MAAM,CAAC,aAAa,IAAI;;AAGvC,SAAgB,gBAAgB,WAA4B;CAC1D,OAAO,cAAc,sBAAsB,cAAc"}
|
|
@@ -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 { 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,3 +1,4 @@
|
|
|
1
|
+
import { VINEXT_CACHE_HEADER } from "./headers.js";
|
|
1
2
|
import { buildPagesCacheValue } from "./isr-cache.js";
|
|
2
3
|
import { buildCachedRevalidateCacheControl } from "./cache-control.js";
|
|
3
4
|
import { buildPagesNextDataScript } from "./pages-page-response.js";
|
|
@@ -22,10 +23,12 @@ function matchesPagesStaticPath(pathEntry, params) {
|
|
|
22
23
|
});
|
|
23
24
|
}
|
|
24
25
|
function buildPagesCacheResponse(html, cacheState, fontLinkHeader, revalidateSeconds, expireSeconds, cacheControl) {
|
|
26
|
+
const effectiveRevalidateSeconds = cacheControl?.revalidate ?? revalidateSeconds ?? 60;
|
|
27
|
+
const effectiveExpireSeconds = cacheControl === void 0 ? void 0 : cacheControl.expire ?? expireSeconds;
|
|
25
28
|
const headers = {
|
|
26
29
|
"Content-Type": "text/html",
|
|
27
|
-
|
|
28
|
-
"Cache-Control": buildCachedRevalidateCacheControl(cacheState,
|
|
30
|
+
[VINEXT_CACHE_HEADER]: cacheState,
|
|
31
|
+
"Cache-Control": buildCachedRevalidateCacheControl(cacheState, effectiveRevalidateSeconds, effectiveExpireSeconds)
|
|
29
32
|
};
|
|
30
33
|
if (fontLinkHeader) headers.Link = fontLinkHeader;
|
|
31
34
|
return new Response(html, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages-page-data.js","names":[],"sources":["../../src/server/pages-page-data.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { Route } from \"../routing/pages-router.js\";\nimport type { CachedPagesValue, CacheControlMetadata } from \"vinext/shims/cache\";\nimport { buildCachedRevalidateCacheControl } from \"./cache-control.js\";\nimport { buildPagesCacheValue, type ISRCacheEntry } from \"./isr-cache.js\";\nimport {\n buildPagesNextDataScript,\n type PagesGsspResponse,\n type PagesI18nRenderContext,\n} from \"./pages-page-response.js\";\n\ntype PagesRedirectResult = {\n destination: string;\n permanent?: boolean;\n statusCode?: number;\n};\n\ntype PagesStaticPathsEntry = {\n params: Record<string, unknown>;\n};\n\ntype PagesStaticPathsResult = {\n fallback?: boolean | \"blocking\";\n paths?: PagesStaticPathsEntry[];\n};\n\ntype PagesPagePropsResult = {\n props?: Record<string, unknown>;\n redirect?: PagesRedirectResult;\n notFound?: boolean;\n revalidate?: number;\n};\n\nexport type PagesMutableGsspResponse = {\n headersSent: boolean;\n} & PagesGsspResponse;\n\nexport type PagesGsspContextResponse = {\n req: unknown;\n res: PagesMutableGsspResponse;\n responsePromise: Promise<Response>;\n};\n\nexport type PagesPageModule = {\n default?: unknown;\n getStaticPaths?: (context: {\n locales: string[];\n defaultLocale: string;\n }) => Promise<PagesStaticPathsResult> | PagesStaticPathsResult;\n getServerSideProps?: (context: {\n params: Record<string, unknown>;\n req: unknown;\n res: PagesMutableGsspResponse;\n query: Record<string, unknown>;\n resolvedUrl: string;\n locale?: string;\n locales?: string[];\n defaultLocale?: string;\n }) => Promise<PagesPagePropsResult> | PagesPagePropsResult;\n getStaticProps?: (context: {\n params: Record<string, unknown>;\n locale?: string;\n locales?: string[];\n defaultLocale?: string;\n }) => Promise<PagesPagePropsResult> | PagesPagePropsResult;\n};\n\ntype RenderPagesIsrHtmlOptions = {\n buildId: string | null;\n cachedHtml: string;\n createPageElement: (pageProps: Record<string, unknown>) => ReactNode;\n i18n: PagesI18nRenderContext;\n pageProps: Record<string, unknown>;\n params: Record<string, unknown>;\n renderIsrPassToStringAsync: (element: ReactNode) => Promise<string>;\n routePattern: string;\n safeJsonStringify: (value: unknown) => string;\n};\n\nexport type ResolvePagesPageDataOptions = {\n applyRequestContexts: () => void;\n buildId: string | null;\n createGsspReqRes: () => PagesGsspContextResponse;\n createPageElement: (pageProps: Record<string, unknown>) => ReactNode;\n fontLinkHeader: string;\n i18n: PagesI18nRenderContext;\n isrCacheKey: (router: string, pathname: string) => string;\n isrGet: (key: string) => Promise<ISRCacheEntry | null>;\n isrSet: (\n key: string,\n data: CachedPagesValue,\n revalidateSeconds: number,\n tags?: string[],\n expireSeconds?: number,\n ) => Promise<void>;\n expireSeconds?: number;\n pageModule: PagesPageModule;\n params: Record<string, unknown>;\n query: Record<string, unknown>;\n route: Pick<Route, \"isDynamic\">;\n routePattern: string;\n routeUrl: string;\n runInFreshUnifiedContext: <T>(callback: () => Promise<T>) => Promise<T>;\n safeJsonStringify: (value: unknown) => string;\n sanitizeDestination: (destination: string) => string;\n scriptNonce?: string;\n triggerBackgroundRegeneration: (\n key: string,\n renderFn: () => Promise<void>,\n errorContext?: { routerKind: \"Pages Router\"; routePath: string; routeType: \"render\" },\n ) => void;\n renderIsrPassToStringAsync: (element: ReactNode) => Promise<string>;\n};\n\ntype ResolvePagesPageDataRenderResult = {\n kind: \"render\";\n gsspRes: PagesGsspResponse | null;\n isrRevalidateSeconds: number | null;\n pageProps: Record<string, unknown>;\n};\n\ntype ResolvePagesPageDataResponseResult = {\n kind: \"response\";\n response: Response;\n};\n\ntype ResolvePagesPageDataResult =\n | ResolvePagesPageDataRenderResult\n | ResolvePagesPageDataResponseResult;\n\nfunction buildPagesNotFoundResponse(): Response {\n return new Response(\"<!DOCTYPE html><html><body><h1>404 - Page not found</h1></body></html>\", {\n status: 404,\n headers: { \"Content-Type\": \"text/html\" },\n });\n}\n\nfunction buildPagesDataNotFoundResponse(): Response {\n return new Response(\"404\", { status: 404 });\n}\n\nfunction resolvePagesRedirectStatus(redirect: PagesRedirectResult): number {\n return redirect.statusCode != null ? redirect.statusCode : redirect.permanent ? 308 : 307;\n}\n\nfunction matchesPagesStaticPath(\n pathEntry: PagesStaticPathsEntry,\n params: Record<string, unknown>,\n): boolean {\n return Object.entries(pathEntry.params).every(([key, value]) => {\n const actual = params[key];\n if (Array.isArray(value)) {\n return Array.isArray(actual) && value.join(\"/\") === actual.join(\"/\");\n }\n return String(value) === String(actual);\n });\n}\n\nfunction buildPagesCacheResponse(\n html: string,\n cacheState: \"HIT\" | \"STALE\",\n fontLinkHeader: string,\n revalidateSeconds?: number,\n expireSeconds?: number,\n cacheControl?: CacheControlMetadata,\n): Response {\n // Legacy cache entries written before cacheControl metadata existed can still\n // hit this path without a persisted revalidate value; keep the historic\n // 60-second fallback for that migration window.\n const effectiveRevalidateSeconds = cacheControl?.revalidate ?? revalidateSeconds ?? 60;\n const effectiveExpireSeconds =\n cacheControl === undefined ? undefined : (cacheControl.expire ?? expireSeconds);\n const headers: Record<string, string> = {\n \"Content-Type\": \"text/html\",\n \"X-Vinext-Cache\": cacheState,\n \"Cache-Control\": buildCachedRevalidateCacheControl(\n cacheState,\n effectiveRevalidateSeconds,\n effectiveExpireSeconds,\n ),\n };\n\n if (fontLinkHeader) {\n headers.Link = fontLinkHeader;\n }\n\n return new Response(html, {\n status: 200,\n headers,\n });\n}\n\nfunction rewritePagesCachedHtml(\n cachedHtml: string,\n freshBody: string,\n nextDataScript: string,\n): string {\n const bodyMarker = '<div id=\"__next\">';\n const bodyStart = cachedHtml.indexOf(bodyMarker);\n const contentStart = bodyStart >= 0 ? bodyStart + bodyMarker.length : -1;\n // This intentionally looks for the bare inline __NEXT_DATA__ marker.\n // Pages responses with scriptNonce are excluded from ISR writes, so cached\n // HTML should never contain nonce-prefixed __NEXT_DATA__ scripts here.\n const nextDataMarker = \"<script>window.__NEXT_DATA__\";\n const nextDataStart = cachedHtml.indexOf(nextDataMarker);\n\n if (contentStart >= 0 && nextDataStart >= 0) {\n const region = cachedHtml.slice(contentStart, nextDataStart);\n const lastCloseDiv = region.lastIndexOf(\"</div>\");\n const gap = lastCloseDiv >= 0 ? region.slice(lastCloseDiv + 6) : \"\";\n const nextDataEnd = cachedHtml.indexOf(\"</script>\", nextDataStart) + 9;\n const tail = cachedHtml.slice(nextDataEnd);\n\n return cachedHtml.slice(0, contentStart) + freshBody + \"</div>\" + gap + nextDataScript + tail;\n }\n\n return (\n '<!DOCTYPE html>\\n<html>\\n<head>\\n</head>\\n<body>\\n <div id=\"__next\">' +\n freshBody +\n \"</div>\\n \" +\n nextDataScript +\n \"\\n</body>\\n</html>\"\n );\n}\n\nexport async function renderPagesIsrHtml(options: RenderPagesIsrHtmlOptions): Promise<string> {\n const freshBody = await options.renderIsrPassToStringAsync(\n options.createPageElement(options.pageProps),\n );\n const nextDataScript = buildPagesNextDataScript({\n buildId: options.buildId,\n i18n: options.i18n,\n pageProps: options.pageProps,\n params: options.params,\n routePattern: options.routePattern,\n safeJsonStringify: options.safeJsonStringify,\n });\n\n return rewritePagesCachedHtml(options.cachedHtml, freshBody, nextDataScript);\n}\n\nexport async function resolvePagesPageData(\n options: ResolvePagesPageDataOptions,\n): Promise<ResolvePagesPageDataResult> {\n if (typeof options.pageModule.getStaticPaths === \"function\" && options.route.isDynamic) {\n const pathsResult = await options.pageModule.getStaticPaths({\n locales: options.i18n.locales ?? [],\n defaultLocale: options.i18n.defaultLocale ?? \"\",\n });\n const fallback = pathsResult?.fallback ?? false;\n\n if (fallback === false) {\n const paths = pathsResult?.paths ?? [];\n const isValidPath = paths.some((pathEntry) =>\n matchesPagesStaticPath(pathEntry, options.params),\n );\n\n if (!isValidPath) {\n return {\n kind: \"response\",\n response: buildPagesNotFoundResponse(),\n };\n }\n }\n }\n\n let pageProps: Record<string, unknown> = {};\n let gsspRes: PagesMutableGsspResponse | null = null;\n\n if (typeof options.pageModule.getServerSideProps === \"function\") {\n const { req, res, responsePromise } = options.createGsspReqRes();\n const result = await options.pageModule.getServerSideProps({\n params: options.params,\n req,\n res,\n query: options.query,\n resolvedUrl: options.routeUrl,\n locale: options.i18n.locale,\n locales: options.i18n.locales,\n defaultLocale: options.i18n.defaultLocale,\n });\n\n if (res.headersSent) {\n return {\n kind: \"response\",\n response: await responsePromise,\n };\n }\n\n if (result?.props) {\n pageProps = result.props;\n }\n\n if (result?.redirect) {\n return {\n kind: \"response\",\n response: new Response(null, {\n status: resolvePagesRedirectStatus(result.redirect),\n headers: { Location: options.sanitizeDestination(result.redirect.destination) },\n }),\n };\n }\n\n if (result?.notFound) {\n return {\n kind: \"response\",\n response: buildPagesDataNotFoundResponse(),\n };\n }\n\n gsspRes = res;\n }\n\n let isrRevalidateSeconds: number | null = null;\n\n if (typeof options.pageModule.getStaticProps === \"function\") {\n const pathname = options.routeUrl.split(\"?\")[0];\n const cacheKey = options.isrCacheKey(\"pages\", pathname);\n const cached = await options.isrGet(cacheKey);\n const cachedValue = cached?.value.value;\n\n if (cachedValue?.kind === \"PAGES\" && cached && !cached.isStale && !options.scriptNonce) {\n return {\n kind: \"response\",\n response: buildPagesCacheResponse(\n cachedValue.html,\n \"HIT\",\n options.fontLinkHeader,\n undefined,\n options.expireSeconds,\n cached.value.cacheControl,\n ),\n };\n }\n\n if (cachedValue?.kind === \"PAGES\" && cached && cached.isStale && !options.scriptNonce) {\n options.triggerBackgroundRegeneration(\n cacheKey,\n async function () {\n return options.runInFreshUnifiedContext(async () => {\n const freshResult = await options.pageModule.getStaticProps?.({\n params: options.params,\n locale: options.i18n.locale,\n locales: options.i18n.locales,\n defaultLocale: options.i18n.defaultLocale,\n });\n\n if (\n freshResult?.props &&\n typeof freshResult.revalidate === \"number\" &&\n freshResult.revalidate > 0\n ) {\n options.applyRequestContexts();\n const freshHtml = await renderPagesIsrHtml({\n buildId: options.buildId,\n cachedHtml: cachedValue.html,\n createPageElement: options.createPageElement,\n i18n: options.i18n,\n pageProps: freshResult.props,\n params: options.params,\n renderIsrPassToStringAsync: options.renderIsrPassToStringAsync,\n routePattern: options.routePattern,\n safeJsonStringify: options.safeJsonStringify,\n });\n\n await options.isrSet(\n cacheKey,\n buildPagesCacheValue(freshHtml, freshResult.props),\n freshResult.revalidate,\n undefined,\n options.expireSeconds,\n );\n }\n });\n },\n {\n routerKind: \"Pages Router\",\n routePath: options.routePattern,\n routeType: \"render\",\n },\n );\n\n return {\n kind: \"response\",\n response: buildPagesCacheResponse(\n cachedValue.html,\n \"STALE\",\n options.fontLinkHeader,\n undefined,\n options.expireSeconds,\n cached.value.cacheControl,\n ),\n };\n }\n\n const result = await options.pageModule.getStaticProps({\n params: options.params,\n locale: options.i18n.locale,\n locales: options.i18n.locales,\n defaultLocale: options.i18n.defaultLocale,\n });\n\n if (result?.props) {\n pageProps = result.props;\n }\n\n if (result?.redirect) {\n return {\n kind: \"response\",\n response: new Response(null, {\n status: resolvePagesRedirectStatus(result.redirect),\n headers: { Location: options.sanitizeDestination(result.redirect.destination) },\n }),\n };\n }\n\n if (result?.notFound) {\n return {\n kind: \"response\",\n response: buildPagesDataNotFoundResponse(),\n };\n }\n\n if (typeof result?.revalidate === \"number\" && result.revalidate > 0) {\n isrRevalidateSeconds = result.revalidate;\n }\n }\n\n return {\n kind: \"render\",\n gsspRes,\n isrRevalidateSeconds,\n pageProps,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pages-page-data.js","names":[],"sources":["../../src/server/pages-page-data.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { Route } from \"../routing/pages-router.js\";\nimport type { CachedPagesValue, CacheControlMetadata } from \"vinext/shims/cache\";\nimport { buildCachedRevalidateCacheControl } from \"./cache-control.js\";\nimport { VINEXT_CACHE_HEADER } from \"./headers.js\";\nimport { buildPagesCacheValue, type ISRCacheEntry } from \"./isr-cache.js\";\nimport {\n buildPagesNextDataScript,\n type PagesGsspResponse,\n type PagesI18nRenderContext,\n} from \"./pages-page-response.js\";\n\ntype PagesRedirectResult = {\n destination: string;\n permanent?: boolean;\n statusCode?: number;\n};\n\ntype PagesStaticPathsEntry = {\n params: Record<string, unknown>;\n};\n\ntype PagesStaticPathsResult = {\n fallback?: boolean | \"blocking\";\n paths?: PagesStaticPathsEntry[];\n};\n\ntype PagesPagePropsResult = {\n props?: Record<string, unknown>;\n redirect?: PagesRedirectResult;\n notFound?: boolean;\n revalidate?: number;\n};\n\nexport type PagesMutableGsspResponse = {\n headersSent: boolean;\n} & PagesGsspResponse;\n\nexport type PagesGsspContextResponse = {\n req: unknown;\n res: PagesMutableGsspResponse;\n responsePromise: Promise<Response>;\n};\n\nexport type PagesPageModule = {\n default?: unknown;\n getStaticPaths?: (context: {\n locales: string[];\n defaultLocale: string;\n }) => Promise<PagesStaticPathsResult> | PagesStaticPathsResult;\n getServerSideProps?: (context: {\n params: Record<string, unknown>;\n req: unknown;\n res: PagesMutableGsspResponse;\n query: Record<string, unknown>;\n resolvedUrl: string;\n locale?: string;\n locales?: string[];\n defaultLocale?: string;\n }) => Promise<PagesPagePropsResult> | PagesPagePropsResult;\n getStaticProps?: (context: {\n params: Record<string, unknown>;\n locale?: string;\n locales?: string[];\n defaultLocale?: string;\n }) => Promise<PagesPagePropsResult> | PagesPagePropsResult;\n};\n\ntype RenderPagesIsrHtmlOptions = {\n buildId: string | null;\n cachedHtml: string;\n createPageElement: (pageProps: Record<string, unknown>) => ReactNode;\n i18n: PagesI18nRenderContext;\n pageProps: Record<string, unknown>;\n params: Record<string, unknown>;\n renderIsrPassToStringAsync: (element: ReactNode) => Promise<string>;\n routePattern: string;\n safeJsonStringify: (value: unknown) => string;\n};\n\nexport type ResolvePagesPageDataOptions = {\n applyRequestContexts: () => void;\n buildId: string | null;\n createGsspReqRes: () => PagesGsspContextResponse;\n createPageElement: (pageProps: Record<string, unknown>) => ReactNode;\n fontLinkHeader: string;\n i18n: PagesI18nRenderContext;\n isrCacheKey: (router: string, pathname: string) => string;\n isrGet: (key: string) => Promise<ISRCacheEntry | null>;\n isrSet: (\n key: string,\n data: CachedPagesValue,\n revalidateSeconds: number,\n tags?: string[],\n expireSeconds?: number,\n ) => Promise<void>;\n expireSeconds?: number;\n pageModule: PagesPageModule;\n params: Record<string, unknown>;\n query: Record<string, unknown>;\n route: Pick<Route, \"isDynamic\">;\n routePattern: string;\n routeUrl: string;\n runInFreshUnifiedContext: <T>(callback: () => Promise<T>) => Promise<T>;\n safeJsonStringify: (value: unknown) => string;\n sanitizeDestination: (destination: string) => string;\n scriptNonce?: string;\n triggerBackgroundRegeneration: (\n key: string,\n renderFn: () => Promise<void>,\n errorContext?: { routerKind: \"Pages Router\"; routePath: string; routeType: \"render\" },\n ) => void;\n renderIsrPassToStringAsync: (element: ReactNode) => Promise<string>;\n};\n\ntype ResolvePagesPageDataRenderResult = {\n kind: \"render\";\n gsspRes: PagesGsspResponse | null;\n isrRevalidateSeconds: number | null;\n pageProps: Record<string, unknown>;\n};\n\ntype ResolvePagesPageDataResponseResult = {\n kind: \"response\";\n response: Response;\n};\n\ntype ResolvePagesPageDataResult =\n | ResolvePagesPageDataRenderResult\n | ResolvePagesPageDataResponseResult;\n\nfunction buildPagesNotFoundResponse(): Response {\n return new Response(\"<!DOCTYPE html><html><body><h1>404 - Page not found</h1></body></html>\", {\n status: 404,\n headers: { \"Content-Type\": \"text/html\" },\n });\n}\n\nfunction buildPagesDataNotFoundResponse(): Response {\n return new Response(\"404\", { status: 404 });\n}\n\nfunction resolvePagesRedirectStatus(redirect: PagesRedirectResult): number {\n return redirect.statusCode != null ? redirect.statusCode : redirect.permanent ? 308 : 307;\n}\n\nfunction matchesPagesStaticPath(\n pathEntry: PagesStaticPathsEntry,\n params: Record<string, unknown>,\n): boolean {\n return Object.entries(pathEntry.params).every(([key, value]) => {\n const actual = params[key];\n if (Array.isArray(value)) {\n return Array.isArray(actual) && value.join(\"/\") === actual.join(\"/\");\n }\n return String(value) === String(actual);\n });\n}\n\nfunction buildPagesCacheResponse(\n html: string,\n cacheState: \"HIT\" | \"STALE\",\n fontLinkHeader: string,\n revalidateSeconds?: number,\n expireSeconds?: number,\n cacheControl?: CacheControlMetadata,\n): Response {\n // Legacy cache entries written before cacheControl metadata existed can still\n // hit this path without a persisted revalidate value; keep the historic\n // 60-second fallback for that migration window.\n const effectiveRevalidateSeconds = cacheControl?.revalidate ?? revalidateSeconds ?? 60;\n const effectiveExpireSeconds =\n cacheControl === undefined ? undefined : (cacheControl.expire ?? expireSeconds);\n const headers: Record<string, string> = {\n \"Content-Type\": \"text/html\",\n [VINEXT_CACHE_HEADER]: cacheState,\n \"Cache-Control\": buildCachedRevalidateCacheControl(\n cacheState,\n effectiveRevalidateSeconds,\n effectiveExpireSeconds,\n ),\n };\n\n if (fontLinkHeader) {\n headers.Link = fontLinkHeader;\n }\n\n return new Response(html, {\n status: 200,\n headers,\n });\n}\n\nfunction rewritePagesCachedHtml(\n cachedHtml: string,\n freshBody: string,\n nextDataScript: string,\n): string {\n const bodyMarker = '<div id=\"__next\">';\n const bodyStart = cachedHtml.indexOf(bodyMarker);\n const contentStart = bodyStart >= 0 ? bodyStart + bodyMarker.length : -1;\n // This intentionally looks for the bare inline __NEXT_DATA__ marker.\n // Pages responses with scriptNonce are excluded from ISR writes, so cached\n // HTML should never contain nonce-prefixed __NEXT_DATA__ scripts here.\n const nextDataMarker = \"<script>window.__NEXT_DATA__\";\n const nextDataStart = cachedHtml.indexOf(nextDataMarker);\n\n if (contentStart >= 0 && nextDataStart >= 0) {\n const region = cachedHtml.slice(contentStart, nextDataStart);\n const lastCloseDiv = region.lastIndexOf(\"</div>\");\n const gap = lastCloseDiv >= 0 ? region.slice(lastCloseDiv + 6) : \"\";\n const nextDataEnd = cachedHtml.indexOf(\"</script>\", nextDataStart) + 9;\n const tail = cachedHtml.slice(nextDataEnd);\n\n return cachedHtml.slice(0, contentStart) + freshBody + \"</div>\" + gap + nextDataScript + tail;\n }\n\n return (\n '<!DOCTYPE html>\\n<html>\\n<head>\\n</head>\\n<body>\\n <div id=\"__next\">' +\n freshBody +\n \"</div>\\n \" +\n nextDataScript +\n \"\\n</body>\\n</html>\"\n );\n}\n\nexport async function renderPagesIsrHtml(options: RenderPagesIsrHtmlOptions): Promise<string> {\n const freshBody = await options.renderIsrPassToStringAsync(\n options.createPageElement(options.pageProps),\n );\n const nextDataScript = buildPagesNextDataScript({\n buildId: options.buildId,\n i18n: options.i18n,\n pageProps: options.pageProps,\n params: options.params,\n routePattern: options.routePattern,\n safeJsonStringify: options.safeJsonStringify,\n });\n\n return rewritePagesCachedHtml(options.cachedHtml, freshBody, nextDataScript);\n}\n\nexport async function resolvePagesPageData(\n options: ResolvePagesPageDataOptions,\n): Promise<ResolvePagesPageDataResult> {\n if (typeof options.pageModule.getStaticPaths === \"function\" && options.route.isDynamic) {\n const pathsResult = await options.pageModule.getStaticPaths({\n locales: options.i18n.locales ?? [],\n defaultLocale: options.i18n.defaultLocale ?? \"\",\n });\n const fallback = pathsResult?.fallback ?? false;\n\n if (fallback === false) {\n const paths = pathsResult?.paths ?? [];\n const isValidPath = paths.some((pathEntry) =>\n matchesPagesStaticPath(pathEntry, options.params),\n );\n\n if (!isValidPath) {\n return {\n kind: \"response\",\n response: buildPagesNotFoundResponse(),\n };\n }\n }\n }\n\n let pageProps: Record<string, unknown> = {};\n let gsspRes: PagesMutableGsspResponse | null = null;\n\n if (typeof options.pageModule.getServerSideProps === \"function\") {\n const { req, res, responsePromise } = options.createGsspReqRes();\n const result = await options.pageModule.getServerSideProps({\n params: options.params,\n req,\n res,\n query: options.query,\n resolvedUrl: options.routeUrl,\n locale: options.i18n.locale,\n locales: options.i18n.locales,\n defaultLocale: options.i18n.defaultLocale,\n });\n\n if (res.headersSent) {\n return {\n kind: \"response\",\n response: await responsePromise,\n };\n }\n\n if (result?.props) {\n pageProps = result.props;\n }\n\n if (result?.redirect) {\n return {\n kind: \"response\",\n response: new Response(null, {\n status: resolvePagesRedirectStatus(result.redirect),\n headers: { Location: options.sanitizeDestination(result.redirect.destination) },\n }),\n };\n }\n\n if (result?.notFound) {\n return {\n kind: \"response\",\n response: buildPagesDataNotFoundResponse(),\n };\n }\n\n gsspRes = res;\n }\n\n let isrRevalidateSeconds: number | null = null;\n\n if (typeof options.pageModule.getStaticProps === \"function\") {\n const pathname = options.routeUrl.split(\"?\")[0];\n const cacheKey = options.isrCacheKey(\"pages\", pathname);\n const cached = await options.isrGet(cacheKey);\n const cachedValue = cached?.value.value;\n\n if (cachedValue?.kind === \"PAGES\" && cached && !cached.isStale && !options.scriptNonce) {\n return {\n kind: \"response\",\n response: buildPagesCacheResponse(\n cachedValue.html,\n \"HIT\",\n options.fontLinkHeader,\n undefined,\n options.expireSeconds,\n cached.value.cacheControl,\n ),\n };\n }\n\n if (cachedValue?.kind === \"PAGES\" && cached && cached.isStale && !options.scriptNonce) {\n options.triggerBackgroundRegeneration(\n cacheKey,\n async function () {\n return options.runInFreshUnifiedContext(async () => {\n const freshResult = await options.pageModule.getStaticProps?.({\n params: options.params,\n locale: options.i18n.locale,\n locales: options.i18n.locales,\n defaultLocale: options.i18n.defaultLocale,\n });\n\n if (\n freshResult?.props &&\n typeof freshResult.revalidate === \"number\" &&\n freshResult.revalidate > 0\n ) {\n options.applyRequestContexts();\n const freshHtml = await renderPagesIsrHtml({\n buildId: options.buildId,\n cachedHtml: cachedValue.html,\n createPageElement: options.createPageElement,\n i18n: options.i18n,\n pageProps: freshResult.props,\n params: options.params,\n renderIsrPassToStringAsync: options.renderIsrPassToStringAsync,\n routePattern: options.routePattern,\n safeJsonStringify: options.safeJsonStringify,\n });\n\n await options.isrSet(\n cacheKey,\n buildPagesCacheValue(freshHtml, freshResult.props),\n freshResult.revalidate,\n undefined,\n options.expireSeconds,\n );\n }\n });\n },\n {\n routerKind: \"Pages Router\",\n routePath: options.routePattern,\n routeType: \"render\",\n },\n );\n\n return {\n kind: \"response\",\n response: buildPagesCacheResponse(\n cachedValue.html,\n \"STALE\",\n options.fontLinkHeader,\n undefined,\n options.expireSeconds,\n cached.value.cacheControl,\n ),\n };\n }\n\n const result = await options.pageModule.getStaticProps({\n params: options.params,\n locale: options.i18n.locale,\n locales: options.i18n.locales,\n defaultLocale: options.i18n.defaultLocale,\n });\n\n if (result?.props) {\n pageProps = result.props;\n }\n\n if (result?.redirect) {\n return {\n kind: \"response\",\n response: new Response(null, {\n status: resolvePagesRedirectStatus(result.redirect),\n headers: { Location: options.sanitizeDestination(result.redirect.destination) },\n }),\n };\n }\n\n if (result?.notFound) {\n return {\n kind: \"response\",\n response: buildPagesDataNotFoundResponse(),\n };\n }\n\n if (typeof result?.revalidate === \"number\" && result.revalidate > 0) {\n isrRevalidateSeconds = result.revalidate;\n }\n }\n\n return {\n kind: \"render\",\n gsspRes,\n isrRevalidateSeconds,\n pageProps,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
2
|
+
import { VINEXT_CACHE_HEADER } from "./headers.js";
|
|
2
3
|
import { reportRequestError } from "./instrumentation.js";
|
|
3
4
|
import { withScriptNonce } from "../shims/script-nonce-context.js";
|
|
4
5
|
import { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr } from "./html.js";
|
|
5
|
-
import { buildRevalidateCacheControl } from "./cache-control.js";
|
|
6
6
|
import { readStreamAsText } from "../utils/text-stream.js";
|
|
7
|
+
import { buildRevalidateCacheControl } from "./cache-control.js";
|
|
7
8
|
import React from "react";
|
|
8
9
|
//#region src/server/pages-page-response.ts
|
|
9
10
|
function buildPagesFontHeadHtml(fontLinks, fontPreloads, fontStyles, scriptNonce) {
|
|
@@ -160,7 +161,7 @@ async function renderPagesPageResponse(options) {
|
|
|
160
161
|
if (options.scriptNonce) responseHeaders.set("Cache-Control", "no-store, must-revalidate");
|
|
161
162
|
else if (options.isrRevalidateSeconds) {
|
|
162
163
|
responseHeaders.set("Cache-Control", buildRevalidateCacheControl(options.isrRevalidateSeconds, options.expireSeconds));
|
|
163
|
-
responseHeaders.set(
|
|
164
|
+
responseHeaders.set(VINEXT_CACHE_HEADER, "MISS");
|
|
164
165
|
}
|
|
165
166
|
if (options.fontLinkHeader) responseHeaders.set("Link", options.fontLinkHeader);
|
|
166
167
|
return Object.assign(new Response(compositeStream, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages-page-response.js","names":[],"sources":["../../src/server/pages-page-response.ts"],"sourcesContent":["import React, { type ComponentType, type ReactNode } from \"react\";\nimport type { CachedPagesValue } from \"vinext/shims/cache\";\nimport { withScriptNonce } from \"vinext/shims/script-nonce-context\";\nimport { getRequestExecutionContext } from \"vinext/shims/request-context\";\nimport { buildRevalidateCacheControl } from \"./cache-control.js\";\nimport { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr } from \"./html.js\";\nimport { reportRequestError } from \"./instrumentation.js\";\nimport { readStreamAsText } from \"../utils/text-stream.js\";\n\ntype PagesFontPreload = {\n href: string;\n type: string;\n};\n\nexport type PagesI18nRenderContext = {\n locale?: string;\n locales?: string[];\n defaultLocale?: string;\n domainLocales?: unknown;\n};\n\nexport type PagesGsspResponse = {\n statusCode: number;\n getHeaders(): Record<string, string | number | boolean | string[]>;\n};\n\ntype PagesStreamedHtmlResponse = {\n __vinextStreamedHtmlResponse?: boolean;\n} & Response;\n\ntype RenderPagesPageResponseOptions = {\n assetTags: string;\n buildId: string | null;\n clearSsrContext: () => void;\n createPageElement: (pageProps: Record<string, unknown>) => ReactNode;\n DocumentComponent: ComponentType | null;\n flushPreloads?: (() => Promise<void> | void) | undefined;\n fontLinkHeader: string;\n fontPreloads: PagesFontPreload[];\n getFontLinks: () => string[];\n getFontStyles: () => string[];\n getSSRHeadHTML?: (() => string) | undefined;\n gsspRes: PagesGsspResponse | null;\n isrCacheKey: (router: string, pathname: string) => string;\n expireSeconds?: number;\n isrRevalidateSeconds: number | null;\n isrSet: (\n key: string,\n data: CachedPagesValue,\n revalidateSeconds: number,\n tags?: string[],\n expireSeconds?: number,\n ) => Promise<void>;\n i18n: PagesI18nRenderContext;\n pageProps: Record<string, unknown>;\n params: Record<string, unknown>;\n renderDocumentToString: (element: ReactNode) => Promise<string>;\n renderToReadableStream: (element: ReactNode) => Promise<ReadableStream<Uint8Array>>;\n resetSSRHead?: (() => void) | undefined;\n routePattern: string;\n routeUrl: string;\n safeJsonStringify: (value: unknown) => string;\n scriptNonce?: string;\n};\n\nfunction buildPagesFontHeadHtml(\n fontLinks: string[],\n fontPreloads: PagesFontPreload[],\n fontStyles: string[],\n scriptNonce?: string,\n): string {\n let html = \"\";\n const nonceAttr = createNonceAttribute(scriptNonce);\n\n for (const link of fontLinks) {\n html += `<link rel=\"stylesheet\"${nonceAttr} href=\"${escapeHtmlAttr(link)}\" />\\n `;\n }\n\n for (const preload of fontPreloads) {\n html += `<link rel=\"preload\"${nonceAttr} href=\"${escapeHtmlAttr(preload.href)}\" as=\"font\" type=\"${escapeHtmlAttr(preload.type)}\" crossorigin />\\n `;\n }\n\n if (fontStyles.length > 0) {\n html += `<style data-vinext-fonts${nonceAttr}>${fontStyles.join(\"\\n\")}</style>\\n `;\n }\n\n return html;\n}\n\nexport function buildPagesNextDataScript(\n options: Pick<\n RenderPagesPageResponseOptions,\n | \"buildId\"\n | \"i18n\"\n | \"pageProps\"\n | \"params\"\n | \"routePattern\"\n | \"safeJsonStringify\"\n | \"scriptNonce\"\n >,\n): string {\n const nextDataPayload: Record<string, unknown> = {\n props: { pageProps: options.pageProps },\n page: options.routePattern,\n query: options.params,\n buildId: options.buildId,\n isFallback: false,\n };\n\n if (options.i18n.locales) {\n nextDataPayload.locale = options.i18n.locale;\n nextDataPayload.locales = options.i18n.locales;\n nextDataPayload.defaultLocale = options.i18n.defaultLocale;\n nextDataPayload.domainLocales = options.i18n.domainLocales;\n }\n\n const localeGlobals = options.i18n.locales\n ? `;window.__VINEXT_LOCALE__=${options.safeJsonStringify(options.i18n.locale)}` +\n `;window.__VINEXT_LOCALES__=${options.safeJsonStringify(options.i18n.locales)}` +\n `;window.__VINEXT_DEFAULT_LOCALE__=${options.safeJsonStringify(options.i18n.defaultLocale)}`\n : \"\";\n\n return createInlineScriptTag(\n `window.__NEXT_DATA__ = ${options.safeJsonStringify(nextDataPayload)}${localeGlobals}`,\n options.scriptNonce,\n );\n}\n\nasync function buildPagesShellHtml(\n bodyMarker: string,\n fontHeadHTML: string,\n nextDataScript: string,\n options: Pick<\n RenderPagesPageResponseOptions,\n \"assetTags\" | \"DocumentComponent\" | \"renderDocumentToString\"\n > & {\n ssrHeadHTML: string;\n },\n): Promise<string> {\n if (options.DocumentComponent) {\n let html = await options.renderDocumentToString(React.createElement(options.DocumentComponent));\n html = html.replace(\"__NEXT_MAIN__\", bodyMarker);\n if (options.ssrHeadHTML || options.assetTags || fontHeadHTML) {\n html = html.replace(\n \"</head>\",\n ` ${fontHeadHTML}${options.ssrHeadHTML}\\n ${options.assetTags}\\n</head>`,\n );\n }\n html = html.replace(\"<!-- __NEXT_SCRIPTS__ -->\", nextDataScript);\n if (!html.includes(\"__NEXT_DATA__\")) {\n html = html.replace(\"</body>\", ` ${nextDataScript}\\n</body>`);\n }\n return html;\n }\n\n return (\n \"<!DOCTYPE html>\\n<html>\\n<head>\\n\" +\n ' <meta charset=\"utf-8\" />\\n' +\n ' <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\\n' +\n ` ${fontHeadHTML}${options.ssrHeadHTML}\\n` +\n ` ${options.assetTags}\\n` +\n \"</head>\\n<body>\\n\" +\n ` <div id=\"__next\">${bodyMarker}</div>\\n` +\n ` ${nextDataScript}\\n` +\n \"</body>\\n</html>\"\n );\n}\n\nasync function buildPagesCompositeStream(\n bodyStream: ReadableStream<Uint8Array>,\n shellPrefix: string,\n shellSuffix: string,\n): Promise<ReadableStream<Uint8Array>> {\n const encoder = new TextEncoder();\n\n return new ReadableStream({\n async start(controller) {\n controller.enqueue(encoder.encode(shellPrefix));\n const reader = bodyStream.getReader();\n try {\n for (;;) {\n const chunk = await reader.read();\n if (chunk.done) {\n break;\n }\n controller.enqueue(chunk.value);\n }\n } finally {\n reader.releaseLock();\n }\n controller.enqueue(encoder.encode(shellSuffix));\n controller.close();\n },\n });\n}\n\nasync function reportPagesIsrCacheWriteError(\n error: unknown,\n cacheKey: string,\n routePattern: string,\n): Promise<void> {\n console.error(`[vinext] Pages ISR cache write failed for ${cacheKey}:`, error);\n try {\n await reportRequestError(\n error instanceof Error ? error : new Error(String(error)),\n { path: cacheKey, method: \"GET\", headers: {} },\n {\n routerKind: \"Pages Router\",\n routePath: routePattern,\n routeType: \"render\",\n },\n );\n } catch {\n // Cache-write failure reporting must never make the background task reject.\n }\n}\n\nfunction schedulePagesIsrCacheWrite(options: {\n cacheKey: string;\n expireSeconds?: number;\n pageData: Record<string, unknown>;\n revalidateSeconds: number;\n routePattern: string;\n shellPrefix: string;\n shellSuffix: string;\n stream: ReadableStream<Uint8Array>;\n setCache: RenderPagesPageResponseOptions[\"isrSet\"];\n}): void {\n const cacheWritePromise = readStreamAsText(options.stream)\n .then((bodyHtml) =>\n options.setCache(\n options.cacheKey,\n {\n kind: \"PAGES\",\n html: options.shellPrefix + bodyHtml + options.shellSuffix,\n pageData: options.pageData,\n headers: undefined,\n status: undefined,\n },\n options.revalidateSeconds,\n undefined,\n options.expireSeconds,\n ),\n )\n .catch((error: unknown) =>\n reportPagesIsrCacheWriteError(error, options.cacheKey, options.routePattern),\n );\n\n getRequestExecutionContext()?.waitUntil(cacheWritePromise);\n}\n\nfunction applyGsspHeaders(headers: Headers, gsspRes: PagesGsspResponse | null): number {\n if (!gsspRes) {\n return 200;\n }\n\n const gsspHeaders = gsspRes.getHeaders();\n for (const key of Object.keys(gsspHeaders)) {\n const value = gsspHeaders[key];\n const lowerKey = key.toLowerCase();\n if (lowerKey === \"set-cookie\" && Array.isArray(value)) {\n for (const cookie of value) {\n headers.append(\"set-cookie\", String(cookie));\n }\n continue;\n }\n if (Array.isArray(value)) {\n headers.set(key, value.join(\", \"));\n continue;\n }\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n headers.set(key, String(value));\n }\n }\n headers.set(\"Content-Type\", \"text/html\");\n return gsspRes.statusCode;\n}\n\nexport async function renderPagesPageResponse(\n options: RenderPagesPageResponseOptions,\n): Promise<Response> {\n const pageElement = withScriptNonce(\n React.createElement(React.Fragment, null, options.createPageElement(options.pageProps)),\n options.scriptNonce,\n );\n\n options.resetSSRHead?.();\n await options.flushPreloads?.();\n\n const fontHeadHTML = buildPagesFontHeadHtml(\n options.getFontLinks(),\n options.fontPreloads,\n options.getFontStyles(),\n options.scriptNonce,\n );\n const nextDataScript = buildPagesNextDataScript({\n buildId: options.buildId,\n i18n: options.i18n,\n pageProps: options.pageProps,\n params: options.params,\n routePattern: options.routePattern,\n safeJsonStringify: options.safeJsonStringify,\n scriptNonce: options.scriptNonce,\n });\n const bodyMarker = \"<!--VINEXT_STREAM_BODY-->\";\n // Render the page FIRST so that <Head> and other SSR state collectors\n // (e.g. styled-jsx, useServerInsertedHTML) are populated before we read\n // them. This fixes a race condition where head styles were silently dropped\n // because they were collected before the page had finished rendering.\n // Mirrors Next.js fix: vercel/next.js@9853944\n const bodyStream = await options.renderToReadableStream(pageElement);\n\n const shellHtml = await buildPagesShellHtml(bodyMarker, fontHeadHTML, nextDataScript, {\n assetTags: options.assetTags,\n DocumentComponent: options.DocumentComponent,\n renderDocumentToString: options.renderDocumentToString,\n ssrHeadHTML: options.getSSRHeadHTML?.() ?? \"\",\n });\n\n options.clearSsrContext();\n\n const markerIndex = shellHtml.indexOf(bodyMarker);\n const shellPrefix = shellHtml.slice(0, markerIndex);\n const shellSuffix = shellHtml.slice(markerIndex + bodyMarker.length);\n\n let responseBodyStream = bodyStream;\n if (\n // Keep nonce-bearing pages out of ISR writes: rewritePagesCachedHtml()\n // later matches the cached __NEXT_DATA__ block via a bare <script> marker.\n !options.scriptNonce &&\n options.isrRevalidateSeconds !== null &&\n options.isrRevalidateSeconds > 0\n ) {\n const cacheBodyStreamPair = bodyStream.tee();\n responseBodyStream = cacheBodyStreamPair[0];\n const cacheBodyStream = cacheBodyStreamPair[1];\n const isrPathname = options.routeUrl.split(\"?\")[0];\n const cacheKey = options.isrCacheKey(\"pages\", isrPathname);\n\n schedulePagesIsrCacheWrite({\n cacheKey,\n expireSeconds: options.expireSeconds,\n pageData: options.pageProps,\n revalidateSeconds: options.isrRevalidateSeconds,\n routePattern: options.routePattern,\n setCache: options.isrSet,\n shellPrefix,\n shellSuffix,\n stream: cacheBodyStream,\n });\n }\n\n const compositeStream = await buildPagesCompositeStream(\n responseBodyStream,\n shellPrefix,\n shellSuffix,\n );\n\n const responseHeaders = new Headers({ \"Content-Type\": \"text/html\" });\n const finalStatus = applyGsspHeaders(responseHeaders, options.gsspRes);\n\n if (options.scriptNonce) {\n responseHeaders.set(\"Cache-Control\", \"no-store, must-revalidate\");\n } else if (options.isrRevalidateSeconds) {\n responseHeaders.set(\n \"Cache-Control\",\n buildRevalidateCacheControl(options.isrRevalidateSeconds, options.expireSeconds),\n );\n responseHeaders.set(\"X-Vinext-Cache\", \"MISS\");\n }\n if (options.fontLinkHeader) {\n responseHeaders.set(\"Link\", options.fontLinkHeader);\n }\n\n const response: PagesStreamedHtmlResponse = Object.assign(\n new Response(compositeStream, {\n status: finalStatus,\n headers: responseHeaders,\n }),\n {\n __vinextStreamedHtmlResponse: true,\n },\n );\n // Mark the normal streamed HTML render so the Node prod server can strip\n // stale Content-Length only for this path, not for custom gSSP responses.\n return response;\n}\n"],"mappings":";;;;;;;;AAiEA,SAAS,uBACP,WACA,cACA,YACA,aACQ;CACR,IAAI,OAAO;CACX,MAAM,YAAY,qBAAqB,YAAY;AAEnD,MAAK,MAAM,QAAQ,UACjB,SAAQ,yBAAyB,UAAU,SAAS,eAAe,KAAK,CAAC;AAG3E,MAAK,MAAM,WAAW,aACpB,SAAQ,sBAAsB,UAAU,SAAS,eAAe,QAAQ,KAAK,CAAC,oBAAoB,eAAe,QAAQ,KAAK,CAAC;AAGjI,KAAI,WAAW,SAAS,EACtB,SAAQ,2BAA2B,UAAU,GAAG,WAAW,KAAK,KAAK,CAAC;AAGxE,QAAO;;AAGT,SAAgB,yBACd,SAUQ;CACR,MAAM,kBAA2C;EAC/C,OAAO,EAAE,WAAW,QAAQ,WAAW;EACvC,MAAM,QAAQ;EACd,OAAO,QAAQ;EACf,SAAS,QAAQ;EACjB,YAAY;EACb;AAED,KAAI,QAAQ,KAAK,SAAS;AACxB,kBAAgB,SAAS,QAAQ,KAAK;AACtC,kBAAgB,UAAU,QAAQ,KAAK;AACvC,kBAAgB,gBAAgB,QAAQ,KAAK;AAC7C,kBAAgB,gBAAgB,QAAQ,KAAK;;CAG/C,MAAM,gBAAgB,QAAQ,KAAK,UAC/B,6BAA6B,QAAQ,kBAAkB,QAAQ,KAAK,OAAO,CAAA,6BAC7C,QAAQ,kBAAkB,QAAQ,KAAK,QAAQ,CAAA,oCACxC,QAAQ,kBAAkB,QAAQ,KAAK,cAAc,KAC1F;AAEJ,QAAO,sBACL,0BAA0B,QAAQ,kBAAkB,gBAAgB,GAAG,iBACvE,QAAQ,YACT;;AAGH,eAAe,oBACb,YACA,cACA,gBACA,SAMiB;AACjB,KAAI,QAAQ,mBAAmB;EAC7B,IAAI,OAAO,MAAM,QAAQ,uBAAuB,MAAM,cAAc,QAAQ,kBAAkB,CAAC;AAC/F,SAAO,KAAK,QAAQ,iBAAiB,WAAW;AAChD,MAAI,QAAQ,eAAe,QAAQ,aAAa,aAC9C,QAAO,KAAK,QACV,WACA,KAAK,eAAe,QAAQ,YAAY,MAAM,QAAQ,UAAU,WACjE;AAEH,SAAO,KAAK,QAAQ,6BAA6B,eAAe;AAChE,MAAI,CAAC,KAAK,SAAS,gBAAgB,CACjC,QAAO,KAAK,QAAQ,WAAW,KAAK,eAAe,WAAW;AAEhE,SAAO;;AAGT,QACE;;;;;IAGK,eAAe,QAAQ,YAAY,MACnC,QAAQ,UAAU;;qBAED,WAAW,YAC5B,eAAe;;;AAKxB,eAAe,0BACb,YACA,aACA,aACqC;CACrC,MAAM,UAAU,IAAI,aAAa;AAEjC,QAAO,IAAI,eAAe,EACxB,MAAM,MAAM,YAAY;AACtB,aAAW,QAAQ,QAAQ,OAAO,YAAY,CAAC;EAC/C,MAAM,SAAS,WAAW,WAAW;AACrC,MAAI;AACF,YAAS;IACP,MAAM,QAAQ,MAAM,OAAO,MAAM;AACjC,QAAI,MAAM,KACR;AAEF,eAAW,QAAQ,MAAM,MAAM;;YAEzB;AACR,UAAO,aAAa;;AAEtB,aAAW,QAAQ,QAAQ,OAAO,YAAY,CAAC;AAC/C,aAAW,OAAO;IAErB,CAAC;;AAGJ,eAAe,8BACb,OACA,UACA,cACe;AACf,SAAQ,MAAM,6CAA6C,SAAS,IAAI,MAAM;AAC9E,KAAI;AACF,QAAM,mBACJ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,EACzD;GAAE,MAAM;GAAU,QAAQ;GAAO,SAAS,EAAE;GAAE,EAC9C;GACE,YAAY;GACZ,WAAW;GACX,WAAW;GACZ,CACF;SACK;;AAKV,SAAS,2BAA2B,SAU3B;CACP,MAAM,oBAAoB,iBAAiB,QAAQ,OAAO,CACvD,MAAM,aACL,QAAQ,SACN,QAAQ,UACR;EACE,MAAM;EACN,MAAM,QAAQ,cAAc,WAAW,QAAQ;EAC/C,UAAU,QAAQ;EAClB,SAAS,KAAA;EACT,QAAQ,KAAA;EACT,EACD,QAAQ,mBACR,KAAA,GACA,QAAQ,cACT,CACF,CACA,OAAO,UACN,8BAA8B,OAAO,QAAQ,UAAU,QAAQ,aAAa,CAC7E;AAEH,6BAA4B,EAAE,UAAU,kBAAkB;;AAG5D,SAAS,iBAAiB,SAAkB,SAA2C;AACrF,KAAI,CAAC,QACH,QAAO;CAGT,MAAM,cAAc,QAAQ,YAAY;AACxC,MAAK,MAAM,OAAO,OAAO,KAAK,YAAY,EAAE;EAC1C,MAAM,QAAQ,YAAY;AAE1B,MADiB,IAAI,aAAa,KACjB,gBAAgB,MAAM,QAAQ,MAAM,EAAE;AACrD,QAAK,MAAM,UAAU,MACnB,SAAQ,OAAO,cAAc,OAAO,OAAO,CAAC;AAE9C;;AAEF,MAAI,MAAM,QAAQ,MAAM,EAAE;AACxB,WAAQ,IAAI,KAAK,MAAM,KAAK,KAAK,CAAC;AAClC;;AAEF,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,OAAO,UAAU,UAC7E,SAAQ,IAAI,KAAK,OAAO,MAAM,CAAC;;AAGnC,SAAQ,IAAI,gBAAgB,YAAY;AACxC,QAAO,QAAQ;;AAGjB,eAAsB,wBACpB,SACmB;CACnB,MAAM,cAAc,gBAClB,MAAM,cAAc,MAAM,UAAU,MAAM,QAAQ,kBAAkB,QAAQ,UAAU,CAAC,EACvF,QAAQ,YACT;AAED,SAAQ,gBAAgB;AACxB,OAAM,QAAQ,iBAAiB;CAE/B,MAAM,eAAe,uBACnB,QAAQ,cAAc,EACtB,QAAQ,cACR,QAAQ,eAAe,EACvB,QAAQ,YACT;CACD,MAAM,iBAAiB,yBAAyB;EAC9C,SAAS,QAAQ;EACjB,MAAM,QAAQ;EACd,WAAW,QAAQ;EACnB,QAAQ,QAAQ;EAChB,cAAc,QAAQ;EACtB,mBAAmB,QAAQ;EAC3B,aAAa,QAAQ;EACtB,CAAC;CACF,MAAM,aAAa;CAMnB,MAAM,aAAa,MAAM,QAAQ,uBAAuB,YAAY;CAEpE,MAAM,YAAY,MAAM,oBAAoB,YAAY,cAAc,gBAAgB;EACpF,WAAW,QAAQ;EACnB,mBAAmB,QAAQ;EAC3B,wBAAwB,QAAQ;EAChC,aAAa,QAAQ,kBAAkB,IAAI;EAC5C,CAAC;AAEF,SAAQ,iBAAiB;CAEzB,MAAM,cAAc,UAAU,QAAQ,WAAW;CACjD,MAAM,cAAc,UAAU,MAAM,GAAG,YAAY;CACnD,MAAM,cAAc,UAAU,MAAM,cAAc,GAAkB;CAEpE,IAAI,qBAAqB;AACzB,KAGE,CAAC,QAAQ,eACT,QAAQ,yBAAyB,QACjC,QAAQ,uBAAuB,GAC/B;EACA,MAAM,sBAAsB,WAAW,KAAK;AAC5C,uBAAqB,oBAAoB;EACzC,MAAM,kBAAkB,oBAAoB;EAC5C,MAAM,cAAc,QAAQ,SAAS,MAAM,IAAI,CAAC;AAGhD,6BAA2B;GACzB,UAHe,QAAQ,YAAY,SAAS,YAAY;GAIxD,eAAe,QAAQ;GACvB,UAAU,QAAQ;GAClB,mBAAmB,QAAQ;GAC3B,cAAc,QAAQ;GACtB,UAAU,QAAQ;GAClB;GACA;GACA,QAAQ;GACT,CAAC;;CAGJ,MAAM,kBAAkB,MAAM,0BAC5B,oBACA,aACA,YACD;CAED,MAAM,kBAAkB,IAAI,QAAQ,EAAE,gBAAgB,aAAa,CAAC;CACpE,MAAM,cAAc,iBAAiB,iBAAiB,QAAQ,QAAQ;AAEtE,KAAI,QAAQ,YACV,iBAAgB,IAAI,iBAAiB,4BAA4B;UACxD,QAAQ,sBAAsB;AACvC,kBAAgB,IACd,iBACA,4BAA4B,QAAQ,sBAAsB,QAAQ,cAAc,CACjF;AACD,kBAAgB,IAAI,kBAAkB,OAAO;;AAE/C,KAAI,QAAQ,eACV,iBAAgB,IAAI,QAAQ,QAAQ,eAAe;AAcrD,QAX4C,OAAO,OACjD,IAAI,SAAS,iBAAiB;EAC5B,QAAQ;EACR,SAAS;EACV,CAAC,EACF,EACE,8BAA8B,MAC/B,CACF"}
|
|
1
|
+
{"version":3,"file":"pages-page-response.js","names":[],"sources":["../../src/server/pages-page-response.ts"],"sourcesContent":["import React, { type ComponentType, type ReactNode } from \"react\";\nimport type { CachedPagesValue } from \"vinext/shims/cache\";\nimport { withScriptNonce } from \"vinext/shims/script-nonce-context\";\nimport { getRequestExecutionContext } from \"vinext/shims/request-context\";\nimport { buildRevalidateCacheControl } from \"./cache-control.js\";\nimport { VINEXT_CACHE_HEADER } from \"./headers.js\";\nimport { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr } from \"./html.js\";\nimport { reportRequestError } from \"./instrumentation.js\";\nimport { readStreamAsText } from \"../utils/text-stream.js\";\n\ntype PagesFontPreload = {\n href: string;\n type: string;\n};\n\nexport type PagesI18nRenderContext = {\n locale?: string;\n locales?: string[];\n defaultLocale?: string;\n domainLocales?: unknown;\n};\n\nexport type PagesGsspResponse = {\n statusCode: number;\n getHeaders(): Record<string, string | number | boolean | string[]>;\n};\n\ntype PagesStreamedHtmlResponse = {\n __vinextStreamedHtmlResponse?: boolean;\n} & Response;\n\ntype RenderPagesPageResponseOptions = {\n assetTags: string;\n buildId: string | null;\n clearSsrContext: () => void;\n createPageElement: (pageProps: Record<string, unknown>) => ReactNode;\n DocumentComponent: ComponentType | null;\n flushPreloads?: (() => Promise<void> | void) | undefined;\n fontLinkHeader: string;\n fontPreloads: PagesFontPreload[];\n getFontLinks: () => string[];\n getFontStyles: () => string[];\n getSSRHeadHTML?: (() => string) | undefined;\n gsspRes: PagesGsspResponse | null;\n isrCacheKey: (router: string, pathname: string) => string;\n expireSeconds?: number;\n isrRevalidateSeconds: number | null;\n isrSet: (\n key: string,\n data: CachedPagesValue,\n revalidateSeconds: number,\n tags?: string[],\n expireSeconds?: number,\n ) => Promise<void>;\n i18n: PagesI18nRenderContext;\n pageProps: Record<string, unknown>;\n params: Record<string, unknown>;\n renderDocumentToString: (element: ReactNode) => Promise<string>;\n renderToReadableStream: (element: ReactNode) => Promise<ReadableStream<Uint8Array>>;\n resetSSRHead?: (() => void) | undefined;\n routePattern: string;\n routeUrl: string;\n safeJsonStringify: (value: unknown) => string;\n scriptNonce?: string;\n};\n\nfunction buildPagesFontHeadHtml(\n fontLinks: string[],\n fontPreloads: PagesFontPreload[],\n fontStyles: string[],\n scriptNonce?: string,\n): string {\n let html = \"\";\n const nonceAttr = createNonceAttribute(scriptNonce);\n\n for (const link of fontLinks) {\n html += `<link rel=\"stylesheet\"${nonceAttr} href=\"${escapeHtmlAttr(link)}\" />\\n `;\n }\n\n for (const preload of fontPreloads) {\n html += `<link rel=\"preload\"${nonceAttr} href=\"${escapeHtmlAttr(preload.href)}\" as=\"font\" type=\"${escapeHtmlAttr(preload.type)}\" crossorigin />\\n `;\n }\n\n if (fontStyles.length > 0) {\n html += `<style data-vinext-fonts${nonceAttr}>${fontStyles.join(\"\\n\")}</style>\\n `;\n }\n\n return html;\n}\n\nexport function buildPagesNextDataScript(\n options: Pick<\n RenderPagesPageResponseOptions,\n | \"buildId\"\n | \"i18n\"\n | \"pageProps\"\n | \"params\"\n | \"routePattern\"\n | \"safeJsonStringify\"\n | \"scriptNonce\"\n >,\n): string {\n const nextDataPayload: Record<string, unknown> = {\n props: { pageProps: options.pageProps },\n page: options.routePattern,\n query: options.params,\n buildId: options.buildId,\n isFallback: false,\n };\n\n if (options.i18n.locales) {\n nextDataPayload.locale = options.i18n.locale;\n nextDataPayload.locales = options.i18n.locales;\n nextDataPayload.defaultLocale = options.i18n.defaultLocale;\n nextDataPayload.domainLocales = options.i18n.domainLocales;\n }\n\n const localeGlobals = options.i18n.locales\n ? `;window.__VINEXT_LOCALE__=${options.safeJsonStringify(options.i18n.locale)}` +\n `;window.__VINEXT_LOCALES__=${options.safeJsonStringify(options.i18n.locales)}` +\n `;window.__VINEXT_DEFAULT_LOCALE__=${options.safeJsonStringify(options.i18n.defaultLocale)}`\n : \"\";\n\n return createInlineScriptTag(\n `window.__NEXT_DATA__ = ${options.safeJsonStringify(nextDataPayload)}${localeGlobals}`,\n options.scriptNonce,\n );\n}\n\nasync function buildPagesShellHtml(\n bodyMarker: string,\n fontHeadHTML: string,\n nextDataScript: string,\n options: Pick<\n RenderPagesPageResponseOptions,\n \"assetTags\" | \"DocumentComponent\" | \"renderDocumentToString\"\n > & {\n ssrHeadHTML: string;\n },\n): Promise<string> {\n if (options.DocumentComponent) {\n let html = await options.renderDocumentToString(React.createElement(options.DocumentComponent));\n html = html.replace(\"__NEXT_MAIN__\", bodyMarker);\n if (options.ssrHeadHTML || options.assetTags || fontHeadHTML) {\n html = html.replace(\n \"</head>\",\n ` ${fontHeadHTML}${options.ssrHeadHTML}\\n ${options.assetTags}\\n</head>`,\n );\n }\n html = html.replace(\"<!-- __NEXT_SCRIPTS__ -->\", nextDataScript);\n if (!html.includes(\"__NEXT_DATA__\")) {\n html = html.replace(\"</body>\", ` ${nextDataScript}\\n</body>`);\n }\n return html;\n }\n\n return (\n \"<!DOCTYPE html>\\n<html>\\n<head>\\n\" +\n ' <meta charset=\"utf-8\" />\\n' +\n ' <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\\n' +\n ` ${fontHeadHTML}${options.ssrHeadHTML}\\n` +\n ` ${options.assetTags}\\n` +\n \"</head>\\n<body>\\n\" +\n ` <div id=\"__next\">${bodyMarker}</div>\\n` +\n ` ${nextDataScript}\\n` +\n \"</body>\\n</html>\"\n );\n}\n\nasync function buildPagesCompositeStream(\n bodyStream: ReadableStream<Uint8Array>,\n shellPrefix: string,\n shellSuffix: string,\n): Promise<ReadableStream<Uint8Array>> {\n const encoder = new TextEncoder();\n\n return new ReadableStream({\n async start(controller) {\n controller.enqueue(encoder.encode(shellPrefix));\n const reader = bodyStream.getReader();\n try {\n for (;;) {\n const chunk = await reader.read();\n if (chunk.done) {\n break;\n }\n controller.enqueue(chunk.value);\n }\n } finally {\n reader.releaseLock();\n }\n controller.enqueue(encoder.encode(shellSuffix));\n controller.close();\n },\n });\n}\n\nasync function reportPagesIsrCacheWriteError(\n error: unknown,\n cacheKey: string,\n routePattern: string,\n): Promise<void> {\n console.error(`[vinext] Pages ISR cache write failed for ${cacheKey}:`, error);\n try {\n await reportRequestError(\n error instanceof Error ? error : new Error(String(error)),\n { path: cacheKey, method: \"GET\", headers: {} },\n {\n routerKind: \"Pages Router\",\n routePath: routePattern,\n routeType: \"render\",\n },\n );\n } catch {\n // Cache-write failure reporting must never make the background task reject.\n }\n}\n\nfunction schedulePagesIsrCacheWrite(options: {\n cacheKey: string;\n expireSeconds?: number;\n pageData: Record<string, unknown>;\n revalidateSeconds: number;\n routePattern: string;\n shellPrefix: string;\n shellSuffix: string;\n stream: ReadableStream<Uint8Array>;\n setCache: RenderPagesPageResponseOptions[\"isrSet\"];\n}): void {\n const cacheWritePromise = readStreamAsText(options.stream)\n .then((bodyHtml) =>\n options.setCache(\n options.cacheKey,\n {\n kind: \"PAGES\",\n html: options.shellPrefix + bodyHtml + options.shellSuffix,\n pageData: options.pageData,\n headers: undefined,\n status: undefined,\n },\n options.revalidateSeconds,\n undefined,\n options.expireSeconds,\n ),\n )\n .catch((error: unknown) =>\n reportPagesIsrCacheWriteError(error, options.cacheKey, options.routePattern),\n );\n\n getRequestExecutionContext()?.waitUntil(cacheWritePromise);\n}\n\nfunction applyGsspHeaders(headers: Headers, gsspRes: PagesGsspResponse | null): number {\n if (!gsspRes) {\n return 200;\n }\n\n const gsspHeaders = gsspRes.getHeaders();\n for (const key of Object.keys(gsspHeaders)) {\n const value = gsspHeaders[key];\n const lowerKey = key.toLowerCase();\n if (lowerKey === \"set-cookie\" && Array.isArray(value)) {\n for (const cookie of value) {\n headers.append(\"set-cookie\", String(cookie));\n }\n continue;\n }\n if (Array.isArray(value)) {\n headers.set(key, value.join(\", \"));\n continue;\n }\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n headers.set(key, String(value));\n }\n }\n headers.set(\"Content-Type\", \"text/html\");\n return gsspRes.statusCode;\n}\n\nexport async function renderPagesPageResponse(\n options: RenderPagesPageResponseOptions,\n): Promise<Response> {\n const pageElement = withScriptNonce(\n React.createElement(React.Fragment, null, options.createPageElement(options.pageProps)),\n options.scriptNonce,\n );\n\n options.resetSSRHead?.();\n await options.flushPreloads?.();\n\n const fontHeadHTML = buildPagesFontHeadHtml(\n options.getFontLinks(),\n options.fontPreloads,\n options.getFontStyles(),\n options.scriptNonce,\n );\n const nextDataScript = buildPagesNextDataScript({\n buildId: options.buildId,\n i18n: options.i18n,\n pageProps: options.pageProps,\n params: options.params,\n routePattern: options.routePattern,\n safeJsonStringify: options.safeJsonStringify,\n scriptNonce: options.scriptNonce,\n });\n const bodyMarker = \"<!--VINEXT_STREAM_BODY-->\";\n // Render the page FIRST so that <Head> and other SSR state collectors\n // (e.g. styled-jsx, useServerInsertedHTML) are populated before we read\n // them. This fixes a race condition where head styles were silently dropped\n // because they were collected before the page had finished rendering.\n // Mirrors Next.js fix: vercel/next.js@9853944\n const bodyStream = await options.renderToReadableStream(pageElement);\n\n const shellHtml = await buildPagesShellHtml(bodyMarker, fontHeadHTML, nextDataScript, {\n assetTags: options.assetTags,\n DocumentComponent: options.DocumentComponent,\n renderDocumentToString: options.renderDocumentToString,\n ssrHeadHTML: options.getSSRHeadHTML?.() ?? \"\",\n });\n\n options.clearSsrContext();\n\n const markerIndex = shellHtml.indexOf(bodyMarker);\n const shellPrefix = shellHtml.slice(0, markerIndex);\n const shellSuffix = shellHtml.slice(markerIndex + bodyMarker.length);\n\n let responseBodyStream = bodyStream;\n if (\n // Keep nonce-bearing pages out of ISR writes: rewritePagesCachedHtml()\n // later matches the cached __NEXT_DATA__ block via a bare <script> marker.\n !options.scriptNonce &&\n options.isrRevalidateSeconds !== null &&\n options.isrRevalidateSeconds > 0\n ) {\n const cacheBodyStreamPair = bodyStream.tee();\n responseBodyStream = cacheBodyStreamPair[0];\n const cacheBodyStream = cacheBodyStreamPair[1];\n const isrPathname = options.routeUrl.split(\"?\")[0];\n const cacheKey = options.isrCacheKey(\"pages\", isrPathname);\n\n schedulePagesIsrCacheWrite({\n cacheKey,\n expireSeconds: options.expireSeconds,\n pageData: options.pageProps,\n revalidateSeconds: options.isrRevalidateSeconds,\n routePattern: options.routePattern,\n setCache: options.isrSet,\n shellPrefix,\n shellSuffix,\n stream: cacheBodyStream,\n });\n }\n\n const compositeStream = await buildPagesCompositeStream(\n responseBodyStream,\n shellPrefix,\n shellSuffix,\n );\n\n const responseHeaders = new Headers({ \"Content-Type\": \"text/html\" });\n const finalStatus = applyGsspHeaders(responseHeaders, options.gsspRes);\n\n if (options.scriptNonce) {\n responseHeaders.set(\"Cache-Control\", \"no-store, must-revalidate\");\n } else if (options.isrRevalidateSeconds) {\n responseHeaders.set(\n \"Cache-Control\",\n buildRevalidateCacheControl(options.isrRevalidateSeconds, options.expireSeconds),\n );\n responseHeaders.set(VINEXT_CACHE_HEADER, \"MISS\");\n }\n if (options.fontLinkHeader) {\n responseHeaders.set(\"Link\", options.fontLinkHeader);\n }\n\n const response: PagesStreamedHtmlResponse = Object.assign(\n new Response(compositeStream, {\n status: finalStatus,\n headers: responseHeaders,\n }),\n {\n __vinextStreamedHtmlResponse: true,\n },\n );\n // Mark the normal streamed HTML render so the Node prod server can strip\n // stale Content-Length only for this path, not for custom gSSP responses.\n return response;\n}\n"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { workUnitAsyncStorage } from "../shims/internal/work-unit-async-storage.
|
|
|
4
4
|
* Sets up the work unit async storage for prerendering.
|
|
5
5
|
*
|
|
6
6
|
* When VINEXT_PRERENDER=1, wraps execution in a workUnitAsyncStorage.run()
|
|
7
|
-
* with a PrerenderStore so that dynamic APIs (e.g.,
|
|
7
|
+
* with a PrerenderStore so that dynamic APIs (e.g., io()) can
|
|
8
8
|
* detect the prerender context and return hanging promises.
|
|
9
9
|
*
|
|
10
10
|
* Used by: app-rsc-entry.ts handler template.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prerender-work-unit-setup.js","names":[],"sources":["../../src/server/prerender-work-unit-setup.ts"],"sourcesContent":["/**\n * Sets up the work unit async storage for prerendering.\n *\n * When VINEXT_PRERENDER=1, wraps execution in a workUnitAsyncStorage.run()\n * with a PrerenderStore so that dynamic APIs (e.g.,
|
|
1
|
+
{"version":3,"file":"prerender-work-unit-setup.js","names":[],"sources":["../../src/server/prerender-work-unit-setup.ts"],"sourcesContent":["/**\n * Sets up the work unit async storage for prerendering.\n *\n * When VINEXT_PRERENDER=1, wraps execution in a workUnitAsyncStorage.run()\n * with a PrerenderStore so that dynamic APIs (e.g., io()) can\n * detect the prerender context and return hanging promises.\n *\n * Used by: app-rsc-entry.ts handler template.\n *\n * TODO: If future dynamic APIs need request-scoped stores for normal (non-prerender)\n * requests, add a `{ type: \"request\" }` store during normal request handling.\n */\nimport { workUnitAsyncStorage } from \"vinext/shims/internal/work-unit-async-storage\";\n\nexport function runWithPrerenderWorkUnit<T>(\n fn: () => Promise<T>,\n options?: { route?: string | (() => string) },\n): Promise<T> {\n if (process.env.VINEXT_PRERENDER === \"1\") {\n const controller = new AbortController();\n const route = typeof options?.route === \"function\" ? options.route() : options?.route;\n return workUnitAsyncStorage\n .run(\n {\n type: \"prerender\",\n renderSignal: controller.signal,\n route,\n },\n fn,\n )\n .finally(() => controller.abort());\n }\n return fn();\n}\n"],"mappings":";;;;;;;;;;;;;;AAcA,SAAgB,yBACd,IACA,SACY;CACZ,IAAI,QAAQ,IAAI,qBAAqB,KAAK;EACxC,MAAM,aAAa,IAAI,iBAAiB;EACxC,MAAM,QAAQ,OAAO,SAAS,UAAU,aAAa,QAAQ,OAAO,GAAG,SAAS;EAChF,OAAO,qBACJ,IACC;GACE,MAAM;GACN,cAAc,WAAW;GACzB;GACD,EACD,GACD,CACA,cAAc,WAAW,OAAO,CAAC;;CAEtC,OAAO,IAAI"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
2
2
|
import { hasBasePath, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
|
|
3
|
+
import { VINEXT_PRERENDER_SECRET_HEADER, VINEXT_STATIC_FILE_HEADER } from "./headers.js";
|
|
3
4
|
import { normalizePath } from "./normalize-path.js";
|
|
4
5
|
import { applyMiddlewareRequestHeaders, isExternalUrl, matchRedirect, matchRewrite, proxyExternalRequest, requestContextFromRequest, sanitizeDestination } from "../config/config-matchers.js";
|
|
5
6
|
import { notFoundResponse } from "./http-error-responses.js";
|
|
@@ -612,7 +613,7 @@ async function startAppRouterServer(options) {
|
|
|
612
613
|
const seededRoutes = await seedMemoryCacheFromPrerender(path.dirname(rscEntryPath));
|
|
613
614
|
if (seededRoutes > 0) console.log(`[vinext] Seeded ${seededRoutes} pre-rendered route${seededRoutes !== 1 ? "s" : ""} into memory cache`);
|
|
614
615
|
const staticCache = await StaticFileCache.create(clientDir);
|
|
615
|
-
const
|
|
616
|
+
const handleRequest = async (req, res) => {
|
|
616
617
|
const rawUrl = req.url ?? "/";
|
|
617
618
|
const rawPathname = rawUrl.split("?")[0];
|
|
618
619
|
if (isOpenRedirectShaped(rawPathname)) {
|
|
@@ -630,7 +631,7 @@ async function startAppRouterServer(options) {
|
|
|
630
631
|
return;
|
|
631
632
|
}
|
|
632
633
|
if (pathname === "/__vinext/prerender/static-params" || pathname === "/__vinext/prerender/pages-static-paths") {
|
|
633
|
-
const secret = req.headers[
|
|
634
|
+
const secret = req.headers[VINEXT_PRERENDER_SECRET_HEADER];
|
|
634
635
|
if (!prerenderSecret || secret !== prerenderSecret) {
|
|
635
636
|
res.writeHead(403);
|
|
636
637
|
res.end("Forbidden");
|
|
@@ -663,7 +664,7 @@ async function startAppRouterServer(options) {
|
|
|
663
664
|
try {
|
|
664
665
|
const qs = rawUrl.includes("?") ? rawUrl.slice(rawUrl.indexOf("?")) : "";
|
|
665
666
|
const response = await rscHandler(nodeToWebRequest(req, pathname + qs));
|
|
666
|
-
const staticFileSignal = response.headers.get(
|
|
667
|
+
const staticFileSignal = response.headers.get(VINEXT_STATIC_FILE_HEADER);
|
|
667
668
|
if (staticFileSignal) {
|
|
668
669
|
let staticFilePath = "/";
|
|
669
670
|
try {
|
|
@@ -672,7 +673,7 @@ async function startAppRouterServer(options) {
|
|
|
672
673
|
staticFilePath = staticFileSignal;
|
|
673
674
|
}
|
|
674
675
|
const staticResponseHeaders = omitHeadersCaseInsensitive(mergeResponseHeaders({}, response), [
|
|
675
|
-
|
|
676
|
+
VINEXT_STATIC_FILE_HEADER,
|
|
676
677
|
"content-encoding",
|
|
677
678
|
"content-length",
|
|
678
679
|
"content-type"
|
|
@@ -691,6 +692,9 @@ async function startAppRouterServer(options) {
|
|
|
691
692
|
res.end("Internal Server Error");
|
|
692
693
|
}
|
|
693
694
|
}
|
|
695
|
+
};
|
|
696
|
+
const server = createServer((req, res) => {
|
|
697
|
+
handleRequest(req, res);
|
|
694
698
|
});
|
|
695
699
|
await new Promise((resolve) => {
|
|
696
700
|
server.listen(port, host, () => {
|
|
@@ -705,6 +709,17 @@ async function startAppRouterServer(options) {
|
|
|
705
709
|
port: typeof addr === "object" && addr ? addr.port : port
|
|
706
710
|
};
|
|
707
711
|
}
|
|
712
|
+
function isPagesServerEntryPageRoute(value) {
|
|
713
|
+
if (!value || typeof value !== "object" || !("pattern" in value)) return false;
|
|
714
|
+
if (typeof value.pattern !== "string") return false;
|
|
715
|
+
if (!("module" in value) || value.module === void 0) return true;
|
|
716
|
+
const pageModule = value.module;
|
|
717
|
+
if (!pageModule || typeof pageModule !== "object") return false;
|
|
718
|
+
return !("getStaticPaths" in pageModule) || typeof pageModule.getStaticPaths === "function";
|
|
719
|
+
}
|
|
720
|
+
function readPagesServerEntryPageRoutes(value) {
|
|
721
|
+
return Array.isArray(value) && value.every(isPagesServerEntryPageRoute) ? value : void 0;
|
|
722
|
+
}
|
|
708
723
|
/**
|
|
709
724
|
* Start the Pages Router production server.
|
|
710
725
|
*
|
|
@@ -719,6 +734,8 @@ async function startPagesRouterServer(options) {
|
|
|
719
734
|
const serverMtime = fs.statSync(serverEntryPath).mtimeMs;
|
|
720
735
|
const serverEntry = await import(`${pathToFileURL(serverEntryPath).href}?t=${serverMtime}`);
|
|
721
736
|
const { renderPage, handleApiRoute: handleApi, runMiddleware, vinextConfig } = serverEntry;
|
|
737
|
+
const matchPageRoute = typeof serverEntry.matchPageRoute === "function" ? serverEntry.matchPageRoute : void 0;
|
|
738
|
+
const pageRoutes = readPagesServerEntryPageRoutes(serverEntry.pageRoutes);
|
|
722
739
|
const prerenderSecret = readPrerenderSecret(path.dirname(serverEntryPath));
|
|
723
740
|
const basePath = vinextConfig?.basePath ?? "";
|
|
724
741
|
const assetBase = basePath ? `${basePath}/` : "/";
|
|
@@ -733,6 +750,7 @@ async function startPagesRouterServer(options) {
|
|
|
733
750
|
const allowedImageWidths = [...vinextConfig?.images?.deviceSizes ?? DEFAULT_DEVICE_SIZES, ...vinextConfig?.images?.imageSizes ?? DEFAULT_IMAGE_SIZES];
|
|
734
751
|
const pagesImageConfig = vinextConfig?.images ? {
|
|
735
752
|
dangerouslyAllowSVG: vinextConfig.images.dangerouslyAllowSVG,
|
|
753
|
+
dangerouslyAllowLocalIP: vinextConfig.images.dangerouslyAllowLocalIP,
|
|
736
754
|
contentDispositionType: vinextConfig.images.contentDispositionType,
|
|
737
755
|
contentSecurityPolicy: vinextConfig.images.contentSecurityPolicy
|
|
738
756
|
} : void 0;
|
|
@@ -745,7 +763,7 @@ async function startPagesRouterServer(options) {
|
|
|
745
763
|
if (lazyChunks.length > 0) globalThis.__VINEXT_LAZY_CHUNKS__ = lazyChunks;
|
|
746
764
|
} catch {}
|
|
747
765
|
const staticCache = await StaticFileCache.create(clientDir);
|
|
748
|
-
const
|
|
766
|
+
const handleRequest = async (req, res) => {
|
|
749
767
|
const rawUrl = req.url ?? "/";
|
|
750
768
|
const rawPagesPathnameBeforeNormalize = rawUrl.split("?")[0];
|
|
751
769
|
if (isOpenRedirectShaped(rawPagesPathnameBeforeNormalize)) {
|
|
@@ -765,7 +783,7 @@ async function startPagesRouterServer(options) {
|
|
|
765
783
|
}
|
|
766
784
|
let url = pathname + rawQs;
|
|
767
785
|
if (pathname === "/__vinext/prerender/pages-static-paths") {
|
|
768
|
-
const secret = req.headers[
|
|
786
|
+
const secret = req.headers[VINEXT_PRERENDER_SECRET_HEADER];
|
|
769
787
|
if (!prerenderSecret || secret !== prerenderSecret) {
|
|
770
788
|
res.writeHead(403);
|
|
771
789
|
res.end("Forbidden");
|
|
@@ -776,7 +794,7 @@ async function startPagesRouterServer(options) {
|
|
|
776
794
|
const localesRaw = parsedUrl.searchParams.get("locales");
|
|
777
795
|
const locales = localesRaw ? JSON.parse(localesRaw) : [];
|
|
778
796
|
const defaultLocale = parsedUrl.searchParams.get("defaultLocale") ?? "";
|
|
779
|
-
const fn = (
|
|
797
|
+
const fn = (pageRoutes?.find((r) => r.pattern === pattern))?.module?.getStaticPaths;
|
|
780
798
|
if (typeof fn !== "function") {
|
|
781
799
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
782
800
|
res.end("null");
|
|
@@ -868,7 +886,7 @@ async function startPagesRouterServer(options) {
|
|
|
868
886
|
}
|
|
869
887
|
let resolvedUrl = url;
|
|
870
888
|
const middlewareHeaders = {};
|
|
871
|
-
let
|
|
889
|
+
let middlewareStatus;
|
|
872
890
|
if (typeof runMiddleware === "function") {
|
|
873
891
|
const result = await runMiddleware(webRequest, void 0);
|
|
874
892
|
if (result.waitUntilPromises && result.waitUntilPromises.length > 0) Promise.allSettled(result.waitUntilPromises);
|
|
@@ -907,9 +925,9 @@ async function startPagesRouterServer(options) {
|
|
|
907
925
|
else middlewareHeaders[key] = [value];
|
|
908
926
|
} else middlewareHeaders[key] = value;
|
|
909
927
|
if (result.rewriteUrl) resolvedUrl = result.rewriteUrl;
|
|
910
|
-
|
|
928
|
+
middlewareStatus = result.status ?? result.rewriteStatus;
|
|
911
929
|
}
|
|
912
|
-
const { postMwReqCtx, request: postMwReq } = applyMiddlewareRequestHeaders(middlewareHeaders, webRequest);
|
|
930
|
+
const { postMwReqCtx, request: postMwReq } = applyMiddlewareRequestHeaders(middlewareHeaders, webRequest, { preserveCredentialHeaders: isExternalUrl(resolvedUrl) });
|
|
913
931
|
webRequest = postMwReq;
|
|
914
932
|
let resolvedPathname = resolvedUrl.split("?")[0];
|
|
915
933
|
if (configHeaders.length) applyConfigHeadersToHeaderRecord(middlewareHeaders, {
|
|
@@ -937,7 +955,7 @@ async function startPagesRouterServer(options) {
|
|
|
937
955
|
let response;
|
|
938
956
|
if (typeof handleApi === "function") response = await handleApi(webRequest, resolvedUrl);
|
|
939
957
|
else response = new Response("404 - API route not found", { status: 404 });
|
|
940
|
-
const mergedResponse = mergeWebResponse(middlewareHeaders, response,
|
|
958
|
+
const mergedResponse = mergeWebResponse(middlewareHeaders, response, middlewareStatus);
|
|
941
959
|
if (!mergedResponse.body) {
|
|
942
960
|
await sendWebResponse(mergedResponse, req, res, compress);
|
|
943
961
|
return;
|
|
@@ -949,7 +967,8 @@ async function startPagesRouterServer(options) {
|
|
|
949
967
|
sendCompressed(req, res, responseBody, ct, mergedResponse.status, responseHeaders, compress, finalStatusText);
|
|
950
968
|
return;
|
|
951
969
|
}
|
|
952
|
-
|
|
970
|
+
const pageMatch = matchPageRoute ? matchPageRoute(resolvedPathname, webRequest) : null;
|
|
971
|
+
if ((!pageMatch || pageMatch.route.isDynamic) && configRewrites.afterFiles?.length) {
|
|
953
972
|
const rewritten = matchRewrite(resolvedPathname, configRewrites.afterFiles, postMwReqCtx);
|
|
954
973
|
if (rewritten) {
|
|
955
974
|
if (isExternalUrl(rewritten)) {
|
|
@@ -981,7 +1000,7 @@ async function startPagesRouterServer(options) {
|
|
|
981
1000
|
return;
|
|
982
1001
|
}
|
|
983
1002
|
const shouldStreamPagesResponse = isVinextStreamedHtmlResponse(response);
|
|
984
|
-
const mergedResponse = mergeWebResponse(middlewareHeaders, response,
|
|
1003
|
+
const mergedResponse = mergeWebResponse(middlewareHeaders, response, middlewareStatus);
|
|
985
1004
|
if (shouldStreamPagesResponse || !mergedResponse.body) {
|
|
986
1005
|
await sendWebResponse(mergedResponse, req, res, compress);
|
|
987
1006
|
return;
|
|
@@ -998,6 +1017,9 @@ async function startPagesRouterServer(options) {
|
|
|
998
1017
|
res.end("Internal Server Error");
|
|
999
1018
|
}
|
|
1000
1019
|
}
|
|
1020
|
+
};
|
|
1021
|
+
const server = createServer((req, res) => {
|
|
1022
|
+
handleRequest(req, res);
|
|
1001
1023
|
});
|
|
1002
1024
|
await new Promise((resolve) => {
|
|
1003
1025
|
server.listen(port, host, () => {
|