vinext 0.0.49 → 0.0.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build/client-build-config.js.map +1 -1
- package/dist/build/google-fonts/build-url.js.map +1 -1
- package/dist/build/google-fonts/fallback-metrics-data.js +14031 -0
- package/dist/build/google-fonts/fallback-metrics-data.js.map +1 -0
- package/dist/build/google-fonts/fallback-metrics.d.ts +13 -0
- package/dist/build/google-fonts/fallback-metrics.js +46 -0
- package/dist/build/google-fonts/fallback-metrics.js.map +1 -0
- package/dist/build/google-fonts/get-axes.js.map +1 -1
- package/dist/build/google-fonts/sort-variants.js.map +1 -1
- package/dist/build/google-fonts/validate.js.map +1 -1
- package/dist/build/layout-classification.js.map +1 -1
- package/dist/build/nitro-route-rules.js.map +1 -1
- package/dist/build/precompress.d.ts +13 -2
- package/dist/build/precompress.js +12 -3
- package/dist/build/precompress.js.map +1 -1
- package/dist/build/prerender.d.ts +17 -1
- package/dist/build/prerender.js +114 -23
- package/dist/build/prerender.js.map +1 -1
- package/dist/build/report.d.ts +5 -4
- package/dist/build/report.js +196 -348
- package/dist/build/report.js.map +1 -1
- package/dist/build/route-classification-injector.js.map +1 -1
- package/dist/build/route-classification-manifest.js.map +1 -1
- package/dist/build/run-prerender.js.map +1 -1
- package/dist/build/server-manifest.js.map +1 -1
- package/dist/build/ssr-manifest.js.map +1 -1
- package/dist/build/standalone.js.map +1 -1
- package/dist/build/static-export.js.map +1 -1
- package/dist/check.js +2 -1
- package/dist/check.js.map +1 -1
- package/dist/cli-args.js.map +1 -1
- package/dist/cli.js +68 -7
- package/dist/cli.js.map +1 -1
- package/dist/client/instrumentation-client-state.js.map +1 -1
- package/dist/client/validate-module-path.js.map +1 -1
- package/dist/client/vinext-next-data.d.ts +5 -1
- package/dist/client/window-next.d.ts +151 -0
- package/dist/client/window-next.js +48 -0
- package/dist/client/window-next.js.map +1 -0
- package/dist/cloudflare/kv-cache-handler.js.map +1 -1
- package/dist/cloudflare/tpr.js +2 -1
- package/dist/cloudflare/tpr.js.map +1 -1
- package/dist/config/config-matchers.d.ts +3 -1
- package/dist/config/config-matchers.js +5 -4
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/config/dotenv.d.ts +11 -1
- package/dist/config/dotenv.js.map +1 -1
- package/dist/config/next-config.d.ts +93 -6
- package/dist/config/next-config.js +233 -6
- package/dist/config/next-config.js.map +1 -1
- package/dist/config/tsconfig-paths.d.ts +13 -0
- package/dist/config/tsconfig-paths.js +117 -0
- package/dist/config/tsconfig-paths.js.map +1 -0
- package/dist/deploy.js +16 -7
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-browser-entry.d.ts +3 -1
- package/dist/entries/app-browser-entry.js +36 -2
- package/dist/entries/app-browser-entry.js.map +1 -1
- package/dist/entries/app-rsc-entry.d.ts +19 -1
- package/dist/entries/app-rsc-entry.js +49 -12
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.d.ts +9 -0
- package/dist/entries/app-rsc-manifest.js +8 -1
- package/dist/entries/app-rsc-manifest.js.map +1 -1
- package/dist/entries/app-ssr-entry.js.map +1 -1
- package/dist/entries/pages-client-entry.js +3 -5
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-entry-helpers.js.map +1 -1
- package/dist/entries/pages-server-entry.js +34 -1
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.js.map +1 -1
- package/dist/index.js +204 -53
- package/dist/index.js.map +1 -1
- package/dist/init.js.map +1 -1
- package/dist/plugins/async-hooks-stub.js.map +1 -1
- package/dist/plugins/client-reference-dedup.d.ts +15 -2
- package/dist/plugins/client-reference-dedup.js +138 -16
- package/dist/plugins/client-reference-dedup.js.map +1 -1
- package/dist/plugins/fonts.d.ts +2 -2
- package/dist/plugins/fonts.js +15 -6
- package/dist/plugins/fonts.js.map +1 -1
- package/dist/plugins/instrumentation-client.js.map +1 -1
- package/dist/plugins/og-assets.js.map +1 -1
- package/dist/plugins/optimize-imports.js.map +1 -1
- package/dist/plugins/postcss.js.map +1 -1
- package/dist/plugins/rsc-client-reference-loaders.d.ts +7 -0
- package/dist/plugins/rsc-client-reference-loaders.js +48 -0
- package/dist/plugins/rsc-client-reference-loaders.js.map +1 -0
- package/dist/plugins/rsc-client-shim-excludes.js.map +1 -1
- package/dist/plugins/sass.d.ts +34 -0
- package/dist/plugins/sass.js +22 -0
- package/dist/plugins/sass.js.map +1 -0
- package/dist/plugins/server-externals-manifest.js.map +1 -1
- package/dist/plugins/strip-server-exports.js.map +1 -1
- package/dist/routing/app-route-graph.d.ts +78 -6
- package/dist/routing/app-route-graph.js +241 -25
- package/dist/routing/app-route-graph.js.map +1 -1
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/file-matcher.js.map +1 -1
- package/dist/routing/pages-router.js.map +1 -1
- package/dist/routing/route-matching.js.map +1 -1
- package/dist/routing/route-pattern.d.ts +56 -1
- package/dist/routing/route-pattern.js +60 -1
- package/dist/routing/route-pattern.js.map +1 -1
- package/dist/routing/route-trie.js.map +1 -1
- package/dist/routing/route-validation.js.map +1 -1
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/api-handler.js.map +1 -1
- package/dist/server/app-browser-action-result.d.ts +44 -0
- package/dist/server/app-browser-action-result.js +79 -0
- package/dist/server/app-browser-action-result.js.map +1 -0
- package/dist/server/app-browser-entry.js +330 -133
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-error.js.map +1 -1
- package/dist/server/app-browser-hydration.d.ts +31 -0
- package/dist/server/app-browser-hydration.js +30 -0
- package/dist/server/app-browser-hydration.js.map +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +20 -4
- package/dist/server/app-browser-navigation-controller.js +90 -23
- package/dist/server/app-browser-navigation-controller.js.map +1 -1
- package/dist/server/app-browser-popstate.d.ts +16 -0
- package/dist/server/app-browser-popstate.js +17 -0
- package/dist/server/app-browser-popstate.js.map +1 -0
- package/dist/server/app-browser-rsc-redirect.d.ts +28 -0
- package/dist/server/app-browser-rsc-redirect.js +37 -0
- package/dist/server/app-browser-rsc-redirect.js.map +1 -0
- package/dist/server/app-browser-state.d.ts +27 -23
- package/dist/server/app-browser-state.js +158 -54
- package/dist/server/app-browser-state.js.map +1 -1
- package/dist/server/app-browser-stream.d.ts +9 -4
- package/dist/server/app-browser-stream.js +29 -8
- package/dist/server/app-browser-stream.js.map +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +11 -1
- package/dist/server/app-browser-visible-commit.js +69 -21
- package/dist/server/app-browser-visible-commit.js.map +1 -1
- package/dist/server/app-client-reference-preloader.js.map +1 -1
- package/dist/server/app-elements-wire.d.ts +43 -6
- package/dist/server/app-elements-wire.js +121 -5
- package/dist/server/app-elements-wire.js.map +1 -1
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-elements.js.map +1 -1
- package/dist/server/app-fallback-renderer.d.ts +10 -1
- package/dist/server/app-fallback-renderer.js +37 -1
- package/dist/server/app-fallback-renderer.js.map +1 -1
- package/dist/server/app-history-state.d.ts +26 -0
- package/dist/server/app-history-state.js +53 -0
- package/dist/server/app-history-state.js.map +1 -0
- package/dist/server/app-hook-warning-suppression.js.map +1 -1
- package/dist/server/app-middleware.d.ts +1 -1
- package/dist/server/app-middleware.js +4 -9
- package/dist/server/app-middleware.js.map +1 -1
- package/dist/server/app-mounted-slots-header.js.map +1 -1
- package/dist/server/app-page-boundary-render.d.ts +11 -1
- package/dist/server/app-page-boundary-render.js +27 -19
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-boundary.d.ts +1 -0
- package/dist/server/app-page-boundary.js +10 -7
- package/dist/server/app-page-boundary.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +23 -3
- package/dist/server/app-page-cache.js +63 -27
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-dispatch.d.ts +11 -1
- package/dist/server/app-page-dispatch.js +85 -14
- package/dist/server/app-page-dispatch.js.map +1 -1
- package/dist/server/app-page-element-builder.d.ts +10 -1
- package/dist/server/app-page-element-builder.js +38 -6
- package/dist/server/app-page-element-builder.js.map +1 -1
- package/dist/server/app-page-execution.js +2 -3
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-head.d.ts +7 -0
- package/dist/server/app-page-head.js +6 -1
- package/dist/server/app-page-head.js.map +1 -1
- package/dist/server/app-page-method.js.map +1 -1
- package/dist/server/app-page-params.js.map +1 -1
- package/dist/server/app-page-probe.d.ts +23 -1
- package/dist/server/app-page-probe.js +29 -1
- package/dist/server/app-page-probe.js.map +1 -1
- package/dist/server/app-page-render-observation.d.ts +35 -0
- package/dist/server/app-page-render-observation.js +68 -0
- package/dist/server/app-page-render-observation.js.map +1 -0
- package/dist/server/app-page-render.d.ts +12 -2
- package/dist/server/app-page-render.js +90 -7
- package/dist/server/app-page-render.js.map +1 -1
- package/dist/server/app-page-request.d.ts +1 -0
- package/dist/server/app-page-request.js +2 -1
- package/dist/server/app-page-request.js.map +1 -1
- package/dist/server/app-page-response.d.ts +2 -0
- package/dist/server/app-page-response.js +18 -7
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +9 -3
- package/dist/server/app-page-route-wiring.js +91 -62
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-page-segment-state.d.ts +10 -0
- package/dist/server/app-page-segment-state.js +87 -0
- package/dist/server/app-page-segment-state.js.map +1 -0
- package/dist/server/app-page-stream.d.ts +9 -2
- package/dist/server/app-page-stream.js +4 -1
- package/dist/server/app-page-stream.js.map +1 -1
- package/dist/server/app-post-middleware-context.js.map +1 -1
- package/dist/server/app-prerender-endpoints.js.map +1 -1
- package/dist/server/app-prerender-static-params.js.map +1 -1
- package/dist/server/app-render-dependency.js.map +1 -1
- package/dist/server/app-request-context.js.map +1 -1
- package/dist/server/app-route-handler-cache.js.map +1 -1
- package/dist/server/app-route-handler-dispatch.js +3 -1
- package/dist/server/app-route-handler-dispatch.js.map +1 -1
- package/dist/server/app-route-handler-execution.js.map +1 -1
- package/dist/server/app-route-handler-policy.js +1 -0
- package/dist/server/app-route-handler-policy.js.map +1 -1
- package/dist/server/app-route-handler-response.js +4 -3
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-route-handler-runtime.js.map +1 -1
- package/dist/server/app-router-entry.js +7 -15
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +23 -2
- package/dist/server/app-rsc-cache-busting.js +75 -19
- package/dist/server/app-rsc-cache-busting.js.map +1 -1
- package/dist/server/app-rsc-embedded-chunks.d.ts +9 -0
- package/dist/server/app-rsc-embedded-chunks.js +34 -0
- package/dist/server/app-rsc-embedded-chunks.js.map +1 -0
- package/dist/server/app-rsc-error-handler.js.map +1 -1
- package/dist/server/app-rsc-errors.d.ts +4 -1
- package/dist/server/app-rsc-errors.js +1 -1
- package/dist/server/app-rsc-errors.js.map +1 -1
- package/dist/server/app-rsc-handler.d.ts +18 -1
- package/dist/server/app-rsc-handler.js +55 -16
- package/dist/server/app-rsc-handler.js.map +1 -1
- package/dist/server/app-rsc-render-mode.d.ts +11 -0
- package/dist/server/app-rsc-render-mode.js +21 -0
- package/dist/server/app-rsc-render-mode.js.map +1 -0
- package/dist/server/app-rsc-request-normalization.d.ts +4 -1
- package/dist/server/app-rsc-request-normalization.js +7 -2
- package/dist/server/app-rsc-request-normalization.js.map +1 -1
- package/dist/server/app-rsc-response-finalizer.d.ts +2 -1
- package/dist/server/app-rsc-response-finalizer.js +6 -1
- package/dist/server/app-rsc-response-finalizer.js.map +1 -1
- package/dist/server/app-rsc-route-matching.d.ts +23 -0
- package/dist/server/app-rsc-route-matching.js +45 -23
- package/dist/server/app-rsc-route-matching.js.map +1 -1
- package/dist/server/app-segment-config.js.map +1 -1
- package/dist/server/app-server-action-execution.d.ts +51 -5
- package/dist/server/app-server-action-execution.js +161 -51
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/app-ssr-entry.d.ts +7 -0
- package/dist/server/app-ssr-entry.js +44 -14
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/app-ssr-error-meta.d.ts +14 -0
- package/dist/server/app-ssr-error-meta.js +50 -0
- package/dist/server/app-ssr-error-meta.js.map +1 -0
- package/dist/server/app-ssr-stream.d.ts +1 -1
- package/dist/server/app-ssr-stream.js +9 -12
- package/dist/server/app-ssr-stream.js.map +1 -1
- package/dist/server/app-static-generation.js.map +1 -1
- package/dist/server/artifact-compatibility.d.ts +12 -2
- package/dist/server/artifact-compatibility.js +12 -8
- package/dist/server/artifact-compatibility.js.map +1 -1
- package/dist/server/cache-control.js +1 -0
- package/dist/server/cache-control.js.map +1 -1
- package/dist/server/cache-proof.d.ts +124 -5
- package/dist/server/cache-proof.js +416 -18
- package/dist/server/cache-proof.js.map +1 -1
- package/dist/server/csp.js.map +1 -1
- package/dist/server/dev-error-overlay-store.js.map +1 -1
- package/dist/server/dev-error-overlay.js +5 -0
- package/dist/server/dev-error-overlay.js.map +1 -1
- package/dist/server/dev-lockfile.d.ts +110 -0
- package/dist/server/dev-lockfile.js +180 -0
- package/dist/server/dev-lockfile.js.map +1 -0
- package/dist/server/dev-module-runner.js.map +1 -1
- package/dist/server/dev-origin-check.js.map +1 -1
- package/dist/server/dev-route-files.js.map +1 -1
- package/dist/server/dev-server.js +23 -10
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/file-based-metadata.d.ts +13 -0
- package/dist/server/file-based-metadata.js +49 -2
- package/dist/server/file-based-metadata.js.map +1 -1
- package/dist/server/headers.d.ts +81 -0
- package/dist/server/headers.js +104 -0
- package/dist/server/headers.js.map +1 -0
- package/dist/server/html.js +1 -1
- package/dist/server/html.js.map +1 -1
- package/dist/server/http-error-responses.d.ts +10 -0
- package/dist/server/http-error-responses.js +11 -1
- package/dist/server/http-error-responses.js.map +1 -1
- package/dist/server/image-optimization.d.ts +11 -1
- package/dist/server/image-optimization.js.map +1 -1
- package/dist/server/implicit-tags.js +2 -1
- package/dist/server/implicit-tags.js.map +1 -1
- package/dist/server/instrumentation-runtime.js.map +1 -1
- package/dist/server/instrumentation.js.map +1 -1
- package/dist/server/isr-cache.d.ts +12 -2
- package/dist/server/isr-cache.js +16 -5
- package/dist/server/isr-cache.js.map +1 -1
- package/dist/server/metadata-route-build-data.js.map +1 -1
- package/dist/server/metadata-route-response.js +22 -5
- package/dist/server/metadata-route-response.js.map +1 -1
- package/dist/server/metadata-routes.js +27 -8
- package/dist/server/metadata-routes.js.map +1 -1
- package/dist/server/middleware-matcher.js.map +1 -1
- package/dist/server/middleware-request-headers.d.ts +4 -1
- package/dist/server/middleware-request-headers.js +15 -8
- package/dist/server/middleware-request-headers.js.map +1 -1
- package/dist/server/middleware-response-headers.d.ts +2 -1
- package/dist/server/middleware-response-headers.js +1 -1
- package/dist/server/middleware-response-headers.js.map +1 -1
- package/dist/server/middleware-runtime.d.ts +1 -0
- package/dist/server/middleware-runtime.js +7 -3
- package/dist/server/middleware-runtime.js.map +1 -1
- package/dist/server/middleware.d.ts +12 -0
- package/dist/server/middleware.js +12 -0
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/navigation-planner.d.ts +133 -0
- package/dist/server/navigation-planner.js +432 -0
- package/dist/server/navigation-planner.js.map +1 -0
- package/dist/server/navigation-trace.d.ts +19 -2
- package/dist/server/navigation-trace.js +20 -1
- package/dist/server/navigation-trace.js.map +1 -1
- package/dist/server/next-error-digest.d.ts +3 -2
- package/dist/server/next-error-digest.js +4 -2
- package/dist/server/next-error-digest.js.map +1 -1
- package/dist/server/normalize-path.d.ts +2 -1
- package/dist/server/normalize-path.js +4 -1
- package/dist/server/normalize-path.js.map +1 -1
- package/dist/server/pages-api-route.js +1 -0
- package/dist/server/pages-api-route.js.map +1 -1
- package/dist/server/pages-i18n.js.map +1 -1
- package/dist/server/pages-media-type.js.map +1 -1
- package/dist/server/pages-node-compat.js.map +1 -1
- package/dist/server/pages-page-data.d.ts +3 -2
- package/dist/server/pages-page-data.js +27 -5
- package/dist/server/pages-page-data.js.map +1 -1
- package/dist/server/pages-page-response.js +2 -1
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/prerender-work-unit-setup.js +1 -1
- package/dist/server/prerender-work-unit-setup.js.map +1 -1
- package/dist/server/prod-server.d.ts +28 -1
- package/dist/server/prod-server.js +97 -22
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-log.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +1 -13
- package/dist/server/request-pipeline.js +3 -25
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/server/rsc-stream-hints.js.map +1 -1
- package/dist/server/seed-cache.js.map +1 -1
- package/dist/server/server-action-not-found.d.ts +16 -3
- package/dist/server/server-action-not-found.js +22 -4
- package/dist/server/server-action-not-found.js.map +1 -1
- package/dist/server/server-globals.d.ts +5 -0
- package/dist/server/server-globals.js +37 -0
- package/dist/server/server-globals.js.map +1 -0
- package/dist/server/socket-error-backstop.js.map +1 -1
- package/dist/server/static-file-cache.js +1 -1
- package/dist/server/static-file-cache.js.map +1 -1
- package/dist/server/worker-utils.d.ts +0 -7
- package/dist/server/worker-utils.js +3 -2
- package/dist/server/worker-utils.js.map +1 -1
- package/dist/shims/amp.js.map +1 -1
- package/dist/shims/app.d.ts +37 -4
- package/dist/shims/app.js +50 -1
- package/dist/shims/app.js.map +1 -0
- package/dist/shims/cache-for-request.js.map +1 -1
- package/dist/shims/cache-runtime.d.ts +19 -2
- package/dist/shims/cache-runtime.js +87 -19
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.d.ts +20 -21
- package/dist/shims/cache.js +101 -15
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/client-hook-error.js.map +1 -1
- package/dist/shims/compat-router.js.map +1 -1
- package/dist/shims/config.js.map +1 -1
- package/dist/shims/constants.js.map +1 -1
- package/dist/shims/document.js.map +1 -1
- package/dist/shims/dynamic.d.ts +18 -10
- package/dist/shims/dynamic.js +107 -51
- package/dist/shims/dynamic.js.map +1 -1
- package/dist/shims/error-boundary.d.ts +35 -6
- package/dist/shims/error-boundary.js +116 -33
- package/dist/shims/error-boundary.js.map +1 -1
- package/dist/shims/error.d.ts +18 -1
- package/dist/shims/error.js +56 -1
- package/dist/shims/error.js.map +1 -1
- package/dist/shims/fetch-cache.d.ts +25 -1
- package/dist/shims/fetch-cache.js +159 -13
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/font-google-base.d.ts +22 -8
- package/dist/shims/font-google-base.js +41 -71
- package/dist/shims/font-google-base.js.map +1 -1
- package/dist/shims/font-local.d.ts +3 -20
- package/dist/shims/font-local.js +23 -75
- package/dist/shims/font-local.js.map +1 -1
- package/dist/shims/font-utils.d.ts +51 -0
- package/dist/shims/font-utils.js +97 -0
- package/dist/shims/font-utils.js.map +1 -0
- package/dist/shims/form.js +3 -1
- package/dist/shims/form.js.map +1 -1
- package/dist/shims/hash-scroll.d.ts +7 -0
- package/dist/shims/hash-scroll.js +30 -0
- package/dist/shims/hash-scroll.js.map +1 -0
- package/dist/shims/head-state.js.map +1 -1
- package/dist/shims/head.d.ts +3 -1
- package/dist/shims/head.js +28 -16
- package/dist/shims/head.js.map +1 -1
- package/dist/shims/headers.d.ts +11 -12
- package/dist/shims/headers.js +45 -8
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/i18n-context.js.map +1 -1
- package/dist/shims/i18n-state.js.map +1 -1
- package/dist/shims/image-config.d.ts +14 -1
- package/dist/shims/image-config.js +24 -1
- package/dist/shims/image-config.js.map +1 -1
- package/dist/shims/image.d.ts +1 -0
- package/dist/shims/image.js +159 -80
- package/dist/shims/image.js.map +1 -1
- package/dist/shims/internal/als-registry.js.map +1 -1
- package/dist/shims/internal/app-router-context.d.ts +7 -6
- package/dist/shims/internal/app-router-context.js +17 -6
- package/dist/shims/internal/app-router-context.js.map +1 -1
- package/dist/shims/internal/cookie-serialize.js.map +1 -1
- package/dist/shims/internal/make-hanging-promise.d.ts +1 -1
- package/dist/shims/internal/make-hanging-promise.js +1 -1
- package/dist/shims/internal/make-hanging-promise.js.map +1 -1
- package/dist/shims/internal/parse-cookie-header.js.map +1 -1
- package/dist/shims/internal/utils.js.map +1 -1
- package/dist/shims/internal/work-unit-async-storage.js +2 -2
- package/dist/shims/internal/work-unit-async-storage.js.map +1 -1
- package/dist/shims/layout-segment-context.js.map +1 -1
- package/dist/shims/legacy-image.js.map +1 -1
- package/dist/shims/link-prefetch.d.ts +42 -0
- package/dist/shims/link-prefetch.js +45 -0
- package/dist/shims/link-prefetch.js.map +1 -0
- package/dist/shims/link.d.ts +37 -4
- package/dist/shims/link.js +156 -46
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +16 -30
- package/dist/shims/metadata.js +87 -28
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation-state.js.map +1 -1
- package/dist/shims/navigation.d.ts +172 -10
- package/dist/shims/navigation.js +335 -70
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/navigation.react-server.d.ts +3 -2
- package/dist/shims/navigation.react-server.js +5 -2
- package/dist/shims/navigation.react-server.js.map +1 -1
- package/dist/shims/offline.js.map +1 -1
- package/dist/shims/pages-router-runtime.d.ts +7 -0
- package/dist/shims/pages-router-runtime.js +16 -0
- package/dist/shims/pages-router-runtime.js.map +1 -0
- package/dist/shims/readonly-url-search-params.js.map +1 -1
- package/dist/shims/request-context.js.map +1 -1
- package/dist/shims/root-params.js.map +1 -1
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/router.d.ts +69 -7
- package/dist/shims/router.js +232 -249
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/script-nonce-context.js.map +1 -1
- package/dist/shims/script.js +110 -32
- package/dist/shims/script.js.map +1 -1
- package/dist/shims/server.js +12 -15
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/slot.d.ts +7 -1
- package/dist/shims/slot.js +60 -7
- package/dist/shims/slot.js.map +1 -1
- package/dist/shims/thenable-params.js.map +1 -1
- package/dist/shims/unified-request-context.js +5 -0
- package/dist/shims/unified-request-context.js.map +1 -1
- package/dist/shims/unrecognized-action-error.d.ts +35 -0
- package/dist/shims/unrecognized-action-error.js +41 -0
- package/dist/shims/unrecognized-action-error.js.map +1 -0
- package/dist/shims/url-safety.js.map +1 -1
- package/dist/shims/url-utils.d.ts +22 -1
- package/dist/shims/url-utils.js +76 -3
- package/dist/shims/url-utils.js.map +1 -1
- package/dist/shims/use-merged-ref.js.map +1 -1
- package/dist/shims/web-vitals.d.ts +4 -21
- package/dist/shims/web-vitals.js +19 -6
- package/dist/shims/web-vitals.js.map +1 -1
- package/dist/utils/asset-prefix.d.ts +69 -0
- package/dist/utils/asset-prefix.js +91 -0
- package/dist/utils/asset-prefix.js.map +1 -0
- package/dist/utils/base-path.d.ts +7 -1
- package/dist/utils/base-path.js +10 -1
- package/dist/utils/base-path.js.map +1 -1
- package/dist/utils/cache-control-metadata.js.map +1 -1
- package/dist/utils/domain-locale.js.map +1 -1
- package/dist/utils/encode-cache-tag.d.ts +31 -0
- package/dist/utils/encode-cache-tag.js +38 -0
- package/dist/utils/encode-cache-tag.js.map +1 -0
- package/dist/utils/error-cause.js.map +1 -1
- package/dist/utils/hash.js.map +1 -1
- package/dist/utils/lazy-chunks.js.map +1 -1
- package/dist/utils/manifest-paths.js.map +1 -1
- package/dist/utils/mdx-scan.js.map +1 -1
- package/dist/utils/navigation-signal.d.ts +5 -0
- package/dist/utils/navigation-signal.js +14 -0
- package/dist/utils/navigation-signal.js.map +1 -0
- package/dist/utils/project.js.map +1 -1
- package/dist/utils/public-routes.js.map +1 -1
- package/dist/utils/query.js.map +1 -1
- package/dist/utils/safe-json-file.js.map +1 -1
- package/dist/utils/sorted-array.d.ts +9 -0
- package/dist/utils/sorted-array.js +22 -0
- package/dist/utils/sorted-array.js.map +1 -0
- package/dist/utils/text-stream.js.map +1 -1
- package/dist/utils/vinext-root.js.map +1 -1
- package/package.json +8 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache-proof.js","names":[],"sources":["../../src/server/cache-proof.ts"],"sourcesContent":["import type { AppRouteSemanticIds } from \"../routing/app-route-graph.js\";\nimport { fnv1a64 } from \"../utils/hash.js\";\n\nexport const CACHE_PROOF_MODEL_SCHEMA_VERSION = 0;\nexport type CacheProofModelSchemaVersion = 0;\n\nexport type CacheProofRejectionCode =\n | \"CP_MODEL_DISABLED\"\n | \"CP_DIMENSION_COUNT_EXCEEDED\"\n | \"CP_DIMENSION_NAME_MISSING\"\n | \"CP_DIMENSION_NAME_TOO_LONG\"\n | \"CP_DIMENSION_VALUE_COUNT_EXCEEDED\"\n | \"CP_DIMENSION_VALUE_TOO_LONG\"\n | \"CP_DIMENSION_VALUES_MISSING\"\n | \"CP_ENCODED_VARIANT_TOO_LONG\"\n | \"CP_INVALID_VARIANT_BUDGET\"\n | \"CP_ROUTE_VARIANT_CEILING_EXCEEDED\"\n | \"CP_UNSAFE_PUBLIC_DIMENSION\"\n | \"CP_BOUNDARY_OUTCOME_MISMATCH\"\n | \"CP_BOUNDARY_OUTCOME_UNKNOWN\";\n\nexport type CacheProofTraceFieldValue = string | number | boolean | null | readonly string[];\n\nexport type CacheProofTraceFields = Readonly<Record<string, CacheProofTraceFieldValue>>;\n\nexport type CacheProofBreakerFallbackMode = \"renderFresh\" | \"privateUncacheable\";\nexport type CacheProofFallbackScope = \"affectedOutput\" | \"route\";\n\nexport type CacheProofBreakerFallback = Readonly<{\n kind: \"breakerFallback\";\n code: CacheProofRejectionCode;\n mode: CacheProofBreakerFallbackMode;\n scope: CacheProofFallbackScope;\n fields: CacheProofTraceFields;\n}>;\n\nexport type CacheVariantBudget = Readonly<{\n maxDimensionCount: number;\n maxDimensionNameLength: number;\n maxDimensionValueLength: number;\n maxEncodedLength: number;\n maxValuesPerDimension: number;\n maxVariantsPerRoute: number;\n}>;\n\nexport const DEFAULT_CACHE_VARIANT_BUDGET = {\n maxDimensionCount: 8,\n maxDimensionNameLength: 64,\n maxDimensionValueLength: 256,\n maxEncodedLength: 1024,\n maxValuesPerDimension: 8,\n maxVariantsPerRoute: 64,\n} satisfies CacheVariantBudget;\n\nexport type CacheVariantDimensionSource =\n | \"auth\"\n | \"cookie\"\n | \"custom\"\n | \"draft-mode\"\n | \"header\"\n | \"interception\"\n | \"mounted-slots\"\n | \"params\"\n | \"route\"\n | \"search\"\n | \"session\";\n\nexport type CacheVariantDimensionPrivacy = \"internal\" | \"private\" | \"public\";\n\nexport type CacheVariantDimensionInput = Readonly<{\n name: string;\n privacy: CacheVariantDimensionPrivacy;\n source: CacheVariantDimensionSource;\n values: readonly string[];\n}>;\n\nexport type CacheVariantDimension = Readonly<{\n encoded: string;\n name: string;\n privacy: CacheVariantDimensionPrivacy;\n source: CacheVariantDimensionSource;\n valueCount: number;\n valueHashes: readonly string[];\n}>;\n\nexport type CacheProofOutputScope =\n | Readonly<{\n kind: \"app-html\";\n renderEpoch: string | null;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"app-rsc\";\n mountedSlotsFingerprint: string | null;\n renderEpoch: string | null;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"layout\";\n layoutId: string;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"page\";\n pageId: string;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"route-handler\";\n routeHandlerId: string;\n routeId: string;\n }>\n | Readonly<{\n kind: \"slot\";\n rootBoundaryId: string | null;\n routeId: string;\n slotId: string;\n }>\n | Readonly<{\n kind: \"template\";\n rootBoundaryId: string | null;\n routeId: string;\n templateId: string;\n }>;\n\nexport type CacheVariant = Readonly<{\n budget: CacheVariantBudget;\n cacheKey: string;\n dimensions: readonly CacheVariantDimension[];\n encodedLength: number;\n output: CacheProofOutputScope;\n schemaVersion: CacheProofModelSchemaVersion;\n}>;\n\nexport type BuildCacheVariantInput = Readonly<{\n budget: CacheVariantBudget;\n dimensions: readonly CacheVariantDimensionInput[];\n existingVariantCount: number;\n output: CacheProofOutputScope;\n}>;\n\nexport type BuildCacheVariantResult =\n | Readonly<{ kind: \"variant\"; variant: CacheVariant }>\n | Readonly<{ kind: \"breakerFallback\"; fallback: CacheProofBreakerFallback }>;\n\nexport type AppRouteCacheProofGraphScopeInput = Readonly<{\n ids: AppRouteSemanticIds;\n}>;\n\nexport type AppRouteCacheProofGraphScope = Readonly<{\n layoutIds: readonly string[];\n pageId: string | null;\n routeHandlerId: string | null;\n routeId: string;\n slotIds: readonly string[];\n templateIds: readonly string[];\n}>;\n\nexport type BoundaryOutcome =\n | Readonly<{ kind: \"error\"; digest?: string }>\n | Readonly<{ kind: \"forbidden\" }>\n | Readonly<{ kind: \"globalError\"; digest?: string }>\n | Readonly<{ kind: \"notFound\" }>\n | Readonly<{ kind: \"redirect\"; location: string; status: number }>\n | Readonly<{ kind: \"success\" }>\n | Readonly<{ kind: \"unauthorized\" }>\n | Readonly<{ kind: \"unknown\" }>;\n\nexport type BoundaryOutcomeCompatibility =\n | Readonly<{\n kind: \"compatible\";\n outcome: BoundaryOutcome;\n reason: \"CP_BOUNDARY_OUTCOME_MATCH\";\n }>\n | Readonly<{\n candidate: BoundaryOutcome;\n expected: BoundaryOutcome;\n fallback: CacheProofBreakerFallback;\n kind: \"incompatible\";\n }>;\n\nexport type RenderObservationCompleteness = \"complete\" | \"partial\" | \"unknown\";\nexport type RenderCacheability = \"private\" | \"public\" | \"uncacheable\" | \"unknown\";\nexport type RenderRequestApiKind =\n | \"connection\"\n | \"cookies\"\n | \"draftMode\"\n | \"headers\"\n | \"params\"\n | \"searchParams\";\nexport type RenderRequestApiStatus = \"notObserved\" | \"observed\" | \"unknown\";\n\nexport type RenderRequestApiObservation = Readonly<{\n kind: RenderRequestApiKind;\n status: RenderRequestApiStatus;\n}>;\n\nexport type RenderObservation = Readonly<{\n boundaryOutcome: BoundaryOutcome;\n cacheTags: readonly string[];\n cacheability: RenderCacheability;\n completeness: RenderObservationCompleteness;\n dynamicFetches: readonly string[];\n output: CacheProofOutputScope;\n pathTags: readonly string[];\n requestApis: readonly RenderRequestApiObservation[];\n schemaVersion: CacheProofModelSchemaVersion;\n}>;\n\nexport type BuildRenderObservationInput = Readonly<{\n boundaryOutcome: BoundaryOutcome;\n cacheTags: readonly string[];\n cacheability: RenderCacheability;\n completeness: RenderObservationCompleteness;\n dynamicFetches: readonly string[];\n output: CacheProofOutputScope;\n pathTags: readonly string[];\n requestApis: readonly RenderRequestApiObservation[];\n}>;\n\nexport type DisabledCacheProofDecision = Readonly<{\n canReuse: false;\n fallback: CacheProofBreakerFallback;\n kind: \"disabled\";\n observation: RenderObservation;\n variant: CacheVariant;\n}>;\n\nexport type CreateDisabledCacheProofDecisionInput = Readonly<{\n observation: RenderObservation;\n variant: CacheVariant;\n}>;\n\nconst PUBLIC_UNSAFE_DIMENSION_SOURCES: ReadonlySet<CacheVariantDimensionSource> = new Set([\n \"auth\",\n \"cookie\",\n \"draft-mode\",\n \"header\",\n \"session\",\n]);\n\ntype CacheVariantDimensionAccumulator = {\n name: string;\n privacy: CacheVariantDimensionPrivacy;\n source: CacheVariantDimensionSource;\n values: string[];\n};\n\ntype DimensionAccumulatorByName = Map<string, CacheVariantDimensionAccumulator>;\ntype DimensionAccumulatorByPrivacy = Map<CacheVariantDimensionPrivacy, DimensionAccumulatorByName>;\ntype DimensionAccumulatorBySource = Map<CacheVariantDimensionSource, DimensionAccumulatorByPrivacy>;\n\nfunction buildBreakerFallback(\n code: CacheProofRejectionCode,\n fields: CacheProofTraceFields = {},\n mode: CacheProofBreakerFallbackMode = \"renderFresh\",\n scope: CacheProofFallbackScope = \"affectedOutput\",\n): CacheProofBreakerFallback {\n return {\n kind: \"breakerFallback\",\n code,\n mode,\n scope,\n fields,\n };\n}\n\nfunction sortedUnique(values: readonly string[]): string[] {\n return [...new Set(values)].sort();\n}\n\nfunction normalizeDimensionName(name: string): string {\n return name.trim().toLowerCase();\n}\n\nfunction redactValue(value: string): string {\n return `h:${fnv1a64(value)}`;\n}\n\nfunction sortedUniqueRedacted(values: readonly string[]): string[] {\n return sortedUnique(sortedUnique(values).map(redactValue));\n}\n\nfunction encodeParts(parts: readonly unknown[]): string {\n return JSON.stringify(parts);\n}\n\nfunction compareDimensions(a: CacheVariantDimension, b: CacheVariantDimension): number {\n return (\n a.source.localeCompare(b.source) ||\n a.name.localeCompare(b.name) ||\n a.privacy.localeCompare(b.privacy)\n );\n}\n\nfunction encodeNullable(value: string | null): string | null {\n return value;\n}\n\nfunction assertNever(value: never): never {\n throw new Error(`Unhandled cache proof variant: ${String(value)}`);\n}\n\nfunction encodeOutputScope(output: CacheProofOutputScope): string {\n switch (output.kind) {\n case \"app-html\":\n return encodeParts([\n output.kind,\n output.routeId,\n encodeNullable(output.rootBoundaryId),\n encodeNullable(output.renderEpoch),\n ]);\n case \"app-rsc\":\n return encodeParts([\n output.kind,\n output.routeId,\n encodeNullable(output.rootBoundaryId),\n encodeNullable(output.renderEpoch),\n encodeNullable(output.mountedSlotsFingerprint),\n ]);\n case \"layout\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.layoutId,\n encodeNullable(output.rootBoundaryId),\n ]);\n case \"page\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.pageId,\n encodeNullable(output.rootBoundaryId),\n ]);\n case \"route-handler\":\n return encodeParts([output.kind, output.routeId, output.routeHandlerId]);\n case \"slot\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.slotId,\n encodeNullable(output.rootBoundaryId),\n ]);\n case \"template\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.templateId,\n encodeNullable(output.rootBoundaryId),\n ]);\n default:\n return assertNever(output);\n }\n}\n\nfunction validateBudgetNumber(name: string, value: number): CacheProofBreakerFallback | null {\n if (Number.isInteger(value) && value >= 0) return null;\n return buildBreakerFallback(\"CP_INVALID_VARIANT_BUDGET\", {\n budgetField: name,\n });\n}\n\nfunction validateBudget(budget: CacheVariantBudget): CacheProofBreakerFallback | null {\n return (\n validateBudgetNumber(\"maxDimensionCount\", budget.maxDimensionCount) ??\n validateBudgetNumber(\"maxDimensionNameLength\", budget.maxDimensionNameLength) ??\n validateBudgetNumber(\"maxDimensionValueLength\", budget.maxDimensionValueLength) ??\n validateBudgetNumber(\"maxEncodedLength\", budget.maxEncodedLength) ??\n validateBudgetNumber(\"maxValuesPerDimension\", budget.maxValuesPerDimension) ??\n validateBudgetNumber(\"maxVariantsPerRoute\", budget.maxVariantsPerRoute)\n );\n}\n\nfunction buildDimension(\n input: CacheVariantDimensionInput,\n budget: CacheVariantBudget,\n): CacheVariantDimension | CacheProofBreakerFallback {\n const name = normalizeDimensionName(input.name);\n if (name.length === 0) {\n return buildBreakerFallback(\"CP_DIMENSION_NAME_MISSING\", {\n source: input.source,\n });\n }\n if (name.length > budget.maxDimensionNameLength) {\n return buildBreakerFallback(\"CP_DIMENSION_NAME_TOO_LONG\", {\n maxLength: budget.maxDimensionNameLength,\n nameHash: redactValue(name),\n source: input.source,\n });\n }\n if (input.privacy === \"public\" && PUBLIC_UNSAFE_DIMENSION_SOURCES.has(input.source)) {\n return buildBreakerFallback(\n \"CP_UNSAFE_PUBLIC_DIMENSION\",\n {\n name,\n source: input.source,\n },\n \"privateUncacheable\",\n );\n }\n\n const values = sortedUnique(input.values);\n if (values.length === 0) {\n return buildBreakerFallback(\"CP_DIMENSION_VALUES_MISSING\", {\n name,\n source: input.source,\n });\n }\n if (values.length > budget.maxValuesPerDimension) {\n return buildBreakerFallback(\"CP_DIMENSION_VALUE_COUNT_EXCEEDED\", {\n maxValues: budget.maxValuesPerDimension,\n name,\n source: input.source,\n valueCount: values.length,\n });\n }\n for (const value of values) {\n if (value.length > budget.maxDimensionValueLength) {\n return buildBreakerFallback(\"CP_DIMENSION_VALUE_TOO_LONG\", {\n maxLength: budget.maxDimensionValueLength,\n name,\n source: input.source,\n valueHash: redactValue(value),\n });\n }\n }\n\n const valueHashes = values.map(redactValue);\n const encoded = encodeParts([input.source, input.privacy, name, valueHashes]);\n\n return {\n encoded,\n name,\n privacy: input.privacy,\n source: input.source,\n valueCount: valueHashes.length,\n valueHashes,\n };\n}\n\nfunction isCacheProofBreakerFallback(\n value: CacheVariantDimension | CacheProofBreakerFallback,\n): value is CacheProofBreakerFallback {\n return \"code\" in value;\n}\n\nfunction getDimensionBucket(\n bySource: DimensionAccumulatorBySource,\n source: CacheVariantDimensionSource,\n privacy: CacheVariantDimensionPrivacy,\n): DimensionAccumulatorByName {\n const existingByPrivacy = bySource.get(source);\n const byPrivacy = existingByPrivacy ?? new Map();\n if (!existingByPrivacy) {\n bySource.set(source, byPrivacy);\n }\n\n const existingByName = byPrivacy.get(privacy);\n const byName = existingByName ?? new Map();\n if (!existingByName) {\n byPrivacy.set(privacy, byName);\n }\n\n return byName;\n}\n\nfunction mergeDimensionInputs(\n dimensions: readonly CacheVariantDimensionInput[],\n): CacheVariantDimensionInput[] {\n const bySource: DimensionAccumulatorBySource = new Map();\n const orderedDimensions: CacheVariantDimensionAccumulator[] = [];\n\n for (const dimension of dimensions) {\n const name = normalizeDimensionName(dimension.name);\n const bucket = getDimensionBucket(bySource, dimension.source, dimension.privacy);\n const existing = bucket.get(name);\n if (existing) {\n existing.values.push(...dimension.values);\n continue;\n }\n const accumulator = {\n name,\n privacy: dimension.privacy,\n source: dimension.source,\n values: [...dimension.values],\n };\n bucket.set(name, accumulator);\n orderedDimensions.push(accumulator);\n }\n\n return orderedDimensions;\n}\n\nexport function createAppRouteCacheProofGraphScope(\n route: AppRouteCacheProofGraphScopeInput,\n): AppRouteCacheProofGraphScope {\n return {\n routeId: route.ids.route,\n pageId: route.ids.page,\n routeHandlerId: route.ids.routeHandler,\n layoutIds: [...route.ids.layouts],\n templateIds: [...route.ids.templates],\n slotIds: sortedUnique(Object.values(route.ids.slots)),\n };\n}\n\nexport function buildCacheVariant(input: BuildCacheVariantInput): BuildCacheVariantResult {\n const budgetFallback = validateBudget(input.budget);\n if (budgetFallback) {\n return {\n kind: \"breakerFallback\",\n fallback: budgetFallback,\n };\n }\n if (input.existingVariantCount >= input.budget.maxVariantsPerRoute) {\n return {\n kind: \"breakerFallback\",\n fallback: buildBreakerFallback(\n \"CP_ROUTE_VARIANT_CEILING_EXCEEDED\",\n {\n existingVariantCount: input.existingVariantCount,\n maxVariantsPerRoute: input.budget.maxVariantsPerRoute,\n routeId: input.output.routeId,\n },\n \"privateUncacheable\",\n \"route\",\n ),\n };\n }\n const dimensionInputs = mergeDimensionInputs(input.dimensions);\n if (dimensionInputs.length > input.budget.maxDimensionCount) {\n return {\n kind: \"breakerFallback\",\n fallback: buildBreakerFallback(\"CP_DIMENSION_COUNT_EXCEEDED\", {\n dimensionCount: dimensionInputs.length,\n maxDimensionCount: input.budget.maxDimensionCount,\n routeId: input.output.routeId,\n }),\n };\n }\n\n const dimensions: CacheVariantDimension[] = [];\n for (const dimensionInput of dimensionInputs) {\n const dimension = buildDimension(dimensionInput, input.budget);\n if (isCacheProofBreakerFallback(dimension)) {\n return {\n kind: \"breakerFallback\",\n fallback: dimension,\n };\n }\n dimensions.push(dimension);\n }\n dimensions.sort(compareDimensions);\n\n const encoded = [\n `schema:${CACHE_PROOF_MODEL_SCHEMA_VERSION}`,\n encodeOutputScope(input.output),\n ...dimensions.map((dimension) => dimension.encoded),\n ].join(\"|\");\n\n if (encoded.length > input.budget.maxEncodedLength) {\n return {\n kind: \"breakerFallback\",\n fallback: buildBreakerFallback(\"CP_ENCODED_VARIANT_TOO_LONG\", {\n encodedHash: redactValue(encoded),\n encodedLength: encoded.length,\n maxEncodedLength: input.budget.maxEncodedLength,\n routeId: input.output.routeId,\n }),\n };\n }\n\n return {\n kind: \"variant\",\n variant: {\n schemaVersion: CACHE_PROOF_MODEL_SCHEMA_VERSION,\n cacheKey: `cp0:${fnv1a64(encoded)}`,\n output: input.output,\n dimensions,\n encodedLength: encoded.length,\n budget: { ...input.budget },\n },\n };\n}\n\nfunction boundaryOutcomesMatch(expected: BoundaryOutcome, candidate: BoundaryOutcome): boolean {\n switch (expected.kind) {\n case \"error\":\n return candidate.kind === \"error\" && (expected.digest ?? \"\") === (candidate.digest ?? \"\");\n case \"forbidden\":\n return candidate.kind === \"forbidden\";\n case \"globalError\":\n return (\n candidate.kind === \"globalError\" && (expected.digest ?? \"\") === (candidate.digest ?? \"\")\n );\n case \"notFound\":\n return candidate.kind === \"notFound\";\n case \"redirect\":\n return (\n candidate.kind === \"redirect\" &&\n expected.status === candidate.status &&\n expected.location === candidate.location\n );\n case \"success\":\n return candidate.kind === \"success\";\n case \"unauthorized\":\n return candidate.kind === \"unauthorized\";\n case \"unknown\":\n return false;\n default:\n return assertNever(expected);\n }\n}\n\nexport function buildBoundaryOutcomeCompatibility(input: {\n candidate: BoundaryOutcome;\n expected: BoundaryOutcome;\n}): BoundaryOutcomeCompatibility {\n if (input.expected.kind === \"unknown\" || input.candidate.kind === \"unknown\") {\n return {\n kind: \"incompatible\",\n expected: input.expected,\n candidate: input.candidate,\n fallback: buildBreakerFallback(\"CP_BOUNDARY_OUTCOME_UNKNOWN\", {\n candidateKind: input.candidate.kind,\n expectedKind: input.expected.kind,\n }),\n };\n }\n\n if (boundaryOutcomesMatch(input.expected, input.candidate)) {\n return {\n kind: \"compatible\",\n outcome: input.candidate,\n reason: \"CP_BOUNDARY_OUTCOME_MATCH\",\n };\n }\n\n return {\n kind: \"incompatible\",\n expected: input.expected,\n candidate: input.candidate,\n fallback: buildBreakerFallback(\"CP_BOUNDARY_OUTCOME_MISMATCH\", {\n candidateKind: input.candidate.kind,\n expectedKind: input.expected.kind,\n }),\n };\n}\n\nfunction requestApiStatusRank(status: RenderRequestApiStatus): number {\n switch (status) {\n case \"notObserved\":\n return 0;\n case \"unknown\":\n return 1;\n case \"observed\":\n return 2;\n default:\n return assertNever(status);\n }\n}\n\nfunction normalizeRequestApiObservations(\n observations: readonly RenderRequestApiObservation[],\n): RenderRequestApiObservation[] {\n const byKind = new Map<RenderRequestApiKind, RenderRequestApiStatus>();\n for (const observation of observations) {\n const current = byKind.get(observation.kind);\n if (\n current === undefined ||\n requestApiStatusRank(observation.status) > requestApiStatusRank(current)\n ) {\n byKind.set(observation.kind, observation.status);\n }\n }\n\n return [...byKind.entries()]\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([kind, status]) => ({ kind, status }));\n}\n\nexport function buildRenderObservation(input: BuildRenderObservationInput): RenderObservation {\n return {\n schemaVersion: CACHE_PROOF_MODEL_SCHEMA_VERSION,\n output: input.output,\n completeness: input.completeness,\n boundaryOutcome: input.boundaryOutcome,\n requestApis: normalizeRequestApiObservations(input.requestApis),\n dynamicFetches: sortedUniqueRedacted(input.dynamicFetches),\n cacheTags: sortedUnique(input.cacheTags),\n pathTags: sortedUnique(input.pathTags),\n cacheability: input.cacheability,\n };\n}\n\nexport function hasCompleteNegativeRequestApiProof(\n observation: RenderObservation,\n requiredApis: readonly RenderRequestApiKind[],\n): boolean {\n if (observation.completeness !== \"complete\") return false;\n\n const statuses = new Map<RenderRequestApiKind, RenderRequestApiStatus>();\n for (const requestApi of observation.requestApis) {\n statuses.set(requestApi.kind, requestApi.status);\n }\n\n for (const api of requiredApis) {\n if (statuses.get(api) !== \"notObserved\") return false;\n }\n return true;\n}\n\nexport function createDisabledCacheProofDecision(\n input: CreateDisabledCacheProofDecisionInput,\n): DisabledCacheProofDecision {\n return {\n kind: \"disabled\",\n canReuse: false,\n variant: input.variant,\n observation: input.observation,\n fallback: buildBreakerFallback(\"CP_MODEL_DISABLED\"),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cache-proof.js","names":[],"sources":["../../src/server/cache-proof.ts"],"sourcesContent":["import type { AppRouteSemanticIds } from \"../routing/app-route-graph.js\";\nimport { fnv1a64 } from \"../utils/hash.js\";\nimport { findSortedStringPosition } from \"../utils/sorted-array.js\";\n\nexport const CACHE_PROOF_MODEL_SCHEMA_VERSION = 1;\nexport type CacheProofModelSchemaVersion = 1;\n\nexport type CacheProofRejectionCode =\n | \"CP_MODEL_DISABLED\"\n | \"CP_DIMENSION_COUNT_EXCEEDED\"\n | \"CP_DIMENSION_NAME_MISSING\"\n | \"CP_DIMENSION_NAME_TOO_LONG\"\n | \"CP_DIMENSION_VALUE_COUNT_EXCEEDED\"\n | \"CP_DIMENSION_VALUE_TOO_LONG\"\n | \"CP_DIMENSION_VALUES_MISSING\"\n | \"CP_ENCODED_VARIANT_TOO_LONG\"\n | \"CP_INVALID_VARIANT_BUDGET\"\n | \"CP_ROUTE_VARIANT_BUDGET_ROUTE_MISMATCH\"\n | \"CP_ROUTE_VARIANT_CEILING_EXCEEDED\"\n | \"CP_UNSAFE_PUBLIC_DIMENSION\"\n | \"CP_BOUNDARY_OUTCOME_MISMATCH\"\n | \"CP_BOUNDARY_OUTCOME_UNKNOWN\"\n | \"CP_PRIVATE_DYNAMIC_DOWNGRADE\"\n | \"CP_STATIC_LAYOUT_CANDIDATE_OUTPUT_KIND\"\n | \"CP_STATIC_LAYOUT_CURRENT_OUTPUT_KIND\"\n | \"CP_STATIC_LAYOUT_ID_MISMATCH\"\n | \"CP_STATIC_LAYOUT_OBSERVATION_OUTPUT_KIND\"\n | \"CP_STATIC_LAYOUT_OBSERVATION_OUTPUT_MISMATCH\"\n | \"CP_STATIC_LAYOUT_PRIVATE_DYNAMIC_DOWNGRADE\"\n | \"CP_STATIC_LAYOUT_PRIVATE_VARIANT_DIMENSION\"\n | \"CP_STATIC_LAYOUT_REQUEST_API_OBSERVED\"\n | \"CP_STATIC_LAYOUT_REQUEST_API_UNKNOWN\"\n | \"CP_STATIC_LAYOUT_ROOT_BOUNDARY_MISMATCH\"\n | \"CP_STATIC_LAYOUT_ROOT_BOUNDARY_UNKNOWN\";\n\nexport type CacheProofAcceptanceCode = \"CP_STATIC_LAYOUT_REUSE_PROVEN\";\n\nexport type CacheProofTraceCode = CacheProofAcceptanceCode | CacheProofRejectionCode;\n\nexport type CacheProofTraceFieldValue = string | number | boolean | null | readonly string[];\n\nexport type CacheProofTraceFields = Readonly<Record<string, CacheProofTraceFieldValue>>;\n\nexport type CacheProofBreakerFallbackMode = \"renderFresh\" | \"privateUncacheable\";\nexport type CacheProofFallbackScope = \"affectedOutput\" | \"route\";\n\nexport type CacheProofBreakerFallback = Readonly<{\n kind: \"breakerFallback\";\n code: CacheProofRejectionCode;\n mode: CacheProofBreakerFallbackMode;\n scope: CacheProofFallbackScope;\n fields: CacheProofTraceFields;\n}>;\n\nexport type CacheVariantBudget = Readonly<{\n maxDimensionCount: number;\n maxDimensionNameLength: number;\n maxDimensionValueLength: number;\n maxEncodedLength: number;\n maxValuesPerDimension: number;\n maxVariantsPerRoute: number;\n}>;\n\nexport const DEFAULT_CACHE_VARIANT_BUDGET = {\n maxDimensionCount: 8,\n maxDimensionNameLength: 64,\n maxDimensionValueLength: 256,\n maxEncodedLength: 1024,\n maxValuesPerDimension: 8,\n maxVariantsPerRoute: 64,\n} satisfies CacheVariantBudget;\n\nexport type CacheVariantDimensionSource =\n | \"auth\"\n | \"cookie\"\n | \"custom\"\n | \"draft-mode\"\n | \"header\"\n | \"interception\"\n | \"mounted-slots\"\n | \"params\"\n | \"route\"\n | \"search\"\n | \"session\";\n\nexport type CacheVariantDimensionPrivacy = \"internal\" | \"private\" | \"public\";\n\nexport type CacheVariantDimensionInput = Readonly<{\n name: string;\n privacy: CacheVariantDimensionPrivacy;\n source: CacheVariantDimensionSource;\n values: readonly string[];\n}>;\n\nexport type CacheVariantDimension = Readonly<{\n encoded: string;\n name: string;\n privacy: CacheVariantDimensionPrivacy;\n source: CacheVariantDimensionSource;\n valueCount: number;\n valueHashes: readonly string[];\n}>;\n\nexport type CacheProofOutputScope =\n | Readonly<{\n kind: \"app-html\";\n renderEpoch: string | null;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"app-rsc\";\n mountedSlotsFingerprint: string | null;\n renderEpoch: string | null;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"layout\";\n layoutId: string;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"page\";\n pageId: string;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"route-handler\";\n routeHandlerId: string;\n routeId: string;\n }>\n | Readonly<{\n kind: \"slot\";\n rootBoundaryId: string | null;\n routeId: string;\n slotId: string;\n }>\n | Readonly<{\n kind: \"template\";\n rootBoundaryId: string | null;\n routeId: string;\n templateId: string;\n }>;\n\nexport type StaticLayoutCacheProofOutputScope = Extract<CacheProofOutputScope, { kind: \"layout\" }>;\n\nexport type CacheVariant = Readonly<{\n budget: CacheVariantBudget;\n cacheKey: string;\n dimensions: readonly CacheVariantDimension[];\n encodedLength: number;\n output: CacheProofOutputScope;\n schemaVersion: CacheProofModelSchemaVersion;\n}>;\n\nexport type BuildCacheVariantInput = Readonly<{\n budget: CacheVariantBudget;\n dimensions: readonly CacheVariantDimensionInput[];\n output: CacheProofOutputScope;\n}>;\n\nexport type BuildCacheVariantResult =\n | Readonly<{ kind: \"variant\"; variant: CacheVariant }>\n | Readonly<{ kind: \"breakerFallback\"; fallback: CacheProofBreakerFallback }>;\n\nexport type CacheVariantRouteBudget = Readonly<{\n routeId: string;\n variantCacheKeys: readonly string[];\n}>;\n\nexport type CacheVariantRouteBudgetAdmission =\n | Readonly<{\n didConsumeRouteVariantBudget: boolean;\n kind: \"variant\";\n routeBudget: CacheVariantRouteBudget;\n variant: CacheVariant;\n }>\n | Readonly<{\n fallback: CacheProofBreakerFallback;\n kind: \"breakerFallback\";\n routeBudget: CacheVariantRouteBudget | null;\n }>;\n\nexport type BuildCacheVariantWithRouteBudgetInput = BuildCacheVariantInput &\n Readonly<{\n routeBudget: CacheVariantRouteBudget | null;\n }>;\n\nexport type BuildCacheVariantWithRouteBudgetResult = CacheVariantRouteBudgetAdmission;\n\nexport type AppRouteCacheProofGraphScopeInput = Readonly<{\n ids: AppRouteSemanticIds;\n}>;\n\nexport type AppRouteCacheProofGraphScope = Readonly<{\n layoutIds: readonly string[];\n pageId: string | null;\n routeHandlerId: string | null;\n routeId: string;\n slotIds: readonly string[];\n templateIds: readonly string[];\n}>;\n\nexport type BoundaryOutcome =\n | Readonly<{ kind: \"error\"; digest?: string }>\n | Readonly<{ kind: \"forbidden\" }>\n | Readonly<{ kind: \"globalError\"; digest?: string }>\n | Readonly<{ kind: \"notFound\" }>\n | Readonly<{ kind: \"redirect\"; location: string; status: number }>\n | Readonly<{ kind: \"success\" }>\n | Readonly<{ kind: \"unauthorized\" }>\n | Readonly<{ kind: \"unknown\" }>;\n\nexport type BoundaryOutcomeCompatibility =\n | Readonly<{\n kind: \"compatible\";\n outcome: BoundaryOutcome;\n reason: \"CP_BOUNDARY_OUTCOME_MATCH\";\n }>\n | Readonly<{\n candidate: BoundaryOutcome;\n expected: BoundaryOutcome;\n fallback: CacheProofBreakerFallback;\n kind: \"incompatible\";\n }>;\n\nexport type RenderObservationCompleteness = \"complete\" | \"partial\" | \"unknown\";\nexport type RenderCacheability = \"private\" | \"public\" | \"uncacheable\" | \"unknown\";\nexport type RenderRequestApiKind =\n | \"connection\"\n | \"cookies\"\n | \"draftMode\"\n | \"headers\"\n | \"params\"\n | \"searchParams\";\nexport type RenderRequestApiStatus = \"notObserved\" | \"observed\" | \"unknown\";\n\nexport const ALL_RENDER_REQUEST_API_KINDS: readonly RenderRequestApiKind[] = [\n \"connection\",\n \"cookies\",\n \"draftMode\",\n \"headers\",\n \"params\",\n \"searchParams\",\n];\n\nexport type RenderRequestApiObservation = Readonly<{\n kind: RenderRequestApiKind;\n status: RenderRequestApiStatus;\n}>;\n\nexport type CacheProofDowngradeTarget =\n | \"freshRender\"\n | \"private\"\n | \"privateUncacheable\"\n | \"public\"\n | \"publicVariant\";\n\nexport type CacheProofDowngradeReason =\n | Readonly<{\n code: \"CP_DOWNGRADE_CACHEABILITY_PRIVATE\";\n target: \"private\";\n }>\n | Readonly<{\n code: \"CP_DOWNGRADE_CACHEABILITY_UNCACHEABLE\";\n target: \"privateUncacheable\";\n }>\n | Readonly<{\n code: \"CP_DOWNGRADE_CACHEABILITY_UNKNOWN\";\n target: \"freshRender\";\n }>\n | Readonly<{\n code: \"CP_DOWNGRADE_DYNAMIC_FETCH\";\n dynamicFetchCount: number;\n target: \"freshRender\";\n }>\n | Readonly<{\n code: \"CP_DOWNGRADE_DYNAMIC_REQUEST_API\";\n requestApi: \"connection\";\n target: \"freshRender\";\n }>\n | Readonly<{\n code: \"CP_DOWNGRADE_DRAFT_MODE\";\n requestApi: \"draftMode\";\n target: \"privateUncacheable\";\n }>\n | Readonly<{\n code: \"CP_DOWNGRADE_INCOMPLETE_OBSERVATION\";\n completeness: Exclude<RenderObservationCompleteness, \"complete\">;\n target: \"freshRender\";\n }>\n | Readonly<{\n code: \"CP_DOWNGRADE_PRIVATE_DIMENSION\";\n inputClass: \"auth\" | \"draft\" | \"private\" | \"session\";\n source: \"auth\" | \"cookie\" | \"draft-mode\" | \"header\" | \"session\";\n target: \"private\" | \"privateUncacheable\";\n }>\n | Readonly<{\n code: \"CP_DOWNGRADE_PRIVATE_REQUEST_API\";\n requestApi: \"cookies\" | \"headers\";\n target: \"private\";\n }>\n | Readonly<{\n code: \"CP_DOWNGRADE_PUBLIC_REQUEST_API\";\n requestApi: \"params\" | \"searchParams\";\n target: \"publicVariant\";\n }>\n | Readonly<{\n code: \"CP_DOWNGRADE_UNKNOWN_REQUEST_API\";\n requestApi: RenderRequestApiKind;\n target: \"freshRender\";\n }>;\n\nexport type CacheProofDowngradeClassification = Readonly<{\n fallback: CacheProofBreakerFallback | null;\n isPublicCacheCandidate: boolean;\n reasons: readonly CacheProofDowngradeReason[];\n target: CacheProofDowngradeTarget;\n}>;\n\nexport type ClassifyRenderObservationDowngradeInput = Readonly<{\n cacheability: RenderCacheability;\n completeness: RenderObservationCompleteness;\n dynamicFetches: readonly string[];\n requestApis: readonly RenderRequestApiObservation[];\n}>;\n\nexport type ClassifyCacheVariantDimensionDowngradeInput = Pick<\n CacheVariantDimensionInput,\n \"source\"\n>;\n\nexport type RenderObservation = Readonly<{\n boundaryOutcome: BoundaryOutcome;\n cacheTags: readonly string[];\n cacheability: RenderCacheability;\n completeness: RenderObservationCompleteness;\n downgrade: CacheProofDowngradeClassification;\n dynamicFetches: readonly string[];\n output: CacheProofOutputScope;\n pathTags: readonly string[];\n requestApis: readonly RenderRequestApiObservation[];\n schemaVersion: CacheProofModelSchemaVersion;\n}>;\n\nexport type StaticLayoutReuseProof = Readonly<{\n authorizesRuntimeReuse: false;\n candidateOutput: StaticLayoutCacheProofOutputScope;\n code: \"CP_STATIC_LAYOUT_REUSE_PROVEN\";\n currentOutput: StaticLayoutCacheProofOutputScope;\n fields: CacheProofTraceFields;\n observation: RenderObservation;\n requiredNegativeRequestApis: readonly RenderRequestApiKind[];\n reuseClass: \"static-layout\";\n variant: CacheVariant;\n}>;\n\nexport type BuildStaticLayoutReuseProofInput = Readonly<{\n candidateObservation: RenderObservation;\n candidateVariant: CacheVariant;\n currentOutput: CacheProofOutputScope;\n}>;\n\nexport type BuildStaticLayoutReuseProofResult =\n | Readonly<{ kind: \"proof\"; proof: StaticLayoutReuseProof }>\n | Readonly<{ kind: \"rejected\"; fallback: CacheProofBreakerFallback }>;\n\nexport type BuildRenderObservationInput = Readonly<{\n boundaryOutcome: BoundaryOutcome;\n cacheTags: readonly string[];\n cacheability: RenderCacheability;\n completeness: RenderObservationCompleteness;\n dynamicFetches: readonly string[];\n output: CacheProofOutputScope;\n pathTags: readonly string[];\n requestApis: readonly RenderRequestApiObservation[];\n}>;\n\nexport type BuildRenderRequestApiObservationsInput = Readonly<{\n completeness: RenderObservationCompleteness;\n observed: readonly RenderRequestApiKind[];\n}>;\n\nexport type DisabledCacheProofDecision = Readonly<{\n canReuse: false;\n fallback: CacheProofBreakerFallback;\n kind: \"disabled\";\n observation: RenderObservation;\n staticLayoutProof?: StaticLayoutReuseProof;\n variant: CacheVariant;\n}>;\n\nexport type CreateDisabledCacheProofDecisionInput = Readonly<{\n observation: RenderObservation;\n staticLayoutProof?: StaticLayoutReuseProof;\n variant: CacheVariant;\n}>;\n\nconst PUBLIC_UNSAFE_DIMENSION_SOURCES: ReadonlySet<CacheVariantDimensionSource> = new Set([\n \"auth\",\n \"cookie\",\n \"draft-mode\",\n \"header\",\n \"session\",\n]);\n\ntype CacheVariantDimensionAccumulator = {\n name: string;\n privacy: CacheVariantDimensionPrivacy;\n source: CacheVariantDimensionSource;\n values: string[];\n};\n\ntype DimensionAccumulatorByName = Map<string, CacheVariantDimensionAccumulator>;\ntype DimensionAccumulatorByPrivacy = Map<CacheVariantDimensionPrivacy, DimensionAccumulatorByName>;\ntype DimensionAccumulatorBySource = Map<CacheVariantDimensionSource, DimensionAccumulatorByPrivacy>;\n\nfunction buildBreakerFallback(\n code: CacheProofRejectionCode,\n fields: CacheProofTraceFields = {},\n mode: CacheProofBreakerFallbackMode = \"renderFresh\",\n scope: CacheProofFallbackScope = \"affectedOutput\",\n): CacheProofBreakerFallback {\n return {\n kind: \"breakerFallback\",\n code,\n mode,\n scope,\n fields,\n };\n}\n\nfunction sortedUnique(values: readonly string[]): string[] {\n return [...new Set(values)].sort();\n}\n\nfunction normalizeDimensionName(name: string): string {\n return name.trim().toLowerCase();\n}\n\nfunction redactValue(value: string): string {\n return `h:${fnv1a64(value)}`;\n}\n\nfunction sortedUniqueRedacted(values: readonly string[]): string[] {\n return sortedUnique(sortedUnique(values).map(redactValue));\n}\n\nfunction encodeParts(parts: readonly unknown[]): string {\n return JSON.stringify(parts);\n}\n\nfunction compareDimensions(a: CacheVariantDimension, b: CacheVariantDimension): number {\n return (\n a.source.localeCompare(b.source) ||\n a.name.localeCompare(b.name) ||\n a.privacy.localeCompare(b.privacy)\n );\n}\n\nfunction encodeNullable(value: string | null): string | null {\n return value;\n}\n\nfunction assertNever(value: never): never {\n throw new Error(`Unhandled cache proof variant: ${String(value)}`);\n}\n\nfunction encodeOutputScope(output: CacheProofOutputScope): string {\n switch (output.kind) {\n case \"app-html\":\n return encodeParts([\n output.kind,\n output.routeId,\n encodeNullable(output.rootBoundaryId),\n encodeNullable(output.renderEpoch),\n ]);\n case \"app-rsc\":\n return encodeParts([\n output.kind,\n output.routeId,\n encodeNullable(output.rootBoundaryId),\n encodeNullable(output.renderEpoch),\n encodeNullable(output.mountedSlotsFingerprint),\n ]);\n case \"layout\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.layoutId,\n encodeNullable(output.rootBoundaryId),\n ]);\n case \"page\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.pageId,\n encodeNullable(output.rootBoundaryId),\n ]);\n case \"route-handler\":\n return encodeParts([output.kind, output.routeId, output.routeHandlerId]);\n case \"slot\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.slotId,\n encodeNullable(output.rootBoundaryId),\n ]);\n case \"template\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.templateId,\n encodeNullable(output.rootBoundaryId),\n ]);\n default:\n return assertNever(output);\n }\n}\n\nfunction validateBudgetNumber(name: string, value: number): CacheProofBreakerFallback | null {\n if (Number.isInteger(value) && value >= 0) return null;\n return buildBreakerFallback(\"CP_INVALID_VARIANT_BUDGET\", {\n budgetField: name,\n });\n}\n\nfunction validateBudget(budget: CacheVariantBudget): CacheProofBreakerFallback | null {\n return (\n validateBudgetNumber(\"maxDimensionCount\", budget.maxDimensionCount) ??\n validateBudgetNumber(\"maxDimensionNameLength\", budget.maxDimensionNameLength) ??\n validateBudgetNumber(\"maxDimensionValueLength\", budget.maxDimensionValueLength) ??\n validateBudgetNumber(\"maxEncodedLength\", budget.maxEncodedLength) ??\n validateBudgetNumber(\"maxValuesPerDimension\", budget.maxValuesPerDimension) ??\n validateBudgetNumber(\"maxVariantsPerRoute\", budget.maxVariantsPerRoute)\n );\n}\n\nfunction buildDimension(\n input: CacheVariantDimensionInput,\n budget: CacheVariantBudget,\n): CacheVariantDimension | CacheProofBreakerFallback {\n const name = normalizeDimensionName(input.name);\n if (name.length === 0) {\n return buildBreakerFallback(\"CP_DIMENSION_NAME_MISSING\", {\n source: input.source,\n });\n }\n if (name.length > budget.maxDimensionNameLength) {\n return buildBreakerFallback(\"CP_DIMENSION_NAME_TOO_LONG\", {\n maxLength: budget.maxDimensionNameLength,\n nameHash: redactValue(name),\n source: input.source,\n });\n }\n if (input.privacy === \"public\" && PUBLIC_UNSAFE_DIMENSION_SOURCES.has(input.source)) {\n return buildBreakerFallback(\n \"CP_UNSAFE_PUBLIC_DIMENSION\",\n {\n name,\n source: input.source,\n },\n \"privateUncacheable\",\n );\n }\n\n const values = sortedUnique(input.values);\n if (values.length === 0) {\n return buildBreakerFallback(\"CP_DIMENSION_VALUES_MISSING\", {\n name,\n source: input.source,\n });\n }\n if (values.length > budget.maxValuesPerDimension) {\n return buildBreakerFallback(\"CP_DIMENSION_VALUE_COUNT_EXCEEDED\", {\n maxValues: budget.maxValuesPerDimension,\n name,\n source: input.source,\n valueCount: values.length,\n });\n }\n for (const value of values) {\n if (value.length > budget.maxDimensionValueLength) {\n return buildBreakerFallback(\"CP_DIMENSION_VALUE_TOO_LONG\", {\n maxLength: budget.maxDimensionValueLength,\n name,\n source: input.source,\n valueHash: redactValue(value),\n });\n }\n }\n\n const valueHashes = values.map(redactValue);\n const encoded = encodeParts([input.source, input.privacy, name, valueHashes]);\n\n return {\n encoded,\n name,\n privacy: input.privacy,\n source: input.source,\n valueCount: valueHashes.length,\n valueHashes,\n };\n}\n\nfunction isCacheProofBreakerFallback(\n value: CacheVariantDimension | CacheProofBreakerFallback,\n): value is CacheProofBreakerFallback {\n return \"code\" in value;\n}\n\nfunction getDimensionBucket(\n bySource: DimensionAccumulatorBySource,\n source: CacheVariantDimensionSource,\n privacy: CacheVariantDimensionPrivacy,\n): DimensionAccumulatorByName {\n const existingByPrivacy = bySource.get(source);\n const byPrivacy = existingByPrivacy ?? new Map();\n if (!existingByPrivacy) {\n bySource.set(source, byPrivacy);\n }\n\n const existingByName = byPrivacy.get(privacy);\n const byName = existingByName ?? new Map();\n if (!existingByName) {\n byPrivacy.set(privacy, byName);\n }\n\n return byName;\n}\n\nfunction mergeDimensionInputs(\n dimensions: readonly CacheVariantDimensionInput[],\n): CacheVariantDimensionInput[] {\n const bySource: DimensionAccumulatorBySource = new Map();\n const orderedDimensions: CacheVariantDimensionAccumulator[] = [];\n\n for (const dimension of dimensions) {\n const name = normalizeDimensionName(dimension.name);\n const bucket = getDimensionBucket(bySource, dimension.source, dimension.privacy);\n const existing = bucket.get(name);\n if (existing) {\n existing.values.push(...dimension.values);\n continue;\n }\n const accumulator = {\n name,\n privacy: dimension.privacy,\n source: dimension.source,\n values: [...dimension.values],\n };\n bucket.set(name, accumulator);\n orderedDimensions.push(accumulator);\n }\n\n return orderedDimensions;\n}\n\nexport function createAppRouteCacheProofGraphScope(\n route: AppRouteCacheProofGraphScopeInput,\n): AppRouteCacheProofGraphScope {\n return {\n routeId: route.ids.route,\n pageId: route.ids.page,\n routeHandlerId: route.ids.routeHandler,\n layoutIds: [...route.ids.layouts],\n templateIds: [...route.ids.templates],\n slotIds: sortedUnique(Object.values(route.ids.slots)),\n };\n}\n\nexport function buildCacheVariant(input: BuildCacheVariantInput): BuildCacheVariantResult {\n const budgetFallback = validateBudget(input.budget);\n if (budgetFallback) {\n return {\n kind: \"breakerFallback\",\n fallback: budgetFallback,\n };\n }\n const dimensionInputs = mergeDimensionInputs(input.dimensions);\n if (dimensionInputs.length > input.budget.maxDimensionCount) {\n return {\n kind: \"breakerFallback\",\n fallback: buildBreakerFallback(\"CP_DIMENSION_COUNT_EXCEEDED\", {\n dimensionCount: dimensionInputs.length,\n maxDimensionCount: input.budget.maxDimensionCount,\n routeId: input.output.routeId,\n }),\n };\n }\n\n const dimensions: CacheVariantDimension[] = [];\n for (const dimensionInput of dimensionInputs) {\n const dimension = buildDimension(dimensionInput, input.budget);\n if (isCacheProofBreakerFallback(dimension)) {\n return {\n kind: \"breakerFallback\",\n fallback: dimension,\n };\n }\n dimensions.push(dimension);\n }\n dimensions.sort(compareDimensions);\n\n const encoded = [\n `schema:${CACHE_PROOF_MODEL_SCHEMA_VERSION}`,\n encodeOutputScope(input.output),\n ...dimensions.map((dimension) => dimension.encoded),\n ].join(\"|\");\n\n if (encoded.length > input.budget.maxEncodedLength) {\n return {\n kind: \"breakerFallback\",\n fallback: buildBreakerFallback(\"CP_ENCODED_VARIANT_TOO_LONG\", {\n encodedHash: redactValue(encoded),\n encodedLength: encoded.length,\n maxEncodedLength: input.budget.maxEncodedLength,\n routeId: input.output.routeId,\n }),\n };\n }\n\n return {\n kind: \"variant\",\n variant: {\n schemaVersion: CACHE_PROOF_MODEL_SCHEMA_VERSION,\n cacheKey: `cp${CACHE_PROOF_MODEL_SCHEMA_VERSION}:${fnv1a64(encoded)}`,\n output: input.output,\n dimensions,\n encodedLength: encoded.length,\n budget: { ...input.budget },\n },\n };\n}\n\nfunction normalizeRouteBudget(input: CacheVariantRouteBudget): CacheVariantRouteBudget {\n return {\n routeId: input.routeId,\n variantCacheKeys: sortedUnique(input.variantCacheKeys),\n };\n}\n\nfunction buildRouteVariantCeilingFallback(\n variant: CacheVariant,\n existingVariantCount: number,\n): CacheProofBreakerFallback {\n return buildBreakerFallback(\n \"CP_ROUTE_VARIANT_CEILING_EXCEEDED\",\n {\n existingVariantCount,\n maxVariantsPerRoute: variant.budget.maxVariantsPerRoute,\n routeId: variant.output.routeId,\n },\n \"privateUncacheable\",\n \"route\",\n );\n}\n\nexport function enforceCacheVariantRouteBudget(input: {\n routeBudget: CacheVariantRouteBudget | null;\n variant: CacheVariant;\n}): CacheVariantRouteBudgetAdmission {\n if (input.routeBudget && input.routeBudget.routeId !== input.variant.output.routeId) {\n return {\n kind: \"breakerFallback\",\n routeBudget: normalizeRouteBudget(input.routeBudget),\n fallback: buildBreakerFallback(\n \"CP_ROUTE_VARIANT_BUDGET_ROUTE_MISMATCH\",\n {\n budgetRouteId: input.routeBudget.routeId,\n routeId: input.variant.output.routeId,\n },\n \"privateUncacheable\",\n \"route\",\n ),\n };\n }\n\n const routeBudget = normalizeRouteBudget(\n input.routeBudget ?? {\n routeId: input.variant.output.routeId,\n variantCacheKeys: [],\n },\n );\n const existingVariantCount = routeBudget.variantCacheKeys.length;\n const variantKeyPosition = findSortedStringPosition(\n routeBudget.variantCacheKeys,\n input.variant.cacheKey,\n );\n\n if (existingVariantCount > input.variant.budget.maxVariantsPerRoute) {\n return {\n kind: \"breakerFallback\",\n routeBudget,\n fallback: buildRouteVariantCeilingFallback(input.variant, existingVariantCount),\n };\n }\n\n if (variantKeyPosition.found) {\n return {\n kind: \"variant\",\n variant: input.variant,\n routeBudget,\n didConsumeRouteVariantBudget: false,\n };\n }\n\n if (existingVariantCount >= input.variant.budget.maxVariantsPerRoute) {\n return {\n kind: \"breakerFallback\",\n routeBudget,\n fallback: buildRouteVariantCeilingFallback(input.variant, existingVariantCount),\n };\n }\n\n return {\n kind: \"variant\",\n variant: input.variant,\n routeBudget: {\n routeId: routeBudget.routeId,\n variantCacheKeys: [\n ...routeBudget.variantCacheKeys.slice(0, variantKeyPosition.index),\n input.variant.cacheKey,\n ...routeBudget.variantCacheKeys.slice(variantKeyPosition.index),\n ],\n },\n didConsumeRouteVariantBudget: true,\n };\n}\n\nexport function buildCacheVariantWithRouteBudget(\n input: BuildCacheVariantWithRouteBudgetInput,\n): BuildCacheVariantWithRouteBudgetResult {\n const variantResult = buildCacheVariant({\n budget: input.budget,\n dimensions: input.dimensions,\n output: input.output,\n });\n\n if (variantResult.kind === \"breakerFallback\") {\n return {\n kind: \"breakerFallback\",\n routeBudget: input.routeBudget ? normalizeRouteBudget(input.routeBudget) : null,\n fallback: variantResult.fallback,\n };\n }\n\n return enforceCacheVariantRouteBudget({\n routeBudget: input.routeBudget,\n variant: variantResult.variant,\n });\n}\n\nfunction boundaryOutcomesMatch(expected: BoundaryOutcome, candidate: BoundaryOutcome): boolean {\n switch (expected.kind) {\n case \"error\":\n return candidate.kind === \"error\" && (expected.digest ?? \"\") === (candidate.digest ?? \"\");\n case \"forbidden\":\n return candidate.kind === \"forbidden\";\n case \"globalError\":\n return (\n candidate.kind === \"globalError\" && (expected.digest ?? \"\") === (candidate.digest ?? \"\")\n );\n case \"notFound\":\n return candidate.kind === \"notFound\";\n case \"redirect\":\n return (\n candidate.kind === \"redirect\" &&\n expected.status === candidate.status &&\n expected.location === candidate.location\n );\n case \"success\":\n return candidate.kind === \"success\";\n case \"unauthorized\":\n return candidate.kind === \"unauthorized\";\n case \"unknown\":\n return false;\n default:\n return assertNever(expected);\n }\n}\n\nexport function buildBoundaryOutcomeCompatibility(input: {\n candidate: BoundaryOutcome;\n expected: BoundaryOutcome;\n}): BoundaryOutcomeCompatibility {\n if (input.expected.kind === \"unknown\" || input.candidate.kind === \"unknown\") {\n return {\n kind: \"incompatible\",\n expected: input.expected,\n candidate: input.candidate,\n fallback: buildBreakerFallback(\"CP_BOUNDARY_OUTCOME_UNKNOWN\", {\n candidateKind: input.candidate.kind,\n expectedKind: input.expected.kind,\n }),\n };\n }\n\n if (boundaryOutcomesMatch(input.expected, input.candidate)) {\n return {\n kind: \"compatible\",\n outcome: input.candidate,\n reason: \"CP_BOUNDARY_OUTCOME_MATCH\",\n };\n }\n\n return {\n kind: \"incompatible\",\n expected: input.expected,\n candidate: input.candidate,\n fallback: buildBreakerFallback(\"CP_BOUNDARY_OUTCOME_MISMATCH\", {\n candidateKind: input.candidate.kind,\n expectedKind: input.expected.kind,\n }),\n };\n}\n\nfunction requestApiStatusRank(status: RenderRequestApiStatus): number {\n switch (status) {\n case \"notObserved\":\n return 0;\n case \"unknown\":\n return 1;\n case \"observed\":\n return 2;\n default:\n return assertNever(status);\n }\n}\n\nfunction normalizeRequestApiObservations(\n observations: readonly RenderRequestApiObservation[],\n): RenderRequestApiObservation[] {\n const byKind = new Map<RenderRequestApiKind, RenderRequestApiStatus>();\n for (const observation of observations) {\n const current = byKind.get(observation.kind);\n if (\n current === undefined ||\n requestApiStatusRank(observation.status) > requestApiStatusRank(current)\n ) {\n byKind.set(observation.kind, observation.status);\n }\n }\n\n return [...byKind.entries()]\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([kind, status]) => ({ kind, status }));\n}\n\nfunction cacheProofDowngradeTargetRank(target: CacheProofDowngradeTarget): number {\n switch (target) {\n case \"public\":\n return 0;\n case \"publicVariant\":\n return 1;\n case \"private\":\n return 2;\n case \"privateUncacheable\":\n return 3;\n case \"freshRender\":\n return 4;\n default:\n return assertNever(target);\n }\n}\n\nfunction maxCacheProofDowngradeTarget(\n current: CacheProofDowngradeTarget,\n candidate: CacheProofDowngradeTarget,\n): CacheProofDowngradeTarget {\n return cacheProofDowngradeTargetRank(candidate) > cacheProofDowngradeTargetRank(current)\n ? candidate\n : current;\n}\n\nfunction createDowngradeFallback(\n target: CacheProofDowngradeTarget,\n reasons: readonly CacheProofDowngradeReason[],\n): CacheProofBreakerFallback | null {\n switch (target) {\n case \"public\":\n case \"publicVariant\":\n case \"private\":\n return null;\n case \"privateUncacheable\":\n return buildBreakerFallback(\n \"CP_PRIVATE_DYNAMIC_DOWNGRADE\",\n {\n reasonCodes: reasons.map((reason) => reason.code),\n target,\n },\n \"privateUncacheable\",\n );\n case \"freshRender\":\n return buildBreakerFallback(\"CP_PRIVATE_DYNAMIC_DOWNGRADE\", {\n reasonCodes: reasons.map((reason) => reason.code),\n target,\n });\n default:\n return assertNever(target);\n }\n}\n\nfunction classifyObservedRequestApiDowngrade(\n kind: RenderRequestApiKind,\n): CacheProofDowngradeReason {\n switch (kind) {\n case \"connection\":\n return {\n code: \"CP_DOWNGRADE_DYNAMIC_REQUEST_API\",\n requestApi: \"connection\",\n target: \"freshRender\",\n };\n case \"cookies\":\n return {\n code: \"CP_DOWNGRADE_PRIVATE_REQUEST_API\",\n requestApi: \"cookies\",\n target: \"private\",\n };\n case \"draftMode\":\n return {\n code: \"CP_DOWNGRADE_DRAFT_MODE\",\n requestApi: \"draftMode\",\n target: \"privateUncacheable\",\n };\n case \"headers\":\n return {\n code: \"CP_DOWNGRADE_PRIVATE_REQUEST_API\",\n requestApi: \"headers\",\n target: \"private\",\n };\n case \"params\":\n return {\n code: \"CP_DOWNGRADE_PUBLIC_REQUEST_API\",\n requestApi: \"params\",\n target: \"publicVariant\",\n };\n case \"searchParams\":\n return {\n code: \"CP_DOWNGRADE_PUBLIC_REQUEST_API\",\n requestApi: \"searchParams\",\n target: \"publicVariant\",\n };\n default:\n return assertNever(kind);\n }\n}\n\nexport function classifyCacheVariantDimensionDowngrade(\n input: ClassifyCacheVariantDimensionDowngradeInput,\n): CacheProofDowngradeReason | null {\n switch (input.source) {\n case \"auth\":\n return {\n code: \"CP_DOWNGRADE_PRIVATE_DIMENSION\",\n inputClass: \"auth\",\n source: \"auth\",\n target: \"private\",\n };\n case \"cookie\":\n return {\n code: \"CP_DOWNGRADE_PRIVATE_DIMENSION\",\n inputClass: \"private\",\n source: \"cookie\",\n target: \"private\",\n };\n case \"draft-mode\":\n return {\n code: \"CP_DOWNGRADE_PRIVATE_DIMENSION\",\n inputClass: \"draft\",\n source: \"draft-mode\",\n target: \"privateUncacheable\",\n };\n case \"header\":\n return {\n code: \"CP_DOWNGRADE_PRIVATE_DIMENSION\",\n inputClass: \"private\",\n source: \"header\",\n target: \"private\",\n };\n case \"session\":\n return {\n code: \"CP_DOWNGRADE_PRIVATE_DIMENSION\",\n inputClass: \"session\",\n source: \"session\",\n target: \"private\",\n };\n case \"custom\":\n case \"interception\":\n case \"mounted-slots\":\n case \"params\":\n case \"route\":\n case \"search\":\n return null;\n default:\n return assertNever(input.source);\n }\n}\n\nexport function classifyRenderObservationDowngrade(\n input: ClassifyRenderObservationDowngradeInput,\n): CacheProofDowngradeClassification {\n const reasons: CacheProofDowngradeReason[] = [];\n let target: CacheProofDowngradeTarget = \"public\";\n\n switch (input.cacheability) {\n case \"public\":\n break;\n case \"private\": {\n const reason = {\n code: \"CP_DOWNGRADE_CACHEABILITY_PRIVATE\",\n target: \"private\",\n } satisfies CacheProofDowngradeReason;\n reasons.push(reason);\n target = maxCacheProofDowngradeTarget(target, reason.target);\n break;\n }\n case \"uncacheable\": {\n const reason = {\n code: \"CP_DOWNGRADE_CACHEABILITY_UNCACHEABLE\",\n target: \"privateUncacheable\",\n } satisfies CacheProofDowngradeReason;\n reasons.push(reason);\n target = maxCacheProofDowngradeTarget(target, reason.target);\n break;\n }\n case \"unknown\": {\n const reason = {\n code: \"CP_DOWNGRADE_CACHEABILITY_UNKNOWN\",\n target: \"freshRender\",\n } satisfies CacheProofDowngradeReason;\n reasons.push(reason);\n target = maxCacheProofDowngradeTarget(target, reason.target);\n break;\n }\n default:\n assertNever(input.cacheability);\n }\n\n if (input.completeness !== \"complete\") {\n const reason = {\n code: \"CP_DOWNGRADE_INCOMPLETE_OBSERVATION\",\n completeness: input.completeness,\n target: \"freshRender\",\n } satisfies CacheProofDowngradeReason;\n reasons.push(reason);\n target = maxCacheProofDowngradeTarget(target, reason.target);\n }\n\n if (input.dynamicFetches.length > 0) {\n const reason = {\n code: \"CP_DOWNGRADE_DYNAMIC_FETCH\",\n dynamicFetchCount: input.dynamicFetches.length,\n target: \"freshRender\",\n } satisfies CacheProofDowngradeReason;\n reasons.push(reason);\n target = maxCacheProofDowngradeTarget(target, reason.target);\n }\n\n const requestApis = normalizeRequestApiObservations(input.requestApis);\n for (const requestApi of requestApis) {\n if (requestApi.status === \"notObserved\") continue;\n const reason =\n requestApi.status === \"unknown\"\n ? ({\n code: \"CP_DOWNGRADE_UNKNOWN_REQUEST_API\",\n requestApi: requestApi.kind,\n target: \"freshRender\",\n } satisfies CacheProofDowngradeReason)\n : classifyObservedRequestApiDowngrade(requestApi.kind);\n reasons.push(reason);\n target = maxCacheProofDowngradeTarget(target, reason.target);\n }\n\n return {\n target,\n reasons,\n fallback: createDowngradeFallback(target, reasons),\n isPublicCacheCandidate: target === \"public\" || target === \"publicVariant\",\n };\n}\n\nexport function buildRenderRequestApiObservations(\n input: BuildRenderRequestApiObservationsInput,\n): RenderRequestApiObservation[] {\n const observedKinds = new Set(input.observed);\n const absentStatus: RenderRequestApiStatus =\n input.completeness === \"complete\" ? \"notObserved\" : \"unknown\";\n\n return ALL_RENDER_REQUEST_API_KINDS.map((kind) => ({\n kind,\n status: observedKinds.has(kind) ? \"observed\" : absentStatus,\n }));\n}\n\nexport function buildRenderObservation(input: BuildRenderObservationInput): RenderObservation {\n const requestApis = normalizeRequestApiObservations(input.requestApis);\n const dynamicFetches = sortedUniqueRedacted(input.dynamicFetches);\n\n return {\n schemaVersion: CACHE_PROOF_MODEL_SCHEMA_VERSION,\n output: input.output,\n completeness: input.completeness,\n boundaryOutcome: input.boundaryOutcome,\n requestApis,\n dynamicFetches,\n cacheTags: sortedUnique(input.cacheTags),\n pathTags: sortedUnique(input.pathTags),\n cacheability: input.cacheability,\n downgrade: classifyRenderObservationDowngrade({\n cacheability: input.cacheability,\n completeness: input.completeness,\n dynamicFetches,\n requestApis,\n }),\n };\n}\n\nexport function hasCompleteNegativeRequestApiProof(\n observation: RenderObservation,\n requiredApis: readonly RenderRequestApiKind[],\n): boolean {\n if (observation.completeness !== \"complete\") return false;\n\n const statuses = new Map<RenderRequestApiKind, RenderRequestApiStatus>();\n for (const requestApi of normalizeRequestApiObservations(observation.requestApis)) {\n statuses.set(requestApi.kind, requestApi.status);\n }\n\n for (const api of requiredApis) {\n if (statuses.get(api) !== \"notObserved\") return false;\n }\n return true;\n}\n\nfunction isStaticLayoutOutputScope(\n output: CacheProofOutputScope,\n): output is StaticLayoutCacheProofOutputScope {\n return output.kind === \"layout\";\n}\n\nfunction rejectStaticLayoutReuseProof(\n code: CacheProofRejectionCode,\n fields: CacheProofTraceFields,\n mode: CacheProofBreakerFallbackMode = \"renderFresh\",\n): BuildStaticLayoutReuseProofResult {\n return {\n kind: \"rejected\",\n fallback: buildBreakerFallback(code, fields, mode),\n };\n}\n\nfunction getRequestApiStatus(\n observations: readonly RenderRequestApiObservation[],\n kind: RenderRequestApiKind,\n): RenderRequestApiStatus | \"missing\" {\n let status: RenderRequestApiStatus | null = null;\n\n for (const requestApi of observations) {\n if (requestApi.kind !== kind) continue;\n if (status === null || requestApiStatusRank(requestApi.status) > requestApiStatusRank(status)) {\n status = requestApi.status;\n }\n }\n\n return status ?? \"missing\";\n}\n\nfunction createStaticLayoutDowngradeFallback(\n downgrade: CacheProofDowngradeClassification,\n): CacheProofBreakerFallback {\n const mode: CacheProofBreakerFallbackMode =\n downgrade.target === \"privateUncacheable\" ? \"privateUncacheable\" : \"renderFresh\";\n return buildBreakerFallback(\n \"CP_STATIC_LAYOUT_PRIVATE_DYNAMIC_DOWNGRADE\",\n {\n reasonCodes: downgrade.reasons.map((reason) => reason.code),\n target: downgrade.target,\n },\n mode,\n );\n}\n\nfunction createPrivateVariantDimensionFallback(\n dimension: CacheVariantDimension,\n): CacheProofBreakerFallback | null {\n const downgrade = classifyCacheVariantDimensionDowngrade({ source: dimension.source });\n if (!downgrade && dimension.privacy !== \"private\") {\n return null;\n }\n\n const target = downgrade?.target ?? \"private\";\n const mode: CacheProofBreakerFallbackMode =\n target === \"privateUncacheable\" ? \"privateUncacheable\" : \"renderFresh\";\n return buildBreakerFallback(\n \"CP_STATIC_LAYOUT_PRIVATE_VARIANT_DIMENSION\",\n {\n dimension: dimension.name,\n privacy: dimension.privacy,\n reasonCode: downgrade?.code ?? null,\n source: dimension.source,\n target,\n },\n mode,\n );\n}\n\nfunction outputFieldMismatch(\n candidate: StaticLayoutCacheProofOutputScope,\n observation: StaticLayoutCacheProofOutputScope,\n): \"layoutId\" | \"rootBoundaryId\" | \"routeId\" | null {\n if (candidate.layoutId !== observation.layoutId) return \"layoutId\";\n if (candidate.rootBoundaryId !== observation.rootBoundaryId) return \"rootBoundaryId\";\n if (candidate.routeId !== observation.routeId) return \"routeId\";\n return null;\n}\n\nexport function buildStaticLayoutReuseProof(\n input: BuildStaticLayoutReuseProofInput,\n): BuildStaticLayoutReuseProofResult {\n if (!isStaticLayoutOutputScope(input.currentOutput)) {\n return rejectStaticLayoutReuseProof(\"CP_STATIC_LAYOUT_CURRENT_OUTPUT_KIND\", {\n currentOutputKind: input.currentOutput.kind,\n });\n }\n\n if (!isStaticLayoutOutputScope(input.candidateVariant.output)) {\n return rejectStaticLayoutReuseProof(\"CP_STATIC_LAYOUT_CANDIDATE_OUTPUT_KIND\", {\n candidateOutputKind: input.candidateVariant.output.kind,\n });\n }\n\n if (!isStaticLayoutOutputScope(input.candidateObservation.output)) {\n return rejectStaticLayoutReuseProof(\"CP_STATIC_LAYOUT_OBSERVATION_OUTPUT_KIND\", {\n observationOutputKind: input.candidateObservation.output.kind,\n });\n }\n\n const currentOutput = input.currentOutput;\n const candidateOutput = input.candidateVariant.output;\n const observationOutput = input.candidateObservation.output;\n const requestApis = normalizeRequestApiObservations(input.candidateObservation.requestApis);\n const candidateObservation = {\n ...input.candidateObservation,\n requestApis,\n downgrade: classifyRenderObservationDowngrade({\n cacheability: input.candidateObservation.cacheability,\n completeness: input.candidateObservation.completeness,\n dynamicFetches: input.candidateObservation.dynamicFetches,\n requestApis,\n }),\n } satisfies RenderObservation;\n const observedOutputMismatch = outputFieldMismatch(candidateOutput, observationOutput);\n if (observedOutputMismatch) {\n return rejectStaticLayoutReuseProof(\"CP_STATIC_LAYOUT_OBSERVATION_OUTPUT_MISMATCH\", {\n candidateLayoutId: candidateOutput.layoutId,\n candidateRootBoundaryId: candidateOutput.rootBoundaryId,\n candidateRouteId: candidateOutput.routeId,\n field: observedOutputMismatch,\n observationLayoutId: observationOutput.layoutId,\n observationRootBoundaryId: observationOutput.rootBoundaryId,\n observationRouteId: observationOutput.routeId,\n });\n }\n\n if (currentOutput.layoutId !== candidateOutput.layoutId) {\n return rejectStaticLayoutReuseProof(\"CP_STATIC_LAYOUT_ID_MISMATCH\", {\n candidateLayoutId: candidateOutput.layoutId,\n currentLayoutId: currentOutput.layoutId,\n });\n }\n\n if (currentOutput.rootBoundaryId === null || candidateOutput.rootBoundaryId === null) {\n return rejectStaticLayoutReuseProof(\"CP_STATIC_LAYOUT_ROOT_BOUNDARY_UNKNOWN\", {\n candidateRootBoundaryId: candidateOutput.rootBoundaryId,\n currentRootBoundaryId: currentOutput.rootBoundaryId,\n });\n }\n\n if (currentOutput.rootBoundaryId !== candidateOutput.rootBoundaryId) {\n return rejectStaticLayoutReuseProof(\"CP_STATIC_LAYOUT_ROOT_BOUNDARY_MISMATCH\", {\n candidateRootBoundaryId: candidateOutput.rootBoundaryId,\n currentRootBoundaryId: currentOutput.rootBoundaryId,\n });\n }\n\n const boundaryCompatibility = buildBoundaryOutcomeCompatibility({\n candidate: candidateObservation.boundaryOutcome,\n expected: { kind: \"success\" },\n });\n if (boundaryCompatibility.kind === \"incompatible\") {\n return {\n kind: \"rejected\",\n fallback: boundaryCompatibility.fallback,\n };\n }\n\n for (const dimension of input.candidateVariant.dimensions) {\n const fallback = createPrivateVariantDimensionFallback(dimension);\n if (fallback) {\n return {\n kind: \"rejected\",\n fallback,\n };\n }\n }\n\n if (!candidateObservation.downgrade.isPublicCacheCandidate) {\n return {\n kind: \"rejected\",\n fallback: createStaticLayoutDowngradeFallback(candidateObservation.downgrade),\n };\n }\n\n // The loop can use the shared readonly registry; the proof stores a detached evidence copy.\n const requiredNegativeRequestApis = ALL_RENDER_REQUEST_API_KINDS;\n for (const api of requiredNegativeRequestApis) {\n const status = getRequestApiStatus(candidateObservation.requestApis, api);\n if (status === \"notObserved\") continue;\n\n return rejectStaticLayoutReuseProof(\n status === \"missing\"\n ? \"CP_STATIC_LAYOUT_REQUEST_API_UNKNOWN\"\n : \"CP_STATIC_LAYOUT_REQUEST_API_OBSERVED\",\n {\n requestApi: api,\n status,\n },\n );\n }\n\n return {\n kind: \"proof\",\n proof: {\n authorizesRuntimeReuse: false,\n candidateOutput,\n code: \"CP_STATIC_LAYOUT_REUSE_PROVEN\",\n currentOutput,\n fields: {\n candidateRouteId: candidateOutput.routeId,\n currentRouteId: currentOutput.routeId,\n layoutId: currentOutput.layoutId,\n rootBoundaryId: currentOutput.rootBoundaryId,\n },\n observation: candidateObservation,\n requiredNegativeRequestApis: [...requiredNegativeRequestApis],\n reuseClass: \"static-layout\",\n variant: input.candidateVariant,\n },\n };\n}\n\nexport function createDisabledCacheProofDecision(\n input: CreateDisabledCacheProofDecisionInput,\n): DisabledCacheProofDecision {\n return {\n kind: \"disabled\",\n canReuse: false,\n variant: input.variant,\n observation: input.observation,\n ...(input.staticLayoutProof ? { staticLayoutProof: input.staticLayoutProof } : {}),\n fallback: buildBreakerFallback(\"CP_MODEL_DISABLED\"),\n };\n}\n"],"mappings":"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"}
|
package/dist/server/csp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"csp.js","names":[],"sources":["../../src/server/csp.ts"],"sourcesContent":["import type { IncomingHttpHeaders, OutgoingHttpHeaders } from \"node:http\";\n\nconst ESCAPE_REGEX = /[&><\\u2028\\u2029]/;\ntype NodeHeaders = IncomingHttpHeaders | OutgoingHttpHeaders;\n\nfunction matchesDirectiveName(directive: string, name: string): boolean {\n return directive === name || directive.startsWith(`${name} `);\n}\n\nfunction getNodeHeaderValue(\n headers: NodeHeaders | null | undefined,\n key: \"content-security-policy\" | \"content-security-policy-report-only\",\n): string | undefined {\n const value = headers?.[key];\n if (Array.isArray(value)) {\n return value.join(\", \");\n }\n if (value == null) {\n return undefined;\n }\n return String(value);\n}\n\nexport function getScriptNonceFromHeader(cspHeaderValue: string): string | undefined {\n const directives = cspHeaderValue.split(\";\").map((directive) => directive.trim());\n\n const directive =\n directives.find((value) => matchesDirectiveName(value, \"script-src\")) ??\n directives.find((value) => matchesDirectiveName(value, \"default-src\"));\n\n if (!directive) {\n return undefined;\n }\n\n const nonce = directive\n .split(\" \")\n .slice(1)\n .map((source) => source.trim())\n .find((source) => source.startsWith(\"'nonce-\") && source.length > 8 && source.endsWith(\"'\"))\n ?.slice(7, -1);\n\n if (!nonce) {\n return undefined;\n }\n\n if (ESCAPE_REGEX.test(nonce)) {\n throw new Error(\n \"Nonce value from Content-Security-Policy contained HTML escape characters.\\nLearn more: https://nextjs.org/docs/messages/nonce-contained-invalid-characters\",\n );\n }\n\n return nonce;\n}\n\nexport function getScriptNonceFromHeaders(headers: Headers | null | undefined): string | undefined {\n const csp =\n headers?.get(\"content-security-policy\") ?? headers?.get(\"content-security-policy-report-only\");\n\n if (!csp) {\n return undefined;\n }\n\n return getScriptNonceFromHeader(csp);\n}\n\nfunction getScriptNonceFromNodeHeaders(\n headers: NodeHeaders | null | undefined,\n): string | undefined {\n const csp =\n getNodeHeaderValue(headers, \"content-security-policy\") ??\n getNodeHeaderValue(headers, \"content-security-policy-report-only\");\n\n if (!csp) {\n return undefined;\n }\n\n return getScriptNonceFromHeader(csp);\n}\n\nexport function getScriptNonceFromNodeHeaderSources(\n ...headersList: readonly (NodeHeaders | null | undefined)[]\n): string | undefined {\n for (const headers of headersList) {\n const nonce = getScriptNonceFromNodeHeaders(headers);\n if (nonce) {\n return nonce;\n }\n }\n\n return undefined;\n}\n\nexport function getScriptNonceFromHeaderSources(\n ...headersList: readonly (Headers | null | undefined)[]\n): string | undefined {\n for (const headers of headersList) {\n const nonce = getScriptNonceFromHeaders(headers);\n if (nonce) {\n return nonce;\n }\n }\n\n return undefined;\n}\n"],"mappings":";AAEA,MAAM,eAAe;AAGrB,SAAS,qBAAqB,WAAmB,MAAuB;
|
|
1
|
+
{"version":3,"file":"csp.js","names":[],"sources":["../../src/server/csp.ts"],"sourcesContent":["import type { IncomingHttpHeaders, OutgoingHttpHeaders } from \"node:http\";\n\nconst ESCAPE_REGEX = /[&><\\u2028\\u2029]/;\ntype NodeHeaders = IncomingHttpHeaders | OutgoingHttpHeaders;\n\nfunction matchesDirectiveName(directive: string, name: string): boolean {\n return directive === name || directive.startsWith(`${name} `);\n}\n\nfunction getNodeHeaderValue(\n headers: NodeHeaders | null | undefined,\n key: \"content-security-policy\" | \"content-security-policy-report-only\",\n): string | undefined {\n const value = headers?.[key];\n if (Array.isArray(value)) {\n return value.join(\", \");\n }\n if (value == null) {\n return undefined;\n }\n return String(value);\n}\n\nexport function getScriptNonceFromHeader(cspHeaderValue: string): string | undefined {\n const directives = cspHeaderValue.split(\";\").map((directive) => directive.trim());\n\n const directive =\n directives.find((value) => matchesDirectiveName(value, \"script-src\")) ??\n directives.find((value) => matchesDirectiveName(value, \"default-src\"));\n\n if (!directive) {\n return undefined;\n }\n\n const nonce = directive\n .split(\" \")\n .slice(1)\n .map((source) => source.trim())\n .find((source) => source.startsWith(\"'nonce-\") && source.length > 8 && source.endsWith(\"'\"))\n ?.slice(7, -1);\n\n if (!nonce) {\n return undefined;\n }\n\n if (ESCAPE_REGEX.test(nonce)) {\n throw new Error(\n \"Nonce value from Content-Security-Policy contained HTML escape characters.\\nLearn more: https://nextjs.org/docs/messages/nonce-contained-invalid-characters\",\n );\n }\n\n return nonce;\n}\n\nexport function getScriptNonceFromHeaders(headers: Headers | null | undefined): string | undefined {\n const csp =\n headers?.get(\"content-security-policy\") ?? headers?.get(\"content-security-policy-report-only\");\n\n if (!csp) {\n return undefined;\n }\n\n return getScriptNonceFromHeader(csp);\n}\n\nfunction getScriptNonceFromNodeHeaders(\n headers: NodeHeaders | null | undefined,\n): string | undefined {\n const csp =\n getNodeHeaderValue(headers, \"content-security-policy\") ??\n getNodeHeaderValue(headers, \"content-security-policy-report-only\");\n\n if (!csp) {\n return undefined;\n }\n\n return getScriptNonceFromHeader(csp);\n}\n\nexport function getScriptNonceFromNodeHeaderSources(\n ...headersList: readonly (NodeHeaders | null | undefined)[]\n): string | undefined {\n for (const headers of headersList) {\n const nonce = getScriptNonceFromNodeHeaders(headers);\n if (nonce) {\n return nonce;\n }\n }\n\n return undefined;\n}\n\nexport function getScriptNonceFromHeaderSources(\n ...headersList: readonly (Headers | null | undefined)[]\n): string | undefined {\n for (const headers of headersList) {\n const nonce = getScriptNonceFromHeaders(headers);\n if (nonce) {\n return nonce;\n }\n }\n\n return undefined;\n}\n"],"mappings":";AAEA,MAAM,eAAe;AAGrB,SAAS,qBAAqB,WAAmB,MAAuB;CACtE,OAAO,cAAc,QAAQ,UAAU,WAAW,GAAG,KAAK,GAAG;;AAG/D,SAAS,mBACP,SACA,KACoB;CACpB,MAAM,QAAQ,UAAU;CACxB,IAAI,MAAM,QAAQ,MAAM,EACtB,OAAO,MAAM,KAAK,KAAK;CAEzB,IAAI,SAAS,MACX;CAEF,OAAO,OAAO,MAAM;;AAGtB,SAAgB,yBAAyB,gBAA4C;CACnF,MAAM,aAAa,eAAe,MAAM,IAAI,CAAC,KAAK,cAAc,UAAU,MAAM,CAAC;CAEjF,MAAM,YACJ,WAAW,MAAM,UAAU,qBAAqB,OAAO,aAAa,CAAC,IACrE,WAAW,MAAM,UAAU,qBAAqB,OAAO,cAAc,CAAC;CAExE,IAAI,CAAC,WACH;CAGF,MAAM,QAAQ,UACX,MAAM,IAAI,CACV,MAAM,EAAE,CACR,KAAK,WAAW,OAAO,MAAM,CAAC,CAC9B,MAAM,WAAW,OAAO,WAAW,UAAU,IAAI,OAAO,SAAS,KAAK,OAAO,SAAS,IAAI,CAAC,EAC1F,MAAM,GAAG,GAAG;CAEhB,IAAI,CAAC,OACH;CAGF,IAAI,aAAa,KAAK,MAAM,EAC1B,MAAM,IAAI,MACR,8JACD;CAGH,OAAO;;AAGT,SAAgB,0BAA0B,SAAyD;CACjG,MAAM,MACJ,SAAS,IAAI,0BAA0B,IAAI,SAAS,IAAI,sCAAsC;CAEhG,IAAI,CAAC,KACH;CAGF,OAAO,yBAAyB,IAAI;;AAGtC,SAAS,8BACP,SACoB;CACpB,MAAM,MACJ,mBAAmB,SAAS,0BAA0B,IACtD,mBAAmB,SAAS,sCAAsC;CAEpE,IAAI,CAAC,KACH;CAGF,OAAO,yBAAyB,IAAI;;AAGtC,SAAgB,oCACd,GAAG,aACiB;CACpB,KAAK,MAAM,WAAW,aAAa;EACjC,MAAM,QAAQ,8BAA8B,QAAQ;EACpD,IAAI,OACF,OAAO;;;AAOb,SAAgB,gCACd,GAAG,aACiB;CACpB,KAAK,MAAM,WAAW,aAAa;EACjC,MAAM,QAAQ,0BAA0B,QAAQ;EAChD,IAAI,OACF,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-error-overlay-store.js","names":[],"sources":["../../src/server/dev-error-overlay-store.ts"],"sourcesContent":["// Module-level store for the dev error overlay. Lives in its own file so the\n// overlay React component (dev-error-overlay.tsx) can subscribe via\n// useSyncExternalStore without circular imports.\n\nexport type Source = \"uncaught\" | \"caught\" | \"window-error\" | \"unhandledrejection\";\n\nexport type ReportedError = {\n source: Source;\n message: string;\n stack: string | undefined;\n componentStack: string | undefined;\n};\n\nexport type OverlayState = {\n errors: ReportedError[];\n index: number;\n minimized: boolean;\n};\n\n// Cap the buffer so a hot-reloading loop or an effect that throws on every\n// render can't grow the array (and its retained stack strings) without\n// bound. FIFO eviction keeps the most recent failures.\nconst MAX_DEV_OVERLAY_ERRORS = 50;\n\nlet snapshot: OverlayState = { errors: [], index: 0, minimized: false };\nconst listeners = new Set<() => void>();\n\nfunction emit(): void {\n for (const fn of listeners) fn();\n}\n\nexport function subscribeOverlay(fn: () => void): () => void {\n listeners.add(fn);\n return () => {\n listeners.delete(fn);\n };\n}\n\nexport function getOverlaySnapshot(): OverlayState {\n return snapshot;\n}\n\nexport function reportToOverlay(error: ReportedError): void {\n // Any new error pops the dialog open, regardless of source or current\n // state. The developer can minimize once they've taken stock; subsequent\n // failures will re-expand.\n const next = [...snapshot.errors, error];\n const dropped = next.length > MAX_DEV_OVERLAY_ERRORS ? next.length - MAX_DEV_OVERLAY_ERRORS : 0;\n const errors = dropped > 0 ? next.slice(dropped) : next;\n snapshot = {\n errors,\n index: errors.length - 1,\n minimized: false,\n };\n emit();\n}\n\nexport function dismissOverlay(): void {\n snapshot = { errors: [], index: 0, minimized: false };\n emit();\n}\n\nexport function setOverlayIndex(index: number): void {\n if (index < 0 || index >= snapshot.errors.length) return;\n snapshot = { ...snapshot, index };\n emit();\n}\n\nexport function minimizeOverlay(): void {\n if (snapshot.minimized) return;\n snapshot = { ...snapshot, minimized: true };\n emit();\n}\n\nexport function expandOverlay(): void {\n if (!snapshot.minimized) return;\n snapshot = { ...snapshot, minimized: false };\n emit();\n}\n"],"mappings":";AAsBA,MAAM,yBAAyB;AAE/B,IAAI,WAAyB;CAAE,QAAQ,EAAE;CAAE,OAAO;CAAG,WAAW;CAAO;AACvE,MAAM,4BAAY,IAAI,KAAiB;AAEvC,SAAS,OAAa;
|
|
1
|
+
{"version":3,"file":"dev-error-overlay-store.js","names":[],"sources":["../../src/server/dev-error-overlay-store.ts"],"sourcesContent":["// Module-level store for the dev error overlay. Lives in its own file so the\n// overlay React component (dev-error-overlay.tsx) can subscribe via\n// useSyncExternalStore without circular imports.\n\nexport type Source = \"uncaught\" | \"caught\" | \"window-error\" | \"unhandledrejection\";\n\nexport type ReportedError = {\n source: Source;\n message: string;\n stack: string | undefined;\n componentStack: string | undefined;\n};\n\nexport type OverlayState = {\n errors: ReportedError[];\n index: number;\n minimized: boolean;\n};\n\n// Cap the buffer so a hot-reloading loop or an effect that throws on every\n// render can't grow the array (and its retained stack strings) without\n// bound. FIFO eviction keeps the most recent failures.\nconst MAX_DEV_OVERLAY_ERRORS = 50;\n\nlet snapshot: OverlayState = { errors: [], index: 0, minimized: false };\nconst listeners = new Set<() => void>();\n\nfunction emit(): void {\n for (const fn of listeners) fn();\n}\n\nexport function subscribeOverlay(fn: () => void): () => void {\n listeners.add(fn);\n return () => {\n listeners.delete(fn);\n };\n}\n\nexport function getOverlaySnapshot(): OverlayState {\n return snapshot;\n}\n\nexport function reportToOverlay(error: ReportedError): void {\n // Any new error pops the dialog open, regardless of source or current\n // state. The developer can minimize once they've taken stock; subsequent\n // failures will re-expand.\n const next = [...snapshot.errors, error];\n const dropped = next.length > MAX_DEV_OVERLAY_ERRORS ? next.length - MAX_DEV_OVERLAY_ERRORS : 0;\n const errors = dropped > 0 ? next.slice(dropped) : next;\n snapshot = {\n errors,\n index: errors.length - 1,\n minimized: false,\n };\n emit();\n}\n\nexport function dismissOverlay(): void {\n snapshot = { errors: [], index: 0, minimized: false };\n emit();\n}\n\nexport function setOverlayIndex(index: number): void {\n if (index < 0 || index >= snapshot.errors.length) return;\n snapshot = { ...snapshot, index };\n emit();\n}\n\nexport function minimizeOverlay(): void {\n if (snapshot.minimized) return;\n snapshot = { ...snapshot, minimized: true };\n emit();\n}\n\nexport function expandOverlay(): void {\n if (!snapshot.minimized) return;\n snapshot = { ...snapshot, minimized: false };\n emit();\n}\n"],"mappings":";AAsBA,MAAM,yBAAyB;AAE/B,IAAI,WAAyB;CAAE,QAAQ,EAAE;CAAE,OAAO;CAAG,WAAW;CAAO;AACvE,MAAM,4BAAY,IAAI,KAAiB;AAEvC,SAAS,OAAa;CACpB,KAAK,MAAM,MAAM,WAAW,IAAI;;AAGlC,SAAgB,iBAAiB,IAA4B;CAC3D,UAAU,IAAI,GAAG;CACjB,aAAa;EACX,UAAU,OAAO,GAAG;;;AAIxB,SAAgB,qBAAmC;CACjD,OAAO;;AAGT,SAAgB,gBAAgB,OAA4B;CAI1D,MAAM,OAAO,CAAC,GAAG,SAAS,QAAQ,MAAM;CACxC,MAAM,UAAU,KAAK,SAAS,yBAAyB,KAAK,SAAS,yBAAyB;CAC9F,MAAM,SAAS,UAAU,IAAI,KAAK,MAAM,QAAQ,GAAG;CACnD,WAAW;EACT;EACA,OAAO,OAAO,SAAS;EACvB,WAAW;EACZ;CACD,MAAM;;AAGR,SAAgB,iBAAuB;CACrC,WAAW;EAAE,QAAQ,EAAE;EAAE,OAAO;EAAG,WAAW;EAAO;CACrD,MAAM;;AAGR,SAAgB,gBAAgB,OAAqB;CACnD,IAAI,QAAQ,KAAK,SAAS,SAAS,OAAO,QAAQ;CAClD,WAAW;EAAE,GAAG;EAAU;EAAO;CACjC,MAAM;;AAGR,SAAgB,kBAAwB;CACtC,IAAI,SAAS,WAAW;CACxB,WAAW;EAAE,GAAG;EAAU,WAAW;EAAM;CAC3C,MAAM;;AAGR,SAAgB,gBAAsB;CACpC,IAAI,CAAC,SAAS,WAAW;CACzB,WAAW;EAAE,GAAG;EAAU,WAAW;EAAO;CAC5C,MAAM"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
1
2
|
import { dismissOverlay, expandOverlay, getOverlaySnapshot, minimizeOverlay, reportToOverlay, setOverlayIndex, subscribeOverlay } from "./dev-error-overlay-store.js";
|
|
2
3
|
import { useEffect, useSyncExternalStore } from "react";
|
|
3
4
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -18,6 +19,7 @@ function installDevErrorOverlay() {
|
|
|
18
19
|
installed = true;
|
|
19
20
|
window.addEventListener("error", (event) => {
|
|
20
21
|
const err = event.error;
|
|
22
|
+
if (isNavigationSignalError(err)) return;
|
|
21
23
|
if (err instanceof Error) {
|
|
22
24
|
if (alreadyReported(err)) return;
|
|
23
25
|
reportDevError(err, { source: "window-error" });
|
|
@@ -25,6 +27,7 @@ function installDevErrorOverlay() {
|
|
|
25
27
|
});
|
|
26
28
|
window.addEventListener("unhandledrejection", (event) => {
|
|
27
29
|
const reason = event.reason;
|
|
30
|
+
if (isNavigationSignalError(reason)) return;
|
|
28
31
|
if (reason instanceof Error) {
|
|
29
32
|
if (alreadyReported(reason)) return;
|
|
30
33
|
reportDevError(reason, { source: "unhandledrejection" });
|
|
@@ -45,6 +48,7 @@ function reportDevError(error, options) {
|
|
|
45
48
|
});
|
|
46
49
|
}
|
|
47
50
|
function devOnCaughtError(error, errorInfo) {
|
|
51
|
+
if (isNavigationSignalError(error)) return;
|
|
48
52
|
console.error(error);
|
|
49
53
|
if (errorInfo?.componentStack) console.error("The above error occurred in a React component:\n" + errorInfo.componentStack);
|
|
50
54
|
reportDevError(error, {
|
|
@@ -53,6 +57,7 @@ function devOnCaughtError(error, errorInfo) {
|
|
|
53
57
|
});
|
|
54
58
|
}
|
|
55
59
|
function devOnUncaughtError(error, errorInfo) {
|
|
60
|
+
if (isNavigationSignalError(error)) return;
|
|
56
61
|
console.error(error);
|
|
57
62
|
if (errorInfo?.componentStack) console.error("The above error occurred in a React component:\n" + errorInfo.componentStack);
|
|
58
63
|
reportDevError(error, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-error-overlay.js","names":[],"sources":["../../src/server/dev-error-overlay.tsx"],"sourcesContent":["// Dev-only runtime error overlay. Surfaces three error sources that\n// otherwise only reach the console:\n// 1. React render errors caught by an error.tsx boundary (onCaughtError)\n// 2. React render errors with no boundary above them (onUncaughtError)\n// 3. Plain script errors / unhandled promise rejections (window listeners)\n//\n// Rendered via a separate React root mounted on a detached <div> appended to\n// the body. That isolation means the overlay survives an unmount of the main\n// hydrateRoot(document, ...) tree — necessary because most of the errors we\n// want to surface are exactly the ones that take that tree down.\n\nimport { useEffect, useSyncExternalStore } from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\n\nimport {\n type OverlayState,\n type ReportedError,\n type Source,\n dismissOverlay,\n expandOverlay,\n getOverlaySnapshot,\n minimizeOverlay,\n reportToOverlay,\n setOverlayIndex,\n subscribeOverlay,\n} from \"./dev-error-overlay-store.js\";\n\n// Re-export so callers (e.g. the HMR rsc:update handler) can clear the\n// overlay when a new payload lands.\nexport { dismissOverlay } from \"./dev-error-overlay-store.js\";\n\nconst MOUNT_NODE_ID = \"__vinext_dev_error_overlay_root\";\n\nlet reactRoot: Root | null = null;\nlet installed = false;\n\n// Errors React already routed through onCaughtError/onUncaughtError shouldn't\n// also surface from the window listeners — otherwise the same throw appears\n// twice in the dialog (\"Runtime Error\" + \"Unhandled Script Error\"). We track\n// instances we've reported and skip them in the global handlers.\nconst reportedErrors = new WeakSet<object>();\n\nfunction rememberReported(error: unknown): void {\n if (error && typeof error === \"object\") reportedErrors.add(error);\n}\n\nfunction alreadyReported(error: unknown): boolean {\n return !!error && typeof error === \"object\" && reportedErrors.has(error);\n}\n\nexport function installDevErrorOverlay(): void {\n if (installed || typeof window === \"undefined\") return;\n installed = true;\n\n window.addEventListener(\"error\", (event: ErrorEvent) => {\n const err = event.error;\n if (err instanceof Error) {\n if (alreadyReported(err)) return;\n reportDevError(err, { source: \"window-error\" });\n } else if (event.message) {\n reportDevError(new Error(event.message), { source: \"window-error\" });\n }\n });\n\n window.addEventListener(\"unhandledrejection\", (event: PromiseRejectionEvent) => {\n const reason = event.reason;\n if (reason instanceof Error) {\n if (alreadyReported(reason)) return;\n reportDevError(reason, { source: \"unhandledrejection\" });\n } else {\n reportDevError(new Error(String(reason)), { source: \"unhandledrejection\" });\n }\n });\n}\n\nfunction reportDevError(\n error: unknown,\n options: { source: Source; componentStack?: string },\n): void {\n if (typeof window === \"undefined\") return;\n\n rememberReported(error);\n\n const message =\n error instanceof Error\n ? error.message\n : typeof error === \"string\"\n ? error\n : safeStringify(error);\n const stack = error instanceof Error ? error.stack : undefined;\n\n ensureMounted();\n reportToOverlay({\n source: options.source,\n message,\n stack,\n componentStack: options.componentStack,\n });\n}\n\n// React's onCaughtError fires for boundary-caught errors. We log to the console\n// (preserving the default behavior) and surface in the overlay. Sentinel errors\n// (NEXT_NOT_FOUND, NEXT_REDIRECT, etc.) are re-thrown in getDerivedStateFromError\n// before they reach onCaughtError, so they don't appear here in practice.\nexport function devOnCaughtError(\n error: unknown,\n errorInfo: { componentStack?: string; errorBoundary?: unknown },\n): void {\n console.error(error);\n if (errorInfo?.componentStack) {\n console.error(\"The above error occurred in a React component:\\n\" + errorInfo.componentStack);\n }\n reportDevError(error, { source: \"caught\", componentStack: errorInfo?.componentStack });\n}\n\n// Dev variant of onUncaughtError. Surfaces the error in the overlay and stops\n// — we deliberately do NOT perform the prod recovery navigation\n// (window.location.assign) because in dev the overlay is the user-facing\n// recovery; a hard navigation would blow it away along with the rest of the\n// page. HMR or a manual refresh resumes the session once the bug is fixed.\nexport function devOnUncaughtError(\n error: unknown,\n errorInfo: { componentStack?: string; errorBoundary?: unknown },\n): void {\n console.error(error);\n if (errorInfo?.componentStack) {\n console.error(\"The above error occurred in a React component:\\n\" + errorInfo.componentStack);\n }\n reportDevError(error, { source: \"uncaught\", componentStack: errorInfo?.componentStack });\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return Object.prototype.toString.call(value);\n }\n}\n\nfunction ensureMounted(): void {\n if (reactRoot) return;\n const node = document.createElement(\"div\");\n node.id = MOUNT_NODE_ID;\n // Fall back to documentElement in case body hasn't been parsed yet (e.g.\n // an extremely early hydration error firing before the body element is\n // attached). Either parent keeps the overlay outside the React-managed\n // hydrateRoot tree, which is what matters.\n (document.body ?? document.documentElement).appendChild(node);\n reactRoot = createRoot(node);\n reactRoot.render(<DevErrorOverlayApp />);\n}\n\n// ---------------------------------------------------------------------------\n// React component tree\n// ---------------------------------------------------------------------------\n\nconst SOURCE_LABEL: Record<Source, string> = {\n uncaught: \"Unhandled Runtime Error\",\n caught: \"Runtime Error\",\n \"window-error\": \"Unhandled Script Error\",\n unhandledrejection: \"Unhandled Promise Rejection\",\n};\n\nfunction DevErrorOverlayApp(): React.ReactNode {\n const state = useSyncExternalStore<OverlayState>(\n subscribeOverlay,\n getOverlaySnapshot,\n getOverlaySnapshot,\n );\n if (state.errors.length === 0) return null;\n const current = state.errors[state.index] ?? state.errors[0]!;\n\n // Render the stylesheet once at the root so it's not re-injected when\n // toggling between minimized and expanded states.\n return (\n <>\n <style>{overlayStylesheet}</style>\n {state.minimized ? (\n <DevErrorIndicator\n count={state.errors.length}\n source={current.source}\n onExpand={expandOverlay}\n />\n ) : (\n <DevErrorOverlay\n error={current}\n index={state.index}\n total={state.errors.length}\n // setOverlayIndex bounds-checks internally and the prev/next\n // buttons are disabled at the edges, so no clamp needed here.\n onPrev={() => setOverlayIndex(state.index - 1)}\n onNext={() => setOverlayIndex(state.index + 1)}\n onMinimize={minimizeOverlay}\n onDismiss={dismissOverlay}\n />\n )}\n </>\n );\n}\n\nfunction DevErrorIndicator({\n count,\n source,\n onExpand,\n}: {\n count: number;\n source: Source;\n onExpand: () => void;\n}): React.ReactNode {\n return (\n <div style={indicatorContainerStyle}>\n <button\n type=\"button\"\n data-testid=\"vinext-dev-error-indicator\"\n aria-label={`${count} runtime error${count === 1 ? \"\" : \"s\"} — click to expand`}\n title={SOURCE_LABEL[source]}\n onClick={onExpand}\n className=\"vinext-overlay-indicator\"\n >\n <span aria-hidden=\"true\" style={indicatorIconStyle}>\n ⚠\n </span>\n <span data-testid=\"vinext-dev-error-indicator-count\" style={indicatorCountStyle}>\n {count}\n </span>\n </button>\n </div>\n );\n}\n\nfunction DevErrorOverlay({\n error,\n index,\n total,\n onPrev,\n onNext,\n onMinimize,\n onDismiss,\n}: {\n error: ReportedError;\n index: number;\n total: number;\n onPrev: () => void;\n onNext: () => void;\n onMinimize: () => void;\n onDismiss: () => void;\n}): React.ReactNode {\n const frames = error.stack ? parseStack(error.stack) : [];\n\n // Esc minimizes, ←/→ navigate between errors. Esc no longer dismisses\n // outright — once a developer wants the overlay gone they can hit the ×\n // button. Listener is attached on the window so it works regardless of\n // focus location inside the overlay.\n useEffect(() => {\n const onKey = (e: KeyboardEvent): void => {\n if (e.key === \"Escape\") {\n onMinimize();\n } else if (e.key === \"ArrowLeft\" && total > 1) {\n onPrev();\n } else if (e.key === \"ArrowRight\" && total > 1) {\n onNext();\n }\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [onMinimize, onPrev, onNext, total]);\n\n return (\n <div style={backdropStyle} data-testid=\"vinext-dev-error-backdrop\" onClick={onMinimize}>\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={SOURCE_LABEL[error.source]}\n data-testid=\"vinext-dev-error-overlay\"\n style={dialogStyle}\n onClick={(e) => e.stopPropagation()}\n >\n <div style={accentBarStyle} />\n\n <header style={headerStyle}>\n <div style={headerLeftStyle}>\n <span data-testid=\"vinext-dev-error-title\" style={badgeStyle}>\n {SOURCE_LABEL[error.source]}\n </span>\n {total > 1 ? (\n <div data-testid=\"vinext-dev-error-pagination\" style={paginationStyle}>\n <button\n type=\"button\"\n data-testid=\"vinext-dev-error-prev\"\n onClick={onPrev}\n disabled={index === 0}\n className=\"vinext-overlay-nav\"\n aria-label=\"Previous error\"\n >\n ‹\n </button>\n <span data-testid=\"vinext-dev-error-counter\" style={counterStyle}>\n {index + 1} of {total}\n </span>\n <button\n type=\"button\"\n data-testid=\"vinext-dev-error-next\"\n onClick={onNext}\n disabled={index === total - 1}\n className=\"vinext-overlay-nav\"\n aria-label=\"Next error\"\n >\n ›\n </button>\n </div>\n ) : null}\n </div>\n <button\n type=\"button\"\n data-testid=\"vinext-dev-error-minimize\"\n onClick={onMinimize}\n className=\"vinext-overlay-minimize\"\n aria-label=\"Minimize\"\n title=\"Minimize (Esc)\"\n >\n –\n </button>\n <button\n type=\"button\"\n data-testid=\"vinext-dev-error-close\"\n onClick={onDismiss}\n className=\"vinext-overlay-close\"\n aria-label=\"Dismiss\"\n title=\"Dismiss all errors\"\n >\n ×\n </button>\n </header>\n\n <div style={bodyStyle}>\n <h2 data-testid=\"vinext-dev-error-message\" style={messageStyle}>\n {error.message}\n </h2>\n\n {frames.length > 0 ? (\n <ol data-testid=\"vinext-dev-error-stack\" style={stackListStyle}>\n {frames.map((frame) => (\n <li key={frame.key} className=\"vinext-overlay-frame\" style={stackItemStyle}>\n <span style={frameFnStyle}>{frame.fn}</span>\n {frame.file ? (\n <span style={frameLocStyle}>\n {frame.file}\n {frame.line ? `:${frame.line}` : \"\"}\n {frame.col ? `:${frame.col}` : \"\"}\n </span>\n ) : null}\n </li>\n ))}\n </ol>\n ) : null}\n\n {error.componentStack ? (\n <details style={detailsStyle}>\n <summary style={summaryStyle}>Component stack</summary>\n <pre data-testid=\"vinext-dev-error-component-stack\" style={componentStackStyle}>\n {error.componentStack}\n </pre>\n </details>\n ) : null}\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Stack parsing — handles V8 (\" at fn (file:line:col)\") and SpiderMonkey/\n// JavaScriptCore (\"fn@file:line:col\") formats. Lines that don't match either\n// shape are kept verbatim as a function-name-only frame so the overlay still\n// renders something useful in unfamiliar runtimes.\n// ---------------------------------------------------------------------------\n\ntype Frame = { key: string; fn: string; file?: string; line?: string; col?: string };\n\nconst V8_PAREN_FRAME = /^(.*?)\\s*\\((.+):(\\d+):(\\d+)\\)$/;\nconst V8_BARE_FRAME = /^(.+):(\\d+):(\\d+)$/;\nconst MOZ_FRAME = /^(.*?)@(.+):(\\d+):(\\d+)$/;\n\nfunction parseStack(stack: string): Frame[] {\n const frames: Frame[] = [];\n // Suffix repeat occurrences with #2, #3 so React keys stay unique even when\n // the same frame appears multiple times in a recursive stack.\n const seen = new Map<string, number>();\n const pushFrame = (fn: string, file?: string, line?: string, col?: string): void => {\n const base = `${fn}@${file ?? \"\"}:${line ?? \"\"}:${col ?? \"\"}`;\n const count = (seen.get(base) ?? 0) + 1;\n seen.set(base, count);\n const key = count === 1 ? base : `${base}#${count}`;\n frames.push({ key, fn, file, line, col });\n };\n for (const raw of stack.split(\"\\n\")) {\n const line = raw.trim();\n if (!line) continue;\n\n // V8 / Chromium: \" at fn (file:line:col)\" or \" at file:line:col\"\n if (line.startsWith(\"at \")) {\n const body = line.slice(3);\n const parenMatch = body.match(V8_PAREN_FRAME);\n if (parenMatch) {\n pushFrame(parenMatch[1] || \"<anonymous>\", parenMatch[2], parenMatch[3], parenMatch[4]);\n continue;\n }\n const bareMatch = body.match(V8_BARE_FRAME);\n if (bareMatch) {\n pushFrame(\"<anonymous>\", bareMatch[1], bareMatch[2], bareMatch[3]);\n continue;\n }\n pushFrame(body);\n continue;\n }\n\n // SpiderMonkey (Firefox) / JavaScriptCore (Safari): \"fn@file:line:col\".\n // The first line of a Firefox stack is the error message itself; skip it\n // by requiring the @-form match.\n const mozMatch = line.match(MOZ_FRAME);\n if (mozMatch) {\n pushFrame(mozMatch[1] || \"<anonymous>\", mozMatch[2], mozMatch[3], mozMatch[4]);\n continue;\n }\n\n // Unknown shape — preserve the line as a function-name-only frame so the\n // overlay shows something rather than dropping the line silently.\n pushFrame(line);\n }\n return frames;\n}\n\n// ---------------------------------------------------------------------------\n// Inline styles + a tiny stylesheet for hover/focus + entrance animation.\n// Keeping it all in this file means the overlay has no external CSS\n// dependency and works the same way in any host app.\n// ---------------------------------------------------------------------------\n\nconst FONT_STACK =\n \"ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\";\nconst MONO_STACK = \"ui-monospace, SFMono-Regular, Menlo, Consolas, monospace\";\n\nconst overlayStylesheet = `\n@keyframes vinextOverlayBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n@keyframes vinextOverlayDialogIn {\n from { opacity: 0; transform: translateY(8px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n}\n@keyframes vinextOverlayIndicatorIn {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.vinext-overlay-nav {\n background: transparent;\n border: none;\n color: inherit;\n cursor: pointer;\n padding: 2px 8px;\n font-size: 14px;\n line-height: 1;\n border-radius: 6px;\n transition: background 0.12s ease;\n}\n.vinext-overlay-nav:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.08);\n}\n.vinext-overlay-nav:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n}\n.vinext-overlay-minimize,\n.vinext-overlay-close {\n background: transparent;\n border: none;\n color: #a1a1aa;\n cursor: pointer;\n font-size: 16px;\n line-height: 1;\n padding: 4px 8px;\n border-radius: 6px;\n transition: background 0.12s ease, color 0.12s ease;\n}\n.vinext-overlay-minimize:hover,\n.vinext-overlay-close:hover {\n background: rgba(255, 255, 255, 0.08);\n color: #fafafa;\n}\n.vinext-overlay-close { font-size: 20px; }\n.vinext-overlay-frame {\n padding: 8px 12px;\n border-radius: 6px;\n transition: background 0.12s ease;\n}\n.vinext-overlay-frame:hover {\n background: rgba(255, 255, 255, 0.04);\n}\n.vinext-overlay-indicator {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n border-radius: 999px;\n background: #18181b;\n color: #fafafa;\n border: 1px solid rgba(239, 68, 68, 0.45);\n font: 600 13px ${FONT_STACK};\n cursor: pointer;\n transition: background 0.12s ease, border-color 0.12s ease, transform 0.12s ease;\n animation: vinextOverlayIndicatorIn 0.18s ease-out;\n}\n.vinext-overlay-indicator:hover {\n background: #1f1f23;\n border-color: rgba(239, 68, 68, 0.7);\n transform: translateY(-1px);\n}\n`;\n\nconst backdropStyle: React.CSSProperties = {\n // The backdrop captures click-outside-to-minimize as a proper modal would —\n // a click on it dismisses the overlay rather than reaching the page\n // underneath. The dialog re-enables pointer events for itself via\n // dialogStyle.\n position: \"fixed\",\n inset: 0,\n background: \"rgba(10, 10, 12, 0.55)\",\n backdropFilter: \"blur(3px)\",\n WebkitBackdropFilter: \"blur(3px)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 24,\n zIndex: 2147483646,\n animation: \"vinextOverlayBackdropIn 0.15s ease-out\",\n};\n\nconst dialogStyle: React.CSSProperties = {\n position: \"relative\",\n pointerEvents: \"auto\",\n width: \"min(640px, 100%)\",\n maxHeight: \"min(80vh, 720px)\",\n display: \"flex\",\n flexDirection: \"column\",\n background: \"#0a0a0a\",\n color: \"#fafafa\",\n border: \"1px solid rgba(255, 255, 255, 0.08)\",\n borderRadius: 12,\n fontFamily: FONT_STACK,\n fontSize: 14,\n lineHeight: 1.5,\n overflow: \"hidden\",\n animation: \"vinextOverlayDialogIn 0.18s ease-out\",\n};\n\nconst indicatorContainerStyle: React.CSSProperties = {\n position: \"fixed\",\n bottom: 16,\n left: 16,\n zIndex: 2147483646,\n};\n\nconst indicatorIconStyle: React.CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#ef4444\",\n fontSize: 14,\n};\n\nconst indicatorCountStyle: React.CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minWidth: 18,\n padding: \"0 6px\",\n height: 18,\n borderRadius: 999,\n background: \"rgba(239, 68, 68, 0.18)\",\n color: \"#fca5a5\",\n fontSize: 11,\n fontWeight: 600,\n fontVariantNumeric: \"tabular-nums\",\n};\n\nconst accentBarStyle: React.CSSProperties = {\n height: 3,\n background: \"linear-gradient(90deg, #ef4444 0%, #f97316 100%)\",\n};\n\nconst headerStyle: React.CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: 12,\n padding: \"14px 16px\",\n borderBottom: \"1px solid rgba(255, 255, 255, 0.06)\",\n};\n\nconst headerLeftStyle: React.CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n minWidth: 0,\n};\n\nconst badgeStyle: React.CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n background: \"rgba(239, 68, 68, 0.12)\",\n color: \"#fca5a5\",\n border: \"1px solid rgba(239, 68, 68, 0.25)\",\n padding: \"3px 10px\",\n borderRadius: 999,\n fontSize: 11,\n fontWeight: 600,\n letterSpacing: 0.2,\n textTransform: \"uppercase\",\n whiteSpace: \"nowrap\",\n};\n\nconst paginationStyle: React.CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n gap: 2,\n color: \"#a1a1aa\",\n fontSize: 12,\n};\n\nconst counterStyle: React.CSSProperties = {\n padding: \"0 4px\",\n fontVariantNumeric: \"tabular-nums\",\n};\n\nconst bodyStyle: React.CSSProperties = {\n padding: \"16px 20px 20px\",\n overflow: \"auto\",\n flex: 1,\n};\n\nconst messageStyle: React.CSSProperties = {\n margin: \"0 0 16px 0\",\n fontFamily: MONO_STACK,\n fontSize: 16,\n fontWeight: 500,\n lineHeight: 1.45,\n color: \"#fafafa\",\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n};\n\nconst stackListStyle: React.CSSProperties = {\n listStyle: \"none\",\n margin: 0,\n padding: 0,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 2,\n fontFamily: MONO_STACK,\n fontSize: 12,\n};\n\nconst stackItemStyle: React.CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n gap: 2,\n cursor: \"default\",\n};\n\nconst frameFnStyle: React.CSSProperties = {\n color: \"#fafafa\",\n fontWeight: 500,\n};\n\nconst frameLocStyle: React.CSSProperties = {\n color: \"#71717a\",\n fontSize: 11,\n};\n\nconst detailsStyle: React.CSSProperties = {\n marginTop: 16,\n paddingTop: 12,\n borderTop: \"1px solid rgba(255, 255, 255, 0.06)\",\n color: \"#a1a1aa\",\n fontSize: 12,\n};\n\nconst summaryStyle: React.CSSProperties = {\n cursor: \"pointer\",\n userSelect: \"none\",\n padding: \"4px 0\",\n color: \"#a1a1aa\",\n fontWeight: 500,\n};\n\nconst componentStackStyle: React.CSSProperties = {\n margin: \"8px 0 0 0\",\n fontFamily: MONO_STACK,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n color: \"#a1a1aa\",\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dev-error-overlay.js","names":[],"sources":["../../src/server/dev-error-overlay.tsx"],"sourcesContent":["// Dev-only runtime error overlay. Surfaces three error sources that\n// otherwise only reach the console:\n// 1. React render errors caught by an error.tsx boundary (onCaughtError)\n// 2. React render errors with no boundary above them (onUncaughtError)\n// 3. Plain script errors / unhandled promise rejections (window listeners)\n//\n// Rendered via a separate React root mounted on a detached <div> appended to\n// the body. That isolation means the overlay survives an unmount of the main\n// hydrateRoot(document, ...) tree — necessary because most of the errors we\n// want to surface are exactly the ones that take that tree down.\n\nimport { useEffect, useSyncExternalStore } from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\n\nimport { isNavigationSignalError } from \"../utils/navigation-signal.js\";\nimport {\n type OverlayState,\n type ReportedError,\n type Source,\n dismissOverlay,\n expandOverlay,\n getOverlaySnapshot,\n minimizeOverlay,\n reportToOverlay,\n setOverlayIndex,\n subscribeOverlay,\n} from \"./dev-error-overlay-store.js\";\n\n// Re-export so callers (e.g. the HMR rsc:update handler) can clear the\n// overlay when a new payload lands.\nexport { dismissOverlay } from \"./dev-error-overlay-store.js\";\n\nconst MOUNT_NODE_ID = \"__vinext_dev_error_overlay_root\";\n\nlet reactRoot: Root | null = null;\nlet installed = false;\n\n// Errors React already routed through onCaughtError/onUncaughtError shouldn't\n// also surface from the window listeners — otherwise the same throw appears\n// twice in the dialog (\"Runtime Error\" + \"Unhandled Script Error\"). We track\n// instances we've reported and skip them in the global handlers.\nconst reportedErrors = new WeakSet<object>();\n\nfunction rememberReported(error: unknown): void {\n if (error && typeof error === \"object\") reportedErrors.add(error);\n}\n\nfunction alreadyReported(error: unknown): boolean {\n return !!error && typeof error === \"object\" && reportedErrors.has(error);\n}\n\nexport function installDevErrorOverlay(): void {\n if (installed || typeof window === \"undefined\") return;\n installed = true;\n\n window.addEventListener(\"error\", (event: ErrorEvent) => {\n const err = event.error;\n if (isNavigationSignalError(err)) return;\n if (err instanceof Error) {\n if (alreadyReported(err)) return;\n reportDevError(err, { source: \"window-error\" });\n } else if (event.message) {\n reportDevError(new Error(event.message), { source: \"window-error\" });\n }\n });\n\n window.addEventListener(\"unhandledrejection\", (event: PromiseRejectionEvent) => {\n const reason = event.reason;\n if (isNavigationSignalError(reason)) return;\n if (reason instanceof Error) {\n if (alreadyReported(reason)) return;\n reportDevError(reason, { source: \"unhandledrejection\" });\n } else {\n reportDevError(new Error(String(reason)), { source: \"unhandledrejection\" });\n }\n });\n}\n\nfunction reportDevError(\n error: unknown,\n options: { source: Source; componentStack?: string },\n): void {\n if (typeof window === \"undefined\") return;\n\n rememberReported(error);\n\n const message =\n error instanceof Error\n ? error.message\n : typeof error === \"string\"\n ? error\n : safeStringify(error);\n const stack = error instanceof Error ? error.stack : undefined;\n\n ensureMounted();\n reportToOverlay({\n source: options.source,\n message,\n stack,\n componentStack: options.componentStack,\n });\n}\n\n// React's onCaughtError fires for boundary-caught errors. We log to the console\n// (preserving the default behavior) and surface in the overlay. Sentinel errors\n// (NEXT_NOT_FOUND, NEXT_REDIRECT, etc.) are re-thrown in getDerivedStateFromError\n// before they reach onCaughtError, so they don't appear here in practice.\nexport function devOnCaughtError(\n error: unknown,\n errorInfo: { componentStack?: string; errorBoundary?: unknown },\n): void {\n if (isNavigationSignalError(error)) return;\n\n console.error(error);\n if (errorInfo?.componentStack) {\n console.error(\"The above error occurred in a React component:\\n\" + errorInfo.componentStack);\n }\n reportDevError(error, { source: \"caught\", componentStack: errorInfo?.componentStack });\n}\n\n// Dev variant of onUncaughtError. Surfaces the error in the overlay and stops\n// — we deliberately do NOT perform the prod recovery navigation\n// (window.location.assign) because in dev the overlay is the user-facing\n// recovery; a hard navigation would blow it away along with the rest of the\n// page. HMR or a manual refresh resumes the session once the bug is fixed.\nexport function devOnUncaughtError(\n error: unknown,\n errorInfo: { componentStack?: string; errorBoundary?: unknown },\n): void {\n if (isNavigationSignalError(error)) return;\n\n console.error(error);\n if (errorInfo?.componentStack) {\n console.error(\"The above error occurred in a React component:\\n\" + errorInfo.componentStack);\n }\n reportDevError(error, { source: \"uncaught\", componentStack: errorInfo?.componentStack });\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return Object.prototype.toString.call(value);\n }\n}\n\nfunction ensureMounted(): void {\n if (reactRoot) return;\n const node = document.createElement(\"div\");\n node.id = MOUNT_NODE_ID;\n // Fall back to documentElement in case body hasn't been parsed yet (e.g.\n // an extremely early hydration error firing before the body element is\n // attached). Either parent keeps the overlay outside the React-managed\n // hydrateRoot tree, which is what matters.\n (document.body ?? document.documentElement).appendChild(node);\n reactRoot = createRoot(node);\n reactRoot.render(<DevErrorOverlayApp />);\n}\n\n// ---------------------------------------------------------------------------\n// React component tree\n// ---------------------------------------------------------------------------\n\nconst SOURCE_LABEL: Record<Source, string> = {\n uncaught: \"Unhandled Runtime Error\",\n caught: \"Runtime Error\",\n \"window-error\": \"Unhandled Script Error\",\n unhandledrejection: \"Unhandled Promise Rejection\",\n};\n\nfunction DevErrorOverlayApp(): React.ReactNode {\n const state = useSyncExternalStore<OverlayState>(\n subscribeOverlay,\n getOverlaySnapshot,\n getOverlaySnapshot,\n );\n if (state.errors.length === 0) return null;\n const current = state.errors[state.index] ?? state.errors[0]!;\n\n // Render the stylesheet once at the root so it's not re-injected when\n // toggling between minimized and expanded states.\n return (\n <>\n <style>{overlayStylesheet}</style>\n {state.minimized ? (\n <DevErrorIndicator\n count={state.errors.length}\n source={current.source}\n onExpand={expandOverlay}\n />\n ) : (\n <DevErrorOverlay\n error={current}\n index={state.index}\n total={state.errors.length}\n // setOverlayIndex bounds-checks internally and the prev/next\n // buttons are disabled at the edges, so no clamp needed here.\n onPrev={() => setOverlayIndex(state.index - 1)}\n onNext={() => setOverlayIndex(state.index + 1)}\n onMinimize={minimizeOverlay}\n onDismiss={dismissOverlay}\n />\n )}\n </>\n );\n}\n\nfunction DevErrorIndicator({\n count,\n source,\n onExpand,\n}: {\n count: number;\n source: Source;\n onExpand: () => void;\n}): React.ReactNode {\n return (\n <div style={indicatorContainerStyle}>\n <button\n type=\"button\"\n data-testid=\"vinext-dev-error-indicator\"\n aria-label={`${count} runtime error${count === 1 ? \"\" : \"s\"} — click to expand`}\n title={SOURCE_LABEL[source]}\n onClick={onExpand}\n className=\"vinext-overlay-indicator\"\n >\n <span aria-hidden=\"true\" style={indicatorIconStyle}>\n ⚠\n </span>\n <span data-testid=\"vinext-dev-error-indicator-count\" style={indicatorCountStyle}>\n {count}\n </span>\n </button>\n </div>\n );\n}\n\nfunction DevErrorOverlay({\n error,\n index,\n total,\n onPrev,\n onNext,\n onMinimize,\n onDismiss,\n}: {\n error: ReportedError;\n index: number;\n total: number;\n onPrev: () => void;\n onNext: () => void;\n onMinimize: () => void;\n onDismiss: () => void;\n}): React.ReactNode {\n const frames = error.stack ? parseStack(error.stack) : [];\n\n // Esc minimizes, ←/→ navigate between errors. Esc no longer dismisses\n // outright — once a developer wants the overlay gone they can hit the ×\n // button. Listener is attached on the window so it works regardless of\n // focus location inside the overlay.\n useEffect(() => {\n const onKey = (e: KeyboardEvent): void => {\n if (e.key === \"Escape\") {\n onMinimize();\n } else if (e.key === \"ArrowLeft\" && total > 1) {\n onPrev();\n } else if (e.key === \"ArrowRight\" && total > 1) {\n onNext();\n }\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [onMinimize, onPrev, onNext, total]);\n\n return (\n <div style={backdropStyle} data-testid=\"vinext-dev-error-backdrop\" onClick={onMinimize}>\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={SOURCE_LABEL[error.source]}\n data-testid=\"vinext-dev-error-overlay\"\n style={dialogStyle}\n onClick={(e) => e.stopPropagation()}\n >\n <div style={accentBarStyle} />\n\n <header style={headerStyle}>\n <div style={headerLeftStyle}>\n <span data-testid=\"vinext-dev-error-title\" style={badgeStyle}>\n {SOURCE_LABEL[error.source]}\n </span>\n {total > 1 ? (\n <div data-testid=\"vinext-dev-error-pagination\" style={paginationStyle}>\n <button\n type=\"button\"\n data-testid=\"vinext-dev-error-prev\"\n onClick={onPrev}\n disabled={index === 0}\n className=\"vinext-overlay-nav\"\n aria-label=\"Previous error\"\n >\n ‹\n </button>\n <span data-testid=\"vinext-dev-error-counter\" style={counterStyle}>\n {index + 1} of {total}\n </span>\n <button\n type=\"button\"\n data-testid=\"vinext-dev-error-next\"\n onClick={onNext}\n disabled={index === total - 1}\n className=\"vinext-overlay-nav\"\n aria-label=\"Next error\"\n >\n ›\n </button>\n </div>\n ) : null}\n </div>\n <button\n type=\"button\"\n data-testid=\"vinext-dev-error-minimize\"\n onClick={onMinimize}\n className=\"vinext-overlay-minimize\"\n aria-label=\"Minimize\"\n title=\"Minimize (Esc)\"\n >\n –\n </button>\n <button\n type=\"button\"\n data-testid=\"vinext-dev-error-close\"\n onClick={onDismiss}\n className=\"vinext-overlay-close\"\n aria-label=\"Dismiss\"\n title=\"Dismiss all errors\"\n >\n ×\n </button>\n </header>\n\n <div style={bodyStyle}>\n <h2 data-testid=\"vinext-dev-error-message\" style={messageStyle}>\n {error.message}\n </h2>\n\n {frames.length > 0 ? (\n <ol data-testid=\"vinext-dev-error-stack\" style={stackListStyle}>\n {frames.map((frame) => (\n <li key={frame.key} className=\"vinext-overlay-frame\" style={stackItemStyle}>\n <span style={frameFnStyle}>{frame.fn}</span>\n {frame.file ? (\n <span style={frameLocStyle}>\n {frame.file}\n {frame.line ? `:${frame.line}` : \"\"}\n {frame.col ? `:${frame.col}` : \"\"}\n </span>\n ) : null}\n </li>\n ))}\n </ol>\n ) : null}\n\n {error.componentStack ? (\n <details style={detailsStyle}>\n <summary style={summaryStyle}>Component stack</summary>\n <pre data-testid=\"vinext-dev-error-component-stack\" style={componentStackStyle}>\n {error.componentStack}\n </pre>\n </details>\n ) : null}\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Stack parsing — handles V8 (\" at fn (file:line:col)\") and SpiderMonkey/\n// JavaScriptCore (\"fn@file:line:col\") formats. Lines that don't match either\n// shape are kept verbatim as a function-name-only frame so the overlay still\n// renders something useful in unfamiliar runtimes.\n// ---------------------------------------------------------------------------\n\ntype Frame = { key: string; fn: string; file?: string; line?: string; col?: string };\n\nconst V8_PAREN_FRAME = /^(.*?)\\s*\\((.+):(\\d+):(\\d+)\\)$/;\nconst V8_BARE_FRAME = /^(.+):(\\d+):(\\d+)$/;\nconst MOZ_FRAME = /^(.*?)@(.+):(\\d+):(\\d+)$/;\n\nfunction parseStack(stack: string): Frame[] {\n const frames: Frame[] = [];\n // Suffix repeat occurrences with #2, #3 so React keys stay unique even when\n // the same frame appears multiple times in a recursive stack.\n const seen = new Map<string, number>();\n const pushFrame = (fn: string, file?: string, line?: string, col?: string): void => {\n const base = `${fn}@${file ?? \"\"}:${line ?? \"\"}:${col ?? \"\"}`;\n const count = (seen.get(base) ?? 0) + 1;\n seen.set(base, count);\n const key = count === 1 ? base : `${base}#${count}`;\n frames.push({ key, fn, file, line, col });\n };\n for (const raw of stack.split(\"\\n\")) {\n const line = raw.trim();\n if (!line) continue;\n\n // V8 / Chromium: \" at fn (file:line:col)\" or \" at file:line:col\"\n if (line.startsWith(\"at \")) {\n const body = line.slice(3);\n const parenMatch = body.match(V8_PAREN_FRAME);\n if (parenMatch) {\n pushFrame(parenMatch[1] || \"<anonymous>\", parenMatch[2], parenMatch[3], parenMatch[4]);\n continue;\n }\n const bareMatch = body.match(V8_BARE_FRAME);\n if (bareMatch) {\n pushFrame(\"<anonymous>\", bareMatch[1], bareMatch[2], bareMatch[3]);\n continue;\n }\n pushFrame(body);\n continue;\n }\n\n // SpiderMonkey (Firefox) / JavaScriptCore (Safari): \"fn@file:line:col\".\n // The first line of a Firefox stack is the error message itself; skip it\n // by requiring the @-form match.\n const mozMatch = line.match(MOZ_FRAME);\n if (mozMatch) {\n pushFrame(mozMatch[1] || \"<anonymous>\", mozMatch[2], mozMatch[3], mozMatch[4]);\n continue;\n }\n\n // Unknown shape — preserve the line as a function-name-only frame so the\n // overlay shows something rather than dropping the line silently.\n pushFrame(line);\n }\n return frames;\n}\n\n// ---------------------------------------------------------------------------\n// Inline styles + a tiny stylesheet for hover/focus + entrance animation.\n// Keeping it all in this file means the overlay has no external CSS\n// dependency and works the same way in any host app.\n// ---------------------------------------------------------------------------\n\nconst FONT_STACK =\n \"ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\";\nconst MONO_STACK = \"ui-monospace, SFMono-Regular, Menlo, Consolas, monospace\";\n\nconst overlayStylesheet = `\n@keyframes vinextOverlayBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n@keyframes vinextOverlayDialogIn {\n from { opacity: 0; transform: translateY(8px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n}\n@keyframes vinextOverlayIndicatorIn {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.vinext-overlay-nav {\n background: transparent;\n border: none;\n color: inherit;\n cursor: pointer;\n padding: 2px 8px;\n font-size: 14px;\n line-height: 1;\n border-radius: 6px;\n transition: background 0.12s ease;\n}\n.vinext-overlay-nav:hover:not(:disabled) {\n background: rgba(255, 255, 255, 0.08);\n}\n.vinext-overlay-nav:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n}\n.vinext-overlay-minimize,\n.vinext-overlay-close {\n background: transparent;\n border: none;\n color: #a1a1aa;\n cursor: pointer;\n font-size: 16px;\n line-height: 1;\n padding: 4px 8px;\n border-radius: 6px;\n transition: background 0.12s ease, color 0.12s ease;\n}\n.vinext-overlay-minimize:hover,\n.vinext-overlay-close:hover {\n background: rgba(255, 255, 255, 0.08);\n color: #fafafa;\n}\n.vinext-overlay-close { font-size: 20px; }\n.vinext-overlay-frame {\n padding: 8px 12px;\n border-radius: 6px;\n transition: background 0.12s ease;\n}\n.vinext-overlay-frame:hover {\n background: rgba(255, 255, 255, 0.04);\n}\n.vinext-overlay-indicator {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n border-radius: 999px;\n background: #18181b;\n color: #fafafa;\n border: 1px solid rgba(239, 68, 68, 0.45);\n font: 600 13px ${FONT_STACK};\n cursor: pointer;\n transition: background 0.12s ease, border-color 0.12s ease, transform 0.12s ease;\n animation: vinextOverlayIndicatorIn 0.18s ease-out;\n}\n.vinext-overlay-indicator:hover {\n background: #1f1f23;\n border-color: rgba(239, 68, 68, 0.7);\n transform: translateY(-1px);\n}\n`;\n\nconst backdropStyle: React.CSSProperties = {\n // The backdrop captures click-outside-to-minimize as a proper modal would —\n // a click on it dismisses the overlay rather than reaching the page\n // underneath. The dialog re-enables pointer events for itself via\n // dialogStyle.\n position: \"fixed\",\n inset: 0,\n background: \"rgba(10, 10, 12, 0.55)\",\n backdropFilter: \"blur(3px)\",\n WebkitBackdropFilter: \"blur(3px)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 24,\n zIndex: 2147483646,\n animation: \"vinextOverlayBackdropIn 0.15s ease-out\",\n};\n\nconst dialogStyle: React.CSSProperties = {\n position: \"relative\",\n pointerEvents: \"auto\",\n width: \"min(640px, 100%)\",\n maxHeight: \"min(80vh, 720px)\",\n display: \"flex\",\n flexDirection: \"column\",\n background: \"#0a0a0a\",\n color: \"#fafafa\",\n border: \"1px solid rgba(255, 255, 255, 0.08)\",\n borderRadius: 12,\n fontFamily: FONT_STACK,\n fontSize: 14,\n lineHeight: 1.5,\n overflow: \"hidden\",\n animation: \"vinextOverlayDialogIn 0.18s ease-out\",\n};\n\nconst indicatorContainerStyle: React.CSSProperties = {\n position: \"fixed\",\n bottom: 16,\n left: 16,\n zIndex: 2147483646,\n};\n\nconst indicatorIconStyle: React.CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#ef4444\",\n fontSize: 14,\n};\n\nconst indicatorCountStyle: React.CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minWidth: 18,\n padding: \"0 6px\",\n height: 18,\n borderRadius: 999,\n background: \"rgba(239, 68, 68, 0.18)\",\n color: \"#fca5a5\",\n fontSize: 11,\n fontWeight: 600,\n fontVariantNumeric: \"tabular-nums\",\n};\n\nconst accentBarStyle: React.CSSProperties = {\n height: 3,\n background: \"linear-gradient(90deg, #ef4444 0%, #f97316 100%)\",\n};\n\nconst headerStyle: React.CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: 12,\n padding: \"14px 16px\",\n borderBottom: \"1px solid rgba(255, 255, 255, 0.06)\",\n};\n\nconst headerLeftStyle: React.CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n minWidth: 0,\n};\n\nconst badgeStyle: React.CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n background: \"rgba(239, 68, 68, 0.12)\",\n color: \"#fca5a5\",\n border: \"1px solid rgba(239, 68, 68, 0.25)\",\n padding: \"3px 10px\",\n borderRadius: 999,\n fontSize: 11,\n fontWeight: 600,\n letterSpacing: 0.2,\n textTransform: \"uppercase\",\n whiteSpace: \"nowrap\",\n};\n\nconst paginationStyle: React.CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n gap: 2,\n color: \"#a1a1aa\",\n fontSize: 12,\n};\n\nconst counterStyle: React.CSSProperties = {\n padding: \"0 4px\",\n fontVariantNumeric: \"tabular-nums\",\n};\n\nconst bodyStyle: React.CSSProperties = {\n padding: \"16px 20px 20px\",\n overflow: \"auto\",\n flex: 1,\n};\n\nconst messageStyle: React.CSSProperties = {\n margin: \"0 0 16px 0\",\n fontFamily: MONO_STACK,\n fontSize: 16,\n fontWeight: 500,\n lineHeight: 1.45,\n color: \"#fafafa\",\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n};\n\nconst stackListStyle: React.CSSProperties = {\n listStyle: \"none\",\n margin: 0,\n padding: 0,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 2,\n fontFamily: MONO_STACK,\n fontSize: 12,\n};\n\nconst stackItemStyle: React.CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n gap: 2,\n cursor: \"default\",\n};\n\nconst frameFnStyle: React.CSSProperties = {\n color: \"#fafafa\",\n fontWeight: 500,\n};\n\nconst frameLocStyle: React.CSSProperties = {\n color: \"#71717a\",\n fontSize: 11,\n};\n\nconst detailsStyle: React.CSSProperties = {\n marginTop: 16,\n paddingTop: 12,\n borderTop: \"1px solid rgba(255, 255, 255, 0.06)\",\n color: \"#a1a1aa\",\n fontSize: 12,\n};\n\nconst summaryStyle: React.CSSProperties = {\n cursor: \"pointer\",\n userSelect: \"none\",\n padding: \"4px 0\",\n color: \"#a1a1aa\",\n fontWeight: 500,\n};\n\nconst componentStackStyle: React.CSSProperties = {\n margin: \"8px 0 0 0\",\n fontFamily: MONO_STACK,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n color: \"#a1a1aa\",\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
//#region src/server/dev-lockfile.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Dev server lock file.
|
|
4
|
+
*
|
|
5
|
+
* Writes the running dev server's PID, port, and URL into a lock file at
|
|
6
|
+
* `<root>/.vinext/dev/lock.json`. When a second `vinext dev` process starts in
|
|
7
|
+
* the same project directory, it reads the lock file and either fails with an
|
|
8
|
+
* actionable error or, if the previous process is dead, takes over the lock.
|
|
9
|
+
*
|
|
10
|
+
* This is especially useful for AI coding agents, which frequently attempt to
|
|
11
|
+
* start `vinext dev` without knowing a server is already running.
|
|
12
|
+
*
|
|
13
|
+
* Ported behaviorally from Next.js:
|
|
14
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/build/lockfile.ts
|
|
15
|
+
*
|
|
16
|
+
* Differences vs Next.js:
|
|
17
|
+
* - No native `flock()`. Next.js uses Rust SWC bindings for cross-platform
|
|
18
|
+
* advisory locking; vinext uses a JSON file plus a PID liveness check
|
|
19
|
+
* (`process.kill(pid, 0)`), which is good enough for the dev-server
|
|
20
|
+
* "another server is running" use case. Race conditions on lock acquisition
|
|
21
|
+
* are tolerated: at worst, two dev servers race and one fails to bind a port.
|
|
22
|
+
* - Lock file lives in `<root>/.vinext/dev/lock.json` (mirroring Next.js'
|
|
23
|
+
* `.next/dev/lock` layout). `.vinext/` is already used by the fonts plugin
|
|
24
|
+
* to cache self-hosted Google Fonts, so this re-uses the same project-local
|
|
25
|
+
* state directory rather than polluting `node_modules`.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Information about a running dev server, stored inside the lock file itself.
|
|
29
|
+
*/
|
|
30
|
+
type DevServerInfo = {
|
|
31
|
+
pid: number;
|
|
32
|
+
port: number;
|
|
33
|
+
hostname: string;
|
|
34
|
+
appUrl: string;
|
|
35
|
+
startedAt: number; /** Project directory the server is running in. Used to detect stale entries. */
|
|
36
|
+
cwd: string;
|
|
37
|
+
};
|
|
38
|
+
type DevLockfile = {
|
|
39
|
+
/** Update the lock file contents (e.g. once the port is known after listen). */update(info: DevServerInfo): void; /** Release the lock — deletes the file. Safe to call multiple times. */
|
|
40
|
+
release(): void; /** Absolute path to the lock file. */
|
|
41
|
+
path: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Returns the absolute path to the lock file for a given project root.
|
|
45
|
+
*/
|
|
46
|
+
declare function getLockfilePath(root: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Reads and parses the lock file at the given path. Returns `undefined` if the
|
|
49
|
+
* file doesn't exist or can't be parsed.
|
|
50
|
+
*/
|
|
51
|
+
declare function readLockfile(lockfilePath: string): DevServerInfo | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Returns true if a process with the given PID is running.
|
|
54
|
+
*
|
|
55
|
+
* Uses `process.kill(pid, 0)`, which sends a null signal — it doesn't actually
|
|
56
|
+
* kill the process, it just checks if it exists. Throws `ESRCH` if the process
|
|
57
|
+
* doesn't exist, or `EPERM` if it exists but we don't have permission to
|
|
58
|
+
* signal it (in which case it's still running, just owned by someone else).
|
|
59
|
+
*/
|
|
60
|
+
declare function isPidAlive(pid: number): boolean;
|
|
61
|
+
type FormatErrorOptions = {
|
|
62
|
+
/** Existing server info from the lock file, if readable. */existing: DevServerInfo | undefined; /** Project directory the new (failing) process is trying to run in. */
|
|
63
|
+
cwd: string; /** Path to the lock file. */
|
|
64
|
+
lockfilePath: string;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Format the error message printed when another dev server is already running.
|
|
68
|
+
*
|
|
69
|
+
* Matches Next.js' error layout so AI agents and CLIs can parse the same
|
|
70
|
+
* `- PID: ` / `- Local: ` lines.
|
|
71
|
+
*
|
|
72
|
+
* The `existing: undefined` branch below is defensive — `tryAcquireLockfile`
|
|
73
|
+
* currently only returns `ok: false` with a defined `existing`, but the
|
|
74
|
+
* formatter is exported and unit-tested separately, so it handles both shapes.
|
|
75
|
+
*/
|
|
76
|
+
declare function formatAlreadyRunningError(opts: FormatErrorOptions): string;
|
|
77
|
+
type AcquireOptions = {
|
|
78
|
+
/** Project root. Lock file goes in `<root>/.vinext/dev/lock.json`. */root: string; /** Initial server info to write. Port/URL may be updated later via `update()`. */
|
|
79
|
+
info: DevServerInfo;
|
|
80
|
+
/**
|
|
81
|
+
* If a lock file exists but its PID is dead, take over instead of failing.
|
|
82
|
+
* Defaults to `true`. Set to `false` for testing.
|
|
83
|
+
*/
|
|
84
|
+
takeOverStale?: boolean; /** Register `process.on('exit', release)`. Defaults to `true`. */
|
|
85
|
+
unlockOnExit?: boolean;
|
|
86
|
+
};
|
|
87
|
+
type AcquireSuccess = {
|
|
88
|
+
ok: true;
|
|
89
|
+
lockfile: DevLockfile;
|
|
90
|
+
};
|
|
91
|
+
type AcquireFailure = {
|
|
92
|
+
ok: false; /** The server info from the existing lock file, if readable. */
|
|
93
|
+
existing: DevServerInfo | undefined; /** Absolute path to the lock file. */
|
|
94
|
+
lockfilePath: string;
|
|
95
|
+
};
|
|
96
|
+
type AcquireResult = AcquireSuccess | AcquireFailure;
|
|
97
|
+
/**
|
|
98
|
+
* Try to acquire the dev lock file for the given project root.
|
|
99
|
+
*
|
|
100
|
+
* Returns `{ ok: true, lockfile }` on success — the caller should call
|
|
101
|
+
* `lockfile.release()` on shutdown (or rely on the exit listener registered
|
|
102
|
+
* via `unlockOnExit`).
|
|
103
|
+
*
|
|
104
|
+
* Returns `{ ok: false, existing, lockfilePath }` if another live dev server
|
|
105
|
+
* already holds the lock.
|
|
106
|
+
*/
|
|
107
|
+
declare function tryAcquireLockfile(opts: AcquireOptions): AcquireResult;
|
|
108
|
+
//#endregion
|
|
109
|
+
export { DevLockfile, DevServerInfo, formatAlreadyRunningError, getLockfilePath, isPidAlive, readLockfile, tryAcquireLockfile };
|
|
110
|
+
//# sourceMappingURL=dev-lockfile.d.ts.map
|