@tanstack/router-generator 1.20.0 → 1.20.3-alpha.1
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/config.cjs +93 -13
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/config.d.cts +126 -9
- package/dist/cjs/filesystem/physical/getRouteNodes.cjs +191 -0
- package/dist/cjs/filesystem/physical/getRouteNodes.cjs.map +1 -0
- package/dist/cjs/filesystem/physical/getRouteNodes.d.cts +14 -0
- package/dist/cjs/filesystem/physical/rootPathId.cjs +5 -0
- package/dist/cjs/filesystem/physical/rootPathId.cjs.map +1 -0
- package/dist/cjs/filesystem/physical/rootPathId.d.cts +1 -0
- package/dist/cjs/filesystem/virtual/config.cjs +37 -0
- package/dist/cjs/filesystem/virtual/config.cjs.map +1 -0
- package/dist/cjs/filesystem/virtual/config.d.cts +3 -0
- package/dist/cjs/filesystem/virtual/getRouteNodes.cjs +186 -0
- package/dist/cjs/filesystem/virtual/getRouteNodes.cjs.map +1 -0
- package/dist/cjs/filesystem/virtual/getRouteNodes.d.cts +5 -0
- package/dist/cjs/filesystem/virtual/loadConfigFile.cjs +11 -0
- package/dist/cjs/filesystem/virtual/loadConfigFile.cjs.map +1 -0
- package/dist/cjs/filesystem/virtual/loadConfigFile.d.cts +1 -0
- package/dist/cjs/generator.cjs +516 -328
- package/dist/cjs/generator.cjs.map +1 -1
- package/dist/cjs/generator.d.cts +1 -37
- package/dist/cjs/index.cjs +24 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +7 -1
- package/dist/cjs/template.cjs +110 -0
- package/dist/cjs/template.cjs.map +1 -0
- package/dist/cjs/template.d.cts +33 -0
- package/dist/cjs/types.d.cts +20 -0
- package/dist/cjs/utils.cjs +177 -10
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +47 -5
- package/dist/esm/config.d.ts +126 -9
- package/dist/esm/config.js +88 -8
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/filesystem/physical/getRouteNodes.d.ts +14 -0
- package/dist/esm/filesystem/physical/getRouteNodes.js +174 -0
- package/dist/esm/filesystem/physical/getRouteNodes.js.map +1 -0
- package/dist/esm/filesystem/physical/rootPathId.d.ts +1 -0
- package/dist/esm/filesystem/physical/rootPathId.js +5 -0
- package/dist/esm/filesystem/physical/rootPathId.js.map +1 -0
- package/dist/esm/filesystem/virtual/config.d.ts +3 -0
- package/dist/esm/filesystem/virtual/config.js +37 -0
- package/dist/esm/filesystem/virtual/config.js.map +1 -0
- package/dist/esm/filesystem/virtual/getRouteNodes.d.ts +5 -0
- package/dist/esm/filesystem/virtual/getRouteNodes.js +186 -0
- package/dist/esm/filesystem/virtual/getRouteNodes.js.map +1 -0
- package/dist/esm/filesystem/virtual/loadConfigFile.d.ts +1 -0
- package/dist/esm/filesystem/virtual/loadConfigFile.js +11 -0
- package/dist/esm/filesystem/virtual/loadConfigFile.js.map +1 -0
- package/dist/esm/generator.d.ts +1 -37
- package/dist/esm/generator.js +509 -320
- package/dist/esm/generator.js.map +1 -1
- package/dist/esm/index.d.ts +7 -1
- package/dist/esm/index.js +26 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/template.d.ts +33 -0
- package/dist/esm/template.js +110 -0
- package/dist/esm/template.js.map +1 -0
- package/dist/esm/types.d.ts +20 -0
- package/dist/esm/utils.d.ts +47 -5
- package/dist/esm/utils.js +160 -11
- package/dist/esm/utils.js.map +1 -1
- package/package.json +27 -22
- package/src/config.ts +112 -8
- package/src/filesystem/physical/getRouteNodes.ts +295 -0
- package/src/filesystem/physical/rootPathId.ts +1 -0
- package/src/filesystem/virtual/config.ts +45 -0
- package/src/filesystem/virtual/getRouteNodes.ts +260 -0
- package/src/filesystem/virtual/loadConfigFile.ts +8 -0
- package/src/generator.ts +712 -395
- package/src/index.ts +33 -1
- package/src/template.ts +156 -0
- package/src/types.ts +31 -0
- package/src/utils.ts +237 -10
package/dist/cjs/generator.cjs
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const path = require("path");
|
|
4
|
-
const fs = require("fs");
|
|
5
|
-
const fsp = require("fs/promises");
|
|
6
|
-
const prettier = require("prettier");
|
|
3
|
+
const path = require("node:path");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const fsp = require("node:fs/promises");
|
|
7
6
|
const utils = require("./utils.cjs");
|
|
7
|
+
const getRouteNodes$1 = require("./filesystem/physical/getRouteNodes.cjs");
|
|
8
|
+
const getRouteNodes = require("./filesystem/virtual/getRouteNodes.cjs");
|
|
9
|
+
const rootPathId = require("./filesystem/physical/rootPathId.cjs");
|
|
10
|
+
const template = require("./template.cjs");
|
|
8
11
|
function _interopNamespaceDefault(e) {
|
|
9
12
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
10
13
|
if (e) {
|
|
@@ -23,105 +26,19 @@ function _interopNamespaceDefault(e) {
|
|
|
23
26
|
}
|
|
24
27
|
const fs__namespace = /* @__PURE__ */ _interopNamespaceDefault(fs);
|
|
25
28
|
const fsp__namespace = /* @__PURE__ */ _interopNamespaceDefault(fsp);
|
|
26
|
-
const
|
|
29
|
+
const rootRouteId = "__root__";
|
|
27
30
|
let latestTask = 0;
|
|
28
|
-
const rootPathId = "__root";
|
|
29
31
|
const routeGroupPatternRegex = /\(.+\)/g;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const logger = utils.logging({ disabled: config.disableLogging });
|
|
33
|
-
const routeFileIgnoreRegExp = new RegExp(routeFileIgnorePattern ?? "", "g");
|
|
34
|
-
let routeNodes = [];
|
|
35
|
-
async function recurse(dir) {
|
|
36
|
-
const fullDir = path.resolve(config.routesDirectory, dir);
|
|
37
|
-
let dirList = await fsp__namespace.readdir(fullDir, { withFileTypes: true });
|
|
38
|
-
dirList = dirList.filter((d) => {
|
|
39
|
-
if (d.name.startsWith(".") || routeFileIgnorePrefix && d.name.startsWith(routeFileIgnorePrefix)) {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
if (routeFilePrefix) {
|
|
43
|
-
return d.name.startsWith(routeFilePrefix);
|
|
44
|
-
}
|
|
45
|
-
if (routeFileIgnorePattern) {
|
|
46
|
-
return !d.name.match(routeFileIgnoreRegExp);
|
|
47
|
-
}
|
|
48
|
-
return true;
|
|
49
|
-
});
|
|
50
|
-
await Promise.all(
|
|
51
|
-
dirList.map(async (dirent) => {
|
|
52
|
-
var _a;
|
|
53
|
-
const fullPath = path.join(fullDir, dirent.name);
|
|
54
|
-
const relativePath = path.join(dir, dirent.name);
|
|
55
|
-
if (dirent.isDirectory()) {
|
|
56
|
-
await recurse(relativePath);
|
|
57
|
-
} else if (fullPath.match(/\.(tsx|ts|jsx|js)$/)) {
|
|
58
|
-
const filePath = replaceBackslash(path.join(dir, dirent.name));
|
|
59
|
-
const filePathNoExt = removeExt(filePath);
|
|
60
|
-
let routePath = utils.cleanPath(`/${filePathNoExt.split(".").join("/")}`) || "";
|
|
61
|
-
if (routeFilePrefix) {
|
|
62
|
-
routePath = routePath.replaceAll(routeFilePrefix, "");
|
|
63
|
-
}
|
|
64
|
-
const variableName = routePathToVariable(routePath);
|
|
65
|
-
let isLazy = routePath == null ? void 0 : routePath.endsWith("/lazy");
|
|
66
|
-
if (isLazy) {
|
|
67
|
-
routePath = routePath == null ? void 0 : routePath.replace(/\/lazy$/, "");
|
|
68
|
-
}
|
|
69
|
-
let isRoute = routePath == null ? void 0 : routePath.endsWith("/route");
|
|
70
|
-
let isComponent = routePath == null ? void 0 : routePath.endsWith("/component");
|
|
71
|
-
let isErrorComponent = routePath == null ? void 0 : routePath.endsWith("/errorComponent");
|
|
72
|
-
let isPendingComponent = routePath == null ? void 0 : routePath.endsWith("/pendingComponent");
|
|
73
|
-
let isLoader = routePath == null ? void 0 : routePath.endsWith("/loader");
|
|
74
|
-
const segments = (routePath ?? "").split("/");
|
|
75
|
-
let isLayout = ((_a = segments[segments.length - 1]) == null ? void 0 : _a.startsWith("_")) || false;
|
|
76
|
-
[
|
|
77
|
-
[isComponent, "component"],
|
|
78
|
-
[isErrorComponent, "errorComponent"],
|
|
79
|
-
[isPendingComponent, "pendingComponent"],
|
|
80
|
-
[isLoader, "loader"]
|
|
81
|
-
].forEach(([isType, type]) => {
|
|
82
|
-
if (isType) {
|
|
83
|
-
logger.warn(
|
|
84
|
-
`WARNING: The \`.${type}.tsx\` suffix used for the ${filePath} file is deprecated. Use the new \`.lazy.tsx\` suffix instead.`
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
routePath = routePath == null ? void 0 : routePath.replace(
|
|
89
|
-
/\/(component|errorComponent|pendingComponent|loader|route|lazy)$/,
|
|
90
|
-
""
|
|
91
|
-
);
|
|
92
|
-
if (routePath === "index") {
|
|
93
|
-
routePath = "/";
|
|
94
|
-
}
|
|
95
|
-
routePath = routePath.replace(/\/index$/, "/") || "/";
|
|
96
|
-
routeNodes.push({
|
|
97
|
-
filePath,
|
|
98
|
-
fullPath,
|
|
99
|
-
routePath,
|
|
100
|
-
variableName,
|
|
101
|
-
isRoute,
|
|
102
|
-
isComponent,
|
|
103
|
-
isErrorComponent,
|
|
104
|
-
isPendingComponent,
|
|
105
|
-
isLoader,
|
|
106
|
-
isLazy,
|
|
107
|
-
isLayout
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
})
|
|
111
|
-
);
|
|
112
|
-
return routeNodes;
|
|
113
|
-
}
|
|
114
|
-
await recurse("./");
|
|
115
|
-
return routeNodes;
|
|
116
|
-
}
|
|
117
|
-
let first = false;
|
|
32
|
+
const possiblyNestedRouteGroupPatternRegex = /\([^/]+\)\/?/g;
|
|
33
|
+
let isFirst = false;
|
|
118
34
|
let skipMessage = false;
|
|
119
|
-
async function generator(config) {
|
|
35
|
+
async function generator(config, root) {
|
|
36
|
+
const ROUTE_TEMPLATE = template.getTargetTemplate(config.target);
|
|
120
37
|
const logger = utils.logging({ disabled: config.disableLogging });
|
|
121
38
|
logger.log("");
|
|
122
|
-
if (!
|
|
39
|
+
if (!isFirst) {
|
|
123
40
|
logger.log("♻️ Generating routes...");
|
|
124
|
-
|
|
41
|
+
isFirst = true;
|
|
125
42
|
} else if (skipMessage) {
|
|
126
43
|
skipMessage = false;
|
|
127
44
|
} else {
|
|
@@ -137,42 +54,73 @@ async function generator(config) {
|
|
|
137
54
|
return true;
|
|
138
55
|
};
|
|
139
56
|
const start = Date.now();
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
57
|
+
const TYPES_DISABLED = config.disableTypes;
|
|
58
|
+
let getRouteNodesResult;
|
|
59
|
+
if (config.virtualRouteConfig) {
|
|
60
|
+
getRouteNodesResult = await getRouteNodes.getRouteNodes(config, root);
|
|
61
|
+
} else {
|
|
62
|
+
getRouteNodesResult = await getRouteNodes$1.getRouteNodes(config, root);
|
|
63
|
+
}
|
|
64
|
+
const { rootRouteNode, routeNodes: beforeRouteNodes } = getRouteNodesResult;
|
|
65
|
+
if (rootRouteNode === void 0) {
|
|
66
|
+
let errorMessage = `rootRouteNode must not be undefined. Make sure you've added your root route into the route-tree.`;
|
|
67
|
+
if (!config.virtualRouteConfig) {
|
|
68
|
+
errorMessage += `
|
|
69
|
+
Make sure that you add a "${rootPathId.rootPathId}.${config.disableTypes ? "js" : "tsx"}" file to your routes directory.
|
|
70
|
+
Add the file in: "${config.routesDirectory}/${rootPathId.rootPathId}.${config.disableTypes ? "js" : "tsx"}"`;
|
|
71
|
+
}
|
|
72
|
+
throw new Error(errorMessage);
|
|
73
|
+
}
|
|
74
|
+
const preRouteNodes = utils.multiSortBy(beforeRouteNodes, [
|
|
146
75
|
(d) => d.routePath === "/" ? -1 : 1,
|
|
147
76
|
(d) => {
|
|
148
77
|
var _a;
|
|
149
78
|
return (_a = d.routePath) == null ? void 0 : _a.split("/").length;
|
|
150
79
|
},
|
|
151
|
-
(d) => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
(d) => {
|
|
156
|
-
var _a;
|
|
157
|
-
return ((_a = d.filePath) == null ? void 0 : _a.match(
|
|
158
|
-
/[./](component|errorComponent|pendingComponent|loader|lazy)[.]/
|
|
159
|
-
)) ? 1 : -1;
|
|
160
|
-
},
|
|
161
|
-
(d) => {
|
|
162
|
-
var _a;
|
|
163
|
-
return ((_a = d.filePath) == null ? void 0 : _a.match(/[./]route[.]/)) ? -1 : 1;
|
|
164
|
-
},
|
|
80
|
+
(d) => d.filePath.match(new RegExp(`[./]${config.indexToken}[.]`)) ? 1 : -1,
|
|
81
|
+
(d) => d.filePath.match(
|
|
82
|
+
/[./](component|errorComponent|pendingComponent|loader|lazy)[.]/
|
|
83
|
+
) ? 1 : -1,
|
|
84
|
+
(d) => d.filePath.match(new RegExp(`[./]${config.routeToken}[.]`)) ? -1 : 1,
|
|
165
85
|
(d) => {
|
|
166
86
|
var _a;
|
|
167
87
|
return ((_a = d.routePath) == null ? void 0 : _a.endsWith("/")) ? -1 : 1;
|
|
168
88
|
},
|
|
169
89
|
(d) => d.routePath
|
|
170
|
-
]).filter((d) => ![`/${rootPathId}`].includes(d.routePath || ""));
|
|
90
|
+
]).filter((d) => ![`/${rootPathId.rootPathId}`].includes(d.routePath || ""));
|
|
171
91
|
const routeTree = [];
|
|
172
92
|
const routePiecesByPath = {};
|
|
173
|
-
|
|
93
|
+
const routeNodes = [];
|
|
94
|
+
const handleRootNode = async (node) => {
|
|
95
|
+
if (!node) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const routeCode = fs__namespace.readFileSync(node.fullPath, "utf-8");
|
|
99
|
+
if (!routeCode) {
|
|
100
|
+
const _rootTemplate = ROUTE_TEMPLATE.rootRoute;
|
|
101
|
+
const replaced = await template.fillTemplate(config, _rootTemplate.template(), {
|
|
102
|
+
tsrImports: _rootTemplate.imports.tsrImports(),
|
|
103
|
+
tsrPath: rootPathId.rootPathId,
|
|
104
|
+
tsrExportStart: _rootTemplate.imports.tsrExportStart(),
|
|
105
|
+
tsrExportEnd: _rootTemplate.imports.tsrExportEnd()
|
|
106
|
+
});
|
|
107
|
+
await utils.writeIfDifferent(
|
|
108
|
+
node.fullPath,
|
|
109
|
+
"",
|
|
110
|
+
// Empty string because the file doesn't exist yet
|
|
111
|
+
replaced,
|
|
112
|
+
{
|
|
113
|
+
beforeWrite: () => {
|
|
114
|
+
logger.log(`🟡 Creating ${node.fullPath}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
await handleRootNode(rootRouteNode);
|
|
174
121
|
const handleNode = async (node) => {
|
|
175
|
-
var _a, _b;
|
|
122
|
+
var _a, _b, _c, _d, _e;
|
|
123
|
+
utils.resetRegex(routeGroupPatternRegex);
|
|
176
124
|
let parentRoute = hasParentRoute(routeNodes, node, node.routePath);
|
|
177
125
|
if ((parentRoute == null ? void 0 : parentRoute.isVirtualParentRoute) && ((_a = parentRoute.children) == null ? void 0 : _a.length)) {
|
|
178
126
|
const possibleParentRoute = hasParentRoute(
|
|
@@ -184,79 +132,158 @@ async function generator(config) {
|
|
|
184
132
|
parentRoute = possibleParentRoute;
|
|
185
133
|
}
|
|
186
134
|
}
|
|
187
|
-
if (parentRoute)
|
|
188
|
-
node.parent = parentRoute;
|
|
135
|
+
if (parentRoute) node.parent = parentRoute;
|
|
189
136
|
node.path = determineNodePath(node);
|
|
190
137
|
const trimmedPath = utils.trimPathLeft(node.path ?? "");
|
|
191
|
-
const split =
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
node.isNonPath = lastRouteSegment.startsWith("_");
|
|
195
|
-
node.isNonLayout = first2.endsWith("_");
|
|
138
|
+
const split = trimmedPath.split("/");
|
|
139
|
+
const lastRouteSegment = split[split.length - 1] ?? trimmedPath;
|
|
140
|
+
node.isNonPath = lastRouteSegment.startsWith("_") || routeGroupPatternRegex.test(lastRouteSegment);
|
|
196
141
|
node.cleanedPath = removeGroups(
|
|
197
|
-
removeUnderscores(removeLayoutSegments(node.path)) ?? ""
|
|
142
|
+
utils.removeUnderscores(removeLayoutSegments(node.path)) ?? ""
|
|
198
143
|
);
|
|
199
|
-
if (!node.isVirtualParentRoute) {
|
|
144
|
+
if (!node.isVirtualParentRoute && !node.isVirtual) {
|
|
200
145
|
const routeCode = fs__namespace.readFileSync(node.fullPath, "utf-8");
|
|
201
|
-
const escapedRoutePath =
|
|
202
|
-
((_b = node.routePath) == null ? void 0 : _b.replaceAll("$", "$$")) ?? ""
|
|
203
|
-
);
|
|
146
|
+
const escapedRoutePath = ((_b = node.routePath) == null ? void 0 : _b.replaceAll("$", "$$")) ?? "";
|
|
204
147
|
let replaced = routeCode;
|
|
148
|
+
const tRouteTemplate = ROUTE_TEMPLATE.route;
|
|
149
|
+
const tLazyRouteTemplate = ROUTE_TEMPLATE.lazyRoute;
|
|
205
150
|
if (!routeCode) {
|
|
206
|
-
if (node.
|
|
207
|
-
replaced =
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
].
|
|
151
|
+
if (node._fsRouteType === "lazy") {
|
|
152
|
+
replaced = await template.fillTemplate(
|
|
153
|
+
config,
|
|
154
|
+
(((_c = config.customScaffolding) == null ? void 0 : _c.lazyRouteTemplate) || ((_d = config.customScaffolding) == null ? void 0 : _d.routeTemplate)) ?? tLazyRouteTemplate.template(),
|
|
155
|
+
{
|
|
156
|
+
tsrImports: tLazyRouteTemplate.imports.tsrImports(),
|
|
157
|
+
tsrPath: escapedRoutePath.replaceAll(/\{(.+)\}/gm, "$1"),
|
|
158
|
+
tsrExportStart: tLazyRouteTemplate.imports.tsrExportStart(escapedRoutePath),
|
|
159
|
+
tsrExportEnd: tLazyRouteTemplate.imports.tsrExportEnd()
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
} else if (
|
|
163
|
+
// Creating a new normal route file
|
|
164
|
+
["layout", "static"].some(
|
|
165
|
+
(d) => d === node._fsRouteType
|
|
166
|
+
) || [
|
|
167
|
+
"component",
|
|
168
|
+
"pendingComponent",
|
|
169
|
+
"errorComponent",
|
|
170
|
+
"loader"
|
|
171
|
+
].every((d) => d !== node._fsRouteType)
|
|
172
|
+
) {
|
|
173
|
+
replaced = await template.fillTemplate(
|
|
174
|
+
config,
|
|
175
|
+
((_e = config.customScaffolding) == null ? void 0 : _e.routeTemplate) ?? tRouteTemplate.template(),
|
|
176
|
+
{
|
|
177
|
+
tsrImports: tRouteTemplate.imports.tsrImports(),
|
|
178
|
+
tsrPath: escapedRoutePath.replaceAll(/\{(.+)\}/gm, "$1"),
|
|
179
|
+
tsrExportStart: tRouteTemplate.imports.tsrExportStart(escapedRoutePath),
|
|
180
|
+
tsrExportEnd: tRouteTemplate.imports.tsrExportEnd()
|
|
181
|
+
}
|
|
182
|
+
);
|
|
220
183
|
}
|
|
184
|
+
} else if (config.verboseFileRoutes === false) {
|
|
185
|
+
if (!routeCode.split("\n").some((line) => line.trim().startsWith("export const Route"))) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
replaced = routeCode.replace(
|
|
189
|
+
/(FileRoute\(\s*['"])([^\s]*)(['"],?\s*\))/g,
|
|
190
|
+
(_, p1, __, p3) => `${p1}${escapedRoutePath}${p3}`
|
|
191
|
+
).replace(
|
|
192
|
+
new RegExp(
|
|
193
|
+
`(import\\s*\\{)(.*)(create(Lazy)?FileRoute)(.*)(\\}\\s*from\\s*['"]@tanstack\\/${ROUTE_TEMPLATE.subPkg}['"])`,
|
|
194
|
+
"gs"
|
|
195
|
+
),
|
|
196
|
+
(_, p1, p2, ___, ____, p5, p6) => {
|
|
197
|
+
const beforeCreateFileRoute = () => {
|
|
198
|
+
if (!p2) return "";
|
|
199
|
+
let trimmed = p2.trim();
|
|
200
|
+
if (trimmed.endsWith(",")) {
|
|
201
|
+
trimmed = trimmed.slice(0, -1);
|
|
202
|
+
}
|
|
203
|
+
return trimmed;
|
|
204
|
+
};
|
|
205
|
+
const afterCreateFileRoute = () => {
|
|
206
|
+
if (!p5) return "";
|
|
207
|
+
let trimmed = p5.trim();
|
|
208
|
+
if (trimmed.startsWith(",")) {
|
|
209
|
+
trimmed = trimmed.slice(1);
|
|
210
|
+
}
|
|
211
|
+
return trimmed;
|
|
212
|
+
};
|
|
213
|
+
const newImport = () => {
|
|
214
|
+
const before = beforeCreateFileRoute();
|
|
215
|
+
const after = afterCreateFileRoute();
|
|
216
|
+
if (!before) return after;
|
|
217
|
+
if (!after) return before;
|
|
218
|
+
return `${before},${after}`;
|
|
219
|
+
};
|
|
220
|
+
const middle = newImport();
|
|
221
|
+
if (middle === "") return "";
|
|
222
|
+
return `${p1} ${newImport()} ${p6}`;
|
|
223
|
+
}
|
|
224
|
+
).replace(
|
|
225
|
+
/create(Lazy)?FileRoute(\(\s*['"])([^\s]*)(['"],?\s*\))/g,
|
|
226
|
+
(_, __, p2, ___, p4) => `${node._fsRouteType === "lazy" ? "createLazyFileRoute" : "createFileRoute"}`
|
|
227
|
+
);
|
|
221
228
|
} else {
|
|
222
229
|
replaced = routeCode.replace(
|
|
223
230
|
/(FileRoute\(\s*['"])([^\s]*)(['"],?\s*\))/g,
|
|
224
|
-
(
|
|
231
|
+
(_, p1, __, p3) => `${p1}${escapedRoutePath}${p3}`
|
|
232
|
+
).replace(
|
|
233
|
+
/((FileRoute)(\s*)(\({))/g,
|
|
234
|
+
(_, __, p2, p3, p4) => `${p2}('${escapedRoutePath}')${p3}${p4}`
|
|
225
235
|
).replace(
|
|
226
|
-
|
|
227
|
-
|
|
236
|
+
new RegExp(
|
|
237
|
+
`(import\\s*\\{.*)(create(Lazy)?FileRoute)(.*\\}\\s*from\\s*['"]@tanstack\\/${ROUTE_TEMPLATE.subPkg}['"])`,
|
|
238
|
+
"gs"
|
|
239
|
+
),
|
|
240
|
+
(_, p1, __, ___, p4) => `${p1}${node._fsRouteType === "lazy" ? "createLazyFileRoute" : "createFileRoute"}${p4}`
|
|
228
241
|
).replace(
|
|
229
|
-
/(
|
|
230
|
-
(
|
|
242
|
+
/create(Lazy)?FileRoute(\(\s*['"])([^\s]*)(['"],?\s*\))/g,
|
|
243
|
+
(_, __, p2, ___, p4) => `${node._fsRouteType === "lazy" ? "createLazyFileRoute" : "createFileRoute"}${p2}${escapedRoutePath}${p4}`
|
|
231
244
|
);
|
|
245
|
+
const regex = new RegExp(
|
|
246
|
+
`(import\\s*\\{.*)(create(Lazy)?FileRoute)(.*\\}\\s*from\\s*['"]@tanstack\\/${ROUTE_TEMPLATE.subPkg}['"])`,
|
|
247
|
+
"gm"
|
|
248
|
+
);
|
|
249
|
+
if (!replaced.match(regex)) {
|
|
250
|
+
replaced = [
|
|
251
|
+
`import { ${node._fsRouteType === "lazy" ? "createLazyFileRoute" : "createFileRoute"} } from '@tanstack/${ROUTE_TEMPLATE.subPkg}'`,
|
|
252
|
+
...replaced.split("\n")
|
|
253
|
+
].join("\n");
|
|
254
|
+
}
|
|
232
255
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
256
|
+
await utils.writeIfDifferent(node.fullPath, routeCode, replaced, {
|
|
257
|
+
beforeWrite: () => {
|
|
258
|
+
logger.log(`🟡 Updating ${node.fullPath}`);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
237
261
|
}
|
|
238
|
-
if (!node.isVirtual &&
|
|
262
|
+
if (!node.isVirtual && [
|
|
263
|
+
"lazy",
|
|
264
|
+
"loader",
|
|
265
|
+
"component",
|
|
266
|
+
"pendingComponent",
|
|
267
|
+
"errorComponent"
|
|
268
|
+
].some((d) => d === node._fsRouteType)) {
|
|
239
269
|
routePiecesByPath[node.routePath] = routePiecesByPath[node.routePath] || {};
|
|
240
|
-
routePiecesByPath[node.routePath][node.
|
|
270
|
+
routePiecesByPath[node.routePath][node._fsRouteType === "lazy" ? "lazy" : node._fsRouteType === "loader" ? "loader" : node._fsRouteType === "errorComponent" ? "errorComponent" : node._fsRouteType === "pendingComponent" ? "pendingComponent" : "component"] = node;
|
|
241
271
|
const anchorRoute = routeNodes.find((d) => d.routePath === node.routePath);
|
|
242
272
|
if (!anchorRoute) {
|
|
243
273
|
await handleNode({
|
|
244
274
|
...node,
|
|
245
275
|
isVirtual: true,
|
|
246
|
-
|
|
247
|
-
isLoader: false,
|
|
248
|
-
isComponent: false,
|
|
249
|
-
isErrorComponent: false,
|
|
250
|
-
isPendingComponent: false
|
|
276
|
+
_fsRouteType: "static"
|
|
251
277
|
});
|
|
252
278
|
}
|
|
253
279
|
return;
|
|
254
280
|
}
|
|
255
281
|
const cleanedPathIsEmpty = (node.cleanedPath || "").length === 0;
|
|
256
|
-
|
|
282
|
+
const nonPathRoute = node._fsRouteType === "pathless_layout" && node.isNonPath;
|
|
283
|
+
node.isVirtualParentRequired = node._fsRouteType === "pathless_layout" || nonPathRoute ? !cleanedPathIsEmpty : false;
|
|
257
284
|
if (!node.isVirtual && node.isVirtualParentRequired) {
|
|
258
285
|
const parentRoutePath = removeLastSegmentFromPath(node.routePath) || "/";
|
|
259
|
-
const parentVariableName = routePathToVariable(parentRoutePath);
|
|
286
|
+
const parentVariableName = utils.routePathToVariable(parentRoutePath);
|
|
260
287
|
const anchorRoute = routeNodes.find(
|
|
261
288
|
(d) => d.routePath === parentRoutePath
|
|
262
289
|
);
|
|
@@ -269,14 +296,15 @@ async function generator(config) {
|
|
|
269
296
|
routePath: parentRoutePath,
|
|
270
297
|
variableName: parentVariableName,
|
|
271
298
|
isVirtual: true,
|
|
272
|
-
|
|
299
|
+
_fsRouteType: "layout",
|
|
300
|
+
// layout since this route will wrap other routes
|
|
273
301
|
isVirtualParentRoute: true,
|
|
274
302
|
isVirtualParentRequired: false
|
|
275
303
|
};
|
|
276
304
|
parentNode.children = parentNode.children ?? [];
|
|
277
305
|
parentNode.children.push(node);
|
|
278
306
|
node.parent = parentNode;
|
|
279
|
-
if (node.
|
|
307
|
+
if (node._fsRouteType === "pathless_layout") {
|
|
280
308
|
node.path = determineNodePath(node);
|
|
281
309
|
}
|
|
282
310
|
await handleNode(parentNode);
|
|
@@ -299,29 +327,47 @@ async function generator(config) {
|
|
|
299
327
|
for (const node of preRouteNodes) {
|
|
300
328
|
await handleNode(node);
|
|
301
329
|
}
|
|
302
|
-
|
|
330
|
+
checkRouteFullPathUniqueness(
|
|
331
|
+
preRouteNodes.filter(
|
|
332
|
+
(d) => d.children === void 0 && "lazy" !== d._fsRouteType
|
|
333
|
+
),
|
|
334
|
+
config
|
|
335
|
+
);
|
|
336
|
+
function buildRouteTreeConfig(nodes, depth = 1) {
|
|
303
337
|
const children = nodes.map((node) => {
|
|
304
338
|
var _a, _b;
|
|
305
|
-
if (node.
|
|
339
|
+
if (node._fsRouteType === "__root") {
|
|
306
340
|
return;
|
|
307
341
|
}
|
|
308
|
-
if (node.
|
|
342
|
+
if (node._fsRouteType === "pathless_layout" && !((_a = node.children) == null ? void 0 : _a.length)) {
|
|
309
343
|
return;
|
|
310
344
|
}
|
|
311
345
|
const route = `${node.variableName}Route`;
|
|
312
346
|
if ((_b = node.children) == null ? void 0 : _b.length) {
|
|
313
|
-
const childConfigs =
|
|
314
|
-
|
|
347
|
+
const childConfigs = buildRouteTreeConfig(node.children, depth + 1);
|
|
348
|
+
const childrenDeclaration = TYPES_DISABLED ? "" : `interface ${route}Children {
|
|
349
|
+
${node.children.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
350
|
+
}`;
|
|
351
|
+
const children2 = `const ${route}Children${TYPES_DISABLED ? "" : `: ${route}Children`} = {
|
|
352
|
+
${node.children.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
353
|
+
}`;
|
|
354
|
+
const routeWithChildren = `const ${route}WithChildren = ${route}._addFileChildren(${route}Children)`;
|
|
355
|
+
return [
|
|
356
|
+
childConfigs,
|
|
357
|
+
childrenDeclaration,
|
|
358
|
+
children2,
|
|
359
|
+
routeWithChildren
|
|
360
|
+
].join("\n\n");
|
|
315
361
|
}
|
|
316
|
-
return
|
|
362
|
+
return void 0;
|
|
317
363
|
});
|
|
318
|
-
return children.filter(Boolean).join(
|
|
364
|
+
return children.filter(Boolean).join("\n\n");
|
|
319
365
|
}
|
|
320
|
-
const routeConfigChildrenText =
|
|
321
|
-
const sortedRouteNodes = multiSortBy(routeNodes, [
|
|
366
|
+
const routeConfigChildrenText = buildRouteTreeConfig(routeTree);
|
|
367
|
+
const sortedRouteNodes = utils.multiSortBy(routeNodes, [
|
|
322
368
|
(d) => {
|
|
323
369
|
var _a;
|
|
324
|
-
return ((_a = d.routePath) == null ? void 0 : _a.includes(`/${rootPathId}`)) ? -1 : 1;
|
|
370
|
+
return ((_a = d.routePath) == null ? void 0 : _a.includes(`/${rootPathId.rootPathId}`)) ? -1 : 1;
|
|
325
371
|
},
|
|
326
372
|
(d) => {
|
|
327
373
|
var _a;
|
|
@@ -329,10 +375,25 @@ async function generator(config) {
|
|
|
329
375
|
},
|
|
330
376
|
(d) => {
|
|
331
377
|
var _a;
|
|
332
|
-
return ((_a = d.routePath) == null ? void 0 : _a.endsWith(
|
|
378
|
+
return ((_a = d.routePath) == null ? void 0 : _a.endsWith(config.indexToken)) ? -1 : 1;
|
|
333
379
|
},
|
|
334
380
|
(d) => d
|
|
335
381
|
]);
|
|
382
|
+
const typeImports = Object.entries({
|
|
383
|
+
// Used for augmentation of regular routes
|
|
384
|
+
CreateFileRoute: config.verboseFileRoutes === false && sortedRouteNodes.some(
|
|
385
|
+
(d) => isRouteNodeValidForAugmentation(d) && d._fsRouteType !== "lazy"
|
|
386
|
+
),
|
|
387
|
+
// Used for augmentation of lazy (`.lazy`) routes
|
|
388
|
+
CreateLazyFileRoute: config.verboseFileRoutes === false && sortedRouteNodes.some(
|
|
389
|
+
(node) => {
|
|
390
|
+
var _a;
|
|
391
|
+
return ((_a = routePiecesByPath[node.routePath]) == null ? void 0 : _a.lazy) && isRouteNodeValidForAugmentation(node);
|
|
392
|
+
}
|
|
393
|
+
),
|
|
394
|
+
// Used in the process of augmenting the routes
|
|
395
|
+
FileRoutesByPath: config.verboseFileRoutes === false && sortedRouteNodes.some((d) => isRouteNodeValidForAugmentation(d))
|
|
396
|
+
}).filter((d) => d[1]).map((d) => d[0]).sort((a, b) => a.localeCompare(b));
|
|
336
397
|
const imports = Object.entries({
|
|
337
398
|
createFileRoute: sortedRouteNodes.some((d) => d.isVirtual),
|
|
338
399
|
lazyFn: sortedRouteNodes.some(
|
|
@@ -349,43 +410,36 @@ async function generator(config) {
|
|
|
349
410
|
)
|
|
350
411
|
}).filter((d) => d[1]).map((d) => d[0]);
|
|
351
412
|
const virtualRouteNodes = sortedRouteNodes.filter((d) => d.isVirtual);
|
|
352
|
-
|
|
413
|
+
function getImportPath(node) {
|
|
414
|
+
return utils.replaceBackslash(
|
|
415
|
+
utils.removeExt(
|
|
416
|
+
path.relative(
|
|
417
|
+
path.dirname(config.generatedRouteTree),
|
|
418
|
+
path.resolve(config.routesDirectory, node.filePath)
|
|
419
|
+
),
|
|
420
|
+
config.addExtensions
|
|
421
|
+
)
|
|
422
|
+
);
|
|
423
|
+
}
|
|
353
424
|
const routeImports = [
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
` : ""
|
|
425
|
+
...config.routeTreeFileHeader,
|
|
426
|
+
`// This file was automatically generated by TanStack Router.
|
|
427
|
+
// You should NOT make any changes in this file as it will be overwritten.
|
|
428
|
+
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.`,
|
|
429
|
+
[
|
|
430
|
+
imports.length ? `import { ${imports.join(", ")} } from '${ROUTE_TEMPLATE.fullPkg}'` : "",
|
|
431
|
+
!TYPES_DISABLED && typeImports.length ? `import type { ${typeImports.join(", ")} } from '${ROUTE_TEMPLATE.fullPkg}'` : ""
|
|
432
|
+
].filter(Boolean).join("\n"),
|
|
361
433
|
"// Import Routes",
|
|
362
434
|
[
|
|
363
|
-
`import { Route as rootRoute } from './${
|
|
364
|
-
path.relative(
|
|
365
|
-
path.dirname(config.generatedRouteTree),
|
|
366
|
-
path.resolve(
|
|
367
|
-
config.routesDirectory,
|
|
368
|
-
`${routePathIdPrefix}${rootPathId}${rootPathIdExtension}`
|
|
369
|
-
)
|
|
370
|
-
)
|
|
371
|
-
)}'`,
|
|
435
|
+
`import { Route as rootRoute } from './${getImportPath(rootRouteNode)}'`,
|
|
372
436
|
...sortedRouteNodes.filter((d) => !d.isVirtual).map((node) => {
|
|
373
|
-
return `import { Route as ${node.variableName}
|
|
374
|
-
removeExt(
|
|
375
|
-
path.relative(
|
|
376
|
-
path.dirname(config.generatedRouteTree),
|
|
377
|
-
path.resolve(config.routesDirectory, node.filePath)
|
|
378
|
-
),
|
|
379
|
-
config.addExtensions
|
|
380
|
-
)
|
|
381
|
-
)}'`;
|
|
437
|
+
return `import { Route as ${node.variableName}RouteImport } from './${getImportPath(node)}'`;
|
|
382
438
|
})
|
|
383
439
|
].join("\n"),
|
|
384
440
|
virtualRouteNodes.length ? "// Create Virtual Routes" : "",
|
|
385
441
|
virtualRouteNodes.map((node) => {
|
|
386
|
-
return `const ${node.variableName}
|
|
387
|
-
node.routePath
|
|
388
|
-
)}')()`;
|
|
442
|
+
return `const ${node.variableName}RouteImport = createFileRoute('${node.routePath}')()`;
|
|
389
443
|
}).join("\n"),
|
|
390
444
|
"// Create/Update Routes",
|
|
391
445
|
sortedRouteNodes.map((node) => {
|
|
@@ -396,155 +450,221 @@ async function generator(config) {
|
|
|
396
450
|
const pendingComponentNode = (_d = routePiecesByPath[node.routePath]) == null ? void 0 : _d.pendingComponent;
|
|
397
451
|
const lazyComponentNode = (_e = routePiecesByPath[node.routePath]) == null ? void 0 : _e.lazy;
|
|
398
452
|
return [
|
|
399
|
-
|
|
453
|
+
[
|
|
454
|
+
`const ${node.variableName}Route = ${node.variableName}RouteImport.update({
|
|
400
455
|
${[
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
path.dirname(config.generatedRouteTree),
|
|
409
|
-
path.resolve(config.routesDirectory, loaderNode.filePath)
|
|
410
|
-
),
|
|
411
|
-
config.addExtensions
|
|
412
|
-
)
|
|
413
|
-
)}'), 'loader') })` : "",
|
|
414
|
-
componentNode || errorComponentNode || pendingComponentNode ? `.update({
|
|
415
|
-
${[
|
|
416
|
-
["component", componentNode],
|
|
417
|
-
["errorComponent", errorComponentNode],
|
|
418
|
-
["pendingComponent", pendingComponentNode]
|
|
419
|
-
].filter((d) => d[1]).map((d) => {
|
|
420
|
-
return `${d[0]}: lazyRouteComponent(() => import('./${replaceBackslash(
|
|
421
|
-
removeExt(
|
|
456
|
+
`id: '${node.path}'`,
|
|
457
|
+
!node.isNonPath ? `path: '${node.cleanedPath}'` : void 0,
|
|
458
|
+
`getParentRoute: () => ${((_f = node.parent) == null ? void 0 : _f.variableName) ?? "root"}Route`
|
|
459
|
+
].filter(Boolean).join(",")}
|
|
460
|
+
}${TYPES_DISABLED ? "" : "as any"})`,
|
|
461
|
+
loaderNode ? `.updateLoader({ loader: lazyFn(() => import('./${utils.replaceBackslash(
|
|
462
|
+
utils.removeExt(
|
|
422
463
|
path.relative(
|
|
423
464
|
path.dirname(config.generatedRouteTree),
|
|
424
|
-
path.resolve(config.routesDirectory,
|
|
465
|
+
path.resolve(config.routesDirectory, loaderNode.filePath)
|
|
425
466
|
),
|
|
426
467
|
config.addExtensions
|
|
427
468
|
)
|
|
428
|
-
)}'), '
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
469
|
+
)}'), 'loader') })` : "",
|
|
470
|
+
componentNode || errorComponentNode || pendingComponentNode ? `.update({
|
|
471
|
+
${[
|
|
472
|
+
["component", componentNode],
|
|
473
|
+
["errorComponent", errorComponentNode],
|
|
474
|
+
["pendingComponent", pendingComponentNode]
|
|
475
|
+
].filter((d) => d[1]).map((d) => {
|
|
476
|
+
return `${d[0]}: lazyRouteComponent(() => import('./${utils.replaceBackslash(
|
|
477
|
+
utils.removeExt(
|
|
478
|
+
path.relative(
|
|
479
|
+
path.dirname(config.generatedRouteTree),
|
|
480
|
+
path.resolve(config.routesDirectory, d[1].filePath)
|
|
481
|
+
),
|
|
482
|
+
config.addExtensions
|
|
438
483
|
)
|
|
439
|
-
),
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
484
|
+
)}'), '${d[0]}')`;
|
|
485
|
+
}).join("\n,")}
|
|
486
|
+
})` : "",
|
|
487
|
+
lazyComponentNode ? `.lazy(() => import('./${utils.replaceBackslash(
|
|
488
|
+
utils.removeExt(
|
|
489
|
+
path.relative(
|
|
490
|
+
path.dirname(config.generatedRouteTree),
|
|
491
|
+
path.resolve(
|
|
492
|
+
config.routesDirectory,
|
|
493
|
+
lazyComponentNode.filePath
|
|
494
|
+
)
|
|
495
|
+
),
|
|
496
|
+
config.addExtensions
|
|
497
|
+
)
|
|
498
|
+
)}').then((d) => d.Route))` : ""
|
|
499
|
+
].join("")
|
|
500
|
+
].join("\n\n");
|
|
444
501
|
}).join("\n\n"),
|
|
445
|
-
...
|
|
502
|
+
...TYPES_DISABLED ? [] : [
|
|
446
503
|
"// Populate the FileRoutesByPath interface",
|
|
447
|
-
`declare module '
|
|
504
|
+
`declare module '${ROUTE_TEMPLATE.fullPkg}' {
|
|
448
505
|
interface FileRoutesByPath {
|
|
449
506
|
${routeNodes.map((routeNode) => {
|
|
450
|
-
var _a, _b
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
507
|
+
var _a, _b;
|
|
508
|
+
const filePathId = routeNode.routePath;
|
|
509
|
+
return `'${filePathId}': {
|
|
510
|
+
id: '${filePathId}'
|
|
511
|
+
path: '${inferPath(routeNode)}'
|
|
512
|
+
fullPath: '${inferFullPath(routeNode)}'
|
|
513
|
+
preLoaderRoute: typeof ${routeNode.variableName}RouteImport
|
|
514
|
+
parentRoute: typeof ${routeNode.isVirtualParentRequired ? `${(_a = routeNode.parent) == null ? void 0 : _a.variableName}Route` : ((_b = routeNode.parent) == null ? void 0 : _b.variableName) ? `${routeNode.parent.variableName}RouteImport` : "rootRoute"}
|
|
454
515
|
}`;
|
|
455
516
|
}).join("\n")}
|
|
456
517
|
}
|
|
457
518
|
}`
|
|
458
519
|
],
|
|
520
|
+
...TYPES_DISABLED ? [] : config.verboseFileRoutes !== false ? [] : [
|
|
521
|
+
`// Add type-safety to the createFileRoute function across the route tree`,
|
|
522
|
+
routeNodes.map((routeNode) => {
|
|
523
|
+
var _a;
|
|
524
|
+
function getModuleDeclaration(routeNode2) {
|
|
525
|
+
if (!isRouteNodeValidForAugmentation(routeNode2)) {
|
|
526
|
+
return "";
|
|
527
|
+
}
|
|
528
|
+
return `declare module './${getImportPath(routeNode2)}' {
|
|
529
|
+
const ${routeNode2._fsRouteType === "lazy" ? "createLazyFileRoute" : "createFileRoute"}: ${routeNode2._fsRouteType === "lazy" ? `CreateLazyFileRoute<FileRoutesByPath['${routeNode2.routePath}']['preLoaderRoute']>}` : `CreateFileRoute<
|
|
530
|
+
'${routeNode2.routePath}',
|
|
531
|
+
FileRoutesByPath['${routeNode2.routePath}']['parentRoute'],
|
|
532
|
+
FileRoutesByPath['${routeNode2.routePath}']['id'],
|
|
533
|
+
FileRoutesByPath['${routeNode2.routePath}']['path'],
|
|
534
|
+
FileRoutesByPath['${routeNode2.routePath}']['fullPath']
|
|
535
|
+
>
|
|
536
|
+
}`}`;
|
|
537
|
+
}
|
|
538
|
+
return getModuleDeclaration(routeNode) + getModuleDeclaration(
|
|
539
|
+
(_a = routePiecesByPath[routeNode.routePath]) == null ? void 0 : _a.lazy
|
|
540
|
+
);
|
|
541
|
+
}).join("\n")
|
|
542
|
+
],
|
|
459
543
|
"// Create and export the route tree",
|
|
460
|
-
|
|
461
|
-
|
|
544
|
+
routeConfigChildrenText,
|
|
545
|
+
...TYPES_DISABLED ? [] : [
|
|
546
|
+
`export interface FileRoutesByFullPath {
|
|
547
|
+
${[...createRouteNodesByFullPath(routeNodes).entries()].map(
|
|
548
|
+
([fullPath, routeNode]) => {
|
|
549
|
+
return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
|
|
550
|
+
}
|
|
551
|
+
)}
|
|
552
|
+
}`,
|
|
553
|
+
`export interface FileRoutesByTo {
|
|
554
|
+
${[...createRouteNodesByTo(routeNodes).entries()].map(([to, routeNode]) => {
|
|
555
|
+
return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
|
|
556
|
+
})}
|
|
557
|
+
}`,
|
|
558
|
+
`export interface FileRoutesById {
|
|
559
|
+
'${rootRouteId}': typeof rootRoute,
|
|
560
|
+
${[...createRouteNodesById(routeNodes).entries()].map(([id, routeNode]) => {
|
|
561
|
+
return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
|
|
562
|
+
})}
|
|
563
|
+
}`,
|
|
564
|
+
`export interface FileRouteTypes {
|
|
565
|
+
fileRoutesByFullPath: FileRoutesByFullPath
|
|
566
|
+
fullPaths: ${routeNodes.length > 0 ? [...createRouteNodesByFullPath(routeNodes).keys()].map((fullPath) => `'${fullPath}'`).join("|") : "never"}
|
|
567
|
+
fileRoutesByTo: FileRoutesByTo
|
|
568
|
+
to: ${routeNodes.length > 0 ? [...createRouteNodesByTo(routeNodes).keys()].map((to) => `'${to}'`).join("|") : "never"}
|
|
569
|
+
id: ${[`'${rootRouteId}'`, ...[...createRouteNodesById(routeNodes).keys()].map((id) => `'${id}'`)].join("|")}
|
|
570
|
+
fileRoutesById: FileRoutesById
|
|
571
|
+
}`,
|
|
572
|
+
`export interface RootRouteChildren {
|
|
573
|
+
${routeTree.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
574
|
+
}`
|
|
575
|
+
],
|
|
576
|
+
`const rootRouteChildren${TYPES_DISABLED ? "" : ": RootRouteChildren"} = {
|
|
577
|
+
${routeTree.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
578
|
+
}`,
|
|
579
|
+
`export const routeTree = rootRoute._addFileChildren(rootRouteChildren)${TYPES_DISABLED ? "" : "._addFileTypes<FileRouteTypes>()"}`,
|
|
580
|
+
...config.routeTreeFileFooter
|
|
462
581
|
].filter(Boolean).join("\n\n");
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
582
|
+
const createRouteManifest = () => {
|
|
583
|
+
const routesManifest = {
|
|
584
|
+
[rootRouteId]: {
|
|
585
|
+
filePath: rootRouteNode.filePath,
|
|
586
|
+
children: routeTree.map((d) => d.routePath)
|
|
587
|
+
},
|
|
588
|
+
...Object.fromEntries(
|
|
589
|
+
routeNodes.map((d) => {
|
|
590
|
+
var _a, _b;
|
|
591
|
+
const filePathId = d.routePath;
|
|
592
|
+
return [
|
|
593
|
+
filePathId,
|
|
594
|
+
{
|
|
595
|
+
filePath: d.filePath,
|
|
596
|
+
parent: ((_a = d.parent) == null ? void 0 : _a.routePath) ? d.parent.routePath : void 0,
|
|
597
|
+
children: (_b = d.children) == null ? void 0 : _b.map((childRoute) => childRoute.routePath)
|
|
598
|
+
}
|
|
599
|
+
];
|
|
600
|
+
})
|
|
601
|
+
)
|
|
602
|
+
};
|
|
603
|
+
return JSON.stringify(
|
|
604
|
+
{
|
|
605
|
+
routes: routesManifest
|
|
606
|
+
},
|
|
607
|
+
null,
|
|
608
|
+
2
|
|
609
|
+
);
|
|
610
|
+
};
|
|
611
|
+
const includeManifest = ["react", "solid"];
|
|
612
|
+
const routeConfigFileContent = config.disableManifestGeneration || !includeManifest.includes(config.target) ? routeImports : [
|
|
613
|
+
routeImports,
|
|
614
|
+
"\n",
|
|
615
|
+
"/* ROUTE_MANIFEST_START",
|
|
616
|
+
createRouteManifest(),
|
|
617
|
+
"ROUTE_MANIFEST_END */"
|
|
618
|
+
].join("\n");
|
|
619
|
+
if (!checkLatest()) return;
|
|
620
|
+
const existingRouteTreeContent = await fsp__namespace.readFile(path.resolve(config.generatedRouteTree), "utf-8").catch((err) => {
|
|
469
621
|
if (err.code === "ENOENT") {
|
|
470
|
-
return
|
|
622
|
+
return "";
|
|
471
623
|
}
|
|
472
624
|
throw err;
|
|
473
625
|
});
|
|
474
|
-
if (!checkLatest())
|
|
626
|
+
if (!checkLatest()) return;
|
|
627
|
+
await fsp__namespace.mkdir(path.dirname(path.resolve(config.generatedRouteTree)), {
|
|
628
|
+
recursive: true
|
|
629
|
+
});
|
|
630
|
+
if (!checkLatest()) return;
|
|
631
|
+
const routeTreeWriteResult = await utils.writeIfDifferent(
|
|
632
|
+
path.resolve(config.generatedRouteTree),
|
|
633
|
+
config.enableRouteTreeFormatting ? await utils.format(existingRouteTreeContent, config) : existingRouteTreeContent,
|
|
634
|
+
config.enableRouteTreeFormatting ? await utils.format(routeConfigFileContent, config) : routeConfigFileContent,
|
|
635
|
+
{
|
|
636
|
+
beforeWrite: () => {
|
|
637
|
+
logger.log(`🟡 Updating ${config.generatedRouteTree}`);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
);
|
|
641
|
+
if (routeTreeWriteResult && !checkLatest()) {
|
|
475
642
|
return;
|
|
476
|
-
if (routeTreeContent !== routeConfigFileContent) {
|
|
477
|
-
await fsp__namespace.mkdir(path.dirname(path.resolve(config.generatedRouteTree)), {
|
|
478
|
-
recursive: true
|
|
479
|
-
});
|
|
480
|
-
if (!checkLatest())
|
|
481
|
-
return;
|
|
482
|
-
await fsp__namespace.writeFile(
|
|
483
|
-
path.resolve(config.generatedRouteTree),
|
|
484
|
-
routeConfigFileContent
|
|
485
|
-
);
|
|
486
643
|
}
|
|
487
644
|
logger.log(
|
|
488
645
|
`✅ Processed ${routeNodes.length === 1 ? "route" : "routes"} in ${Date.now() - start}ms`
|
|
489
646
|
);
|
|
490
647
|
}
|
|
491
|
-
function routePathToVariable(d) {
|
|
492
|
-
var _a, _b, _c, _d;
|
|
493
|
-
return ((_d = (_c = (_b = (_a = removeUnderscores(d)) == null ? void 0 : _a.replace(/\/\$\//g, "/splat/")) == null ? void 0 : _b.replace(/\$$/g, "splat")) == null ? void 0 : _c.replace(/\$/g, "")) == null ? void 0 : _d.split(/[/-]/g).map((d2, i) => i > 0 ? capitalize(d2) : d2).join("").replace(/([^a-zA-Z0-9]|[\.])/gm, "").replace(/^(\d)/g, "R$1")) ?? "";
|
|
494
|
-
}
|
|
495
|
-
function removeExt(d, keepExtension = false) {
|
|
496
|
-
return keepExtension ? d : d.substring(0, d.lastIndexOf(".")) || d;
|
|
497
|
-
}
|
|
498
|
-
function spaces(d) {
|
|
499
|
-
return Array.from({ length: d }).map(() => " ").join("");
|
|
500
|
-
}
|
|
501
|
-
function multiSortBy(arr, accessors = [(d) => d]) {
|
|
502
|
-
return arr.map((d, i) => [d, i]).sort(([a, ai], [b, bi]) => {
|
|
503
|
-
for (const accessor of accessors) {
|
|
504
|
-
const ao = accessor(a);
|
|
505
|
-
const bo = accessor(b);
|
|
506
|
-
if (typeof ao === "undefined") {
|
|
507
|
-
if (typeof bo === "undefined") {
|
|
508
|
-
continue;
|
|
509
|
-
}
|
|
510
|
-
return 1;
|
|
511
|
-
}
|
|
512
|
-
if (ao === bo) {
|
|
513
|
-
continue;
|
|
514
|
-
}
|
|
515
|
-
return ao > bo ? 1 : -1;
|
|
516
|
-
}
|
|
517
|
-
return ai - bi;
|
|
518
|
-
}).map(([d]) => d);
|
|
519
|
-
}
|
|
520
|
-
function capitalize(s) {
|
|
521
|
-
if (typeof s !== "string")
|
|
522
|
-
return "";
|
|
523
|
-
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
524
|
-
}
|
|
525
|
-
function removeUnderscores(s) {
|
|
526
|
-
return s == null ? void 0 : s.replaceAll(/(^_|_$)/gi, "").replaceAll(/(\/_|_\/)/gi, "/");
|
|
527
|
-
}
|
|
528
|
-
function removeTrailingUnderscores(s) {
|
|
529
|
-
return s == null ? void 0 : s.replaceAll(/(_$)/gi, "").replaceAll(/(_\/)/gi, "/");
|
|
530
|
-
}
|
|
531
|
-
function replaceBackslash(s) {
|
|
532
|
-
return s.replaceAll(/\\/gi, "/");
|
|
533
|
-
}
|
|
534
648
|
function removeGroups(s) {
|
|
535
|
-
return s.
|
|
649
|
+
return s.replace(possiblyNestedRouteGroupPatternRegex, "");
|
|
650
|
+
}
|
|
651
|
+
function isRouteNodeValidForAugmentation(routeNode) {
|
|
652
|
+
if (!routeNode || routeNode.isVirtual) {
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
return true;
|
|
536
656
|
}
|
|
537
657
|
function determineNodePath(node) {
|
|
538
658
|
var _a;
|
|
539
|
-
return node.path = node.parent ? ((_a = node.routePath) == null ? void 0 : _a.replace(node.parent.routePath, "")) || "/" : node.routePath;
|
|
659
|
+
return node.path = node.parent ? ((_a = node.routePath) == null ? void 0 : _a.replace(node.parent.routePath ?? "", "")) || "/" : node.routePath;
|
|
540
660
|
}
|
|
541
|
-
function removeLastSegmentFromPath(
|
|
542
|
-
const segments =
|
|
661
|
+
function removeLastSegmentFromPath(routePath = "/") {
|
|
662
|
+
const segments = routePath.split("/");
|
|
543
663
|
segments.pop();
|
|
544
664
|
return segments.join("/");
|
|
545
665
|
}
|
|
546
|
-
function removeLayoutSegments(
|
|
547
|
-
const segments =
|
|
666
|
+
function removeLayoutSegments(routePath = "/") {
|
|
667
|
+
const segments = routePath.split("/");
|
|
548
668
|
const newSegments = segments.filter((segment) => !segment.startsWith("_"));
|
|
549
669
|
return newSegments.join("/");
|
|
550
670
|
}
|
|
@@ -552,13 +672,12 @@ function hasParentRoute(routes, node, routePathToCheck) {
|
|
|
552
672
|
if (!routePathToCheck || routePathToCheck === "/") {
|
|
553
673
|
return null;
|
|
554
674
|
}
|
|
555
|
-
const sortedNodes = multiSortBy(routes, [
|
|
675
|
+
const sortedNodes = utils.multiSortBy(routes, [
|
|
556
676
|
(d) => d.routePath.length * -1,
|
|
557
677
|
(d) => d.variableName
|
|
558
|
-
]).filter((d) => d.routePath !== `/${rootPathId}`);
|
|
678
|
+
]).filter((d) => d.routePath !== `/${rootPathId.rootPathId}`);
|
|
559
679
|
for (const route of sortedNodes) {
|
|
560
|
-
if (route.routePath === "/")
|
|
561
|
-
continue;
|
|
680
|
+
if (route.routePath === "/") continue;
|
|
562
681
|
if (routePathToCheck.startsWith(`${route.routePath}/`) && route.routePath !== routePathToCheck) {
|
|
563
682
|
return route;
|
|
564
683
|
}
|
|
@@ -568,10 +687,79 @@ function hasParentRoute(routes, node, routePathToCheck) {
|
|
|
568
687
|
const parentRoutePath = segments.join("/");
|
|
569
688
|
return hasParentRoute(routes, node, parentRoutePath);
|
|
570
689
|
}
|
|
690
|
+
const getResolvedRouteNodeVariableName = (routeNode) => {
|
|
691
|
+
var _a;
|
|
692
|
+
return ((_a = routeNode.children) == null ? void 0 : _a.length) ? `${routeNode.variableName}RouteWithChildren` : `${routeNode.variableName}Route`;
|
|
693
|
+
};
|
|
694
|
+
const createRouteNodesByFullPath = (routeNodes) => {
|
|
695
|
+
return new Map(
|
|
696
|
+
routeNodes.map((routeNode) => [inferFullPath(routeNode), routeNode])
|
|
697
|
+
);
|
|
698
|
+
};
|
|
699
|
+
const createRouteNodesByTo = (routeNodes) => {
|
|
700
|
+
return new Map(
|
|
701
|
+
dedupeBranchesAndIndexRoutes(routeNodes).map((routeNode) => [
|
|
702
|
+
inferTo(routeNode),
|
|
703
|
+
routeNode
|
|
704
|
+
])
|
|
705
|
+
);
|
|
706
|
+
};
|
|
707
|
+
const createRouteNodesById = (routeNodes) => {
|
|
708
|
+
return new Map(
|
|
709
|
+
routeNodes.map((routeNode) => {
|
|
710
|
+
const id = routeNode.routePath ?? "";
|
|
711
|
+
return [id, routeNode];
|
|
712
|
+
})
|
|
713
|
+
);
|
|
714
|
+
};
|
|
715
|
+
const inferFullPath = (routeNode) => {
|
|
716
|
+
const fullPath = removeGroups(
|
|
717
|
+
utils.removeUnderscores(removeLayoutSegments(routeNode.routePath)) ?? ""
|
|
718
|
+
);
|
|
719
|
+
return routeNode.cleanedPath === "/" ? fullPath : fullPath.replace(/\/$/, "");
|
|
720
|
+
};
|
|
721
|
+
const inferPath = (routeNode) => {
|
|
722
|
+
var _a;
|
|
723
|
+
return routeNode.cleanedPath === "/" ? routeNode.cleanedPath : ((_a = routeNode.cleanedPath) == null ? void 0 : _a.replace(/\/$/, "")) ?? "";
|
|
724
|
+
};
|
|
725
|
+
const inferTo = (routeNode) => {
|
|
726
|
+
const fullPath = inferFullPath(routeNode);
|
|
727
|
+
if (fullPath === "/") return fullPath;
|
|
728
|
+
return fullPath.replace(/\/$/, "");
|
|
729
|
+
};
|
|
730
|
+
const dedupeBranchesAndIndexRoutes = (routes) => {
|
|
731
|
+
return routes.filter((route) => {
|
|
732
|
+
var _a;
|
|
733
|
+
if ((_a = route.children) == null ? void 0 : _a.find((child) => child.cleanedPath === "/")) return false;
|
|
734
|
+
return true;
|
|
735
|
+
});
|
|
736
|
+
};
|
|
737
|
+
function checkUnique(routes, key) {
|
|
738
|
+
const keys = routes.map((d) => d[key]);
|
|
739
|
+
const uniqueKeys = new Set(keys);
|
|
740
|
+
if (keys.length !== uniqueKeys.size) {
|
|
741
|
+
const duplicateKeys = keys.filter((d, i) => keys.indexOf(d) !== i);
|
|
742
|
+
const conflictingFiles = routes.filter(
|
|
743
|
+
(d) => duplicateKeys.includes(d[key])
|
|
744
|
+
);
|
|
745
|
+
return conflictingFiles;
|
|
746
|
+
}
|
|
747
|
+
return void 0;
|
|
748
|
+
}
|
|
749
|
+
function checkRouteFullPathUniqueness(_routes, config) {
|
|
750
|
+
const routes = _routes.map((d) => {
|
|
751
|
+
const inferredFullPath = inferFullPath(d);
|
|
752
|
+
return { ...d, inferredFullPath };
|
|
753
|
+
});
|
|
754
|
+
const conflictingFiles = checkUnique(routes, "inferredFullPath");
|
|
755
|
+
if (conflictingFiles !== void 0) {
|
|
756
|
+
const errorMessage = `Conflicting configuration paths were found for the following route${conflictingFiles.length > 1 ? "s" : ""}: ${conflictingFiles.map((p) => `"${p.inferredFullPath}"`).join(", ")}.
|
|
757
|
+
Please ensure each Route has a unique full path.
|
|
758
|
+
Conflicting files:
|
|
759
|
+
${conflictingFiles.map((d) => path.resolve(config.routesDirectory, d.filePath)).join("\n ")}
|
|
760
|
+
`;
|
|
761
|
+
throw new Error(errorMessage);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
571
764
|
exports.generator = generator;
|
|
572
|
-
exports.hasParentRoute = hasParentRoute;
|
|
573
|
-
exports.multiSortBy = multiSortBy;
|
|
574
|
-
exports.removeExt = removeExt;
|
|
575
|
-
exports.removeLastSegmentFromPath = removeLastSegmentFromPath;
|
|
576
|
-
exports.rootPathId = rootPathId;
|
|
577
765
|
//# sourceMappingURL=generator.cjs.map
|