@tanstack/router-generator 1.121.0-alpha.27 → 1.121.0-alpha.28

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.
Files changed (67) hide show
  1. package/dist/cjs/config.cjs +1 -3
  2. package/dist/cjs/config.cjs.map +1 -1
  3. package/dist/cjs/config.d.cts +3 -3
  4. package/dist/cjs/filesystem/physical/getRouteNodes.cjs +18 -4
  5. package/dist/cjs/filesystem/physical/getRouteNodes.cjs.map +1 -1
  6. package/dist/cjs/filesystem/physical/getRouteNodes.d.cts +1 -0
  7. package/dist/cjs/filesystem/virtual/config.cjs.map +1 -1
  8. package/dist/cjs/filesystem/virtual/getRouteNodes.cjs +18 -12
  9. package/dist/cjs/filesystem/virtual/getRouteNodes.cjs.map +1 -1
  10. package/dist/cjs/filesystem/virtual/getRouteNodes.d.cts +4 -1
  11. package/dist/cjs/filesystem/virtual/loadConfigFile.cjs.map +1 -1
  12. package/dist/cjs/generator.cjs +144 -97
  13. package/dist/cjs/generator.cjs.map +1 -1
  14. package/dist/cjs/generator.d.cts +11 -9
  15. package/dist/cjs/index.d.cts +1 -1
  16. package/dist/cjs/logger.cjs.map +1 -1
  17. package/dist/cjs/plugin/default-generator-plugin.cjs +16 -10
  18. package/dist/cjs/plugin/default-generator-plugin.cjs.map +1 -1
  19. package/dist/cjs/template.cjs.map +1 -1
  20. package/dist/cjs/transform/default-transform-plugin.cjs +6 -4
  21. package/dist/cjs/transform/default-transform-plugin.cjs.map +1 -1
  22. package/dist/cjs/transform/transform.cjs +41 -20
  23. package/dist/cjs/transform/transform.cjs.map +1 -1
  24. package/dist/cjs/transform/utils.cjs.map +1 -1
  25. package/dist/cjs/types.d.cts +5 -0
  26. package/dist/cjs/utils.cjs +43 -24
  27. package/dist/cjs/utils.cjs.map +1 -1
  28. package/dist/cjs/utils.d.cts +6 -0
  29. package/dist/esm/config.d.ts +3 -3
  30. package/dist/esm/config.js +2 -4
  31. package/dist/esm/config.js.map +1 -1
  32. package/dist/esm/filesystem/physical/getRouteNodes.d.ts +1 -0
  33. package/dist/esm/filesystem/physical/getRouteNodes.js +19 -5
  34. package/dist/esm/filesystem/physical/getRouteNodes.js.map +1 -1
  35. package/dist/esm/filesystem/virtual/config.js.map +1 -1
  36. package/dist/esm/filesystem/virtual/getRouteNodes.d.ts +4 -1
  37. package/dist/esm/filesystem/virtual/getRouteNodes.js +19 -13
  38. package/dist/esm/filesystem/virtual/getRouteNodes.js.map +1 -1
  39. package/dist/esm/filesystem/virtual/loadConfigFile.js.map +1 -1
  40. package/dist/esm/generator.d.ts +11 -9
  41. package/dist/esm/generator.js +147 -100
  42. package/dist/esm/generator.js.map +1 -1
  43. package/dist/esm/index.d.ts +1 -1
  44. package/dist/esm/logger.js.map +1 -1
  45. package/dist/esm/plugin/default-generator-plugin.js +16 -10
  46. package/dist/esm/plugin/default-generator-plugin.js.map +1 -1
  47. package/dist/esm/template.js.map +1 -1
  48. package/dist/esm/transform/default-transform-plugin.js +6 -4
  49. package/dist/esm/transform/default-transform-plugin.js.map +1 -1
  50. package/dist/esm/transform/transform.js +41 -20
  51. package/dist/esm/transform/transform.js.map +1 -1
  52. package/dist/esm/transform/utils.js.map +1 -1
  53. package/dist/esm/types.d.ts +5 -0
  54. package/dist/esm/utils.d.ts +6 -0
  55. package/dist/esm/utils.js +43 -24
  56. package/dist/esm/utils.js.map +1 -1
  57. package/package.json +5 -5
  58. package/src/config.ts +1 -2
  59. package/src/filesystem/physical/getRouteNodes.ts +31 -11
  60. package/src/filesystem/virtual/getRouteNodes.ts +32 -23
  61. package/src/generator.ts +193 -71
  62. package/src/index.ts +2 -0
  63. package/src/plugin/default-generator-plugin.ts +16 -3
  64. package/src/transform/default-transform-plugin.ts +5 -2
  65. package/src/transform/transform.ts +59 -25
  66. package/src/types.ts +7 -0
  67. package/src/utils.ts +79 -31
