vinext 0.0.47 → 0.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/build/layout-classification.js +3 -1
- package/dist/build/layout-classification.js.map +1 -1
- package/dist/build/prerender.js +10 -10
- package/dist/build/prerender.js.map +1 -1
- package/dist/build/report.d.ts +8 -4
- package/dist/build/report.js +17 -7
- package/dist/build/report.js.map +1 -1
- package/dist/build/run-prerender.d.ts +5 -0
- package/dist/build/run-prerender.js +4 -1
- package/dist/build/run-prerender.js.map +1 -1
- package/dist/build/server-manifest.js +2 -7
- package/dist/build/server-manifest.js.map +1 -1
- package/dist/build/standalone.js +3 -5
- package/dist/build/standalone.js.map +1 -1
- package/dist/check.js +45 -29
- package/dist/check.js.map +1 -1
- package/dist/cli-args.d.ts +3 -1
- package/dist/cli-args.js +18 -1
- package/dist/cli-args.js.map +1 -1
- package/dist/cli.js +9 -1
- package/dist/cli.js.map +1 -1
- package/dist/config/config-matchers.js +46 -37
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/deploy.d.ts +18 -2
- package/dist/deploy.js +47 -4
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-rsc-entry.js +11 -9
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.js +4 -1
- package/dist/entries/app-rsc-manifest.js.map +1 -1
- package/dist/entries/pages-client-entry.js +3 -2
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-server-entry.js +21 -62
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.d.ts +12 -3
- package/dist/entries/runtime-entry-module.js +15 -4
- package/dist/entries/runtime-entry-module.js.map +1 -1
- package/dist/index.js +12 -7
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +1 -1
- package/dist/init.js +2 -2
- package/dist/init.js.map +1 -1
- package/dist/plugins/og-assets.js +15 -16
- package/dist/plugins/og-assets.js.map +1 -1
- package/dist/plugins/rsc-client-shim-excludes.d.ts +2 -1
- package/dist/plugins/rsc-client-shim-excludes.js +10 -1
- package/dist/plugins/rsc-client-shim-excludes.js.map +1 -1
- package/dist/routing/app-route-graph.d.ts +90 -4
- package/dist/routing/app-route-graph.js +210 -7
- package/dist/routing/app-route-graph.js.map +1 -1
- package/dist/routing/app-router.d.ts +15 -3
- package/dist/routing/app-router.js +20 -23
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/file-matcher.d.ts +3 -1
- package/dist/routing/file-matcher.js +6 -1
- package/dist/routing/file-matcher.js.map +1 -1
- package/dist/routing/pages-router.js +10 -19
- package/dist/routing/pages-router.js.map +1 -1
- package/dist/routing/route-matching.d.ts +28 -0
- package/dist/routing/route-matching.js +44 -0
- package/dist/routing/route-matching.js.map +1 -0
- package/dist/routing/route-pattern.js +4 -1
- package/dist/routing/route-pattern.js.map +1 -1
- package/dist/routing/route-trie.d.ts +8 -0
- package/dist/routing/route-trie.js +12 -1
- package/dist/routing/route-trie.js.map +1 -1
- package/dist/routing/route-validation.js +3 -4
- package/dist/routing/route-validation.js.map +1 -1
- package/dist/routing/utils.d.ts +8 -1
- package/dist/routing/utils.js +25 -2
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/api-handler.js +2 -8
- package/dist/server/api-handler.js.map +1 -1
- package/dist/server/app-browser-entry.js +66 -49
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-navigation-controller.d.ts +7 -5
- package/dist/server/app-browser-navigation-controller.js +43 -35
- package/dist/server/app-browser-navigation-controller.js.map +1 -1
- package/dist/server/app-browser-state.d.ts +33 -15
- package/dist/server/app-browser-state.js +52 -59
- package/dist/server/app-browser-state.js.map +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +68 -0
- package/dist/server/app-browser-visible-commit.js +182 -0
- package/dist/server/app-browser-visible-commit.js.map +1 -0
- package/dist/server/app-client-reference-preloader.d.ts +15 -0
- package/dist/server/app-client-reference-preloader.js +46 -0
- package/dist/server/app-client-reference-preloader.js.map +1 -0
- package/dist/server/app-elements-wire.d.ts +130 -0
- package/dist/server/app-elements-wire.js +205 -0
- package/dist/server/app-elements-wire.js.map +1 -0
- package/dist/server/app-elements.d.ts +2 -84
- package/dist/server/app-elements.js +3 -102
- package/dist/server/app-elements.js.map +1 -1
- package/dist/server/app-fallback-renderer.d.ts +1 -1
- package/dist/server/app-middleware.d.ts +2 -1
- package/dist/server/app-middleware.js +34 -11
- package/dist/server/app-middleware.js.map +1 -1
- package/dist/server/app-page-boundary-render.d.ts +1 -1
- package/dist/server/app-page-boundary-render.js +8 -5
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-boundary.js +2 -1
- package/dist/server/app-page-boundary.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +1 -0
- package/dist/server/app-page-cache.js +8 -13
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-dispatch.d.ts +2 -1
- package/dist/server/app-page-dispatch.js +18 -10
- package/dist/server/app-page-dispatch.js.map +1 -1
- package/dist/server/app-page-element-builder.d.ts +1 -1
- package/dist/server/app-page-element-builder.js +8 -5
- package/dist/server/app-page-element-builder.js.map +1 -1
- package/dist/server/app-page-execution.d.ts +23 -5
- package/dist/server/app-page-execution.js +39 -24
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-head.js +2 -1
- package/dist/server/app-page-head.js.map +1 -1
- package/dist/server/app-page-method.js +2 -5
- package/dist/server/app-page-method.js.map +1 -1
- package/dist/server/app-page-probe.d.ts +1 -1
- package/dist/server/app-page-probe.js +5 -1
- package/dist/server/app-page-probe.js.map +1 -1
- package/dist/server/app-page-render.d.ts +1 -1
- package/dist/server/app-page-render.js +38 -3
- package/dist/server/app-page-render.js.map +1 -1
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +7 -10
- package/dist/server/app-page-request.js.map +1 -1
- package/dist/server/app-page-response.js +3 -2
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +5 -2
- package/dist/server/app-page-route-wiring.js +15 -12
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-page-stream.d.ts +7 -0
- package/dist/server/app-page-stream.js +9 -2
- package/dist/server/app-page-stream.js.map +1 -1
- package/dist/server/app-prerender-endpoints.js +3 -2
- package/dist/server/app-prerender-endpoints.js.map +1 -1
- package/dist/server/app-route-handler-cache.js +2 -1
- package/dist/server/app-route-handler-cache.js.map +1 -1
- package/dist/server/app-route-handler-dispatch.js +6 -5
- package/dist/server/app-route-handler-dispatch.js.map +1 -1
- package/dist/server/app-route-handler-policy.js +13 -13
- package/dist/server/app-route-handler-policy.js.map +1 -1
- package/dist/server/app-route-handler-response.js +2 -1
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-route-handler-runtime.d.ts +9 -1
- package/dist/server/app-route-handler-runtime.js +11 -1
- package/dist/server/app-route-handler-runtime.js.map +1 -1
- package/dist/server/app-router-entry.js +9 -4
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +34 -0
- package/dist/server/app-rsc-cache-busting.js +137 -0
- package/dist/server/app-rsc-cache-busting.js.map +1 -0
- package/dist/server/app-rsc-handler.js +22 -11
- package/dist/server/app-rsc-handler.js.map +1 -1
- package/dist/server/app-rsc-request-normalization.d.ts +4 -2
- package/dist/server/app-rsc-request-normalization.js +10 -6
- package/dist/server/app-rsc-request-normalization.js.map +1 -1
- package/dist/server/app-rsc-response-finalizer.js +1 -1
- package/dist/server/app-rsc-route-matching.js +8 -4
- package/dist/server/app-rsc-route-matching.js.map +1 -1
- package/dist/server/app-segment-config.js +4 -0
- package/dist/server/app-segment-config.js.map +1 -1
- package/dist/server/app-server-action-execution.js +43 -51
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/app-ssr-entry.js +21 -20
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/artifact-compatibility.d.ts +44 -0
- package/dist/server/artifact-compatibility.js +82 -0
- package/dist/server/artifact-compatibility.js.map +1 -0
- package/dist/server/cache-proof.d.ts +200 -0
- package/dist/server/cache-proof.js +342 -0
- package/dist/server/cache-proof.js.map +1 -0
- package/dist/server/dev-origin-check.js +8 -4
- package/dist/server/dev-origin-check.js.map +1 -1
- package/dist/server/dev-server.js +6 -16
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/http-error-responses.d.ts +67 -0
- package/dist/server/http-error-responses.js +77 -0
- package/dist/server/http-error-responses.js.map +1 -0
- package/dist/server/image-optimization.js +2 -1
- package/dist/server/image-optimization.js.map +1 -1
- package/dist/server/metadata-route-response.js +6 -5
- package/dist/server/metadata-route-response.js.map +1 -1
- package/dist/server/metadata-routes.d.ts +1 -0
- package/dist/server/metadata-routes.js +6 -0
- package/dist/server/metadata-routes.js.map +1 -1
- package/dist/server/middleware-matcher.js +2 -2
- package/dist/server/middleware-matcher.js.map +1 -1
- package/dist/server/middleware-response-headers.js +21 -0
- package/dist/server/middleware-response-headers.js.map +1 -1
- package/dist/server/middleware-runtime.js +3 -3
- package/dist/server/middleware-runtime.js.map +1 -1
- package/dist/server/navigation-trace.d.ts +33 -0
- package/dist/server/navigation-trace.js +35 -0
- package/dist/server/navigation-trace.js.map +1 -0
- package/dist/server/next-error-digest.d.ts +44 -0
- package/dist/server/next-error-digest.js +40 -0
- package/dist/server/next-error-digest.js.map +1 -0
- package/dist/server/pages-api-route.js +4 -7
- package/dist/server/pages-api-route.js.map +1 -1
- package/dist/server/pages-node-compat.js +4 -16
- package/dist/server/pages-node-compat.js.map +1 -1
- package/dist/server/pages-page-response.d.ts +2 -8
- package/dist/server/pages-page-response.js +44 -14
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/prod-server.d.ts +6 -0
- package/dist/server/prod-server.js +28 -21
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +42 -1
- package/dist/server/request-pipeline.js +97 -17
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/shims/cache-runtime.d.ts +2 -2
- package/dist/shims/cache-runtime.js +3 -6
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.js +3 -5
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/fetch-cache.js +2 -3
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/head-state.js +2 -3
- package/dist/shims/head-state.js.map +1 -1
- package/dist/shims/headers.js +4 -44
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/i18n-state.js +2 -3
- package/dist/shims/i18n-state.js.map +1 -1
- package/dist/shims/internal/als-registry.d.ts +15 -0
- package/dist/shims/internal/als-registry.js +55 -0
- package/dist/shims/internal/als-registry.js.map +1 -0
- package/dist/shims/internal/cookie-serialize.d.ts +46 -0
- package/dist/shims/internal/cookie-serialize.js +51 -0
- package/dist/shims/internal/cookie-serialize.js.map +1 -0
- package/dist/shims/link.js +31 -26
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +26 -1
- package/dist/shims/metadata.js +94 -4
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation-state.js +2 -3
- package/dist/shims/navigation-state.js.map +1 -1
- package/dist/shims/navigation.d.ts +2 -7
- package/dist/shims/navigation.js +44 -36
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/request-context.js +2 -4
- package/dist/shims/request-context.js.map +1 -1
- package/dist/shims/router-state.js +2 -3
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/router.js +2 -2
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/server.js +5 -30
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/slot.d.ts +1 -1
- package/dist/shims/slot.js +5 -4
- package/dist/shims/slot.js.map +1 -1
- package/dist/shims/thenable-params.d.ts +5 -2
- package/dist/shims/thenable-params.js +26 -6
- package/dist/shims/thenable-params.js.map +1 -1
- package/dist/shims/unified-request-context.js +2 -14
- package/dist/shims/unified-request-context.js.map +1 -1
- package/dist/utils/base-path.d.ts +7 -1
- package/dist/utils/base-path.js +12 -1
- package/dist/utils/base-path.js.map +1 -1
- package/dist/utils/query.d.ts +8 -1
- package/dist/utils/query.js +12 -1
- package/dist/utils/query.js.map +1 -1
- package/dist/utils/safe-json-file.d.ts +18 -0
- package/dist/utils/safe-json-file.js +25 -0
- package/dist/utils/safe-json-file.js.map +1 -0
- package/dist/utils/text-stream.d.ts +29 -0
- package/dist/utils/text-stream.js +66 -0
- package/dist/utils/text-stream.js.map +1 -0
- package/package.json +5 -5
|
@@ -3,6 +3,7 @@ import { scanWithExtensions } from "./file-matcher.js";
|
|
|
3
3
|
import { validateRoutePatterns } from "./route-validation.js";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
6
7
|
//#region src/routing/app-route-graph.ts
|
|
7
8
|
/**
|
|
8
9
|
* App Router route graph construction.
|
|
@@ -10,6 +11,139 @@ import path from "node:path";
|
|
|
10
11
|
* Scans app/ directories and materializes route metadata before the request-time
|
|
11
12
|
* matcher consumes it. Keep request matching and cache ownership in app-router.ts.
|
|
12
13
|
*/
|
|
14
|
+
function createAppRouteGraphRouteId(pattern) {
|
|
15
|
+
return `route:${pattern}`;
|
|
16
|
+
}
|
|
17
|
+
function createAppRouteGraphPageId(pattern) {
|
|
18
|
+
return `page:${pattern}`;
|
|
19
|
+
}
|
|
20
|
+
function createAppRouteGraphRouteHandlerId(pattern) {
|
|
21
|
+
return `route-handler:${pattern}`;
|
|
22
|
+
}
|
|
23
|
+
function createAppRouteGraphLayoutId(treePath) {
|
|
24
|
+
return `layout:${treePath}`;
|
|
25
|
+
}
|
|
26
|
+
function createAppRouteGraphTemplateId(treePath) {
|
|
27
|
+
return `template:${treePath}`;
|
|
28
|
+
}
|
|
29
|
+
function createAppRouteGraphSlotId(slotName, ownerTreePath) {
|
|
30
|
+
return `slot:${slotName}:${ownerTreePath}`;
|
|
31
|
+
}
|
|
32
|
+
function createAppRouteGraphRootBoundaryId(treePath) {
|
|
33
|
+
return `root-boundary:${treePath}`;
|
|
34
|
+
}
|
|
35
|
+
function compareStableStrings(left, right) {
|
|
36
|
+
if (left < right) return -1;
|
|
37
|
+
if (left > right) return 1;
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
function sortedMapValues(map) {
|
|
41
|
+
return Array.from(map.entries()).sort(([left], [right]) => compareStableStrings(left, right)).map(([, value]) => value);
|
|
42
|
+
}
|
|
43
|
+
function createRouteManifest(routes) {
|
|
44
|
+
const segmentGraph = createStaticSegmentGraph(routes);
|
|
45
|
+
return {
|
|
46
|
+
graphVersion: createRouteManifestGraphVersion(segmentGraph),
|
|
47
|
+
segmentGraph
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function createStaticSegmentGraph(routes) {
|
|
51
|
+
const routeEntries = /* @__PURE__ */ new Map();
|
|
52
|
+
const pages = /* @__PURE__ */ new Map();
|
|
53
|
+
const routeHandlers = /* @__PURE__ */ new Map();
|
|
54
|
+
const layouts = /* @__PURE__ */ new Map();
|
|
55
|
+
const templates = /* @__PURE__ */ new Map();
|
|
56
|
+
const slots = /* @__PURE__ */ new Map();
|
|
57
|
+
const rootBoundaries = /* @__PURE__ */ new Map();
|
|
58
|
+
for (const route of routes) {
|
|
59
|
+
routeEntries.set(route.ids.route, {
|
|
60
|
+
id: route.ids.route,
|
|
61
|
+
pattern: route.pattern,
|
|
62
|
+
patternParts: [...route.patternParts],
|
|
63
|
+
isDynamic: route.isDynamic,
|
|
64
|
+
paramNames: [...route.params],
|
|
65
|
+
rootParamNames: [...route.rootParamNames],
|
|
66
|
+
rootBoundaryId: route.ids.rootBoundary,
|
|
67
|
+
pageId: route.ids.page,
|
|
68
|
+
routeHandlerId: route.ids.routeHandler,
|
|
69
|
+
layoutIds: [...route.ids.layouts],
|
|
70
|
+
templateIds: [...route.ids.templates],
|
|
71
|
+
slotIds: route.parallelSlots.map((slot) => slot.id).sort(compareStableStrings)
|
|
72
|
+
});
|
|
73
|
+
if (route.ids.page) pages.set(route.ids.page, {
|
|
74
|
+
id: route.ids.page,
|
|
75
|
+
routeId: route.ids.route,
|
|
76
|
+
pattern: route.pattern
|
|
77
|
+
});
|
|
78
|
+
if (route.ids.routeHandler) routeHandlers.set(route.ids.routeHandler, {
|
|
79
|
+
id: route.ids.routeHandler,
|
|
80
|
+
routeId: route.ids.route,
|
|
81
|
+
pattern: route.pattern
|
|
82
|
+
});
|
|
83
|
+
for (const [index, layoutId] of route.ids.layouts.entries()) {
|
|
84
|
+
const treePosition = route.layoutTreePositions[index];
|
|
85
|
+
assertRouteManifestTreePosition("layout", route, layoutId, treePosition);
|
|
86
|
+
const treePath = createAppRouteGraphTreePath(route.routeSegments, treePosition);
|
|
87
|
+
const existingLayout = layouts.get(layoutId);
|
|
88
|
+
if (existingLayout) assertRouteManifestRootBoundary("layout", route, layoutId, existingLayout.rootBoundaryId);
|
|
89
|
+
layouts.set(layoutId, {
|
|
90
|
+
id: layoutId,
|
|
91
|
+
treePath,
|
|
92
|
+
rootBoundaryId: route.ids.rootBoundary
|
|
93
|
+
});
|
|
94
|
+
if (index === 0 && route.ids.rootBoundary) rootBoundaries.set(route.ids.rootBoundary, {
|
|
95
|
+
id: route.ids.rootBoundary,
|
|
96
|
+
layoutId,
|
|
97
|
+
treePath
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
for (const [index, templateId] of route.ids.templates.entries()) {
|
|
101
|
+
const treePosition = route.templateTreePositions?.[index];
|
|
102
|
+
assertRouteManifestTreePosition("template", route, templateId, treePosition);
|
|
103
|
+
const existingTemplate = templates.get(templateId);
|
|
104
|
+
if (existingTemplate) assertRouteManifestRootBoundary("template", route, templateId, existingTemplate.rootBoundaryId);
|
|
105
|
+
templates.set(templateId, {
|
|
106
|
+
id: templateId,
|
|
107
|
+
treePath: createAppRouteGraphTreePath(route.routeSegments, treePosition),
|
|
108
|
+
rootBoundaryId: route.ids.rootBoundary
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
for (const slot of route.parallelSlots) slots.set(slot.id, {
|
|
112
|
+
id: slot.id,
|
|
113
|
+
key: slot.key,
|
|
114
|
+
name: slot.name
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
routes: routeEntries,
|
|
119
|
+
pages,
|
|
120
|
+
routeHandlers,
|
|
121
|
+
layouts,
|
|
122
|
+
templates,
|
|
123
|
+
slots,
|
|
124
|
+
rootBoundaries
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function assertRouteManifestTreePosition(kind, route, id, treePosition) {
|
|
128
|
+
if (treePosition !== void 0) return;
|
|
129
|
+
throw new Error(`[vinext] App route graph invariant violated: missing ${kind} tree position for ${id} on ${route.pattern}`);
|
|
130
|
+
}
|
|
131
|
+
function assertRouteManifestRootBoundary(kind, route, id, existingRootBoundaryId) {
|
|
132
|
+
if (existingRootBoundaryId === route.ids.rootBoundary) return;
|
|
133
|
+
throw new Error(`[vinext] App route graph invariant violated: ${kind} ${id} is shared across root boundaries (${existingRootBoundaryId ?? "none"} and ${route.ids.rootBoundary ?? "none"}) on ${route.pattern}`);
|
|
134
|
+
}
|
|
135
|
+
function createRouteManifestGraphVersion(segmentGraph) {
|
|
136
|
+
const stableShape = {
|
|
137
|
+
routes: sortedMapValues(segmentGraph.routes),
|
|
138
|
+
pages: sortedMapValues(segmentGraph.pages),
|
|
139
|
+
routeHandlers: sortedMapValues(segmentGraph.routeHandlers),
|
|
140
|
+
layouts: sortedMapValues(segmentGraph.layouts),
|
|
141
|
+
templates: sortedMapValues(segmentGraph.templates),
|
|
142
|
+
slots: sortedMapValues(segmentGraph.slots),
|
|
143
|
+
rootBoundaries: sortedMapValues(segmentGraph.rootBoundaries)
|
|
144
|
+
};
|
|
145
|
+
return `graph:${createHash("sha256").update(JSON.stringify(stableShape)).digest("hex")}`;
|
|
146
|
+
}
|
|
13
147
|
async function buildAppRouteGraph(appDir, matcher) {
|
|
14
148
|
const routes = [];
|
|
15
149
|
const excludeDir = (name) => name.startsWith("@") || name.startsWith("_");
|
|
@@ -38,7 +172,10 @@ async function buildAppRouteGraph(appDir, matcher) {
|
|
|
38
172
|
validateRoutePatterns(routes.map((route) => route.pattern));
|
|
39
173
|
validateRoutePatterns([...new Set(routes.flatMap((route) => route.parallelSlots.flatMap((slot) => slot.interceptingRoutes.map((intercept) => intercept.targetPattern))))]);
|
|
40
174
|
routes.sort(compareRoutes);
|
|
41
|
-
return {
|
|
175
|
+
return {
|
|
176
|
+
routes,
|
|
177
|
+
routeManifest: createRouteManifest(routes)
|
|
178
|
+
};
|
|
42
179
|
}
|
|
43
180
|
function hasParallelSlotDirectory(dir) {
|
|
44
181
|
try {
|
|
@@ -99,8 +236,9 @@ function discoverSlotSubRoutes(routes, matcher) {
|
|
|
99
236
|
};
|
|
100
237
|
for (const parentRoute of routes) {
|
|
101
238
|
if (parentRoute.parallelSlots.length === 0) continue;
|
|
102
|
-
|
|
103
|
-
|
|
239
|
+
const isLayoutOnlyUiRoute = !parentRoute.pagePath && !parentRoute.routePath && parentRoute.layouts.length > 0;
|
|
240
|
+
if (!parentRoute.pagePath && !isLayoutOnlyUiRoute) continue;
|
|
241
|
+
const parentPageDir = parentRoute.pagePath ? path.dirname(parentRoute.pagePath) : path.dirname(parentRoute.layouts[parentRoute.layouts.length - 1]);
|
|
104
242
|
const subPathMap = /* @__PURE__ */ new Map();
|
|
105
243
|
for (const slot of parentRoute.parallelSlots) {
|
|
106
244
|
if (path.dirname(slot.ownerDir) !== parentPageDir) continue;
|
|
@@ -131,7 +269,7 @@ function discoverSlotSubRoutes(routes, matcher) {
|
|
|
131
269
|
}
|
|
132
270
|
if (subPathMap.size === 0) continue;
|
|
133
271
|
const childrenDefault = findFile(parentPageDir, "default", matcher);
|
|
134
|
-
if (!childrenDefault) continue;
|
|
272
|
+
if (parentRoute.pagePath && !childrenDefault) continue;
|
|
135
273
|
for (const { rawSegments, converted: convertedSubRoute, slotPages } of subPathMap.values()) {
|
|
136
274
|
const { urlSegments: urlParts, params: subParams, isDynamic: subIsDynamic } = convertedSubRoute;
|
|
137
275
|
const subUrlPath = urlParts.join("/");
|
|
@@ -142,6 +280,8 @@ function discoverSlotSubRoutes(routes, matcher) {
|
|
|
142
280
|
applySlotSubPages(existingRoute, slotPages, rawSegments);
|
|
143
281
|
continue;
|
|
144
282
|
}
|
|
283
|
+
const syntheticParts = [...parentRoute.patternParts, ...urlParts];
|
|
284
|
+
if (Array.from(routesByPattern.values()).some((r) => patternsStructurallyEquivalent(r.patternParts, syntheticParts))) continue;
|
|
145
285
|
const subSlots = parentRoute.parallelSlots.map((slot) => {
|
|
146
286
|
const subPage = slotPages.get(slot.key);
|
|
147
287
|
return {
|
|
@@ -151,6 +291,15 @@ function discoverSlotSubRoutes(routes, matcher) {
|
|
|
151
291
|
};
|
|
152
292
|
});
|
|
153
293
|
const newRoute = {
|
|
294
|
+
ids: createAppRouteSemanticIds({
|
|
295
|
+
pattern,
|
|
296
|
+
pagePath: childrenDefault,
|
|
297
|
+
routePath: null,
|
|
298
|
+
routeSegments: [...parentRoute.routeSegments, ...rawSegments],
|
|
299
|
+
layoutTreePositions: parentRoute.layoutTreePositions,
|
|
300
|
+
templateTreePositions: parentRoute.templateTreePositions,
|
|
301
|
+
slots: subSlots
|
|
302
|
+
}),
|
|
154
303
|
pattern,
|
|
155
304
|
pagePath: childrenDefault,
|
|
156
305
|
routePath: null,
|
|
@@ -245,6 +394,15 @@ function directoryToAppRoute(dir, appDir, matcher, pagePath, routePath) {
|
|
|
245
394
|
const unauthorizedPaths = discoverBoundaryFilePerLayout(layouts, "unauthorized", matcher);
|
|
246
395
|
const parallelSlots = discoverInheritedParallelSlots(segments, appDir, routeDir, matcher);
|
|
247
396
|
return {
|
|
397
|
+
ids: createAppRouteSemanticIds({
|
|
398
|
+
pattern: pattern === "/" ? "/" : pattern,
|
|
399
|
+
pagePath,
|
|
400
|
+
routePath,
|
|
401
|
+
routeSegments: segments,
|
|
402
|
+
layoutTreePositions,
|
|
403
|
+
templateTreePositions,
|
|
404
|
+
slots: parallelSlots
|
|
405
|
+
}),
|
|
248
406
|
pattern: pattern === "/" ? "/" : pattern,
|
|
249
407
|
pagePath,
|
|
250
408
|
routePath,
|
|
@@ -285,6 +443,29 @@ function computeRootParamNames(routeSegments, layoutTreePositions) {
|
|
|
285
443
|
}
|
|
286
444
|
return names;
|
|
287
445
|
}
|
|
446
|
+
function resolveRootBoundaryId(routeSegments, layoutTreePositions) {
|
|
447
|
+
const rootLayoutPosition = layoutTreePositions[0];
|
|
448
|
+
if (rootLayoutPosition === void 0) return null;
|
|
449
|
+
return createAppRouteGraphRootBoundaryId(createAppRouteGraphTreePath(routeSegments, rootLayoutPosition));
|
|
450
|
+
}
|
|
451
|
+
function createAppRouteSemanticIds(input) {
|
|
452
|
+
const slots = {};
|
|
453
|
+
for (const slot of input.slots) slots[slot.key] = slot.id;
|
|
454
|
+
return {
|
|
455
|
+
route: createAppRouteGraphRouteId(input.pattern),
|
|
456
|
+
page: input.pagePath ? createAppRouteGraphPageId(input.pattern) : null,
|
|
457
|
+
routeHandler: input.routePath ? createAppRouteGraphRouteHandlerId(input.pattern) : null,
|
|
458
|
+
rootBoundary: resolveRootBoundaryId(input.routeSegments, input.layoutTreePositions),
|
|
459
|
+
layouts: input.layoutTreePositions.map((treePosition) => createAppRouteGraphLayoutId(createAppRouteGraphTreePath(input.routeSegments, treePosition))),
|
|
460
|
+
templates: (input.templateTreePositions ?? []).map((treePosition) => createAppRouteGraphTemplateId(createAppRouteGraphTreePath(input.routeSegments, treePosition))),
|
|
461
|
+
slots
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
function createAppRouteGraphTreePath(routeSegments, treePosition) {
|
|
465
|
+
const treePathSegments = routeSegments.slice(0, treePosition);
|
|
466
|
+
if (treePathSegments.length === 0) return "/";
|
|
467
|
+
return `/${treePathSegments.join("/")}`;
|
|
468
|
+
}
|
|
288
469
|
/**
|
|
289
470
|
* Compute the tree position (directory depth from app root) for each layout.
|
|
290
471
|
* Root layout = 0, a layout at app/blog/ = 1, app/blog/(group)/ = 2.
|
|
@@ -545,6 +726,22 @@ function scoreSlotPattern(urlSegments) {
|
|
|
545
726
|
return score;
|
|
546
727
|
}
|
|
547
728
|
/**
|
|
729
|
+
* Map a pattern segment to the tree-node type used by Next.js' route
|
|
730
|
+
* validator. Two segments are structurally equivalent iff they share the
|
|
731
|
+
* same tree-node type.
|
|
732
|
+
*/
|
|
733
|
+
function segmentTreeNodeType(seg) {
|
|
734
|
+
if (!seg.startsWith(":")) return `literal:${seg}`;
|
|
735
|
+
if (seg.endsWith("*")) return "optionalCatchAll";
|
|
736
|
+
if (seg.endsWith("+")) return "catchAll";
|
|
737
|
+
return "dynamic";
|
|
738
|
+
}
|
|
739
|
+
function patternsStructurallyEquivalent(a, b) {
|
|
740
|
+
if (a.length !== b.length) return false;
|
|
741
|
+
for (let i = 0; i < a.length; i++) if (segmentTreeNodeType(a[i]) !== segmentTreeNodeType(b[i])) return false;
|
|
742
|
+
return true;
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
548
745
|
* Discover parallel route slots (@team, @analytics, etc.) in a directory.
|
|
549
746
|
* Returns a ParallelSlot for each @-prefixed subdirectory that has a page or default component.
|
|
550
747
|
*/
|
|
@@ -560,7 +757,10 @@ function discoverParallelSlots(dir, appDir, matcher) {
|
|
|
560
757
|
const defaultPath = findFile(slotDir, "default", matcher);
|
|
561
758
|
const interceptingRoutes = discoverInterceptingRoutes(slotDir, dir, appDir, matcher);
|
|
562
759
|
if (!pagePath && !defaultPath && interceptingRoutes.length === 0) continue;
|
|
760
|
+
const ownerSegments = path.relative(appDir, dir).split(path.sep).filter((segment) => segment.length > 0);
|
|
761
|
+
const ownerTreePath = createAppRouteGraphTreePath(ownerSegments, ownerSegments.length);
|
|
563
762
|
slots.push({
|
|
763
|
+
id: createAppRouteGraphSlotId(slotName, ownerTreePath),
|
|
564
764
|
key: `${slotName}@${path.relative(appDir, slotDir).replace(/\\/g, "/")}`,
|
|
565
765
|
name: slotName,
|
|
566
766
|
ownerDir: slotDir,
|
|
@@ -774,24 +974,27 @@ function convertSegmentsToRouteParts(segments) {
|
|
|
774
974
|
for (let i = 0; i < segments.length; i++) {
|
|
775
975
|
const segment = segments[i];
|
|
776
976
|
if (isInvisibleSegment(segment)) continue;
|
|
777
|
-
const catchAllMatch = segment.match(/^\[\.\.\.([
|
|
977
|
+
const catchAllMatch = segment.match(/^\[\.\.\.([^\]]+)\]$/);
|
|
778
978
|
if (catchAllMatch) {
|
|
779
979
|
if (hasRemainingVisibleSegments(segments, i + 1)) return null;
|
|
980
|
+
if (catchAllMatch[1].endsWith("+") || catchAllMatch[1].endsWith("*")) return null;
|
|
780
981
|
isDynamic = true;
|
|
781
982
|
params.push(catchAllMatch[1]);
|
|
782
983
|
urlSegments.push(`:${catchAllMatch[1]}+`);
|
|
783
984
|
continue;
|
|
784
985
|
}
|
|
785
|
-
const optionalCatchAllMatch = segment.match(/^\[\[\.\.\.([
|
|
986
|
+
const optionalCatchAllMatch = segment.match(/^\[\[\.\.\.([^\]]+)\]\]$/);
|
|
786
987
|
if (optionalCatchAllMatch) {
|
|
787
988
|
if (hasRemainingVisibleSegments(segments, i + 1)) return null;
|
|
989
|
+
if (optionalCatchAllMatch[1].endsWith("+") || optionalCatchAllMatch[1].endsWith("*")) return null;
|
|
788
990
|
isDynamic = true;
|
|
789
991
|
params.push(optionalCatchAllMatch[1]);
|
|
790
992
|
urlSegments.push(`:${optionalCatchAllMatch[1]}*`);
|
|
791
993
|
continue;
|
|
792
994
|
}
|
|
793
|
-
const dynamicMatch = segment.match(/^\[([
|
|
995
|
+
const dynamicMatch = segment.match(/^\[([^\]]+)\]$/);
|
|
794
996
|
if (dynamicMatch) {
|
|
997
|
+
if (dynamicMatch[1].endsWith("+") || dynamicMatch[1].endsWith("*")) return null;
|
|
795
998
|
isDynamic = true;
|
|
796
999
|
params.push(dynamicMatch[1]);
|
|
797
1000
|
urlSegments.push(`:${dynamicMatch[1]}`);
|