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
package/dist/routing/utils.d.ts
CHANGED
|
@@ -1,13 +1,42 @@
|
|
|
1
1
|
//#region src/routing/utils.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* Sort
|
|
4
|
-
*
|
|
3
|
+
* Sort routes by precedence — lower score sorts first (higher priority), with a
|
|
4
|
+
* lexicographic tiebreaker on the pattern for determinism. Sorts in place and
|
|
5
|
+
* returns the same array (mirrors `Array.prototype.sort`).
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
+
* `routePrecedence` is a pure function of the pattern, so each pattern's score
|
|
8
|
+
* is computed exactly once up front (decorate-sort) instead of ~2·log n times
|
|
9
|
+
* by a comparator that re-parses on every comparison. The `localeCompare`
|
|
10
|
+
* tiebreaker already guarantees a total order, so the result is byte-identical
|
|
11
|
+
* to comparing precedence inline.
|
|
12
|
+
*
|
|
13
|
+
* Usage: sortRoutes(routes)
|
|
7
14
|
*/
|
|
8
|
-
declare function
|
|
15
|
+
declare function sortRoutes<T extends {
|
|
9
16
|
pattern: string;
|
|
10
|
-
}>(
|
|
17
|
+
}>(routes: T[]): T[];
|
|
18
|
+
/**
|
|
19
|
+
* Single source of truth for hybrid App/Pages route ownership.
|
|
20
|
+
*
|
|
21
|
+
* Mirrors Next.js's DefaultRouteMatcherManager ordering: Pages providers
|
|
22
|
+
* are registered before App providers, then merged dynamic matchers sort
|
|
23
|
+
* together. Returns the router that should own a request/navigation to
|
|
24
|
+
* a URL that matched BOTH routers.
|
|
25
|
+
*
|
|
26
|
+
* Centralised so the server's request handling and the client's link /
|
|
27
|
+
* prefetch / programmatic-navigation paths all reach the same owner for
|
|
28
|
+
* the same (pages pattern, app pattern) pair. This intentionally implements
|
|
29
|
+
* Next.js's segment-tree ordering directly instead of vinext's broader
|
|
30
|
+
* `sortRoutes()` score heuristic. It only arbitrates two routes that already
|
|
31
|
+
* matched the same URL; each router's own trie ordering remains unchanged.
|
|
32
|
+
*
|
|
33
|
+
* Usage:
|
|
34
|
+
* compareHybridRoutePatterns("/:slug", true, "/:slug", true) // → "pages"
|
|
35
|
+
* compareHybridRoutePatterns("/_sites/:slug*", true, "/:slug*", true) // → "pages"
|
|
36
|
+
* compareHybridRoutePatterns("/:path+", true, "/dashboard", false) // → "app"
|
|
37
|
+
* compareHybridRoutePatterns("/", false, "/", false) // → "app"
|
|
38
|
+
*/
|
|
39
|
+
declare function compareHybridRoutePatterns(pagesPattern: string, pagesIsDynamic: boolean, appPattern: string, appIsDynamic: boolean): "app" | "pages";
|
|
11
40
|
/**
|
|
12
41
|
* Decode a filesystem or URL path segment while preserving encoded path delimiters.
|
|
13
42
|
* Mirrors Next.js segment-wise decoding so "%5F" becomes "_" but "%2F" stays "%2F".
|
|
@@ -85,4 +114,4 @@ declare function isOptionalCatchAllSegment(segment: string): boolean;
|
|
|
85
114
|
*/
|
|
86
115
|
declare function countConsumedPathnameSegments(visibleTreePathSegments: readonly string[], pathnameSegmentCount: number): number;
|
|
87
116
|
//#endregion
|
|
88
|
-
export { buildParams,
|
|
117
|
+
export { buildParams, compareHybridRoutePatterns, countConsumedPathnameSegments, decodeMatchedParams, decodeRouteSegment, isCatchAllSegment, isInvisibleSegment, isOptionalCatchAllSegment, normalizePathnameForRouteMatch, normalizePathnameForRouteMatchStrict, sortRoutes, splitPathSegments, splitPathnameForRouteMatch };
|
package/dist/routing/utils.js
CHANGED
|
@@ -44,14 +44,66 @@ function routePrecedence(pattern) {
|
|
|
44
44
|
return score;
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
|
-
* Sort
|
|
48
|
-
*
|
|
47
|
+
* Sort routes by precedence — lower score sorts first (higher priority), with a
|
|
48
|
+
* lexicographic tiebreaker on the pattern for determinism. Sorts in place and
|
|
49
|
+
* returns the same array (mirrors `Array.prototype.sort`).
|
|
49
50
|
*
|
|
50
|
-
*
|
|
51
|
+
* `routePrecedence` is a pure function of the pattern, so each pattern's score
|
|
52
|
+
* is computed exactly once up front (decorate-sort) instead of ~2·log n times
|
|
53
|
+
* by a comparator that re-parses on every comparison. The `localeCompare`
|
|
54
|
+
* tiebreaker already guarantees a total order, so the result is byte-identical
|
|
55
|
+
* to comparing precedence inline.
|
|
56
|
+
*
|
|
57
|
+
* Usage: sortRoutes(routes)
|
|
58
|
+
*/
|
|
59
|
+
function sortRoutes(routes) {
|
|
60
|
+
const scores = /* @__PURE__ */ new Map();
|
|
61
|
+
for (const route of routes) if (!scores.has(route.pattern)) scores.set(route.pattern, routePrecedence(route.pattern));
|
|
62
|
+
return routes.sort((a, b) => {
|
|
63
|
+
const diff = (scores.get(a.pattern) ?? 0) - (scores.get(b.pattern) ?? 0);
|
|
64
|
+
return diff !== 0 ? diff : a.pattern.localeCompare(b.pattern);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Single source of truth for hybrid App/Pages route ownership.
|
|
69
|
+
*
|
|
70
|
+
* Mirrors Next.js's DefaultRouteMatcherManager ordering: Pages providers
|
|
71
|
+
* are registered before App providers, then merged dynamic matchers sort
|
|
72
|
+
* together. Returns the router that should own a request/navigation to
|
|
73
|
+
* a URL that matched BOTH routers.
|
|
74
|
+
*
|
|
75
|
+
* Centralised so the server's request handling and the client's link /
|
|
76
|
+
* prefetch / programmatic-navigation paths all reach the same owner for
|
|
77
|
+
* the same (pages pattern, app pattern) pair. This intentionally implements
|
|
78
|
+
* Next.js's segment-tree ordering directly instead of vinext's broader
|
|
79
|
+
* `sortRoutes()` score heuristic. It only arbitrates two routes that already
|
|
80
|
+
* matched the same URL; each router's own trie ordering remains unchanged.
|
|
81
|
+
*
|
|
82
|
+
* Usage:
|
|
83
|
+
* compareHybridRoutePatterns("/:slug", true, "/:slug", true) // → "pages"
|
|
84
|
+
* compareHybridRoutePatterns("/_sites/:slug*", true, "/:slug*", true) // → "pages"
|
|
85
|
+
* compareHybridRoutePatterns("/:path+", true, "/dashboard", false) // → "app"
|
|
86
|
+
* compareHybridRoutePatterns("/", false, "/", false) // → "app"
|
|
51
87
|
*/
|
|
52
|
-
function
|
|
53
|
-
|
|
54
|
-
|
|
88
|
+
function compareHybridRoutePatterns(pagesPattern, pagesIsDynamic, appPattern, appIsDynamic) {
|
|
89
|
+
if (pagesPattern === appPattern) throw new Error(`Conflicting app and page routes found for "${pagesPattern}"`);
|
|
90
|
+
if (!pagesIsDynamic) return appIsDynamic ? "pages" : "app";
|
|
91
|
+
if (!appIsDynamic) return "app";
|
|
92
|
+
const pagesSegments = pagesPattern.split("/").filter(Boolean);
|
|
93
|
+
const appSegments = appPattern.split("/").filter(Boolean);
|
|
94
|
+
const segmentRank = (segment) => {
|
|
95
|
+
if (!segment.startsWith(":")) return 0;
|
|
96
|
+
if (segment.endsWith("*")) return 3;
|
|
97
|
+
if (segment.endsWith("+")) return 2;
|
|
98
|
+
return 1;
|
|
99
|
+
};
|
|
100
|
+
for (let index = 0; index < Math.min(pagesSegments.length, appSegments.length); index++) {
|
|
101
|
+
const pagesRank = segmentRank(pagesSegments[index]);
|
|
102
|
+
const appRank = segmentRank(appSegments[index]);
|
|
103
|
+
if (pagesRank !== appRank) return pagesRank < appRank ? "pages" : "app";
|
|
104
|
+
}
|
|
105
|
+
if (pagesSegments.length !== appSegments.length) return pagesSegments.length < appSegments.length ? "pages" : "app";
|
|
106
|
+
return "pages";
|
|
55
107
|
}
|
|
56
108
|
const PATH_DELIMITER_REGEX = /([/#?\\]|%(2f|23|3f|5c))/gi;
|
|
57
109
|
function encodePathDelimiters(segment) {
|
|
@@ -187,4 +239,4 @@ function countConsumedPathnameSegments(visibleTreePathSegments, pathnameSegmentC
|
|
|
187
239
|
return consumed;
|
|
188
240
|
}
|
|
189
241
|
//#endregion
|
|
190
|
-
export { buildParams,
|
|
242
|
+
export { buildParams, compareHybridRoutePatterns, countConsumedPathnameSegments, decodeMatchedParams, decodeRouteSegment, isCatchAllSegment, isInvisibleSegment, isOptionalCatchAllSegment, normalizePathnameForRouteMatch, normalizePathnameForRouteMatchStrict, sortRoutes, splitPathSegments, splitPathnameForRouteMatch };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NextI18nConfig } from "../config/next-config.js";
|
|
1
2
|
import { Route } from "../routing/pages-router.js";
|
|
2
3
|
import { ModuleImporter } from "./instrumentation.js";
|
|
3
4
|
import { IncomingMessage, ServerResponse } from "node:http";
|
|
@@ -7,6 +8,10 @@ import { IncomingMessage, ServerResponse } from "node:http";
|
|
|
7
8
|
* Handle an API route request.
|
|
8
9
|
* Returns true if the request was handled, false if no API route matched.
|
|
9
10
|
*/
|
|
10
|
-
declare function handleApiRoute(runner: ModuleImporter, req: IncomingMessage, res: ServerResponse, url: string, apiRoutes: Route[]
|
|
11
|
+
declare function handleApiRoute(runner: ModuleImporter, req: IncomingMessage, res: ServerResponse, url: string, apiRoutes: Route[], nextConfig?: {
|
|
12
|
+
basePath?: string;
|
|
13
|
+
i18n?: NextI18nConfig | null;
|
|
14
|
+
trailingSlash?: boolean;
|
|
15
|
+
}): Promise<boolean>;
|
|
11
16
|
//#endregion
|
|
12
17
|
export { handleApiRoute };
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { hasBasePath } from "../utils/base-path.js";
|
|
1
2
|
import { matchRoute } from "../routing/pages-router.js";
|
|
2
3
|
import "./server-globals.js";
|
|
4
|
+
import { parseCookieHeader } from "../utils/parse-cookie.js";
|
|
3
5
|
import { NextRequest } from "../shims/server.js";
|
|
4
6
|
import { importModule, reportRequestError } from "./instrumentation.js";
|
|
5
|
-
import { mergeRouteParamsIntoQuery, parseQueryString } from "../utils/query.js";
|
|
7
|
+
import { mergeRouteParamsIntoQuery, parseQueryString, urlQueryToSearchParams } from "../utils/query.js";
|
|
6
8
|
import { PagesBodyParseError, getMediaType, isJsonMediaType } from "./pages-media-type.js";
|
|
7
9
|
import { isEdgeApiRuntime } from "./edge-api-runtime.js";
|
|
8
10
|
import { DEFAULT_PAGES_API_BODY_SIZE_LIMIT, resolveBodyParserConfig } from "./pages-body-parser-config.js";
|
|
@@ -71,13 +73,7 @@ async function parseBody(req, sizeLimit = MAX_BODY_SIZE) {
|
|
|
71
73
|
* Parse cookies from the Cookie header.
|
|
72
74
|
*/
|
|
73
75
|
function parseCookies(req) {
|
|
74
|
-
|
|
75
|
-
const cookies = {};
|
|
76
|
-
for (const part of header.split(";")) {
|
|
77
|
-
const [key, ...rest] = part.split("=");
|
|
78
|
-
if (key) cookies[key.trim()] = rest.join("=").trim();
|
|
79
|
-
}
|
|
80
|
-
return cookies;
|
|
76
|
+
return parseCookieHeader(req.headers.cookie);
|
|
81
77
|
}
|
|
82
78
|
function isEdgeApiRouteModule(module) {
|
|
83
79
|
if (typeof module.default !== "function") return false;
|
|
@@ -98,13 +94,19 @@ function readEdgeRequestBody(req) {
|
|
|
98
94
|
req.on("error", (error) => controller.error(error));
|
|
99
95
|
} });
|
|
100
96
|
}
|
|
101
|
-
function createEdgeApiRequest(req, url) {
|
|
97
|
+
function createEdgeApiRequest(req, url, params, nextConfig) {
|
|
102
98
|
const headers = new Headers();
|
|
103
|
-
for (const [name, value] of Object.entries(req.headers))
|
|
104
|
-
|
|
99
|
+
for (const [name, value] of Object.entries(req.headers)) {
|
|
100
|
+
if (name.startsWith(":")) continue;
|
|
101
|
+
if (Array.isArray(value)) for (const item of value) headers.append(name, item);
|
|
102
|
+
else if (value !== void 0) headers.set(name, value);
|
|
103
|
+
}
|
|
105
104
|
const proto = resolveRequestProtocol(req);
|
|
106
105
|
const host = resolveRequestHost(req, "localhost");
|
|
107
|
-
const requestUrl = new URL(url, `${proto}://${host}`);
|
|
106
|
+
const requestUrl = new URL(req.url ?? url, `${proto}://${host}`);
|
|
107
|
+
const basePath = nextConfig?.basePath;
|
|
108
|
+
if (basePath && !hasBasePath(requestUrl.pathname, basePath)) requestUrl.pathname = `${basePath}${requestUrl.pathname}`;
|
|
109
|
+
requestUrl.search = urlQueryToSearchParams(mergeRouteParamsIntoQuery(parseQueryString(url), params)).toString();
|
|
108
110
|
const body = readEdgeRequestBody(req);
|
|
109
111
|
const init = {
|
|
110
112
|
headers,
|
|
@@ -210,14 +212,18 @@ function enhanceApiObjects(req, res, query, body) {
|
|
|
210
212
|
* Handle an API route request.
|
|
211
213
|
* Returns true if the request was handled, false if no API route matched.
|
|
212
214
|
*/
|
|
213
|
-
async function handleApiRoute(runner, req, res, url, apiRoutes) {
|
|
215
|
+
async function handleApiRoute(runner, req, res, url, apiRoutes, nextConfig) {
|
|
214
216
|
const match = matchRoute(url, apiRoutes);
|
|
215
217
|
if (!match) return false;
|
|
216
218
|
const { route, params } = match;
|
|
217
219
|
try {
|
|
218
220
|
const apiModule = await importModule(runner, route.filePath);
|
|
219
221
|
if (isEdgeApiRouteModule(apiModule)) {
|
|
220
|
-
const nextRequest = new NextRequest(createEdgeApiRequest(req, url)
|
|
222
|
+
const nextRequest = new NextRequest(createEdgeApiRequest(req, url, params, nextConfig), nextConfig ? { nextConfig: {
|
|
223
|
+
basePath: nextConfig.basePath,
|
|
224
|
+
i18n: nextConfig.i18n ?? void 0,
|
|
225
|
+
trailingSlash: nextConfig.trailingSlash
|
|
226
|
+
} } : void 0);
|
|
221
227
|
const response = await apiModule.default(nextRequest);
|
|
222
228
|
if (!(response instanceof Response)) throw new Error("Edge API route did not return a Response");
|
|
223
229
|
res.statusCode = response.status;
|
|
@@ -253,7 +259,7 @@ async function handleApiRoute(runner, req, res, url, apiRoutes) {
|
|
|
253
259
|
reportRequestError(e instanceof Error ? e : new Error(String(e)), {
|
|
254
260
|
path: url,
|
|
255
261
|
method: req.method ?? "GET",
|
|
256
|
-
headers: Object.fromEntries(Object.entries(req.headers).map(([k, v]) => [k, Array.isArray(v) ? v.join(", ") : String(v ?? "")]))
|
|
262
|
+
headers: Object.fromEntries(Object.entries(req.headers).filter(([k]) => !k.startsWith(":")).map(([k, v]) => [k, Array.isArray(v) ? v.join(", ") : String(v ?? "")]))
|
|
257
263
|
}, {
|
|
258
264
|
routerKind: "Pages Router",
|
|
259
265
|
routePath: match.route.pattern,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ServerActionResultFacts } from "./navigation-planner.js";
|
|
2
|
+
|
|
1
3
|
//#region src/server/app-browser-action-result.d.ts
|
|
2
4
|
type AppBrowserServerActionResult<TRoot> = {
|
|
3
5
|
root?: TRoot;
|
|
@@ -24,12 +26,23 @@ declare function shouldClearClientNavigationCachesForServerActionResult<TRoot>(r
|
|
|
24
26
|
declare function parseServerActionRevalidationHeader(headers: Pick<Headers, "get">): ServerActionRevalidationKind;
|
|
25
27
|
declare function normalizeServerActionThrownValue(data: unknown, responseStatus: number): unknown;
|
|
26
28
|
declare function readInvalidServerActionResponseError(response: Pick<Response, "headers" | "status" | "text">, hasRedirectLocation: boolean): Promise<Error | null>;
|
|
27
|
-
|
|
28
|
-
declare function resolveServerActionRedirectCompatibilityHardNavigationTarget(options: {
|
|
29
|
+
type ServerActionResultResponseFactsInput = {
|
|
29
30
|
actionRedirectHref: string | null;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
actionRedirectType: string | null;
|
|
32
|
+
clientCompatibilityId: string | null;
|
|
33
|
+
contentTypeHeader: string | null;
|
|
34
|
+
compatibilityIdHeader: string | null;
|
|
35
|
+
currentHref: string;
|
|
36
|
+
origin: string;
|
|
37
|
+
responseUrl: string | null;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Converts raw browser response data into the narrow facts expected by the
|
|
41
|
+
* navigation planner. This is the single place where redirect-type
|
|
42
|
+
* normalisation and RSC content-type detection happen for server-action
|
|
43
|
+
* compatibility checks.
|
|
44
|
+
*/
|
|
45
|
+
declare function createServerActionResultFacts(input: ServerActionResultResponseFactsInput): ServerActionResultFacts;
|
|
33
46
|
declare function shouldScheduleRefreshForDiscardedServerAction(revalidation: ServerActionRevalidationKind): boolean;
|
|
34
47
|
declare function createServerActionInitiationSnapshot<TRouterState>(options: {
|
|
35
48
|
href: string;
|
|
@@ -48,4 +61,4 @@ type DiscardedServerActionRefreshSchedulerOptions = {
|
|
|
48
61
|
};
|
|
49
62
|
declare function createDiscardedServerActionRefreshScheduler(options: DiscardedServerActionRefreshSchedulerOptions): DiscardedServerActionRefreshScheduler;
|
|
50
63
|
//#endregion
|
|
51
|
-
export { AppBrowserServerActionResult, ServerActionRevalidationKind, createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError,
|
|
64
|
+
export { AppBrowserServerActionResult, ServerActionResultResponseFactsInput, ServerActionRevalidationKind, createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult, shouldScheduleRefreshForDiscardedServerAction };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ACTION_REVALIDATED_HEADER } from "./headers.js";
|
|
2
|
-
import { VINEXT_RSC_CONTENT_TYPE
|
|
2
|
+
import { VINEXT_RSC_CONTENT_TYPE } from "./app-rsc-cache-busting.js";
|
|
3
3
|
//#region src/server/app-browser-action-result.ts
|
|
4
4
|
const ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC = 1;
|
|
5
5
|
const ACTION_DID_REVALIDATE_DYNAMIC_ONLY = 2;
|
|
@@ -47,14 +47,23 @@ async function readInvalidServerActionResponseError(response, hasRedirectLocatio
|
|
|
47
47
|
const message = response.status >= 400 && contentType.toLowerCase().startsWith("text/plain") ? await response.text() : "An unexpected response was received from the server.";
|
|
48
48
|
return new Error(message || "An unexpected response was received from the server.");
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return
|
|
50
|
+
/**
|
|
51
|
+
* Converts raw browser response data into the narrow facts expected by the
|
|
52
|
+
* navigation planner. This is the single place where redirect-type
|
|
53
|
+
* normalisation and RSC content-type detection happen for server-action
|
|
54
|
+
* compatibility checks.
|
|
55
|
+
*/
|
|
56
|
+
function createServerActionResultFacts(input) {
|
|
57
|
+
return {
|
|
58
|
+
actionRedirectHref: input.actionRedirectHref,
|
|
59
|
+
actionRedirectType: input.actionRedirectType === "push" ? "push" : "replace",
|
|
60
|
+
clientCompatibilityId: input.clientCompatibilityId,
|
|
61
|
+
compatibilityIdHeader: input.compatibilityIdHeader,
|
|
62
|
+
currentHref: input.currentHref,
|
|
63
|
+
isRscContentType: (input.contentTypeHeader ?? "").startsWith(VINEXT_RSC_CONTENT_TYPE),
|
|
64
|
+
origin: input.origin,
|
|
65
|
+
responseUrl: input.responseUrl
|
|
66
|
+
};
|
|
58
67
|
}
|
|
59
68
|
function shouldScheduleRefreshForDiscardedServerAction(revalidation) {
|
|
60
69
|
return revalidation !== "none";
|
|
@@ -99,4 +108,4 @@ function createDiscardedServerActionRefreshScheduler(options) {
|
|
|
99
108
|
};
|
|
100
109
|
}
|
|
101
110
|
//#endregion
|
|
102
|
-
export { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError,
|
|
111
|
+
export { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult, shouldScheduleRefreshForDiscardedServerAction };
|