@@ -1,19 +1,26 @@
1
1
  import path from "node:path";
2
2
  import * as fsp from "node:fs/promises";
3
- import { mkdtempSync } from "node:fs";
3
+ import { mkdirSync } from "node:fs";
4
4
  import crypto from "node:crypto";
5
5
  import { deepEqual, rootRouteId } from "@tanstack/router-core";
6
6
  import { logging } from "./logger.js";
7
- import { getRouteNodes as getRouteNodes$1 } from "./filesystem/physical/getRouteNodes.js";
7
+ import { getRouteNodes as getRouteNodes$1, isVirtualConfigFile } from "./filesystem/physical/getRouteNodes.js";
8
8
  import { getRouteNodes } from "./filesystem/virtual/getRouteNodes.js";
9
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, lowerCaseFirstChar, isRouteNodeValidForAugmentation, inferPath, inferFullPath } from "./utils.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
11
  import { getTargetTemplate, fillTemplate } from "./template.js";
12
12
  import { transform } from "./transform/transform.js";
13
13
  import { defaultGeneratorPlugin } from "./plugin/default-generator-plugin.js";
14
14
  const DefaultFileSystem = {
15
- stat: (filePath) => fsp.stat(filePath, { bigint: true }),
16
- mkdtempSync,
15
+ stat: async (filePath) => {
16
+ const res = await fsp.stat(filePath, { bigint: true });
17
+ return {
18
+ mtimeMs: res.mtimeMs,
19
+ mode: Number(res.mode),
20
+ uid: Number(res.uid),
21
+ gid: Number(res.gid)
22
+ };
23
+ },
17
24
  rename: (oldPath, newPath) => fsp.rename(oldPath, newPath),
18
25
  writeFile: (filePath, content) => fsp.writeFile(filePath, content),
19
26
  readFile: async (filePath) => {
@@ -31,7 +38,9 @@ const DefaultFileSystem = {
31
38
  }
32
39
  throw e;
33
40
  }
34
- }
41
+ },
42
+ chmod: (filePath, mode) => fsp.chmod(filePath, mode),
43
+ chown: (filePath, uid, gid) => fsp.chown(filePath, uid, gid)
35
44
  };
