vinext 1.3.1 → 1.4.1
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 +25 -22
- package/THIRD_PARTY_LICENSES.md +47 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -2
- package/dist/build/prerender.js +4 -3
- package/dist/build/report.d.ts +0 -14
- package/dist/build/report.js +1 -51
- package/dist/check.js +4 -7
- package/dist/cli.js +3 -0
- package/dist/client/dev-error-overlay-store.d.ts +1 -0
- package/dist/client/dev-error-overlay.d.ts +2 -0
- package/dist/client/dev-error-overlay.js +20 -4
- package/dist/client/navigation-runtime.d.ts +13 -1
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.js +2 -0
- package/dist/config/destination-params.d.ts +2 -1
- package/dist/config/destination-params.js +52 -2
- package/dist/config/next-config.d.ts +25 -0
- package/dist/config/next-config.js +82 -4
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-codec.js +327 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-data.js +123 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/index.js +29 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/internal.js +134 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-codec.js +50 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data-generated.js +455 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/big5-added.json.js +169 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp936.json.js +2584 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp949.json.js +2220 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp950.json.js +227 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/eucjp.json.js +425 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gb18030-ranges.json.js +427 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gbk-added.json.js +229 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/shiftjis.json.js +292 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf16.js +106 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf7.js +182 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/bom-handling.js +42 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/extend-node.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/index.js +94 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/streams.js +95 -0
- package/dist/deps/.pnpm/safer-buffer@2.1.2/deps/safer-buffer/safer.js +45 -0
- package/dist/entries/app-rsc-entry.js +17 -49
- package/dist/entries/app-rsc-manifest.js +3 -4
- package/dist/entries/app-ssr-entry.js +1 -0
- package/dist/entries/pages-server-entry.js +36 -9
- package/dist/index.js +112 -90
- package/dist/init-cloudflare.d.ts +1 -3
- package/dist/init-cloudflare.js +10 -48
- package/dist/init-platform.d.ts +2 -0
- package/dist/init-platform.js +4 -0
- package/dist/plugins/extensionless-dynamic-import.js +6 -2
- package/dist/plugins/next-intl-catalog.d.ts +12 -0
- package/dist/plugins/next-intl-catalog.js +85 -0
- package/dist/plugins/pages-node-externals.d.ts +1 -0
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/strip-server-exports.js +2 -1
- package/dist/plugins/use-cache-callable.d.ts +1 -1
- package/dist/plugins/use-cache-callable.js +136 -94
- package/dist/routing/app-route-graph.d.ts +6 -0
- package/dist/routing/app-route-graph.js +9 -1
- package/dist/server/api-handler.js +21 -5
- package/dist/server/app-bfcache-identity.js +1 -1
- package/dist/server/app-browser-entry.js +86 -66
- package/dist/server/app-browser-history-controller.d.ts +5 -4
- package/dist/server/app-browser-history-controller.js +93 -15
- package/dist/server/app-browser-navigation-controller.d.ts +2 -2
- package/dist/server/app-browser-navigation-controller.js +1 -2
- package/dist/server/app-browser-rsc-redirect.js +7 -7
- package/dist/server/app-browser-server-action-client.d.ts +2 -0
- package/dist/server/app-browser-server-action-client.js +5 -4
- package/dist/server/app-browser-state.d.ts +2 -4
- package/dist/server/app-browser-state.js +9 -4
- package/dist/server/app-browser-supplemental-refresh.js +16 -1
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-browser-visible-commit.js +4 -14
- package/dist/server/app-elements-wire.d.ts +6 -38
- package/dist/server/app-elements-wire.js +4 -41
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-history-state.d.ts +2 -2
- package/dist/server/app-history-state.js +5 -2
- package/dist/server/app-mounted-layouts.d.ts +21 -0
- package/dist/server/app-mounted-layouts.js +67 -0
- package/dist/server/app-optimistic-routing.d.ts +19 -1
- package/dist/server/app-optimistic-routing.js +43 -4
- package/dist/server/app-page-boundary-render.js +10 -14
- package/dist/server/app-page-boundary.js +2 -2
- package/dist/server/app-page-cache-finalizer.d.ts +12 -1
- package/dist/server/app-page-cache-finalizer.js +70 -29
- package/dist/server/app-page-cache.d.ts +13 -1
- package/dist/server/app-page-cache.js +31 -9
- package/dist/server/app-page-dispatch.d.ts +5 -11
- package/dist/server/app-page-dispatch.js +84 -155
- package/dist/server/app-page-element-builder.d.ts +2 -2
- package/dist/server/app-page-element-builder.js +13 -12
- package/dist/server/app-page-execution.d.ts +17 -52
- package/dist/server/app-page-execution.js +102 -95
- package/dist/server/app-page-head.d.ts +13 -0
- package/dist/server/app-page-head.js +44 -16
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +1 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +2 -2
- package/dist/server/app-page-layout-gate.d.ts +35 -0
- package/dist/server/app-page-layout-gate.js +50 -0
- package/dist/server/app-page-params.d.ts +0 -1
- package/dist/server/app-page-params.js +1 -14
- package/dist/server/app-page-probe.d.ts +3 -21
- package/dist/server/app-page-probe.js +4 -37
- package/dist/server/app-page-render.d.ts +2 -13
- package/dist/server/app-page-render.js +103 -234
- package/dist/server/app-page-request.d.ts +1 -3
- package/dist/server/app-page-request.js +1 -1
- package/dist/server/app-page-response.js +3 -3
- package/dist/server/app-page-route-wiring.d.ts +13 -6
- package/dist/server/app-page-route-wiring.js +86 -63
- package/dist/server/app-page-rsc-render-status.d.ts +27 -1
- package/dist/server/app-page-rsc-render-status.js +121 -13
- package/dist/server/app-page-stream.d.ts +12 -8
- package/dist/server/app-page-stream.js +4 -3
- package/dist/server/app-pages-bridge.d.ts +4 -0
- package/dist/server/app-pages-bridge.js +7 -3
- package/dist/server/app-render-dependency.d.ts +11 -4
- package/dist/server/app-render-dependency.js +86 -38
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +1 -1
- package/dist/server/app-route-handler-cache.js +2 -2
- package/dist/server/app-route-handler-dispatch.js +14 -9
- package/dist/server/app-route-handler-execution.js +11 -5
- package/dist/server/app-route-handler-policy.d.ts +1 -1
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-handler-runtime.d.ts +1 -1
- package/dist/server/app-route-handler-runtime.js +28 -11
- package/dist/server/app-router-entry.js +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +12 -12
- package/dist/server/app-rsc-cache-busting.js +31 -72
- package/dist/server/app-rsc-error-handler.d.ts +2 -1
- package/dist/server/app-rsc-error-handler.js +10 -2
- package/dist/server/app-rsc-errors.d.ts +8 -0
- package/dist/server/app-rsc-errors.js +11 -1
- package/dist/server/app-rsc-handler.d.ts +5 -5
- package/dist/server/app-rsc-handler.js +80 -83
- package/dist/server/app-rsc-request-normalization.d.ts +10 -16
- package/dist/server/app-rsc-request-normalization.js +12 -18
- package/dist/server/app-rsc-response-finalizer.js +2 -2
- package/dist/server/app-rsc-response-stage.js +9 -15
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +15 -8
- package/dist/server/app-ssr-entry.d.ts +8 -0
- package/dist/server/app-ssr-entry.js +22 -16
- package/dist/server/app-ssr-stream.js +1 -1
- package/dist/server/app-visited-response-cache.d.ts +36 -1
- package/dist/server/app-visited-response-cache.js +46 -5
- package/dist/server/app-worker-stages.d.ts +37 -6
- package/dist/server/app-worker-stages.js +81 -9
- package/dist/server/artifact-compatibility.d.ts +0 -1
- package/dist/server/artifact-compatibility.js +1 -10
- package/dist/server/bfcache-identity.d.ts +7 -0
- package/dist/server/bfcache-identity.js +10 -1
- package/dist/server/cache-proof.d.ts +1 -115
- package/dist/server/cache-proof.js +1 -544
- package/dist/server/cacheability-manifest.js +1 -2
- package/dist/server/cacheability-request.js +13 -8
- package/dist/server/dev-origin-check.d.ts +2 -1
- package/dist/server/dev-origin-check.js +2 -1
- package/dist/server/dev-server.js +6 -4
- package/dist/server/headers.d.ts +6 -3
- package/dist/server/headers.js +9 -5
- package/dist/server/image-optimization.d.ts +5 -0
- package/dist/server/image-optimization.js +6 -1
- package/dist/server/isr-cache.d.ts +8 -2
- package/dist/server/isr-cache.js +30 -2
- package/dist/server/metadata-route-response.js +32 -15
- package/dist/server/middleware-matcher.js +19 -6
- package/dist/server/middleware-runtime.js +6 -2
- package/dist/server/multi-stage.d.ts +57 -12
- package/dist/server/multi-stage.js +13 -1
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/pages-api-route.js +28 -19
- package/dist/server/pages-media-type.d.ts +21 -1
- package/dist/server/pages-media-type.js +69 -5
- package/dist/server/pages-node-compat.d.ts +1 -1
- package/dist/server/pages-node-compat.js +54 -27
- package/dist/server/pages-page-data.js +2 -1
- package/dist/server/pages-page-handler.js +28 -26
- package/dist/server/pages-page-response.d.ts +9 -0
- package/dist/server/pages-page-response.js +18 -4
- package/dist/server/pages-request-pipeline.d.ts +8 -0
- package/dist/server/pages-request-pipeline.js +2 -2
- package/dist/server/pages-request-stage-entry.js +36 -14
- package/dist/server/pages-response-stage-entry.js +9 -3
- package/dist/server/pages-router-entry.js +3 -2
- package/dist/server/prod-server.d.ts +2 -2
- package/dist/server/prod-server.js +47 -9
- package/dist/server/request-error-log.d.ts +9 -0
- package/dist/server/request-error-log.js +13 -0
- package/dist/server/request-pipeline.d.ts +15 -4
- package/dist/server/request-pipeline.js +43 -15
- package/dist/server/rsc-completion-metadata.js +3 -0
- package/dist/server/shared-cache-identity.d.ts +23 -0
- package/dist/server/shared-cache-identity.js +36 -0
- package/dist/server/static-file-cache.d.ts +9 -0
- package/dist/server/static-file-cache.js +13 -2
- package/dist/server/worker-stages.d.ts +16 -3
- package/dist/server/worker-stages.js +23 -4
- package/dist/shims/cache-handler.js +2 -2
- package/dist/shims/cache-request-state.d.ts +23 -26
- package/dist/shims/cache-request-state.js +22 -57
- package/dist/shims/cache-runtime.d.ts +3 -1
- package/dist/shims/cache-runtime.js +94 -48
- package/dist/shims/cache.d.ts +16 -10
- package/dist/shims/cache.js +47 -36
- package/dist/shims/cacheability-classification.d.ts +2 -0
- package/dist/shims/cdn-cache.d.ts +22 -5
- package/dist/shims/client-hook-error.d.ts +2 -0
- package/dist/shims/client-hook-error.js +16 -1
- package/dist/shims/client-page-root.js +2 -2
- package/dist/shims/dynamic.js +9 -6
- package/dist/shims/error-boundary.js +2 -2
- package/dist/shims/fetch-cache-state.d.ts +5 -1
- package/dist/shims/fetch-cache-state.js +1 -3
- package/dist/shims/fetch-cache.d.ts +2 -1
- package/dist/shims/fetch-cache.js +39 -25
- package/dist/shims/form.js +2 -2
- package/dist/shims/headers.d.ts +10 -24
- package/dist/shims/headers.js +22 -70
- package/dist/shims/internal/cache-context-accessor.d.ts +1 -1
- package/dist/shims/internal/navigation-untracked.js +1 -1
- package/dist/shims/link.js +8 -11
- package/dist/shims/metadata.d.ts +23 -21
- package/dist/shims/metadata.js +62 -24
- package/dist/shims/navigation-server.js +1 -1
- package/dist/shims/navigation.d.ts +74 -7
- package/dist/shims/navigation.js +184 -31
- package/dist/shims/navigation.react-server.js +2 -2
- package/dist/shims/request-state-types.d.ts +3 -2
- package/dist/shims/slot.d.ts +16 -0
- package/dist/shims/slot.js +44 -9
- package/dist/shims/unified-request-context.d.ts +7 -1
- package/dist/shims/unified-request-context.js +3 -3
- package/dist/utils/cache-control-metadata.d.ts +5 -0
- package/dist/utils/cache-control-metadata.js +9 -1
- package/dist/utils/cache-life-profiles.d.ts +33 -0
- package/dist/utils/cache-life-profiles.js +111 -0
- package/dist/utils/middleware-request-headers.d.ts +14 -3
- package/dist/utils/middleware-request-headers.js +54 -7
- package/dist/utils/project.d.ts +2 -2
- package/dist/utils/project.js +3 -16
- package/dist/utils/regex.d.ts +5 -0
- package/dist/utils/regex.js +11 -1
- package/dist/utils/text-stream.d.ts +10 -5
- package/dist/utils/text-stream.js +6 -6
- package/package.json +2 -1
- package/dist/build/layout-classification-types.d.ts +0 -60
- package/dist/build/layout-classification-types.js +0 -1
- package/dist/build/layout-classification.d.ts +0 -62
- package/dist/build/layout-classification.js +0 -98
- package/dist/build/route-classification-injector.d.ts +0 -33
- package/dist/build/route-classification-injector.js +0 -59
- package/dist/build/route-classification-manifest.d.ts +0 -54
- package/dist/build/route-classification-manifest.js +0 -143
- package/dist/server/app-browser-client-reuse-manifest.d.ts +0 -11
- package/dist/server/app-browser-client-reuse-manifest.js +0 -101
- package/dist/server/app-layout-param-observation.d.ts +0 -42
- package/dist/server/app-layout-param-observation.js +0 -168
- package/dist/server/client-reuse-manifest.d.ts +0 -103
- package/dist/server/client-reuse-manifest.js +0 -209
- package/dist/server/skip-cache-proof.d.ts +0 -60
- package/dist/server/skip-cache-proof.js +0 -168
- package/dist/server/static-layout-client-reuse-proof.d.ts +0 -14
- package/dist/server/static-layout-client-reuse-proof.js +0 -33
- package/dist/utils/sorted-array.d.ts +0 -8
- package/dist/utils/sorted-array.js +0 -20
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
import { fnv1a64 } from "../utils/hash.js";
|
|
2
|
-
import { evaluateArtifactCompatibility } from "./artifact-compatibility.js";
|
|
3
|
-
import { findSortedStringPosition } from "../utils/sorted-array.js";
|
|
4
2
|
//#region src/server/cache-proof.ts
|
|
5
3
|
const CACHE_PROOF_MODEL_SCHEMA_VERSION = 1;
|
|
6
|
-
const DEFAULT_CACHE_VARIANT_BUDGET = {
|
|
7
|
-
maxDimensionCount: 8,
|
|
8
|
-
maxDimensionNameLength: 64,
|
|
9
|
-
maxDimensionValueLength: 256,
|
|
10
|
-
maxEncodedLength: 1024,
|
|
11
|
-
maxValuesPerDimension: 8,
|
|
12
|
-
maxVariantsPerRoute: 64
|
|
13
|
-
};
|
|
14
4
|
const ALL_RENDER_REQUEST_API_KINDS = [
|
|
15
5
|
"connection",
|
|
16
6
|
"cookies",
|
|
@@ -19,13 +9,6 @@ const ALL_RENDER_REQUEST_API_KINDS = [
|
|
|
19
9
|
"params",
|
|
20
10
|
"searchParams"
|
|
21
11
|
];
|
|
22
|
-
const PUBLIC_UNSAFE_DIMENSION_SOURCES = /* @__PURE__ */ new Set([
|
|
23
|
-
"auth",
|
|
24
|
-
"cookie",
|
|
25
|
-
"draft-mode",
|
|
26
|
-
"header",
|
|
27
|
-
"session"
|
|
28
|
-
]);
|
|
29
12
|
function buildBreakerFallback(code, fields = {}, mode = "renderFresh", scope = "affectedOutput") {
|
|
30
13
|
return {
|
|
31
14
|
kind: "breakerFallback",
|
|
@@ -38,332 +21,15 @@ function buildBreakerFallback(code, fields = {}, mode = "renderFresh", scope = "
|
|
|
38
21
|
function sortedUnique(values) {
|
|
39
22
|
return [...new Set(values)].sort();
|
|
40
23
|
}
|
|
41
|
-
function normalizeDimensionName(name) {
|
|
42
|
-
return name.trim().toLowerCase();
|
|
43
|
-
}
|
|
44
24
|
function redactValue(value) {
|
|
45
25
|
return `h:${fnv1a64(value)}`;
|
|
46
26
|
}
|
|
47
27
|
function sortedUniqueRedacted(values) {
|
|
48
28
|
return sortedUnique(sortedUnique(values).map(redactValue));
|
|
49
29
|
}
|
|
50
|
-
function encodeParts(parts) {
|
|
51
|
-
return JSON.stringify(parts);
|
|
52
|
-
}
|
|
53
|
-
function compareDimensions(a, b) {
|
|
54
|
-
return a.source.localeCompare(b.source) || a.name.localeCompare(b.name) || a.privacy.localeCompare(b.privacy);
|
|
55
|
-
}
|
|
56
|
-
function encodeNullable(value) {
|
|
57
|
-
return value;
|
|
58
|
-
}
|
|
59
30
|
function assertNever(value) {
|
|
60
31
|
throw new Error(`Unhandled cache proof variant: ${String(value)}`);
|
|
61
32
|
}
|
|
62
|
-
function encodeOutputScope(output) {
|
|
63
|
-
switch (output.kind) {
|
|
64
|
-
case "app-html": return encodeParts([
|
|
65
|
-
output.kind,
|
|
66
|
-
output.routeId,
|
|
67
|
-
encodeNullable(output.rootBoundaryId),
|
|
68
|
-
encodeNullable(output.renderEpoch)
|
|
69
|
-
]);
|
|
70
|
-
case "app-rsc": return encodeParts([
|
|
71
|
-
output.kind,
|
|
72
|
-
output.routeId,
|
|
73
|
-
encodeNullable(output.rootBoundaryId),
|
|
74
|
-
encodeNullable(output.renderEpoch),
|
|
75
|
-
encodeNullable(output.mountedSlotsFingerprint)
|
|
76
|
-
]);
|
|
77
|
-
case "layout": return encodeParts([
|
|
78
|
-
output.kind,
|
|
79
|
-
output.routeId,
|
|
80
|
-
output.layoutId,
|
|
81
|
-
encodeNullable(output.rootBoundaryId)
|
|
82
|
-
]);
|
|
83
|
-
case "page": return encodeParts([
|
|
84
|
-
output.kind,
|
|
85
|
-
output.routeId,
|
|
86
|
-
output.pageId,
|
|
87
|
-
encodeNullable(output.rootBoundaryId)
|
|
88
|
-
]);
|
|
89
|
-
case "route-handler": return encodeParts([
|
|
90
|
-
output.kind,
|
|
91
|
-
output.routeId,
|
|
92
|
-
output.routeHandlerId
|
|
93
|
-
]);
|
|
94
|
-
case "slot": return encodeParts([
|
|
95
|
-
output.kind,
|
|
96
|
-
output.routeId,
|
|
97
|
-
output.slotId,
|
|
98
|
-
encodeNullable(output.rootBoundaryId)
|
|
99
|
-
]);
|
|
100
|
-
case "template": return encodeParts([
|
|
101
|
-
output.kind,
|
|
102
|
-
output.routeId,
|
|
103
|
-
output.templateId,
|
|
104
|
-
encodeNullable(output.rootBoundaryId)
|
|
105
|
-
]);
|
|
106
|
-
default: return assertNever(output);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
function validateBudgetNumber(name, value) {
|
|
110
|
-
if (Number.isInteger(value) && value >= 0) return null;
|
|
111
|
-
return buildBreakerFallback("CP_INVALID_VARIANT_BUDGET", { budgetField: name });
|
|
112
|
-
}
|
|
113
|
-
function validateBudget(budget) {
|
|
114
|
-
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);
|
|
115
|
-
}
|
|
116
|
-
function buildDimension(input, budget) {
|
|
117
|
-
const name = normalizeDimensionName(input.name);
|
|
118
|
-
if (name.length === 0) return buildBreakerFallback("CP_DIMENSION_NAME_MISSING", { source: input.source });
|
|
119
|
-
if (name.length > budget.maxDimensionNameLength) return buildBreakerFallback("CP_DIMENSION_NAME_TOO_LONG", {
|
|
120
|
-
maxLength: budget.maxDimensionNameLength,
|
|
121
|
-
nameHash: redactValue(name),
|
|
122
|
-
source: input.source
|
|
123
|
-
});
|
|
124
|
-
if (input.privacy === "public" && PUBLIC_UNSAFE_DIMENSION_SOURCES.has(input.source)) return buildBreakerFallback("CP_UNSAFE_PUBLIC_DIMENSION", {
|
|
125
|
-
name,
|
|
126
|
-
source: input.source
|
|
127
|
-
}, "privateUncacheable");
|
|
128
|
-
const values = sortedUnique(input.values);
|
|
129
|
-
if (values.length === 0) return buildBreakerFallback("CP_DIMENSION_VALUES_MISSING", {
|
|
130
|
-
name,
|
|
131
|
-
source: input.source
|
|
132
|
-
});
|
|
133
|
-
if (values.length > budget.maxValuesPerDimension) return buildBreakerFallback("CP_DIMENSION_VALUE_COUNT_EXCEEDED", {
|
|
134
|
-
maxValues: budget.maxValuesPerDimension,
|
|
135
|
-
name,
|
|
136
|
-
source: input.source,
|
|
137
|
-
valueCount: values.length
|
|
138
|
-
});
|
|
139
|
-
for (const value of values) if (value.length > budget.maxDimensionValueLength) return buildBreakerFallback("CP_DIMENSION_VALUE_TOO_LONG", {
|
|
140
|
-
maxLength: budget.maxDimensionValueLength,
|
|
141
|
-
name,
|
|
142
|
-
source: input.source,
|
|
143
|
-
valueHash: redactValue(value)
|
|
144
|
-
});
|
|
145
|
-
const valueHashes = values.map(redactValue);
|
|
146
|
-
return {
|
|
147
|
-
encoded: encodeParts([
|
|
148
|
-
input.source,
|
|
149
|
-
input.privacy,
|
|
150
|
-
name,
|
|
151
|
-
valueHashes
|
|
152
|
-
]),
|
|
153
|
-
name,
|
|
154
|
-
privacy: input.privacy,
|
|
155
|
-
source: input.source,
|
|
156
|
-
valueCount: valueHashes.length,
|
|
157
|
-
valueHashes
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
function isCacheProofBreakerFallback(value) {
|
|
161
|
-
return "code" in value;
|
|
162
|
-
}
|
|
163
|
-
function getDimensionBucket(bySource, source, privacy) {
|
|
164
|
-
const existingByPrivacy = bySource.get(source);
|
|
165
|
-
const byPrivacy = existingByPrivacy ?? /* @__PURE__ */ new Map();
|
|
166
|
-
if (!existingByPrivacy) bySource.set(source, byPrivacy);
|
|
167
|
-
const existingByName = byPrivacy.get(privacy);
|
|
168
|
-
const byName = existingByName ?? /* @__PURE__ */ new Map();
|
|
169
|
-
if (!existingByName) byPrivacy.set(privacy, byName);
|
|
170
|
-
return byName;
|
|
171
|
-
}
|
|
172
|
-
function mergeDimensionInputs(dimensions) {
|
|
173
|
-
const bySource = /* @__PURE__ */ new Map();
|
|
174
|
-
const orderedDimensions = [];
|
|
175
|
-
for (const dimension of dimensions) {
|
|
176
|
-
const name = normalizeDimensionName(dimension.name);
|
|
177
|
-
const bucket = getDimensionBucket(bySource, dimension.source, dimension.privacy);
|
|
178
|
-
const existing = bucket.get(name);
|
|
179
|
-
if (existing) {
|
|
180
|
-
existing.values.push(...dimension.values);
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
const accumulator = {
|
|
184
|
-
name,
|
|
185
|
-
privacy: dimension.privacy,
|
|
186
|
-
source: dimension.source,
|
|
187
|
-
values: [...dimension.values]
|
|
188
|
-
};
|
|
189
|
-
bucket.set(name, accumulator);
|
|
190
|
-
orderedDimensions.push(accumulator);
|
|
191
|
-
}
|
|
192
|
-
return orderedDimensions;
|
|
193
|
-
}
|
|
194
|
-
function createAppRouteCacheProofGraphScope(route) {
|
|
195
|
-
return {
|
|
196
|
-
routeId: route.ids.route,
|
|
197
|
-
pageId: route.ids.page,
|
|
198
|
-
routeHandlerId: route.ids.routeHandler,
|
|
199
|
-
layoutIds: [...route.ids.layouts],
|
|
200
|
-
templateIds: [...route.ids.templates],
|
|
201
|
-
slotIds: sortedUnique(Object.values(route.ids.slots))
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
function buildCacheVariant(input) {
|
|
205
|
-
const budgetFallback = validateBudget(input.budget);
|
|
206
|
-
if (budgetFallback) return {
|
|
207
|
-
kind: "breakerFallback",
|
|
208
|
-
fallback: budgetFallback
|
|
209
|
-
};
|
|
210
|
-
const dimensionInputs = mergeDimensionInputs(input.dimensions);
|
|
211
|
-
if (dimensionInputs.length > input.budget.maxDimensionCount) return {
|
|
212
|
-
kind: "breakerFallback",
|
|
213
|
-
fallback: buildBreakerFallback("CP_DIMENSION_COUNT_EXCEEDED", {
|
|
214
|
-
dimensionCount: dimensionInputs.length,
|
|
215
|
-
maxDimensionCount: input.budget.maxDimensionCount,
|
|
216
|
-
routeId: input.output.routeId
|
|
217
|
-
})
|
|
218
|
-
};
|
|
219
|
-
const dimensions = [];
|
|
220
|
-
for (const dimensionInput of dimensionInputs) {
|
|
221
|
-
const dimension = buildDimension(dimensionInput, input.budget);
|
|
222
|
-
if (isCacheProofBreakerFallback(dimension)) return {
|
|
223
|
-
kind: "breakerFallback",
|
|
224
|
-
fallback: dimension
|
|
225
|
-
};
|
|
226
|
-
dimensions.push(dimension);
|
|
227
|
-
}
|
|
228
|
-
dimensions.sort(compareDimensions);
|
|
229
|
-
const encoded = [
|
|
230
|
-
`schema:1`,
|
|
231
|
-
encodeOutputScope(input.output),
|
|
232
|
-
...dimensions.map((dimension) => dimension.encoded)
|
|
233
|
-
].join("|");
|
|
234
|
-
if (encoded.length > input.budget.maxEncodedLength) return {
|
|
235
|
-
kind: "breakerFallback",
|
|
236
|
-
fallback: buildBreakerFallback("CP_ENCODED_VARIANT_TOO_LONG", {
|
|
237
|
-
encodedHash: redactValue(encoded),
|
|
238
|
-
encodedLength: encoded.length,
|
|
239
|
-
maxEncodedLength: input.budget.maxEncodedLength,
|
|
240
|
-
routeId: input.output.routeId
|
|
241
|
-
})
|
|
242
|
-
};
|
|
243
|
-
return {
|
|
244
|
-
kind: "variant",
|
|
245
|
-
variant: {
|
|
246
|
-
schemaVersion: 1,
|
|
247
|
-
cacheKey: `cp1:${fnv1a64(encoded)}`,
|
|
248
|
-
output: input.output,
|
|
249
|
-
dimensions,
|
|
250
|
-
encodedLength: encoded.length,
|
|
251
|
-
budget: { ...input.budget }
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
function normalizeRouteBudget(input) {
|
|
256
|
-
return {
|
|
257
|
-
routeId: input.routeId,
|
|
258
|
-
variantCacheKeys: sortedUnique(input.variantCacheKeys)
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
function buildRouteVariantCeilingFallback(variant, existingVariantCount) {
|
|
262
|
-
return buildBreakerFallback("CP_ROUTE_VARIANT_CEILING_EXCEEDED", {
|
|
263
|
-
existingVariantCount,
|
|
264
|
-
maxVariantsPerRoute: variant.budget.maxVariantsPerRoute,
|
|
265
|
-
routeId: variant.output.routeId
|
|
266
|
-
}, "privateUncacheable", "route");
|
|
267
|
-
}
|
|
268
|
-
function enforceCacheVariantRouteBudget(input) {
|
|
269
|
-
if (input.routeBudget && input.routeBudget.routeId !== input.variant.output.routeId) return {
|
|
270
|
-
kind: "breakerFallback",
|
|
271
|
-
routeBudget: normalizeRouteBudget(input.routeBudget),
|
|
272
|
-
fallback: buildBreakerFallback("CP_ROUTE_VARIANT_BUDGET_ROUTE_MISMATCH", {
|
|
273
|
-
budgetRouteId: input.routeBudget.routeId,
|
|
274
|
-
routeId: input.variant.output.routeId
|
|
275
|
-
}, "privateUncacheable", "route")
|
|
276
|
-
};
|
|
277
|
-
const routeBudget = normalizeRouteBudget(input.routeBudget ?? {
|
|
278
|
-
routeId: input.variant.output.routeId,
|
|
279
|
-
variantCacheKeys: []
|
|
280
|
-
});
|
|
281
|
-
const existingVariantCount = routeBudget.variantCacheKeys.length;
|
|
282
|
-
const variantKeyPosition = findSortedStringPosition(routeBudget.variantCacheKeys, input.variant.cacheKey);
|
|
283
|
-
if (existingVariantCount > input.variant.budget.maxVariantsPerRoute) return {
|
|
284
|
-
kind: "breakerFallback",
|
|
285
|
-
routeBudget,
|
|
286
|
-
fallback: buildRouteVariantCeilingFallback(input.variant, existingVariantCount)
|
|
287
|
-
};
|
|
288
|
-
if (variantKeyPosition.found) return {
|
|
289
|
-
kind: "variant",
|
|
290
|
-
variant: input.variant,
|
|
291
|
-
routeBudget,
|
|
292
|
-
didConsumeRouteVariantBudget: false
|
|
293
|
-
};
|
|
294
|
-
if (existingVariantCount >= input.variant.budget.maxVariantsPerRoute) return {
|
|
295
|
-
kind: "breakerFallback",
|
|
296
|
-
routeBudget,
|
|
297
|
-
fallback: buildRouteVariantCeilingFallback(input.variant, existingVariantCount)
|
|
298
|
-
};
|
|
299
|
-
return {
|
|
300
|
-
kind: "variant",
|
|
301
|
-
variant: input.variant,
|
|
302
|
-
routeBudget: {
|
|
303
|
-
routeId: routeBudget.routeId,
|
|
304
|
-
variantCacheKeys: [
|
|
305
|
-
...routeBudget.variantCacheKeys.slice(0, variantKeyPosition.index),
|
|
306
|
-
input.variant.cacheKey,
|
|
307
|
-
...routeBudget.variantCacheKeys.slice(variantKeyPosition.index)
|
|
308
|
-
]
|
|
309
|
-
},
|
|
310
|
-
didConsumeRouteVariantBudget: true
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
function buildCacheVariantWithRouteBudget(input) {
|
|
314
|
-
const variantResult = buildCacheVariant({
|
|
315
|
-
budget: input.budget,
|
|
316
|
-
dimensions: input.dimensions,
|
|
317
|
-
output: input.output
|
|
318
|
-
});
|
|
319
|
-
if (variantResult.kind === "breakerFallback") return {
|
|
320
|
-
kind: "breakerFallback",
|
|
321
|
-
routeBudget: input.routeBudget ? normalizeRouteBudget(input.routeBudget) : null,
|
|
322
|
-
fallback: variantResult.fallback
|
|
323
|
-
};
|
|
324
|
-
return enforceCacheVariantRouteBudget({
|
|
325
|
-
routeBudget: input.routeBudget,
|
|
326
|
-
variant: variantResult.variant
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
function boundaryOutcomesMatch(expected, candidate) {
|
|
330
|
-
switch (expected.kind) {
|
|
331
|
-
case "error": return candidate.kind === "error" && (expected.digest ?? "") === (candidate.digest ?? "");
|
|
332
|
-
case "forbidden": return candidate.kind === "forbidden";
|
|
333
|
-
case "globalError": return candidate.kind === "globalError" && (expected.digest ?? "") === (candidate.digest ?? "");
|
|
334
|
-
case "notFound": return candidate.kind === "notFound";
|
|
335
|
-
case "redirect": return candidate.kind === "redirect" && expected.status === candidate.status && expected.location === candidate.location;
|
|
336
|
-
case "success": return candidate.kind === "success";
|
|
337
|
-
case "unauthorized": return candidate.kind === "unauthorized";
|
|
338
|
-
case "unknown": return false;
|
|
339
|
-
default: return assertNever(expected);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
function buildBoundaryOutcomeCompatibility(input) {
|
|
343
|
-
if (input.expected.kind === "unknown" || input.candidate.kind === "unknown") return {
|
|
344
|
-
kind: "incompatible",
|
|
345
|
-
expected: input.expected,
|
|
346
|
-
candidate: input.candidate,
|
|
347
|
-
fallback: buildBreakerFallback("CP_BOUNDARY_OUTCOME_UNKNOWN", {
|
|
348
|
-
candidateKind: input.candidate.kind,
|
|
349
|
-
expectedKind: input.expected.kind
|
|
350
|
-
})
|
|
351
|
-
};
|
|
352
|
-
if (boundaryOutcomesMatch(input.expected, input.candidate)) return {
|
|
353
|
-
kind: "compatible",
|
|
354
|
-
outcome: input.candidate,
|
|
355
|
-
reason: "CP_BOUNDARY_OUTCOME_MATCH"
|
|
356
|
-
};
|
|
357
|
-
return {
|
|
358
|
-
kind: "incompatible",
|
|
359
|
-
expected: input.expected,
|
|
360
|
-
candidate: input.candidate,
|
|
361
|
-
fallback: buildBreakerFallback("CP_BOUNDARY_OUTCOME_MISMATCH", {
|
|
362
|
-
candidateKind: input.candidate.kind,
|
|
363
|
-
expectedKind: input.expected.kind
|
|
364
|
-
})
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
33
|
function requestApiStatusRank(status) {
|
|
368
34
|
switch (status) {
|
|
369
35
|
case "notObserved": return 0;
|
|
@@ -447,47 +113,6 @@ function classifyObservedRequestApiDowngrade(kind) {
|
|
|
447
113
|
default: return assertNever(kind);
|
|
448
114
|
}
|
|
449
115
|
}
|
|
450
|
-
function classifyCacheVariantDimensionDowngrade(input) {
|
|
451
|
-
switch (input.source) {
|
|
452
|
-
case "auth": return {
|
|
453
|
-
code: "CP_DOWNGRADE_PRIVATE_DIMENSION",
|
|
454
|
-
inputClass: "auth",
|
|
455
|
-
source: "auth",
|
|
456
|
-
target: "private"
|
|
457
|
-
};
|
|
458
|
-
case "cookie": return {
|
|
459
|
-
code: "CP_DOWNGRADE_PRIVATE_DIMENSION",
|
|
460
|
-
inputClass: "private",
|
|
461
|
-
source: "cookie",
|
|
462
|
-
target: "private"
|
|
463
|
-
};
|
|
464
|
-
case "draft-mode": return {
|
|
465
|
-
code: "CP_DOWNGRADE_PRIVATE_DIMENSION",
|
|
466
|
-
inputClass: "draft",
|
|
467
|
-
source: "draft-mode",
|
|
468
|
-
target: "privateUncacheable"
|
|
469
|
-
};
|
|
470
|
-
case "header": return {
|
|
471
|
-
code: "CP_DOWNGRADE_PRIVATE_DIMENSION",
|
|
472
|
-
inputClass: "private",
|
|
473
|
-
source: "header",
|
|
474
|
-
target: "private"
|
|
475
|
-
};
|
|
476
|
-
case "session": return {
|
|
477
|
-
code: "CP_DOWNGRADE_PRIVATE_DIMENSION",
|
|
478
|
-
inputClass: "session",
|
|
479
|
-
source: "session",
|
|
480
|
-
target: "private"
|
|
481
|
-
};
|
|
482
|
-
case "custom":
|
|
483
|
-
case "interception":
|
|
484
|
-
case "mounted-slots":
|
|
485
|
-
case "params":
|
|
486
|
-
case "route":
|
|
487
|
-
case "search": return null;
|
|
488
|
-
default: return assertNever(input.source);
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
116
|
function classifyRenderObservationDowngrade(input) {
|
|
492
117
|
const reasons = [];
|
|
493
118
|
let target = "public";
|
|
@@ -602,164 +227,6 @@ function hasCompleteNegativeRequestApiProof(observation, requiredApis) {
|
|
|
602
227
|
function hasQueryInvariantRenderProof(observation) {
|
|
603
228
|
return observation !== void 0 && hasCompleteNegativeRequestApiProof(observation, ["searchParams"]);
|
|
604
229
|
}
|
|
605
|
-
function isStaticLayoutOutputScope(output) {
|
|
606
|
-
return output.kind === "layout";
|
|
607
|
-
}
|
|
608
|
-
function rejectStaticLayoutReuseProof(code, fields, mode = "renderFresh") {
|
|
609
|
-
return {
|
|
610
|
-
kind: "rejected",
|
|
611
|
-
fallback: buildBreakerFallback(code, fields, mode)
|
|
612
|
-
};
|
|
613
|
-
}
|
|
614
|
-
function getRequestApiStatus(observations, kind) {
|
|
615
|
-
let status = null;
|
|
616
|
-
for (const requestApi of observations) {
|
|
617
|
-
if (requestApi.kind !== kind) continue;
|
|
618
|
-
if (status === null || requestApiStatusRank(requestApi.status) > requestApiStatusRank(status)) status = requestApi.status;
|
|
619
|
-
}
|
|
620
|
-
return status ?? "missing";
|
|
621
|
-
}
|
|
622
|
-
function createStaticLayoutDowngradeFallback(downgrade) {
|
|
623
|
-
const mode = downgrade.target === "privateUncacheable" ? "privateUncacheable" : "renderFresh";
|
|
624
|
-
return buildBreakerFallback("CP_STATIC_LAYOUT_PRIVATE_DYNAMIC_DOWNGRADE", {
|
|
625
|
-
reasonCodes: downgrade.reasons.map((reason) => reason.code),
|
|
626
|
-
target: downgrade.target
|
|
627
|
-
}, mode);
|
|
628
|
-
}
|
|
629
|
-
function outputFieldMismatch(candidate, observation) {
|
|
630
|
-
if (candidate.layoutId !== observation.layoutId) return "layoutId";
|
|
631
|
-
if (candidate.rootBoundaryId !== observation.rootBoundaryId) return "rootBoundaryId";
|
|
632
|
-
if (candidate.routeId !== observation.routeId) return "routeId";
|
|
633
|
-
return null;
|
|
634
|
-
}
|
|
635
|
-
function buildStaticLayoutReuseProof(input) {
|
|
636
|
-
if (!isStaticLayoutOutputScope(input.currentOutput)) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_CURRENT_OUTPUT_KIND", { currentOutputKind: input.currentOutput.kind });
|
|
637
|
-
if (!isStaticLayoutOutputScope(input.candidateVariant.output)) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_CANDIDATE_OUTPUT_KIND", { candidateOutputKind: input.candidateVariant.output.kind });
|
|
638
|
-
if (!isStaticLayoutOutputScope(input.candidateObservation.output)) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_OBSERVATION_OUTPUT_KIND", { observationOutputKind: input.candidateObservation.output.kind });
|
|
639
|
-
const currentOutput = input.currentOutput;
|
|
640
|
-
const candidateOutput = input.candidateVariant.output;
|
|
641
|
-
const observationOutput = input.candidateObservation.output;
|
|
642
|
-
const requestApis = normalizeRequestApiObservations(input.candidateObservation.requestApis);
|
|
643
|
-
const candidateObservation = {
|
|
644
|
-
...input.candidateObservation,
|
|
645
|
-
requestApis,
|
|
646
|
-
downgrade: classifyRenderObservationDowngrade({
|
|
647
|
-
cacheability: input.candidateObservation.cacheability,
|
|
648
|
-
completeness: input.candidateObservation.completeness,
|
|
649
|
-
dynamicFetches: input.candidateObservation.dynamicFetches,
|
|
650
|
-
requestApis
|
|
651
|
-
})
|
|
652
|
-
};
|
|
653
|
-
const observedOutputMismatch = outputFieldMismatch(candidateOutput, observationOutput);
|
|
654
|
-
if (observedOutputMismatch) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_OBSERVATION_OUTPUT_MISMATCH", {
|
|
655
|
-
candidateLayoutId: candidateOutput.layoutId,
|
|
656
|
-
candidateRootBoundaryId: candidateOutput.rootBoundaryId,
|
|
657
|
-
candidateRouteId: candidateOutput.routeId,
|
|
658
|
-
field: observedOutputMismatch,
|
|
659
|
-
observationLayoutId: observationOutput.layoutId,
|
|
660
|
-
observationRootBoundaryId: observationOutput.rootBoundaryId,
|
|
661
|
-
observationRouteId: observationOutput.routeId
|
|
662
|
-
});
|
|
663
|
-
if (currentOutput.layoutId !== candidateOutput.layoutId) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_ID_MISMATCH", {
|
|
664
|
-
candidateLayoutId: candidateOutput.layoutId,
|
|
665
|
-
currentLayoutId: currentOutput.layoutId
|
|
666
|
-
});
|
|
667
|
-
if (currentOutput.rootBoundaryId === null || candidateOutput.rootBoundaryId === null) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_ROOT_BOUNDARY_UNKNOWN", {
|
|
668
|
-
candidateRootBoundaryId: candidateOutput.rootBoundaryId,
|
|
669
|
-
currentRootBoundaryId: currentOutput.rootBoundaryId
|
|
670
|
-
});
|
|
671
|
-
if (currentOutput.rootBoundaryId !== candidateOutput.rootBoundaryId) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_ROOT_BOUNDARY_MISMATCH", {
|
|
672
|
-
candidateRootBoundaryId: candidateOutput.rootBoundaryId,
|
|
673
|
-
currentRootBoundaryId: currentOutput.rootBoundaryId
|
|
674
|
-
});
|
|
675
|
-
const boundaryCompatibility = buildBoundaryOutcomeCompatibility({
|
|
676
|
-
candidate: candidateObservation.boundaryOutcome,
|
|
677
|
-
expected: { kind: "success" }
|
|
678
|
-
});
|
|
679
|
-
if (boundaryCompatibility.kind === "incompatible") return {
|
|
680
|
-
kind: "rejected",
|
|
681
|
-
fallback: boundaryCompatibility.fallback
|
|
682
|
-
};
|
|
683
|
-
if (input.candidateVariant.dimensions.length > 0) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_VARIANT_DIMENSION_UNPROVEN", {
|
|
684
|
-
dimensionCount: input.candidateVariant.dimensions.length,
|
|
685
|
-
sources: sortedUnique(input.candidateVariant.dimensions.map((dimension) => dimension.source))
|
|
686
|
-
});
|
|
687
|
-
if (!candidateObservation.downgrade.isPublicCacheCandidate) return {
|
|
688
|
-
kind: "rejected",
|
|
689
|
-
fallback: createStaticLayoutDowngradeFallback(candidateObservation.downgrade)
|
|
690
|
-
};
|
|
691
|
-
const requiredNegativeRequestApis = ALL_RENDER_REQUEST_API_KINDS;
|
|
692
|
-
for (const api of requiredNegativeRequestApis) {
|
|
693
|
-
const status = getRequestApiStatus(candidateObservation.requestApis, api);
|
|
694
|
-
if (status === "notObserved") continue;
|
|
695
|
-
return rejectStaticLayoutReuseProof(status === "missing" ? "CP_STATIC_LAYOUT_REQUEST_API_UNKNOWN" : "CP_STATIC_LAYOUT_REQUEST_API_OBSERVED", {
|
|
696
|
-
requestApi: api,
|
|
697
|
-
status
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
return {
|
|
701
|
-
kind: "proof",
|
|
702
|
-
proof: {
|
|
703
|
-
authorizesRuntimeReuse: true,
|
|
704
|
-
candidateOutput,
|
|
705
|
-
code: "CP_STATIC_LAYOUT_REUSE_PROVEN",
|
|
706
|
-
currentOutput,
|
|
707
|
-
fields: {
|
|
708
|
-
candidateRouteId: candidateOutput.routeId,
|
|
709
|
-
currentRouteId: currentOutput.routeId,
|
|
710
|
-
layoutId: currentOutput.layoutId,
|
|
711
|
-
rootBoundaryId: currentOutput.rootBoundaryId
|
|
712
|
-
},
|
|
713
|
-
observation: candidateObservation,
|
|
714
|
-
requiredNegativeRequestApis: [...requiredNegativeRequestApis],
|
|
715
|
-
reuseClass: "static-layout",
|
|
716
|
-
variant: input.candidateVariant
|
|
717
|
-
}
|
|
718
|
-
};
|
|
719
|
-
}
|
|
720
|
-
function createCacheProofHotPathMetric(outcome, code, fields) {
|
|
721
|
-
return {
|
|
722
|
-
name: "vinext.cache.static_layout_artifact_reuse",
|
|
723
|
-
outcome,
|
|
724
|
-
code,
|
|
725
|
-
fields
|
|
726
|
-
};
|
|
727
|
-
}
|
|
728
|
-
function createStaticLayoutArtifactReuseFallback(fallback) {
|
|
729
|
-
return {
|
|
730
|
-
kind: "fallback",
|
|
731
|
-
canReuse: false,
|
|
732
|
-
fallback,
|
|
733
|
-
metric: createCacheProofHotPathMetric("fallback", fallback.code, fallback.fields)
|
|
734
|
-
};
|
|
735
|
-
}
|
|
736
|
-
function createStaticLayoutArtifactReuseDecision(input) {
|
|
737
|
-
if (input.candidateVariant.kind === "breakerFallback") return createStaticLayoutArtifactReuseFallback(input.candidateVariant.fallback);
|
|
738
|
-
const artifactCompatibility = evaluateArtifactCompatibility(input.currentArtifactCompatibility, input.candidateArtifactCompatibility, { compatibilityMap: input.compatibilityMap });
|
|
739
|
-
if (artifactCompatibility.kind === "unknown") return createStaticLayoutArtifactReuseFallback(buildBreakerFallback("CP_ARTIFACT_COMPATIBILITY_UNKNOWN", {
|
|
740
|
-
compatibilityFallback: artifactCompatibility.fallback,
|
|
741
|
-
reason: artifactCompatibility.reason
|
|
742
|
-
}));
|
|
743
|
-
if (artifactCompatibility.kind === "incompatible") return createStaticLayoutArtifactReuseFallback(buildBreakerFallback("CP_ARTIFACT_COMPATIBILITY_INCOMPATIBLE", {
|
|
744
|
-
compatibilityFallback: artifactCompatibility.fallback,
|
|
745
|
-
reason: artifactCompatibility.reason
|
|
746
|
-
}));
|
|
747
|
-
const proof = buildStaticLayoutReuseProof({
|
|
748
|
-
candidateObservation: input.candidateObservation,
|
|
749
|
-
candidateVariant: input.candidateVariant.variant,
|
|
750
|
-
currentOutput: input.currentOutput
|
|
751
|
-
});
|
|
752
|
-
if (proof.kind === "rejected") return createStaticLayoutArtifactReuseFallback(proof.fallback);
|
|
753
|
-
return {
|
|
754
|
-
kind: "reuse",
|
|
755
|
-
canReuse: true,
|
|
756
|
-
proof: {
|
|
757
|
-
...proof.proof,
|
|
758
|
-
candidateArtifactCompatibility: { ...input.candidateArtifactCompatibility }
|
|
759
|
-
},
|
|
760
|
-
metric: createCacheProofHotPathMetric("reuse", proof.proof.code, proof.proof.fields)
|
|
761
|
-
};
|
|
762
|
-
}
|
|
763
230
|
function createCacheEntryReuseProof(decision) {
|
|
764
231
|
if (decision === null) return {
|
|
765
232
|
kind: "runtime-cache-entry",
|
|
@@ -788,15 +255,5 @@ function createCacheEntryReuseProof(decision) {
|
|
|
788
255
|
default: return assertNever(decision);
|
|
789
256
|
}
|
|
790
257
|
}
|
|
791
|
-
function createDisabledCacheProofDecision(input) {
|
|
792
|
-
return {
|
|
793
|
-
kind: "disabled",
|
|
794
|
-
canReuse: false,
|
|
795
|
-
variant: input.variant,
|
|
796
|
-
observation: input.observation,
|
|
797
|
-
...input.staticLayoutProof ? { staticLayoutProof: input.staticLayoutProof } : {},
|
|
798
|
-
fallback: buildBreakerFallback("CP_MODEL_DISABLED")
|
|
799
|
-
};
|
|
800
|
-
}
|
|
801
258
|
//#endregion
|
|
802
|
-
export { ALL_RENDER_REQUEST_API_KINDS, CACHE_PROOF_MODEL_SCHEMA_VERSION,
|
|
259
|
+
export { ALL_RENDER_REQUEST_API_KINDS, CACHE_PROOF_MODEL_SCHEMA_VERSION, buildRenderObservation, buildRenderRequestApiObservations, classifyRenderObservationDowngrade, createCacheEntryReuseProof, hasCompleteNegativeRequestApiProof, hasQueryInvariantRenderProof };
|
|
@@ -118,7 +118,7 @@ function cacheabilityRequestIdentity(request, trustedRepresentation) {
|
|
|
118
118
|
representation: "pages-data",
|
|
119
119
|
requestKey
|
|
120
120
|
};
|
|
121
|
-
if (!(request.headers.get("RSC") === "1"
|
|
121
|
+
if (!(request.headers.get("RSC") === "1")) return (request.headers.get("Accept")?.toLowerCase() ?? "").includes("text/html") ? {
|
|
122
122
|
representation: "html",
|
|
123
123
|
requestKey
|
|
124
124
|
} : {
|
|
@@ -146,7 +146,6 @@ function normalizeCacheabilityRoutePathname(pathname) {
|
|
|
146
146
|
}
|
|
147
147
|
function cacheabilityRoutePathname(pathname, representation) {
|
|
148
148
|
const normalized = new URL(pathname, "http://vinext.local").pathname;
|
|
149
|
-
if (representation === "rsc-full" || representation === "rsc-loading-shell") return normalizeCacheabilityRoutePathname(normalized.endsWith(".rsc") ? normalized.slice(0, -4) : normalized);
|
|
150
149
|
if (representation !== "pages-data") return normalizeCacheabilityRoutePathname(normalized);
|
|
151
150
|
const marker = normalized.indexOf("/_next/data/");
|
|
152
151
|
const restWithBuildId = marker === -1 ? "" : normalized.slice(marker + 12);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../utils/protocol-headers.js";
|
|
2
2
|
import { isVinextRscVaryField } from "./app-rsc-vary.js";
|
|
3
|
-
import { VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER, VINEXT_SPECIAL_ERROR_STATUS_HEADER } from "./headers.js";
|
|
3
|
+
import { NEXT_ROUTER_STALE_TIME_HEADER, VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER, VINEXT_SPECIAL_ERROR_STATUS_HEADER, VINEXT_STALE_TIME_PENDING_HEADER } from "./headers.js";
|
|
4
4
|
import { hasSharedCacheCredentials, isNonCacheableCacheControl } from "../shims/cdn-cache.js";
|
|
5
5
|
import { CACHEABILITY_REQUEST_STATE, recordConfigCdnCachePolicyHeader } from "../shims/cacheability-classification.js";
|
|
6
6
|
import { NO_STORE_CACHE_CONTROL, applyCdnResponseBuildIdentityHeaders, applyCdnResponseHeaders, hasExplicitNonCacheableResponsePolicy, isCdnResponsePolicyHeader, readCdnResponseCacheControl, readCdnResponsePolicyHeaderName } from "./cache-control.js";
|
|
@@ -348,20 +348,25 @@ async function captureCacheabilityAdmissionBody(body, deadlineAt, limit = CACHEA
|
|
|
348
348
|
throw error;
|
|
349
349
|
}
|
|
350
350
|
}
|
|
351
|
-
function responseWithCachePolicy(response, body, outcome, browserCacheControl,
|
|
351
|
+
function responseWithCachePolicy(response, body, outcome, browserCacheControl, completedRender) {
|
|
352
352
|
const headers = new Headers(response.headers);
|
|
353
353
|
if (typeof body === "string") headers.delete("Content-Length");
|
|
354
|
-
for (const [name, value] of Object.entries(
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
354
|
+
for (const [name, value] of Object.entries(completedRender?.headers ?? {})) if (!headers.has(name)) headers.set(name, value);
|
|
355
|
+
const cacheControl = outcome?.cacheable === true ? outcome.cacheControl : void 0;
|
|
356
|
+
applyCdnResponseHeaders(headers, cacheControl ? {
|
|
357
|
+
cacheControl,
|
|
358
|
+
tags: outcome?.tags,
|
|
358
359
|
browserCacheControl
|
|
359
360
|
} : {
|
|
360
361
|
cacheControl: NO_STORE_CACHE_CONTROL,
|
|
361
362
|
browserCacheControl
|
|
362
363
|
});
|
|
363
|
-
|
|
364
|
-
|
|
364
|
+
if (cacheControl && completedRender) {
|
|
365
|
+
headers.delete(VINEXT_STALE_TIME_PENDING_HEADER);
|
|
366
|
+
if (completedRender.staleTimeSeconds !== void 0 && !headers.has("x-nextjs-stale-time")) headers.set(NEXT_ROUTER_STALE_TIME_HEADER, String(Math.floor(completedRender.staleTimeSeconds)));
|
|
367
|
+
}
|
|
368
|
+
const status = completedRender?.status ?? response.status;
|
|
369
|
+
const completed = completedRender?.status;
|
|
365
370
|
if (completed === 401 || completed === 403 || completed === 404) headers.set(VINEXT_SPECIAL_ERROR_STATUS_HEADER, String(completed));
|
|
366
371
|
return new Response(body, {
|
|
367
372
|
headers,
|
|
@@ -41,7 +41,8 @@ export declare function isCrossSiteNoCorsRequest(secFetchSite: string | null | u
|
|
|
41
41
|
* Validate a dev server request from a Node.js IncomingMessage.
|
|
42
42
|
*
|
|
43
43
|
* Returns null if the request is allowed, or a reason string if it should be blocked.
|
|
44
|
-
* This is used by the
|
|
44
|
+
* This is used by the vinext:dev-origin-check connect middleware and the Pages
|
|
45
|
+
* Router handler.
|
|
45
46
|
*/
|
|
46
47
|
export declare function validateDevRequest(headers: {
|
|
47
48
|
origin?: string;
|
|
@@ -74,7 +74,8 @@ function isCrossSiteNoCorsRequest(secFetchSite, secFetchMode) {
|
|
|
74
74
|
* Validate a dev server request from a Node.js IncomingMessage.
|
|
75
75
|
*
|
|
76
76
|
* Returns null if the request is allowed, or a reason string if it should be blocked.
|
|
77
|
-
* This is used by the
|
|
77
|
+
* This is used by the vinext:dev-origin-check connect middleware and the Pages
|
|
78
|
+
* Router handler.
|
|
78
79
|
*/
|
|
79
80
|
function validateDevRequest(headers, allowedDevOrigins) {
|
|
80
81
|
if (isCrossSiteNoCorsRequest(headers["sec-fetch-site"], headers["sec-fetch-mode"])) return `cross-site no-cors request blocked`;
|