@tanstack/router-generator 1.121.0-alpha.5 → 1.121.0
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 +23 -5
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/config.d.cts +7 -3
- package/dist/cjs/filesystem/physical/getRouteNodes.cjs +5 -3
- package/dist/cjs/filesystem/physical/getRouteNodes.cjs.map +1 -1
- package/dist/cjs/filesystem/virtual/getRouteNodes.cjs +1 -1
- package/dist/cjs/filesystem/virtual/getRouteNodes.cjs.map +1 -1
- package/dist/cjs/generator.cjs +828 -665
- package/dist/cjs/generator.cjs.map +1 -1
- package/dist/cjs/generator.d.cts +78 -1
- package/dist/cjs/index.cjs +5 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +7 -3
- package/dist/cjs/logger.cjs +37 -0
- package/dist/cjs/logger.cjs.map +1 -0
- package/dist/cjs/logger.d.cts +10 -0
- package/dist/cjs/plugin/default-generator-plugin.cjs +88 -0
- package/dist/cjs/plugin/default-generator-plugin.cjs.map +1 -0
- package/dist/cjs/plugin/default-generator-plugin.d.cts +2 -0
- package/dist/cjs/plugin/types.d.cts +46 -0
- package/dist/cjs/template.cjs +10 -10
- package/dist/cjs/template.cjs.map +1 -1
- package/dist/cjs/template.d.cts +2 -2
- package/dist/cjs/transform/default-transform-plugin.cjs +95 -0
- package/dist/cjs/transform/default-transform-plugin.cjs.map +1 -0
- package/dist/cjs/transform/default-transform-plugin.d.cts +2 -0
- package/dist/cjs/transform/transform.cjs +351 -0
- package/dist/cjs/transform/transform.cjs.map +1 -0
- package/dist/cjs/transform/transform.d.cts +4 -0
- package/dist/cjs/transform/types.d.cts +43 -0
- package/dist/cjs/transform/utils.cjs +36 -0
- package/dist/cjs/transform/utils.cjs.map +1 -0
- package/dist/cjs/transform/utils.d.cts +2 -0
- package/dist/cjs/types.d.cts +22 -0
- package/dist/cjs/utils.cjs +237 -40
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +76 -9
- package/dist/esm/config.d.ts +7 -3
- package/dist/esm/config.js +21 -3
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/filesystem/physical/getRouteNodes.js +3 -1
- package/dist/esm/filesystem/physical/getRouteNodes.js.map +1 -1
- package/dist/esm/filesystem/virtual/getRouteNodes.js +1 -1
- package/dist/esm/filesystem/virtual/getRouteNodes.js.map +1 -1
- package/dist/esm/generator.d.ts +78 -1
- package/dist/esm/generator.js +817 -653
- package/dist/esm/generator.js.map +1 -1
- package/dist/esm/index.d.ts +7 -3
- package/dist/esm/index.js +7 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/logger.d.ts +10 -0
- package/dist/esm/logger.js +37 -0
- package/dist/esm/logger.js.map +1 -0
- package/dist/esm/plugin/default-generator-plugin.d.ts +2 -0
- package/dist/esm/plugin/default-generator-plugin.js +88 -0
- package/dist/esm/plugin/default-generator-plugin.js.map +1 -0
- package/dist/esm/plugin/types.d.ts +46 -0
- package/dist/esm/template.d.ts +2 -2
- package/dist/esm/template.js +10 -10
- package/dist/esm/template.js.map +1 -1
- package/dist/esm/transform/default-transform-plugin.d.ts +2 -0
- package/dist/esm/transform/default-transform-plugin.js +95 -0
- package/dist/esm/transform/default-transform-plugin.js.map +1 -0
- package/dist/esm/transform/transform.d.ts +4 -0
- package/dist/esm/transform/transform.js +351 -0
- package/dist/esm/transform/transform.js.map +1 -0
- package/dist/esm/transform/types.d.ts +43 -0
- package/dist/esm/transform/utils.d.ts +2 -0
- package/dist/esm/transform/utils.js +36 -0
- package/dist/esm/transform/utils.js.map +1 -0
- package/dist/esm/types.d.ts +22 -0
- package/dist/esm/utils.d.ts +76 -9
- package/dist/esm/utils.js +237 -40
- package/dist/esm/utils.js.map +1 -1
- package/package.json +9 -10
- package/src/config.ts +23 -2
- package/src/filesystem/physical/getRouteNodes.ts +2 -1
- package/src/filesystem/virtual/getRouteNodes.ts +1 -1
- package/src/generator.ts +1108 -934
- package/src/index.ts +25 -3
- package/src/logger.ts +43 -0
- package/src/plugin/default-generator-plugin.ts +96 -0
- package/src/plugin/types.ts +51 -0
- package/src/template.ts +33 -12
- package/src/transform/default-transform-plugin.ts +103 -0
- package/src/transform/transform.ts +430 -0
- package/src/transform/types.ts +50 -0
- package/src/transform/utils.ts +42 -0
- package/src/types.ts +25 -0
- package/src/utils.ts +351 -36
package/dist/cjs/generator.cjs
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const path = require("node:path");
|
|
4
|
-
const fs = require("node:fs");
|
|
5
4
|
const fsp = require("node:fs/promises");
|
|
6
|
-
const
|
|
5
|
+
const node_fs = require("node:fs");
|
|
6
|
+
const crypto = require("node:crypto");
|
|
7
|
+
const routerCore = require("@tanstack/router-core");
|
|
8
|
+
const logger = require("./logger.cjs");
|
|
7
9
|
const getRouteNodes$1 = require("./filesystem/physical/getRouteNodes.cjs");
|
|
8
10
|
const getRouteNodes = require("./filesystem/virtual/getRouteNodes.cjs");
|
|
9
11
|
const rootPathId = require("./filesystem/physical/rootPathId.cjs");
|
|
12
|
+
const utils = require("./utils.cjs");
|
|
10
13
|
const template = require("./template.cjs");
|
|
14
|
+
const transform = require("./transform/transform.cjs");
|
|
15
|
+
const defaultGeneratorPlugin = require("./plugin/default-generator-plugin.cjs");
|
|
11
16
|
function _interopNamespaceDefault(e) {
|
|
12
17
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
13
18
|
if (e) {
|
|
@@ -24,106 +29,791 @@ function _interopNamespaceDefault(e) {
|
|
|
24
29
|
n.default = e;
|
|
25
30
|
return Object.freeze(n);
|
|
26
31
|
}
|
|
27
|
-
const fs__namespace = /* @__PURE__ */ _interopNamespaceDefault(fs);
|
|
28
32
|
const fsp__namespace = /* @__PURE__ */ _interopNamespaceDefault(fsp);
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
33
|
+
const DefaultFileSystem = {
|
|
34
|
+
stat: (filePath) => fsp__namespace.stat(filePath, { bigint: true }),
|
|
35
|
+
mkdtempSync: node_fs.mkdtempSync,
|
|
36
|
+
rename: (oldPath, newPath) => fsp__namespace.rename(oldPath, newPath),
|
|
37
|
+
writeFile: (filePath, content) => fsp__namespace.writeFile(filePath, content),
|
|
38
|
+
readFile: async (filePath) => {
|
|
39
|
+
try {
|
|
40
|
+
const fileHandle = await fsp__namespace.open(filePath, "r");
|
|
41
|
+
const stat = await fileHandle.stat({ bigint: true });
|
|
42
|
+
const fileContent = (await fileHandle.readFile()).toString();
|
|
43
|
+
await fileHandle.close();
|
|
44
|
+
return { stat, fileContent };
|
|
45
|
+
} catch (e) {
|
|
46
|
+
if ("code" in e) {
|
|
47
|
+
if (e.code === "ENOENT") {
|
|
48
|
+
return "file-not-existing";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
throw e;
|
|
52
|
+
}
|
|
46
53
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
};
|
|
55
|
+
function rerun(opts) {
|
|
56
|
+
const { event, ...rest } = opts;
|
|
57
|
+
return { rerun: true, event: event ?? { type: "rerun" }, ...rest };
|
|
58
|
+
}
|
|
59
|
+
function isRerun(result) {
|
|
60
|
+
return typeof result === "object" && result !== null && "rerun" in result && result.rerun === true;
|
|
61
|
+
}
|
|
62
|
+
class Generator {
|
|
63
|
+
constructor(opts) {
|
|
64
|
+
this.routeNodeCache = /* @__PURE__ */ new Map();
|
|
65
|
+
this.routeNodeShadowCache = /* @__PURE__ */ new Map();
|
|
66
|
+
this.fileEventQueue = [];
|
|
67
|
+
this.plugins = [defaultGeneratorPlugin.defaultGeneratorPlugin()];
|
|
68
|
+
this.pluginsWithTransform = [];
|
|
69
|
+
this.transformPlugins = [];
|
|
70
|
+
this.routeGroupPatternRegex = /\(.+\)/g;
|
|
71
|
+
this.config = opts.config;
|
|
72
|
+
this.logger = logger.logging({ disabled: this.config.disableLogging });
|
|
73
|
+
this.root = opts.root;
|
|
74
|
+
this.fs = opts.fs || DefaultFileSystem;
|
|
75
|
+
this.tmpDir = this.fs.mkdtempSync(
|
|
76
|
+
path.join(this.config.tmpDir, "router-generator-")
|
|
77
|
+
);
|
|
78
|
+
this.generatedRouteTreePath = path.resolve(this.config.generatedRouteTree);
|
|
79
|
+
this.targetTemplate = template.getTargetTemplate(this.config);
|
|
80
|
+
this.routesDirectoryPath = this.getRoutesDirectoryPath();
|
|
81
|
+
this.plugins.push(...opts.config.plugins || []);
|
|
82
|
+
this.plugins.forEach((plugin) => {
|
|
83
|
+
if ("transformPlugin" in plugin) {
|
|
84
|
+
if (this.pluginsWithTransform.find((p) => p.name === plugin.name)) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`Plugin with name "${plugin.name}" is already registered for export ${plugin.transformPlugin.exportName}!`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
this.pluginsWithTransform.push(plugin);
|
|
90
|
+
this.transformPlugins.push(plugin.transformPlugin);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
63
93
|
}
|
|
64
|
-
|
|
65
|
-
|
|
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);
|
|
94
|
+
getRoutesDirectoryPath() {
|
|
95
|
+
return path.isAbsolute(this.config.routesDirectory) ? this.config.routesDirectory : path.resolve(this.root, this.config.routesDirectory);
|
|
73
96
|
}
|
|
74
|
-
|
|
75
|
-
(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
97
|
+
async run(event) {
|
|
98
|
+
if (event && event.type !== "rerun") {
|
|
99
|
+
if (!(event.path === this.generatedRouteTreePath || event.path.startsWith(this.routesDirectoryPath))) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
this.fileEventQueue.push(event ?? { type: "rerun" });
|
|
104
|
+
if (this.runPromise) {
|
|
105
|
+
return this.runPromise;
|
|
106
|
+
}
|
|
107
|
+
this.runPromise = (async () => {
|
|
108
|
+
do {
|
|
109
|
+
const tempQueue = this.fileEventQueue;
|
|
110
|
+
this.fileEventQueue = [];
|
|
111
|
+
const remainingEvents = (await Promise.all(
|
|
112
|
+
tempQueue.map(async (e) => {
|
|
113
|
+
if (e.type === "update") {
|
|
114
|
+
let cacheEntry;
|
|
115
|
+
if (e.path === this.generatedRouteTreePath) {
|
|
116
|
+
cacheEntry = this.routeTreeFileCache;
|
|
117
|
+
} else {
|
|
118
|
+
cacheEntry = this.routeNodeCache.get(e.path);
|
|
119
|
+
}
|
|
120
|
+
const change = await this.didFileChangeComparedToCache(
|
|
121
|
+
{ path: e.path },
|
|
122
|
+
cacheEntry
|
|
123
|
+
);
|
|
124
|
+
if (change.result === false) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return e;
|
|
129
|
+
})
|
|
130
|
+
)).filter((e) => e !== null);
|
|
131
|
+
if (remainingEvents.length === 0) {
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
const start = performance.now();
|
|
136
|
+
await this.generatorInternal();
|
|
137
|
+
const end = performance.now();
|
|
138
|
+
this.logger.info(
|
|
139
|
+
`Generated route tree in ${Math.round(end - start)}ms`
|
|
140
|
+
);
|
|
141
|
+
} catch (err) {
|
|
142
|
+
const errArray = !Array.isArray(err) ? [err] : err;
|
|
143
|
+
const recoverableErrors = errArray.filter((e) => isRerun(e));
|
|
144
|
+
if (recoverableErrors.length === errArray.length) {
|
|
145
|
+
this.fileEventQueue.push(...recoverableErrors.map((e) => e.event));
|
|
146
|
+
recoverableErrors.forEach((e) => {
|
|
147
|
+
if (e.msg) {
|
|
148
|
+
this.logger.info(e.msg);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
} else {
|
|
152
|
+
const unrecoverableErrors = errArray.filter((e) => !isRerun(e));
|
|
153
|
+
this.runPromise = void 0;
|
|
154
|
+
throw new Error(
|
|
155
|
+
unrecoverableErrors.map((e) => e.message).join()
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
} while (this.fileEventQueue.length);
|
|
160
|
+
this.runPromise = void 0;
|
|
161
|
+
})();
|
|
162
|
+
return this.runPromise;
|
|
163
|
+
}
|
|
164
|
+
async generatorInternal() {
|
|
165
|
+
let writeRouteTreeFile = false;
|
|
166
|
+
let getRouteNodesResult;
|
|
167
|
+
if (this.config.virtualRouteConfig) {
|
|
168
|
+
getRouteNodesResult = await getRouteNodes.getRouteNodes(this.config, this.root);
|
|
169
|
+
} else {
|
|
170
|
+
getRouteNodesResult = await getRouteNodes$1.getRouteNodes(this.config, this.root);
|
|
171
|
+
}
|
|
172
|
+
const { rootRouteNode, routeNodes: beforeRouteNodes } = getRouteNodesResult;
|
|
173
|
+
if (rootRouteNode === void 0) {
|
|
174
|
+
let errorMessage = `rootRouteNode must not be undefined. Make sure you've added your root route into the route-tree.`;
|
|
175
|
+
if (!this.config.virtualRouteConfig) {
|
|
176
|
+
errorMessage += `
|
|
177
|
+
Make sure that you add a "${rootPathId.rootPathId}.${this.config.disableTypes ? "js" : "tsx"}" file to your routes directory.
|
|
178
|
+
Add the file in: "${this.config.routesDirectory}/${rootPathId.rootPathId}.${this.config.disableTypes ? "js" : "tsx"}"`;
|
|
179
|
+
}
|
|
180
|
+
throw new Error(errorMessage);
|
|
181
|
+
}
|
|
182
|
+
writeRouteTreeFile = await this.handleRootNode(rootRouteNode);
|
|
183
|
+
const preRouteNodes = utils.multiSortBy(beforeRouteNodes, [
|
|
184
|
+
(d) => d.routePath === "/" ? -1 : 1,
|
|
185
|
+
(d) => {
|
|
186
|
+
var _a;
|
|
187
|
+
return (_a = d.routePath) == null ? void 0 : _a.split("/").length;
|
|
188
|
+
},
|
|
189
|
+
(d) => d.filePath.match(new RegExp(`[./]${this.config.indexToken}[.]`)) ? 1 : -1,
|
|
190
|
+
(d) => d.filePath.match(
|
|
191
|
+
/[./](component|errorComponent|pendingComponent|loader|lazy)[.]/
|
|
192
|
+
) ? 1 : -1,
|
|
193
|
+
(d) => d.filePath.match(new RegExp(`[./]${this.config.routeToken}[.]`)) ? -1 : 1,
|
|
194
|
+
(d) => {
|
|
195
|
+
var _a;
|
|
196
|
+
return ((_a = d.routePath) == null ? void 0 : _a.endsWith("/")) ? -1 : 1;
|
|
197
|
+
},
|
|
198
|
+
(d) => d.routePath
|
|
199
|
+
]).filter((d) => ![`/${rootPathId.rootPathId}`].includes(d.routePath || ""));
|
|
200
|
+
const routeFileAllResult = await Promise.allSettled(
|
|
201
|
+
preRouteNodes.filter((n) => !n.isVirtualParentRoute && !n.isVirtual).map((n) => this.processRouteNodeFile(n))
|
|
202
|
+
);
|
|
203
|
+
const rejections = routeFileAllResult.filter(
|
|
204
|
+
(result) => result.status === "rejected"
|
|
205
|
+
);
|
|
206
|
+
if (rejections.length > 0) {
|
|
207
|
+
throw rejections.map((e) => e.reason);
|
|
208
|
+
}
|
|
209
|
+
const routeFileResult = routeFileAllResult.flatMap((result) => {
|
|
210
|
+
if (result.status === "fulfilled" && result.value !== null) {
|
|
211
|
+
return result.value;
|
|
212
|
+
}
|
|
213
|
+
return [];
|
|
214
|
+
});
|
|
215
|
+
routeFileResult.forEach((result) => {
|
|
86
216
|
var _a;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
217
|
+
if (!((_a = result.node.exports) == null ? void 0 : _a.length)) {
|
|
218
|
+
this.logger.warn(
|
|
219
|
+
`Route file "${result.cacheEntry.fileContent}" does not export any route piece. This is likely a mistake.`
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
if (routeFileResult.find((r) => r.shouldWriteTree)) {
|
|
224
|
+
writeRouteTreeFile = true;
|
|
225
|
+
}
|
|
226
|
+
if (!this.routeTreeFileCache) {
|
|
227
|
+
const routeTreeFile = await this.fs.readFile(this.generatedRouteTreePath);
|
|
228
|
+
if (routeTreeFile !== "file-not-existing") {
|
|
229
|
+
this.routeTreeFileCache = {
|
|
230
|
+
fileContent: routeTreeFile.fileContent,
|
|
231
|
+
mtimeMs: routeTreeFile.stat.mtimeMs
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
writeRouteTreeFile = true;
|
|
235
|
+
}
|
|
236
|
+
if (!writeRouteTreeFile) {
|
|
96
237
|
return;
|
|
97
238
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
logger.log(`🟡 Creating ${node.fullPath}`);
|
|
239
|
+
let routeTreeContent = this.buildRouteTreeFileContent(
|
|
240
|
+
rootRouteNode,
|
|
241
|
+
preRouteNodes,
|
|
242
|
+
routeFileResult
|
|
243
|
+
);
|
|
244
|
+
routeTreeContent = this.config.enableRouteTreeFormatting ? await utils.format(routeTreeContent, this.config) : routeTreeContent;
|
|
245
|
+
let newMtimeMs;
|
|
246
|
+
if (this.routeTreeFileCache) {
|
|
247
|
+
if (this.routeTreeFileCache.fileContent === routeTreeContent) ;
|
|
248
|
+
else {
|
|
249
|
+
const newRouteTreeFileStat = await this.safeFileWrite({
|
|
250
|
+
filePath: this.generatedRouteTreePath,
|
|
251
|
+
newContent: routeTreeContent,
|
|
252
|
+
strategy: {
|
|
253
|
+
type: "mtime",
|
|
254
|
+
expectedMtimeMs: this.routeTreeFileCache.mtimeMs
|
|
115
255
|
}
|
|
256
|
+
});
|
|
257
|
+
newMtimeMs = newRouteTreeFileStat.mtimeMs;
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
const newRouteTreeFileStat = await this.safeFileWrite({
|
|
261
|
+
filePath: this.generatedRouteTreePath,
|
|
262
|
+
newContent: routeTreeContent,
|
|
263
|
+
strategy: {
|
|
264
|
+
type: "new-file"
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
newMtimeMs = newRouteTreeFileStat.mtimeMs;
|
|
268
|
+
}
|
|
269
|
+
if (newMtimeMs !== void 0) {
|
|
270
|
+
this.routeTreeFileCache = {
|
|
271
|
+
fileContent: routeTreeContent,
|
|
272
|
+
mtimeMs: newMtimeMs
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
this.routeNodeCache = this.routeNodeShadowCache;
|
|
276
|
+
this.routeNodeShadowCache = /* @__PURE__ */ new Map();
|
|
277
|
+
}
|
|
278
|
+
buildRouteTreeFileContent(rootRouteNode, preRouteNodes, routeFileResult) {
|
|
279
|
+
const getImportForRouteNode = (node, exportName) => {
|
|
280
|
+
var _a;
|
|
281
|
+
if ((_a = node.exports) == null ? void 0 : _a.includes(exportName)) {
|
|
282
|
+
return {
|
|
283
|
+
source: `./${this.getImportPath(node)}`,
|
|
284
|
+
specifiers: [
|
|
285
|
+
{
|
|
286
|
+
imported: exportName,
|
|
287
|
+
local: `${node.variableName}${exportName}Import`
|
|
288
|
+
}
|
|
289
|
+
]
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
return void 0;
|
|
293
|
+
};
|
|
294
|
+
const buildRouteTreeForExport = (plugin) => {
|
|
295
|
+
var _a, _b, _c;
|
|
296
|
+
const exportName = plugin.transformPlugin.exportName;
|
|
297
|
+
const acc = {
|
|
298
|
+
routeTree: [],
|
|
299
|
+
routeNodes: [],
|
|
300
|
+
routePiecesByPath: {}
|
|
301
|
+
};
|
|
302
|
+
for (const node of preRouteNodes) {
|
|
303
|
+
if ((_a = node.exports) == null ? void 0 : _a.includes(plugin.transformPlugin.exportName)) {
|
|
304
|
+
this.handleNode(node, acc);
|
|
116
305
|
}
|
|
306
|
+
}
|
|
307
|
+
const sortedRouteNodes = utils.multiSortBy(acc.routeNodes, [
|
|
308
|
+
(d) => {
|
|
309
|
+
var _a2;
|
|
310
|
+
return ((_a2 = d.routePath) == null ? void 0 : _a2.includes(`/${rootPathId.rootPathId}`)) ? -1 : 1;
|
|
311
|
+
},
|
|
312
|
+
(d) => {
|
|
313
|
+
var _a2;
|
|
314
|
+
return (_a2 = d.routePath) == null ? void 0 : _a2.split("/").length;
|
|
315
|
+
},
|
|
316
|
+
(d) => {
|
|
317
|
+
var _a2;
|
|
318
|
+
return ((_a2 = d.routePath) == null ? void 0 : _a2.endsWith(this.config.indexToken)) ? -1 : 1;
|
|
319
|
+
},
|
|
320
|
+
(d) => d
|
|
321
|
+
]);
|
|
322
|
+
const pluginConfig = plugin.config({
|
|
323
|
+
generator: this,
|
|
324
|
+
rootRouteNode,
|
|
325
|
+
sortedRouteNodes
|
|
326
|
+
});
|
|
327
|
+
const routeImports2 = sortedRouteNodes.filter((d) => !d.isVirtual).flatMap((node) => getImportForRouteNode(node, exportName) ?? []);
|
|
328
|
+
const hasMatchingRouteFiles = acc.routeNodes.length > 0 || ((_b = rootRouteNode.exports) == null ? void 0 : _b.includes(exportName));
|
|
329
|
+
const virtualRouteNodes = sortedRouteNodes.filter((d) => d.isVirtual).map((node) => {
|
|
330
|
+
return `const ${node.variableName}${exportName}Import = ${plugin.createVirtualRouteCode({ node })}`;
|
|
331
|
+
});
|
|
332
|
+
if (!((_c = rootRouteNode.exports) == null ? void 0 : _c.includes(exportName)) && pluginConfig.virtualRootRoute) {
|
|
333
|
+
virtualRouteNodes.unshift(
|
|
334
|
+
`const ${rootRouteNode.variableName}${exportName}Import = ${plugin.createRootRouteCode()}`
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
const imports = plugin.imports({
|
|
338
|
+
sortedRouteNodes,
|
|
339
|
+
acc,
|
|
340
|
+
generator: this,
|
|
341
|
+
rootRouteNode
|
|
342
|
+
});
|
|
343
|
+
const routeTreeConfig = utils.buildRouteTreeConfig(
|
|
344
|
+
acc.routeTree,
|
|
345
|
+
exportName,
|
|
346
|
+
this.config.disableTypes
|
|
117
347
|
);
|
|
348
|
+
const createUpdateRoutes = sortedRouteNodes.map((node) => {
|
|
349
|
+
var _a2, _b2, _c2, _d, _e;
|
|
350
|
+
const loaderNode = (_a2 = acc.routePiecesByPath[node.routePath]) == null ? void 0 : _a2.loader;
|
|
351
|
+
const componentNode = (_b2 = acc.routePiecesByPath[node.routePath]) == null ? void 0 : _b2.component;
|
|
352
|
+
const errorComponentNode = (_c2 = acc.routePiecesByPath[node.routePath]) == null ? void 0 : _c2.errorComponent;
|
|
353
|
+
const pendingComponentNode = (_d = acc.routePiecesByPath[node.routePath]) == null ? void 0 : _d.pendingComponent;
|
|
354
|
+
const lazyComponentNode = (_e = acc.routePiecesByPath[node.routePath]) == null ? void 0 : _e.lazy;
|
|
355
|
+
return [
|
|
356
|
+
[
|
|
357
|
+
`const ${node.variableName}${exportName} = ${node.variableName}${exportName}Import.update({
|
|
358
|
+
${[
|
|
359
|
+
`id: '${node.path}'`,
|
|
360
|
+
!node.isNonPath ? `path: '${node.cleanedPath}'` : void 0,
|
|
361
|
+
`getParentRoute: () => ${utils.findParent(node, exportName)}`
|
|
362
|
+
].filter(Boolean).join(",")}
|
|
363
|
+
}${this.config.disableTypes ? "" : "as any"})`,
|
|
364
|
+
loaderNode ? `.updateLoader({ loader: lazyFn(() => import('./${utils.replaceBackslash(
|
|
365
|
+
utils.removeExt(
|
|
366
|
+
path.relative(
|
|
367
|
+
path.dirname(this.config.generatedRouteTree),
|
|
368
|
+
path.resolve(
|
|
369
|
+
this.config.routesDirectory,
|
|
370
|
+
loaderNode.filePath
|
|
371
|
+
)
|
|
372
|
+
),
|
|
373
|
+
this.config.addExtensions
|
|
374
|
+
)
|
|
375
|
+
)}'), 'loader') })` : "",
|
|
376
|
+
componentNode || errorComponentNode || pendingComponentNode ? `.update({
|
|
377
|
+
${[
|
|
378
|
+
["component", componentNode],
|
|
379
|
+
["errorComponent", errorComponentNode],
|
|
380
|
+
["pendingComponent", pendingComponentNode]
|
|
381
|
+
].filter((d) => d[1]).map((d) => {
|
|
382
|
+
return `${d[0]}: lazyRouteComponent(() => import('./${utils.replaceBackslash(
|
|
383
|
+
utils.removeExt(
|
|
384
|
+
path.relative(
|
|
385
|
+
path.dirname(this.config.generatedRouteTree),
|
|
386
|
+
path.resolve(
|
|
387
|
+
this.config.routesDirectory,
|
|
388
|
+
d[1].filePath
|
|
389
|
+
)
|
|
390
|
+
),
|
|
391
|
+
this.config.addExtensions
|
|
392
|
+
)
|
|
393
|
+
)}'), '${d[0]}')`;
|
|
394
|
+
}).join("\n,")}
|
|
395
|
+
})` : "",
|
|
396
|
+
lazyComponentNode ? `.lazy(() => import('./${utils.replaceBackslash(
|
|
397
|
+
utils.removeExt(
|
|
398
|
+
path.relative(
|
|
399
|
+
path.dirname(this.config.generatedRouteTree),
|
|
400
|
+
path.resolve(
|
|
401
|
+
this.config.routesDirectory,
|
|
402
|
+
lazyComponentNode.filePath
|
|
403
|
+
)
|
|
404
|
+
),
|
|
405
|
+
this.config.addExtensions
|
|
406
|
+
)
|
|
407
|
+
)}').then((d) => d.${exportName}))` : ""
|
|
408
|
+
].join("")
|
|
409
|
+
].join("\n\n");
|
|
410
|
+
});
|
|
411
|
+
let fileRoutesByPathInterfacePerPlugin = "";
|
|
412
|
+
let fileRoutesByFullPathPerPlugin = "";
|
|
413
|
+
if (!this.config.disableTypes && hasMatchingRouteFiles) {
|
|
414
|
+
fileRoutesByFullPathPerPlugin = [
|
|
415
|
+
`export interface File${exportName}sByFullPath {
|
|
416
|
+
${[...utils.createRouteNodesByFullPath(acc.routeNodes).entries()].map(
|
|
417
|
+
([fullPath, routeNode]) => {
|
|
418
|
+
return `'${fullPath}': typeof ${utils.getResolvedRouteNodeVariableName(routeNode, exportName)}`;
|
|
419
|
+
}
|
|
420
|
+
)}
|
|
421
|
+
}`,
|
|
422
|
+
`export interface File${exportName}sByTo {
|
|
423
|
+
${[...utils.createRouteNodesByTo(acc.routeNodes).entries()].map(([to, routeNode]) => {
|
|
424
|
+
return `'${to}': typeof ${utils.getResolvedRouteNodeVariableName(routeNode, exportName)}`;
|
|
425
|
+
})}
|
|
426
|
+
}`,
|
|
427
|
+
`export interface File${exportName}sById {
|
|
428
|
+
'${routerCore.rootRouteId}': typeof root${exportName}Import,
|
|
429
|
+
${[...utils.createRouteNodesById(acc.routeNodes).entries()].map(([id, routeNode]) => {
|
|
430
|
+
return `'${id}': typeof ${utils.getResolvedRouteNodeVariableName(routeNode, exportName)}`;
|
|
431
|
+
})}
|
|
432
|
+
}`,
|
|
433
|
+
`export interface File${exportName}Types {
|
|
434
|
+
file${exportName}sByFullPath: File${exportName}sByFullPath
|
|
435
|
+
fullPaths: ${acc.routeNodes.length > 0 ? [...utils.createRouteNodesByFullPath(acc.routeNodes).keys()].map((fullPath) => `'${fullPath}'`).join("|") : "never"}
|
|
436
|
+
file${exportName}sByTo: File${exportName}sByTo
|
|
437
|
+
to: ${acc.routeNodes.length > 0 ? [...utils.createRouteNodesByTo(acc.routeNodes).keys()].map((to) => `'${to}'`).join("|") : "never"}
|
|
438
|
+
id: ${[`'${routerCore.rootRouteId}'`, ...[...utils.createRouteNodesById(acc.routeNodes).keys()].map((id) => `'${id}'`)].join("|")}
|
|
439
|
+
file${exportName}sById: File${exportName}sById
|
|
440
|
+
}`,
|
|
441
|
+
`export interface Root${exportName}Children {
|
|
442
|
+
${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${utils.getResolvedRouteNodeVariableName(child, exportName)}`).join(",")}
|
|
443
|
+
}`
|
|
444
|
+
].join("\n");
|
|
445
|
+
fileRoutesByPathInterfacePerPlugin = buildFileRoutesByPathInterface({
|
|
446
|
+
...plugin.moduleAugmentation({ generator: this }),
|
|
447
|
+
routeNodes: preRouteNodes,
|
|
448
|
+
exportName
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
let routeTree = "";
|
|
452
|
+
if (hasMatchingRouteFiles) {
|
|
453
|
+
routeTree = [
|
|
454
|
+
`const root${exportName}Children${this.config.disableTypes ? "" : `: Root${exportName}Children`} = {
|
|
455
|
+
${acc.routeTree.map(
|
|
456
|
+
(child) => `${child.variableName}${exportName}: ${utils.getResolvedRouteNodeVariableName(child, exportName)}`
|
|
457
|
+
).join(",")}
|
|
458
|
+
}`,
|
|
459
|
+
`export const ${utils.lowerCaseFirstChar(exportName)}Tree = root${exportName}Import._addFileChildren(root${exportName}Children)${this.config.disableTypes ? "" : `._addFileTypes<File${exportName}Types>()`}`
|
|
460
|
+
].join("\n");
|
|
461
|
+
}
|
|
462
|
+
return {
|
|
463
|
+
routeImports: routeImports2,
|
|
464
|
+
sortedRouteNodes,
|
|
465
|
+
acc,
|
|
466
|
+
virtualRouteNodes,
|
|
467
|
+
routeTreeConfig,
|
|
468
|
+
routeTree,
|
|
469
|
+
imports,
|
|
470
|
+
createUpdateRoutes,
|
|
471
|
+
fileRoutesByFullPathPerPlugin,
|
|
472
|
+
fileRoutesByPathInterfacePerPlugin
|
|
473
|
+
};
|
|
474
|
+
};
|
|
475
|
+
const routeTrees = this.pluginsWithTransform.map((plugin) => ({
|
|
476
|
+
exportName: plugin.transformPlugin.exportName,
|
|
477
|
+
...buildRouteTreeForExport(plugin)
|
|
478
|
+
}));
|
|
479
|
+
this.plugins.map((plugin) => {
|
|
480
|
+
var _a;
|
|
481
|
+
return (_a = plugin.onRouteTreesChanged) == null ? void 0 : _a.call(plugin, {
|
|
482
|
+
routeTrees,
|
|
483
|
+
rootRouteNode,
|
|
484
|
+
generator: this
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
let mergedImports = utils.mergeImportDeclarations(
|
|
488
|
+
routeTrees.flatMap((d) => d.imports)
|
|
489
|
+
);
|
|
490
|
+
if (this.config.disableTypes) {
|
|
491
|
+
mergedImports = mergedImports.filter((d) => d.importKind !== "type");
|
|
492
|
+
}
|
|
493
|
+
const importStatements = mergedImports.map(utils.buildImportString);
|
|
494
|
+
let moduleAugmentation = "";
|
|
495
|
+
if (this.config.verboseFileRoutes === false && !this.config.disableTypes) {
|
|
496
|
+
moduleAugmentation = routeFileResult.map(({ node }) => {
|
|
497
|
+
const getModuleDeclaration = (routeNode) => {
|
|
498
|
+
if (!utils.isRouteNodeValidForAugmentation(routeNode)) {
|
|
499
|
+
return "";
|
|
500
|
+
}
|
|
501
|
+
const moduleAugmentation2 = this.pluginsWithTransform.map((plugin) => {
|
|
502
|
+
return plugin.routeModuleAugmentation({
|
|
503
|
+
routeNode
|
|
504
|
+
});
|
|
505
|
+
}).filter(Boolean).join("\n");
|
|
506
|
+
return `declare module './${this.getImportPath(routeNode)}' {
|
|
507
|
+
${moduleAugmentation2}
|
|
508
|
+
}`;
|
|
509
|
+
};
|
|
510
|
+
return getModuleDeclaration(node);
|
|
511
|
+
}).join("\n");
|
|
512
|
+
}
|
|
513
|
+
const routeImports = routeTrees.flatMap((t) => t.routeImports);
|
|
514
|
+
const rootRouteImports = this.pluginsWithTransform.flatMap(
|
|
515
|
+
(p) => getImportForRouteNode(rootRouteNode, p.transformPlugin.exportName) ?? []
|
|
516
|
+
);
|
|
517
|
+
if (rootRouteImports.length > 0) {
|
|
518
|
+
routeImports.unshift(...rootRouteImports);
|
|
118
519
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
520
|
+
const routeTreeContent = [
|
|
521
|
+
...this.config.routeTreeFileHeader,
|
|
522
|
+
`// This file was automatically generated by TanStack Router.
|
|
523
|
+
// You should NOT make any changes in this file as it will be overwritten.
|
|
524
|
+
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.`,
|
|
525
|
+
[...importStatements].join("\n"),
|
|
526
|
+
utils.mergeImportDeclarations(routeImports).map(utils.buildImportString).join("\n"),
|
|
527
|
+
routeTrees.flatMap((t) => t.virtualRouteNodes).join("\n"),
|
|
528
|
+
routeTrees.flatMap((t) => t.createUpdateRoutes).join("\n"),
|
|
529
|
+
routeTrees.map((t) => t.fileRoutesByFullPathPerPlugin).join("\n"),
|
|
530
|
+
routeTrees.map((t) => t.fileRoutesByPathInterfacePerPlugin).join("\n"),
|
|
531
|
+
moduleAugmentation,
|
|
532
|
+
routeTrees.flatMap((t) => t.routeTreeConfig).join("\n"),
|
|
533
|
+
routeTrees.map((t) => t.routeTree).join("\n"),
|
|
534
|
+
...this.config.routeTreeFileFooter
|
|
535
|
+
].filter(Boolean).join("\n\n");
|
|
536
|
+
return routeTreeContent;
|
|
537
|
+
}
|
|
538
|
+
getImportPath(node) {
|
|
539
|
+
return utils.replaceBackslash(
|
|
540
|
+
utils.removeExt(
|
|
541
|
+
path.relative(
|
|
542
|
+
path.dirname(this.config.generatedRouteTree),
|
|
543
|
+
path.resolve(this.config.routesDirectory, node.filePath)
|
|
544
|
+
),
|
|
545
|
+
this.config.addExtensions
|
|
546
|
+
)
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
async processRouteNodeFile(node) {
|
|
122
550
|
var _a, _b, _c, _d, _e;
|
|
123
|
-
|
|
124
|
-
|
|
551
|
+
const result = await this.isRouteFileCacheFresh(node);
|
|
552
|
+
if (result.status === "fresh") {
|
|
553
|
+
node.exports = result.cacheEntry.exports;
|
|
554
|
+
return {
|
|
555
|
+
node,
|
|
556
|
+
shouldWriteTree: result.exportsChanged,
|
|
557
|
+
cacheEntry: result.cacheEntry
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
const existingRouteFile = await this.fs.readFile(node.fullPath);
|
|
561
|
+
if (existingRouteFile === "file-not-existing") {
|
|
562
|
+
throw new Error(`⚠️ File ${node.fullPath} does not exist`);
|
|
563
|
+
}
|
|
564
|
+
const updatedCacheEntry = {
|
|
565
|
+
fileContent: existingRouteFile.fileContent,
|
|
566
|
+
mtimeMs: existingRouteFile.stat.mtimeMs,
|
|
567
|
+
exports: []
|
|
568
|
+
};
|
|
569
|
+
const escapedRoutePath = ((_a = node.routePath) == null ? void 0 : _a.replaceAll("$", "$$")) ?? "";
|
|
570
|
+
let shouldWriteRouteFile = false;
|
|
571
|
+
if (!existingRouteFile.fileContent) {
|
|
572
|
+
shouldWriteRouteFile = true;
|
|
573
|
+
if (node._fsRouteType === "lazy") {
|
|
574
|
+
const tLazyRouteTemplate = this.targetTemplate.lazyRoute;
|
|
575
|
+
updatedCacheEntry.fileContent = await template.fillTemplate(
|
|
576
|
+
this.config,
|
|
577
|
+
(((_b = this.config.customScaffolding) == null ? void 0 : _b.lazyRouteTemplate) || ((_c = this.config.customScaffolding) == null ? void 0 : _c.routeTemplate)) ?? tLazyRouteTemplate.template(),
|
|
578
|
+
{
|
|
579
|
+
tsrImports: tLazyRouteTemplate.imports.tsrImports(),
|
|
580
|
+
tsrPath: escapedRoutePath.replaceAll(/\{(.+)\}/gm, "$1"),
|
|
581
|
+
tsrExportStart: tLazyRouteTemplate.imports.tsrExportStart(escapedRoutePath),
|
|
582
|
+
tsrExportEnd: tLazyRouteTemplate.imports.tsrExportEnd()
|
|
583
|
+
}
|
|
584
|
+
);
|
|
585
|
+
updatedCacheEntry.exports = ["Route"];
|
|
586
|
+
} else if (
|
|
587
|
+
// Creating a new normal route file
|
|
588
|
+
["layout", "static"].some(
|
|
589
|
+
(d) => d === node._fsRouteType
|
|
590
|
+
) || [
|
|
591
|
+
"component",
|
|
592
|
+
"pendingComponent",
|
|
593
|
+
"errorComponent",
|
|
594
|
+
"loader"
|
|
595
|
+
].every((d) => d !== node._fsRouteType)
|
|
596
|
+
) {
|
|
597
|
+
const tRouteTemplate = this.targetTemplate.route;
|
|
598
|
+
updatedCacheEntry.fileContent = await template.fillTemplate(
|
|
599
|
+
this.config,
|
|
600
|
+
((_d = this.config.customScaffolding) == null ? void 0 : _d.routeTemplate) ?? tRouteTemplate.template(),
|
|
601
|
+
{
|
|
602
|
+
tsrImports: tRouteTemplate.imports.tsrImports(),
|
|
603
|
+
tsrPath: escapedRoutePath.replaceAll(/\{(.+)\}/gm, "$1"),
|
|
604
|
+
tsrExportStart: tRouteTemplate.imports.tsrExportStart(escapedRoutePath),
|
|
605
|
+
tsrExportEnd: tRouteTemplate.imports.tsrExportEnd()
|
|
606
|
+
}
|
|
607
|
+
);
|
|
608
|
+
updatedCacheEntry.exports = ["Route"];
|
|
609
|
+
} else {
|
|
610
|
+
return null;
|
|
611
|
+
}
|
|
612
|
+
} else {
|
|
613
|
+
const transformResult = await transform.transform({
|
|
614
|
+
source: updatedCacheEntry.fileContent,
|
|
615
|
+
ctx: {
|
|
616
|
+
target: this.config.target,
|
|
617
|
+
routeId: escapedRoutePath,
|
|
618
|
+
lazy: node._fsRouteType === "lazy",
|
|
619
|
+
verboseFileRoutes: !(this.config.verboseFileRoutes === false)
|
|
620
|
+
},
|
|
621
|
+
plugins: this.transformPlugins
|
|
622
|
+
});
|
|
623
|
+
if (transformResult.result === "error") {
|
|
624
|
+
throw new Error(
|
|
625
|
+
`Error transforming route file ${node.fullPath}: ${transformResult.error}`
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
updatedCacheEntry.exports = transformResult.exports;
|
|
629
|
+
if (transformResult.result === "modified") {
|
|
630
|
+
updatedCacheEntry.fileContent = transformResult.output;
|
|
631
|
+
shouldWriteRouteFile = true;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
if (shouldWriteRouteFile) {
|
|
635
|
+
const stats = await this.safeFileWrite({
|
|
636
|
+
filePath: node.fullPath,
|
|
637
|
+
newContent: updatedCacheEntry.fileContent,
|
|
638
|
+
strategy: {
|
|
639
|
+
type: "mtime",
|
|
640
|
+
expectedMtimeMs: updatedCacheEntry.mtimeMs
|
|
641
|
+
}
|
|
642
|
+
});
|
|
643
|
+
updatedCacheEntry.mtimeMs = stats.mtimeMs;
|
|
644
|
+
}
|
|
645
|
+
this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry);
|
|
646
|
+
node.exports = updatedCacheEntry.exports;
|
|
647
|
+
const shouldWriteTree = !routerCore.deepEqual(
|
|
648
|
+
(_e = result.cacheEntry) == null ? void 0 : _e.exports,
|
|
649
|
+
updatedCacheEntry.exports
|
|
650
|
+
);
|
|
651
|
+
return {
|
|
652
|
+
node,
|
|
653
|
+
shouldWriteTree,
|
|
654
|
+
cacheEntry: updatedCacheEntry
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
async didRouteFileChangeComparedToCache(file, cache) {
|
|
658
|
+
const cacheEntry = this[cache].get(file.path);
|
|
659
|
+
return this.didFileChangeComparedToCache(file, cacheEntry);
|
|
660
|
+
}
|
|
661
|
+
async didFileChangeComparedToCache(file, cacheEntry) {
|
|
662
|
+
if (!cacheEntry) {
|
|
663
|
+
return { result: "file-not-in-cache" };
|
|
664
|
+
}
|
|
665
|
+
let mtimeMs = file.mtimeMs;
|
|
666
|
+
if (mtimeMs === void 0) {
|
|
667
|
+
try {
|
|
668
|
+
const currentStat = await this.fs.stat(file.path);
|
|
669
|
+
mtimeMs = currentStat.mtimeMs;
|
|
670
|
+
} catch {
|
|
671
|
+
return { result: "cannot-stat-file" };
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
return { result: mtimeMs !== cacheEntry.mtimeMs, mtimeMs, cacheEntry };
|
|
675
|
+
}
|
|
676
|
+
async safeFileWrite(opts) {
|
|
677
|
+
const tmpPath = this.getTempFileName(opts.filePath);
|
|
678
|
+
await this.fs.writeFile(tmpPath, opts.newContent);
|
|
679
|
+
if (opts.strategy.type === "mtime") {
|
|
680
|
+
const beforeStat = await this.fs.stat(opts.filePath);
|
|
681
|
+
if (beforeStat.mtimeMs !== opts.strategy.expectedMtimeMs) {
|
|
682
|
+
throw rerun({
|
|
683
|
+
msg: `File ${opts.filePath} was modified by another process during processing.`,
|
|
684
|
+
event: { type: "update", path: opts.filePath }
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
} else {
|
|
688
|
+
if (await utils.checkFileExists(opts.filePath)) {
|
|
689
|
+
throw rerun({
|
|
690
|
+
msg: `File ${opts.filePath} already exists. Cannot overwrite.`,
|
|
691
|
+
event: { type: "update", path: opts.filePath }
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
const stat = await this.fs.stat(tmpPath);
|
|
696
|
+
await this.fs.rename(tmpPath, opts.filePath);
|
|
697
|
+
return stat;
|
|
698
|
+
}
|
|
699
|
+
getTempFileName(filePath) {
|
|
700
|
+
const absPath = path.resolve(filePath);
|
|
701
|
+
const hash = crypto.createHash("md5").update(absPath).digest("hex");
|
|
702
|
+
return path.join(this.tmpDir, hash);
|
|
703
|
+
}
|
|
704
|
+
async isRouteFileCacheFresh(node) {
|
|
705
|
+
const fileChangedCache = await this.didRouteFileChangeComparedToCache(
|
|
706
|
+
{ path: node.fullPath },
|
|
707
|
+
"routeNodeCache"
|
|
708
|
+
);
|
|
709
|
+
if (fileChangedCache.result === false) {
|
|
710
|
+
this.routeNodeShadowCache.set(node.fullPath, fileChangedCache.cacheEntry);
|
|
711
|
+
return {
|
|
712
|
+
status: "fresh",
|
|
713
|
+
exportsChanged: false,
|
|
714
|
+
cacheEntry: fileChangedCache.cacheEntry
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
if (fileChangedCache.result === "cannot-stat-file") {
|
|
718
|
+
throw new Error(`⚠️ expected route file to exist at ${node.fullPath}`);
|
|
719
|
+
}
|
|
720
|
+
const mtimeMs = fileChangedCache.result === true ? fileChangedCache.mtimeMs : void 0;
|
|
721
|
+
const shadowCacheFileChange = await this.didRouteFileChangeComparedToCache(
|
|
722
|
+
{ path: node.fullPath, mtimeMs },
|
|
723
|
+
"routeNodeShadowCache"
|
|
724
|
+
);
|
|
725
|
+
if (shadowCacheFileChange.result === "cannot-stat-file") {
|
|
726
|
+
throw new Error(`⚠️ expected route file to exist at ${node.fullPath}`);
|
|
727
|
+
}
|
|
728
|
+
if (shadowCacheFileChange.result === false) {
|
|
729
|
+
if (fileChangedCache.result === true) {
|
|
730
|
+
if (routerCore.deepEqual(
|
|
731
|
+
fileChangedCache.cacheEntry.exports,
|
|
732
|
+
shadowCacheFileChange.cacheEntry.exports
|
|
733
|
+
)) {
|
|
734
|
+
return {
|
|
735
|
+
status: "fresh",
|
|
736
|
+
exportsChanged: false,
|
|
737
|
+
cacheEntry: shadowCacheFileChange.cacheEntry
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
return {
|
|
741
|
+
status: "fresh",
|
|
742
|
+
exportsChanged: true,
|
|
743
|
+
cacheEntry: shadowCacheFileChange.cacheEntry
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
if (fileChangedCache.result === "file-not-in-cache") {
|
|
748
|
+
return {
|
|
749
|
+
status: "stale"
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
return { status: "stale", cacheEntry: fileChangedCache.cacheEntry };
|
|
753
|
+
}
|
|
754
|
+
async handleRootNode(node) {
|
|
755
|
+
var _a;
|
|
756
|
+
const result = await this.isRouteFileCacheFresh(node);
|
|
757
|
+
if (result.status === "fresh") {
|
|
758
|
+
node.exports = result.cacheEntry.exports;
|
|
759
|
+
this.routeNodeShadowCache.set(node.fullPath, result.cacheEntry);
|
|
760
|
+
return result.exportsChanged;
|
|
761
|
+
}
|
|
762
|
+
const rootNodeFile = await this.fs.readFile(node.fullPath);
|
|
763
|
+
if (rootNodeFile === "file-not-existing") {
|
|
764
|
+
throw new Error(`⚠️ expected root route to exist at ${node.fullPath}`);
|
|
765
|
+
}
|
|
766
|
+
const updatedCacheEntry = {
|
|
767
|
+
fileContent: rootNodeFile.fileContent,
|
|
768
|
+
mtimeMs: rootNodeFile.stat.mtimeMs,
|
|
769
|
+
exports: []
|
|
770
|
+
};
|
|
771
|
+
if (!rootNodeFile.fileContent) {
|
|
772
|
+
const rootTemplate = this.targetTemplate.rootRoute;
|
|
773
|
+
const rootRouteContent = await template.fillTemplate(
|
|
774
|
+
this.config,
|
|
775
|
+
rootTemplate.template(),
|
|
776
|
+
{
|
|
777
|
+
tsrImports: rootTemplate.imports.tsrImports(),
|
|
778
|
+
tsrPath: rootPathId.rootPathId,
|
|
779
|
+
tsrExportStart: rootTemplate.imports.tsrExportStart(),
|
|
780
|
+
tsrExportEnd: rootTemplate.imports.tsrExportEnd()
|
|
781
|
+
}
|
|
782
|
+
);
|
|
783
|
+
this.logger.log(`🟡 Creating ${node.fullPath}`);
|
|
784
|
+
const stats = await this.safeFileWrite({
|
|
785
|
+
filePath: node.fullPath,
|
|
786
|
+
newContent: rootRouteContent,
|
|
787
|
+
strategy: {
|
|
788
|
+
type: "mtime",
|
|
789
|
+
expectedMtimeMs: rootNodeFile.stat.mtimeMs
|
|
790
|
+
}
|
|
791
|
+
});
|
|
792
|
+
updatedCacheEntry.fileContent = rootRouteContent;
|
|
793
|
+
updatedCacheEntry.mtimeMs = stats.mtimeMs;
|
|
794
|
+
}
|
|
795
|
+
const rootRouteExports = [];
|
|
796
|
+
for (const plugin of this.pluginsWithTransform) {
|
|
797
|
+
const exportName = plugin.transformPlugin.exportName;
|
|
798
|
+
if (rootNodeFile.fileContent.includes(`export const ${exportName}`)) {
|
|
799
|
+
rootRouteExports.push(exportName);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
updatedCacheEntry.exports = rootRouteExports;
|
|
803
|
+
node.exports = rootRouteExports;
|
|
804
|
+
this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry);
|
|
805
|
+
const shouldWriteTree = !routerCore.deepEqual(
|
|
806
|
+
(_a = result.cacheEntry) == null ? void 0 : _a.exports,
|
|
807
|
+
rootRouteExports
|
|
808
|
+
);
|
|
809
|
+
return shouldWriteTree;
|
|
810
|
+
}
|
|
811
|
+
handleNode(node, acc) {
|
|
812
|
+
var _a;
|
|
813
|
+
utils.resetRegex(this.routeGroupPatternRegex);
|
|
814
|
+
let parentRoute = utils.hasParentRoute(acc.routeNodes, node, node.routePath);
|
|
125
815
|
if ((parentRoute == null ? void 0 : parentRoute.isVirtualParentRoute) && ((_a = parentRoute.children) == null ? void 0 : _a.length)) {
|
|
126
|
-
const possibleParentRoute = hasParentRoute(
|
|
816
|
+
const possibleParentRoute = utils.hasParentRoute(
|
|
127
817
|
parentRoute.children,
|
|
128
818
|
node,
|
|
129
819
|
node.routePath
|
|
@@ -133,135 +823,14 @@ Add the file in: "${config.routesDirectory}/${rootPathId.rootPathId}.${config.di
|
|
|
133
823
|
}
|
|
134
824
|
}
|
|
135
825
|
if (parentRoute) node.parent = parentRoute;
|
|
136
|
-
node.path = determineNodePath(node);
|
|
826
|
+
node.path = utils.determineNodePath(node);
|
|
137
827
|
const trimmedPath = utils.trimPathLeft(node.path ?? "");
|
|
138
828
|
const split = trimmedPath.split("/");
|
|
139
829
|
const lastRouteSegment = split[split.length - 1] ?? trimmedPath;
|
|
140
|
-
node.isNonPath = lastRouteSegment.startsWith("_") || routeGroupPatternRegex.test(lastRouteSegment);
|
|
141
|
-
node.cleanedPath = removeGroups(
|
|
142
|
-
utils.removeUnderscores(removeLayoutSegments(node.path)) ?? ""
|
|
830
|
+
node.isNonPath = lastRouteSegment.startsWith("_") || this.routeGroupPatternRegex.test(lastRouteSegment);
|
|
831
|
+
node.cleanedPath = utils.removeGroups(
|
|
832
|
+
utils.removeUnderscores(utils.removeLayoutSegments(node.path)) ?? ""
|
|
143
833
|
);
|
|
144
|
-
if (!node.isVirtualParentRoute && !node.isVirtual) {
|
|
145
|
-
const routeCode = fs__namespace.readFileSync(node.fullPath, "utf-8");
|
|
146
|
-
const escapedRoutePath = ((_b = node.routePath) == null ? void 0 : _b.replaceAll("$", "$$")) ?? "";
|
|
147
|
-
let replaced = routeCode;
|
|
148
|
-
const tRouteTemplate = ROUTE_TEMPLATE.route;
|
|
149
|
-
const tLazyRouteTemplate = ROUTE_TEMPLATE.lazyRoute;
|
|
150
|
-
if (!routeCode) {
|
|
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
|
-
);
|
|
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
|
-
);
|
|
228
|
-
} else {
|
|
229
|
-
if (!routeCode.split("\n").some((line) => line.trim().startsWith("export const Route"))) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
replaced = routeCode.replace(
|
|
233
|
-
/(FileRoute\(\s*['"])([^\s]*)(['"],?\s*\))/g,
|
|
234
|
-
(_, p1, __, p3) => `${p1}${escapedRoutePath}${p3}`
|
|
235
|
-
).replace(
|
|
236
|
-
/((FileRoute)(\s*)(\({))/g,
|
|
237
|
-
(_, __, p2, p3, p4) => `${p2}('${escapedRoutePath}')${p3}${p4}`
|
|
238
|
-
).replace(
|
|
239
|
-
new RegExp(
|
|
240
|
-
`(import\\s*\\{.*)(create(Lazy)?FileRoute)(.*\\}\\s*from\\s*['"]@tanstack\\/${ROUTE_TEMPLATE.subPkg}['"])`,
|
|
241
|
-
"gs"
|
|
242
|
-
),
|
|
243
|
-
(_, p1, __, ___, p4) => `${p1}${node._fsRouteType === "lazy" ? "createLazyFileRoute" : "createFileRoute"}${p4}`
|
|
244
|
-
).replace(
|
|
245
|
-
/create(Lazy)?FileRoute(\(\s*['"])([^\s]*)(['"],?\s*\))/g,
|
|
246
|
-
(_, __, p2, ___, p4) => `${node._fsRouteType === "lazy" ? "createLazyFileRoute" : "createFileRoute"}${p2}${escapedRoutePath}${p4}`
|
|
247
|
-
);
|
|
248
|
-
const regex = new RegExp(
|
|
249
|
-
`(import\\s*\\{.*)(create(Lazy)?FileRoute)(.*\\}\\s*from\\s*['"]@tanstack\\/${ROUTE_TEMPLATE.subPkg}['"])`,
|
|
250
|
-
"gm"
|
|
251
|
-
);
|
|
252
|
-
if (!replaced.match(regex)) {
|
|
253
|
-
replaced = [
|
|
254
|
-
`import { ${node._fsRouteType === "lazy" ? "createLazyFileRoute" : "createFileRoute"} } from '@tanstack/${ROUTE_TEMPLATE.subPkg}'`,
|
|
255
|
-
...replaced.split("\n")
|
|
256
|
-
].join("\n");
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
await utils.writeIfDifferent(node.fullPath, routeCode, replaced, {
|
|
260
|
-
beforeWrite: () => {
|
|
261
|
-
logger.log(`🟡 Updating ${node.fullPath}`);
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
834
|
if (!node.isVirtual && [
|
|
266
835
|
"lazy",
|
|
267
836
|
"loader",
|
|
@@ -269,15 +838,20 @@ Add the file in: "${config.routesDirectory}/${rootPathId.rootPathId}.${config.di
|
|
|
269
838
|
"pendingComponent",
|
|
270
839
|
"errorComponent"
|
|
271
840
|
].some((d) => d === node._fsRouteType)) {
|
|
272
|
-
routePiecesByPath[node.routePath] = routePiecesByPath[node.routePath] || {};
|
|
273
|
-
routePiecesByPath[node.routePath][node._fsRouteType === "lazy" ? "lazy" : node._fsRouteType === "loader" ? "loader" : node._fsRouteType === "errorComponent" ? "errorComponent" : node._fsRouteType === "pendingComponent" ? "pendingComponent" : "component"] = node;
|
|
274
|
-
const anchorRoute = routeNodes.find(
|
|
841
|
+
acc.routePiecesByPath[node.routePath] = acc.routePiecesByPath[node.routePath] || {};
|
|
842
|
+
acc.routePiecesByPath[node.routePath][node._fsRouteType === "lazy" ? "lazy" : node._fsRouteType === "loader" ? "loader" : node._fsRouteType === "errorComponent" ? "errorComponent" : node._fsRouteType === "pendingComponent" ? "pendingComponent" : "component"] = node;
|
|
843
|
+
const anchorRoute = acc.routeNodes.find(
|
|
844
|
+
(d) => d.routePath === node.routePath
|
|
845
|
+
);
|
|
275
846
|
if (!anchorRoute) {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
847
|
+
this.handleNode(
|
|
848
|
+
{
|
|
849
|
+
...node,
|
|
850
|
+
isVirtual: true,
|
|
851
|
+
_fsRouteType: "static"
|
|
852
|
+
},
|
|
853
|
+
acc
|
|
854
|
+
);
|
|
281
855
|
}
|
|
282
856
|
return;
|
|
283
857
|
}
|
|
@@ -285,17 +859,17 @@ Add the file in: "${config.routesDirectory}/${rootPathId.rootPathId}.${config.di
|
|
|
285
859
|
const nonPathRoute = node._fsRouteType === "pathless_layout" && node.isNonPath;
|
|
286
860
|
node.isVirtualParentRequired = node._fsRouteType === "pathless_layout" || nonPathRoute ? !cleanedPathIsEmpty : false;
|
|
287
861
|
if (!node.isVirtual && node.isVirtualParentRequired) {
|
|
288
|
-
const parentRoutePath = removeLastSegmentFromPath(node.routePath) || "/";
|
|
862
|
+
const parentRoutePath = utils.removeLastSegmentFromPath(node.routePath) || "/";
|
|
289
863
|
const parentVariableName = utils.routePathToVariable(parentRoutePath);
|
|
290
|
-
const anchorRoute = routeNodes.find(
|
|
864
|
+
const anchorRoute = acc.routeNodes.find(
|
|
291
865
|
(d) => d.routePath === parentRoutePath
|
|
292
866
|
);
|
|
293
867
|
if (!anchorRoute) {
|
|
294
868
|
const parentNode = {
|
|
295
869
|
...node,
|
|
296
|
-
path: removeLastSegmentFromPath(node.path) || "/",
|
|
297
|
-
filePath: removeLastSegmentFromPath(node.filePath) || "/",
|
|
298
|
-
fullPath: removeLastSegmentFromPath(node.fullPath) || "/",
|
|
870
|
+
path: utils.removeLastSegmentFromPath(node.path) || "/",
|
|
871
|
+
filePath: utils.removeLastSegmentFromPath(node.filePath) || "/",
|
|
872
|
+
fullPath: utils.removeLastSegmentFromPath(node.fullPath) || "/",
|
|
299
873
|
routePath: parentRoutePath,
|
|
300
874
|
variableName: parentVariableName,
|
|
301
875
|
isVirtual: true,
|
|
@@ -308,9 +882,9 @@ Add the file in: "${config.routesDirectory}/${rootPathId.rootPathId}.${config.di
|
|
|
308
882
|
parentNode.children.push(node);
|
|
309
883
|
node.parent = parentNode;
|
|
310
884
|
if (node._fsRouteType === "pathless_layout") {
|
|
311
|
-
node.path = determineNodePath(node);
|
|
885
|
+
node.path = utils.determineNodePath(node);
|
|
312
886
|
}
|
|
313
|
-
|
|
887
|
+
this.handleNode(parentNode, acc);
|
|
314
888
|
} else {
|
|
315
889
|
anchorRoute.children = anchorRoute.children ?? [];
|
|
316
890
|
anchorRoute.children.push(node);
|
|
@@ -323,446 +897,35 @@ Add the file in: "${config.routesDirectory}/${rootPathId.rootPathId}.${config.di
|
|
|
323
897
|
node.parent.children.push(node);
|
|
324
898
|
}
|
|
325
899
|
} else {
|
|
326
|
-
routeTree.push(node);
|
|
900
|
+
acc.routeTree.push(node);
|
|
327
901
|
}
|
|
328
|
-
routeNodes.push(node);
|
|
329
|
-
};
|
|
330
|
-
for (const node of preRouteNodes) {
|
|
331
|
-
await handleNode(node);
|
|
332
|
-
}
|
|
333
|
-
checkRouteFullPathUniqueness(
|
|
334
|
-
preRouteNodes.filter(
|
|
335
|
-
(d) => d.children === void 0 && "lazy" !== d._fsRouteType
|
|
336
|
-
),
|
|
337
|
-
config
|
|
338
|
-
);
|
|
339
|
-
function buildRouteTreeConfig(nodes, depth = 1) {
|
|
340
|
-
const children = nodes.map((node) => {
|
|
341
|
-
var _a, _b;
|
|
342
|
-
if (node._fsRouteType === "__root") {
|
|
343
|
-
return;
|
|
344
|
-
}
|
|
345
|
-
if (node._fsRouteType === "pathless_layout" && !((_a = node.children) == null ? void 0 : _a.length)) {
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
const route = `${node.variableName}Route`;
|
|
349
|
-
if ((_b = node.children) == null ? void 0 : _b.length) {
|
|
350
|
-
const childConfigs = buildRouteTreeConfig(node.children, depth + 1);
|
|
351
|
-
const childrenDeclaration = TYPES_DISABLED ? "" : `interface ${route}Children {
|
|
352
|
-
${node.children.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
353
|
-
}`;
|
|
354
|
-
const children2 = `const ${route}Children${TYPES_DISABLED ? "" : `: ${route}Children`} = {
|
|
355
|
-
${node.children.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
356
|
-
}`;
|
|
357
|
-
const routeWithChildren = `const ${route}WithChildren = ${route}._addFileChildren(${route}Children)`;
|
|
358
|
-
return [
|
|
359
|
-
childConfigs,
|
|
360
|
-
childrenDeclaration,
|
|
361
|
-
children2,
|
|
362
|
-
routeWithChildren
|
|
363
|
-
].join("\n\n");
|
|
364
|
-
}
|
|
365
|
-
return void 0;
|
|
366
|
-
});
|
|
367
|
-
return children.filter(Boolean).join("\n\n");
|
|
902
|
+
acc.routeNodes.push(node);
|
|
368
903
|
}
|
|
369
|
-
const routeConfigChildrenText = buildRouteTreeConfig(routeTree);
|
|
370
|
-
const sortedRouteNodes = utils.multiSortBy(routeNodes, [
|
|
371
|
-
(d) => {
|
|
372
|
-
var _a;
|
|
373
|
-
return ((_a = d.routePath) == null ? void 0 : _a.includes(`/${rootPathId.rootPathId}`)) ? -1 : 1;
|
|
374
|
-
},
|
|
375
|
-
(d) => {
|
|
376
|
-
var _a;
|
|
377
|
-
return (_a = d.routePath) == null ? void 0 : _a.split("/").length;
|
|
378
|
-
},
|
|
379
|
-
(d) => {
|
|
380
|
-
var _a;
|
|
381
|
-
return ((_a = d.routePath) == null ? void 0 : _a.endsWith(config.indexToken)) ? -1 : 1;
|
|
382
|
-
},
|
|
383
|
-
(d) => d
|
|
384
|
-
]);
|
|
385
|
-
const typeImports = Object.entries({
|
|
386
|
-
// Used for augmentation of regular routes
|
|
387
|
-
CreateFileRoute: config.verboseFileRoutes === false && sortedRouteNodes.some(
|
|
388
|
-
(d) => isRouteNodeValidForAugmentation(d) && d._fsRouteType !== "lazy"
|
|
389
|
-
),
|
|
390
|
-
// Used for augmentation of lazy (`.lazy`) routes
|
|
391
|
-
CreateLazyFileRoute: config.verboseFileRoutes === false && sortedRouteNodes.some(
|
|
392
|
-
(node) => {
|
|
393
|
-
var _a;
|
|
394
|
-
return ((_a = routePiecesByPath[node.routePath]) == null ? void 0 : _a.lazy) && isRouteNodeValidForAugmentation(node);
|
|
395
|
-
}
|
|
396
|
-
),
|
|
397
|
-
// Used in the process of augmenting the routes
|
|
398
|
-
FileRoutesByPath: config.verboseFileRoutes === false && sortedRouteNodes.some((d) => isRouteNodeValidForAugmentation(d))
|
|
399
|
-
}).filter((d) => d[1]).map((d) => d[0]).sort((a, b) => a.localeCompare(b));
|
|
400
|
-
const imports = Object.entries({
|
|
401
|
-
createFileRoute: sortedRouteNodes.some((d) => d.isVirtual),
|
|
402
|
-
lazyFn: sortedRouteNodes.some(
|
|
403
|
-
(node) => {
|
|
404
|
-
var _a;
|
|
405
|
-
return (_a = routePiecesByPath[node.routePath]) == null ? void 0 : _a.loader;
|
|
406
|
-
}
|
|
407
|
-
),
|
|
408
|
-
lazyRouteComponent: sortedRouteNodes.some(
|
|
409
|
-
(node) => {
|
|
410
|
-
var _a, _b, _c;
|
|
411
|
-
return ((_a = routePiecesByPath[node.routePath]) == null ? void 0 : _a.component) || ((_b = routePiecesByPath[node.routePath]) == null ? void 0 : _b.errorComponent) || ((_c = routePiecesByPath[node.routePath]) == null ? void 0 : _c.pendingComponent);
|
|
412
|
-
}
|
|
413
|
-
)
|
|
414
|
-
}).filter((d) => d[1]).map((d) => d[0]);
|
|
415
|
-
const virtualRouteNodes = sortedRouteNodes.filter((d) => d.isVirtual);
|
|
416
|
-
function getImportPath(node) {
|
|
417
|
-
return utils.replaceBackslash(
|
|
418
|
-
utils.removeExt(
|
|
419
|
-
path.relative(
|
|
420
|
-
path.dirname(config.generatedRouteTree),
|
|
421
|
-
path.resolve(config.routesDirectory, node.filePath)
|
|
422
|
-
),
|
|
423
|
-
config.addExtensions
|
|
424
|
-
)
|
|
425
|
-
);
|
|
426
|
-
}
|
|
427
|
-
const routeImports = [
|
|
428
|
-
...config.routeTreeFileHeader,
|
|
429
|
-
`// This file was automatically generated by TanStack Router.
|
|
430
|
-
// You should NOT make any changes in this file as it will be overwritten.
|
|
431
|
-
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.`,
|
|
432
|
-
[
|
|
433
|
-
imports.length ? `import { ${imports.join(", ")} } from '${ROUTE_TEMPLATE.fullPkg}'` : "",
|
|
434
|
-
!TYPES_DISABLED && typeImports.length ? `import type { ${typeImports.join(", ")} } from '${ROUTE_TEMPLATE.fullPkg}'` : ""
|
|
435
|
-
].filter(Boolean).join("\n"),
|
|
436
|
-
"// Import Routes",
|
|
437
|
-
[
|
|
438
|
-
`import { Route as rootRoute } from './${getImportPath(rootRouteNode)}'`,
|
|
439
|
-
...sortedRouteNodes.filter((d) => !d.isVirtual).map((node) => {
|
|
440
|
-
return `import { Route as ${node.variableName}RouteImport } from './${getImportPath(node)}'`;
|
|
441
|
-
})
|
|
442
|
-
].join("\n"),
|
|
443
|
-
virtualRouteNodes.length ? "// Create Virtual Routes" : "",
|
|
444
|
-
virtualRouteNodes.map((node) => {
|
|
445
|
-
return `const ${node.variableName}RouteImport = createFileRoute('${node.routePath}')()`;
|
|
446
|
-
}).join("\n"),
|
|
447
|
-
"// Create/Update Routes",
|
|
448
|
-
sortedRouteNodes.map((node) => {
|
|
449
|
-
var _a, _b, _c, _d, _e, _f;
|
|
450
|
-
const loaderNode = (_a = routePiecesByPath[node.routePath]) == null ? void 0 : _a.loader;
|
|
451
|
-
const componentNode = (_b = routePiecesByPath[node.routePath]) == null ? void 0 : _b.component;
|
|
452
|
-
const errorComponentNode = (_c = routePiecesByPath[node.routePath]) == null ? void 0 : _c.errorComponent;
|
|
453
|
-
const pendingComponentNode = (_d = routePiecesByPath[node.routePath]) == null ? void 0 : _d.pendingComponent;
|
|
454
|
-
const lazyComponentNode = (_e = routePiecesByPath[node.routePath]) == null ? void 0 : _e.lazy;
|
|
455
|
-
return [
|
|
456
|
-
[
|
|
457
|
-
`const ${node.variableName}Route = ${node.variableName}RouteImport.update({
|
|
458
|
-
${[
|
|
459
|
-
`id: '${node.path}'`,
|
|
460
|
-
!node.isNonPath ? `path: '${node.cleanedPath}'` : void 0,
|
|
461
|
-
`getParentRoute: () => ${((_f = node.parent) == null ? void 0 : _f.variableName) ?? "root"}Route`
|
|
462
|
-
].filter(Boolean).join(",")}
|
|
463
|
-
}${TYPES_DISABLED ? "" : "as any"})`,
|
|
464
|
-
loaderNode ? `.updateLoader({ loader: lazyFn(() => import('./${utils.replaceBackslash(
|
|
465
|
-
utils.removeExt(
|
|
466
|
-
path.relative(
|
|
467
|
-
path.dirname(config.generatedRouteTree),
|
|
468
|
-
path.resolve(config.routesDirectory, loaderNode.filePath)
|
|
469
|
-
),
|
|
470
|
-
config.addExtensions
|
|
471
|
-
)
|
|
472
|
-
)}'), 'loader') })` : "",
|
|
473
|
-
componentNode || errorComponentNode || pendingComponentNode ? `.update({
|
|
474
|
-
${[
|
|
475
|
-
["component", componentNode],
|
|
476
|
-
["errorComponent", errorComponentNode],
|
|
477
|
-
["pendingComponent", pendingComponentNode]
|
|
478
|
-
].filter((d) => d[1]).map((d) => {
|
|
479
|
-
return `${d[0]}: lazyRouteComponent(() => import('./${utils.replaceBackslash(
|
|
480
|
-
utils.removeExt(
|
|
481
|
-
path.relative(
|
|
482
|
-
path.dirname(config.generatedRouteTree),
|
|
483
|
-
path.resolve(config.routesDirectory, d[1].filePath)
|
|
484
|
-
),
|
|
485
|
-
config.addExtensions
|
|
486
|
-
)
|
|
487
|
-
)}'), '${d[0]}')`;
|
|
488
|
-
}).join("\n,")}
|
|
489
|
-
})` : "",
|
|
490
|
-
lazyComponentNode ? `.lazy(() => import('./${utils.replaceBackslash(
|
|
491
|
-
utils.removeExt(
|
|
492
|
-
path.relative(
|
|
493
|
-
path.dirname(config.generatedRouteTree),
|
|
494
|
-
path.resolve(
|
|
495
|
-
config.routesDirectory,
|
|
496
|
-
lazyComponentNode.filePath
|
|
497
|
-
)
|
|
498
|
-
),
|
|
499
|
-
config.addExtensions
|
|
500
|
-
)
|
|
501
|
-
)}').then((d) => d.Route))` : ""
|
|
502
|
-
].join("")
|
|
503
|
-
].join("\n\n");
|
|
504
|
-
}).join("\n\n"),
|
|
505
|
-
...TYPES_DISABLED ? [] : [
|
|
506
|
-
"// Populate the FileRoutesByPath interface",
|
|
507
|
-
`declare module '${ROUTE_TEMPLATE.fullPkg}' {
|
|
508
|
-
interface FileRoutesByPath {
|
|
509
|
-
${routeNodes.map((routeNode) => {
|
|
510
|
-
var _a, _b;
|
|
511
|
-
const filePathId = routeNode.routePath;
|
|
512
|
-
return `'${filePathId}': {
|
|
513
|
-
id: '${filePathId}'
|
|
514
|
-
path: '${inferPath(routeNode)}'
|
|
515
|
-
fullPath: '${inferFullPath(routeNode)}'
|
|
516
|
-
preLoaderRoute: typeof ${routeNode.variableName}RouteImport
|
|
517
|
-
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"}
|
|
518
|
-
}`;
|
|
519
|
-
}).join("\n")}
|
|
520
|
-
}
|
|
521
|
-
}`
|
|
522
|
-
],
|
|
523
|
-
...TYPES_DISABLED ? [] : config.verboseFileRoutes !== false ? [] : [
|
|
524
|
-
`// Add type-safety to the createFileRoute function across the route tree`,
|
|
525
|
-
routeNodes.map((routeNode) => {
|
|
526
|
-
var _a;
|
|
527
|
-
function getModuleDeclaration(routeNode2) {
|
|
528
|
-
if (!isRouteNodeValidForAugmentation(routeNode2)) {
|
|
529
|
-
return "";
|
|
530
|
-
}
|
|
531
|
-
return `declare module './${getImportPath(routeNode2)}' {
|
|
532
|
-
const ${routeNode2._fsRouteType === "lazy" ? "createLazyFileRoute" : "createFileRoute"}: ${routeNode2._fsRouteType === "lazy" ? `CreateLazyFileRoute<FileRoutesByPath['${routeNode2.routePath}']['preLoaderRoute']>}` : `CreateFileRoute<
|
|
533
|
-
'${routeNode2.routePath}',
|
|
534
|
-
FileRoutesByPath['${routeNode2.routePath}']['parentRoute'],
|
|
535
|
-
FileRoutesByPath['${routeNode2.routePath}']['id'],
|
|
536
|
-
FileRoutesByPath['${routeNode2.routePath}']['path'],
|
|
537
|
-
FileRoutesByPath['${routeNode2.routePath}']['fullPath']
|
|
538
|
-
>
|
|
539
|
-
}`}`;
|
|
540
|
-
}
|
|
541
|
-
return getModuleDeclaration(routeNode) + getModuleDeclaration(
|
|
542
|
-
(_a = routePiecesByPath[routeNode.routePath]) == null ? void 0 : _a.lazy
|
|
543
|
-
);
|
|
544
|
-
}).join("\n")
|
|
545
|
-
],
|
|
546
|
-
"// Create and export the route tree",
|
|
547
|
-
routeConfigChildrenText,
|
|
548
|
-
...TYPES_DISABLED ? [] : [
|
|
549
|
-
`export interface FileRoutesByFullPath {
|
|
550
|
-
${[...createRouteNodesByFullPath(routeNodes).entries()].map(
|
|
551
|
-
([fullPath, routeNode]) => {
|
|
552
|
-
return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
|
|
553
|
-
}
|
|
554
|
-
)}
|
|
555
|
-
}`,
|
|
556
|
-
`export interface FileRoutesByTo {
|
|
557
|
-
${[...createRouteNodesByTo(routeNodes).entries()].map(([to, routeNode]) => {
|
|
558
|
-
return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
|
|
559
|
-
})}
|
|
560
|
-
}`,
|
|
561
|
-
`export interface FileRoutesById {
|
|
562
|
-
'${rootRouteId}': typeof rootRoute,
|
|
563
|
-
${[...createRouteNodesById(routeNodes).entries()].map(([id, routeNode]) => {
|
|
564
|
-
return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
|
|
565
|
-
})}
|
|
566
|
-
}`,
|
|
567
|
-
`export interface FileRouteTypes {
|
|
568
|
-
fileRoutesByFullPath: FileRoutesByFullPath
|
|
569
|
-
fullPaths: ${routeNodes.length > 0 ? [...createRouteNodesByFullPath(routeNodes).keys()].map((fullPath) => `'${fullPath}'`).join("|") : "never"}
|
|
570
|
-
fileRoutesByTo: FileRoutesByTo
|
|
571
|
-
to: ${routeNodes.length > 0 ? [...createRouteNodesByTo(routeNodes).keys()].map((to) => `'${to}'`).join("|") : "never"}
|
|
572
|
-
id: ${[`'${rootRouteId}'`, ...[...createRouteNodesById(routeNodes).keys()].map((id) => `'${id}'`)].join("|")}
|
|
573
|
-
fileRoutesById: FileRoutesById
|
|
574
|
-
}`,
|
|
575
|
-
`export interface RootRouteChildren {
|
|
576
|
-
${routeTree.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
577
|
-
}`
|
|
578
|
-
],
|
|
579
|
-
`const rootRouteChildren${TYPES_DISABLED ? "" : ": RootRouteChildren"} = {
|
|
580
|
-
${routeTree.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
581
|
-
}`,
|
|
582
|
-
`export const routeTree = rootRoute._addFileChildren(rootRouteChildren)${TYPES_DISABLED ? "" : "._addFileTypes<FileRouteTypes>()"}`,
|
|
583
|
-
...config.routeTreeFileFooter
|
|
584
|
-
].filter(Boolean).join("\n\n");
|
|
585
|
-
const createRouteManifest = () => {
|
|
586
|
-
const routesManifest = {
|
|
587
|
-
[rootRouteId]: {
|
|
588
|
-
filePath: rootRouteNode.filePath,
|
|
589
|
-
children: routeTree.map((d) => d.routePath)
|
|
590
|
-
},
|
|
591
|
-
...Object.fromEntries(
|
|
592
|
-
routeNodes.map((d) => {
|
|
593
|
-
var _a, _b;
|
|
594
|
-
const filePathId = d.routePath;
|
|
595
|
-
return [
|
|
596
|
-
filePathId,
|
|
597
|
-
{
|
|
598
|
-
filePath: d.filePath,
|
|
599
|
-
parent: ((_a = d.parent) == null ? void 0 : _a.routePath) ? d.parent.routePath : void 0,
|
|
600
|
-
children: (_b = d.children) == null ? void 0 : _b.map((childRoute) => childRoute.routePath)
|
|
601
|
-
}
|
|
602
|
-
];
|
|
603
|
-
})
|
|
604
|
-
)
|
|
605
|
-
};
|
|
606
|
-
return JSON.stringify(
|
|
607
|
-
{
|
|
608
|
-
routes: routesManifest
|
|
609
|
-
},
|
|
610
|
-
null,
|
|
611
|
-
2
|
|
612
|
-
);
|
|
613
|
-
};
|
|
614
|
-
const includeManifest = ["react", "solid"];
|
|
615
|
-
const routeConfigFileContent = config.disableManifestGeneration || !includeManifest.includes(config.target) ? routeImports : [
|
|
616
|
-
routeImports,
|
|
617
|
-
"\n",
|
|
618
|
-
"/* ROUTE_MANIFEST_START",
|
|
619
|
-
createRouteManifest(),
|
|
620
|
-
"ROUTE_MANIFEST_END */"
|
|
621
|
-
].join("\n");
|
|
622
|
-
if (!checkLatest()) return;
|
|
623
|
-
const existingRouteTreeContent = await fsp__namespace.readFile(path.resolve(config.generatedRouteTree), "utf-8").catch((err) => {
|
|
624
|
-
if (err.code === "ENOENT") {
|
|
625
|
-
return "";
|
|
626
|
-
}
|
|
627
|
-
throw err;
|
|
628
|
-
});
|
|
629
|
-
if (!checkLatest()) return;
|
|
630
|
-
await fsp__namespace.mkdir(path.dirname(path.resolve(config.generatedRouteTree)), {
|
|
631
|
-
recursive: true
|
|
632
|
-
});
|
|
633
|
-
if (!checkLatest()) return;
|
|
634
|
-
const routeTreeWriteResult = await utils.writeIfDifferent(
|
|
635
|
-
path.resolve(config.generatedRouteTree),
|
|
636
|
-
config.enableRouteTreeFormatting ? await utils.format(existingRouteTreeContent, config) : existingRouteTreeContent,
|
|
637
|
-
config.enableRouteTreeFormatting ? await utils.format(routeConfigFileContent, config) : routeConfigFileContent,
|
|
638
|
-
{
|
|
639
|
-
beforeWrite: () => {
|
|
640
|
-
logger.log(`🟡 Updating ${config.generatedRouteTree}`);
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
);
|
|
644
|
-
if (routeTreeWriteResult && !checkLatest()) {
|
|
645
|
-
return;
|
|
646
|
-
}
|
|
647
|
-
logger.log(
|
|
648
|
-
`✅ Processed ${routeNodes.length === 1 ? "route" : "routes"} in ${Date.now() - start}ms`
|
|
649
|
-
);
|
|
650
904
|
}
|
|
651
|
-
function
|
|
652
|
-
return
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
if (!routeNode || routeNode.isVirtual) {
|
|
656
|
-
return false;
|
|
657
|
-
}
|
|
658
|
-
return true;
|
|
659
|
-
}
|
|
660
|
-
function determineNodePath(node) {
|
|
661
|
-
var _a;
|
|
662
|
-
return node.path = node.parent ? ((_a = node.routePath) == null ? void 0 : _a.replace(node.parent.routePath ?? "", "")) || "/" : node.routePath;
|
|
663
|
-
}
|
|
664
|
-
function removeLastSegmentFromPath(routePath = "/") {
|
|
665
|
-
const segments = routePath.split("/");
|
|
666
|
-
segments.pop();
|
|
667
|
-
return segments.join("/");
|
|
668
|
-
}
|
|
669
|
-
function removeLayoutSegments(routePath = "/") {
|
|
670
|
-
const segments = routePath.split("/");
|
|
671
|
-
const newSegments = segments.filter((segment) => !segment.startsWith("_"));
|
|
672
|
-
return newSegments.join("/");
|
|
673
|
-
}
|
|
674
|
-
function hasParentRoute(routes, node, routePathToCheck) {
|
|
675
|
-
if (!routePathToCheck || routePathToCheck === "/") {
|
|
676
|
-
return null;
|
|
677
|
-
}
|
|
678
|
-
const sortedNodes = utils.multiSortBy(routes, [
|
|
679
|
-
(d) => d.routePath.length * -1,
|
|
680
|
-
(d) => d.variableName
|
|
681
|
-
]).filter((d) => d.routePath !== `/${rootPathId.rootPathId}`);
|
|
682
|
-
for (const route of sortedNodes) {
|
|
683
|
-
if (route.routePath === "/") continue;
|
|
684
|
-
if (routePathToCheck.startsWith(`${route.routePath}/`) && route.routePath !== routePathToCheck) {
|
|
685
|
-
return route;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
const segments = routePathToCheck.split("/");
|
|
689
|
-
segments.pop();
|
|
690
|
-
const parentRoutePath = segments.join("/");
|
|
691
|
-
return hasParentRoute(routes, node, parentRoutePath);
|
|
692
|
-
}
|
|
693
|
-
const getResolvedRouteNodeVariableName = (routeNode) => {
|
|
694
|
-
var _a;
|
|
695
|
-
return ((_a = routeNode.children) == null ? void 0 : _a.length) ? `${routeNode.variableName}RouteWithChildren` : `${routeNode.variableName}Route`;
|
|
696
|
-
};
|
|
697
|
-
const createRouteNodesByFullPath = (routeNodes) => {
|
|
698
|
-
return new Map(
|
|
699
|
-
routeNodes.map((routeNode) => [inferFullPath(routeNode), routeNode])
|
|
700
|
-
);
|
|
701
|
-
};
|
|
702
|
-
const createRouteNodesByTo = (routeNodes) => {
|
|
703
|
-
return new Map(
|
|
704
|
-
dedupeBranchesAndIndexRoutes(routeNodes).map((routeNode) => [
|
|
705
|
-
inferTo(routeNode),
|
|
706
|
-
routeNode
|
|
707
|
-
])
|
|
708
|
-
);
|
|
709
|
-
};
|
|
710
|
-
const createRouteNodesById = (routeNodes) => {
|
|
711
|
-
return new Map(
|
|
712
|
-
routeNodes.map((routeNode) => {
|
|
713
|
-
const id = routeNode.routePath ?? "";
|
|
714
|
-
return [id, routeNode];
|
|
715
|
-
})
|
|
716
|
-
);
|
|
717
|
-
};
|
|
718
|
-
const inferFullPath = (routeNode) => {
|
|
719
|
-
const fullPath = removeGroups(
|
|
720
|
-
utils.removeUnderscores(removeLayoutSegments(routeNode.routePath)) ?? ""
|
|
721
|
-
);
|
|
722
|
-
return routeNode.cleanedPath === "/" ? fullPath : fullPath.replace(/\/$/, "");
|
|
723
|
-
};
|
|
724
|
-
const inferPath = (routeNode) => {
|
|
725
|
-
var _a;
|
|
726
|
-
return routeNode.cleanedPath === "/" ? routeNode.cleanedPath : ((_a = routeNode.cleanedPath) == null ? void 0 : _a.replace(/\/$/, "")) ?? "";
|
|
727
|
-
};
|
|
728
|
-
const inferTo = (routeNode) => {
|
|
729
|
-
const fullPath = inferFullPath(routeNode);
|
|
730
|
-
if (fullPath === "/") return fullPath;
|
|
731
|
-
return fullPath.replace(/\/$/, "");
|
|
732
|
-
};
|
|
733
|
-
const dedupeBranchesAndIndexRoutes = (routes) => {
|
|
734
|
-
return routes.filter((route) => {
|
|
905
|
+
function buildFileRoutesByPathInterface(opts) {
|
|
906
|
+
return `declare module '${opts.module}' {
|
|
907
|
+
interface ${opts.interfaceName} {
|
|
908
|
+
${opts.routeNodes.map((routeNode) => {
|
|
735
909
|
var _a;
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
}
|
|
752
|
-
function checkRouteFullPathUniqueness(_routes, config) {
|
|
753
|
-
const routes = _routes.map((d) => {
|
|
754
|
-
const inferredFullPath = inferFullPath(d);
|
|
755
|
-
return { ...d, inferredFullPath };
|
|
756
|
-
});
|
|
757
|
-
const conflictingFiles = checkUnique(routes, "inferredFullPath");
|
|
758
|
-
if (conflictingFiles !== void 0) {
|
|
759
|
-
const errorMessage = `Conflicting configuration paths were found for the following route${conflictingFiles.length > 1 ? "s" : ""}: ${conflictingFiles.map((p) => `"${p.inferredFullPath}"`).join(", ")}.
|
|
760
|
-
Please ensure each Route has a unique full path.
|
|
761
|
-
Conflicting files:
|
|
762
|
-
${conflictingFiles.map((d) => path.resolve(config.routesDirectory, d.filePath)).join("\n ")}
|
|
763
|
-
`;
|
|
764
|
-
throw new Error(errorMessage);
|
|
910
|
+
const filePathId = routeNode.routePath;
|
|
911
|
+
let preloaderRoute = "";
|
|
912
|
+
if ((_a = routeNode.exports) == null ? void 0 : _a.includes(opts.exportName)) {
|
|
913
|
+
preloaderRoute = `typeof ${routeNode.variableName}${opts.exportName}Import`;
|
|
914
|
+
} else {
|
|
915
|
+
preloaderRoute = "unknown";
|
|
916
|
+
}
|
|
917
|
+
const parent = utils.findParent(routeNode, opts.exportName);
|
|
918
|
+
return `'${filePathId}': {
|
|
919
|
+
id: '${filePathId}'
|
|
920
|
+
path: '${utils.inferPath(routeNode)}'
|
|
921
|
+
fullPath: '${utils.inferFullPath(routeNode)}'
|
|
922
|
+
preLoaderRoute: ${preloaderRoute}
|
|
923
|
+
parentRoute: typeof ${parent}
|
|
924
|
+
}`;
|
|
925
|
+
}).join("\n")}
|
|
765
926
|
}
|
|
927
|
+
}`;
|
|
766
928
|
}
|
|
767
|
-
exports.
|
|
929
|
+
exports.Generator = Generator;
|
|
930
|
+
exports.buildFileRoutesByPathInterface = buildFileRoutesByPathInterface;
|
|
768
931
|
//# sourceMappingURL=generator.cjs.map
|