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