vinext 0.0.46 → 0.0.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -6
- package/dist/build/layout-classification.js +3 -1
- package/dist/build/layout-classification.js.map +1 -1
- package/dist/build/prerender.d.ts +2 -1
- package/dist/build/prerender.js +80 -24
- package/dist/build/prerender.js.map +1 -1
- package/dist/build/report.d.ts +9 -5
- package/dist/build/report.js +17 -7
- package/dist/build/report.js.map +1 -1
- package/dist/build/route-classification-injector.d.ts +35 -0
- package/dist/build/route-classification-injector.js +61 -0
- package/dist/build/route-classification-injector.js.map +1 -0
- package/dist/build/route-classification-manifest.d.ts +1 -1
- package/dist/build/run-prerender.d.ts +5 -0
- package/dist/build/run-prerender.js +4 -1
- package/dist/build/run-prerender.js.map +1 -1
- package/dist/build/server-manifest.js +2 -7
- package/dist/build/server-manifest.js.map +1 -1
- package/dist/build/standalone.js +3 -5
- package/dist/build/standalone.js.map +1 -1
- package/dist/build/static-export.d.ts +1 -1
- package/dist/check.js +45 -29
- package/dist/check.js.map +1 -1
- package/dist/cli-args.d.ts +33 -0
- package/dist/cli-args.js +121 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli.js +11 -20
- package/dist/cli.js.map +1 -1
- package/dist/cloudflare/kv-cache-handler.js +29 -9
- package/dist/cloudflare/kv-cache-handler.js.map +1 -1
- package/dist/config/config-matchers.js +46 -37
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/config/next-config.d.ts +4 -2
- package/dist/config/next-config.js +3 -0
- package/dist/config/next-config.js.map +1 -1
- package/dist/deploy.d.ts +18 -2
- package/dist/deploy.js +47 -4
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-rsc-entry.d.ts +4 -3
- package/dist/entries/app-rsc-entry.js +379 -858
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.d.ts +1 -1
- package/dist/entries/app-rsc-manifest.js +6 -1
- package/dist/entries/app-rsc-manifest.js.map +1 -1
- package/dist/entries/pages-client-entry.js +3 -2
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-server-entry.js +19 -61
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.d.ts +12 -3
- package/dist/entries/runtime-entry-module.js +15 -4
- package/dist/entries/runtime-entry-module.js.map +1 -1
- package/dist/index.js +40 -58
- package/dist/index.js.map +1 -1
- package/dist/plugins/fonts.js +54 -32
- package/dist/plugins/fonts.js.map +1 -1
- package/dist/plugins/og-assets.js +15 -16
- package/dist/plugins/og-assets.js.map +1 -1
- package/dist/plugins/rsc-client-shim-excludes.d.ts +2 -1
- package/dist/plugins/rsc-client-shim-excludes.js +11 -1
- package/dist/plugins/rsc-client-shim-excludes.js.map +1 -1
- package/dist/routing/app-route-graph.d.ts +195 -0
- package/dist/routing/app-route-graph.js +1022 -0
- package/dist/routing/app-route-graph.js.map +1 -0
- package/dist/routing/app-router.d.ts +14 -88
- package/dist/routing/app-router.js +21 -712
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/file-matcher.d.ts +3 -1
- package/dist/routing/file-matcher.js +6 -1
- package/dist/routing/file-matcher.js.map +1 -1
- package/dist/routing/pages-router.js +10 -19
- package/dist/routing/pages-router.js.map +1 -1
- package/dist/routing/route-matching.d.ts +28 -0
- package/dist/routing/route-matching.js +44 -0
- package/dist/routing/route-matching.js.map +1 -0
- package/dist/routing/route-pattern.js +4 -1
- package/dist/routing/route-pattern.js.map +1 -1
- package/dist/routing/route-trie.d.ts +8 -0
- package/dist/routing/route-trie.js +12 -1
- package/dist/routing/route-trie.js.map +1 -1
- package/dist/routing/route-validation.js +3 -4
- package/dist/routing/route-validation.js.map +1 -1
- package/dist/routing/utils.d.ts +8 -1
- package/dist/routing/utils.js +25 -2
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/app-browser-entry.js +145 -294
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-error.d.ts +3 -4
- package/dist/server/app-browser-error.js +8 -4
- package/dist/server/app-browser-error.js.map +1 -1
- package/dist/server/app-browser-navigation-controller.d.ts +75 -0
- package/dist/server/app-browser-navigation-controller.js +290 -0
- package/dist/server/app-browser-navigation-controller.js.map +1 -0
- package/dist/server/app-browser-state.d.ts +33 -15
- package/dist/server/app-browser-state.js +52 -59
- package/dist/server/app-browser-state.js.map +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +68 -0
- package/dist/server/app-browser-visible-commit.js +182 -0
- package/dist/server/app-browser-visible-commit.js.map +1 -0
- package/dist/server/app-client-reference-preloader.d.ts +15 -0
- package/dist/server/app-client-reference-preloader.js +46 -0
- package/dist/server/app-client-reference-preloader.js.map +1 -0
- package/dist/server/app-elements-wire.d.ts +130 -0
- package/dist/server/app-elements-wire.js +205 -0
- package/dist/server/app-elements-wire.js.map +1 -0
- package/dist/server/app-elements.d.ts +2 -84
- package/dist/server/app-elements.js +4 -107
- package/dist/server/app-elements.js.map +1 -1
- package/dist/server/app-fallback-renderer.d.ts +57 -0
- package/dist/server/app-fallback-renderer.js +79 -0
- package/dist/server/app-fallback-renderer.js.map +1 -0
- package/dist/server/app-hook-warning-suppression.d.ts +7 -0
- package/dist/server/app-hook-warning-suppression.js +12 -0
- package/dist/server/app-hook-warning-suppression.js.map +1 -0
- package/dist/server/app-middleware.d.ts +2 -1
- package/dist/server/app-middleware.js +34 -11
- package/dist/server/app-middleware.js.map +1 -1
- package/dist/server/app-mounted-slots-header.d.ts +17 -0
- package/dist/server/app-mounted-slots-header.js +21 -0
- package/dist/server/app-mounted-slots-header.js.map +1 -0
- package/dist/server/app-page-boundary-render.d.ts +3 -3
- package/dist/server/app-page-boundary-render.js +8 -5
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-boundary.js +2 -1
- package/dist/server/app-page-boundary.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +19 -4
- package/dist/server/app-page-cache.js +60 -22
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-dispatch.d.ts +9 -5
- package/dist/server/app-page-dispatch.js +41 -17
- package/dist/server/app-page-dispatch.js.map +1 -1
- package/dist/server/app-page-element-builder.d.ts +61 -0
- package/dist/server/app-page-element-builder.js +142 -0
- package/dist/server/app-page-element-builder.js.map +1 -0
- package/dist/server/app-page-execution.d.ts +23 -5
- package/dist/server/app-page-execution.js +39 -24
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-head.js +2 -1
- package/dist/server/app-page-head.js.map +1 -1
- package/dist/server/app-page-method.js +2 -5
- package/dist/server/app-page-method.js.map +1 -1
- package/dist/server/app-page-params.d.ts +2 -1
- package/dist/server/app-page-params.js +3 -3
- package/dist/server/app-page-params.js.map +1 -1
- package/dist/server/app-page-probe.d.ts +1 -1
- package/dist/server/app-page-probe.js +5 -1
- package/dist/server/app-page-probe.js.map +1 -1
- package/dist/server/app-page-render.d.ts +6 -2
- package/dist/server/app-page-render.js +118 -30
- package/dist/server/app-page-render.js.map +1 -1
- package/dist/server/app-page-request.d.ts +19 -5
- package/dist/server/app-page-request.js +49 -7
- package/dist/server/app-page-request.js.map +1 -1
- package/dist/server/app-page-response.d.ts +1 -0
- package/dist/server/app-page-response.js +6 -9
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +20 -4
- package/dist/server/app-page-route-wiring.js +15 -12
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-page-stream.d.ts +7 -0
- package/dist/server/app-page-stream.js +9 -2
- package/dist/server/app-page-stream.js.map +1 -1
- package/dist/server/app-post-middleware-context.d.ts +16 -0
- package/dist/server/app-post-middleware-context.js +28 -0
- package/dist/server/app-post-middleware-context.js.map +1 -0
- package/dist/server/app-prerender-endpoints.js +3 -2
- package/dist/server/app-prerender-endpoints.js.map +1 -1
- package/dist/server/app-request-context.d.ts +22 -0
- package/dist/server/app-request-context.js +30 -0
- package/dist/server/app-request-context.js.map +1 -0
- package/dist/server/app-route-handler-cache.d.ts +1 -0
- package/dist/server/app-route-handler-cache.js +7 -2
- package/dist/server/app-route-handler-cache.js.map +1 -1
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +8 -5
- package/dist/server/app-route-handler-dispatch.js.map +1 -1
- package/dist/server/app-route-handler-execution.d.ts +2 -1
- package/dist/server/app-route-handler-execution.js +2 -2
- package/dist/server/app-route-handler-execution.js.map +1 -1
- package/dist/server/app-route-handler-policy.js +13 -13
- package/dist/server/app-route-handler-policy.js.map +1 -1
- package/dist/server/app-route-handler-response.d.ts +4 -2
- package/dist/server/app-route-handler-response.js +9 -7
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-route-handler-runtime.d.ts +9 -1
- package/dist/server/app-route-handler-runtime.js +11 -1
- package/dist/server/app-route-handler-runtime.js.map +1 -1
- package/dist/server/app-router-entry.js +9 -4
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +34 -0
- package/dist/server/app-rsc-cache-busting.js +137 -0
- package/dist/server/app-rsc-cache-busting.js.map +1 -0
- package/dist/server/app-rsc-error-handler.d.ts +21 -0
- package/dist/server/app-rsc-error-handler.js +30 -0
- package/dist/server/app-rsc-error-handler.js.map +1 -0
- package/dist/server/app-rsc-handler.d.ts +117 -0
- package/dist/server/app-rsc-handler.js +271 -0
- package/dist/server/app-rsc-handler.js.map +1 -0
- package/dist/server/app-rsc-request-normalization.d.ts +42 -0
- package/dist/server/app-rsc-request-normalization.js +67 -0
- package/dist/server/app-rsc-request-normalization.js.map +1 -0
- package/dist/server/app-rsc-response-finalizer.d.ts +30 -0
- package/dist/server/app-rsc-response-finalizer.js +38 -0
- package/dist/server/app-rsc-response-finalizer.js.map +1 -0
- package/dist/server/app-rsc-route-matching.js +8 -4
- package/dist/server/app-rsc-route-matching.js.map +1 -1
- package/dist/server/app-segment-config.d.ts +33 -0
- package/dist/server/app-segment-config.js +90 -0
- package/dist/server/app-segment-config.js.map +1 -0
- package/dist/server/app-server-action-execution.d.ts +2 -0
- package/dist/server/app-server-action-execution.js +45 -51
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/app-ssr-entry.js +21 -20
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/artifact-compatibility.d.ts +44 -0
- package/dist/server/artifact-compatibility.js +82 -0
- package/dist/server/artifact-compatibility.js.map +1 -0
- package/dist/server/cache-control.d.ts +24 -0
- package/dist/server/cache-control.js +33 -0
- package/dist/server/cache-control.js.map +1 -0
- package/dist/server/cache-proof.d.ts +200 -0
- package/dist/server/cache-proof.js +342 -0
- package/dist/server/cache-proof.js.map +1 -0
- package/dist/server/dev-error-overlay-store.d.ts +23 -0
- package/dist/server/dev-error-overlay-store.js +67 -0
- package/dist/server/dev-error-overlay-store.js.map +1 -0
- package/dist/server/dev-error-overlay.d.ts +15 -0
- package/dist/server/dev-error-overlay.js +548 -0
- package/dist/server/dev-error-overlay.js.map +1 -0
- package/dist/server/dev-origin-check.js +8 -4
- package/dist/server/dev-origin-check.js.map +1 -1
- package/dist/server/dev-server.js +1 -6
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/http-error-responses.d.ts +67 -0
- package/dist/server/http-error-responses.js +77 -0
- package/dist/server/http-error-responses.js.map +1 -0
- package/dist/server/image-optimization.js +2 -1
- package/dist/server/image-optimization.js.map +1 -1
- package/dist/server/instrumentation-runtime.d.ts +44 -0
- package/dist/server/instrumentation-runtime.js +29 -0
- package/dist/server/instrumentation-runtime.js.map +1 -0
- package/dist/server/isr-cache.d.ts +2 -7
- package/dist/server/isr-cache.js +7 -10
- package/dist/server/isr-cache.js.map +1 -1
- package/dist/server/metadata-route-response.js +6 -5
- package/dist/server/metadata-route-response.js.map +1 -1
- package/dist/server/metadata-routes.d.ts +1 -0
- package/dist/server/metadata-routes.js +6 -0
- package/dist/server/metadata-routes.js.map +1 -1
- package/dist/server/middleware-matcher.js +2 -2
- package/dist/server/middleware-matcher.js.map +1 -1
- package/dist/server/middleware-response-headers.js +21 -0
- package/dist/server/middleware-response-headers.js.map +1 -1
- package/dist/server/middleware-runtime.js +3 -3
- package/dist/server/middleware-runtime.js.map +1 -1
- package/dist/server/navigation-trace.d.ts +33 -0
- package/dist/server/navigation-trace.js +35 -0
- package/dist/server/navigation-trace.js.map +1 -0
- package/dist/server/next-error-digest.d.ts +44 -0
- package/dist/server/next-error-digest.js +40 -0
- package/dist/server/next-error-digest.js.map +1 -0
- package/dist/server/pages-api-route.js +2 -1
- package/dist/server/pages-api-route.js.map +1 -1
- package/dist/server/pages-node-compat.js +4 -16
- package/dist/server/pages-node-compat.js.map +1 -1
- package/dist/server/pages-page-data.d.ts +2 -1
- package/dist/server/pages-page-data.js +6 -5
- package/dist/server/pages-page-data.js.map +1 -1
- package/dist/server/pages-page-response.d.ts +3 -8
- package/dist/server/pages-page-response.js +46 -15
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/prod-server.d.ts +6 -0
- package/dist/server/prod-server.js +28 -21
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +42 -1
- package/dist/server/request-pipeline.js +97 -17
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/server/rsc-stream-hints.d.ts +3 -1
- package/dist/server/rsc-stream-hints.js +4 -1
- package/dist/server/rsc-stream-hints.js.map +1 -1
- package/dist/server/seed-cache.js +19 -8
- package/dist/server/seed-cache.js.map +1 -1
- package/dist/shims/cache-runtime.d.ts +2 -2
- package/dist/shims/cache-runtime.js +31 -17
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.d.ts +15 -3
- package/dist/shims/cache.js +45 -20
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/error-boundary.d.ts +17 -1
- package/dist/shims/error-boundary.js +31 -1
- package/dist/shims/error-boundary.js.map +1 -1
- package/dist/shims/fetch-cache.d.ts +4 -1
- package/dist/shims/fetch-cache.js +57 -16
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/head-state.js +2 -3
- package/dist/shims/head-state.js.map +1 -1
- package/dist/shims/headers.js +4 -44
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/i18n-state.js +2 -3
- package/dist/shims/i18n-state.js.map +1 -1
- package/dist/shims/image.js +93 -5
- package/dist/shims/image.js.map +1 -1
- package/dist/shims/internal/als-registry.d.ts +15 -0
- package/dist/shims/internal/als-registry.js +55 -0
- package/dist/shims/internal/als-registry.js.map +1 -0
- package/dist/shims/internal/cookie-serialize.d.ts +46 -0
- package/dist/shims/internal/cookie-serialize.js +51 -0
- package/dist/shims/internal/cookie-serialize.js.map +1 -0
- package/dist/shims/link.js +31 -26
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +26 -1
- package/dist/shims/metadata.js +94 -4
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation-state.js +2 -3
- package/dist/shims/navigation-state.js.map +1 -1
- package/dist/shims/navigation.d.ts +2 -7
- package/dist/shims/navigation.js +44 -36
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/request-context.js +2 -4
- package/dist/shims/request-context.js.map +1 -1
- package/dist/shims/request-state-types.d.ts +1 -1
- package/dist/shims/router-state.js +2 -3
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/router.js +2 -2
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/server.js +5 -30
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/slot.d.ts +1 -1
- package/dist/shims/slot.js +5 -4
- package/dist/shims/slot.js.map +1 -1
- package/dist/shims/thenable-params.d.ts +5 -2
- package/dist/shims/thenable-params.js +26 -6
- package/dist/shims/thenable-params.js.map +1 -1
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +3 -14
- package/dist/shims/unified-request-context.js.map +1 -1
- package/dist/shims/use-merged-ref.d.ts +7 -0
- package/dist/shims/use-merged-ref.js +40 -0
- package/dist/shims/use-merged-ref.js.map +1 -0
- package/dist/utils/base-path.d.ts +7 -1
- package/dist/utils/base-path.js +12 -1
- package/dist/utils/base-path.js.map +1 -1
- package/dist/utils/cache-control-metadata.d.ts +6 -0
- package/dist/utils/cache-control-metadata.js +16 -0
- package/dist/utils/cache-control-metadata.js.map +1 -0
- package/dist/utils/safe-json-file.d.ts +18 -0
- package/dist/utils/safe-json-file.js +25 -0
- package/dist/utils/safe-json-file.js.map +1 -0
- package/dist/utils/text-stream.d.ts +29 -0
- package/dist/utils/text-stream.js +66 -0
- package/dist/utils/text-stream.js.map +1 -0
- package/package.json +5 -5
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import { fnv1a64 } from "../utils/hash.js";
|
|
2
|
+
//#region src/server/cache-proof.ts
|
|
3
|
+
const CACHE_PROOF_MODEL_SCHEMA_VERSION = 0;
|
|
4
|
+
const DEFAULT_CACHE_VARIANT_BUDGET = {
|
|
5
|
+
maxDimensionCount: 8,
|
|
6
|
+
maxDimensionNameLength: 64,
|
|
7
|
+
maxDimensionValueLength: 256,
|
|
8
|
+
maxEncodedLength: 1024,
|
|
9
|
+
maxValuesPerDimension: 8,
|
|
10
|
+
maxVariantsPerRoute: 64
|
|
11
|
+
};
|
|
12
|
+
const PUBLIC_UNSAFE_DIMENSION_SOURCES = new Set([
|
|
13
|
+
"auth",
|
|
14
|
+
"cookie",
|
|
15
|
+
"draft-mode",
|
|
16
|
+
"header",
|
|
17
|
+
"session"
|
|
18
|
+
]);
|
|
19
|
+
function buildBreakerFallback(code, fields = {}, mode = "renderFresh", scope = "affectedOutput") {
|
|
20
|
+
return {
|
|
21
|
+
kind: "breakerFallback",
|
|
22
|
+
code,
|
|
23
|
+
mode,
|
|
24
|
+
scope,
|
|
25
|
+
fields
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function sortedUnique(values) {
|
|
29
|
+
return [...new Set(values)].sort();
|
|
30
|
+
}
|
|
31
|
+
function normalizeDimensionName(name) {
|
|
32
|
+
return name.trim().toLowerCase();
|
|
33
|
+
}
|
|
34
|
+
function redactValue(value) {
|
|
35
|
+
return `h:${fnv1a64(value)}`;
|
|
36
|
+
}
|
|
37
|
+
function sortedUniqueRedacted(values) {
|
|
38
|
+
return sortedUnique(sortedUnique(values).map(redactValue));
|
|
39
|
+
}
|
|
40
|
+
function encodeParts(parts) {
|
|
41
|
+
return JSON.stringify(parts);
|
|
42
|
+
}
|
|
43
|
+
function compareDimensions(a, b) {
|
|
44
|
+
return a.source.localeCompare(b.source) || a.name.localeCompare(b.name) || a.privacy.localeCompare(b.privacy);
|
|
45
|
+
}
|
|
46
|
+
function encodeNullable(value) {
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
function assertNever(value) {
|
|
50
|
+
throw new Error(`Unhandled cache proof variant: ${String(value)}`);
|
|
51
|
+
}
|
|
52
|
+
function encodeOutputScope(output) {
|
|
53
|
+
switch (output.kind) {
|
|
54
|
+
case "app-html": return encodeParts([
|
|
55
|
+
output.kind,
|
|
56
|
+
output.routeId,
|
|
57
|
+
encodeNullable(output.rootBoundaryId),
|
|
58
|
+
encodeNullable(output.renderEpoch)
|
|
59
|
+
]);
|
|
60
|
+
case "app-rsc": return encodeParts([
|
|
61
|
+
output.kind,
|
|
62
|
+
output.routeId,
|
|
63
|
+
encodeNullable(output.rootBoundaryId),
|
|
64
|
+
encodeNullable(output.renderEpoch),
|
|
65
|
+
encodeNullable(output.mountedSlotsFingerprint)
|
|
66
|
+
]);
|
|
67
|
+
case "layout": return encodeParts([
|
|
68
|
+
output.kind,
|
|
69
|
+
output.routeId,
|
|
70
|
+
output.layoutId,
|
|
71
|
+
encodeNullable(output.rootBoundaryId)
|
|
72
|
+
]);
|
|
73
|
+
case "page": return encodeParts([
|
|
74
|
+
output.kind,
|
|
75
|
+
output.routeId,
|
|
76
|
+
output.pageId,
|
|
77
|
+
encodeNullable(output.rootBoundaryId)
|
|
78
|
+
]);
|
|
79
|
+
case "route-handler": return encodeParts([
|
|
80
|
+
output.kind,
|
|
81
|
+
output.routeId,
|
|
82
|
+
output.routeHandlerId
|
|
83
|
+
]);
|
|
84
|
+
case "slot": return encodeParts([
|
|
85
|
+
output.kind,
|
|
86
|
+
output.routeId,
|
|
87
|
+
output.slotId,
|
|
88
|
+
encodeNullable(output.rootBoundaryId)
|
|
89
|
+
]);
|
|
90
|
+
case "template": return encodeParts([
|
|
91
|
+
output.kind,
|
|
92
|
+
output.routeId,
|
|
93
|
+
output.templateId,
|
|
94
|
+
encodeNullable(output.rootBoundaryId)
|
|
95
|
+
]);
|
|
96
|
+
default: return assertNever(output);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function validateBudgetNumber(name, value) {
|
|
100
|
+
if (Number.isInteger(value) && value >= 0) return null;
|
|
101
|
+
return buildBreakerFallback("CP_INVALID_VARIANT_BUDGET", { budgetField: name });
|
|
102
|
+
}
|
|
103
|
+
function validateBudget(budget) {
|
|
104
|
+
return validateBudgetNumber("maxDimensionCount", budget.maxDimensionCount) ?? validateBudgetNumber("maxDimensionNameLength", budget.maxDimensionNameLength) ?? validateBudgetNumber("maxDimensionValueLength", budget.maxDimensionValueLength) ?? validateBudgetNumber("maxEncodedLength", budget.maxEncodedLength) ?? validateBudgetNumber("maxValuesPerDimension", budget.maxValuesPerDimension) ?? validateBudgetNumber("maxVariantsPerRoute", budget.maxVariantsPerRoute);
|
|
105
|
+
}
|
|
106
|
+
function buildDimension(input, budget) {
|
|
107
|
+
const name = normalizeDimensionName(input.name);
|
|
108
|
+
if (name.length === 0) return buildBreakerFallback("CP_DIMENSION_NAME_MISSING", { source: input.source });
|
|
109
|
+
if (name.length > budget.maxDimensionNameLength) return buildBreakerFallback("CP_DIMENSION_NAME_TOO_LONG", {
|
|
110
|
+
maxLength: budget.maxDimensionNameLength,
|
|
111
|
+
nameHash: redactValue(name),
|
|
112
|
+
source: input.source
|
|
113
|
+
});
|
|
114
|
+
if (input.privacy === "public" && PUBLIC_UNSAFE_DIMENSION_SOURCES.has(input.source)) return buildBreakerFallback("CP_UNSAFE_PUBLIC_DIMENSION", {
|
|
115
|
+
name,
|
|
116
|
+
source: input.source
|
|
117
|
+
}, "privateUncacheable");
|
|
118
|
+
const values = sortedUnique(input.values);
|
|
119
|
+
if (values.length === 0) return buildBreakerFallback("CP_DIMENSION_VALUES_MISSING", {
|
|
120
|
+
name,
|
|
121
|
+
source: input.source
|
|
122
|
+
});
|
|
123
|
+
if (values.length > budget.maxValuesPerDimension) return buildBreakerFallback("CP_DIMENSION_VALUE_COUNT_EXCEEDED", {
|
|
124
|
+
maxValues: budget.maxValuesPerDimension,
|
|
125
|
+
name,
|
|
126
|
+
source: input.source,
|
|
127
|
+
valueCount: values.length
|
|
128
|
+
});
|
|
129
|
+
for (const value of values) if (value.length > budget.maxDimensionValueLength) return buildBreakerFallback("CP_DIMENSION_VALUE_TOO_LONG", {
|
|
130
|
+
maxLength: budget.maxDimensionValueLength,
|
|
131
|
+
name,
|
|
132
|
+
source: input.source,
|
|
133
|
+
valueHash: redactValue(value)
|
|
134
|
+
});
|
|
135
|
+
const valueHashes = values.map(redactValue);
|
|
136
|
+
return {
|
|
137
|
+
encoded: encodeParts([
|
|
138
|
+
input.source,
|
|
139
|
+
input.privacy,
|
|
140
|
+
name,
|
|
141
|
+
valueHashes
|
|
142
|
+
]),
|
|
143
|
+
name,
|
|
144
|
+
privacy: input.privacy,
|
|
145
|
+
source: input.source,
|
|
146
|
+
valueCount: valueHashes.length,
|
|
147
|
+
valueHashes
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function isCacheProofBreakerFallback(value) {
|
|
151
|
+
return "code" in value;
|
|
152
|
+
}
|
|
153
|
+
function getDimensionBucket(bySource, source, privacy) {
|
|
154
|
+
const existingByPrivacy = bySource.get(source);
|
|
155
|
+
const byPrivacy = existingByPrivacy ?? /* @__PURE__ */ new Map();
|
|
156
|
+
if (!existingByPrivacy) bySource.set(source, byPrivacy);
|
|
157
|
+
const existingByName = byPrivacy.get(privacy);
|
|
158
|
+
const byName = existingByName ?? /* @__PURE__ */ new Map();
|
|
159
|
+
if (!existingByName) byPrivacy.set(privacy, byName);
|
|
160
|
+
return byName;
|
|
161
|
+
}
|
|
162
|
+
function mergeDimensionInputs(dimensions) {
|
|
163
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
164
|
+
const orderedDimensions = [];
|
|
165
|
+
for (const dimension of dimensions) {
|
|
166
|
+
const name = normalizeDimensionName(dimension.name);
|
|
167
|
+
const bucket = getDimensionBucket(bySource, dimension.source, dimension.privacy);
|
|
168
|
+
const existing = bucket.get(name);
|
|
169
|
+
if (existing) {
|
|
170
|
+
existing.values.push(...dimension.values);
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
const accumulator = {
|
|
174
|
+
name,
|
|
175
|
+
privacy: dimension.privacy,
|
|
176
|
+
source: dimension.source,
|
|
177
|
+
values: [...dimension.values]
|
|
178
|
+
};
|
|
179
|
+
bucket.set(name, accumulator);
|
|
180
|
+
orderedDimensions.push(accumulator);
|
|
181
|
+
}
|
|
182
|
+
return orderedDimensions;
|
|
183
|
+
}
|
|
184
|
+
function createAppRouteCacheProofGraphScope(route) {
|
|
185
|
+
return {
|
|
186
|
+
routeId: route.ids.route,
|
|
187
|
+
pageId: route.ids.page,
|
|
188
|
+
routeHandlerId: route.ids.routeHandler,
|
|
189
|
+
layoutIds: [...route.ids.layouts],
|
|
190
|
+
templateIds: [...route.ids.templates],
|
|
191
|
+
slotIds: sortedUnique(Object.values(route.ids.slots))
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function buildCacheVariant(input) {
|
|
195
|
+
const budgetFallback = validateBudget(input.budget);
|
|
196
|
+
if (budgetFallback) return {
|
|
197
|
+
kind: "breakerFallback",
|
|
198
|
+
fallback: budgetFallback
|
|
199
|
+
};
|
|
200
|
+
if (input.existingVariantCount >= input.budget.maxVariantsPerRoute) return {
|
|
201
|
+
kind: "breakerFallback",
|
|
202
|
+
fallback: buildBreakerFallback("CP_ROUTE_VARIANT_CEILING_EXCEEDED", {
|
|
203
|
+
existingVariantCount: input.existingVariantCount,
|
|
204
|
+
maxVariantsPerRoute: input.budget.maxVariantsPerRoute,
|
|
205
|
+
routeId: input.output.routeId
|
|
206
|
+
}, "privateUncacheable", "route")
|
|
207
|
+
};
|
|
208
|
+
const dimensionInputs = mergeDimensionInputs(input.dimensions);
|
|
209
|
+
if (dimensionInputs.length > input.budget.maxDimensionCount) return {
|
|
210
|
+
kind: "breakerFallback",
|
|
211
|
+
fallback: buildBreakerFallback("CP_DIMENSION_COUNT_EXCEEDED", {
|
|
212
|
+
dimensionCount: dimensionInputs.length,
|
|
213
|
+
maxDimensionCount: input.budget.maxDimensionCount,
|
|
214
|
+
routeId: input.output.routeId
|
|
215
|
+
})
|
|
216
|
+
};
|
|
217
|
+
const dimensions = [];
|
|
218
|
+
for (const dimensionInput of dimensionInputs) {
|
|
219
|
+
const dimension = buildDimension(dimensionInput, input.budget);
|
|
220
|
+
if (isCacheProofBreakerFallback(dimension)) return {
|
|
221
|
+
kind: "breakerFallback",
|
|
222
|
+
fallback: dimension
|
|
223
|
+
};
|
|
224
|
+
dimensions.push(dimension);
|
|
225
|
+
}
|
|
226
|
+
dimensions.sort(compareDimensions);
|
|
227
|
+
const encoded = [
|
|
228
|
+
`schema:0`,
|
|
229
|
+
encodeOutputScope(input.output),
|
|
230
|
+
...dimensions.map((dimension) => dimension.encoded)
|
|
231
|
+
].join("|");
|
|
232
|
+
if (encoded.length > input.budget.maxEncodedLength) return {
|
|
233
|
+
kind: "breakerFallback",
|
|
234
|
+
fallback: buildBreakerFallback("CP_ENCODED_VARIANT_TOO_LONG", {
|
|
235
|
+
encodedHash: redactValue(encoded),
|
|
236
|
+
encodedLength: encoded.length,
|
|
237
|
+
maxEncodedLength: input.budget.maxEncodedLength,
|
|
238
|
+
routeId: input.output.routeId
|
|
239
|
+
})
|
|
240
|
+
};
|
|
241
|
+
return {
|
|
242
|
+
kind: "variant",
|
|
243
|
+
variant: {
|
|
244
|
+
schemaVersion: 0,
|
|
245
|
+
cacheKey: `cp0:${fnv1a64(encoded)}`,
|
|
246
|
+
output: input.output,
|
|
247
|
+
dimensions,
|
|
248
|
+
encodedLength: encoded.length,
|
|
249
|
+
budget: { ...input.budget }
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function boundaryOutcomesMatch(expected, candidate) {
|
|
254
|
+
switch (expected.kind) {
|
|
255
|
+
case "error": return candidate.kind === "error" && (expected.digest ?? "") === (candidate.digest ?? "");
|
|
256
|
+
case "forbidden": return candidate.kind === "forbidden";
|
|
257
|
+
case "globalError": return candidate.kind === "globalError" && (expected.digest ?? "") === (candidate.digest ?? "");
|
|
258
|
+
case "notFound": return candidate.kind === "notFound";
|
|
259
|
+
case "redirect": return candidate.kind === "redirect" && expected.status === candidate.status && expected.location === candidate.location;
|
|
260
|
+
case "success": return candidate.kind === "success";
|
|
261
|
+
case "unauthorized": return candidate.kind === "unauthorized";
|
|
262
|
+
case "unknown": return false;
|
|
263
|
+
default: return assertNever(expected);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
function buildBoundaryOutcomeCompatibility(input) {
|
|
267
|
+
if (input.expected.kind === "unknown" || input.candidate.kind === "unknown") return {
|
|
268
|
+
kind: "incompatible",
|
|
269
|
+
expected: input.expected,
|
|
270
|
+
candidate: input.candidate,
|
|
271
|
+
fallback: buildBreakerFallback("CP_BOUNDARY_OUTCOME_UNKNOWN", {
|
|
272
|
+
candidateKind: input.candidate.kind,
|
|
273
|
+
expectedKind: input.expected.kind
|
|
274
|
+
})
|
|
275
|
+
};
|
|
276
|
+
if (boundaryOutcomesMatch(input.expected, input.candidate)) return {
|
|
277
|
+
kind: "compatible",
|
|
278
|
+
outcome: input.candidate,
|
|
279
|
+
reason: "CP_BOUNDARY_OUTCOME_MATCH"
|
|
280
|
+
};
|
|
281
|
+
return {
|
|
282
|
+
kind: "incompatible",
|
|
283
|
+
expected: input.expected,
|
|
284
|
+
candidate: input.candidate,
|
|
285
|
+
fallback: buildBreakerFallback("CP_BOUNDARY_OUTCOME_MISMATCH", {
|
|
286
|
+
candidateKind: input.candidate.kind,
|
|
287
|
+
expectedKind: input.expected.kind
|
|
288
|
+
})
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
function requestApiStatusRank(status) {
|
|
292
|
+
switch (status) {
|
|
293
|
+
case "notObserved": return 0;
|
|
294
|
+
case "unknown": return 1;
|
|
295
|
+
case "observed": return 2;
|
|
296
|
+
default: return assertNever(status);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
function normalizeRequestApiObservations(observations) {
|
|
300
|
+
const byKind = /* @__PURE__ */ new Map();
|
|
301
|
+
for (const observation of observations) {
|
|
302
|
+
const current = byKind.get(observation.kind);
|
|
303
|
+
if (current === void 0 || requestApiStatusRank(observation.status) > requestApiStatusRank(current)) byKind.set(observation.kind, observation.status);
|
|
304
|
+
}
|
|
305
|
+
return [...byKind.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([kind, status]) => ({
|
|
306
|
+
kind,
|
|
307
|
+
status
|
|
308
|
+
}));
|
|
309
|
+
}
|
|
310
|
+
function buildRenderObservation(input) {
|
|
311
|
+
return {
|
|
312
|
+
schemaVersion: 0,
|
|
313
|
+
output: input.output,
|
|
314
|
+
completeness: input.completeness,
|
|
315
|
+
boundaryOutcome: input.boundaryOutcome,
|
|
316
|
+
requestApis: normalizeRequestApiObservations(input.requestApis),
|
|
317
|
+
dynamicFetches: sortedUniqueRedacted(input.dynamicFetches),
|
|
318
|
+
cacheTags: sortedUnique(input.cacheTags),
|
|
319
|
+
pathTags: sortedUnique(input.pathTags),
|
|
320
|
+
cacheability: input.cacheability
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
function hasCompleteNegativeRequestApiProof(observation, requiredApis) {
|
|
324
|
+
if (observation.completeness !== "complete") return false;
|
|
325
|
+
const statuses = /* @__PURE__ */ new Map();
|
|
326
|
+
for (const requestApi of observation.requestApis) statuses.set(requestApi.kind, requestApi.status);
|
|
327
|
+
for (const api of requiredApis) if (statuses.get(api) !== "notObserved") return false;
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
function createDisabledCacheProofDecision(input) {
|
|
331
|
+
return {
|
|
332
|
+
kind: "disabled",
|
|
333
|
+
canReuse: false,
|
|
334
|
+
variant: input.variant,
|
|
335
|
+
observation: input.observation,
|
|
336
|
+
fallback: buildBreakerFallback("CP_MODEL_DISABLED")
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
//#endregion
|
|
340
|
+
export { CACHE_PROOF_MODEL_SCHEMA_VERSION, DEFAULT_CACHE_VARIANT_BUDGET, buildBoundaryOutcomeCompatibility, buildCacheVariant, buildRenderObservation, createAppRouteCacheProofGraphScope, createDisabledCacheProofDecision, hasCompleteNegativeRequestApiProof };
|
|
341
|
+
|
|
342
|
+
//# sourceMappingURL=cache-proof.js.map
|
|
@@ -0,0 +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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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/server/dev-error-overlay-store.d.ts
|
|
2
|
+
type Source = "uncaught" | "caught" | "window-error" | "unhandledrejection";
|
|
3
|
+
type ReportedError = {
|
|
4
|
+
source: Source;
|
|
5
|
+
message: string;
|
|
6
|
+
stack: string | undefined;
|
|
7
|
+
componentStack: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
type OverlayState = {
|
|
10
|
+
errors: ReportedError[];
|
|
11
|
+
index: number;
|
|
12
|
+
minimized: boolean;
|
|
13
|
+
};
|
|
14
|
+
declare function subscribeOverlay(fn: () => void): () => void;
|
|
15
|
+
declare function getOverlaySnapshot(): OverlayState;
|
|
16
|
+
declare function reportToOverlay(error: ReportedError): void;
|
|
17
|
+
declare function dismissOverlay(): void;
|
|
18
|
+
declare function setOverlayIndex(index: number): void;
|
|
19
|
+
declare function minimizeOverlay(): void;
|
|
20
|
+
declare function expandOverlay(): void;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { OverlayState, ReportedError, Source, dismissOverlay, expandOverlay, getOverlaySnapshot, minimizeOverlay, reportToOverlay, setOverlayIndex, subscribeOverlay };
|
|
23
|
+
//# sourceMappingURL=dev-error-overlay-store.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
//#region src/server/dev-error-overlay-store.ts
|
|
2
|
+
const MAX_DEV_OVERLAY_ERRORS = 50;
|
|
3
|
+
let snapshot = {
|
|
4
|
+
errors: [],
|
|
5
|
+
index: 0,
|
|
6
|
+
minimized: false
|
|
7
|
+
};
|
|
8
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
9
|
+
function emit() {
|
|
10
|
+
for (const fn of listeners) fn();
|
|
11
|
+
}
|
|
12
|
+
function subscribeOverlay(fn) {
|
|
13
|
+
listeners.add(fn);
|
|
14
|
+
return () => {
|
|
15
|
+
listeners.delete(fn);
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function getOverlaySnapshot() {
|
|
19
|
+
return snapshot;
|
|
20
|
+
}
|
|
21
|
+
function reportToOverlay(error) {
|
|
22
|
+
const next = [...snapshot.errors, error];
|
|
23
|
+
const dropped = next.length > MAX_DEV_OVERLAY_ERRORS ? next.length - MAX_DEV_OVERLAY_ERRORS : 0;
|
|
24
|
+
const errors = dropped > 0 ? next.slice(dropped) : next;
|
|
25
|
+
snapshot = {
|
|
26
|
+
errors,
|
|
27
|
+
index: errors.length - 1,
|
|
28
|
+
minimized: false
|
|
29
|
+
};
|
|
30
|
+
emit();
|
|
31
|
+
}
|
|
32
|
+
function dismissOverlay() {
|
|
33
|
+
snapshot = {
|
|
34
|
+
errors: [],
|
|
35
|
+
index: 0,
|
|
36
|
+
minimized: false
|
|
37
|
+
};
|
|
38
|
+
emit();
|
|
39
|
+
}
|
|
40
|
+
function setOverlayIndex(index) {
|
|
41
|
+
if (index < 0 || index >= snapshot.errors.length) return;
|
|
42
|
+
snapshot = {
|
|
43
|
+
...snapshot,
|
|
44
|
+
index
|
|
45
|
+
};
|
|
46
|
+
emit();
|
|
47
|
+
}
|
|
48
|
+
function minimizeOverlay() {
|
|
49
|
+
if (snapshot.minimized) return;
|
|
50
|
+
snapshot = {
|
|
51
|
+
...snapshot,
|
|
52
|
+
minimized: true
|
|
53
|
+
};
|
|
54
|
+
emit();
|
|
55
|
+
}
|
|
56
|
+
function expandOverlay() {
|
|
57
|
+
if (!snapshot.minimized) return;
|
|
58
|
+
snapshot = {
|
|
59
|
+
...snapshot,
|
|
60
|
+
minimized: false
|
|
61
|
+
};
|
|
62
|
+
emit();
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
export { dismissOverlay, expandOverlay, getOverlaySnapshot, minimizeOverlay, reportToOverlay, setOverlayIndex, subscribeOverlay };
|
|
66
|
+
|
|
67
|
+
//# sourceMappingURL=dev-error-overlay-store.js.map
|
|
@@ -0,0 +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;AACpB,MAAK,MAAM,MAAM,UAAW,KAAI;;AAGlC,SAAgB,iBAAiB,IAA4B;AAC3D,WAAU,IAAI,GAAG;AACjB,cAAa;AACX,YAAU,OAAO,GAAG;;;AAIxB,SAAgB,qBAAmC;AACjD,QAAO;;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;AACnD,YAAW;EACT;EACA,OAAO,OAAO,SAAS;EACvB,WAAW;EACZ;AACD,OAAM;;AAGR,SAAgB,iBAAuB;AACrC,YAAW;EAAE,QAAQ,EAAE;EAAE,OAAO;EAAG,WAAW;EAAO;AACrD,OAAM;;AAGR,SAAgB,gBAAgB,OAAqB;AACnD,KAAI,QAAQ,KAAK,SAAS,SAAS,OAAO,OAAQ;AAClD,YAAW;EAAE,GAAG;EAAU;EAAO;AACjC,OAAM;;AAGR,SAAgB,kBAAwB;AACtC,KAAI,SAAS,UAAW;AACxB,YAAW;EAAE,GAAG;EAAU,WAAW;EAAM;AAC3C,OAAM;;AAGR,SAAgB,gBAAsB;AACpC,KAAI,CAAC,SAAS,UAAW;AACzB,YAAW;EAAE,GAAG;EAAU,WAAW;EAAO;AAC5C,OAAM"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { dismissOverlay } from "./dev-error-overlay-store.js";
|
|
2
|
+
|
|
3
|
+
//#region src/server/dev-error-overlay.d.ts
|
|
4
|
+
declare function installDevErrorOverlay(): void;
|
|
5
|
+
declare function devOnCaughtError(error: unknown, errorInfo: {
|
|
6
|
+
componentStack?: string;
|
|
7
|
+
errorBoundary?: unknown;
|
|
8
|
+
}): void;
|
|
9
|
+
declare function devOnUncaughtError(error: unknown, errorInfo: {
|
|
10
|
+
componentStack?: string;
|
|
11
|
+
errorBoundary?: unknown;
|
|
12
|
+
}): void;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { devOnCaughtError, devOnUncaughtError, dismissOverlay, installDevErrorOverlay };
|
|
15
|
+
//# sourceMappingURL=dev-error-overlay.d.ts.map
|