vinext 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build/client-build-config.d.ts +11 -2
- package/dist/build/client-build-config.js +17 -6
- package/dist/build/prerender.d.ts +9 -1
- package/dist/build/prerender.js +42 -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/pages-router-link-navigation.d.ts +33 -7
- package/dist/client/pages-router-link-navigation.js +32 -2
- package/dist/client/vinext-next-data.d.ts +18 -1
- package/dist/client/vinext-next-data.js +2 -0
- 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.d.ts +11 -1
- package/dist/config/config-matchers.js +87 -16
- package/dist/config/next-config.d.ts +46 -4
- package/dist/config/next-config.js +147 -48
- package/dist/config/tsconfig-paths.js +14 -1
- package/dist/deploy.d.ts +30 -11
- package/dist/deploy.js +200 -112
- 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 +65 -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 +66 -20
- package/dist/entries/pages-server-entry.js +47 -31
- package/dist/index.js +417 -102
- package/dist/plugins/dynamic-preload-metadata.js +2 -4
- package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
- package/dist/plugins/extensionless-dynamic-import.js +152 -0
- package/dist/plugins/fonts.js +5 -4
- 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/strip-server-exports.d.ts +9 -7
- package/dist/plugins/strip-server-exports.js +493 -46
- 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 +46 -16
- 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 +20 -11
- package/dist/server/app-browser-entry.js +175 -91
- 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 +5 -3
- 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-state.d.ts +1 -1
- package/dist/server/app-browser-state.js +19 -11
- package/dist/server/app-browser-stream.js +86 -43
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- 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 +23 -1
- package/dist/server/app-pages-bridge.js +26 -17
- 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 +28 -0
- package/dist/server/app-rsc-handler.js +195 -59
- package/dist/server/app-rsc-route-matching.d.ts +3 -0
- package/dist/server/app-rsc-route-matching.js +8 -2
- 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 +47 -15
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +84 -39
- package/dist/server/before-interactive-head.d.ts +17 -0
- package/dist/server/before-interactive-head.js +35 -0
- package/dist/server/cache-control.js +4 -0
- package/dist/server/csp.js +1 -4
- package/dist/server/dev-server.d.ts +2 -2
- package/dist/server/dev-server.js +321 -83
- 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/middleware-matcher.js +12 -3
- package/dist/server/middleware-runtime.d.ts +3 -4
- package/dist/server/middleware-runtime.js +2 -0
- package/dist/server/navigation-planner.d.ts +135 -41
- package/dist/server/navigation-planner.js +138 -0
- package/dist/server/navigation-trace.d.ts +9 -1
- package/dist/server/navigation-trace.js +9 -1
- package/dist/server/operation-token.d.ts +40 -0
- package/dist/server/operation-token.js +85 -0
- 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 +9 -2
- package/dist/server/pages-data-route.js +18 -6
- package/dist/server/pages-dev-module-url.d.ts +4 -0
- package/dist/server/pages-dev-module-url.js +15 -0
- package/dist/server/pages-document-initial-props.d.ts +4 -15
- package/dist/server/pages-document-initial-props.js +27 -56
- 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-i18n.js +2 -2
- 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 +207 -34
- package/dist/server/pages-page-handler.d.ts +4 -2
- package/dist/server/pages-page-handler.js +62 -23
- package/dist/server/pages-page-response.d.ts +4 -1
- package/dist/server/pages-page-response.js +11 -8
- package/dist/server/pages-readiness.js +1 -1
- package/dist/server/pages-request-pipeline.d.ts +8 -7
- package/dist/server/pages-request-pipeline.js +126 -47
- 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.d.ts +3 -1
- package/dist/server/prod-server.js +50 -13
- 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/server/static-file-cache.js +16 -4
- 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/before-interactive-context.d.ts +14 -3
- 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/document.d.ts +15 -20
- package/dist/shims/document.js +5 -8
- 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/image.js +9 -2
- 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-fetch-dedup.d.ts +6 -7
- package/dist/shims/internal/pages-data-fetch-dedup.js +67 -14
- 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 +47 -19
- package/dist/shims/metadata.js +4 -4
- package/dist/shims/navigation.d.ts +8 -2
- package/dist/shims/navigation.js +63 -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 +18 -3
- package/dist/shims/router.js +512 -142
- package/dist/shims/script.js +8 -4
- 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/has-trailing-comma.d.ts +24 -0
- package/dist/utils/has-trailing-comma.js +62 -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/dist/utils/text-stream.d.ts +1 -1
- package/dist/utils/text-stream.js +2 -2
- package/dist/utils/vite-version.d.ts +12 -1
- package/dist/utils/vite-version.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
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/server/hybrid-route-priority.d.ts
|
|
2
|
+
type HybridRoutePriorityRoute = {
|
|
3
|
+
isDynamic: boolean;
|
|
4
|
+
pattern: string;
|
|
5
|
+
sourcePath?: string | null;
|
|
6
|
+
};
|
|
7
|
+
declare function validateHybridRouteConflicts(pagesRoutes: readonly HybridRoutePriorityRoute[], appRoutes: readonly HybridRoutePriorityRoute[]): void;
|
|
8
|
+
/**
|
|
9
|
+
* Return whether a matched Pages Router route should own the request instead
|
|
10
|
+
* of a matched App Router route.
|
|
11
|
+
*
|
|
12
|
+
* Next.js registers Pages providers before App providers, then sorts all
|
|
13
|
+
* dynamic route pathnames together in DefaultRouteMatcherManager. Vinext keeps
|
|
14
|
+
* separate route tries for each router, so the hybrid boundary needs to apply
|
|
15
|
+
* that same cross-router ordering after both routers have produced their best
|
|
16
|
+
* local match. The decision itself lives in
|
|
17
|
+
* `routing/utils.ts#compareHybridRoutePatterns` so the server and client
|
|
18
|
+
* always reach the same answer.
|
|
19
|
+
*/
|
|
20
|
+
declare function pagesRouteHasPriorityOverAppRoute(pagesRoute: HybridRoutePriorityRoute, appRoute: HybridRoutePriorityRoute | null): boolean;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { HybridRoutePriorityRoute, pagesRouteHasPriorityOverAppRoute, validateHybridRouteConflicts };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { compareHybridRoutePatterns } from "../routing/utils.js";
|
|
2
|
+
import { validateRoutePatterns } from "../routing/route-validation.js";
|
|
3
|
+
//#region src/server/hybrid-route-priority.ts
|
|
4
|
+
function validateHybridRouteConflicts(pagesRoutes, appRoutes) {
|
|
5
|
+
const pagesByPattern = new Map(pagesRoutes.map((route) => [route.pattern, route]));
|
|
6
|
+
const conflicts = appRoutes.flatMap((appRoute) => {
|
|
7
|
+
const pagesRoute = pagesByPattern.get(appRoute.pattern);
|
|
8
|
+
return pagesRoute === void 0 ? [] : [[pagesRoute, appRoute]];
|
|
9
|
+
});
|
|
10
|
+
if (conflicts.length > 0) {
|
|
11
|
+
const message = `Conflicting app and page file${conflicts.length === 1 ? " was" : "s were"} found, please remove the conflicting files to continue:`;
|
|
12
|
+
throw new Error(`${message}\n${conflicts.map(([pagesRoute, appRoute]) => ` "${pagesRoute.sourcePath ?? pagesRoute.pattern}" - "${appRoute.sourcePath ?? appRoute.pattern}"`).join("\n")}`);
|
|
13
|
+
}
|
|
14
|
+
validateRoutePatterns([...pagesRoutes.map((route) => route.pattern), ...appRoutes.map((route) => route.pattern)]);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Return whether a matched Pages Router route should own the request instead
|
|
18
|
+
* of a matched App Router route.
|
|
19
|
+
*
|
|
20
|
+
* Next.js registers Pages providers before App providers, then sorts all
|
|
21
|
+
* dynamic route pathnames together in DefaultRouteMatcherManager. Vinext keeps
|
|
22
|
+
* separate route tries for each router, so the hybrid boundary needs to apply
|
|
23
|
+
* that same cross-router ordering after both routers have produced their best
|
|
24
|
+
* local match. The decision itself lives in
|
|
25
|
+
* `routing/utils.ts#compareHybridRoutePatterns` so the server and client
|
|
26
|
+
* always reach the same answer.
|
|
27
|
+
*/
|
|
28
|
+
function pagesRouteHasPriorityOverAppRoute(pagesRoute, appRoute) {
|
|
29
|
+
if (appRoute === null) return true;
|
|
30
|
+
return compareHybridRoutePatterns(pagesRoute.pattern, pagesRoute.isDynamic, appRoute.pattern, appRoute.isDynamic) === "pages";
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { pagesRouteHasPriorityOverAppRoute, validateHybridRouteConflicts };
|
|
@@ -33,7 +33,15 @@ declare function isImageOptimizationPath(pathname: string): boolean;
|
|
|
33
33
|
* Controls SVG handling and security headers for the image endpoint.
|
|
34
34
|
*/
|
|
35
35
|
type ImageConfig = {
|
|
36
|
-
/**
|
|
36
|
+
/** Allowed device widths. Defaults to Next.js device sizes. */deviceSizes?: number[]; /** Allowed fixed-image widths. Defaults to Next.js image sizes. */
|
|
37
|
+
imageSizes?: number[];
|
|
38
|
+
/**
|
|
39
|
+
* Allowed output qualities. When unset, any quality from 1-100 is permitted
|
|
40
|
+
* (matches Next.js: an unset `images.qualities` is not restricted to a single
|
|
41
|
+
* value). When set, only the listed qualities are accepted.
|
|
42
|
+
*/
|
|
43
|
+
qualities?: number[]; /** Allow SVG through the image optimization endpoint. Default: false. */
|
|
44
|
+
dangerouslyAllowSVG?: boolean;
|
|
37
45
|
/**
|
|
38
46
|
* Allow image optimization for hostnames that resolve to private IP addresses.
|
|
39
47
|
* Default: false.
|
|
@@ -54,18 +62,19 @@ type ImageConfig = {
|
|
|
54
62
|
*/
|
|
55
63
|
declare const DEFAULT_DEVICE_SIZES: number[];
|
|
56
64
|
declare const DEFAULT_IMAGE_SIZES: number[];
|
|
65
|
+
type ParseImageParamsOptions = {
|
|
66
|
+
isDev?: boolean;
|
|
67
|
+
};
|
|
68
|
+
declare function resolveDevImageRedirect(requestUrl: URL, allowedWidths?: number[], allowedQualities?: number[], options?: ParseImageParamsOptions): string | null;
|
|
57
69
|
/**
|
|
58
70
|
* Parse and validate image optimization query parameters.
|
|
59
71
|
* Returns null if the request is malformed.
|
|
60
72
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* When `allowedWidths` is not provided, any width from 0 to ABSOLUTE_MAX_WIDTH
|
|
66
|
-
* 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
|
|
67
76
|
*/
|
|
68
|
-
declare function parseImageParams(url: URL, allowedWidths?: number[]): {
|
|
77
|
+
declare function parseImageParams(url: URL, allowedWidths?: number[], allowedQualities?: number[], options?: ParseImageParamsOptions): {
|
|
69
78
|
imageUrl: string;
|
|
70
79
|
width: number;
|
|
71
80
|
quality: number;
|
|
@@ -113,4 +122,4 @@ type ImageHandlers = {
|
|
|
113
122
|
*/
|
|
114
123
|
declare function handleImageOptimization(request: Request, handlers: ImageHandlers, allowedWidths?: number[], imageConfig?: ImageConfig): Promise<Response>;
|
|
115
124
|
//#endregion
|
|
116
|
-
export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, ImageConfig, ImageHandlers, VINEXT_IMAGE_OPTIMIZATION_PATH, handleImageOptimization, isImageOptimizationPath, isSafeImageContentType, negotiateImageFormat, parseImageParams };
|
|
125
|
+
export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, ImageConfig, ImageHandlers, ParseImageParamsOptions, VINEXT_IMAGE_OPTIMIZATION_PATH, handleImageOptimization, isImageOptimizationPath, isSafeImageContentType, negotiateImageFormat, parseImageParams, resolveDevImageRedirect };
|
|
@@ -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 };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { removeTrailingSlash } from "../utils/base-path.js";
|
|
2
|
-
import { checkHasConditions, requestContextFromRequest, safeRegExp } from "../config/config-matchers.js";
|
|
2
|
+
import { checkHasConditions, isSafeRegex, requestContextFromRequest, safeRegExp } from "../config/config-matchers.js";
|
|
3
3
|
//#region src/server/middleware-matcher.ts
|
|
4
4
|
const EMPTY_MIDDLEWARE_REQUEST_CONTEXT = {
|
|
5
5
|
headers: new Headers(),
|
|
@@ -7,6 +7,7 @@ const EMPTY_MIDDLEWARE_REQUEST_CONTEXT = {
|
|
|
7
7
|
query: new URLSearchParams(),
|
|
8
8
|
host: ""
|
|
9
9
|
};
|
|
10
|
+
const UNSAFE_MATCHER_PATTERN = Symbol("unsafe matcher pattern");
|
|
10
11
|
const _mwPatternCache = /* @__PURE__ */ new Map();
|
|
11
12
|
function matchesMiddleware(pathname, matcher, request, i18nConfig) {
|
|
12
13
|
if (!matcher) return true;
|
|
@@ -55,6 +56,7 @@ function matchPattern(pathname, pattern) {
|
|
|
55
56
|
cached = compileMatcherPattern(pattern);
|
|
56
57
|
_mwPatternCache.set(pattern, cached);
|
|
57
58
|
}
|
|
59
|
+
if (cached === UNSAFE_MATCHER_PATTERN) return true;
|
|
58
60
|
if (cached === null) return pathname === pattern;
|
|
59
61
|
return cached.test(pathname);
|
|
60
62
|
}
|
|
@@ -74,7 +76,7 @@ function extractConstraint(str, re) {
|
|
|
74
76
|
}
|
|
75
77
|
function compileMatcherPattern(pattern) {
|
|
76
78
|
const hasConstraints = /:[\w-]+[*+]?\(/.test(pattern);
|
|
77
|
-
if (!hasConstraints && (pattern.includes("(") || pattern.includes("\\"))) return
|
|
79
|
+
if (!hasConstraints && (pattern.includes("(") || pattern.includes("\\"))) return compileMatcherRegExp("^" + pattern + "$", pattern);
|
|
78
80
|
let regexStr = "";
|
|
79
81
|
const tokenRe = /\/:([\w-]+)\*|\/:([\w-]+)\+|:([\w-]+)|[.]|[^/:.]+|./g;
|
|
80
82
|
let tok;
|
|
@@ -94,7 +96,14 @@ function compileMatcherPattern(pattern) {
|
|
|
94
96
|
else regexStr += group;
|
|
95
97
|
} else if (tok[0] === ".") regexStr += "\\.";
|
|
96
98
|
else regexStr += tok[0];
|
|
97
|
-
return
|
|
99
|
+
return compileMatcherRegExp("^" + regexStr + "$", pattern);
|
|
100
|
+
}
|
|
101
|
+
function compileMatcherRegExp(regexPattern, sourcePattern) {
|
|
102
|
+
if (!isSafeRegex(regexPattern)) {
|
|
103
|
+
console.warn(`[vinext] Rejecting potentially unsafe middleware matcher (ReDoS risk): ${sourcePattern}\n Middleware will run for all paths to avoid bypassing request guards.\n Simplify the matcher to avoid nested repetition.`);
|
|
104
|
+
return UNSAFE_MATCHER_PATTERN;
|
|
105
|
+
}
|
|
106
|
+
return safeRegExp(regexPattern);
|
|
98
107
|
}
|
|
99
108
|
//#endregion
|
|
100
109
|
export { matchPattern, matchesMiddleware };
|
|
@@ -35,10 +35,9 @@ type ExecuteMiddlewareOptions = {
|
|
|
35
35
|
i18nConfig?: NextI18nConfig | null;
|
|
36
36
|
includeErrorDetails?: boolean;
|
|
37
37
|
/**
|
|
38
|
-
* Whether the incoming request was a Next.js `_next/data`
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* flag from the raw incoming headers and forward it explicitly.
|
|
38
|
+
* Whether the incoming request was recognized as a Next.js `_next/data`
|
|
39
|
+
* fetch. Internal headers are stripped before middleware runs, so adapters
|
|
40
|
+
* must derive and forward this from trusted URL normalization.
|
|
42
41
|
*/
|
|
43
42
|
isDataRequest?: boolean;
|
|
44
43
|
isProxy: boolean;
|
|
@@ -142,6 +142,8 @@ async function executeMiddleware(options) {
|
|
|
142
142
|
response: internalServerErrorResponse(options.includeErrorDetails ? "Middleware Error: " + (e instanceof Error ? e.message : String(e)) : "Internal Server Error"),
|
|
143
143
|
waitUntilPromises
|
|
144
144
|
};
|
|
145
|
+
} finally {
|
|
146
|
+
if (process.env.NODE_ENV !== "development" && nextRequest.body) nextRequest.body.cancel().catch(() => {});
|
|
145
147
|
}
|
|
146
148
|
const waitUntilPromises = drainFetchEvent(fetchEvent);
|
|
147
149
|
if (!response) return {
|
|
@@ -2,46 +2,37 @@ import { RouteManifest } from "../routing/app-route-graph.js";
|
|
|
2
2
|
import { CacheEntryReuseDecision, CacheEntryReuseProof } from "./cache-proof.js";
|
|
3
3
|
import { AppElementsSlotBinding } from "./app-elements-wire.js";
|
|
4
4
|
import { NavigationTrace, NavigationTraceFields } from "./navigation-trace.js";
|
|
5
|
+
import { OperationLane, OperationToken } from "./operation-token.js";
|
|
5
6
|
|
|
6
7
|
//#region src/server/navigation-planner.d.ts
|
|
7
|
-
type
|
|
8
|
-
|
|
9
|
-
operationId: number;
|
|
10
|
-
lane: OperationLane;
|
|
11
|
-
baseVisibleCommitVersion: number;
|
|
12
|
-
graphVersion: string | null;
|
|
13
|
-
deploymentVersion: string | null;
|
|
14
|
-
targetSnapshotFingerprint: string;
|
|
15
|
-
cacheVariantFingerprint?: string;
|
|
16
|
-
};
|
|
17
|
-
type RouteSnapshotV0 = {
|
|
18
|
-
interception: InterceptionSnapshotV0 | null;
|
|
8
|
+
type RouteSnapshot = {
|
|
9
|
+
interception: InterceptionSnapshot | null;
|
|
19
10
|
interceptionContext: string | null;
|
|
20
11
|
routeId: string;
|
|
21
12
|
layoutIds: readonly string[];
|
|
22
|
-
mountedParallelSlots: readonly
|
|
13
|
+
mountedParallelSlots: readonly MountedParallelSlotSnapshot[];
|
|
23
14
|
rootBoundaryId: string | null;
|
|
24
15
|
displayUrl: string;
|
|
25
16
|
matchedUrl: string;
|
|
26
|
-
slotBindings: readonly
|
|
17
|
+
slotBindings: readonly ParallelSlotBindingSnapshot[];
|
|
27
18
|
};
|
|
28
|
-
type
|
|
19
|
+
type InterceptionSnapshot = {
|
|
29
20
|
sourceMatchedUrl: string;
|
|
30
21
|
sourceRouteId: string;
|
|
31
22
|
slotId: string;
|
|
32
23
|
targetMatchedUrl: string;
|
|
33
24
|
targetRouteId: string;
|
|
34
25
|
};
|
|
35
|
-
type
|
|
26
|
+
type MountedParallelSlotSnapshot = {
|
|
36
27
|
slotId: string;
|
|
37
28
|
ownerLayoutId: string | null;
|
|
38
29
|
};
|
|
39
|
-
type
|
|
40
|
-
type
|
|
30
|
+
type ParallelSlotBindingSnapshot = AppElementsSlotBinding;
|
|
31
|
+
type NavigationPlannerState = {
|
|
41
32
|
nextOperationToken: OperationToken;
|
|
42
33
|
traceFields?: NavigationTraceFields;
|
|
43
34
|
visibleCommitVersion: number;
|
|
44
|
-
visibleSnapshot:
|
|
35
|
+
visibleSnapshot: RouteSnapshot;
|
|
45
36
|
};
|
|
46
37
|
type RefreshScope = "visible";
|
|
47
38
|
type TraverseDirection = "back" | "forward" | "unknown";
|
|
@@ -62,7 +53,7 @@ type NavigationEvent = {
|
|
|
62
53
|
} | {
|
|
63
54
|
kind: "flightResponseArrived";
|
|
64
55
|
token: OperationToken;
|
|
65
|
-
result:
|
|
56
|
+
result: FlightResult;
|
|
66
57
|
};
|
|
67
58
|
type RequestedWork = {
|
|
68
59
|
kind: "flight";
|
|
@@ -82,12 +73,12 @@ type CommitProposal = {
|
|
|
82
73
|
preserveElementIds: readonly string[];
|
|
83
74
|
preservePreviousSlotIds: readonly string[];
|
|
84
75
|
reason: "currentRootBoundary" | "interceptedCurrentRootBoundary" | "unprovenTopologyFallback";
|
|
85
|
-
targetSnapshot:
|
|
76
|
+
targetSnapshot: RouteSnapshot;
|
|
86
77
|
};
|
|
87
78
|
type NoCommitReason = "prefetchOnly";
|
|
88
|
-
type HardNavigationReason = "cacheProofRejected" | "interceptionProofRejected" | "rootBoundaryChanged";
|
|
79
|
+
type HardNavigationReason = "cacheProofRejected" | "cacheReuseTokenRejected" | "interceptionProofRejected" | "rootBoundaryChanged";
|
|
89
80
|
type RootBoundaryTransition = "currentRootBoundary" | "rootBoundaryChanged" | "rootBoundaryUnknown";
|
|
90
|
-
type
|
|
81
|
+
type NavigationDecision = {
|
|
91
82
|
kind: "requestWork";
|
|
92
83
|
token: OperationToken;
|
|
93
84
|
work: RequestedWork;
|
|
@@ -109,13 +100,13 @@ type NavigationDecisionV0 = {
|
|
|
109
100
|
reason: HardNavigationReason;
|
|
110
101
|
trace: NavigationTrace;
|
|
111
102
|
};
|
|
112
|
-
type
|
|
103
|
+
type FlightResult = {
|
|
113
104
|
cacheEntryReuseProof?: CacheEntryReuseProof;
|
|
114
105
|
href: string;
|
|
115
|
-
targetSnapshot:
|
|
106
|
+
targetSnapshot: RouteSnapshot;
|
|
116
107
|
};
|
|
117
108
|
type RscFetchResultSource = "cached" | "live";
|
|
118
|
-
type
|
|
109
|
+
type RscFetchResultFacts = {
|
|
119
110
|
source: RscFetchResultSource;
|
|
120
111
|
currentHref: string;
|
|
121
112
|
origin: string;
|
|
@@ -130,21 +121,21 @@ type RscFetchResultFactsV0 = {
|
|
|
130
121
|
responseUrl: string | null;
|
|
131
122
|
streamedRedirectTarget: string | null;
|
|
132
123
|
};
|
|
133
|
-
type
|
|
124
|
+
type RscRedirectFollow = {
|
|
134
125
|
href: string;
|
|
135
126
|
historyUpdateMode: "push" | "replace";
|
|
136
127
|
previousNextUrl: string | null;
|
|
137
128
|
redirectDepth: number;
|
|
138
129
|
};
|
|
139
130
|
type RscFetchResultHardNavReason = "invalidRscPayload" | "rscCompatibilityMismatch" | "externalRedirectTarget" | "redirectDepthExhausted" | "streamedRedirectLoop";
|
|
140
|
-
type
|
|
131
|
+
type RscFetchResultDecision = {
|
|
141
132
|
kind: "proceedToCommit";
|
|
142
133
|
discardBody: false;
|
|
143
134
|
trace: NavigationTrace;
|
|
144
135
|
} | {
|
|
145
136
|
kind: "followRedirect";
|
|
146
137
|
discardBody: boolean;
|
|
147
|
-
redirect:
|
|
138
|
+
redirect: RscRedirectFollow;
|
|
148
139
|
trace: NavigationTrace;
|
|
149
140
|
} | {
|
|
150
141
|
kind: "hardNavigate";
|
|
@@ -153,14 +144,14 @@ type RscFetchResultDecisionV0 = {
|
|
|
153
144
|
reason: RscFetchResultHardNavReason;
|
|
154
145
|
trace: NavigationTrace;
|
|
155
146
|
};
|
|
156
|
-
type
|
|
147
|
+
type EarlyNavigationIntentFacts = {
|
|
157
148
|
basePath: string;
|
|
158
149
|
currentHref: string;
|
|
159
150
|
mode: "push" | "replace";
|
|
160
151
|
scroll: boolean;
|
|
161
152
|
targetHref: string;
|
|
162
153
|
};
|
|
163
|
-
type
|
|
154
|
+
type EarlyNavigationIntentDecision = {
|
|
164
155
|
kind: "sameDocumentScroll";
|
|
165
156
|
hash: string;
|
|
166
157
|
mode: "push" | "replace";
|
|
@@ -171,20 +162,86 @@ type EarlyNavigationIntentDecisionV0 = {
|
|
|
171
162
|
bypassNavigationCache: boolean;
|
|
172
163
|
trace: NavigationTrace;
|
|
173
164
|
};
|
|
165
|
+
type NavigationReuseNavigationKind = "navigate" | "refresh" | "traverse";
|
|
166
|
+
type VisitedResponseCacheCandidateFacts = {
|
|
167
|
+
candidate: "missing";
|
|
168
|
+
navigationKind: NavigationReuseNavigationKind;
|
|
169
|
+
} | {
|
|
170
|
+
candidate: "present";
|
|
171
|
+
fresh: boolean;
|
|
172
|
+
mountedSlotsMatch: boolean;
|
|
173
|
+
navigationKind: NavigationReuseNavigationKind;
|
|
174
|
+
};
|
|
175
|
+
type VisitedResponseCacheCandidateDecision = {
|
|
176
|
+
kind: "miss";
|
|
177
|
+
} | {
|
|
178
|
+
kind: "evict";
|
|
179
|
+
reason: "mountedSlotsMismatch" | "refresh" | "stale";
|
|
180
|
+
} | {
|
|
181
|
+
kind: "reuse";
|
|
182
|
+
};
|
|
183
|
+
type NavigationReuseCandidateAvailability = {
|
|
184
|
+
status: "available";
|
|
185
|
+
} | {
|
|
186
|
+
status: "unavailable";
|
|
187
|
+
};
|
|
188
|
+
type OptimisticRouteShellCandidateAvailability = {
|
|
189
|
+
status: "available";
|
|
190
|
+
} | {
|
|
191
|
+
status: "unavailable";
|
|
192
|
+
reason: "routeManifestMissing";
|
|
193
|
+
};
|
|
194
|
+
type NavigationReuseFacts = {
|
|
195
|
+
bypassNavigationCache: boolean;
|
|
196
|
+
navigationKind: NavigationReuseNavigationKind;
|
|
197
|
+
optimisticRouteShell: OptimisticRouteShellCandidateAvailability;
|
|
198
|
+
prefetch: NavigationReuseCandidateAvailability;
|
|
199
|
+
targetHref: string;
|
|
200
|
+
visitedResponse: NavigationReuseCandidateAvailability;
|
|
201
|
+
};
|
|
202
|
+
type FreshFetchReason = "cacheBypassed" | "cacheMiss" | "refresh" | "routeManifestMissing";
|
|
203
|
+
type NavigationReuseDecision = {
|
|
204
|
+
kind: "reuseVisitedResponse";
|
|
205
|
+
trace: NavigationTrace;
|
|
206
|
+
} | {
|
|
207
|
+
kind: "consumePrefetch";
|
|
208
|
+
trace: NavigationTrace;
|
|
209
|
+
} | {
|
|
210
|
+
kind: "attemptOptimisticRouteShell";
|
|
211
|
+
trace: NavigationTrace;
|
|
212
|
+
} | {
|
|
213
|
+
kind: "fetchFresh";
|
|
214
|
+
reason: FreshFetchReason;
|
|
215
|
+
trace: NavigationTrace;
|
|
216
|
+
};
|
|
217
|
+
type NavigationPrefetchProbeFacts = {
|
|
218
|
+
bypassNavigationCache: boolean;
|
|
219
|
+
navigationKind: NavigationReuseNavigationKind;
|
|
220
|
+
visitedResponse: NavigationReuseCandidateAvailability;
|
|
221
|
+
};
|
|
222
|
+
type NavigationPrefetchProbeDecision = {
|
|
223
|
+
kind: "probe";
|
|
224
|
+
} | {
|
|
225
|
+
kind: "skip";
|
|
226
|
+
reason: "cacheBypassed" | "refresh" | "visitedResponseAvailable";
|
|
227
|
+
};
|
|
174
228
|
type NavigationPlannerInput = {
|
|
175
229
|
routeManifest: RouteManifest | null;
|
|
176
|
-
state:
|
|
230
|
+
state: NavigationPlannerState;
|
|
177
231
|
event: NavigationEvent;
|
|
178
232
|
};
|
|
179
233
|
type AcceptedCacheEntryReuseDecision = Extract<CacheEntryReuseDecision, {
|
|
180
234
|
canReuse: true;
|
|
181
235
|
}>;
|
|
182
|
-
declare function classifyRscFetchResult(facts:
|
|
183
|
-
declare function classifyEarlyNavigationIntent(facts:
|
|
236
|
+
declare function classifyRscFetchResult(facts: RscFetchResultFacts): RscFetchResultDecision;
|
|
237
|
+
declare function classifyEarlyNavigationIntent(facts: EarlyNavigationIntentFacts): EarlyNavigationIntentDecision;
|
|
238
|
+
declare function classifyVisitedResponseCacheCandidate(facts: VisitedResponseCacheCandidateFacts): VisitedResponseCacheCandidateDecision;
|
|
239
|
+
declare function classifyNavigationReuse(facts: NavigationReuseFacts): NavigationReuseDecision;
|
|
240
|
+
declare function classifyNavigationPrefetchProbe(facts: NavigationPrefetchProbeFacts): NavigationPrefetchProbeDecision;
|
|
184
241
|
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:
|
|
242
|
+
declare function resolveSameLayoutAncestorPersistence(currentSnapshot: RouteSnapshot, targetSnapshot: RouteSnapshot): readonly string[];
|
|
243
|
+
declare function resolveMountedParallelSlotPersistence(currentSnapshot: RouteSnapshot, targetSnapshot: RouteSnapshot): readonly string[];
|
|
244
|
+
declare function resolveCurrentRootBoundaryElementPersistence(currentSnapshot: RouteSnapshot, targetSnapshot: RouteSnapshot): readonly string[];
|
|
188
245
|
/**
|
|
189
246
|
* Default/unmatched slot preservation law:
|
|
190
247
|
*
|
|
@@ -196,19 +253,56 @@ declare function resolveCurrentRootBoundaryElementPersistence(currentSnapshot: R
|
|
|
196
253
|
* Wire absence and UNMATCHED_SLOT markers are not semantic proof.
|
|
197
254
|
*/
|
|
198
255
|
declare function resolveDefaultOrUnmatchedSlotPersistenceForLayouts(options: {
|
|
199
|
-
currentSlotBindings: readonly
|
|
256
|
+
currentSlotBindings: readonly ParallelSlotBindingSnapshot[];
|
|
200
257
|
preservedLayoutIds: readonly string[];
|
|
201
|
-
targetSlotBindings: readonly
|
|
258
|
+
targetSlotBindings: readonly ParallelSlotBindingSnapshot[];
|
|
202
259
|
}): readonly string[];
|
|
203
|
-
declare function planNavigation(input: NavigationPlannerInput):
|
|
260
|
+
declare function planNavigation(input: NavigationPlannerInput): NavigationDecision;
|
|
261
|
+
type ServerActionResultFacts = {
|
|
262
|
+
actionRedirectHref: string | null;
|
|
263
|
+
actionRedirectType: "push" | "replace";
|
|
264
|
+
clientCompatibilityId: string | null;
|
|
265
|
+
compatibilityIdHeader: string | null;
|
|
266
|
+
currentHref: string;
|
|
267
|
+
isRscContentType: boolean;
|
|
268
|
+
origin: string;
|
|
269
|
+
responseUrl: string | null;
|
|
270
|
+
};
|
|
271
|
+
type ServerActionResultDecision = {
|
|
272
|
+
kind: "proceed";
|
|
273
|
+
trace: NavigationTrace;
|
|
274
|
+
} | {
|
|
275
|
+
kind: "hardNavigate";
|
|
276
|
+
url: string;
|
|
277
|
+
historyMode?: "assign" | "replace";
|
|
278
|
+
clearClientNavigationCaches: boolean;
|
|
279
|
+
reason: "serverActionRedirectCompatibilityMismatch" | "serverActionRscCompatibilityMismatch";
|
|
280
|
+
trace: NavigationTrace;
|
|
281
|
+
};
|
|
282
|
+
type RscNavigationErrorFacts = {
|
|
283
|
+
currentHref: string;
|
|
284
|
+
};
|
|
285
|
+
type RscNavigationErrorDecision = {
|
|
286
|
+
kind: "hardNavigate";
|
|
287
|
+
url: string;
|
|
288
|
+
reason: "rscNavigationError";
|
|
289
|
+
trace: NavigationTrace;
|
|
290
|
+
};
|
|
291
|
+
declare function classifyServerActionResult(facts: ServerActionResultFacts): ServerActionResultDecision;
|
|
292
|
+
declare function classifyRscNavigationError(facts: RscNavigationErrorFacts): RscNavigationErrorDecision;
|
|
204
293
|
declare const navigationPlanner: {
|
|
205
294
|
classifyEarlyNavigationIntent: typeof classifyEarlyNavigationIntent;
|
|
295
|
+
classifyNavigationPrefetchProbe: typeof classifyNavigationPrefetchProbe;
|
|
296
|
+
classifyNavigationReuse: typeof classifyNavigationReuse;
|
|
206
297
|
classifyRscFetchResult: typeof classifyRscFetchResult;
|
|
298
|
+
classifyRscNavigationError: typeof classifyRscNavigationError;
|
|
207
299
|
classifyRootBoundaryTransition: typeof classifyRootBoundaryTransition;
|
|
300
|
+
classifyServerActionResult: typeof classifyServerActionResult;
|
|
301
|
+
classifyVisitedResponseCacheCandidate: typeof classifyVisitedResponseCacheCandidate;
|
|
208
302
|
plan: typeof planNavigation;
|
|
209
303
|
resolveCurrentRootBoundaryElementPersistence: typeof resolveCurrentRootBoundaryElementPersistence;
|
|
210
304
|
resolveMountedParallelSlotPersistence: typeof resolveMountedParallelSlotPersistence;
|
|
211
305
|
resolveSameLayoutAncestorPersistence: typeof resolveSameLayoutAncestorPersistence;
|
|
212
306
|
};
|
|
213
307
|
//#endregion
|
|
214
|
-
export {
|
|
308
|
+
export { EarlyNavigationIntentDecision, EarlyNavigationIntentFacts, FlightResult, InterceptionSnapshot, MountedParallelSlotSnapshot, NavigationDecision, NavigationEvent, NavigationPlannerInput, NavigationPlannerState, NavigationReuseDecision, NavigationReuseFacts, type OperationLane, type OperationToken, ParallelSlotBindingSnapshot, RefreshScope, RootBoundaryTransition, RouteSnapshot, RscFetchResultDecision, RscFetchResultFacts, RscNavigationErrorDecision, RscNavigationErrorFacts, ServerActionResultDecision, ServerActionResultFacts, TraverseDirection, VisitedResponseCacheCandidateFacts, navigationPlanner, resolveDefaultOrUnmatchedSlotPersistenceForLayouts };
|