vinext 0.1.7 → 0.1.8
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/check.d.ts +18 -0
- package/dist/check.js +37 -17
- package/dist/cli.js +2 -2
- package/dist/config/next-config.d.ts +2 -1
- package/dist/config/next-config.js +3 -0
- package/dist/config/server-external-packages.d.ts +4 -0
- package/dist/config/server-external-packages.js +91 -0
- package/dist/deploy.d.ts +7 -0
- package/dist/deploy.js +25 -18
- package/dist/entries/app-rsc-entry.js +54 -10
- package/dist/entries/app-rsc-manifest.js +8 -0
- package/dist/entries/pages-client-entry.js +1 -0
- package/dist/entries/pages-server-entry.js +1 -0
- package/dist/index.js +46 -20
- package/dist/init.js +2 -1
- package/dist/plugins/middleware-server-only.d.ts +8 -6
- package/dist/plugins/middleware-server-only.js +8 -7
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/routing/app-route-graph.d.ts +6 -2
- package/dist/routing/app-route-graph.js +61 -13
- package/dist/routing/app-router.d.ts +5 -0
- package/dist/routing/app-router.js +5 -0
- package/dist/routing/file-matcher.d.ts +5 -0
- package/dist/routing/file-matcher.js +7 -1
- package/dist/server/app-browser-entry.js +42 -147
- package/dist/server/app-browser-history-controller.d.ts +2 -1
- package/dist/server/app-browser-history-controller.js +6 -2
- package/dist/server/app-browser-server-action-client.d.ts +32 -0
- package/dist/server/app-browser-server-action-client.js +128 -0
- package/dist/server/app-fallback-renderer.d.ts +3 -1
- package/dist/server/app-fallback-renderer.js +6 -2
- package/dist/server/app-page-boundary-render.d.ts +3 -0
- package/dist/server/app-page-boundary-render.js +14 -3
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +8 -2
- package/dist/server/app-page-dispatch.d.ts +33 -4
- package/dist/server/app-page-dispatch.js +62 -90
- package/dist/server/app-page-element-builder.d.ts +7 -1
- package/dist/server/app-page-element-builder.js +56 -19
- package/dist/server/app-page-head.d.ts +16 -1
- package/dist/server/app-page-head.js +44 -22
- package/dist/server/app-page-params.d.ts +2 -1
- package/dist/server/app-page-params.js +8 -1
- package/dist/server/app-page-ppr-runtime.d.ts +7 -0
- package/dist/server/app-page-ppr-runtime.js +70 -0
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +1 -1
- package/dist/server/app-page-render.d.ts +4 -1
- package/dist/server/app-page-render.js +8 -3
- package/dist/server/app-page-request.d.ts +8 -1
- package/dist/server/app-page-request.js +23 -11
- package/dist/server/app-page-route-wiring.d.ts +6 -1
- package/dist/server/app-page-route-wiring.js +30 -8
- package/dist/server/app-page-search-params-observation.d.ts +4 -2
- package/dist/server/app-page-search-params-observation.js +11 -7
- package/dist/server/app-ppr-fallback-shell-render.d.ts +4 -3
- package/dist/server/app-route-handler-dispatch.js +1 -0
- package/dist/server/app-route-handler-execution.js +2 -1
- package/dist/server/app-route-module-loader.d.ts +2 -0
- package/dist/server/app-route-module-loader.js +1 -0
- package/dist/server/app-router-entry.js +7 -6
- package/dist/server/app-rsc-errors.js +7 -1
- package/dist/server/app-rsc-handler.d.ts +2 -1
- package/dist/server/app-rsc-handler.js +6 -9
- package/dist/server/app-rsc-route-matching.d.ts +7 -0
- package/dist/server/app-rsc-route-matching.js +36 -3
- package/dist/server/app-segment-config.d.ts +1 -0
- package/dist/server/app-segment-config.js +32 -2
- package/dist/server/app-server-action-execution.d.ts +4 -0
- package/dist/server/app-server-action-execution.js +41 -10
- package/dist/server/app-ssr-entry.js +4 -1
- package/dist/server/app-static-generation.d.ts +1 -0
- package/dist/server/app-static-generation.js +1 -0
- package/dist/server/headers.d.ts +3 -1
- package/dist/server/headers.js +3 -1
- package/dist/server/prod-server.js +15 -6
- package/dist/server/worker-utils.d.ts +2 -1
- package/dist/server/worker-utils.js +7 -1
- package/dist/shims/error-boundary.d.ts +19 -1
- package/dist/shims/error-boundary.js +11 -1
- package/dist/shims/headers.d.ts +3 -1
- package/dist/shims/headers.js +16 -5
- package/dist/shims/link.js +16 -12
- package/dist/shims/metadata.d.ts +3 -2
- package/dist/shims/metadata.js +8 -4
- package/dist/shims/router.js +13 -2
- package/dist/typegen.js +6 -5
- package/dist/utils/path.d.ts +2 -1
- package/dist/utils/path.js +1 -1
- package/dist/utils/project.d.ts +4 -0
- package/dist/utils/project.js +5 -1
- package/package.json +7 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { normalizePathSeparators } from "../utils/path.js";
|
|
2
1
|
import { decodeRouteSegment, isInvisibleSegment, sortRoutes } from "./utils.js";
|
|
2
|
+
import { normalizePathSeparators } from "../utils/path.js";
|
|
3
3
|
import { findFileWithExts, scanWithExtensions } from "./file-matcher.js";
|
|
4
4
|
import { validateRoutePatterns } from "./route-validation.js";
|
|
5
5
|
import { compareStrings } from "../utils/compare.js";
|
|
@@ -360,8 +360,8 @@ async function buildAppRouteGraph(appDir, matcher) {
|
|
|
360
360
|
const routePatterns = new Set(routes.map((route) => route.pattern));
|
|
361
361
|
const ghostParentRoutes = [];
|
|
362
362
|
for await (const file of scanWithExtensions("**/layout", appDir, scanMatcher.extensions, excludeDir)) {
|
|
363
|
-
const dir = path.dirname(file);
|
|
364
|
-
const routeDir = dir === "." ? appDir : path.join(appDir, dir);
|
|
363
|
+
const dir = path.posix.dirname(file);
|
|
364
|
+
const routeDir = dir === "." ? appDir : path.posix.join(appDir, dir);
|
|
365
365
|
if (!hasParallelSlotDirectory(routeDir)) continue;
|
|
366
366
|
if (discoverParallelSlots(routeDir, appDir, scanMatcher).length === 0) continue;
|
|
367
367
|
const route = directoryToAppRoute(dir, appDir, scanMatcher, null, null);
|
|
@@ -434,11 +434,16 @@ function discoverSlotSubRoutes(routes, matcher, ghostParents = []) {
|
|
|
434
434
|
const applySlotSubPages = (route, slotPages, rawSegments) => {
|
|
435
435
|
route.parallelSlots = route.parallelSlots.map((slot) => {
|
|
436
436
|
const subPage = slotPages.get(slot.key);
|
|
437
|
-
if (subPage !== void 0)
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
437
|
+
if (subPage !== void 0) {
|
|
438
|
+
const configLayoutPaths = findSlotConfigLayoutPaths(slot.ownerDir, subPage, matcher);
|
|
439
|
+
return {
|
|
440
|
+
...slot,
|
|
441
|
+
pagePath: subPage,
|
|
442
|
+
configLayoutPaths,
|
|
443
|
+
configLayoutTreePositions: findSlotConfigLayoutTreePositions(slot.ownerDir, configLayoutPaths),
|
|
444
|
+
routeSegments: rawSegments
|
|
445
|
+
};
|
|
446
|
+
}
|
|
442
447
|
return slot;
|
|
443
448
|
});
|
|
444
449
|
};
|
|
@@ -495,9 +500,12 @@ function discoverSlotSubRoutes(routes, matcher, ghostParents = []) {
|
|
|
495
500
|
if (Array.from(routesByPattern.values()).some((r) => patternsStructurallyEquivalent(r.patternParts, syntheticParts))) continue;
|
|
496
501
|
const subSlots = parentRoute.parallelSlots.map((slot) => {
|
|
497
502
|
const subPage = slotPages.get(slot.key);
|
|
503
|
+
const configLayoutPaths = findSlotConfigLayoutPaths(slot.ownerDir, subPage ?? null, matcher);
|
|
498
504
|
return {
|
|
499
505
|
...slot,
|
|
500
506
|
pagePath: subPage || null,
|
|
507
|
+
configLayoutPaths,
|
|
508
|
+
configLayoutTreePositions: findSlotConfigLayoutTreePositions(slot.ownerDir, configLayoutPaths),
|
|
501
509
|
routeSegments: subPage ? rawSegments : null
|
|
502
510
|
};
|
|
503
511
|
});
|
|
@@ -574,6 +582,23 @@ function findSlotSubPages(slotDir, matcher) {
|
|
|
574
582
|
perMatcher.set(slotDir, results);
|
|
575
583
|
return results;
|
|
576
584
|
}
|
|
585
|
+
function findSlotConfigLayoutPaths(slotDir, pagePath, matcher) {
|
|
586
|
+
if (!pagePath) return [];
|
|
587
|
+
const layouts = [];
|
|
588
|
+
let dir = path.dirname(pagePath);
|
|
589
|
+
while (dir !== slotDir && dir.startsWith(`${slotDir}${path.sep}`)) {
|
|
590
|
+
const layoutPath = findFile(dir, "layout", matcher);
|
|
591
|
+
if (layoutPath) layouts.unshift(layoutPath);
|
|
592
|
+
dir = path.dirname(dir);
|
|
593
|
+
}
|
|
594
|
+
return layouts;
|
|
595
|
+
}
|
|
596
|
+
function findSlotConfigLayoutTreePositions(slotDir, layoutPaths) {
|
|
597
|
+
return layoutPaths.map((layoutPath) => {
|
|
598
|
+
const relativeDir = path.relative(slotDir, path.dirname(layoutPath));
|
|
599
|
+
return relativeDir ? relativeDir.split(path.sep).filter(Boolean).length : 0;
|
|
600
|
+
});
|
|
601
|
+
}
|
|
577
602
|
/**
|
|
578
603
|
* Find a sibling catch-all page directly under `dir`, i.e. a `[...slug]` or
|
|
579
604
|
* `[[...slug]]` directory that contains a `page` file. Returns the absolute
|
|
@@ -613,8 +638,14 @@ function fileToAppRoute(file, appDir, type, matcher) {
|
|
|
613
638
|
}
|
|
614
639
|
return directoryToAppRoute(dir, appDir, matcher, type === "page" ? path.join(appDir, file) : null, type === "route" ? path.join(appDir, file) : null);
|
|
615
640
|
}
|
|
641
|
+
/**
|
|
642
|
+
* `dir` and `appDir` must both be forward-slash. `dir` is split on
|
|
643
|
+
* `path.posix.sep` and joined onto `appDir` with `path.posix.join`, and `appDir`
|
|
644
|
+
* is threaded to the layout/slot/boundary discovery below, which build paths the
|
|
645
|
+
* same way.
|
|
646
|
+
*/
|
|
616
647
|
function directoryToAppRoute(dir, appDir, matcher, pagePath, routePath) {
|
|
617
|
-
const segments = dir === "." ? [] : dir.split(path.sep);
|
|
648
|
+
const segments = dir === "." ? [] : dir.split(path.posix.sep);
|
|
618
649
|
const params = [];
|
|
619
650
|
let isDynamic = false;
|
|
620
651
|
const convertedRoute = convertSegmentsToRouteParts(segments);
|
|
@@ -631,7 +662,7 @@ function directoryToAppRoute(dir, appDir, matcher, pagePath, routePath) {
|
|
|
631
662
|
const errorEntries = discoverSegmentErrors(segments, appDir, matcher);
|
|
632
663
|
const errorPaths = errorEntries.map((entry) => entry.path);
|
|
633
664
|
const errorTreePositions = errorEntries.map((entry) => entry.treePosition);
|
|
634
|
-
const routeDir = dir === "." ? appDir : path.join(appDir, dir);
|
|
665
|
+
const routeDir = dir === "." ? appDir : path.posix.join(appDir, dir);
|
|
635
666
|
const loadingPath = findFile(routeDir, "loading", matcher);
|
|
636
667
|
const errorPath = findFile(routeDir, "error", matcher);
|
|
637
668
|
const notFoundPath = discoverBoundaryFile(segments, appDir, "not-found", matcher);
|
|
@@ -863,6 +894,10 @@ function discoverBoundaryFilePerLayout(layouts, fileName, matcher) {
|
|
|
863
894
|
* Walk from appDir through each segment to the route's directory. At each level
|
|
864
895
|
* that has @slot dirs, collect them. Slots at the route's own directory level
|
|
865
896
|
* use page.tsx; slots at ancestor levels use default.tsx only.
|
|
897
|
+
*
|
|
898
|
+
* `appDir` and `routeDir` must be forward-slash — `currentDir` descends from
|
|
899
|
+
* `appDir` via `path.posix.join`, and the `dir === routeDir` active-level test
|
|
900
|
+
* below only matches when both share the canonical separator.
|
|
866
901
|
*/
|
|
867
902
|
function discoverInheritedParallelSlots(segments, appDir, routeDir, matcher) {
|
|
868
903
|
const slotMap = /* @__PURE__ */ new Map();
|
|
@@ -875,7 +910,7 @@ function discoverInheritedParallelSlots(segments, appDir, routeDir, matcher) {
|
|
|
875
910
|
segmentIndex: 0
|
|
876
911
|
});
|
|
877
912
|
for (let i = 0; i < segments.length; i++) {
|
|
878
|
-
currentDir = path.join(currentDir, segments[i]);
|
|
913
|
+
currentDir = path.posix.join(currentDir, segments[i]);
|
|
879
914
|
if (findFile(currentDir, "layout", matcher)) layoutIdx++;
|
|
880
915
|
dirsToCheck.push({
|
|
881
916
|
dir: currentDir,
|
|
@@ -902,9 +937,12 @@ function discoverInheritedParallelSlots(segments, appDir, routeDir, matcher) {
|
|
|
902
937
|
slotPatternParts = [...ownerUrl?.urlSegments ?? [], ...mirror.slotUrlSegments];
|
|
903
938
|
slotParamNames = [...ownerUrl?.params ?? [], ...mirror.slotParamNames];
|
|
904
939
|
}
|
|
940
|
+
const configLayoutPaths = findSlotConfigLayoutPaths(slot.ownerDir, mirror?.pagePath ?? null, matcher);
|
|
905
941
|
const inheritedSlot = {
|
|
906
942
|
...slot,
|
|
907
943
|
pagePath: mirror?.pagePath ?? null,
|
|
944
|
+
configLayoutPaths,
|
|
945
|
+
configLayoutTreePositions: findSlotConfigLayoutTreePositions(slot.ownerDir, configLayoutPaths),
|
|
908
946
|
layoutIndex: slotLayoutIdx,
|
|
909
947
|
routeSegments: mirror?.segments ?? null,
|
|
910
948
|
slotPatternParts,
|
|
@@ -1035,6 +1073,9 @@ function patternsStructurallyEquivalent(a, b) {
|
|
|
1035
1073
|
*
|
|
1036
1074
|
* Returns the absolute page path, or null if no root-level page is found.
|
|
1037
1075
|
*
|
|
1076
|
+
* `slotDir` must be forward-slash: the `path.posix.join` descent stays a
|
|
1077
|
+
* canonical id only when the base already is.
|
|
1078
|
+
*
|
|
1038
1079
|
* Only descends into route-group directories (those whose name starts with `(`
|
|
1039
1080
|
* and ends with `)`). Dynamic segments, regular named dirs, and `@slot` dirs
|
|
1040
1081
|
* are not transparent and are therefore not searched.
|
|
@@ -1051,7 +1092,7 @@ function findSlotRootPage(slotDir, matcher) {
|
|
|
1051
1092
|
for (const entry of entries) {
|
|
1052
1093
|
if (!entry.isDirectory()) continue;
|
|
1053
1094
|
if (!entry.name.startsWith("(") || !entry.name.endsWith(")")) continue;
|
|
1054
|
-
const found = findSlotRootPage(path.join(slotDir, entry.name), matcher);
|
|
1095
|
+
const found = findSlotRootPage(path.posix.join(slotDir, entry.name), matcher);
|
|
1055
1096
|
if (found) return found;
|
|
1056
1097
|
}
|
|
1057
1098
|
return null;
|
|
@@ -1068,13 +1109,14 @@ function discoverParallelSlots(dir, appDir, matcher) {
|
|
|
1068
1109
|
if (!entry.isDirectory() || !entry.name.startsWith("@")) continue;
|
|
1069
1110
|
if (entry.name === "@children") continue;
|
|
1070
1111
|
const slotName = entry.name.slice(1);
|
|
1071
|
-
const slotDir = path.join(dir, entry.name);
|
|
1112
|
+
const slotDir = path.posix.join(dir, entry.name);
|
|
1072
1113
|
const pagePath = findSlotRootPage(slotDir, matcher);
|
|
1073
1114
|
const defaultPath = findFile(slotDir, "default", matcher);
|
|
1074
1115
|
const interceptingRoutes = discoverInterceptingRoutes(slotDir, dir, appDir, matcher);
|
|
1075
1116
|
if (!pagePath && !defaultPath && interceptingRoutes.length === 0) continue;
|
|
1076
1117
|
const ownerSegments = path.relative(appDir, dir).split(path.sep).filter((segment) => segment.length > 0);
|
|
1077
1118
|
const ownerTreePath = createAppRouteGraphTreePath(ownerSegments, ownerSegments.length);
|
|
1119
|
+
const configLayoutPaths = findSlotConfigLayoutPaths(slotDir, pagePath, matcher);
|
|
1078
1120
|
slots.push({
|
|
1079
1121
|
id: createAppRouteGraphSlotId(slotName, ownerTreePath),
|
|
1080
1122
|
key: `${slotName}@${path.relative(appDir, slotDir).replace(/\\/g, "/")}`,
|
|
@@ -1085,6 +1127,8 @@ function discoverParallelSlots(dir, appDir, matcher) {
|
|
|
1085
1127
|
pagePath,
|
|
1086
1128
|
defaultPath,
|
|
1087
1129
|
layoutPath: findFile(slotDir, "layout", matcher),
|
|
1130
|
+
configLayoutPaths,
|
|
1131
|
+
configLayoutTreePositions: findSlotConfigLayoutTreePositions(slotDir, configLayoutPaths),
|
|
1088
1132
|
loadingPath: findFile(slotDir, "loading", matcher),
|
|
1089
1133
|
errorPath: findFile(slotDir, "error", matcher),
|
|
1090
1134
|
interceptingRoutes,
|
|
@@ -1272,8 +1316,12 @@ function collectInterceptingPages(currentDir, interceptRoot, convention, interce
|
|
|
1272
1316
|
if (targetPattern) {
|
|
1273
1317
|
const sourceMatchPattern = computeInterceptSourceMatchPattern(interceptParentDir, appDir);
|
|
1274
1318
|
results.push({
|
|
1319
|
+
branchSegments: [interceptSegment, ...normalizePathSeparators(path.relative(interceptRoot, path.dirname(page))).split("/").filter(Boolean)],
|
|
1275
1320
|
convention,
|
|
1276
1321
|
layoutPaths: [...layoutPaths],
|
|
1322
|
+
layoutSegments: layoutPaths.map((layoutPath) => {
|
|
1323
|
+
return [interceptSegment, ...path.relative(interceptRoot, path.dirname(layoutPath)).split(path.sep).filter(Boolean)];
|
|
1324
|
+
}),
|
|
1277
1325
|
targetPattern: targetPattern.pattern,
|
|
1278
1326
|
sourceMatchPattern,
|
|
1279
1327
|
pagePath: page,
|
|
@@ -12,11 +12,16 @@ declare function invalidateAppRouteCache(): void;
|
|
|
12
12
|
* TODO(#726): Layer 4 should consume this read model directly once the
|
|
13
13
|
* navigation planner owns route graph facts.
|
|
14
14
|
*
|
|
15
|
+
* `appDir` must be forward-slash — callers normalize it at their entry, and it
|
|
16
|
+
* flows into `buildAppRouteGraph`, which builds every path with `path.posix.*`.
|
|
17
|
+
*
|
|
15
18
|
* @internal
|
|
16
19
|
*/
|
|
17
20
|
declare function appRouteGraph(appDir: string, pageExtensions?: readonly string[], matcher?: ValidFileMatcher): Promise<AppRouteGraph>;
|
|
18
21
|
/**
|
|
19
22
|
* Scan the app/ directory and return a list of routes.
|
|
23
|
+
*
|
|
24
|
+
* `appDir` must be forward-slash — it is forwarded to `appRouteGraph`.
|
|
20
25
|
*/
|
|
21
26
|
declare function appRouter(appDir: string, pageExtensions?: readonly string[], matcher?: ValidFileMatcher): Promise<AppRouteGraphRoute[]>;
|
|
22
27
|
/**
|
|
@@ -30,6 +30,9 @@ function invalidateAppRouteCache() {
|
|
|
30
30
|
* TODO(#726): Layer 4 should consume this read model directly once the
|
|
31
31
|
* navigation planner owns route graph facts.
|
|
32
32
|
*
|
|
33
|
+
* `appDir` must be forward-slash — callers normalize it at their entry, and it
|
|
34
|
+
* flows into `buildAppRouteGraph`, which builds every path with `path.posix.*`.
|
|
35
|
+
*
|
|
33
36
|
* @internal
|
|
34
37
|
*/
|
|
35
38
|
async function appRouteGraph(appDir, pageExtensions, matcher) {
|
|
@@ -44,6 +47,8 @@ async function appRouteGraph(appDir, pageExtensions, matcher) {
|
|
|
44
47
|
}
|
|
45
48
|
/**
|
|
46
49
|
* Scan the app/ directory and return a list of routes.
|
|
50
|
+
*
|
|
51
|
+
* `appDir` must be forward-slash — it is forwarded to `appRouteGraph`.
|
|
47
52
|
*/
|
|
48
53
|
async function appRouter(appDir, pageExtensions, matcher) {
|
|
49
54
|
return (await appRouteGraph(appDir, pageExtensions, matcher)).routes;
|
|
@@ -54,6 +54,11 @@ declare function buildViteResolveExtensions(pageExtensions?: readonly string[] |
|
|
|
54
54
|
declare function normalizeViteResolveExtensions(extensions: readonly string[]): string[];
|
|
55
55
|
/**
|
|
56
56
|
* Use function-form exclude for Node < 22.14 compatibility.
|
|
57
|
+
*
|
|
58
|
+
* Yields forward-slash relative paths: node's glob emits native (backslash)
|
|
59
|
+
* separators on Windows, so each match is normalized — this is the entry point
|
|
60
|
+
* that lets downstream consumers treat the scanned paths as canonical
|
|
61
|
+
* forward-slash ids.
|
|
57
62
|
*/
|
|
58
63
|
declare function scanWithExtensions(stem: string, cwd: string, extensions: readonly string[], exclude?: (name: string) => boolean): AsyncGenerator<string>;
|
|
59
64
|
//#endregion
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { escapeRegExp } from "../utils/regex.js";
|
|
2
|
+
import { normalizePathSeparators } from "../utils/path.js";
|
|
2
3
|
import { existsSync } from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { glob } from "node:fs/promises";
|
|
@@ -135,13 +136,18 @@ function normalizeViteResolveExtensions(extensions) {
|
|
|
135
136
|
}
|
|
136
137
|
/**
|
|
137
138
|
* Use function-form exclude for Node < 22.14 compatibility.
|
|
139
|
+
*
|
|
140
|
+
* Yields forward-slash relative paths: node's glob emits native (backslash)
|
|
141
|
+
* separators on Windows, so each match is normalized — this is the entry point
|
|
142
|
+
* that lets downstream consumers treat the scanned paths as canonical
|
|
143
|
+
* forward-slash ids.
|
|
138
144
|
*/
|
|
139
145
|
async function* scanWithExtensions(stem, cwd, extensions, exclude) {
|
|
140
146
|
const pattern = buildExtensionGlob(stem, extensions);
|
|
141
147
|
for await (const file of glob(pattern, {
|
|
142
148
|
cwd,
|
|
143
149
|
...exclude ? { exclude } : {}
|
|
144
|
-
})) yield file;
|
|
150
|
+
})) yield normalizePathSeparators(file);
|
|
145
151
|
}
|
|
146
152
|
//#endregion
|
|
147
153
|
export { buildViteResolveExtensions, createValidFileMatcher, findFileWithExtensions, findFileWithExts, normalizePageExtensions, normalizeViteResolveExtensions, scanWithExtensions };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-safety.js";
|
|
1
|
+
import { VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_PARAMS_HEADER, VINEXT_RSC_REDIRECT_HEADER } from "./headers.js";
|
|
3
2
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
4
3
|
import { APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI } from "./app-rsc-render-mode.js";
|
|
5
4
|
import { getMountedSlotIdsHeader, resolveVisitedResponseInterceptionContext } from "./app-elements.js";
|
|
@@ -14,7 +13,7 @@ import { DevRecoveryBoundary, GlobalErrorBoundary, RedirectBoundary } from "../s
|
|
|
14
13
|
import { beginAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
15
14
|
import { AppRouterScrollCommitProvider } from "../shims/app-router-scroll.js";
|
|
16
15
|
import { BfcacheStateKeyMapContext, ElementsContext, Slot } from "../shims/slot.js";
|
|
17
|
-
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl,
|
|
16
|
+
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, getVinextRscCompatibilityId } from "./app-rsc-cache-busting.js";
|
|
18
17
|
import { getNavigationRuntime, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions } from "../client/navigation-runtime.js";
|
|
19
18
|
import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
|
|
20
19
|
import "../client/instrumentation-client.js";
|
|
@@ -25,26 +24,23 @@ import { blockDangerousStreamedRscRedirect } from "./app-browser-rsc-redirect.js
|
|
|
25
24
|
import { navigationPlanner } from "./navigation-planner.js";
|
|
26
25
|
import { __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, getClientNavigationRenderContext, getPrefetchCache, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, setClientParams, setMountedSlotsHeader, setPendingPathname, useRouter } from "../shims/navigation.js";
|
|
27
26
|
import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-bfcache-identity.js";
|
|
28
|
-
import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot
|
|
27
|
+
import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot } from "./app-browser-action-result.js";
|
|
29
28
|
import { createClientReuseManifestHeaderFromVisibleAppState } from "./app-browser-client-reuse-manifest.js";
|
|
30
29
|
import { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal } from "./app-browser-stream.js";
|
|
31
|
-
import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, isCacheRestorableAppPayloadMetadata, resolveInterceptionContextFromPreviousNextUrl
|
|
30
|
+
import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, isCacheRestorableAppPayloadMetadata, resolveInterceptionContextFromPreviousNextUrl } from "./app-browser-state.js";
|
|
32
31
|
import { clearHardNavigationLoopGuard, createAppBrowserNavigationController, createBasePathStrippedPathAndSearch } from "./app-browser-navigation-controller.js";
|
|
33
|
-
import { applyServerActionResultDecision } from "./app-browser-server-action-navigation.js";
|
|
34
32
|
import { consumeInitialFormState, createVinextHydrateRootOptions, hydrateRootInTransition } from "./app-browser-hydration.js";
|
|
35
33
|
import { AppBrowserHistoryController } from "./app-browser-history-controller.js";
|
|
36
34
|
import { createVisitedResponseCacheEntry, isVisitedResponseCacheEntryFresh } from "./app-visited-response-cache.js";
|
|
37
35
|
import { createPopstateRestoreHandler, restoreSynchronousPopstateScrollPosition } from "./app-browser-popstate.js";
|
|
38
36
|
import { createDevOnCaughtError, createOnUncaughtError, createProdOnCaughtError, prodOnRecoverableError } from "./app-browser-error.js";
|
|
39
|
-
import { dismissOverlay } from "./dev-error-overlay-store.js";
|
|
40
|
-
import { devOnCaughtError, installDevErrorOverlay, installViteHmrErrorHandler, reportInitialDevServerErrors } from "./dev-error-overlay.js";
|
|
41
|
-
import { throwOnServerActionNotFound } from "./server-action-not-found.js";
|
|
42
37
|
import { createOptimisticRouteTemplate, getOptimisticPrefetchSourceKey, getOptimisticRouteTemplateKey, resolveOptimisticNavigationPayload } from "./app-optimistic-routing.js";
|
|
43
38
|
import { removeStylesheetLinksCoveredByInlineCss } from "./app-inline-css-client.js";
|
|
44
39
|
import { createElement, startTransition, use, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
45
40
|
import { flushSync } from "react-dom";
|
|
46
|
-
import { createFromFetch, createFromReadableStream,
|
|
41
|
+
import { createFromFetch, createFromReadableStream, setServerCallback } from "@vitejs/plugin-rsc/browser";
|
|
47
42
|
import { createRoot, hydrateRoot } from "react-dom/client";
|
|
43
|
+
import { hasServerActions, loadServerActionClient } from "virtual:vinext-app-capabilities";
|
|
48
44
|
//#region src/server/app-browser-entry.ts
|
|
49
45
|
function toActionType(kind) {
|
|
50
46
|
return kind === "traverse" ? "traverse" : "navigate";
|
|
@@ -94,10 +90,14 @@ const browserNavigationController = createAppBrowserNavigationController({
|
|
|
94
90
|
getRouteManifest: getBrowserRouteManifest,
|
|
95
91
|
syncHistoryStatePreviousNextUrl: (previousNextUrl, bfcacheIds) => historyController.syncCurrentHistoryStatePreviousNextUrl(previousNextUrl, bfcacheIds)
|
|
96
92
|
});
|
|
97
|
-
const discardedServerActionRefreshScheduler = createDiscardedServerActionRefreshScheduler({ runRefresh() {
|
|
93
|
+
const discardedServerActionRefreshScheduler = hasServerActions ? createDiscardedServerActionRefreshScheduler({ runRefresh() {
|
|
98
94
|
clearClientNavigationCaches();
|
|
99
95
|
getNavigationRuntime()?.functions.navigate?.(window.location.href, 0, "refresh", void 0, void 0, true);
|
|
100
|
-
} })
|
|
96
|
+
} }) : {
|
|
97
|
+
markNavigationSettled() {},
|
|
98
|
+
markNavigationStart() {},
|
|
99
|
+
schedule() {}
|
|
100
|
+
};
|
|
101
101
|
const NavigationCommitSignal = browserNavigationController.NavigationCommitSignal;
|
|
102
102
|
const ACTION_HTTP_FALLBACK_ROBOTS_META_ATTR = "data-vinext-action-http-fallback";
|
|
103
103
|
function syncServerActionHttpFallbackHead(status) {
|
|
@@ -303,52 +303,6 @@ async function renderNavigationPayload(payload, navigationSnapshot, targetHref,
|
|
|
303
303
|
visibleCommitMode
|
|
304
304
|
});
|
|
305
305
|
}
|
|
306
|
-
function resolveActionRedirectTarget(response) {
|
|
307
|
-
const actionRedirect = response.headers.get(ACTION_REDIRECT_HEADER);
|
|
308
|
-
if (!actionRedirect) return null;
|
|
309
|
-
if (isDangerousScheme(actionRedirect)) {
|
|
310
|
-
console.error(DANGEROUS_URL_BLOCK_MESSAGE);
|
|
311
|
-
return null;
|
|
312
|
-
}
|
|
313
|
-
try {
|
|
314
|
-
let redirectUrl;
|
|
315
|
-
if (actionRedirect.startsWith("/") || /^[a-z]+:/i.test(actionRedirect)) redirectUrl = new URL(actionRedirect, window.location.href);
|
|
316
|
-
else {
|
|
317
|
-
const baseParsed = new URL(window.location.href);
|
|
318
|
-
let baseDir = baseParsed.pathname;
|
|
319
|
-
if (!baseDir.endsWith("/")) baseDir = baseDir + "/";
|
|
320
|
-
redirectUrl = new URL(actionRedirect, `${baseParsed.origin}${baseDir}${baseParsed.search}`);
|
|
321
|
-
}
|
|
322
|
-
if (redirectUrl.origin !== window.location.origin) {
|
|
323
|
-
browserNavigationController.performHardNavigation(actionRedirect);
|
|
324
|
-
return null;
|
|
325
|
-
}
|
|
326
|
-
const statusHeader = response.headers.get(ACTION_REDIRECT_STATUS_HEADER);
|
|
327
|
-
const status = statusHeader ? parseInt(statusHeader, 10) : 307;
|
|
328
|
-
return {
|
|
329
|
-
href: redirectUrl.href,
|
|
330
|
-
type: response.headers.get("x-action-redirect-type") ?? "push",
|
|
331
|
-
status
|
|
332
|
-
};
|
|
333
|
-
} catch {
|
|
334
|
-
browserNavigationController.performHardNavigation(actionRedirect);
|
|
335
|
-
return null;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
var ServerActionRedirectError = class extends Error {
|
|
339
|
-
digest;
|
|
340
|
-
handled = true;
|
|
341
|
-
constructor(target) {
|
|
342
|
-
super("NEXT_REDIRECT");
|
|
343
|
-
const redirectUrl = new URL(target.href, window.location.href);
|
|
344
|
-
const redirectHref = redirectUrl.pathname + redirectUrl.search + redirectUrl.hash;
|
|
345
|
-
const redirectType = target.type === "push" ? "push" : "replace";
|
|
346
|
-
this.digest = `NEXT_REDIRECT;${redirectType};${encodeURIComponent(redirectHref)};${target.status};`;
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
function createServerActionRedirectError(target) {
|
|
350
|
-
return new ServerActionRedirectError(target);
|
|
351
|
-
}
|
|
352
306
|
async function commitSameUrlNavigatePayload(nextElements, actionInitiation, returnValue, revalidation = "none") {
|
|
353
307
|
const navigationSnapshot = createClientNavigationRenderSnapshot(actionInitiation.href, actionInitiation.routerState.navigationSnapshot.params);
|
|
354
308
|
return browserNavigationController.commitSameUrlNavigatePayload(nextElements, navigationSnapshot, returnValue, actionInitiation.routerState, {
|
|
@@ -709,112 +663,53 @@ function applyRuntimeRscBootstrap(rsc) {
|
|
|
709
663
|
if (rsc.nav) restoreHydrationNavigationContext(rsc.nav.pathname, rsc.nav.searchParams, params);
|
|
710
664
|
}
|
|
711
665
|
function registerServerActionCallback() {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
const temporaryReferences = createTemporaryReferenceSet();
|
|
666
|
+
setServerCallback((id, args) => {
|
|
667
|
+
const releaseCacheInvalidationGuard = historyController.beginCacheInvalidationGuard();
|
|
715
668
|
const actionInitiation = createActionInitiationSnapshot();
|
|
716
|
-
|
|
717
|
-
const body = await encodeReply(args, { temporaryReferences });
|
|
718
|
-
const { headers } = resolveServerActionRequestState({
|
|
719
|
-
actionId: id,
|
|
669
|
+
return loadServerActionClient().then(({ invokeClientServerAction }) => invokeClientServerAction(id, args, actionInitiation, {
|
|
720
670
|
basePath: __basePath,
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
if (hasActionRedirect && !actionRedirectTarget) return;
|
|
733
|
-
const actionResultFacts = createServerActionResultFacts({
|
|
734
|
-
actionRedirectHref: actionRedirectTarget?.href ?? null,
|
|
735
|
-
actionRedirectType: actionRedirectTarget?.type ?? null,
|
|
736
|
-
clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
|
|
737
|
-
compatibilityIdHeader: fetchResponse.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
|
|
738
|
-
contentTypeHeader: fetchResponse.headers.get("content-type"),
|
|
739
|
-
currentHref: actionInitiation.href,
|
|
740
|
-
origin: window.location.origin,
|
|
741
|
-
responseUrl: fetchResponse.url
|
|
742
|
-
});
|
|
743
|
-
const fetchResponseIsRsc = actionResultFacts.isRscContentType;
|
|
744
|
-
if (applyServerActionResultDecision(navigationPlanner.classifyServerActionResult(actionResultFacts), clearClientNavigationCaches, (url, historyMode) => browserNavigationController.performHardNavigation(url, historyMode))) return;
|
|
745
|
-
const revalidation = parseServerActionRevalidationHeader(fetchResponse.headers);
|
|
746
|
-
if (revalidation !== "none") clearClientNavigationCaches();
|
|
747
|
-
const invalidResponseError = await readInvalidServerActionResponseError(fetchResponse.clone(), actionRedirectTarget !== null);
|
|
748
|
-
if (invalidResponseError) throw invalidResponseError;
|
|
749
|
-
if (actionRedirectTarget && !fetchResponseIsRsc) {
|
|
750
|
-
browserNavigationController.performHardNavigation(actionRedirectTarget.href);
|
|
751
|
-
return;
|
|
752
|
-
}
|
|
753
|
-
const flightResponse = fetchResponse.status === 303 ? new Response(fetchResponse.body, {
|
|
754
|
-
headers: fetchResponse.headers,
|
|
755
|
-
status: 200,
|
|
756
|
-
statusText: "OK"
|
|
757
|
-
}) : fetchResponse;
|
|
758
|
-
const result = await createFromFetch(Promise.resolve(flightResponse), { temporaryReferences });
|
|
759
|
-
if (revalidation === "none" && shouldClearClientNavigationCachesForServerActionResult(result, revalidation)) clearClientNavigationCaches();
|
|
760
|
-
if (actionRedirectTarget) {
|
|
761
|
-
if (isServerActionResult(result) && result.root !== void 0) {
|
|
762
|
-
const decoded = AppElementsWire.decode(result.root);
|
|
763
|
-
const hashIdx = actionRedirectTarget.href.indexOf("#");
|
|
764
|
-
const actionScrollIntent = beginAppRouterScrollIntent((hashIdx !== -1 ? actionRedirectTarget.href.slice(hashIdx) : "") || null);
|
|
765
|
-
if (actionRedirectTarget.type === "push") saveScrollPosition();
|
|
766
|
-
renderNavigationPayload(Promise.resolve(decoded), createClientNavigationRenderSnapshot(actionRedirectTarget.href, actionInitiation.routerState.navigationSnapshot.params), actionRedirectTarget.href, actionInitiation.navigationId, actionRedirectTarget.type === "push" ? "push" : "replace", {}, null, null, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, actionRedirectTarget.type === "push" ? "navigate" : "replace", "server-action", null, actionScrollIntent).catch(() => {
|
|
767
|
-
browserNavigationController.performHardNavigation(actionRedirectTarget.href);
|
|
671
|
+
clearClientNavigationCaches,
|
|
672
|
+
clientRscCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
|
|
673
|
+
commitSameUrlNavigatePayload,
|
|
674
|
+
navigationPlanner,
|
|
675
|
+
performHardNavigation: (url, historyMode) => browserNavigationController.performHardNavigation(url, historyMode),
|
|
676
|
+
renderRedirectPayload(elements, target, actionInitiation) {
|
|
677
|
+
const hashIdx = target.href.indexOf("#");
|
|
678
|
+
const actionScrollIntent = beginAppRouterScrollIntent((hashIdx !== -1 ? target.href.slice(hashIdx) : "") || null);
|
|
679
|
+
if (target.type === "push") saveScrollPosition();
|
|
680
|
+
renderNavigationPayload(Promise.resolve(elements), createClientNavigationRenderSnapshot(target.href, actionInitiation.routerState.navigationSnapshot.params), target.href, actionInitiation.navigationId, target.type === "push" ? "push" : "replace", {}, null, null, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, target.type === "push" ? "navigate" : "replace", "server-action", null, actionScrollIntent).catch(() => {
|
|
681
|
+
browserNavigationController.performHardNavigation(target.href);
|
|
768
682
|
});
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
}
|
|
774
|
-
syncServerActionHttpFallbackHead(isServerActionResult(result) && result.root !== void 0 ? null : fetchResponse.status);
|
|
775
|
-
if (isServerActionResult(result)) {
|
|
776
|
-
if (result.root !== void 0) {
|
|
777
|
-
const returnValue = result.returnValue && !result.returnValue.ok ? {
|
|
778
|
-
ok: false,
|
|
779
|
-
data: normalizeServerActionThrownValue(result.returnValue.data, fetchResponse.status)
|
|
780
|
-
} : result.returnValue;
|
|
781
|
-
return commitSameUrlNavigatePayload(Promise.resolve(AppElementsWire.decode(result.root)), actionInitiation, returnValue, revalidation);
|
|
782
|
-
}
|
|
783
|
-
if (result.returnValue) {
|
|
784
|
-
if (!result.returnValue.ok) throw normalizeServerActionThrownValue(result.returnValue.data, fetchResponse.status);
|
|
785
|
-
return result.returnValue.data;
|
|
786
|
-
}
|
|
787
|
-
return;
|
|
788
|
-
}
|
|
789
|
-
return commitSameUrlNavigatePayload(Promise.resolve(AppElementsWire.decode(result)), actionInitiation, void 0, revalidation);
|
|
790
|
-
};
|
|
791
|
-
setServerCallback((id, args) => {
|
|
792
|
-
const releaseCacheInvalidationGuard = historyController.beginCacheInvalidationGuard();
|
|
793
|
-
return Promise.resolve().then(() => serverActionCallback(id, args)).finally(releaseCacheInvalidationGuard);
|
|
683
|
+
},
|
|
684
|
+
syncCurrentHistoryState: (previousNextUrl, bfcacheIds) => historyController.syncCurrentHistoryStatePreviousNextUrl(previousNextUrl, bfcacheIds),
|
|
685
|
+
syncServerActionHttpFallbackHead
|
|
686
|
+
})).finally(releaseCacheInvalidationGuard);
|
|
794
687
|
});
|
|
795
688
|
}
|
|
796
689
|
async function main() {
|
|
797
690
|
if (!claimInitialAppRouterBootstrap()) return;
|
|
798
|
-
registerServerActionCallback();
|
|
691
|
+
if (hasServerActions) registerServerActionCallback();
|
|
799
692
|
installAppNavigationFailureListeners();
|
|
693
|
+
let devErrorOverlay = null;
|
|
800
694
|
if (import.meta.env.DEV) {
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
695
|
+
devErrorOverlay = await import("./dev-error-overlay.js");
|
|
696
|
+
devErrorOverlay.installDevErrorOverlay();
|
|
697
|
+
devErrorOverlay.installViteHmrErrorHandler(import.meta.hot);
|
|
698
|
+
devErrorOverlay.reportInitialDevServerErrors();
|
|
804
699
|
}
|
|
805
700
|
const rscStream = await readInitialRscStream();
|
|
806
701
|
if (rscStream === null) return;
|
|
807
|
-
bootstrapHydration(rscStream);
|
|
702
|
+
bootstrapHydration(rscStream, devErrorOverlay);
|
|
808
703
|
}
|
|
809
|
-
function bootstrapHydration(rscStream) {
|
|
704
|
+
function bootstrapHydration(rscStream, devErrorOverlay) {
|
|
810
705
|
const root = decodeAppElementsPromise(createFromReadableStream(rscStream));
|
|
811
706
|
const initialNavigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
|
|
812
707
|
historyController.writeBootstrapHistoryMetadata();
|
|
813
708
|
const onUncaughtError = createOnUncaughtError();
|
|
814
709
|
const formState = consumeInitialFormState(getVinextBrowserGlobal());
|
|
815
|
-
const hydrateRootOptions = import.meta.env.DEV ? createVinextHydrateRootOptions({
|
|
710
|
+
const hydrateRootOptions = import.meta.env.DEV && devErrorOverlay ? createVinextHydrateRootOptions({
|
|
816
711
|
formState,
|
|
817
|
-
onCaughtError: createDevOnCaughtError(devOnCaughtError, onUncaughtError),
|
|
712
|
+
onCaughtError: createDevOnCaughtError(devErrorOverlay.devOnCaughtError, onUncaughtError),
|
|
818
713
|
onUncaughtError
|
|
819
714
|
}) : createVinextHydrateRootOptions({
|
|
820
715
|
formState,
|
|
@@ -1141,7 +1036,7 @@ function bootstrapHydration(rscStream) {
|
|
|
1141
1036
|
restorePopstateScrollPosition
|
|
1142
1037
|
}, event.state);
|
|
1143
1038
|
});
|
|
1144
|
-
if (import.meta.hot) {
|
|
1039
|
+
if (import.meta.env.DEV && import.meta.hot) {
|
|
1145
1040
|
const applyRscHmrUpdate = async (updateId) => {
|
|
1146
1041
|
if (updateId !== latestRscHmrUpdateId) return;
|
|
1147
1042
|
if (document.documentElement.id === "__next_error__") {
|
|
@@ -1157,7 +1052,7 @@ function bootstrapHydration(rscStream) {
|
|
|
1157
1052
|
if (!browserNavigationController.hasBrowserRouterState()) return;
|
|
1158
1053
|
clearClientNavigationCaches();
|
|
1159
1054
|
const navigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
|
|
1160
|
-
dismissOverlay();
|
|
1055
|
+
devErrorOverlay?.dismissOverlay();
|
|
1161
1056
|
const hmrHeaders = createRscRequestHeaders();
|
|
1162
1057
|
await browserNavigationController.hmrReplaceTree(decodeAppElementsPromise(createFromFetch(fetch(await createRscRequestUrl(window.location.pathname + window.location.search, hmrHeaders), { headers: hmrHeaders }))), navigationSnapshot);
|
|
1163
1058
|
};
|
|
@@ -45,6 +45,7 @@ type CommitNavigationHistoryOptions = {
|
|
|
45
45
|
targetHistoryIndex?: number | null;
|
|
46
46
|
stageClientParams: () => void;
|
|
47
47
|
};
|
|
48
|
+
declare function createCanonicalBrowserHistoryHref(href: string): string;
|
|
48
49
|
/**
|
|
49
50
|
* Owns App Router browser-history metadata and traversal bookkeeping behind a
|
|
50
51
|
* typed seam: traversal index allocation/commit, push/replace/traverse/hash-only
|
|
@@ -101,4 +102,4 @@ declare class AppBrowserHistoryController {
|
|
|
101
102
|
restoreHistorySnapshot(options: RestoreHistorySnapshotOptions): boolean;
|
|
102
103
|
}
|
|
103
104
|
//#endregion
|
|
104
|
-
export { AppBrowserHistoryController, RestorableSnapshotCandidate };
|
|
105
|
+
export { AppBrowserHistoryController, RestorableSnapshotCandidate, createCanonicalBrowserHistoryHref };
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { RestorableClientStateController, createHistoryStateWithNavigationMetadata, readHistoryStateBfcacheIds, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
|
|
2
2
|
//#region src/server/app-browser-history-controller.ts
|
|
3
|
+
function createCanonicalBrowserHistoryHref(href) {
|
|
4
|
+
const url = new URL(href);
|
|
5
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
6
|
+
}
|
|
3
7
|
function stripVinextScrollState(state) {
|
|
4
8
|
if (!state || typeof state !== "object") return state;
|
|
5
9
|
const nextState = {};
|
|
@@ -166,7 +170,7 @@ var AppBrowserHistoryController = class {
|
|
|
166
170
|
this.#replaceHistoryState(createHistoryStateWithNavigationMetadata(this.#readHistoryState(), {
|
|
167
171
|
previousNextUrl: null,
|
|
168
172
|
traversalIndex: this.#currentHistoryTraversalIndex
|
|
169
|
-
}), this.#readCurrentHref());
|
|
173
|
+
}), createCanonicalBrowserHistoryHref(this.#readCurrentHref()));
|
|
170
174
|
}
|
|
171
175
|
/** History write performed on the first committed (hydrated) render. */
|
|
172
176
|
writeHydratedHistoryMetadata(options) {
|
|
@@ -207,4 +211,4 @@ function areBfcacheIdMapsEqual(a, b) {
|
|
|
207
211
|
return aEntries.every(([key, value]) => b[key] === value);
|
|
208
212
|
}
|
|
209
213
|
//#endregion
|
|
210
|
-
export { AppBrowserHistoryController };
|
|
214
|
+
export { AppBrowserHistoryController, createCanonicalBrowserHistoryHref };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AppElements, AppWireElements } from "./app-elements-wire.js";
|
|
2
|
+
import { navigationPlanner } from "./navigation-planner.js";
|
|
3
|
+
import { AppBrowserServerActionResult, ServerActionRevalidationKind } from "./app-browser-action-result.js";
|
|
4
|
+
import { AppRouterState } from "./app-browser-state.js";
|
|
5
|
+
|
|
6
|
+
//#region src/server/app-browser-server-action-client.d.ts
|
|
7
|
+
type ServerActionResult = AppBrowserServerActionResult<AppWireElements>;
|
|
8
|
+
type ClientServerActionInitiation = {
|
|
9
|
+
href: string;
|
|
10
|
+
navigationId: number;
|
|
11
|
+
path: string;
|
|
12
|
+
routerState: AppRouterState;
|
|
13
|
+
};
|
|
14
|
+
type ActionRedirectTarget = {
|
|
15
|
+
href: string;
|
|
16
|
+
type: string;
|
|
17
|
+
status: number;
|
|
18
|
+
};
|
|
19
|
+
type ClientServerActionDeps = {
|
|
20
|
+
basePath: string;
|
|
21
|
+
clearClientNavigationCaches(): void;
|
|
22
|
+
clientRscCompatibilityId: string | null;
|
|
23
|
+
commitSameUrlNavigatePayload(elements: Promise<AppElements>, actionInitiation: ClientServerActionInitiation, returnValue: ServerActionResult["returnValue"] | undefined, revalidation: ServerActionRevalidationKind): Promise<unknown>;
|
|
24
|
+
navigationPlanner: typeof navigationPlanner;
|
|
25
|
+
performHardNavigation(url: string, historyMode?: "assign" | "replace"): void;
|
|
26
|
+
renderRedirectPayload(elements: AppElements, target: ActionRedirectTarget, actionInitiation: ClientServerActionInitiation): void;
|
|
27
|
+
syncCurrentHistoryState(previousNextUrl: string | null, bfcacheIds: Readonly<Record<string, string>>): void;
|
|
28
|
+
syncServerActionHttpFallbackHead(status: number | null): void;
|
|
29
|
+
};
|
|
30
|
+
declare function invokeClientServerAction(id: string, args: unknown[], actionInitiation: ClientServerActionInitiation, deps: ClientServerActionDeps): Promise<unknown>;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { ClientServerActionDeps, ClientServerActionInitiation, invokeClientServerAction };
|