@tanstack/router-generator 1.166.8 → 1.166.10
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/cjs/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/cjs/config.cjs +111 -147
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/filesystem/physical/getRouteNodes.cjs +224 -303
- package/dist/cjs/filesystem/physical/getRouteNodes.cjs.map +1 -1
- package/dist/cjs/filesystem/physical/rootPathId.cjs +5 -4
- package/dist/cjs/filesystem/physical/rootPathId.cjs.map +1 -1
- package/dist/cjs/filesystem/virtual/config.cjs +32 -30
- package/dist/cjs/filesystem/virtual/config.cjs.map +1 -1
- package/dist/cjs/filesystem/virtual/getRouteNodes.cjs +164 -209
- package/dist/cjs/filesystem/virtual/getRouteNodes.cjs.map +1 -1
- package/dist/cjs/filesystem/virtual/loadConfigFile.cjs +9 -8
- package/dist/cjs/filesystem/virtual/loadConfigFile.cjs.map +1 -1
- package/dist/cjs/generator.cjs +766 -1106
- package/dist/cjs/generator.cjs.map +1 -1
- package/dist/cjs/index.cjs +32 -34
- package/dist/cjs/logger.cjs +28 -34
- package/dist/cjs/logger.cjs.map +1 -1
- package/dist/cjs/template.cjs +144 -151
- package/dist/cjs/template.cjs.map +1 -1
- package/dist/cjs/transform/transform.cjs +287 -426
- package/dist/cjs/transform/transform.cjs.map +1 -1
- package/dist/cjs/transform/utils.cjs +31 -33
- package/dist/cjs/transform/utils.cjs.map +1 -1
- package/dist/cjs/utils.cjs +534 -544
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/validate-route-params.cjs +66 -51
- package/dist/cjs/validate-route-params.cjs.map +1 -1
- package/dist/esm/config.js +106 -147
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/filesystem/physical/getRouteNodes.js +220 -286
- package/dist/esm/filesystem/physical/getRouteNodes.js.map +1 -1
- package/dist/esm/filesystem/physical/rootPathId.js +6 -5
- package/dist/esm/filesystem/physical/rootPathId.js.map +1 -1
- package/dist/esm/filesystem/virtual/config.js +31 -30
- package/dist/esm/filesystem/virtual/config.js.map +1 -1
- package/dist/esm/filesystem/virtual/getRouteNodes.js +161 -208
- package/dist/esm/filesystem/virtual/getRouteNodes.js.map +1 -1
- package/dist/esm/filesystem/virtual/loadConfigFile.js +7 -7
- package/dist/esm/filesystem/virtual/loadConfigFile.js.map +1 -1
- package/dist/esm/generator.js +756 -1083
- package/dist/esm/generator.js.map +1 -1
- package/dist/esm/index.js +4 -31
- package/dist/esm/logger.js +29 -35
- package/dist/esm/logger.js.map +1 -1
- package/dist/esm/template.js +144 -152
- package/dist/esm/template.js.map +1 -1
- package/dist/esm/transform/transform.js +285 -425
- package/dist/esm/transform/transform.js.map +1 -1
- package/dist/esm/transform/utils.js +31 -33
- package/dist/esm/transform/utils.js.map +1 -1
- package/dist/esm/utils.js +529 -564
- package/dist/esm/utils.js.map +1 -1
- package/dist/esm/validate-route-params.js +67 -52
- package/dist/esm/validate-route-params.js.map +1 -1
- package/package.json +5 -5
- package/dist/cjs/index.cjs.map +0 -1
- package/dist/esm/index.js.map +0 -1
package/dist/esm/utils.js
CHANGED
|
@@ -1,644 +1,609 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "./filesystem/physical/rootPathId.js";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import * as fsp from "node:fs/promises";
|
|
3
4
|
import * as prettier from "prettier";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return this.prefixToRoute.get(routePath);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
5
|
+
//#region src/utils.ts
|
|
6
|
+
/**
|
|
7
|
+
* Prefix map for O(1) parent route lookups.
|
|
8
|
+
* Maps each route path prefix to the route node that owns that prefix.
|
|
9
|
+
* Enables finding longest matching parent without linear search.
|
|
10
|
+
*/
|
|
11
|
+
var RoutePrefixMap = class {
|
|
12
|
+
constructor(routes) {
|
|
13
|
+
this.prefixToRoute = /* @__PURE__ */ new Map();
|
|
14
|
+
this.layoutRoutes = [];
|
|
15
|
+
for (const route of routes) {
|
|
16
|
+
if (!route.routePath || route.routePath === `/__root`) continue;
|
|
17
|
+
if (route._fsRouteType === "lazy" || route._fsRouteType === "loader" || route._fsRouteType === "component" || route._fsRouteType === "pendingComponent" || route._fsRouteType === "errorComponent" || route._fsRouteType === "notFoundComponent") continue;
|
|
18
|
+
this.prefixToRoute.set(route.routePath, route);
|
|
19
|
+
if (route._fsRouteType === "pathless_layout" || route._fsRouteType === "layout" || route._fsRouteType === "__root") this.layoutRoutes.push(route);
|
|
20
|
+
}
|
|
21
|
+
this.layoutRoutes.sort((a, b) => (b.routePath?.length ?? 0) - (a.routePath?.length ?? 0));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Find the longest matching parent route for a given path.
|
|
25
|
+
* O(k) where k is the number of path segments, not O(n) routes.
|
|
26
|
+
*/
|
|
27
|
+
findParent(routePath) {
|
|
28
|
+
if (!routePath || routePath === "/") return null;
|
|
29
|
+
let searchPath = routePath;
|
|
30
|
+
while (searchPath.length > 0) {
|
|
31
|
+
const lastSlash = searchPath.lastIndexOf("/");
|
|
32
|
+
if (lastSlash <= 0) break;
|
|
33
|
+
searchPath = searchPath.substring(0, lastSlash);
|
|
34
|
+
const parent = this.prefixToRoute.get(searchPath);
|
|
35
|
+
if (parent && parent.routePath !== routePath) return parent;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check if a route exists at the given path.
|
|
41
|
+
*/
|
|
42
|
+
has(routePath) {
|
|
43
|
+
return this.prefixToRoute.has(routePath);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get a route by exact path.
|
|
47
|
+
*/
|
|
48
|
+
get(routePath) {
|
|
49
|
+
return this.prefixToRoute.get(routePath);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
54
52
|
function multiSortBy(arr, accessors = [(d) => d]) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return path2 === "/" ? path2 : path2.replace(/^\/{1,}/, "");
|
|
93
|
-
}
|
|
94
|
-
function removeLeadingSlash(path2) {
|
|
95
|
-
return path2.replace(/^\//, "");
|
|
53
|
+
const len = arr.length;
|
|
54
|
+
const indexed = new Array(len);
|
|
55
|
+
for (let i = 0; i < len; i++) {
|
|
56
|
+
const item = arr[i];
|
|
57
|
+
const keys = new Array(accessors.length);
|
|
58
|
+
for (let j = 0; j < accessors.length; j++) keys[j] = accessors[j](item);
|
|
59
|
+
indexed[i] = {
|
|
60
|
+
item,
|
|
61
|
+
index: i,
|
|
62
|
+
keys
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
indexed.sort((a, b) => {
|
|
66
|
+
for (let j = 0; j < accessors.length; j++) {
|
|
67
|
+
const ao = a.keys[j];
|
|
68
|
+
const bo = b.keys[j];
|
|
69
|
+
if (typeof ao === "undefined") {
|
|
70
|
+
if (typeof bo === "undefined") continue;
|
|
71
|
+
return 1;
|
|
72
|
+
}
|
|
73
|
+
if (ao === bo) continue;
|
|
74
|
+
return ao > bo ? 1 : -1;
|
|
75
|
+
}
|
|
76
|
+
return a.index - b.index;
|
|
77
|
+
});
|
|
78
|
+
const result = new Array(len);
|
|
79
|
+
for (let i = 0; i < len; i++) result[i] = indexed[i].item;
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
function cleanPath(path) {
|
|
83
|
+
return path.replace(/\/{2,}/g, "/");
|
|
84
|
+
}
|
|
85
|
+
function trimPathLeft(path) {
|
|
86
|
+
return path === "/" ? path : path.replace(/^\/{1,}/, "");
|
|
87
|
+
}
|
|
88
|
+
function removeLeadingSlash(path) {
|
|
89
|
+
return path.replace(/^\//, "");
|
|
96
90
|
}
|
|
97
91
|
function removeTrailingSlash(s) {
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
92
|
+
return s.replace(/\/$/, "");
|
|
93
|
+
}
|
|
94
|
+
var BRACKET_CONTENT_RE = /\[(.*?)\]/g;
|
|
95
|
+
var SPLIT_REGEX = /(?<!\[)\.(?!\])/g;
|
|
96
|
+
/**
|
|
97
|
+
* Characters that cannot be escaped in square brackets.
|
|
98
|
+
* These are characters that would cause issues in URLs or file systems.
|
|
99
|
+
*/
|
|
100
|
+
var DISALLOWED_ESCAPE_CHARS = new Set([
|
|
101
|
+
"/",
|
|
102
|
+
"\\",
|
|
103
|
+
"?",
|
|
104
|
+
"#",
|
|
105
|
+
":",
|
|
106
|
+
"*",
|
|
107
|
+
"<",
|
|
108
|
+
">",
|
|
109
|
+
"|",
|
|
110
|
+
"!",
|
|
111
|
+
"$",
|
|
112
|
+
"%"
|
|
115
113
|
]);
|
|
116
114
|
function determineInitialRoutePath(routePath) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
});
|
|
139
|
-
const final = cleanPath(`/${escapedParts.join("/")}`) || "";
|
|
140
|
-
return {
|
|
141
|
-
routePath: final,
|
|
142
|
-
originalRoutePath
|
|
143
|
-
};
|
|
144
|
-
}
|
|
115
|
+
const originalRoutePath = cleanPath(`/${(cleanPath(routePath) || "").split(SPLIT_REGEX).join("/")}`) || "";
|
|
116
|
+
return {
|
|
117
|
+
routePath: cleanPath(`/${routePath.split(SPLIT_REGEX).map((part) => {
|
|
118
|
+
let match;
|
|
119
|
+
while ((match = BRACKET_CONTENT_RE.exec(part)) !== null) {
|
|
120
|
+
const character = match[1];
|
|
121
|
+
if (character === void 0) continue;
|
|
122
|
+
if (DISALLOWED_ESCAPE_CHARS.has(character)) {
|
|
123
|
+
console.error(`Error: Disallowed character "${character}" found in square brackets in route path "${routePath}".\nYou cannot use any of the following characters in square brackets: ${Array.from(DISALLOWED_ESCAPE_CHARS).join(", ")}\nPlease remove and/or replace them.`);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return part.replace(BRACKET_CONTENT_RE, "$1");
|
|
128
|
+
}).join("/")}`) || "",
|
|
129
|
+
originalRoutePath
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Checks if a segment is fully escaped (entirely wrapped in brackets with no nested brackets).
|
|
134
|
+
* E.g., "[index]" -> true, "[_layout]" -> true, "foo[.]bar" -> false, "index" -> false
|
|
135
|
+
*/
|
|
145
136
|
function isFullyEscapedSegment(originalSegment) {
|
|
146
|
-
|
|
147
|
-
}
|
|
137
|
+
return originalSegment.startsWith("[") && originalSegment.endsWith("]") && !originalSegment.slice(1, -1).includes("[") && !originalSegment.slice(1, -1).includes("]");
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Checks if the leading underscore in a segment is escaped.
|
|
141
|
+
* Returns true if:
|
|
142
|
+
* - Segment starts with [_] pattern: "[_]layout" -> "_layout"
|
|
143
|
+
* - Segment is fully escaped and content starts with _: "[_1nd3x]" -> "_1nd3x"
|
|
144
|
+
*/
|
|
148
145
|
function hasEscapedLeadingUnderscore(originalSegment) {
|
|
149
|
-
|
|
150
|
-
}
|
|
146
|
+
return originalSegment.startsWith("[_]") || originalSegment.startsWith("[_") && isFullyEscapedSegment(originalSegment);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Checks if the trailing underscore in a segment is escaped.
|
|
150
|
+
* Returns true if:
|
|
151
|
+
* - Segment ends with [_] pattern: "blog[_]" -> "blog_"
|
|
152
|
+
* - Segment is fully escaped and content ends with _: "[_r0ut3_]" -> "_r0ut3_"
|
|
153
|
+
*/
|
|
151
154
|
function hasEscapedTrailingUnderscore(originalSegment) {
|
|
152
|
-
|
|
155
|
+
return originalSegment.endsWith("[_]") || originalSegment.endsWith("_]") && isFullyEscapedSegment(originalSegment);
|
|
153
156
|
}
|
|
154
|
-
|
|
157
|
+
var backslashRegex = /\\/g;
|
|
155
158
|
function replaceBackslash(s) {
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
case "(":
|
|
177
|
-
return "";
|
|
178
|
-
// Removed since route groups use parentheses
|
|
179
|
-
case ")":
|
|
180
|
-
return "";
|
|
181
|
-
// Removed since route groups use parentheses
|
|
182
|
-
case " ":
|
|
183
|
-
return "";
|
|
184
|
-
// Remove spaces
|
|
185
|
-
default:
|
|
186
|
-
return `Char${char.charCodeAt(0)}`;
|
|
187
|
-
}
|
|
159
|
+
return s.replace(backslashRegex, "/");
|
|
160
|
+
}
|
|
161
|
+
var alphanumericRegex = /[a-zA-Z0-9_]/;
|
|
162
|
+
var splatSlashRegex = /\/\$\//g;
|
|
163
|
+
var trailingSplatRegex = /\$$/g;
|
|
164
|
+
var bracketSplatRegex = /\$\{\$\}/g;
|
|
165
|
+
var dollarSignRegex = /\$/g;
|
|
166
|
+
var splitPathRegex = /[/-]/g;
|
|
167
|
+
var leadingDigitRegex = /^(\d)/g;
|
|
168
|
+
var toVariableSafeChar = (char) => {
|
|
169
|
+
if (alphanumericRegex.test(char)) return char;
|
|
170
|
+
switch (char) {
|
|
171
|
+
case ".": return "Dot";
|
|
172
|
+
case "-": return "Dash";
|
|
173
|
+
case "@": return "At";
|
|
174
|
+
case "(": return "";
|
|
175
|
+
case ")": return "";
|
|
176
|
+
case " ": return "";
|
|
177
|
+
default: return `Char${char.charCodeAt(0)}`;
|
|
178
|
+
}
|
|
188
179
|
};
|
|
189
180
|
function routePathToVariable(routePath) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const underscoreStartEndRegex = /(^_|_$)/gi;
|
|
204
|
-
const underscoreSlashRegex = /(\/_|_\/)/gi;
|
|
181
|
+
const cleaned = removeUnderscores(routePath);
|
|
182
|
+
if (!cleaned) return "";
|
|
183
|
+
const parts = cleaned.replace(splatSlashRegex, "/splat/").replace(trailingSplatRegex, "splat").replace(bracketSplatRegex, "splat").replace(dollarSignRegex, "").split(splitPathRegex);
|
|
184
|
+
let result = "";
|
|
185
|
+
for (let i = 0; i < parts.length; i++) {
|
|
186
|
+
const part = parts[i];
|
|
187
|
+
const segment = i > 0 ? capitalize(part) : part;
|
|
188
|
+
for (let j = 0; j < segment.length; j++) result += toVariableSafeChar(segment[j]);
|
|
189
|
+
}
|
|
190
|
+
return result.replace(leadingDigitRegex, "R$1");
|
|
191
|
+
}
|
|
192
|
+
var underscoreStartEndRegex = /(^_|_$)/gi;
|
|
193
|
+
var underscoreSlashRegex = /(\/_|_\/)/gi;
|
|
205
194
|
function removeUnderscores(s) {
|
|
206
|
-
|
|
207
|
-
}
|
|
195
|
+
return s?.replace(underscoreStartEndRegex, "").replace(underscoreSlashRegex, "/");
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Removes underscores from a path, but preserves underscores that were escaped
|
|
199
|
+
* in the original path (indicated by [_] syntax).
|
|
200
|
+
*
|
|
201
|
+
* @param routePath - The path with brackets removed
|
|
202
|
+
* @param originalPath - The original path that may contain [_] escape sequences
|
|
203
|
+
* @returns The path with non-escaped underscores removed
|
|
204
|
+
*/
|
|
208
205
|
function removeUnderscoresWithEscape(routePath, originalPath) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
206
|
+
if (!routePath) return "";
|
|
207
|
+
if (!originalPath) return removeUnderscores(routePath) ?? "";
|
|
208
|
+
const routeSegments = routePath.split("/");
|
|
209
|
+
const originalSegments = originalPath.split("/");
|
|
210
|
+
return routeSegments.map((segment, i) => {
|
|
211
|
+
const originalSegment = originalSegments[i] || "";
|
|
212
|
+
const leadingEscaped = hasEscapedLeadingUnderscore(originalSegment);
|
|
213
|
+
const trailingEscaped = hasEscapedTrailingUnderscore(originalSegment);
|
|
214
|
+
let result = segment;
|
|
215
|
+
if (result.startsWith("_") && !leadingEscaped) result = result.slice(1);
|
|
216
|
+
if (result.endsWith("_") && !trailingEscaped) result = result.slice(0, -1);
|
|
217
|
+
return result;
|
|
218
|
+
}).join("/");
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Removes layout segments (segments starting with underscore) from a path,
|
|
222
|
+
* but preserves segments where the underscore was escaped.
|
|
223
|
+
*
|
|
224
|
+
* @param routePath - The path with brackets removed
|
|
225
|
+
* @param originalPath - The original path that may contain [_] escape sequences
|
|
226
|
+
* @returns The path with non-escaped layout segments removed
|
|
227
|
+
*/
|
|
228
228
|
function removeLayoutSegmentsWithEscape(routePath = "/", originalPath) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
229
|
+
if (!originalPath) return removeLayoutSegments(routePath);
|
|
230
|
+
const routeSegments = routePath.split("/");
|
|
231
|
+
const originalSegments = originalPath.split("/");
|
|
232
|
+
return routeSegments.filter((segment, i) => {
|
|
233
|
+
return !isSegmentPathless(segment, originalSegments[i] || "");
|
|
234
|
+
}).join("/");
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Checks if a segment should be treated as a pathless/layout segment.
|
|
238
|
+
* A segment is pathless if it starts with underscore and the underscore is not escaped.
|
|
239
|
+
*
|
|
240
|
+
* @param segment - The segment from routePath (brackets removed)
|
|
241
|
+
* @param originalSegment - The segment from originalRoutePath (may contain brackets)
|
|
242
|
+
* @returns true if the segment is pathless (has non-escaped leading underscore)
|
|
243
|
+
*/
|
|
238
244
|
function isSegmentPathless(segment, originalSegment) {
|
|
239
|
-
|
|
240
|
-
|
|
245
|
+
if (!segment.startsWith("_")) return false;
|
|
246
|
+
return !hasEscapedLeadingUnderscore(originalSegment);
|
|
241
247
|
}
|
|
242
248
|
function escapeRegExp(s) {
|
|
243
|
-
|
|
249
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
244
250
|
}
|
|
245
251
|
function sanitizeTokenFlags(flags) {
|
|
246
|
-
|
|
247
|
-
|
|
252
|
+
if (!flags) return flags;
|
|
253
|
+
return flags.replace(/[gy]/g, "");
|
|
248
254
|
}
|
|
249
255
|
function createTokenRegex(token, opts) {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
);
|
|
270
|
-
} catch (e) {
|
|
271
|
-
if (e instanceof SyntaxError) {
|
|
272
|
-
const pattern = typeof token === "string" ? token : token instanceof RegExp ? token.source : token.regex;
|
|
273
|
-
throw new Error(
|
|
274
|
-
`Invalid regex pattern in token config: "${pattern}". ${e.message}`
|
|
275
|
-
);
|
|
276
|
-
}
|
|
277
|
-
throw e;
|
|
278
|
-
}
|
|
256
|
+
if (token === void 0 || token === null) throw new Error(`createTokenRegex: token is ${token}. This usually means the config was not properly parsed with defaults.`);
|
|
257
|
+
try {
|
|
258
|
+
if (typeof token === "string") return opts.type === "segment" ? new RegExp(`^${escapeRegExp(token)}$`) : new RegExp(`[./]${escapeRegExp(token)}[.]`);
|
|
259
|
+
if (token instanceof RegExp) {
|
|
260
|
+
const flags = sanitizeTokenFlags(token.flags);
|
|
261
|
+
return opts.type === "segment" ? new RegExp(`^(?:${token.source})$`, flags) : new RegExp(`[./](?:${token.source})[.]`, flags);
|
|
262
|
+
}
|
|
263
|
+
if (typeof token === "object" && "regex" in token) {
|
|
264
|
+
const flags = sanitizeTokenFlags(token.flags);
|
|
265
|
+
return opts.type === "segment" ? new RegExp(`^(?:${token.regex})$`, flags) : new RegExp(`[./](?:${token.regex})[.]`, flags);
|
|
266
|
+
}
|
|
267
|
+
throw new Error(`createTokenRegex: invalid token type. Expected string, RegExp, or { regex, flags } object, got: ${typeof token}`);
|
|
268
|
+
} catch (e) {
|
|
269
|
+
if (e instanceof SyntaxError) {
|
|
270
|
+
const pattern = typeof token === "string" ? token : token instanceof RegExp ? token.source : token.regex;
|
|
271
|
+
throw new Error(`Invalid regex pattern in token config: "${pattern}". ${e.message}`);
|
|
272
|
+
}
|
|
273
|
+
throw e;
|
|
274
|
+
}
|
|
279
275
|
}
|
|
280
276
|
function isBracketWrappedSegment(segment) {
|
|
281
|
-
|
|
277
|
+
return segment.startsWith("[") && segment.endsWith("]");
|
|
282
278
|
}
|
|
283
279
|
function unwrapBracketWrappedSegment(segment) {
|
|
284
|
-
|
|
280
|
+
return isBracketWrappedSegment(segment) ? segment.slice(1, -1) : segment;
|
|
285
281
|
}
|
|
286
282
|
function capitalize(s) {
|
|
287
|
-
|
|
288
|
-
|
|
283
|
+
if (typeof s !== "string") return "";
|
|
284
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
289
285
|
}
|
|
290
286
|
function removeExt(d, addExtensions = false) {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
287
|
+
if (typeof addExtensions === "string") {
|
|
288
|
+
const dotIndex = d.lastIndexOf(".");
|
|
289
|
+
if (dotIndex === -1) return d;
|
|
290
|
+
return d.substring(0, dotIndex) + addExtensions;
|
|
291
|
+
}
|
|
292
|
+
return addExtensions ? d : d.substring(0, d.lastIndexOf(".")) || d;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* This function writes to a file if the content is different.
|
|
296
|
+
*
|
|
297
|
+
* @param filepath The path to the file
|
|
298
|
+
* @param content Original content
|
|
299
|
+
* @param incomingContent New content
|
|
300
|
+
* @param callbacks Callbacks to run before and after writing
|
|
301
|
+
* @returns Whether the file was written
|
|
302
|
+
*/
|
|
298
303
|
async function writeIfDifferent(filepath, content, incomingContent, callbacks) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}
|
|
304
|
+
if (content !== incomingContent) {
|
|
305
|
+
callbacks?.beforeWrite?.();
|
|
306
|
+
await fsp.writeFile(filepath, incomingContent);
|
|
307
|
+
callbacks?.afterWrite?.();
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* This function formats the source code using the default formatter (Prettier).
|
|
314
|
+
*
|
|
315
|
+
* @param source The content to format
|
|
316
|
+
* @param config The configuration object
|
|
317
|
+
* @returns The formatted content
|
|
318
|
+
*/
|
|
307
319
|
async function format(source, config) {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
320
|
+
const prettierOptions = {
|
|
321
|
+
semi: config.semicolons,
|
|
322
|
+
singleQuote: config.quoteStyle === "single",
|
|
323
|
+
parser: "typescript"
|
|
324
|
+
};
|
|
325
|
+
return prettier.format(source, prettierOptions);
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* This function resets the regex index to 0 so that it can be reused
|
|
329
|
+
* without having to create a new regex object or worry about the last
|
|
330
|
+
* state when using the global flag.
|
|
331
|
+
*
|
|
332
|
+
* @param regex The regex object to reset
|
|
333
|
+
* @returns
|
|
334
|
+
*/
|
|
315
335
|
function resetRegex(regex) {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
336
|
+
regex.lastIndex = 0;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* This function checks if a file exists.
|
|
340
|
+
*
|
|
341
|
+
* @param file The path to the file
|
|
342
|
+
* @returns Whether the file exists
|
|
343
|
+
*/
|
|
319
344
|
async function checkFileExists(file) {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
|
|
345
|
+
try {
|
|
346
|
+
await fsp.access(file, fsp.constants.F_OK);
|
|
347
|
+
return true;
|
|
348
|
+
} catch {
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
var possiblyNestedRouteGroupPatternRegex = /\([^/]+\)\/?/g;
|
|
328
353
|
function removeGroups(s) {
|
|
329
|
-
|
|
330
|
-
}
|
|
354
|
+
return s.replace(possiblyNestedRouteGroupPatternRegex, "");
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Removes all segments from a given path that start with an underscore ('_').
|
|
358
|
+
*
|
|
359
|
+
* @param {string} routePath - The path from which to remove segments. Defaults to '/'.
|
|
360
|
+
* @returns {string} The path with all underscore-prefixed segments removed.
|
|
361
|
+
* @example
|
|
362
|
+
* removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'
|
|
363
|
+
*/
|
|
331
364
|
function removeLayoutSegments(routePath = "/") {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
365
|
+
return routePath.split("/").filter((segment) => !segment.startsWith("_")).join("/");
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* The `node.path` is used as the `id` in the route definition.
|
|
369
|
+
* This function checks if the given node has a parent and if so, it determines the correct path for the given node.
|
|
370
|
+
* @param node - The node to determine the path for.
|
|
371
|
+
* @returns The correct path for the given node.
|
|
372
|
+
*/
|
|
336
373
|
function determineNodePath(node) {
|
|
337
|
-
|
|
338
|
-
}
|
|
374
|
+
return node.path = node.parent ? node.routePath?.replace(node.parent.routePath ?? "", "") || "/" : node.routePath;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Removes the last segment from a given path. Segments are considered to be separated by a '/'.
|
|
378
|
+
*
|
|
379
|
+
* @param {string} routePath - The path from which to remove the last segment. Defaults to '/'.
|
|
380
|
+
* @returns {string} The path with the last segment removed.
|
|
381
|
+
* @example
|
|
382
|
+
* removeLastSegmentFromPath('/workspace/_auth/foo') // '/workspace/_auth'
|
|
383
|
+
*/
|
|
339
384
|
function removeLastSegmentFromPath(routePath = "/") {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
385
|
+
const segments = routePath.split("/");
|
|
386
|
+
segments.pop();
|
|
387
|
+
return segments.join("/");
|
|
343
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Find parent route using RoutePrefixMap for O(k) lookups instead of O(n).
|
|
391
|
+
*/
|
|
344
392
|
function hasParentRoute(prefixMap, node, routePathToCheck) {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
393
|
+
if (!routePathToCheck || routePathToCheck === "/") return null;
|
|
394
|
+
return prefixMap.findParent(routePathToCheck);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Gets the final variable name for a route
|
|
398
|
+
*/
|
|
399
|
+
var getResolvedRouteNodeVariableName = (routeNode) => {
|
|
400
|
+
return routeNode.children?.length ? `${routeNode.variableName}RouteWithChildren` : `${routeNode.variableName}Route`;
|
|
352
401
|
};
|
|
402
|
+
/**
|
|
403
|
+
* Checks if a given RouteNode is valid for augmenting it with typing based on conditions.
|
|
404
|
+
* Also asserts that the RouteNode is defined.
|
|
405
|
+
*
|
|
406
|
+
* @param routeNode - The RouteNode to check.
|
|
407
|
+
* @returns A boolean indicating whether the RouteNode is defined.
|
|
408
|
+
*/
|
|
353
409
|
function isRouteNodeValidForAugmentation(routeNode) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
return routeNode.cleanedPath?.replace(/\/$/, "") ?? "";
|
|
410
|
+
if (!routeNode || routeNode.isVirtual) return false;
|
|
411
|
+
return true;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Infers the path for use by TS
|
|
415
|
+
*/
|
|
416
|
+
var inferPath = (routeNode) => {
|
|
417
|
+
if (routeNode.cleanedPath === "/") return routeNode.cleanedPath ?? "";
|
|
418
|
+
return routeNode.cleanedPath?.replace(/\/$/, "") ?? "";
|
|
364
419
|
};
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
)
|
|
374
|
-
);
|
|
375
|
-
if (fullPath === "") {
|
|
376
|
-
return "/";
|
|
377
|
-
}
|
|
378
|
-
const isIndexRoute = routeNode.routePath?.endsWith("/");
|
|
379
|
-
if (isIndexRoute) {
|
|
380
|
-
return fullPath;
|
|
381
|
-
}
|
|
382
|
-
return fullPath.replace(/\/$/, "");
|
|
420
|
+
/**
|
|
421
|
+
* Infers the full path for use by TS
|
|
422
|
+
*/
|
|
423
|
+
var inferFullPath = (routeNode) => {
|
|
424
|
+
const fullPath = removeGroups(removeUnderscoresWithEscape(removeLayoutSegmentsWithEscape(routeNode.routePath, routeNode.originalRoutePath), routeNode.originalRoutePath));
|
|
425
|
+
if (fullPath === "") return "/";
|
|
426
|
+
if (routeNode.routePath?.endsWith("/")) return fullPath;
|
|
427
|
+
return fullPath.replace(/\/$/, "");
|
|
383
428
|
};
|
|
384
|
-
|
|
385
|
-
|
|
429
|
+
var shouldPreferIndexRoute = (current, existing) => {
|
|
430
|
+
return existing.cleanedPath === "/" && current.cleanedPath !== "/";
|
|
386
431
|
};
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
432
|
+
/**
|
|
433
|
+
* Creates a map from fullPath to routeNode
|
|
434
|
+
*/
|
|
435
|
+
var createRouteNodesByFullPath = (routeNodes) => {
|
|
436
|
+
const map = /* @__PURE__ */ new Map();
|
|
437
|
+
for (const routeNode of routeNodes) {
|
|
438
|
+
const fullPath = inferFullPath(routeNode);
|
|
439
|
+
if (fullPath === "/" && map.has("/")) {
|
|
440
|
+
if (shouldPreferIndexRoute(routeNode, map.get("/"))) continue;
|
|
441
|
+
}
|
|
442
|
+
map.set(fullPath, routeNode);
|
|
443
|
+
}
|
|
444
|
+
return map;
|
|
400
445
|
};
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
446
|
+
/**
|
|
447
|
+
* Create a map from 'to' to a routeNode
|
|
448
|
+
*/
|
|
449
|
+
var createRouteNodesByTo = (routeNodes) => {
|
|
450
|
+
const map = /* @__PURE__ */ new Map();
|
|
451
|
+
for (const routeNode of dedupeBranchesAndIndexRoutes(routeNodes)) {
|
|
452
|
+
const to = inferTo(routeNode);
|
|
453
|
+
if (to === "/" && map.has("/")) {
|
|
454
|
+
if (shouldPreferIndexRoute(routeNode, map.get("/"))) continue;
|
|
455
|
+
}
|
|
456
|
+
map.set(to, routeNode);
|
|
457
|
+
}
|
|
458
|
+
return map;
|
|
414
459
|
};
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
460
|
+
/**
|
|
461
|
+
* Create a map from 'id' to a routeNode
|
|
462
|
+
*/
|
|
463
|
+
var createRouteNodesById = (routeNodes) => {
|
|
464
|
+
return new Map(routeNodes.map((routeNode) => {
|
|
465
|
+
return [routeNode.routePath ?? "", routeNode];
|
|
466
|
+
}));
|
|
422
467
|
};
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
468
|
+
/**
|
|
469
|
+
* Infers to path
|
|
470
|
+
*/
|
|
471
|
+
var inferTo = (routeNode) => {
|
|
472
|
+
const fullPath = inferFullPath(routeNode);
|
|
473
|
+
if (fullPath === "/") return fullPath;
|
|
474
|
+
return fullPath.replace(/\/$/, "");
|
|
427
475
|
};
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
476
|
+
/**
|
|
477
|
+
* Dedupes branches and index routes
|
|
478
|
+
*/
|
|
479
|
+
var dedupeBranchesAndIndexRoutes = (routes) => {
|
|
480
|
+
return routes.filter((route) => {
|
|
481
|
+
if (route.children?.find((child) => child.cleanedPath === "/")) return false;
|
|
482
|
+
return true;
|
|
483
|
+
});
|
|
433
484
|
};
|
|
434
485
|
function checkUnique(routes, key) {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
);
|
|
442
|
-
return conflictingFiles;
|
|
443
|
-
}
|
|
444
|
-
return void 0;
|
|
486
|
+
const keys = routes.map((d) => d[key]);
|
|
487
|
+
const uniqueKeys = new Set(keys);
|
|
488
|
+
if (keys.length !== uniqueKeys.size) {
|
|
489
|
+
const duplicateKeys = keys.filter((d, i) => keys.indexOf(d) !== i);
|
|
490
|
+
return routes.filter((d) => duplicateKeys.includes(d[key]));
|
|
491
|
+
}
|
|
445
492
|
}
|
|
446
493
|
function checkRouteFullPathUniqueness(_routes, config) {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
Conflicting files:
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
494
|
+
const emptyPathRoutes = _routes.filter((d) => d.routePath === "");
|
|
495
|
+
if (emptyPathRoutes.length) {
|
|
496
|
+
const errorMessage = `Invalid route path "" was found. Root routes must be defined via __root.tsx (createRootRoute), not createFileRoute('') or a route file that resolves to an empty path.
|
|
497
|
+
Conflicting files: \n ${emptyPathRoutes.map((d) => path.resolve(config.routesDirectory, d.filePath)).join("\n ")}\n`;
|
|
498
|
+
throw new Error(errorMessage);
|
|
499
|
+
}
|
|
500
|
+
const conflictingFiles = checkUnique(_routes.map((d) => {
|
|
501
|
+
const inferredFullPath = inferFullPath(d);
|
|
502
|
+
return {
|
|
503
|
+
...d,
|
|
504
|
+
inferredFullPath
|
|
505
|
+
};
|
|
506
|
+
}), "inferredFullPath");
|
|
507
|
+
if (conflictingFiles !== void 0) {
|
|
508
|
+
const errorMessage = `Conflicting configuration paths were found for the following route${conflictingFiles.length > 1 ? "s" : ""}: ${conflictingFiles.map((p) => `"${p.inferredFullPath}"`).join(", ")}.
|
|
462
509
|
Please ensure each Route has a unique full path.
|
|
463
|
-
Conflicting files:
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
throw new Error(errorMessage);
|
|
467
|
-
}
|
|
510
|
+
Conflicting files: \n ${conflictingFiles.map((d) => path.resolve(config.routesDirectory, d.filePath)).join("\n ")}\n`;
|
|
511
|
+
throw new Error(errorMessage);
|
|
512
|
+
}
|
|
468
513
|
}
|
|
469
514
|
function buildRouteTreeConfig(nodes, disableTypes, depth = 1) {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
if (node.children?.length) {
|
|
479
|
-
const childConfigs = buildRouteTreeConfig(
|
|
480
|
-
node.children,
|
|
481
|
-
disableTypes,
|
|
482
|
-
depth + 1
|
|
483
|
-
);
|
|
484
|
-
const childrenDeclaration = disableTypes ? "" : `interface ${route}RouteChildren {
|
|
485
|
-
${node.children.map(
|
|
486
|
-
(child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`
|
|
487
|
-
).join(",")}
|
|
515
|
+
return nodes.map((node) => {
|
|
516
|
+
if (node._fsRouteType === "__root") return;
|
|
517
|
+
if (node._fsRouteType === "pathless_layout" && !node.children?.length) return;
|
|
518
|
+
const route = `${node.variableName}`;
|
|
519
|
+
if (node.children?.length) {
|
|
520
|
+
const childConfigs = buildRouteTreeConfig(node.children, disableTypes, depth + 1);
|
|
521
|
+
const childrenDeclaration = disableTypes ? "" : `interface ${route}RouteChildren {
|
|
522
|
+
${node.children.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
488
523
|
}`;
|
|
489
|
-
|
|
490
|
-
${node.children.map(
|
|
491
|
-
(child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`
|
|
492
|
-
).join(",")}
|
|
524
|
+
const children = `const ${route}RouteChildren${disableTypes ? "" : `: ${route}RouteChildren`} = {
|
|
525
|
+
${node.children.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
493
526
|
}`;
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
});
|
|
504
|
-
return children.filter((x) => x !== void 0);
|
|
527
|
+
const routeWithChildren = `const ${route}RouteWithChildren = ${route}Route._addFileChildren(${route}RouteChildren)`;
|
|
528
|
+
return [
|
|
529
|
+
childConfigs.join("\n"),
|
|
530
|
+
childrenDeclaration,
|
|
531
|
+
children,
|
|
532
|
+
routeWithChildren
|
|
533
|
+
].join("\n\n");
|
|
534
|
+
}
|
|
535
|
+
}).filter((x) => x !== void 0);
|
|
505
536
|
}
|
|
506
537
|
function buildImportString(importDeclaration) {
|
|
507
|
-
|
|
508
|
-
|
|
538
|
+
const { source, specifiers, importKind } = importDeclaration;
|
|
539
|
+
return specifiers.length ? `import ${importKind === "type" ? "type " : ""}{ ${specifiers.map((s) => s.local ? `${s.imported} as ${s.local}` : s.imported).join(", ")} } from '${source}'` : "";
|
|
509
540
|
}
|
|
510
541
|
function mergeImportDeclarations(imports) {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
return `${node.parent.variableName}Route`;
|
|
542
|
-
}
|
|
543
|
-
return findParent(node.parent);
|
|
542
|
+
const merged = /* @__PURE__ */ new Map();
|
|
543
|
+
for (const imp of imports) {
|
|
544
|
+
const key = `${imp.source}-${imp.importKind ?? ""}`;
|
|
545
|
+
let existing = merged.get(key);
|
|
546
|
+
if (!existing) {
|
|
547
|
+
existing = {
|
|
548
|
+
...imp,
|
|
549
|
+
specifiers: []
|
|
550
|
+
};
|
|
551
|
+
merged.set(key, existing);
|
|
552
|
+
}
|
|
553
|
+
const existingSpecs = existing.specifiers;
|
|
554
|
+
for (const specifier of imp.specifiers) {
|
|
555
|
+
let found = false;
|
|
556
|
+
for (let i = 0; i < existingSpecs.length; i++) {
|
|
557
|
+
const e = existingSpecs[i];
|
|
558
|
+
if (e.imported === specifier.imported && e.local === specifier.local) {
|
|
559
|
+
found = true;
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if (!found) existingSpecs.push(specifier);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return [...merged.values()];
|
|
567
|
+
}
|
|
568
|
+
var findParent = (node) => {
|
|
569
|
+
if (!node) return `rootRouteImport`;
|
|
570
|
+
if (node.parent) return `${node.parent.variableName}Route`;
|
|
571
|
+
return findParent(node.parent);
|
|
544
572
|
};
|
|
545
573
|
function buildFileRoutesByPathInterface(opts) {
|
|
546
|
-
|
|
574
|
+
return `declare module '${opts.module}' {
|
|
547
575
|
interface ${opts.interfaceName} {
|
|
548
576
|
${opts.routeNodes.map((routeNode) => {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
577
|
+
const filePathId = routeNode.routePath;
|
|
578
|
+
const preloaderRoute = `typeof ${routeNode.variableName}RouteImport`;
|
|
579
|
+
const parent = findParent(routeNode);
|
|
580
|
+
return `'${filePathId}': {
|
|
553
581
|
id: '${filePathId}'
|
|
554
582
|
path: '${inferPath(routeNode)}'
|
|
555
583
|
fullPath: '${inferFullPath(routeNode)}'
|
|
556
584
|
preLoaderRoute: ${preloaderRoute}
|
|
557
585
|
parentRoute: typeof ${parent}
|
|
558
586
|
}`;
|
|
559
|
-
|
|
587
|
+
}).join("\n")}
|
|
560
588
|
}
|
|
561
589
|
}`;
|
|
562
590
|
}
|
|
563
591
|
function getImportPath(node, config, generatedRouteTreePath) {
|
|
564
|
-
|
|
565
|
-
removeExt(
|
|
566
|
-
path.relative(
|
|
567
|
-
path.dirname(generatedRouteTreePath),
|
|
568
|
-
path.resolve(config.routesDirectory, node.filePath)
|
|
569
|
-
),
|
|
570
|
-
config.addExtensions
|
|
571
|
-
)
|
|
572
|
-
);
|
|
592
|
+
return replaceBackslash(removeExt(path.relative(path.dirname(generatedRouteTreePath), path.resolve(config.routesDirectory, node.filePath)), config.addExtensions));
|
|
573
593
|
}
|
|
574
594
|
function getImportForRouteNode(node, config, generatedRouteTreePath, root) {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
imported: "Route",
|
|
591
|
-
local: `${node.variableName}RouteImport`
|
|
592
|
-
}
|
|
593
|
-
]
|
|
594
|
-
};
|
|
595
|
-
}
|
|
596
|
-
export {
|
|
597
|
-
RoutePrefixMap,
|
|
598
|
-
buildFileRoutesByPathInterface,
|
|
599
|
-
buildImportString,
|
|
600
|
-
buildRouteTreeConfig,
|
|
601
|
-
capitalize,
|
|
602
|
-
checkFileExists,
|
|
603
|
-
checkRouteFullPathUniqueness,
|
|
604
|
-
cleanPath,
|
|
605
|
-
createRouteNodesByFullPath,
|
|
606
|
-
createRouteNodesById,
|
|
607
|
-
createRouteNodesByTo,
|
|
608
|
-
createTokenRegex,
|
|
609
|
-
dedupeBranchesAndIndexRoutes,
|
|
610
|
-
determineInitialRoutePath,
|
|
611
|
-
determineNodePath,
|
|
612
|
-
findParent,
|
|
613
|
-
format,
|
|
614
|
-
getImportForRouteNode,
|
|
615
|
-
getImportPath,
|
|
616
|
-
getResolvedRouteNodeVariableName,
|
|
617
|
-
hasEscapedLeadingUnderscore,
|
|
618
|
-
hasEscapedTrailingUnderscore,
|
|
619
|
-
hasParentRoute,
|
|
620
|
-
inferFullPath,
|
|
621
|
-
inferPath,
|
|
622
|
-
inferTo,
|
|
623
|
-
isBracketWrappedSegment,
|
|
624
|
-
isRouteNodeValidForAugmentation,
|
|
625
|
-
isSegmentPathless,
|
|
626
|
-
mergeImportDeclarations,
|
|
627
|
-
multiSortBy,
|
|
628
|
-
removeExt,
|
|
629
|
-
removeGroups,
|
|
630
|
-
removeLastSegmentFromPath,
|
|
631
|
-
removeLayoutSegments,
|
|
632
|
-
removeLayoutSegmentsWithEscape,
|
|
633
|
-
removeLeadingSlash,
|
|
634
|
-
removeTrailingSlash,
|
|
635
|
-
removeUnderscores,
|
|
636
|
-
removeUnderscoresWithEscape,
|
|
637
|
-
replaceBackslash,
|
|
638
|
-
resetRegex,
|
|
639
|
-
routePathToVariable,
|
|
640
|
-
trimPathLeft,
|
|
641
|
-
unwrapBracketWrappedSegment,
|
|
642
|
-
writeIfDifferent
|
|
643
|
-
};
|
|
644
|
-
//# sourceMappingURL=utils.js.map
|
|
595
|
+
let source = "";
|
|
596
|
+
if (config.importRoutesUsingAbsolutePaths) source = replaceBackslash(removeExt(path.resolve(root, config.routesDirectory, node.filePath), config.addExtensions));
|
|
597
|
+
else source = `./${getImportPath(node, config, generatedRouteTreePath)}`;
|
|
598
|
+
return {
|
|
599
|
+
source,
|
|
600
|
+
specifiers: [{
|
|
601
|
+
imported: "Route",
|
|
602
|
+
local: `${node.variableName}RouteImport`
|
|
603
|
+
}]
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
//#endregion
|
|
607
|
+
export { RoutePrefixMap, buildFileRoutesByPathInterface, buildImportString, buildRouteTreeConfig, capitalize, checkFileExists, checkRouteFullPathUniqueness, cleanPath, createRouteNodesByFullPath, createRouteNodesById, createRouteNodesByTo, createTokenRegex, determineInitialRoutePath, determineNodePath, findParent, format, getImportForRouteNode, getImportPath, getResolvedRouteNodeVariableName, hasEscapedLeadingUnderscore, hasParentRoute, inferFullPath, isRouteNodeValidForAugmentation, isSegmentPathless, mergeImportDeclarations, multiSortBy, removeExt, removeGroups, removeLastSegmentFromPath, removeLayoutSegmentsWithEscape, removeLeadingSlash, removeTrailingSlash, removeUnderscores, removeUnderscoresWithEscape, replaceBackslash, resetRegex, routePathToVariable, trimPathLeft, unwrapBracketWrappedSegment, writeIfDifferent };
|
|
608
|
+
|
|
609
|
+
//# sourceMappingURL=utils.js.map
|