36
45
  function rerun(opts) {
37
46
  const { event, ...rest } = opts;
@@ -49,13 +58,11 @@ class Generator {
49
58
  this.pluginsWithTransform = [];
50
59
  this.transformPlugins = [];
51
60
  this.routeGroupPatternRegex = /\(.+\)/g;
61
+ this.physicalDirectories = [];
52
62
  this.config = opts.config;
53
63
  this.logger = logging({ disabled: this.config.disableLogging });
54
64
  this.root = opts.root;
55
65
  this.fs = opts.fs || DefaultFileSystem;
56
- this.tmpDir = this.fs.mkdtempSync(
57
- path.join(this.config.tmpDir, "router-generator-")
58
- );
59
66
  this.generatedRouteTreePath = path.resolve(this.config.generatedRouteTree);
60
67
  this.targetTemplate = getTargetTemplate(this.config);
61
68
  this.routesDirectoryPath = this.getRoutesDirectoryPath();
@@ -75,11 +82,17 @@ class Generator {
75
82
  getRoutesDirectoryPath() {
76
83
  return path.isAbsolute(this.config.routesDirectory) ? this.config.routesDirectory : path.resolve(this.root, this.config.routesDirectory);
77
84
  }
85
+ getRoutesByFileMap() {
86
+ return new Map(
87
+ [...this.routeNodeCache.entries()].map(([filePath, cacheEntry]) => [
88
+ filePath,
89
+ { routePath: cacheEntry.routeId }
90
+ ])
91
+ );
92
+ }
78
93
  async run(event) {
79
- if (event && event.type !== "rerun") {
80
- if (!(event.path === this.generatedRouteTreePath || event.path.startsWith(this.routesDirectoryPath))) {
81
- return;
82
- }
94
+ if (event && event.type !== "rerun" && !this.isFileRelevantForRouteTreeGeneration(event.path)) {
95
+ return;
83
96
  }
84
97
  this.fileEventQueue.push(event ?? { type: "rerun" });
85
98
  if (this.runPromise) {
@@ -150,7 +163,11 @@ class Generator {
150
163
  } else {
151
164
  getRouteNodesResult = await getRouteNodes$1(this.config, this.root);
152
165
  }
153
- const { rootRouteNode, routeNodes: beforeRouteNodes } = getRouteNodesResult;
166
+ const {
167
+ rootRouteNode,
168
+ routeNodes: beforeRouteNodes,
169
+ physicalDirectories
170
+ } = getRouteNodesResult;
154
171
  if (rootRouteNode === void 0) {
155
172
  let errorMessage = `rootRouteNode must not be undefined. Make sure you've added your root route into the route-tree.`;
156
173
  if (!this.config.virtualRouteConfig) {
@@ -160,22 +177,17 @@ Add the file in: "${this.config.routesDirectory}/${rootPathId}.${this.config.dis
160
177
  }
161
178
  throw new Error(errorMessage);
162
179
  }
180
+ this.physicalDirectories = physicalDirectories;
163
181
  writeRouteTreeFile = await this.handleRootNode(rootRouteNode);
164
182
  const preRouteNodes = multiSortBy(beforeRouteNodes, [
165
183
  (d) => d.routePath === "/" ? -1 : 1,
166
- (d) => {
167
- var _a;
168
- return (_a = d.routePath) == null ? void 0 : _a.split("/").length;
169
- },
184
+ (d) => d.routePath?.split("/").length,
170
185
  (d) => d.filePath.match(new RegExp(`[./]${this.config.indexToken}[.]`)) ? 1 : -1,
171
186
  (d) => d.filePath.match(
172
187
  /[./](component|errorComponent|pendingComponent|loader|lazy)[.]/
173
188
  ) ? 1 : -1,
174
189
  (d) => d.filePath.match(new RegExp(`[./]${this.config.routeToken}[.]`)) ? -1 : 1,
175
- (d) => {
176
- var _a;
177
- return ((_a = d.routePath) == null ? void 0 : _a.endsWith("/")) ? -1 : 1;
178
- },
190
+ (d) => d.routePath?.endsWith("/") ? -1 : 1,
179
191
  (d) => d.routePath
180
192
  ]).filter((d) => ![`/${rootPathId}`].includes(d.routePath || ""));
181
193
  const routeFileAllResult = await Promise.allSettled(
@@ -194,8 +206,7 @@ Add the file in: "${this.config.routesDirectory}/${rootPathId}.${this.config.dis
194
206
  return [];
195
207
  });
196
208
  routeFileResult.forEach((result) => {
197
- var _a;
198
- if (!((_a = result.node.exports) == null ? void 0 : _a.length)) {
209
+ if (!result.node.exports?.length) {
199
210
  this.logger.warn(
200
211
  `Route file "${result.cacheEntry.fileContent}" does not export any route piece. This is likely a mistake.`
201
212
  );
@@ -213,8 +224,36 @@ Add the file in: "${this.config.routesDirectory}/${rootPathId}.${this.config.dis
213
224
  };
214
225
  }
215
226
  writeRouteTreeFile = true;
227
+ } else {
228
+ const routeTreeFileChange = await this.didFileChangeComparedToCache(
229
+ { path: this.generatedRouteTreePath },
230
+ this.routeTreeFileCache
231
+ );
232
+ if (routeTreeFileChange.result !== false) {
233
+ writeRouteTreeFile = "force";
234
+ if (routeTreeFileChange.result === true) {
235
+ const routeTreeFile = await this.fs.readFile(
236
+ this.generatedRouteTreePath
237
+ );
238
+ if (routeTreeFile !== "file-not-existing") {
239
+ this.routeTreeFileCache = {
240
+ fileContent: routeTreeFile.fileContent,
241
+ mtimeMs: routeTreeFile.stat.mtimeMs
242
+ };
243
+ }
244
+ }
245
+ }
216
246
  }
217
247
  if (!writeRouteTreeFile) {
248
+ for (const fullPath of this.routeNodeCache.keys()) {
249
+ if (!this.routeNodeShadowCache.has(fullPath)) {
250
+ writeRouteTreeFile = true;
251
+ break;
252
+ }
253
+ }
254
+ }
255
+ if (!writeRouteTreeFile) {
256
+ this.swapCaches();
218
257
  return;
219
258
  }
220
259
  let routeTreeContent = this.buildRouteTreeFileContent(
@@ -225,7 +264,7 @@ Add the file in: "${this.config.routesDirectory}/${rootPathId}.${this.config.dis
225
264
  routeTreeContent = this.config.enableRouteTreeFormatting ? await format(routeTreeContent, this.config) : routeTreeContent;
226
265
  let newMtimeMs;
227
266
  if (this.routeTreeFileCache) {
228
- if (this.routeTreeFileCache.fileContent === routeTreeContent) ;
267
+ if (writeRouteTreeFile !== "force" && this.routeTreeFileCache.fileContent === routeTreeContent) ;
229
268
  else {
230
269
  const newRouteTreeFileStat = await this.safeFileWrite({
231
270
  filePath: this.generatedRouteTreePath,
@@ -253,13 +292,15 @@ Add the file in: "${this.config.routesDirectory}/${rootPathId}.${this.config.dis
253
292
  mtimeMs: newMtimeMs
254
293
  };
255
294
  }
295
+ this.swapCaches();
296
+ }
297
+ swapCaches() {
256
298
  this.routeNodeCache = this.routeNodeShadowCache;
257
299
  this.routeNodeShadowCache = /* @__PURE__ */ new Map();
258
300
  }
259
301
  buildRouteTreeFileContent(rootRouteNode, preRouteNodes, routeFileResult) {
260
302
  const getImportForRouteNode = (node, exportName) => {
261
- var _a;
262
- if ((_a = node.exports) == null ? void 0 : _a.includes(exportName)) {
303
+ if (node.exports?.includes(exportName)) {
263
304
  return {
264
305
  source: `./${this.getImportPath(node)}`,
265
306
  specifiers: [
@@ -273,7 +314,6 @@ Add the file in: "${this.config.routesDirectory}/${rootPathId}.${this.config.dis
273
314
  return void 0;
274
315
  };
275
316
  const buildRouteTreeForExport = (plugin) => {
276
- var _a, _b, _c;
277
317
  const exportName = plugin.transformPlugin.exportName;
278
318
  const acc = {
279
319
  routeTree: [],
@@ -281,23 +321,14 @@ Add the file in: "${this.config.routesDirectory}/${rootPathId}.${this.config.dis
281
321
  routePiecesByPath: {}
282
322
  };
283
323
  for (const node of preRouteNodes) {
284
- if ((_a = node.exports) == null ? void 0 : _a.includes(plugin.transformPlugin.exportName)) {
324
+ if (node.exports?.includes(plugin.transformPlugin.exportName)) {
285
325
  this.handleNode(node, acc);
286
326
  }
287
327
  }
288
328
  const sortedRouteNodes = multiSortBy(acc.routeNodes, [
289
- (d) => {
290
- var _a2;
291
- return ((_a2 = d.routePath) == null ? void 0 : _a2.includes(`/${rootPathId}`)) ? -1 : 1;
292
- },
293
- (d) => {
294
- var _a2;
295
- return (_a2 = d.routePath) == null ? void 0 : _a2.split("/").length;
296
- },
297
- (d) => {
298
- var _a2;
299
- return ((_a2 = d.routePath) == null ? void 0 : _a2.endsWith(this.config.indexToken)) ? -1 : 1;
300
- },
329
+ (d) => d.routePath?.includes(`/${rootPathId}`) ? -1 : 1,
330
+ (d) => d.routePath?.split("/").length,
331
+ (d) => d.routePath?.endsWith(this.config.indexToken) ? -1 : 1,
301
332
  (d) => d
302
333
  ]);
303
334
  const pluginConfig = plugin.config({
@@ -306,11 +337,11 @@ Add the file in: "${this.config.routesDirectory}/${rootPathId}.${this.config.dis
306
337
  sortedRouteNodes
307
338
  });
308
339
  const routeImports2 = sortedRouteNodes.filter((d) => !d.isVirtual).flatMap((node) => getImportForRouteNode(node, exportName) ?? []);
309
- const hasMatchingRouteFiles = acc.routeNodes.length > 0 || ((_b = rootRouteNode.exports) == null ? void 0 : _b.includes(exportName));
340
+ const hasMatchingRouteFiles = acc.routeNodes.length > 0 || rootRouteNode.exports?.includes(exportName);
310
341
  const virtualRouteNodes = sortedRouteNodes.filter((d) => d.isVirtual).map((node) => {
311
342
  return `const ${node.variableName}${exportName}Import = ${plugin.createVirtualRouteCode({ node })}`;
312
343
  });
313
- if (!((_c = rootRouteNode.exports) == null ? void 0 : _c.includes(exportName)) && pluginConfig.virtualRootRoute) {
344
+ if (!rootRouteNode.exports?.includes(exportName) && pluginConfig.virtualRootRoute) {
314
345
  virtualRouteNodes.unshift(
315
346
  `const ${rootRouteNode.variableName}${exportName}Import = ${plugin.createRootRouteCode()}`
316
347
  );
@@ -327,12 +358,11 @@ Add the file in: "${this.config.routesDirectory}/${rootPathId}.${this.config.dis
327
358
  this.config.disableTypes
328
359
  );
329
360
  const createUpdateRoutes = sortedRouteNodes.map((node) => {
330
- var _a2, _b2, _c2, _d, _e;
331
- const loaderNode = (_a2 = acc.routePiecesByPath[node.routePath]) == null ? void 0 : _a2.loader;
332
- const componentNode = (_b2 = acc.routePiecesByPath[node.routePath]) == null ? void 0 : _b2.component;
333
- const errorComponentNode = (_c2 = acc.routePiecesByPath[node.routePath]) == null ? void 0 : _c2.errorComponent;
334
- const pendingComponentNode = (_d = acc.routePiecesByPath[node.routePath]) == null ? void 0 : _d.pendingComponent;
335
- const lazyComponentNode = (_e = acc.routePiecesByPath[node.routePath]) == null ? void 0 : _e.lazy;
361
+ const loaderNode = acc.routePiecesByPath[node.routePath]?.loader;
362
+ const componentNode = acc.routePiecesByPath[node.routePath]?.component;
363
+ const errorComponentNode = acc.routePiecesByPath[node.routePath]?.errorComponent;
364
+ const pendingComponentNode = acc.routePiecesByPath[node.routePath]?.pendingComponent;
365
+ const lazyComponentNode = acc.routePiecesByPath[node.routePath]?.lazy;
336
366
  return [
337
367
  [
338
368
  `const ${node.variableName}${exportName} = ${node.variableName}${exportName}Import.update({
@@ -394,14 +424,12 @@ Add the file in: "${this.config.routesDirectory}/${rootPathId}.${this.config.dis
394
424
  if (!this.config.disableTypes && hasMatchingRouteFiles) {
395
425
  fileRoutesByFullPathPerPlugin = [
396
426
  `export interface File${exportName}sByFullPath {
397
- ${[...createRouteNodesByFullPath(acc.routeNodes).entries()].map(
398
- ([fullPath, routeNode]) => {
399
- return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode, exportName)}`;
400
- }
401
- )}
427
+ ${[...createRouteNodesByFullPath(acc.routeNodes).entries()].filter(([fullPath]) => fullPath).map(([fullPath, routeNode]) => {
428
+ return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode, exportName)}`;
429
+ })}
402
430
  }`,
403
431
  `export interface File${exportName}sByTo {
404
- ${[...createRouteNodesByTo(acc.routeNodes).entries()].map(([to, routeNode]) => {
432
+ ${[...createRouteNodesByTo(acc.routeNodes).entries()].filter(([to]) => to).map(([to, routeNode]) => {
405
433
  return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode, exportName)}`;
406
434
  })}
407
435
  }`,
@@ -413,9 +441,9 @@ ${[...createRouteNodesById(acc.routeNodes).entries()].map(([id, routeNode]) => {
413
441
  }`,
414
442
  `export interface File${exportName}Types {
415
443
  file${exportName}sByFullPath: File${exportName}sByFullPath
416
- fullPaths: ${acc.routeNodes.length > 0 ? [...createRouteNodesByFullPath(acc.routeNodes).keys()].map((fullPath) => `'${fullPath}'`).join("|") : "never"}
444
+ fullPaths: ${acc.routeNodes.length > 0 ? [...createRouteNodesByFullPath(acc.routeNodes).keys()].filter((fullPath) => fullPath).map((fullPath) => `'${fullPath}'`).join("|") : "never"}
417
445
  file${exportName}sByTo: File${exportName}sByTo
418
- to: ${acc.routeNodes.length > 0 ? [...createRouteNodesByTo(acc.routeNodes).keys()].map((to) => `'${to}'`).join("|") : "never"}
446
+ to: ${acc.routeNodes.length > 0 ? [...createRouteNodesByTo(acc.routeNodes).keys()].filter((to) => to).map((to) => `'${to}'`).join("|") : "never"}
419
447
  id: ${[`'${rootRouteId}'`, ...[...createRouteNodesById(acc.routeNodes).keys()].map((id) => `'${id}'`)].join("|")}
420
448
  file${exportName}sById: File${exportName}sById
421
449
  }`,
@@ -425,7 +453,10 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
425
453
  ].join("\n");
426
454
  fileRoutesByPathInterfacePerPlugin = buildFileRoutesByPathInterface({
427
455
  ...plugin.moduleAugmentation({ generator: this }),
428
- routeNodes: preRouteNodes,
456
+ routeNodes: this.config.verboseFileRoutes !== false ? sortedRouteNodes : [
457
+ ...routeFileResult.map(({ node }) => node),
458
+ ...sortedRouteNodes.filter((d) => d.isVirtual)
459
+ ],
429
460
  exportName
430
461
  });
431
462
  }
@@ -458,8 +489,7 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
458
489
  ...buildRouteTreeForExport(plugin)
459
490
  }));
460
491
  this.plugins.map((plugin) => {
461
- var _a;
462
- return (_a = plugin.onRouteTreesChanged) == null ? void 0 : _a.call(plugin, {
492
+ return plugin.onRouteTreesChanged?.({
463
493
  routeTrees,
464
494
  rootRouteNode,
465
495
  generator: this
@@ -528,7 +558,6 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
528
558
  );
529
559
  }
530
560
  async processRouteNodeFile(node) {
531
- var _a, _b, _c, _d, _e;
532
561
  const result = await this.isRouteFileCacheFresh(node);
533
562
  if (result.status === "fresh") {
534
563
  node.exports = result.cacheEntry.exports;
@@ -545,9 +574,10 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
545
574
  const updatedCacheEntry = {
546
575
  fileContent: existingRouteFile.fileContent,
547
576
  mtimeMs: existingRouteFile.stat.mtimeMs,
548
- exports: []
577
+ exports: [],
578
+ routeId: node.routePath ?? "$$TSR_NO_ROUTE_PATH_ASSIGNED$$"
549
579
  };
550
- const escapedRoutePath = ((_a = node.routePath) == null ? void 0 : _a.replaceAll("$", "$$")) ?? "";
580
+ const escapedRoutePath = node.routePath?.replaceAll("$", "$$") ?? "";
551
581
  let shouldWriteRouteFile = false;
552
582
  if (!existingRouteFile.fileContent) {
553
583
  shouldWriteRouteFile = true;
@@ -555,10 +585,10 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
555
585
  const tLazyRouteTemplate = this.targetTemplate.lazyRoute;
556
586
  updatedCacheEntry.fileContent = await fillTemplate(
557
587
  this.config,
558
- (((_b = this.config.customScaffolding) == null ? void 0 : _b.lazyRouteTemplate) || ((_c = this.config.customScaffolding) == null ? void 0 : _c.routeTemplate)) ?? tLazyRouteTemplate.template(),
588
+ (this.config.customScaffolding?.lazyRouteTemplate || this.config.customScaffolding?.routeTemplate) ?? tLazyRouteTemplate.template(),
559
589
  {
560
590
  tsrImports: tLazyRouteTemplate.imports.tsrImports(),
561
- tsrPath: escapedRoutePath.replaceAll(/\{(.+)\}/gm, "$1"),
591
+ tsrPath: escapedRoutePath.replaceAll(/\{(.+?)\}/gm, "$1"),
562
592
  tsrExportStart: tLazyRouteTemplate.imports.tsrExportStart(escapedRoutePath),
563
593
  tsrExportEnd: tLazyRouteTemplate.imports.tsrExportEnd()
564
594
  }
@@ -578,10 +608,10 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
578
608
  const tRouteTemplate = this.targetTemplate.route;
579
609
  updatedCacheEntry.fileContent = await fillTemplate(
580
610
  this.config,
581
- ((_d = this.config.customScaffolding) == null ? void 0 : _d.routeTemplate) ?? tRouteTemplate.template(),
611
+ this.config.customScaffolding?.routeTemplate ?? tRouteTemplate.template(),
582
612
  {
583
613
  tsrImports: tRouteTemplate.imports.tsrImports(),
584
- tsrPath: escapedRoutePath.replaceAll(/\{(.+)\}/gm, "$1"),
614
+ tsrPath: escapedRoutePath.replaceAll(/\{(.+?)\}/gm, "$1"),
585
615
  tsrExportStart: tRouteTemplate.imports.tsrExportStart(escapedRoutePath),
586
616
  tsrExportEnd: tRouteTemplate.imports.tsrExportEnd()
587
617
  }
@@ -626,7 +656,7 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
626
656
  this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry);
627
657
  node.exports = updatedCacheEntry.exports;
628
658
  const shouldWriteTree = !deepEqual(
629
- (_e = result.cacheEntry) == null ? void 0 : _e.exports,
659
+ result.cacheEntry?.exports,
630
660
  updatedCacheEntry.exports
631
661
  );
632
662
  return {
@@ -665,6 +695,23 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
665
695
  event: { type: "update", path: opts.filePath }
666
696
  });
667
697
  }
698
+ const newFileState = await this.fs.stat(tmpPath);
699
+ if (newFileState.mode !== beforeStat.mode) {
700
+ await this.fs.chmod(tmpPath, beforeStat.mode);
701
+ }
702
+ if (newFileState.uid !== beforeStat.uid || newFileState.gid !== beforeStat.gid) {
703
+ try {
704
+ await this.fs.chown(tmpPath, beforeStat.uid, beforeStat.gid);
705
+ } catch (err) {
706
+ if (typeof err === "object" && err !== null && "code" in err && err.code === "EPERM") {
707
+ console.warn(
708
+ `[safeFileWrite] chown failed: ${err.message}`
709
+ );
710
+ } else {
711
+ throw err;
712
+ }
713
+ }
714
+ }
668
715
  } else {
669
716
  if (await checkFileExists(opts.filePath)) {
670
717
  throw rerun({
@@ -680,7 +727,11 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
680
727
  getTempFileName(filePath) {
681
728
  const absPath = path.resolve(filePath);
682
729
  const hash = crypto.createHash("md5").update(absPath).digest("hex");
683
- return path.join(this.tmpDir, hash);
730
+ if (!this.sessionId) {
731
+ mkdirSync(this.config.tmpDir, { recursive: true });
732
+ this.sessionId = crypto.randomBytes(4).toString("hex");
733
+ }
734
+ return path.join(this.config.tmpDir, `${this.sessionId}-${hash}`);
684
735
  }
685
736
  async isRouteFileCacheFresh(node) {
686
737
  const fileChangedCache = await this.didRouteFileChangeComparedToCache(
@@ -733,7 +784,6 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
733
784
  return { status: "stale", cacheEntry: fileChangedCache.cacheEntry };
734
785
  }
735
786
  async handleRootNode(node) {
736
- var _a;
737
787
  const result = await this.isRouteFileCacheFresh(node);
738
788
  if (result.status === "fresh") {
739
789
  node.exports = result.cacheEntry.exports;
@@ -747,7 +797,8 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
747
797
  const updatedCacheEntry = {
748
798
  fileContent: rootNodeFile.fileContent,
749
799
  mtimeMs: rootNodeFile.stat.mtimeMs,
750
- exports: []
800
+ exports: [],
801
+ routeId: node.routePath ?? "$$TSR_NO_ROOT_ROUTE_PATH_ASSIGNED$$"
751
802
  };
752
803
  if (!rootNodeFile.fileContent) {
753
804
  const rootTemplate = this.targetTemplate.rootRoute;
@@ -784,16 +835,15 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
784
835
  node.exports = rootRouteExports;
785
836
  this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry);
786
837
  const shouldWriteTree = !deepEqual(
787
- (_a = result.cacheEntry) == null ? void 0 : _a.exports,
838
+ result.cacheEntry?.exports,
788
839
  rootRouteExports
789
840
  );
790
841
  return shouldWriteTree;
791
842
  }
792
843
  handleNode(node, acc) {
793
- var _a;
794
844
  resetRegex(this.routeGroupPatternRegex);
795
845
  let parentRoute = hasParentRoute(acc.routeNodes, node, node.routePath);
796
- if ((parentRoute == null ? void 0 : parentRoute.isVirtualParentRoute) && ((_a = parentRoute.children) == null ? void 0 : _a.length)) {
846
+ if (parentRoute?.isVirtualParentRoute && parentRoute.children?.length) {
797
847
  const possibleParentRoute = hasParentRoute(
798
848
  parentRoute.children,
799
849
  node,
@@ -808,7 +858,7 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
808
858
  const trimmedPath = trimPathLeft(node.path ?? "");
809
859
  const split = trimmedPath.split("/");
810
860
  const lastRouteSegment = split[split.length - 1] ?? trimmedPath;
811
- node.isNonPath = lastRouteSegment.startsWith("_") || this.routeGroupPatternRegex.test(lastRouteSegment);
861
+ node.isNonPath = lastRouteSegment.startsWith("_") || split.every((part) => this.routeGroupPatternRegex.test(part));
812
862
  node.cleanedPath = removeGroups(
813
863
  removeUnderscores(removeLayoutSegments(node.path)) ?? ""
814
864
  );
@@ -882,33 +932,30 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
882
932
  }
883
933
  acc.routeNodes.push(node);
884
934
  }
885
- }
886
- function buildFileRoutesByPathInterface(opts) {
887
- return `declare module '${opts.module}' {
888
- interface ${opts.interfaceName} {
889
- ${opts.routeNodes.map((routeNode) => {
890
- var _a;
891
- const filePathId = routeNode.routePath;
892
- let preloaderRoute = "";
893
- if ((_a = routeNode.exports) == null ? void 0 : _a.includes(opts.exportName)) {
894
- preloaderRoute = `typeof ${routeNode.variableName}${opts.exportName}Import`;
895
- } else {
896
- preloaderRoute = "unknown";
897
- }
898
- const parent = findParent(routeNode, opts.exportName);
899
- return `'${filePathId}': {
900
- id: '${filePathId}'
901
- path: '${inferPath(routeNode)}'
902
- fullPath: '${inferFullPath(routeNode)}'
903
- preLoaderRoute: ${preloaderRoute}
904
- parentRoute: typeof ${parent}
905
- }`;
906
- }).join("\n")}
935
+ // only process files that are relevant for the route tree generation
936
+ isFileRelevantForRouteTreeGeneration(filePath) {
937
+ if (filePath === this.generatedRouteTreePath) {
938
+ return true;
939
+ }
940
+ if (filePath.startsWith(this.routesDirectoryPath)) {
941
+ return true;
942
+ }
943
+ if (typeof this.config.virtualRouteConfig === "string" && filePath === this.config.virtualRouteConfig) {
944
+ return true;
945
+ }
946
+ if (this.routeNodeCache.has(filePath)) {
947
+ return true;
948
+ }
949
+ if (isVirtualConfigFile(path.basename(filePath))) {
950
+ return true;
951
+ }
952
+ if (this.physicalDirectories.some((dir) => filePath.startsWith(dir))) {
953
+ return true;
954
+ }
955
+ return false;
907
956
  }
908
- }`;
909
957
  }
910
958
  export {
911
- Generator,
912
- buildFileRoutesByPathInterface
959
+ Generator
913
960
  };
914
961
  //# sourceMappingURL=generator.js.map