vinext 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build/prerender.d.ts +9 -1
- package/dist/build/prerender.js +41 -12
- package/dist/build/run-prerender.d.ts +10 -2
- package/dist/build/run-prerender.js +15 -1
- package/dist/client/app-nav-failure-handler.d.ts +8 -0
- package/dist/client/app-nav-failure-handler.js +44 -0
- package/dist/client/vinext-next-data.d.ts +18 -1
- package/dist/client/window-next.d.ts +2 -1
- package/dist/client/window-next.js +12 -1
- package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
- package/dist/config/config-matchers.js +73 -14
- package/dist/config/next-config.d.ts +46 -4
- package/dist/config/next-config.js +147 -48
- package/dist/deploy.d.ts +30 -11
- package/dist/deploy.js +180 -99
- package/dist/entries/app-browser-entry.d.ts +9 -3
- package/dist/entries/app-browser-entry.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +64 -5
- package/dist/entries/app-rsc-manifest.js +2 -0
- package/dist/entries/app-ssr-entry.js +1 -1
- package/dist/entries/pages-client-entry.js +53 -8
- package/dist/entries/pages-server-entry.js +41 -5
- package/dist/index.js +200 -62
- package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
- package/dist/plugins/extensionless-dynamic-import.js +152 -0
- package/dist/plugins/optimize-imports.d.ts +2 -1
- package/dist/plugins/optimize-imports.js +11 -9
- package/dist/plugins/postcss.js +7 -7
- package/dist/plugins/typeof-window.d.ts +14 -0
- package/dist/plugins/typeof-window.js +150 -0
- package/dist/routing/app-route-graph.d.ts +2 -1
- package/dist/routing/app-route-graph.js +44 -14
- package/dist/routing/file-matcher.d.ts +10 -1
- package/dist/routing/file-matcher.js +22 -1
- package/dist/routing/pages-router.js +3 -3
- package/dist/routing/utils.d.ts +35 -6
- package/dist/routing/utils.js +59 -7
- package/dist/server/api-handler.d.ts +6 -1
- package/dist/server/api-handler.js +21 -15
- package/dist/server/app-browser-action-result.d.ts +19 -6
- package/dist/server/app-browser-action-result.js +19 -10
- package/dist/server/app-browser-entry.js +167 -90
- package/dist/server/app-browser-error.d.ts +10 -6
- package/dist/server/app-browser-error.js +43 -8
- package/dist/server/app-browser-hydration.d.ts +2 -0
- package/dist/server/app-browser-hydration.js +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +4 -2
- package/dist/server/app-browser-navigation-controller.js +23 -2
- package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
- package/dist/server/app-browser-server-action-navigation.js +9 -0
- package/dist/server/app-browser-stream.js +86 -43
- package/dist/server/app-elements-wire.d.ts +6 -1
- package/dist/server/app-elements-wire.js +14 -4
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-fallback-renderer.d.ts +1 -0
- package/dist/server/app-fallback-renderer.js +3 -1
- package/dist/server/app-optimistic-routing.js +2 -2
- package/dist/server/app-page-boundary-render.d.ts +1 -0
- package/dist/server/app-page-boundary-render.js +27 -14
- package/dist/server/app-page-cache-render.d.ts +53 -0
- package/dist/server/app-page-cache-render.js +91 -0
- package/dist/server/app-page-cache.d.ts +16 -2
- package/dist/server/app-page-cache.js +62 -1
- package/dist/server/app-page-dispatch.d.ts +26 -0
- package/dist/server/app-page-dispatch.js +149 -92
- package/dist/server/app-page-element-builder.d.ts +1 -0
- package/dist/server/app-page-element-builder.js +5 -2
- package/dist/server/app-page-execution.d.ts +6 -1
- package/dist/server/app-page-execution.js +21 -1
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +4 -0
- package/dist/server/app-page-render-observation.d.ts +3 -1
- package/dist/server/app-page-render-observation.js +17 -1
- package/dist/server/app-page-render.d.ts +12 -1
- package/dist/server/app-page-render.js +42 -4
- package/dist/server/app-page-request.d.ts +2 -0
- package/dist/server/app-page-request.js +2 -1
- package/dist/server/app-page-route-wiring.d.ts +3 -1
- package/dist/server/app-page-route-wiring.js +14 -5
- package/dist/server/app-page-stream.d.ts +15 -3
- package/dist/server/app-page-stream.js +11 -5
- package/dist/server/app-pages-bridge.d.ts +18 -0
- package/dist/server/app-pages-bridge.js +22 -5
- package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
- package/dist/server/app-ppr-fallback-shell-render.js +26 -0
- package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
- package/dist/server/app-ppr-fallback-shell.js +8 -1
- package/dist/server/app-route-handler-dispatch.js +9 -2
- package/dist/server/app-route-handler-policy.d.ts +1 -0
- package/dist/server/app-router-entry.js +5 -0
- package/dist/server/app-rsc-cache-busting.js +2 -0
- package/dist/server/app-rsc-handler.d.ts +25 -0
- package/dist/server/app-rsc-handler.js +154 -54
- package/dist/server/app-rsc-route-matching.d.ts +3 -0
- package/dist/server/app-rsc-route-matching.js +2 -0
- package/dist/server/app-segment-config.d.ts +9 -1
- package/dist/server/app-segment-config.js +12 -3
- package/dist/server/app-server-action-execution.d.ts +1 -0
- package/dist/server/app-server-action-execution.js +42 -13
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +83 -10
- package/dist/server/cache-control.js +4 -0
- package/dist/server/dev-server.d.ts +2 -2
- package/dist/server/dev-server.js +244 -51
- package/dist/server/hybrid-route-priority.d.ts +22 -0
- package/dist/server/hybrid-route-priority.js +33 -0
- package/dist/server/image-optimization.d.ts +18 -9
- package/dist/server/image-optimization.js +37 -23
- package/dist/server/implicit-tags.d.ts +2 -1
- package/dist/server/implicit-tags.js +4 -1
- package/dist/server/navigation-planner.d.ts +133 -30
- package/dist/server/navigation-planner.js +114 -0
- package/dist/server/navigation-trace.d.ts +8 -1
- package/dist/server/navigation-trace.js +8 -1
- package/dist/server/pages-api-route.d.ts +6 -0
- package/dist/server/pages-api-route.js +13 -2
- package/dist/server/pages-asset-tags.d.ts +2 -1
- package/dist/server/pages-asset-tags.js +6 -2
- package/dist/server/pages-data-route.d.ts +8 -1
- package/dist/server/pages-data-route.js +11 -2
- package/dist/server/pages-get-initial-props.d.ts +54 -4
- package/dist/server/pages-get-initial-props.js +43 -1
- package/dist/server/pages-node-compat.js +2 -2
- package/dist/server/pages-page-data.d.ts +11 -2
- package/dist/server/pages-page-data.js +204 -33
- package/dist/server/pages-page-handler.d.ts +4 -2
- package/dist/server/pages-page-handler.js +59 -22
- package/dist/server/pages-page-response.d.ts +2 -1
- package/dist/server/pages-page-response.js +7 -4
- package/dist/server/pages-request-pipeline.d.ts +1 -0
- package/dist/server/pages-request-pipeline.js +73 -36
- package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
- package/dist/server/pregenerated-concrete-paths.js +2 -19
- package/dist/server/prerender-manifest.d.ts +33 -0
- package/dist/server/prerender-manifest.js +54 -0
- package/dist/server/prerender-route-params.d.ts +1 -2
- package/dist/server/prod-server.js +9 -3
- package/dist/server/request-pipeline.d.ts +3 -15
- package/dist/server/request-pipeline.js +58 -47
- package/dist/server/rsc-stream-hints.d.ts +5 -1
- package/dist/server/rsc-stream-hints.js +6 -1
- package/dist/server/seed-cache.js +10 -18
- package/dist/shims/app-router-scroll-state.d.ts +3 -1
- package/dist/shims/app-router-scroll-state.js +14 -2
- package/dist/shims/app-router-scroll.d.ts +3 -0
- package/dist/shims/app-router-scroll.js +28 -18
- package/dist/shims/cache-runtime.js +3 -2
- package/dist/shims/cache.d.ts +1 -0
- package/dist/shims/cache.js +1 -1
- package/dist/shims/cdn-cache.d.ts +5 -5
- package/dist/shims/dynamic-preload-chunks.js +6 -4
- package/dist/shims/error-boundary.d.ts +2 -0
- package/dist/shims/error-boundary.js +7 -0
- package/dist/shims/error.js +3 -2
- package/dist/shims/error.react-server.d.ts +9 -0
- package/dist/shims/error.react-server.js +6 -0
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +45 -20
- package/dist/shims/hash-scroll.js +6 -1
- package/dist/shims/headers.js +29 -4
- package/dist/shims/internal/als-registry.js +28 -1
- package/dist/shims/internal/app-route-detection.js +8 -17
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
- package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
- package/dist/shims/internal/navigation-untracked.d.ts +35 -0
- package/dist/shims/internal/navigation-untracked.js +55 -0
- package/dist/shims/internal/pages-data-target.d.ts +7 -2
- package/dist/shims/internal/pages-data-target.js +17 -8
- package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
- package/dist/shims/internal/pages-router-accessor.js +13 -0
- package/dist/shims/internal/router-context.d.ts +2 -1
- package/dist/shims/internal/router-context.js +3 -1
- package/dist/shims/link.js +12 -5
- package/dist/shims/navigation.d.ts +8 -2
- package/dist/shims/navigation.js +61 -31
- package/dist/shims/ppr-fallback-shell.d.ts +5 -1
- package/dist/shims/ppr-fallback-shell.js +28 -7
- package/dist/shims/router.d.ts +13 -2
- package/dist/shims/router.js +419 -128
- package/dist/shims/server.d.ts +16 -1
- package/dist/shims/server.js +44 -12
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/built-asset-url.d.ts +4 -0
- package/dist/utils/built-asset-url.js +11 -0
- package/dist/utils/commonjs-loader.d.ts +16 -0
- package/dist/utils/commonjs-loader.js +100 -0
- package/dist/utils/deployment-id.d.ts +8 -0
- package/dist/utils/deployment-id.js +22 -0
- package/dist/utils/html-limited-bots.d.ts +18 -1
- package/dist/utils/html-limited-bots.js +23 -1
- package/dist/utils/parse-cookie.d.ts +13 -0
- package/dist/utils/parse-cookie.js +52 -0
- package/dist/utils/path.d.ts +7 -1
- package/dist/utils/path.js +9 -1
- package/package.json +2 -2
- package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
- package/dist/shims/internal/parse-cookie-header.js +0 -30
|
@@ -56,32 +56,46 @@ const DEFAULT_IMAGE_SIZES = [
|
|
|
56
56
|
256,
|
|
57
57
|
384
|
|
58
58
|
];
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
const DEV_BLUR_MAX_WIDTH = 8;
|
|
60
|
+
const DEV_BLUR_QUALITY = 70;
|
|
61
|
+
function resolveDevImageRedirect(requestUrl, allowedWidths = [...DEFAULT_DEVICE_SIZES, ...DEFAULT_IMAGE_SIZES], allowedQualities, options = { isDev: true }) {
|
|
62
|
+
const params = parseImageParams(requestUrl, allowedWidths, allowedQualities, options);
|
|
63
|
+
if (!params) return null;
|
|
64
|
+
if (params.imageUrl.startsWith("/@") || params.imageUrl.startsWith("/__vite") || params.imageUrl.startsWith("/node_modules")) return null;
|
|
65
|
+
const resolved = new URL(params.imageUrl, requestUrl.origin);
|
|
66
|
+
if (resolved.origin !== requestUrl.origin) return null;
|
|
67
|
+
return resolved.pathname + resolved.search;
|
|
68
|
+
}
|
|
65
69
|
/**
|
|
66
70
|
* Parse and validate image optimization query parameters.
|
|
67
71
|
* Returns null if the request is malformed.
|
|
68
72
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* When `allowedWidths` is not provided, any width from 0 to ABSOLUTE_MAX_WIDTH
|
|
74
|
-
* is accepted (backwards-compatible fallback).
|
|
73
|
+
* Ported from Next.js:
|
|
74
|
+
* test/integration/image-optimizer/test/index.test.ts
|
|
75
|
+
* https://github.com/vercel/next.js/blob/canary/test/integration/image-optimizer/test/index.test.ts
|
|
75
76
|
*/
|
|
76
|
-
function parseImageParams(url, allowedWidths) {
|
|
77
|
+
function parseImageParams(url, allowedWidths = [...DEFAULT_DEVICE_SIZES, ...DEFAULT_IMAGE_SIZES], allowedQualities, options = {}) {
|
|
78
|
+
const allowedParamNames = new Set([
|
|
79
|
+
"url",
|
|
80
|
+
"w",
|
|
81
|
+
"q"
|
|
82
|
+
]);
|
|
83
|
+
for (const name of url.searchParams.keys()) if (!allowedParamNames.has(name) || url.searchParams.getAll(name).length !== 1) return null;
|
|
77
84
|
const imageUrl = url.searchParams.get("url");
|
|
78
85
|
if (!imageUrl) return null;
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
if (
|
|
83
|
-
if (
|
|
84
|
-
|
|
86
|
+
if (imageUrl.length > 3072) return null;
|
|
87
|
+
const widthParam = url.searchParams.get("w");
|
|
88
|
+
const qualityParam = url.searchParams.get("q");
|
|
89
|
+
if (!widthParam || !/^[0-9]+$/.test(widthParam)) return null;
|
|
90
|
+
if (!qualityParam || !/^[0-9]+$/.test(qualityParam)) return null;
|
|
91
|
+
const width = Number.parseInt(widthParam, 10);
|
|
92
|
+
const quality = Number.parseInt(qualityParam, 10);
|
|
93
|
+
if (String(width) !== widthParam || String(quality) !== qualityParam) return null;
|
|
94
|
+
const isDevBlurWidth = options.isDev && width <= DEV_BLUR_MAX_WIDTH;
|
|
95
|
+
const isDevBlurQuality = options.isDev && quality === DEV_BLUR_QUALITY;
|
|
96
|
+
if (width <= 0 || !allowedWidths.includes(width) && !isDevBlurWidth) return null;
|
|
97
|
+
if (quality < 1 || quality > 100) return null;
|
|
98
|
+
if (allowedQualities && !allowedQualities.includes(quality) && !isDevBlurQuality) return null;
|
|
85
99
|
const normalizedUrl = imageUrl.replaceAll("\\", "/");
|
|
86
100
|
if (!normalizedUrl.startsWith("/") || normalizedUrl.startsWith("//")) return null;
|
|
87
101
|
try {
|
|
@@ -92,8 +106,8 @@ function parseImageParams(url, allowedWidths) {
|
|
|
92
106
|
}
|
|
93
107
|
return {
|
|
94
108
|
imageUrl: normalizedUrl,
|
|
95
|
-
width
|
|
96
|
-
quality
|
|
109
|
+
width,
|
|
110
|
+
quality
|
|
97
111
|
};
|
|
98
112
|
}
|
|
99
113
|
/**
|
|
@@ -174,7 +188,7 @@ function createPassthroughImageResponse(source, config) {
|
|
|
174
188
|
* cache headers.
|
|
175
189
|
*/
|
|
176
190
|
async function handleImageOptimization(request, handlers, allowedWidths, imageConfig) {
|
|
177
|
-
const params = parseImageParams(new URL(request.url), allowedWidths);
|
|
191
|
+
const params = parseImageParams(new URL(request.url), allowedWidths, imageConfig?.qualities);
|
|
178
192
|
if (!params) return badRequestResponse();
|
|
179
193
|
const { imageUrl, width, quality } = params;
|
|
180
194
|
const source = await handlers.fetchAsset(imageUrl, request);
|
|
@@ -212,4 +226,4 @@ async function handleImageOptimization(request, handlers, allowedWidths, imageCo
|
|
|
212
226
|
}
|
|
213
227
|
}
|
|
214
228
|
//#endregion
|
|
215
|
-
export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, VINEXT_IMAGE_OPTIMIZATION_PATH, handleImageOptimization, isImageOptimizationPath, isSafeImageContentType, negotiateImageFormat, parseImageParams };
|
|
229
|
+
export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, VINEXT_IMAGE_OPTIMIZATION_PATH, handleImageOptimization, isImageOptimizationPath, isSafeImageContentType, negotiateImageFormat, parseImageParams, resolveDevImageRedirect };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
//#region src/server/implicit-tags.d.ts
|
|
2
2
|
type AppCacheLeafKind = "page" | "route";
|
|
3
|
+
declare function buildAppPageTags(cleanPathname: string, extraTags: string[], routeSegments: readonly string[]): string[];
|
|
3
4
|
declare function buildPageCacheTags(pathname: string, extraTags: string[], routeSegments: string[], leafKind: AppCacheLeafKind): string[];
|
|
4
5
|
//#endregion
|
|
5
|
-
export { buildPageCacheTags };
|
|
6
|
+
export { buildAppPageTags, buildPageCacheTags };
|
|
@@ -29,6 +29,9 @@ function appendDerivedTags(tags, routePath) {
|
|
|
29
29
|
appendUnique(tags, `${NEXT_CACHE_IMPLICIT_TAG_ID}${currentPathname}`);
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
+
function buildAppPageTags(cleanPathname, extraTags, routeSegments) {
|
|
33
|
+
return buildPageCacheTags(cleanPathname, extraTags, [...routeSegments], "page");
|
|
34
|
+
}
|
|
32
35
|
function buildPageCacheTags(pathname, extraTags, routeSegments, leafKind) {
|
|
33
36
|
const tags = [pathname, `${NEXT_CACHE_IMPLICIT_TAG_ID}${pathname}`];
|
|
34
37
|
if (pathname === "/") appendUnique(tags, `${NEXT_CACHE_IMPLICIT_TAG_ID}/index`);
|
|
@@ -38,4 +41,4 @@ function buildPageCacheTags(pathname, extraTags, routeSegments, leafKind) {
|
|
|
38
41
|
return tags.map(encodeCacheTag);
|
|
39
42
|
}
|
|
40
43
|
//#endregion
|
|
41
|
-
export { buildPageCacheTags };
|
|
44
|
+
export { buildAppPageTags, buildPageCacheTags };
|
|
@@ -14,34 +14,34 @@ type OperationToken = {
|
|
|
14
14
|
targetSnapshotFingerprint: string;
|
|
15
15
|
cacheVariantFingerprint?: string;
|
|
16
16
|
};
|
|
17
|
-
type
|
|
18
|
-
interception:
|
|
17
|
+
type RouteSnapshot = {
|
|
18
|
+
interception: InterceptionSnapshot | null;
|
|
19
19
|
interceptionContext: string | null;
|
|
20
20
|
routeId: string;
|
|
21
21
|
layoutIds: readonly string[];
|
|
22
|
-
mountedParallelSlots: readonly
|
|
22
|
+
mountedParallelSlots: readonly MountedParallelSlotSnapshot[];
|
|
23
23
|
rootBoundaryId: string | null;
|
|
24
24
|
displayUrl: string;
|
|
25
25
|
matchedUrl: string;
|
|
26
|
-
slotBindings: readonly
|
|
26
|
+
slotBindings: readonly ParallelSlotBindingSnapshot[];
|
|
27
27
|
};
|
|
28
|
-
type
|
|
28
|
+
type InterceptionSnapshot = {
|
|
29
29
|
sourceMatchedUrl: string;
|
|
30
30
|
sourceRouteId: string;
|
|
31
31
|
slotId: string;
|
|
32
32
|
targetMatchedUrl: string;
|
|
33
33
|
targetRouteId: string;
|
|
34
34
|
};
|
|
35
|
-
type
|
|
35
|
+
type MountedParallelSlotSnapshot = {
|
|
36
36
|
slotId: string;
|
|
37
37
|
ownerLayoutId: string | null;
|
|
38
38
|
};
|
|
39
|
-
type
|
|
40
|
-
type
|
|
39
|
+
type ParallelSlotBindingSnapshot = AppElementsSlotBinding;
|
|
40
|
+
type NavigationPlannerState = {
|
|
41
41
|
nextOperationToken: OperationToken;
|
|
42
42
|
traceFields?: NavigationTraceFields;
|
|
43
43
|
visibleCommitVersion: number;
|
|
44
|
-
visibleSnapshot:
|
|
44
|
+
visibleSnapshot: RouteSnapshot;
|
|
45
45
|
};
|
|
46
46
|
type RefreshScope = "visible";
|
|
47
47
|
type TraverseDirection = "back" | "forward" | "unknown";
|
|
@@ -62,7 +62,7 @@ type NavigationEvent = {
|
|
|
62
62
|
} | {
|
|
63
63
|
kind: "flightResponseArrived";
|
|
64
64
|
token: OperationToken;
|
|
65
|
-
result:
|
|
65
|
+
result: FlightResult;
|
|
66
66
|
};
|
|
67
67
|
type RequestedWork = {
|
|
68
68
|
kind: "flight";
|
|
@@ -82,12 +82,12 @@ type CommitProposal = {
|
|
|
82
82
|
preserveElementIds: readonly string[];
|
|
83
83
|
preservePreviousSlotIds: readonly string[];
|
|
84
84
|
reason: "currentRootBoundary" | "interceptedCurrentRootBoundary" | "unprovenTopologyFallback";
|
|
85
|
-
targetSnapshot:
|
|
85
|
+
targetSnapshot: RouteSnapshot;
|
|
86
86
|
};
|
|
87
87
|
type NoCommitReason = "prefetchOnly";
|
|
88
88
|
type HardNavigationReason = "cacheProofRejected" | "interceptionProofRejected" | "rootBoundaryChanged";
|
|
89
89
|
type RootBoundaryTransition = "currentRootBoundary" | "rootBoundaryChanged" | "rootBoundaryUnknown";
|
|
90
|
-
type
|
|
90
|
+
type NavigationDecision = {
|
|
91
91
|
kind: "requestWork";
|
|
92
92
|
token: OperationToken;
|
|
93
93
|
work: RequestedWork;
|
|
@@ -109,13 +109,13 @@ type NavigationDecisionV0 = {
|
|
|
109
109
|
reason: HardNavigationReason;
|
|
110
110
|
trace: NavigationTrace;
|
|
111
111
|
};
|
|
112
|
-
type
|
|
112
|
+
type FlightResult = {
|
|
113
113
|
cacheEntryReuseProof?: CacheEntryReuseProof;
|
|
114
114
|
href: string;
|
|
115
|
-
targetSnapshot:
|
|
115
|
+
targetSnapshot: RouteSnapshot;
|
|
116
116
|
};
|
|
117
117
|
type RscFetchResultSource = "cached" | "live";
|
|
118
|
-
type
|
|
118
|
+
type RscFetchResultFacts = {
|
|
119
119
|
source: RscFetchResultSource;
|
|
120
120
|
currentHref: string;
|
|
121
121
|
origin: string;
|
|
@@ -130,21 +130,21 @@ type RscFetchResultFactsV0 = {
|
|
|
130
130
|
responseUrl: string | null;
|
|
131
131
|
streamedRedirectTarget: string | null;
|
|
132
132
|
};
|
|
133
|
-
type
|
|
133
|
+
type RscRedirectFollow = {
|
|
134
134
|
href: string;
|
|
135
135
|
historyUpdateMode: "push" | "replace";
|
|
136
136
|
previousNextUrl: string | null;
|
|
137
137
|
redirectDepth: number;
|
|
138
138
|
};
|
|
139
139
|
type RscFetchResultHardNavReason = "invalidRscPayload" | "rscCompatibilityMismatch" | "externalRedirectTarget" | "redirectDepthExhausted" | "streamedRedirectLoop";
|
|
140
|
-
type
|
|
140
|
+
type RscFetchResultDecision = {
|
|
141
141
|
kind: "proceedToCommit";
|
|
142
142
|
discardBody: false;
|
|
143
143
|
trace: NavigationTrace;
|
|
144
144
|
} | {
|
|
145
145
|
kind: "followRedirect";
|
|
146
146
|
discardBody: boolean;
|
|
147
|
-
redirect:
|
|
147
|
+
redirect: RscRedirectFollow;
|
|
148
148
|
trace: NavigationTrace;
|
|
149
149
|
} | {
|
|
150
150
|
kind: "hardNavigate";
|
|
@@ -153,14 +153,14 @@ type RscFetchResultDecisionV0 = {
|
|
|
153
153
|
reason: RscFetchResultHardNavReason;
|
|
154
154
|
trace: NavigationTrace;
|
|
155
155
|
};
|
|
156
|
-
type
|
|
156
|
+
type EarlyNavigationIntentFacts = {
|
|
157
157
|
basePath: string;
|
|
158
158
|
currentHref: string;
|
|
159
159
|
mode: "push" | "replace";
|
|
160
160
|
scroll: boolean;
|
|
161
161
|
targetHref: string;
|
|
162
162
|
};
|
|
163
|
-
type
|
|
163
|
+
type EarlyNavigationIntentDecision = {
|
|
164
164
|
kind: "sameDocumentScroll";
|
|
165
165
|
hash: string;
|
|
166
166
|
mode: "push" | "replace";
|
|
@@ -171,20 +171,86 @@ type EarlyNavigationIntentDecisionV0 = {
|
|
|
171
171
|
bypassNavigationCache: boolean;
|
|
172
172
|
trace: NavigationTrace;
|
|
173
173
|
};
|
|
174
|
+
type NavigationReuseNavigationKind = "navigate" | "refresh" | "traverse";
|
|
175
|
+
type VisitedResponseCacheCandidateFacts = {
|
|
176
|
+
candidate: "missing";
|
|
177
|
+
navigationKind: NavigationReuseNavigationKind;
|
|
178
|
+
} | {
|
|
179
|
+
candidate: "present";
|
|
180
|
+
fresh: boolean;
|
|
181
|
+
mountedSlotsMatch: boolean;
|
|
182
|
+
navigationKind: NavigationReuseNavigationKind;
|
|
183
|
+
};
|
|
184
|
+
type VisitedResponseCacheCandidateDecision = {
|
|
185
|
+
kind: "miss";
|
|
186
|
+
} | {
|
|
187
|
+
kind: "evict";
|
|
188
|
+
reason: "mountedSlotsMismatch" | "refresh" | "stale";
|
|
189
|
+
} | {
|
|
190
|
+
kind: "reuse";
|
|
191
|
+
};
|
|
192
|
+
type NavigationReuseCandidateAvailability = {
|
|
193
|
+
status: "available";
|
|
194
|
+
} | {
|
|
195
|
+
status: "unavailable";
|
|
196
|
+
};
|
|
197
|
+
type OptimisticRouteShellCandidateAvailability = {
|
|
198
|
+
status: "available";
|
|
199
|
+
} | {
|
|
200
|
+
status: "unavailable";
|
|
201
|
+
reason: "routeManifestMissing";
|
|
202
|
+
};
|
|
203
|
+
type NavigationReuseFacts = {
|
|
204
|
+
bypassNavigationCache: boolean;
|
|
205
|
+
navigationKind: NavigationReuseNavigationKind;
|
|
206
|
+
optimisticRouteShell: OptimisticRouteShellCandidateAvailability;
|
|
207
|
+
prefetch: NavigationReuseCandidateAvailability;
|
|
208
|
+
targetHref: string;
|
|
209
|
+
visitedResponse: NavigationReuseCandidateAvailability;
|
|
210
|
+
};
|
|
211
|
+
type FreshFetchReason = "cacheBypassed" | "cacheMiss" | "refresh" | "routeManifestMissing";
|
|
212
|
+
type NavigationReuseDecision = {
|
|
213
|
+
kind: "reuseVisitedResponse";
|
|
214
|
+
trace: NavigationTrace;
|
|
215
|
+
} | {
|
|
216
|
+
kind: "consumePrefetch";
|
|
217
|
+
trace: NavigationTrace;
|
|
218
|
+
} | {
|
|
219
|
+
kind: "attemptOptimisticRouteShell";
|
|
220
|
+
trace: NavigationTrace;
|
|
221
|
+
} | {
|
|
222
|
+
kind: "fetchFresh";
|
|
223
|
+
reason: FreshFetchReason;
|
|
224
|
+
trace: NavigationTrace;
|
|
225
|
+
};
|
|
226
|
+
type NavigationPrefetchProbeFacts = {
|
|
227
|
+
bypassNavigationCache: boolean;
|
|
228
|
+
navigationKind: NavigationReuseNavigationKind;
|
|
229
|
+
visitedResponse: NavigationReuseCandidateAvailability;
|
|
230
|
+
};
|
|
231
|
+
type NavigationPrefetchProbeDecision = {
|
|
232
|
+
kind: "probe";
|
|
233
|
+
} | {
|
|
234
|
+
kind: "skip";
|
|
235
|
+
reason: "cacheBypassed" | "refresh" | "visitedResponseAvailable";
|
|
236
|
+
};
|
|
174
237
|
type NavigationPlannerInput = {
|
|
175
238
|
routeManifest: RouteManifest | null;
|
|
176
|
-
state:
|
|
239
|
+
state: NavigationPlannerState;
|
|
177
240
|
event: NavigationEvent;
|
|
178
241
|
};
|
|
179
242
|
type AcceptedCacheEntryReuseDecision = Extract<CacheEntryReuseDecision, {
|
|
180
243
|
canReuse: true;
|
|
181
244
|
}>;
|
|
182
|
-
declare function classifyRscFetchResult(facts:
|
|
183
|
-
declare function classifyEarlyNavigationIntent(facts:
|
|
245
|
+
declare function classifyRscFetchResult(facts: RscFetchResultFacts): RscFetchResultDecision;
|
|
246
|
+
declare function classifyEarlyNavigationIntent(facts: EarlyNavigationIntentFacts): EarlyNavigationIntentDecision;
|
|
247
|
+
declare function classifyVisitedResponseCacheCandidate(facts: VisitedResponseCacheCandidateFacts): VisitedResponseCacheCandidateDecision;
|
|
248
|
+
declare function classifyNavigationReuse(facts: NavigationReuseFacts): NavigationReuseDecision;
|
|
249
|
+
declare function classifyNavigationPrefetchProbe(facts: NavigationPrefetchProbeFacts): NavigationPrefetchProbeDecision;
|
|
184
250
|
declare function classifyRootBoundaryTransition(currentRootBoundaryId: string | null, nextRootBoundaryId: string | null): RootBoundaryTransition;
|
|
185
|
-
declare function resolveSameLayoutAncestorPersistence(currentSnapshot:
|
|
186
|
-
declare function resolveMountedParallelSlotPersistence(currentSnapshot:
|
|
187
|
-
declare function resolveCurrentRootBoundaryElementPersistence(currentSnapshot:
|
|
251
|
+
declare function resolveSameLayoutAncestorPersistence(currentSnapshot: RouteSnapshot, targetSnapshot: RouteSnapshot): readonly string[];
|
|
252
|
+
declare function resolveMountedParallelSlotPersistence(currentSnapshot: RouteSnapshot, targetSnapshot: RouteSnapshot): readonly string[];
|
|
253
|
+
declare function resolveCurrentRootBoundaryElementPersistence(currentSnapshot: RouteSnapshot, targetSnapshot: RouteSnapshot): readonly string[];
|
|
188
254
|
/**
|
|
189
255
|
* Default/unmatched slot preservation law:
|
|
190
256
|
*
|
|
@@ -196,19 +262,56 @@ declare function resolveCurrentRootBoundaryElementPersistence(currentSnapshot: R
|
|
|
196
262
|
* Wire absence and UNMATCHED_SLOT markers are not semantic proof.
|
|
197
263
|
*/
|
|
198
264
|
declare function resolveDefaultOrUnmatchedSlotPersistenceForLayouts(options: {
|
|
199
|
-
currentSlotBindings: readonly
|
|
265
|
+
currentSlotBindings: readonly ParallelSlotBindingSnapshot[];
|
|
200
266
|
preservedLayoutIds: readonly string[];
|
|
201
|
-
targetSlotBindings: readonly
|
|
267
|
+
targetSlotBindings: readonly ParallelSlotBindingSnapshot[];
|
|
202
268
|
}): readonly string[];
|
|
203
|
-
declare function planNavigation(input: NavigationPlannerInput):
|
|
269
|
+
declare function planNavigation(input: NavigationPlannerInput): NavigationDecision;
|
|
270
|
+
type ServerActionResultFacts = {
|
|
271
|
+
actionRedirectHref: string | null;
|
|
272
|
+
actionRedirectType: "push" | "replace";
|
|
273
|
+
clientCompatibilityId: string | null;
|
|
274
|
+
compatibilityIdHeader: string | null;
|
|
275
|
+
currentHref: string;
|
|
276
|
+
isRscContentType: boolean;
|
|
277
|
+
origin: string;
|
|
278
|
+
responseUrl: string | null;
|
|
279
|
+
};
|
|
280
|
+
type ServerActionResultDecision = {
|
|
281
|
+
kind: "proceed";
|
|
282
|
+
trace: NavigationTrace;
|
|
283
|
+
} | {
|
|
284
|
+
kind: "hardNavigate";
|
|
285
|
+
url: string;
|
|
286
|
+
historyMode?: "assign" | "replace";
|
|
287
|
+
clearClientNavigationCaches: boolean;
|
|
288
|
+
reason: "serverActionRedirectCompatibilityMismatch" | "serverActionRscCompatibilityMismatch";
|
|
289
|
+
trace: NavigationTrace;
|
|
290
|
+
};
|
|
291
|
+
type RscNavigationErrorFacts = {
|
|
292
|
+
currentHref: string;
|
|
293
|
+
};
|
|
294
|
+
type RscNavigationErrorDecision = {
|
|
295
|
+
kind: "hardNavigate";
|
|
296
|
+
url: string;
|
|
297
|
+
reason: "rscNavigationError";
|
|
298
|
+
trace: NavigationTrace;
|
|
299
|
+
};
|
|
300
|
+
declare function classifyServerActionResult(facts: ServerActionResultFacts): ServerActionResultDecision;
|
|
301
|
+
declare function classifyRscNavigationError(facts: RscNavigationErrorFacts): RscNavigationErrorDecision;
|
|
204
302
|
declare const navigationPlanner: {
|
|
205
303
|
classifyEarlyNavigationIntent: typeof classifyEarlyNavigationIntent;
|
|
304
|
+
classifyNavigationPrefetchProbe: typeof classifyNavigationPrefetchProbe;
|
|
305
|
+
classifyNavigationReuse: typeof classifyNavigationReuse;
|
|
206
306
|
classifyRscFetchResult: typeof classifyRscFetchResult;
|
|
307
|
+
classifyRscNavigationError: typeof classifyRscNavigationError;
|
|
207
308
|
classifyRootBoundaryTransition: typeof classifyRootBoundaryTransition;
|
|
309
|
+
classifyServerActionResult: typeof classifyServerActionResult;
|
|
310
|
+
classifyVisitedResponseCacheCandidate: typeof classifyVisitedResponseCacheCandidate;
|
|
208
311
|
plan: typeof planNavigation;
|
|
209
312
|
resolveCurrentRootBoundaryElementPersistence: typeof resolveCurrentRootBoundaryElementPersistence;
|
|
210
313
|
resolveMountedParallelSlotPersistence: typeof resolveMountedParallelSlotPersistence;
|
|
211
314
|
resolveSameLayoutAncestorPersistence: typeof resolveSameLayoutAncestorPersistence;
|
|
212
315
|
};
|
|
213
316
|
//#endregion
|
|
214
|
-
export {
|
|
317
|
+
export { EarlyNavigationIntentDecision, EarlyNavigationIntentFacts, FlightResult, InterceptionSnapshot, MountedParallelSlotSnapshot, NavigationDecision, NavigationEvent, NavigationPlannerInput, NavigationPlannerState, NavigationReuseDecision, NavigationReuseFacts, OperationLane, OperationToken, ParallelSlotBindingSnapshot, RefreshScope, RootBoundaryTransition, RouteSnapshot, RscFetchResultDecision, RscFetchResultFacts, RscNavigationErrorDecision, RscNavigationErrorFacts, ServerActionResultDecision, ServerActionResultFacts, TraverseDirection, VisitedResponseCacheCandidateFacts, navigationPlanner, resolveDefaultOrUnmatchedSlotPersistenceForLayouts };
|
|
@@ -213,6 +213,71 @@ function classifyEarlyNavigationIntent(facts) {
|
|
|
213
213
|
trace: createEarlyNavigationIntentTrace(NavigationTraceReasonCodes.crossDocumentFlight, facts)
|
|
214
214
|
};
|
|
215
215
|
}
|
|
216
|
+
function classifyVisitedResponseCacheCandidate(facts) {
|
|
217
|
+
if (facts.candidate === "missing") return { kind: "miss" };
|
|
218
|
+
if (!facts.mountedSlotsMatch) return {
|
|
219
|
+
kind: "evict",
|
|
220
|
+
reason: "mountedSlotsMismatch"
|
|
221
|
+
};
|
|
222
|
+
if (facts.navigationKind === "refresh") return {
|
|
223
|
+
kind: "evict",
|
|
224
|
+
reason: "refresh"
|
|
225
|
+
};
|
|
226
|
+
if (!facts.fresh) return {
|
|
227
|
+
kind: "evict",
|
|
228
|
+
reason: "stale"
|
|
229
|
+
};
|
|
230
|
+
return { kind: "reuse" };
|
|
231
|
+
}
|
|
232
|
+
function createNavigationReuseTrace(code, facts, fields = {}) {
|
|
233
|
+
return createNavigationTrace(code, {
|
|
234
|
+
eventKind: facts.navigationKind,
|
|
235
|
+
targetHref: facts.targetHref,
|
|
236
|
+
...fields
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
function createFreshFetchDecision(facts, reason) {
|
|
240
|
+
return {
|
|
241
|
+
kind: "fetchFresh",
|
|
242
|
+
reason,
|
|
243
|
+
trace: createNavigationReuseTrace(NavigationTraceReasonCodes.fetchFresh, facts, { freshFetchReason: reason })
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
function classifyNavigationReuse(facts) {
|
|
247
|
+
if (facts.navigationKind === "refresh") return createFreshFetchDecision(facts, "refresh");
|
|
248
|
+
if (!facts.bypassNavigationCache && facts.visitedResponse.status === "available") return {
|
|
249
|
+
kind: "reuseVisitedResponse",
|
|
250
|
+
trace: createNavigationReuseTrace(NavigationTraceReasonCodes.visitedResponseReuse, facts)
|
|
251
|
+
};
|
|
252
|
+
if (!facts.bypassNavigationCache && facts.prefetch.status === "available") return {
|
|
253
|
+
kind: "consumePrefetch",
|
|
254
|
+
trace: createNavigationReuseTrace(NavigationTraceReasonCodes.prefetchResponseReuse, facts)
|
|
255
|
+
};
|
|
256
|
+
if (facts.navigationKind === "navigate") {
|
|
257
|
+
if (facts.optimisticRouteShell.status === "available") return {
|
|
258
|
+
kind: "attemptOptimisticRouteShell",
|
|
259
|
+
trace: createNavigationReuseTrace(NavigationTraceReasonCodes.optimisticRouteShell, facts)
|
|
260
|
+
};
|
|
261
|
+
return createFreshFetchDecision(facts, facts.bypassNavigationCache ? "cacheBypassed" : facts.optimisticRouteShell.reason);
|
|
262
|
+
}
|
|
263
|
+
if (facts.bypassNavigationCache) return createFreshFetchDecision(facts, "cacheBypassed");
|
|
264
|
+
return createFreshFetchDecision(facts, "cacheMiss");
|
|
265
|
+
}
|
|
266
|
+
function classifyNavigationPrefetchProbe(facts) {
|
|
267
|
+
if (facts.visitedResponse.status === "available") return {
|
|
268
|
+
kind: "skip",
|
|
269
|
+
reason: "visitedResponseAvailable"
|
|
270
|
+
};
|
|
271
|
+
if (facts.navigationKind === "refresh") return {
|
|
272
|
+
kind: "skip",
|
|
273
|
+
reason: "refresh"
|
|
274
|
+
};
|
|
275
|
+
if (facts.bypassNavigationCache) return {
|
|
276
|
+
kind: "skip",
|
|
277
|
+
reason: "cacheBypassed"
|
|
278
|
+
};
|
|
279
|
+
return { kind: "probe" };
|
|
280
|
+
}
|
|
216
281
|
function createSnapshotRouteTopology(snapshot) {
|
|
217
282
|
return {
|
|
218
283
|
layoutIds: snapshot.layoutIds,
|
|
@@ -680,10 +745,59 @@ function planNavigation(input) {
|
|
|
680
745
|
}
|
|
681
746
|
}
|
|
682
747
|
}
|
|
748
|
+
function classifyServerActionResult(facts) {
|
|
749
|
+
if (facts.clientCompatibilityId === null) return {
|
|
750
|
+
kind: "proceed",
|
|
751
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.proceedToCommit, {})
|
|
752
|
+
};
|
|
753
|
+
if (!facts.isRscContentType) return {
|
|
754
|
+
kind: "proceed",
|
|
755
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.proceedToCommit, {})
|
|
756
|
+
};
|
|
757
|
+
if (resolveRscCompatibilityNavigationDecision({
|
|
758
|
+
clientCompatibilityId: facts.clientCompatibilityId,
|
|
759
|
+
currentHref: facts.currentHref,
|
|
760
|
+
origin: facts.origin,
|
|
761
|
+
responseCompatibilityId: facts.compatibilityIdHeader,
|
|
762
|
+
responseUrl: facts.responseUrl
|
|
763
|
+
}).kind === "compatible") return {
|
|
764
|
+
kind: "proceed",
|
|
765
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.proceedToCommit, {})
|
|
766
|
+
};
|
|
767
|
+
if (facts.actionRedirectHref !== null) return {
|
|
768
|
+
kind: "hardNavigate",
|
|
769
|
+
url: facts.actionRedirectHref,
|
|
770
|
+
historyMode: facts.actionRedirectType === "push" ? "assign" : "replace",
|
|
771
|
+
clearClientNavigationCaches: true,
|
|
772
|
+
reason: "serverActionRedirectCompatibilityMismatch",
|
|
773
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.serverActionRedirectCompatibilityMismatch, { targetHref: facts.actionRedirectHref })
|
|
774
|
+
};
|
|
775
|
+
const targetUrl = facts.currentHref;
|
|
776
|
+
return {
|
|
777
|
+
kind: "hardNavigate",
|
|
778
|
+
url: targetUrl,
|
|
779
|
+
clearClientNavigationCaches: false,
|
|
780
|
+
reason: "serverActionRscCompatibilityMismatch",
|
|
781
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.serverActionRscCompatibilityMismatch, { targetHref: targetUrl })
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
function classifyRscNavigationError(facts) {
|
|
785
|
+
return {
|
|
786
|
+
kind: "hardNavigate",
|
|
787
|
+
url: facts.currentHref,
|
|
788
|
+
reason: "rscNavigationError",
|
|
789
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.rscNavigationError, { targetHref: facts.currentHref })
|
|
790
|
+
};
|
|
791
|
+
}
|
|
683
792
|
const navigationPlanner = {
|
|
684
793
|
classifyEarlyNavigationIntent,
|
|
794
|
+
classifyNavigationPrefetchProbe,
|
|
795
|
+
classifyNavigationReuse,
|
|
685
796
|
classifyRscFetchResult,
|
|
797
|
+
classifyRscNavigationError,
|
|
686
798
|
classifyRootBoundaryTransition,
|
|
799
|
+
classifyServerActionResult,
|
|
800
|
+
classifyVisitedResponseCacheCandidate,
|
|
687
801
|
plan: planNavigation,
|
|
688
802
|
resolveCurrentRootBoundaryElementPersistence,
|
|
689
803
|
resolveMountedParallelSlotPersistence,
|
|
@@ -5,6 +5,7 @@ declare const NavigationTraceReasonCodes: {
|
|
|
5
5
|
cacheProofRejected: "NC_CACHE_REJECT";
|
|
6
6
|
commitCurrent: "NC_COMMIT";
|
|
7
7
|
crossDocumentFlight: "NC_CROSS_DOC_FLIGHT";
|
|
8
|
+
fetchFresh: "NC_FETCH_FRESH";
|
|
8
9
|
invalidRscPayload: "NC_RSC_INVALID";
|
|
9
10
|
interceptedCommitCurrent: "NC_INTERCEPT_COMMIT";
|
|
10
11
|
interceptedRejectedIncompatibleRoot: "NC_INTERCEPT_REJECT_ROOT";
|
|
@@ -13,7 +14,9 @@ declare const NavigationTraceReasonCodes: {
|
|
|
13
14
|
interceptedRejectedTargetMismatch: "NC_INTERCEPT_REJECT_TARGET";
|
|
14
15
|
interceptedRejectedUndeclaredTopology: "NC_INTERCEPT_REJECT_GRAPH";
|
|
15
16
|
interceptedRejectedUnknownSource: "NC_INTERCEPT_REJECT_SOURCE";
|
|
17
|
+
optimisticRouteShell: "NC_OPTIMISTIC_SHELL";
|
|
16
18
|
prefetchOnly: "NC_PREFETCH_ONLY";
|
|
19
|
+
prefetchResponseReuse: "NC_PREFETCH_REUSE";
|
|
17
20
|
proceedToCommit: "NC_RSC_PROCEED";
|
|
18
21
|
redirectFollow: "NC_RSC_REDIRECT_FOLLOW";
|
|
19
22
|
redirectTerminalDepth: "NC_RSC_REDIRECT_DEPTH";
|
|
@@ -22,10 +25,14 @@ declare const NavigationTraceReasonCodes: {
|
|
|
22
25
|
rootBoundaryChanged: "NC_ROOT";
|
|
23
26
|
rootBoundaryUnknown: "NC_ROOT_UNKNOWN";
|
|
24
27
|
rscCompatibilityMismatch: "NC_RSC_COMPAT_MISMATCH";
|
|
28
|
+
rscNavigationError: "NC_RSC_NAV_ERROR";
|
|
25
29
|
sameDocumentScroll: "NC_SAME_DOC_SCROLL";
|
|
26
30
|
samePageSearch: "NC_SAME_PAGE_SEARCH";
|
|
31
|
+
serverActionRedirectCompatibilityMismatch: "NC_SA_REDIRECT_COMPAT";
|
|
32
|
+
serverActionRscCompatibilityMismatch: "NC_SA_RSC_COMPAT";
|
|
27
33
|
staleOperation: "NC_STALE";
|
|
28
34
|
streamedRedirectLoop: "NC_RSC_STREAMED_REDIRECT_LOOP";
|
|
35
|
+
visitedResponseReuse: "NC_VISITED_REUSE";
|
|
29
36
|
};
|
|
30
37
|
declare const NavigationTraceTransactionCodes: {
|
|
31
38
|
hardNavigate: "NT_HARD_NAVIGATE";
|
|
@@ -35,7 +42,7 @@ declare const NavigationTraceTransactionCodes: {
|
|
|
35
42
|
type NavigationTraceReasonCode = (typeof NavigationTraceReasonCodes)[keyof typeof NavigationTraceReasonCodes];
|
|
36
43
|
type NavigationTraceTransactionCode = (typeof NavigationTraceTransactionCodes)[keyof typeof NavigationTraceTransactionCodes];
|
|
37
44
|
type NavigationTraceCode = NavigationTraceReasonCode | NavigationTraceTransactionCode;
|
|
38
|
-
type NavigationTraceFieldName = "activeNavigationId" | "cacheProofCode" | "cacheProofMode" | "cacheProofReuseClass" | "cacheProofScope" | "currentRootLayoutTreePath" | "currentVisibleCommitVersion" | "nextRootLayoutTreePath" | "eventKind" | "fetchResultSource" | "operationLane" | "pendingOperationId" | "redirectDepth" | "redirectSignal" | "startedVisibleCommitVersion" | "startedNavigationId" | "targetHref" | "traverseDirection";
|
|
45
|
+
type NavigationTraceFieldName = "activeNavigationId" | "cacheProofCode" | "cacheProofMode" | "cacheProofReuseClass" | "cacheProofScope" | "currentRootLayoutTreePath" | "currentVisibleCommitVersion" | "nextRootLayoutTreePath" | "eventKind" | "fetchResultSource" | "freshFetchReason" | "operationLane" | "pendingOperationId" | "redirectDepth" | "redirectSignal" | "startedVisibleCommitVersion" | "startedNavigationId" | "targetHref" | "traverseDirection";
|
|
39
46
|
type NavigationTraceFieldValue = string | number | boolean | null;
|
|
40
47
|
type NavigationTraceFields = Readonly<Partial<Record<NavigationTraceFieldName, NavigationTraceFieldValue>>>;
|
|
41
48
|
type NavigationTraceEntry = Readonly<{
|
|
@@ -4,6 +4,7 @@ const NavigationTraceReasonCodes = {
|
|
|
4
4
|
cacheProofRejected: "NC_CACHE_REJECT",
|
|
5
5
|
commitCurrent: "NC_COMMIT",
|
|
6
6
|
crossDocumentFlight: "NC_CROSS_DOC_FLIGHT",
|
|
7
|
+
fetchFresh: "NC_FETCH_FRESH",
|
|
7
8
|
invalidRscPayload: "NC_RSC_INVALID",
|
|
8
9
|
interceptedCommitCurrent: "NC_INTERCEPT_COMMIT",
|
|
9
10
|
interceptedRejectedIncompatibleRoot: "NC_INTERCEPT_REJECT_ROOT",
|
|
@@ -12,7 +13,9 @@ const NavigationTraceReasonCodes = {
|
|
|
12
13
|
interceptedRejectedTargetMismatch: "NC_INTERCEPT_REJECT_TARGET",
|
|
13
14
|
interceptedRejectedUndeclaredTopology: "NC_INTERCEPT_REJECT_GRAPH",
|
|
14
15
|
interceptedRejectedUnknownSource: "NC_INTERCEPT_REJECT_SOURCE",
|
|
16
|
+
optimisticRouteShell: "NC_OPTIMISTIC_SHELL",
|
|
15
17
|
prefetchOnly: "NC_PREFETCH_ONLY",
|
|
18
|
+
prefetchResponseReuse: "NC_PREFETCH_REUSE",
|
|
16
19
|
proceedToCommit: "NC_RSC_PROCEED",
|
|
17
20
|
redirectFollow: "NC_RSC_REDIRECT_FOLLOW",
|
|
18
21
|
redirectTerminalDepth: "NC_RSC_REDIRECT_DEPTH",
|
|
@@ -21,10 +24,14 @@ const NavigationTraceReasonCodes = {
|
|
|
21
24
|
rootBoundaryChanged: "NC_ROOT",
|
|
22
25
|
rootBoundaryUnknown: "NC_ROOT_UNKNOWN",
|
|
23
26
|
rscCompatibilityMismatch: "NC_RSC_COMPAT_MISMATCH",
|
|
27
|
+
rscNavigationError: "NC_RSC_NAV_ERROR",
|
|
24
28
|
sameDocumentScroll: "NC_SAME_DOC_SCROLL",
|
|
25
29
|
samePageSearch: "NC_SAME_PAGE_SEARCH",
|
|
30
|
+
serverActionRedirectCompatibilityMismatch: "NC_SA_REDIRECT_COMPAT",
|
|
31
|
+
serverActionRscCompatibilityMismatch: "NC_SA_RSC_COMPAT",
|
|
26
32
|
staleOperation: "NC_STALE",
|
|
27
|
-
streamedRedirectLoop: "NC_RSC_STREAMED_REDIRECT_LOOP"
|
|
33
|
+
streamedRedirectLoop: "NC_RSC_STREAMED_REDIRECT_LOOP",
|
|
34
|
+
visitedResponseReuse: "NC_VISITED_REUSE"
|
|
28
35
|
};
|
|
29
36
|
const NavigationTraceTransactionCodes = {
|
|
30
37
|
hardNavigate: "NT_HARD_NAVIGATE",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NextI18nConfig } from "../config/next-config.js";
|
|
1
2
|
import { Route } from "../routing/pages-router.js";
|
|
2
3
|
import { ExecutionContextLike } from "../shims/request-context.js";
|
|
3
4
|
import { PagesReqResRequest, PagesReqResResponse, PagesRequestQuery } from "./pages-node-compat.js";
|
|
@@ -71,6 +72,11 @@ type HandlePagesApiRouteOptions = {
|
|
|
71
72
|
reportRequestError?: (error: Error, routePattern: string) => void | Promise<void>;
|
|
72
73
|
request: Request;
|
|
73
74
|
url: string;
|
|
75
|
+
nextConfig?: {
|
|
76
|
+
basePath?: string;
|
|
77
|
+
i18n?: NextI18nConfig | null;
|
|
78
|
+
trailingSlash?: boolean;
|
|
79
|
+
};
|
|
74
80
|
};
|
|
75
81
|
declare function handlePagesApiRoute(options: HandlePagesApiRouteOptions): Promise<Response>;
|
|
76
82
|
//#endregion
|
|
@@ -2,7 +2,8 @@ import "./server-globals.js";
|
|
|
2
2
|
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
3
3
|
import { NextRequest } from "../shims/server.js";
|
|
4
4
|
import { internalServerErrorResponse } from "./http-error-responses.js";
|
|
5
|
-
import {
|
|
5
|
+
import { cloneRequestWithUrl } from "./request-pipeline.js";
|
|
6
|
+
import { mergeRouteParamsIntoQuery, parseQueryString, urlQueryToSearchParams } from "../utils/query.js";
|
|
6
7
|
import { PagesBodyParseError } from "./pages-media-type.js";
|
|
7
8
|
import { isEdgeApiRuntime } from "./edge-api-runtime.js";
|
|
8
9
|
import { resolveBodyParserConfig } from "./pages-body-parser-config.js";
|
|
@@ -14,6 +15,12 @@ function resolveModuleRuntime(module) {
|
|
|
14
15
|
function buildPagesApiQuery(url, params) {
|
|
15
16
|
return mergeRouteParamsIntoQuery(parseQueryString(url), params);
|
|
16
17
|
}
|
|
18
|
+
function createEdgeApiRequest(request, url, params) {
|
|
19
|
+
const resolvedUrl = new URL(request.url);
|
|
20
|
+
resolvedUrl.search = urlQueryToSearchParams(buildPagesApiQuery(url, params)).toString();
|
|
21
|
+
const resolvedUrlString = resolvedUrl.toString();
|
|
22
|
+
return resolvedUrlString === request.url ? request : cloneRequestWithUrl(request, resolvedUrlString);
|
|
23
|
+
}
|
|
17
24
|
function isEdgeApiRouteModule(module) {
|
|
18
25
|
return typeof module.default === "function" && isEdgeApiRuntime(resolveModuleRuntime(module));
|
|
19
26
|
}
|
|
@@ -29,7 +36,11 @@ async function _handlePagesApiRoute(options) {
|
|
|
29
36
|
const { route, params } = options.match;
|
|
30
37
|
try {
|
|
31
38
|
if (isEdgeApiRouteModule(route.module)) {
|
|
32
|
-
const nextRequest = new NextRequest(options.request)
|
|
39
|
+
const nextRequest = new NextRequest(createEdgeApiRequest(options.request, options.url, params), options.nextConfig ? { nextConfig: {
|
|
40
|
+
basePath: options.nextConfig.basePath,
|
|
41
|
+
i18n: options.nextConfig.i18n ?? void 0,
|
|
42
|
+
trailingSlash: options.nextConfig.trailingSlash
|
|
43
|
+
} } : void 0);
|
|
33
44
|
const response = await route.module.default(nextRequest);
|
|
34
45
|
if (response instanceof Response) return response;
|
|
35
46
|
throw new Error("Edge API route did not return a Response");
|