@tanstack/router-generator 1.151.3 → 1.151.5

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.
@@ -990,16 +990,13 @@ Current configuration:`;
990
990
  }
991
991
  static handleNode(node, acc, prefixMap, config) {
992
992
  let parentRoute = utils.hasParentRoute(prefixMap, node, node.routePath);
993
- if (!parentRoute && node.routePath) {
994
- let searchPath = node.routePath;
995
- while (searchPath.length > 0) {
996
- const lastSlash = searchPath.lastIndexOf("/");
997
- if (lastSlash <= 0) break;
998
- searchPath = searchPath.substring(0, lastSlash);
999
- const candidate = acc.routeNodesByPath.get(searchPath);
1000
- if (candidate && candidate.routePath !== node.routePath) {
993
+ if (node.routePath) {
994
+ const lastSlash = node.routePath.lastIndexOf("/");
995
+ if (lastSlash > 0) {
996
+ const immediateParentPath = node.routePath.substring(0, lastSlash);
997
+ const candidate = acc.routeNodesByPath.get(immediateParentPath);
998
+ if (candidate && candidate.routePath !== node.routePath && candidate !== parentRoute) {
1001
999
  parentRoute = candidate;
1002
- break;
1003
1000
  }
1004
1001
  }
1005
1002
  }
@@ -1 +1 @@
1
- {"version":3,"file":"generator.cjs","sources":["../../src/generator.ts"],"sourcesContent":["import path from 'node:path'\nimport * as fsp from 'node:fs/promises'\nimport { existsSync, mkdirSync } from 'node:fs'\nimport crypto from 'node:crypto'\nimport { rootRouteId } from '@tanstack/router-core'\nimport { logging } from './logger'\nimport {\n isVirtualConfigFile,\n getRouteNodes as physicalGetRouteNodes,\n} from './filesystem/physical/getRouteNodes'\nimport { getRouteNodes as virtualGetRouteNodes } from './filesystem/virtual/getRouteNodes'\nimport { rootPathId } from './filesystem/physical/rootPathId'\nimport {\n RoutePrefixMap,\n buildFileRoutesByPathInterface,\n buildImportString,\n buildRouteTreeConfig,\n checkFileExists,\n checkRouteFullPathUniqueness,\n createRouteNodesByFullPath,\n createRouteNodesById,\n createRouteNodesByTo,\n createTokenRegex,\n determineNodePath,\n findParent,\n format,\n getImportForRouteNode,\n getImportPath,\n getResolvedRouteNodeVariableName,\n hasParentRoute,\n isRouteNodeValidForAugmentation,\n isSegmentPathless,\n mergeImportDeclarations,\n multiSortBy,\n removeExt,\n removeGroups,\n removeLastSegmentFromPath,\n removeLayoutSegmentsWithEscape,\n removeTrailingSlash,\n removeUnderscoresWithEscape,\n replaceBackslash,\n trimPathLeft,\n} from './utils'\nimport { fillTemplate, getTargetTemplate } from './template'\nimport { transform } from './transform/transform'\nimport type { GeneratorPlugin } from './plugin/types'\nimport type { TargetTemplate } from './template'\nimport type {\n FsRouteType,\n GetRouteNodesResult,\n GetRoutesByFileMapResult,\n HandleNodeAccumulator,\n ImportDeclaration,\n RouteNode,\n} from './types'\nimport type { Config } from './config'\nimport type { Logger } from './logger'\n\ninterface fs {\n stat: (\n filePath: string,\n ) => Promise<{ mtimeMs: bigint; mode: number; uid: number; gid: number }>\n rename: (oldPath: string, newPath: string) => Promise<void>\n writeFile: (filePath: string, content: string) => Promise<void>\n readFile: (\n filePath: string,\n ) => Promise<\n { stat: { mtimeMs: bigint }; fileContent: string } | 'file-not-existing'\n >\n chmod: (filePath: string, mode: number) => Promise<void>\n chown: (filePath: string, uid: number, gid: number) => Promise<void>\n}\n\nconst DefaultFileSystem: fs = {\n stat: async (filePath) => {\n const res = await fsp.stat(filePath, { bigint: true })\n return {\n mtimeMs: res.mtimeMs,\n mode: Number(res.mode),\n uid: Number(res.uid),\n gid: Number(res.gid),\n }\n },\n rename: (oldPath, newPath) => fsp.rename(oldPath, newPath),\n writeFile: (filePath, content) => fsp.writeFile(filePath, content),\n readFile: async (filePath: string) => {\n try {\n const fileHandle = await fsp.open(filePath, 'r')\n const stat = await fileHandle.stat({ bigint: true })\n const fileContent = (await fileHandle.readFile()).toString()\n await fileHandle.close()\n return { stat, fileContent }\n } catch (e: any) {\n if ('code' in e) {\n if (e.code === 'ENOENT') {\n return 'file-not-existing'\n }\n }\n throw e\n }\n },\n chmod: (filePath, mode) => fsp.chmod(filePath, mode),\n chown: (filePath, uid, gid) => fsp.chown(filePath, uid, gid),\n}\n\ninterface Rerun {\n rerun: true\n msg?: string\n event: GeneratorEvent\n}\nfunction rerun(opts: { msg?: string; event?: GeneratorEvent }): Rerun {\n const { event, ...rest } = opts\n return { rerun: true, event: event ?? { type: 'rerun' }, ...rest }\n}\n\nfunction isRerun(result: unknown): result is Rerun {\n return (\n typeof result === 'object' &&\n result !== null &&\n 'rerun' in result &&\n result.rerun === true\n )\n}\n\nexport type FileEventType = 'create' | 'update' | 'delete'\nexport type FileEvent = {\n type: FileEventType\n path: string\n}\nexport type GeneratorEvent = FileEvent | { type: 'rerun' }\n\ntype FileCacheChange<TCacheEntry extends GeneratorCacheEntry> =\n | {\n result: false\n cacheEntry: TCacheEntry\n }\n | { result: true; mtimeMs: bigint; cacheEntry: TCacheEntry }\n | {\n result: 'file-not-in-cache'\n }\n | {\n result: 'cannot-stat-file'\n }\n\ninterface GeneratorCacheEntry {\n mtimeMs: bigint\n fileContent: string\n}\n\ninterface RouteNodeCacheEntry extends GeneratorCacheEntry {\n routeId: string\n node: RouteNode\n}\n\ntype GeneratorRouteNodeCache = Map</** filePath **/ string, RouteNodeCacheEntry>\n\ninterface CrawlingResult {\n rootRouteNode: RouteNode\n routeFileResult: Array<RouteNode>\n acc: HandleNodeAccumulator\n}\n\nexport class Generator {\n /**\n * why do we have two caches for the route files?\n * During processing, we READ from the cache and WRITE to the shadow cache.\n *\n * After a route file is processed, we write to the shadow cache.\n * If during processing we bail out and re-run, we don't lose this modification\n * but still can track whether the file contributed changes and thus the route tree file needs to be regenerated.\n * After all files are processed, we swap the shadow cache with the main cache and initialize a new shadow cache.\n * That way we also ensure deleted/renamed files don't stay in the cache forever.\n */\n private routeNodeCache: GeneratorRouteNodeCache = new Map()\n private routeNodeShadowCache: GeneratorRouteNodeCache = new Map()\n\n private routeTreeFileCache: GeneratorCacheEntry | undefined\n\n private crawlingResult: CrawlingResult | undefined\n public config: Config\n public targetTemplate: TargetTemplate\n\n private root: string\n private routesDirectoryPath: string\n private sessionId?: string\n private fs: fs\n private logger: Logger\n private generatedRouteTreePath: string\n private runPromise: Promise<void> | undefined\n private fileEventQueue: Array<GeneratorEvent> = []\n private plugins: Array<GeneratorPlugin> = []\n private static routeGroupPatternRegex = /\\(.+\\)/\n private physicalDirectories: Array<string> = []\n\n /**\n * Token regexes are pre-compiled once here and reused throughout route processing.\n * We need TWO types of regex for each token because they match against different inputs:\n *\n * 1. FILENAME regexes: Match token patterns within full file path strings.\n * Example: For file \"routes/dashboard.index.tsx\", we want to detect \".index.\"\n * Pattern: `[./](?:token)[.]` - matches token bounded by path separators/dots\n * Used in: sorting route nodes by file path\n *\n * 2. SEGMENT regexes: Match token against a single logical route segment.\n * Example: For segment \"index\" (extracted from path), match the whole segment\n * Pattern: `^(?:token)$` - matches entire segment exactly\n * Used in: route parsing, determining route types, escape detection\n *\n * We cannot reuse one for the other without false positives or missing matches.\n */\n private indexTokenFilenameRegex: RegExp\n private routeTokenFilenameRegex: RegExp\n private indexTokenSegmentRegex: RegExp\n private routeTokenSegmentRegex: RegExp\n private static componentPieceRegex =\n /[./](component|errorComponent|notFoundComponent|pendingComponent|loader|lazy)[.]/\n\n constructor(opts: { config: Config; root: string; fs?: fs }) {\n this.config = opts.config\n this.logger = logging({ disabled: this.config.disableLogging })\n this.root = opts.root\n this.fs = opts.fs || DefaultFileSystem\n this.generatedRouteTreePath = this.getGeneratedRouteTreePath()\n this.targetTemplate = getTargetTemplate(this.config)\n\n this.routesDirectoryPath = this.getRoutesDirectoryPath()\n this.plugins.push(...(opts.config.plugins || []))\n\n // Create all token regexes once in constructor\n this.indexTokenFilenameRegex = createTokenRegex(this.config.indexToken, {\n type: 'filename',\n })\n this.routeTokenFilenameRegex = createTokenRegex(this.config.routeToken, {\n type: 'filename',\n })\n this.indexTokenSegmentRegex = createTokenRegex(this.config.indexToken, {\n type: 'segment',\n })\n this.routeTokenSegmentRegex = createTokenRegex(this.config.routeToken, {\n type: 'segment',\n })\n\n for (const plugin of this.plugins) {\n plugin.init?.({ generator: this })\n }\n }\n\n private getGeneratedRouteTreePath() {\n const generatedRouteTreePath = path.isAbsolute(\n this.config.generatedRouteTree,\n )\n ? this.config.generatedRouteTree\n : path.resolve(this.root, this.config.generatedRouteTree)\n\n const generatedRouteTreeDir = path.dirname(generatedRouteTreePath)\n\n if (!existsSync(generatedRouteTreeDir)) {\n mkdirSync(generatedRouteTreeDir, { recursive: true })\n }\n\n return generatedRouteTreePath\n }\n\n private getRoutesDirectoryPath() {\n return path.isAbsolute(this.config.routesDirectory)\n ? this.config.routesDirectory\n : path.resolve(this.root, this.config.routesDirectory)\n }\n\n public getRoutesByFileMap(): GetRoutesByFileMapResult {\n return new Map(\n [...this.routeNodeCache.entries()].map(([filePath, cacheEntry]) => [\n filePath,\n { routePath: cacheEntry.routeId },\n ]),\n )\n }\n\n public async run(event?: GeneratorEvent): Promise<void> {\n if (\n event &&\n event.type !== 'rerun' &&\n !this.isFileRelevantForRouteTreeGeneration(event.path)\n ) {\n return\n }\n this.fileEventQueue.push(event ?? { type: 'rerun' })\n // only allow a single run at a time\n if (this.runPromise) {\n return this.runPromise\n }\n\n this.runPromise = (async () => {\n do {\n // synchronously copy and clear the queue since we are going to iterate asynchronously over it\n // and while we do so, a new event could be put into the queue\n const tempQueue = this.fileEventQueue\n this.fileEventQueue = []\n // if we only have 'update' events in the queue\n // and we already have the affected files' latest state in our cache, we can exit early\n const remainingEvents = (\n await Promise.all(\n tempQueue.map(async (e) => {\n if (e.type === 'update') {\n let cacheEntry: GeneratorCacheEntry | undefined\n if (e.path === this.generatedRouteTreePath) {\n cacheEntry = this.routeTreeFileCache\n } else {\n // we only check the routeNodeCache here\n // if the file's state is only up-to-date in the shadow cache we need to re-run\n cacheEntry = this.routeNodeCache.get(e.path)\n }\n const change = await this.didFileChangeComparedToCache(\n { path: e.path },\n cacheEntry,\n )\n if (change.result === false) {\n return null\n }\n }\n return e\n }),\n )\n ).filter((e) => e !== null)\n\n if (remainingEvents.length === 0) {\n break\n }\n\n try {\n await this.generatorInternal()\n } catch (err) {\n const errArray = !Array.isArray(err) ? [err] : err\n\n const recoverableErrors = errArray.filter((e) => isRerun(e))\n if (recoverableErrors.length === errArray.length) {\n this.fileEventQueue.push(...recoverableErrors.map((e) => e.event))\n recoverableErrors.forEach((e) => {\n if (e.msg) {\n this.logger.info(e.msg)\n }\n })\n } else {\n const unrecoverableErrors = errArray.filter((e) => !isRerun(e))\n this.runPromise = undefined\n throw new Error(\n unrecoverableErrors.map((e) => (e as Error).message).join(),\n )\n }\n }\n } while (this.fileEventQueue.length)\n this.runPromise = undefined\n })()\n return this.runPromise\n }\n\n private async generatorInternal() {\n let writeRouteTreeFile: boolean | 'force' = false\n\n let getRouteNodesResult: GetRouteNodesResult\n\n if (this.config.virtualRouteConfig) {\n getRouteNodesResult = await virtualGetRouteNodes(this.config, this.root, {\n indexTokenSegmentRegex: this.indexTokenSegmentRegex,\n routeTokenSegmentRegex: this.routeTokenSegmentRegex,\n })\n } else {\n getRouteNodesResult = await physicalGetRouteNodes(\n this.config,\n this.root,\n {\n indexTokenSegmentRegex: this.indexTokenSegmentRegex,\n routeTokenSegmentRegex: this.routeTokenSegmentRegex,\n },\n )\n }\n\n const {\n rootRouteNode,\n routeNodes: beforeRouteNodes,\n physicalDirectories,\n } = getRouteNodesResult\n if (rootRouteNode === undefined) {\n let errorMessage = `rootRouteNode must not be undefined. Make sure you've added your root route into the route-tree.`\n if (!this.config.virtualRouteConfig) {\n errorMessage += `\\nMake sure that you add a \"${rootPathId}.${this.config.disableTypes ? 'js' : 'tsx'}\" file to your routes directory.\\nAdd the file in: \"${this.config.routesDirectory}/${rootPathId}.${this.config.disableTypes ? 'js' : 'tsx'}\"`\n }\n throw new Error(errorMessage)\n }\n this.physicalDirectories = physicalDirectories\n\n await this.handleRootNode(rootRouteNode)\n\n const preRouteNodes = multiSortBy(beforeRouteNodes, [\n (d) => (d.routePath === '/' ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => (d.filePath.match(this.indexTokenFilenameRegex) ? 1 : -1),\n (d) => (d.filePath.match(Generator.componentPieceRegex) ? 1 : -1),\n (d) => (d.filePath.match(this.routeTokenFilenameRegex) ? -1 : 1),\n (d) => (d.routePath?.endsWith('/') ? -1 : 1),\n (d) => d.routePath,\n ]).filter((d) => {\n // Exclude the root route itself, but keep component/loader pieces for the root\n if (d.routePath === `/${rootPathId}`) {\n return [\n 'component',\n 'errorComponent',\n 'notFoundComponent',\n 'pendingComponent',\n 'loader',\n 'lazy',\n ].includes(d._fsRouteType)\n }\n return true\n })\n\n const routeFileAllResult = await Promise.allSettled(\n preRouteNodes\n // only process routes that are backed by an actual file\n .filter((n) => !n.isVirtualParentRoute && !n.isVirtual)\n .map((n) => this.processRouteNodeFile(n)),\n )\n\n const rejections = routeFileAllResult.filter(\n (result) => result.status === 'rejected',\n )\n if (rejections.length > 0) {\n throw rejections.map((e) => e.reason)\n }\n\n const routeFileResult = routeFileAllResult.flatMap((result) => {\n if (result.status === 'fulfilled' && result.value !== null) {\n if (result.value.shouldWriteTree) {\n writeRouteTreeFile = true\n }\n return result.value.node\n }\n return []\n })\n\n // reset children in case we re-use a node from the cache\n routeFileResult.forEach((r) => (r.children = undefined))\n\n const acc: HandleNodeAccumulator = {\n routeTree: [],\n routeNodes: [],\n routePiecesByPath: {},\n routeNodesByPath: new Map(),\n }\n\n const prefixMap = new RoutePrefixMap(routeFileResult)\n\n for (const node of routeFileResult) {\n Generator.handleNode(node, acc, prefixMap, this.config)\n }\n\n this.crawlingResult = { rootRouteNode, routeFileResult, acc }\n\n // this is the first time the generator runs, so read in the route tree file if it exists yet\n if (!this.routeTreeFileCache) {\n const routeTreeFile = await this.fs.readFile(this.generatedRouteTreePath)\n if (routeTreeFile !== 'file-not-existing') {\n this.routeTreeFileCache = {\n fileContent: routeTreeFile.fileContent,\n mtimeMs: routeTreeFile.stat.mtimeMs,\n }\n }\n writeRouteTreeFile = true\n } else {\n const routeTreeFileChange = await this.didFileChangeComparedToCache(\n { path: this.generatedRouteTreePath },\n this.routeTreeFileCache,\n )\n if (routeTreeFileChange.result !== false) {\n writeRouteTreeFile = 'force'\n if (routeTreeFileChange.result === true) {\n const routeTreeFile = await this.fs.readFile(\n this.generatedRouteTreePath,\n )\n if (routeTreeFile !== 'file-not-existing') {\n this.routeTreeFileCache = {\n fileContent: routeTreeFile.fileContent,\n mtimeMs: routeTreeFile.stat.mtimeMs,\n }\n }\n }\n }\n }\n\n if (!writeRouteTreeFile) {\n // only needs to be done if no other changes have been detected yet\n // compare shadowCache and cache to identify deleted routes\n if (this.routeNodeCache.size !== this.routeNodeShadowCache.size) {\n writeRouteTreeFile = true\n } else {\n for (const fullPath of this.routeNodeCache.keys()) {\n if (!this.routeNodeShadowCache.has(fullPath)) {\n writeRouteTreeFile = true\n break\n }\n }\n }\n }\n\n if (!writeRouteTreeFile) {\n this.swapCaches()\n return\n }\n\n const buildResult = this.buildRouteTree({\n rootRouteNode,\n acc,\n routeFileResult,\n })\n let routeTreeContent = buildResult.routeTreeContent\n\n routeTreeContent = this.config.enableRouteTreeFormatting\n ? await format(routeTreeContent, this.config)\n : routeTreeContent\n\n let newMtimeMs: bigint | undefined\n if (this.routeTreeFileCache) {\n if (\n writeRouteTreeFile !== 'force' &&\n this.routeTreeFileCache.fileContent === routeTreeContent\n ) {\n // existing route tree file is already up-to-date, don't write it\n // we should only get here in the initial run when the route cache is not filled yet\n } else {\n const newRouteTreeFileStat = await this.safeFileWrite({\n filePath: this.generatedRouteTreePath,\n newContent: routeTreeContent,\n strategy: {\n type: 'mtime',\n expectedMtimeMs: this.routeTreeFileCache.mtimeMs,\n },\n })\n newMtimeMs = newRouteTreeFileStat.mtimeMs\n }\n } else {\n const newRouteTreeFileStat = await this.safeFileWrite({\n filePath: this.generatedRouteTreePath,\n newContent: routeTreeContent,\n strategy: {\n type: 'new-file',\n },\n })\n newMtimeMs = newRouteTreeFileStat.mtimeMs\n }\n\n if (newMtimeMs !== undefined) {\n this.routeTreeFileCache = {\n fileContent: routeTreeContent,\n mtimeMs: newMtimeMs,\n }\n }\n\n this.plugins.map((plugin) => {\n return plugin.onRouteTreeChanged?.({\n routeTree: buildResult.routeTree,\n routeNodes: buildResult.routeNodes,\n acc,\n rootRouteNode,\n })\n })\n this.swapCaches()\n }\n\n private swapCaches() {\n this.routeNodeCache = this.routeNodeShadowCache\n this.routeNodeShadowCache = new Map()\n }\n\n public buildRouteTree(opts: {\n rootRouteNode: RouteNode\n acc: HandleNodeAccumulator\n routeFileResult: Array<RouteNode>\n config?: Partial<Config>\n }) {\n const config = { ...this.config, ...(opts.config || {}) }\n\n const { rootRouteNode, acc } = opts\n\n // Use pre-compiled regex if config hasn't been overridden, otherwise create new one\n const indexTokenSegmentRegex =\n config.indexToken === this.config.indexToken\n ? this.indexTokenSegmentRegex\n : createTokenRegex(config.indexToken, { type: 'segment' })\n\n const sortedRouteNodes = multiSortBy(acc.routeNodes, [\n (d) => (d.routePath?.includes(`/${rootPathId}`) ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => {\n const segments = d.routePath?.split('/').filter(Boolean) ?? []\n const last = segments[segments.length - 1] ?? ''\n return indexTokenSegmentRegex.test(last) ? -1 : 1\n },\n (d) => d,\n ])\n\n const routeImports: Array<ImportDeclaration> = []\n const virtualRouteNodes: Array<string> = []\n\n for (const node of sortedRouteNodes) {\n if (node.isVirtual) {\n virtualRouteNodes.push(\n `const ${node.variableName}RouteImport = createFileRoute('${node.routePath}')()`,\n )\n } else {\n routeImports.push(\n getImportForRouteNode(\n node,\n config,\n this.generatedRouteTreePath,\n this.root,\n ),\n )\n }\n }\n\n const imports: Array<ImportDeclaration> = []\n if (virtualRouteNodes.length > 0) {\n imports.push({\n specifiers: [{ imported: 'createFileRoute' }],\n source: this.targetTemplate.fullPkg,\n })\n }\n // Add lazyRouteComponent import if there are component pieces\n let hasComponentPieces = false\n let hasLoaderPieces = false\n for (const node of sortedRouteNodes) {\n const pieces = acc.routePiecesByPath[node.routePath!]\n if (pieces) {\n if (\n pieces.component ||\n pieces.errorComponent ||\n pieces.notFoundComponent ||\n pieces.pendingComponent\n ) {\n hasComponentPieces = true\n }\n if (pieces.loader) {\n hasLoaderPieces = true\n }\n if (hasComponentPieces && hasLoaderPieces) break\n }\n }\n if (hasComponentPieces || hasLoaderPieces) {\n const runtimeImport: ImportDeclaration = {\n specifiers: [],\n source: this.targetTemplate.fullPkg,\n }\n if (hasComponentPieces) {\n runtimeImport.specifiers.push({ imported: 'lazyRouteComponent' })\n }\n if (hasLoaderPieces) {\n runtimeImport.specifiers.push({ imported: 'lazyFn' })\n }\n imports.push(runtimeImport)\n }\n if (config.verboseFileRoutes === false) {\n const typeImport: ImportDeclaration = {\n specifiers: [],\n source: this.targetTemplate.fullPkg,\n importKind: 'type',\n }\n let needsCreateFileRoute = false\n let needsCreateLazyFileRoute = false\n for (const node of sortedRouteNodes) {\n if (isRouteNodeValidForAugmentation(node)) {\n if (node._fsRouteType !== 'lazy') {\n needsCreateFileRoute = true\n }\n if (acc.routePiecesByPath[node.routePath!]?.lazy) {\n needsCreateLazyFileRoute = true\n }\n }\n if (needsCreateFileRoute && needsCreateLazyFileRoute) break\n }\n if (needsCreateFileRoute) {\n typeImport.specifiers.push({ imported: 'CreateFileRoute' })\n }\n if (needsCreateLazyFileRoute) {\n typeImport.specifiers.push({ imported: 'CreateLazyFileRoute' })\n }\n\n if (typeImport.specifiers.length > 0) {\n typeImport.specifiers.push({ imported: 'FileRoutesByPath' })\n imports.push(typeImport)\n }\n }\n\n const routeTreeConfig = buildRouteTreeConfig(\n acc.routeTree,\n config.disableTypes,\n )\n\n const createUpdateRoutes = sortedRouteNodes.map((node) => {\n const pieces = acc.routePiecesByPath[node.routePath!]\n const loaderNode = pieces?.loader\n const componentNode = pieces?.component\n const errorComponentNode = pieces?.errorComponent\n const notFoundComponentNode = pieces?.notFoundComponent\n const pendingComponentNode = pieces?.pendingComponent\n const lazyComponentNode = pieces?.lazy\n\n return [\n [\n `const ${node.variableName}Route = ${node.variableName}RouteImport.update({\n ${[\n `id: '${node.path}'`,\n !node.isNonPath ||\n (node._fsRouteType === 'pathless_layout' && node.cleanedPath)\n ? `path: '${node.cleanedPath}'`\n : undefined,\n `getParentRoute: () => ${findParent(node)}`,\n ]\n .filter(Boolean)\n .join(',')}\n }${config.disableTypes ? '' : 'as any'})`,\n loaderNode\n ? `.updateLoader({ loader: lazyFn(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, loaderNode.filePath),\n ),\n config.addExtensions,\n ),\n )}'), 'loader') })`\n : '',\n componentNode ||\n errorComponentNode ||\n notFoundComponentNode ||\n pendingComponentNode\n ? `.update({\n ${(\n [\n ['component', componentNode],\n ['errorComponent', errorComponentNode],\n ['notFoundComponent', notFoundComponentNode],\n ['pendingComponent', pendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n // For .vue files, use 'default' as the export name since Vue SFCs export default\n const isVueFile = d[1]!.filePath.endsWith('.vue')\n const exportName = isVueFile ? 'default' : d[0]\n // Keep .vue extension for Vue files since Vite requires it\n const importPath = replaceBackslash(\n isVueFile\n ? path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n d[1]!.filePath,\n ),\n )\n : removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n d[1]!.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )\n return `${\n d[0]\n }: lazyRouteComponent(() => import('./${importPath}'), '${exportName}')`\n })\n .join('\\n,')}\n })`\n : '',\n lazyComponentNode\n ? (() => {\n // For .vue files, use 'default' export since Vue SFCs export default\n const isVueFile = lazyComponentNode.filePath.endsWith('.vue')\n const exportAccessor = isVueFile ? 'd.default' : 'd.Route'\n // Keep .vue extension for Vue files since Vite requires it\n const importPath = replaceBackslash(\n isVueFile\n ? path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n )\n : removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )\n return `.lazy(() => import('./${importPath}').then((d) => ${exportAccessor}))`\n })()\n : '',\n ].join(''),\n ].join('\\n\\n')\n })\n\n // Generate update for root route if it has component pieces\n const rootRoutePath = `/${rootPathId}`\n const rootPieces = acc.routePiecesByPath[rootRoutePath]\n const rootComponentNode = rootPieces?.component\n const rootErrorComponentNode = rootPieces?.errorComponent\n const rootNotFoundComponentNode = rootPieces?.notFoundComponent\n const rootPendingComponentNode = rootPieces?.pendingComponent\n\n let rootRouteUpdate = ''\n if (\n rootComponentNode ||\n rootErrorComponentNode ||\n rootNotFoundComponentNode ||\n rootPendingComponentNode\n ) {\n rootRouteUpdate = `const rootRouteWithChildren = rootRouteImport${\n rootComponentNode ||\n rootErrorComponentNode ||\n rootNotFoundComponentNode ||\n rootPendingComponentNode\n ? `.update({\n ${(\n [\n ['component', rootComponentNode],\n ['errorComponent', rootErrorComponentNode],\n ['notFoundComponent', rootNotFoundComponentNode],\n ['pendingComponent', rootPendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n // For .vue files, use 'default' as the export name since Vue SFCs export default\n const isVueFile = d[1]!.filePath.endsWith('.vue')\n const exportName = isVueFile ? 'default' : d[0]\n // Keep .vue extension for Vue files since Vite requires it\n const importPath = replaceBackslash(\n isVueFile\n ? path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, d[1]!.filePath),\n )\n : removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n d[1]!.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )\n return `${d[0]}: lazyRouteComponent(() => import('./${importPath}'), '${exportName}')`\n })\n .join('\\n,')}\n })`\n : ''\n }._addFileChildren(rootRouteChildren)${config.disableTypes ? '' : `._addFileTypes<FileRouteTypes>()`}`\n }\n\n let fileRoutesByPathInterface = ''\n let fileRoutesByFullPath = ''\n\n if (!config.disableTypes) {\n const routeNodesByFullPath = createRouteNodesByFullPath(acc.routeNodes)\n const routeNodesByTo = createRouteNodesByTo(acc.routeNodes)\n const routeNodesById = createRouteNodesById(acc.routeNodes)\n\n fileRoutesByFullPath = [\n `export interface FileRoutesByFullPath {\n${[...routeNodesByFullPath.entries()]\n .filter(([fullPath]) => fullPath)\n .map(([fullPath, routeNode]) => {\n return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n })}\n}`,\n `export interface FileRoutesByTo {\n${[...routeNodesByTo.entries()]\n .filter(([to]) => to)\n .map(([to, routeNode]) => {\n return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n })}\n}`,\n `export interface FileRoutesById {\n'${rootRouteId}': typeof rootRouteImport,\n${[...routeNodesById.entries()].map(([id, routeNode]) => {\n return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n})}\n}`,\n `export interface FileRouteTypes {\nfileRoutesByFullPath: FileRoutesByFullPath\nfullPaths: ${\n acc.routeNodes.length > 0\n ? [...routeNodesByFullPath.keys()]\n .filter((fullPath) => fullPath)\n .map((fullPath) => `'${fullPath}'`)\n .join('|')\n : 'never'\n }\nfileRoutesByTo: FileRoutesByTo\nto: ${\n acc.routeNodes.length > 0\n ? [...routeNodesByTo.keys()]\n .filter((to) => to)\n .map((to) => `'${to}'`)\n .join('|')\n : 'never'\n }\nid: ${[`'${rootRouteId}'`, ...[...routeNodesById.keys()].map((id) => `'${id}'`)].join('|')}\nfileRoutesById: FileRoutesById\n}`,\n `export interface RootRouteChildren {\n${acc.routeTree.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}\n}`,\n ].join('\\n')\n\n fileRoutesByPathInterface = buildFileRoutesByPathInterface({\n module: this.targetTemplate.fullPkg,\n interfaceName: 'FileRoutesByPath',\n routeNodes: sortedRouteNodes,\n config,\n })\n }\n\n const routeTree = [\n `const rootRouteChildren${config.disableTypes ? '' : `: RootRouteChildren`} = {\n ${acc.routeTree\n .map(\n (child) =>\n `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`,\n )\n .join(',')}\n}`,\n rootRouteUpdate\n ? rootRouteUpdate.replace(\n 'const rootRouteWithChildren = ',\n 'export const routeTree = ',\n )\n : `export const routeTree = rootRouteImport._addFileChildren(rootRouteChildren)${config.disableTypes ? '' : `._addFileTypes<FileRouteTypes>()`}`,\n ].join('\\n')\n\n checkRouteFullPathUniqueness(\n sortedRouteNodes.filter(\n (d) => d.children === undefined && 'lazy' !== d._fsRouteType,\n ),\n config,\n )\n\n let mergedImports = mergeImportDeclarations(imports)\n if (config.disableTypes) {\n mergedImports = mergedImports.filter((d) => d.importKind !== 'type')\n }\n\n const importStatements = mergedImports.map(buildImportString)\n\n let moduleAugmentation = ''\n if (config.verboseFileRoutes === false && !config.disableTypes) {\n moduleAugmentation = opts.routeFileResult\n .map((node) => {\n const getModuleDeclaration = (routeNode?: RouteNode) => {\n if (!isRouteNodeValidForAugmentation(routeNode)) {\n return ''\n }\n let moduleAugmentation = ''\n if (routeNode._fsRouteType === 'lazy') {\n moduleAugmentation = `const createLazyFileRoute: CreateLazyFileRoute<FileRoutesByPath['${routeNode.routePath}']['preLoaderRoute']>`\n } else {\n moduleAugmentation = `const createFileRoute: CreateFileRoute<'${routeNode.routePath}',\n FileRoutesByPath['${routeNode.routePath}']['parentRoute'],\n FileRoutesByPath['${routeNode.routePath}']['id'],\n FileRoutesByPath['${routeNode.routePath}']['path'],\n FileRoutesByPath['${routeNode.routePath}']['fullPath']\n >\n `\n }\n\n return `declare module './${getImportPath(routeNode, config, this.generatedRouteTreePath)}' {\n ${moduleAugmentation}\n }`\n }\n return getModuleDeclaration(node)\n })\n .join('\\n')\n }\n\n const rootRouteImport = getImportForRouteNode(\n rootRouteNode,\n config,\n this.generatedRouteTreePath,\n this.root,\n )\n routeImports.unshift(rootRouteImport)\n\n let footer: Array<string> = []\n if (config.routeTreeFileFooter) {\n if (Array.isArray(config.routeTreeFileFooter)) {\n footer = config.routeTreeFileFooter\n } else {\n footer = config.routeTreeFileFooter()\n }\n }\n const routeTreeContent = [\n ...config.routeTreeFileHeader,\n `// This file was automatically generated by TanStack Router.\n// You should NOT make any changes in this file as it will be overwritten.\n// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.`,\n [...importStatements].join('\\n'),\n mergeImportDeclarations(routeImports).map(buildImportString).join('\\n'),\n virtualRouteNodes.join('\\n'),\n createUpdateRoutes.join('\\n'),\n fileRoutesByFullPath,\n fileRoutesByPathInterface,\n moduleAugmentation,\n routeTreeConfig.join('\\n'),\n routeTree,\n ...footer,\n ]\n .filter(Boolean)\n .join('\\n\\n')\n return {\n routeTreeContent,\n routeTree: acc.routeTree,\n routeNodes: acc.routeNodes,\n }\n }\n\n private async processRouteNodeFile(node: RouteNode): Promise<{\n shouldWriteTree: boolean\n cacheEntry: RouteNodeCacheEntry\n node: RouteNode\n } | null> {\n const result = await this.isRouteFileCacheFresh(node)\n\n if (result.status === 'fresh') {\n return {\n node: result.cacheEntry.node,\n shouldWriteTree: false,\n cacheEntry: result.cacheEntry,\n }\n }\n\n const previousCacheEntry = result.cacheEntry\n\n const existingRouteFile = await this.fs.readFile(node.fullPath)\n if (existingRouteFile === 'file-not-existing') {\n throw new Error(`⚠️ File ${node.fullPath} does not exist`)\n }\n\n const updatedCacheEntry: RouteNodeCacheEntry = {\n fileContent: existingRouteFile.fileContent,\n mtimeMs: existingRouteFile.stat.mtimeMs,\n routeId: node.routePath ?? '$$TSR_NO_ROUTE_PATH_ASSIGNED$$',\n node,\n }\n\n const escapedRoutePath = node.routePath?.replaceAll('$', '$$') ?? ''\n\n let shouldWriteRouteFile = false\n let shouldWriteTree = false\n // now we need to either scaffold the file or transform it\n if (!existingRouteFile.fileContent) {\n shouldWriteRouteFile = true\n shouldWriteTree = true\n // Creating a new lazy route file\n if (node._fsRouteType === 'lazy') {\n const tLazyRouteTemplate = this.targetTemplate.lazyRoute\n // Check by default check if the user has a specific lazy route template\n // If not, check if the user has a route template and use that instead\n updatedCacheEntry.fileContent = await fillTemplate(\n this.config,\n (this.config.customScaffolding?.lazyRouteTemplate ||\n this.config.customScaffolding?.routeTemplate) ??\n tLazyRouteTemplate.template(),\n {\n tsrImports: tLazyRouteTemplate.imports.tsrImports(),\n tsrPath: escapedRoutePath.replaceAll(/\\{(.+?)\\}/gm, '$1'),\n tsrExportStart:\n tLazyRouteTemplate.imports.tsrExportStart(escapedRoutePath),\n tsrExportEnd: tLazyRouteTemplate.imports.tsrExportEnd(),\n },\n )\n } else if (\n // Creating a new normal route file\n (['layout', 'static'] satisfies Array<FsRouteType>).some(\n (d) => d === node._fsRouteType,\n ) ||\n (\n [\n 'component',\n 'pendingComponent',\n 'errorComponent',\n 'notFoundComponent',\n 'loader',\n ] satisfies Array<FsRouteType>\n ).every((d) => d !== node._fsRouteType)\n ) {\n const tRouteTemplate = this.targetTemplate.route\n updatedCacheEntry.fileContent = await fillTemplate(\n this.config,\n this.config.customScaffolding?.routeTemplate ??\n tRouteTemplate.template(),\n {\n tsrImports: tRouteTemplate.imports.tsrImports(),\n tsrPath: escapedRoutePath.replaceAll(/\\{(.+?)\\}/gm, '$1'),\n tsrExportStart:\n tRouteTemplate.imports.tsrExportStart(escapedRoutePath),\n tsrExportEnd: tRouteTemplate.imports.tsrExportEnd(),\n },\n )\n } else {\n return null\n }\n }\n\n // Check if this is a Vue component file\n // Vue SFC files (.vue) don't need transformation as they can't have a Route export\n const isVueFile = node.filePath.endsWith('.vue')\n\n if (!isVueFile) {\n // transform the file\n const transformResult = await transform({\n source: updatedCacheEntry.fileContent,\n ctx: {\n target: this.config.target,\n routeId: escapedRoutePath,\n lazy: node._fsRouteType === 'lazy',\n verboseFileRoutes: !(this.config.verboseFileRoutes === false),\n },\n node,\n })\n\n if (transformResult.result === 'no-route-export') {\n const fileName = path.basename(node.fullPath)\n const dirName = path.dirname(node.fullPath)\n const ignorePrefix = this.config.routeFileIgnorePrefix\n const ignorePattern = this.config.routeFileIgnorePattern\n const suggestedFileName = `${ignorePrefix}${fileName}`\n const suggestedFullPath = path.join(dirName, suggestedFileName)\n\n let message = `Warning: Route file \"${node.fullPath}\" does not export a Route. This file will not be included in the route tree.`\n message += `\\n\\nIf this file is not intended to be a route, you can exclude it using one of these options:`\n message += `\\n 1. Rename the file to \"${suggestedFullPath}\" (prefix with \"${ignorePrefix}\")`\n message += `\\n 2. Use 'routeFileIgnorePattern' in your config to match this file`\n message += `\\n\\nCurrent configuration:`\n message += `\\n routeFileIgnorePrefix: \"${ignorePrefix}\"`\n message += `\\n routeFileIgnorePattern: ${ignorePattern ? `\"${ignorePattern}\"` : 'undefined'}`\n\n this.logger.warn(message)\n return null\n }\n if (transformResult.result === 'error') {\n throw new Error(\n `Error transforming route file ${node.fullPath}: ${transformResult.error}`,\n )\n }\n if (transformResult.result === 'modified') {\n updatedCacheEntry.fileContent = transformResult.output\n shouldWriteRouteFile = true\n }\n }\n\n for (const plugin of this.plugins) {\n plugin.afterTransform?.({ node, prevNode: previousCacheEntry?.node })\n }\n\n // file was changed\n if (shouldWriteRouteFile) {\n const stats = await this.safeFileWrite({\n filePath: node.fullPath,\n newContent: updatedCacheEntry.fileContent,\n strategy: {\n type: 'mtime',\n expectedMtimeMs: updatedCacheEntry.mtimeMs,\n },\n })\n updatedCacheEntry.mtimeMs = stats.mtimeMs\n }\n\n this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry)\n return {\n node,\n shouldWriteTree,\n cacheEntry: updatedCacheEntry,\n }\n }\n\n private async didRouteFileChangeComparedToCache(\n file: {\n path: string\n mtimeMs?: bigint\n },\n cache: 'routeNodeCache' | 'routeNodeShadowCache',\n ): Promise<FileCacheChange<RouteNodeCacheEntry>> {\n const cacheEntry = this[cache].get(file.path)\n return this.didFileChangeComparedToCache(file, cacheEntry)\n }\n\n private async didFileChangeComparedToCache<\n TCacheEntry extends GeneratorCacheEntry,\n >(\n file: {\n path: string\n mtimeMs?: bigint\n },\n cacheEntry: TCacheEntry | undefined,\n ): Promise<FileCacheChange<TCacheEntry>> {\n // for now we rely on the modification time of the file\n // to determine if the file has changed\n // we could also compare the file content but this would be slower as we would have to read the file\n\n if (!cacheEntry) {\n return { result: 'file-not-in-cache' }\n }\n let mtimeMs = file.mtimeMs\n\n if (mtimeMs === undefined) {\n try {\n const currentStat = await this.fs.stat(file.path)\n mtimeMs = currentStat.mtimeMs\n } catch {\n return { result: 'cannot-stat-file' }\n }\n }\n return { result: mtimeMs !== cacheEntry.mtimeMs, mtimeMs, cacheEntry }\n }\n\n private async safeFileWrite(opts: {\n filePath: string\n newContent: string\n strategy:\n | {\n type: 'mtime'\n expectedMtimeMs: bigint\n }\n | {\n type: 'new-file'\n }\n }) {\n const tmpPath = this.getTempFileName(opts.filePath)\n await this.fs.writeFile(tmpPath, opts.newContent)\n\n if (opts.strategy.type === 'mtime') {\n const beforeStat = await this.fs.stat(opts.filePath)\n if (beforeStat.mtimeMs !== opts.strategy.expectedMtimeMs) {\n throw rerun({\n msg: `File ${opts.filePath} was modified by another process during processing.`,\n event: { type: 'update', path: opts.filePath },\n })\n }\n const newFileState = await this.fs.stat(tmpPath)\n if (newFileState.mode !== beforeStat.mode) {\n await this.fs.chmod(tmpPath, beforeStat.mode)\n }\n if (\n newFileState.uid !== beforeStat.uid ||\n newFileState.gid !== beforeStat.gid\n ) {\n try {\n await this.fs.chown(tmpPath, beforeStat.uid, beforeStat.gid)\n } catch (err) {\n if (\n typeof err === 'object' &&\n err !== null &&\n 'code' in err &&\n (err as any).code === 'EPERM'\n ) {\n console.warn(\n `[safeFileWrite] chown failed: ${(err as any).message}`,\n )\n } else {\n throw err\n }\n }\n }\n } else {\n if (await checkFileExists(opts.filePath)) {\n throw rerun({\n msg: `File ${opts.filePath} already exists. Cannot overwrite.`,\n event: { type: 'update', path: opts.filePath },\n })\n }\n }\n\n const stat = await this.fs.stat(tmpPath)\n\n await this.fs.rename(tmpPath, opts.filePath)\n\n return stat\n }\n\n private getTempFileName(filePath: string) {\n const absPath = path.resolve(filePath)\n const hash = crypto.createHash('md5').update(absPath).digest('hex')\n // lazy initialize sessionId to only create tmpDir when it is first needed\n if (!this.sessionId) {\n // ensure the directory exists\n mkdirSync(this.config.tmpDir, { recursive: true })\n this.sessionId = crypto.randomBytes(4).toString('hex')\n }\n return path.join(this.config.tmpDir, `${this.sessionId}-${hash}`)\n }\n\n private async isRouteFileCacheFresh(node: RouteNode): Promise<\n | {\n status: 'fresh'\n cacheEntry: RouteNodeCacheEntry\n }\n | { status: 'stale'; cacheEntry?: RouteNodeCacheEntry }\n > {\n const fileChangedCache = await this.didRouteFileChangeComparedToCache(\n { path: node.fullPath },\n 'routeNodeCache',\n )\n if (fileChangedCache.result === false) {\n this.routeNodeShadowCache.set(node.fullPath, fileChangedCache.cacheEntry)\n return {\n status: 'fresh',\n cacheEntry: fileChangedCache.cacheEntry,\n }\n }\n if (fileChangedCache.result === 'cannot-stat-file') {\n throw new Error(`⚠️ expected route file to exist at ${node.fullPath}`)\n }\n const mtimeMs =\n fileChangedCache.result === true ? fileChangedCache.mtimeMs : undefined\n\n const shadowCacheFileChange = await this.didRouteFileChangeComparedToCache(\n { path: node.fullPath, mtimeMs },\n 'routeNodeShadowCache',\n )\n\n if (shadowCacheFileChange.result === 'cannot-stat-file') {\n throw new Error(`⚠️ expected route file to exist at ${node.fullPath}`)\n }\n\n if (shadowCacheFileChange.result === false) {\n // shadow cache has latest file state already\n if (fileChangedCache.result === true) {\n return {\n status: 'fresh',\n cacheEntry: shadowCacheFileChange.cacheEntry,\n }\n }\n }\n\n if (fileChangedCache.result === 'file-not-in-cache') {\n return {\n status: 'stale',\n }\n }\n return { status: 'stale', cacheEntry: fileChangedCache.cacheEntry }\n }\n\n private async handleRootNode(node: RouteNode) {\n const result = await this.isRouteFileCacheFresh(node)\n\n if (result.status === 'fresh') {\n this.routeNodeShadowCache.set(node.fullPath, result.cacheEntry)\n }\n const rootNodeFile = await this.fs.readFile(node.fullPath)\n if (rootNodeFile === 'file-not-existing') {\n throw new Error(`⚠️ expected root route to exist at ${node.fullPath}`)\n }\n\n const updatedCacheEntry: RouteNodeCacheEntry = {\n fileContent: rootNodeFile.fileContent,\n mtimeMs: rootNodeFile.stat.mtimeMs,\n routeId: node.routePath ?? '$$TSR_NO_ROOT_ROUTE_PATH_ASSIGNED$$',\n node,\n }\n\n // scaffold the root route\n if (!rootNodeFile.fileContent) {\n const rootTemplate = this.targetTemplate.rootRoute\n const rootRouteContent = await fillTemplate(\n this.config,\n rootTemplate.template(),\n {\n tsrImports: rootTemplate.imports.tsrImports(),\n tsrPath: rootPathId,\n tsrExportStart: rootTemplate.imports.tsrExportStart(),\n tsrExportEnd: rootTemplate.imports.tsrExportEnd(),\n },\n )\n\n this.logger.log(`🟡 Creating ${node.fullPath}`)\n const stats = await this.safeFileWrite({\n filePath: node.fullPath,\n newContent: rootRouteContent,\n strategy: {\n type: 'mtime',\n expectedMtimeMs: rootNodeFile.stat.mtimeMs,\n },\n })\n updatedCacheEntry.fileContent = rootRouteContent\n updatedCacheEntry.mtimeMs = stats.mtimeMs\n }\n\n this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry)\n }\n\n public async getCrawlingResult(): Promise<CrawlingResult | undefined> {\n await this.runPromise\n return this.crawlingResult\n }\n\n private static handleNode(\n node: RouteNode,\n acc: HandleNodeAccumulator,\n prefixMap: RoutePrefixMap,\n config?: Config,\n ) {\n let parentRoute = hasParentRoute(prefixMap, node, node.routePath)\n\n // Fallback: check acc.routeNodesByPath for parents not in prefixMap\n // This handles virtual routes created from lazy-only files that weren't\n // in the initial prefixMap build\n if (!parentRoute && node.routePath) {\n let searchPath = node.routePath\n while (searchPath.length > 0) {\n const lastSlash = searchPath.lastIndexOf('/')\n if (lastSlash <= 0) break\n searchPath = searchPath.substring(0, lastSlash)\n const candidate = acc.routeNodesByPath.get(searchPath)\n if (candidate && candidate.routePath !== node.routePath) {\n parentRoute = candidate\n break\n }\n }\n }\n\n if (parentRoute) node.parent = parentRoute\n\n node.path = determineNodePath(node)\n\n const trimmedPath = trimPathLeft(node.path ?? '')\n const trimmedOriginalPath = trimPathLeft(\n node.originalRoutePath?.replace(\n node.parent?.originalRoutePath ?? '',\n '',\n ) ?? '',\n )\n\n const split = trimmedPath.split('/')\n const originalSplit = trimmedOriginalPath.split('/')\n const lastRouteSegment = split[split.length - 1] ?? trimmedPath\n const lastOriginalSegment =\n originalSplit[originalSplit.length - 1] ?? trimmedOriginalPath\n\n // A segment is non-path if it starts with underscore AND the underscore is not escaped\n node.isNonPath =\n isSegmentPathless(lastRouteSegment, lastOriginalSegment) ||\n split.every((part) => this.routeGroupPatternRegex.test(part))\n\n // Use escape-aware functions to compute cleanedPath\n node.cleanedPath = removeGroups(\n removeUnderscoresWithEscape(\n removeLayoutSegmentsWithEscape(node.path, node.originalRoutePath),\n node.originalRoutePath,\n ),\n )\n\n if (\n node._fsRouteType === 'layout' ||\n node._fsRouteType === 'pathless_layout'\n ) {\n node.cleanedPath = removeTrailingSlash(node.cleanedPath)\n }\n\n if (\n !node.isVirtual &&\n (\n [\n 'lazy',\n 'loader',\n 'component',\n 'pendingComponent',\n 'errorComponent',\n 'notFoundComponent',\n ] satisfies Array<FsRouteType>\n ).some((d) => d === node._fsRouteType)\n ) {\n acc.routePiecesByPath[node.routePath!] =\n acc.routePiecesByPath[node.routePath!] || {}\n\n const pieceKey =\n node._fsRouteType === 'lazy'\n ? 'lazy'\n : (node._fsRouteType as keyof (typeof acc.routePiecesByPath)[string])\n acc.routePiecesByPath[node.routePath!]![pieceKey] = node\n\n const anchorRoute = acc.routeNodesByPath.get(node.routePath!)\n\n // Don't create virtual routes for root route component pieces - the root route is handled separately\n if (!anchorRoute && node.routePath !== `/${rootPathId}`) {\n this.handleNode(\n {\n ...node,\n isVirtual: true,\n _fsRouteType: 'static',\n },\n acc,\n prefixMap,\n config,\n )\n }\n return\n }\n\n const isPathlessLayoutWithPath =\n node._fsRouteType === 'pathless_layout' &&\n node.cleanedPath &&\n node.cleanedPath.length > 0\n\n // Special handling: pathless layouts with path need to find real ancestor\n if (!node.isVirtual && isPathlessLayoutWithPath) {\n const immediateParentPath =\n removeLastSegmentFromPath(node.routePath) || '/'\n const immediateParentOriginalPath =\n removeLastSegmentFromPath(node.originalRoutePath) || '/'\n let searchPath = immediateParentPath\n\n // Find nearest real (non-virtual, non-index) parent\n while (searchPath) {\n const candidate = acc.routeNodesByPath.get(searchPath)\n if (candidate && !candidate.isVirtual && candidate.path !== '/') {\n node.parent = candidate\n node.path =\n node.routePath?.replace(candidate.routePath ?? '', '') || '/'\n const pathRelativeToParent =\n immediateParentPath.replace(candidate.routePath ?? '', '') || '/'\n const originalPathRelativeToParent =\n immediateParentOriginalPath.replace(\n candidate.originalRoutePath ?? '',\n '',\n ) || '/'\n node.cleanedPath = removeGroups(\n removeUnderscoresWithEscape(\n removeLayoutSegmentsWithEscape(\n pathRelativeToParent,\n originalPathRelativeToParent,\n ),\n originalPathRelativeToParent,\n ),\n )\n break\n }\n if (searchPath === '/') break\n searchPath = removeLastSegmentFromPath(searchPath) || '/'\n }\n }\n\n // Add to parent's children or to root\n if (node.parent) {\n node.parent.children = node.parent.children ?? []\n node.parent.children.push(node)\n } else {\n acc.routeTree.push(node)\n }\n\n acc.routeNodes.push(node)\n if (node.routePath) {\n // Always register routes by path so child routes can find parents.\n // Virtual routes (created from lazy-only files) also need to be registered\n // so that index routes like path.index.lazy.tsx can find their parent path.lazy.tsx.\n // If a non-virtual route is later processed for the same path, it will overwrite.\n acc.routeNodesByPath.set(node.routePath, node)\n }\n }\n\n // only process files that are relevant for the route tree generation\n private isFileRelevantForRouteTreeGeneration(filePath: string): boolean {\n // the generated route tree file\n if (filePath === this.generatedRouteTreePath) {\n return true\n }\n\n // files inside the routes folder\n if (filePath.startsWith(this.routesDirectoryPath)) {\n return true\n }\n\n // the virtual route config file passed into `virtualRouteConfig`\n if (\n typeof this.config.virtualRouteConfig === 'string' &&\n filePath === this.config.virtualRouteConfig\n ) {\n return true\n }\n\n // this covers all files that are mounted via `virtualRouteConfig` or any `__virtual.ts` files\n if (this.routeNodeCache.has(filePath)) {\n return true\n }\n\n // virtual config files such as`__virtual.ts`\n if (isVirtualConfigFile(path.basename(filePath))) {\n return true\n }\n\n // route files inside directories mounted via `physical()` inside a virtual route config\n if (this.physicalDirectories.some((dir) => filePath.startsWith(dir))) {\n return true\n }\n\n return false\n }\n}\n"],"names":["fsp","logging","getTargetTemplate","createTokenRegex","existsSync","mkdirSync","virtualGetRouteNodes","physicalGetRouteNodes","rootPathId","multiSortBy","RoutePrefixMap","format","getImportForRouteNode","isRouteNodeValidForAugmentation","buildRouteTreeConfig","findParent","replaceBackslash","removeExt","createRouteNodesByFullPath","createRouteNodesByTo","createRouteNodesById","getResolvedRouteNodeVariableName","rootRouteId","buildFileRoutesByPathInterface","checkRouteFullPathUniqueness","mergeImportDeclarations","buildImportString","moduleAugmentation","getImportPath","fillTemplate","transform","checkFileExists","hasParentRoute","determineNodePath","trimPathLeft","isSegmentPathless","removeGroups","removeUnderscoresWithEscape","removeLayoutSegmentsWithEscape","removeTrailingSlash","removeLastSegmentFromPath","isVirtualConfigFile"],"mappings":"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"}
1
+ {"version":3,"file":"generator.cjs","sources":["../../src/generator.ts"],"sourcesContent":["import path from 'node:path'\nimport * as fsp from 'node:fs/promises'\nimport { existsSync, mkdirSync } from 'node:fs'\nimport crypto from 'node:crypto'\nimport { rootRouteId } from '@tanstack/router-core'\nimport { logging } from './logger'\nimport {\n isVirtualConfigFile,\n getRouteNodes as physicalGetRouteNodes,\n} from './filesystem/physical/getRouteNodes'\nimport { getRouteNodes as virtualGetRouteNodes } from './filesystem/virtual/getRouteNodes'\nimport { rootPathId } from './filesystem/physical/rootPathId'\nimport {\n RoutePrefixMap,\n buildFileRoutesByPathInterface,\n buildImportString,\n buildRouteTreeConfig,\n checkFileExists,\n checkRouteFullPathUniqueness,\n createRouteNodesByFullPath,\n createRouteNodesById,\n createRouteNodesByTo,\n createTokenRegex,\n determineNodePath,\n findParent,\n format,\n getImportForRouteNode,\n getImportPath,\n getResolvedRouteNodeVariableName,\n hasParentRoute,\n isRouteNodeValidForAugmentation,\n isSegmentPathless,\n mergeImportDeclarations,\n multiSortBy,\n removeExt,\n removeGroups,\n removeLastSegmentFromPath,\n removeLayoutSegmentsWithEscape,\n removeTrailingSlash,\n removeUnderscoresWithEscape,\n replaceBackslash,\n trimPathLeft,\n} from './utils'\nimport { fillTemplate, getTargetTemplate } from './template'\nimport { transform } from './transform/transform'\nimport type { GeneratorPlugin } from './plugin/types'\nimport type { TargetTemplate } from './template'\nimport type {\n FsRouteType,\n GetRouteNodesResult,\n GetRoutesByFileMapResult,\n HandleNodeAccumulator,\n ImportDeclaration,\n RouteNode,\n} from './types'\nimport type { Config } from './config'\nimport type { Logger } from './logger'\n\ninterface fs {\n stat: (\n filePath: string,\n ) => Promise<{ mtimeMs: bigint; mode: number; uid: number; gid: number }>\n rename: (oldPath: string, newPath: string) => Promise<void>\n writeFile: (filePath: string, content: string) => Promise<void>\n readFile: (\n filePath: string,\n ) => Promise<\n { stat: { mtimeMs: bigint }; fileContent: string } | 'file-not-existing'\n >\n chmod: (filePath: string, mode: number) => Promise<void>\n chown: (filePath: string, uid: number, gid: number) => Promise<void>\n}\n\nconst DefaultFileSystem: fs = {\n stat: async (filePath) => {\n const res = await fsp.stat(filePath, { bigint: true })\n return {\n mtimeMs: res.mtimeMs,\n mode: Number(res.mode),\n uid: Number(res.uid),\n gid: Number(res.gid),\n }\n },\n rename: (oldPath, newPath) => fsp.rename(oldPath, newPath),\n writeFile: (filePath, content) => fsp.writeFile(filePath, content),\n readFile: async (filePath: string) => {\n try {\n const fileHandle = await fsp.open(filePath, 'r')\n const stat = await fileHandle.stat({ bigint: true })\n const fileContent = (await fileHandle.readFile()).toString()\n await fileHandle.close()\n return { stat, fileContent }\n } catch (e: any) {\n if ('code' in e) {\n if (e.code === 'ENOENT') {\n return 'file-not-existing'\n }\n }\n throw e\n }\n },\n chmod: (filePath, mode) => fsp.chmod(filePath, mode),\n chown: (filePath, uid, gid) => fsp.chown(filePath, uid, gid),\n}\n\ninterface Rerun {\n rerun: true\n msg?: string\n event: GeneratorEvent\n}\nfunction rerun(opts: { msg?: string; event?: GeneratorEvent }): Rerun {\n const { event, ...rest } = opts\n return { rerun: true, event: event ?? { type: 'rerun' }, ...rest }\n}\n\nfunction isRerun(result: unknown): result is Rerun {\n return (\n typeof result === 'object' &&\n result !== null &&\n 'rerun' in result &&\n result.rerun === true\n )\n}\n\nexport type FileEventType = 'create' | 'update' | 'delete'\nexport type FileEvent = {\n type: FileEventType\n path: string\n}\nexport type GeneratorEvent = FileEvent | { type: 'rerun' }\n\ntype FileCacheChange<TCacheEntry extends GeneratorCacheEntry> =\n | {\n result: false\n cacheEntry: TCacheEntry\n }\n | { result: true; mtimeMs: bigint; cacheEntry: TCacheEntry }\n | {\n result: 'file-not-in-cache'\n }\n | {\n result: 'cannot-stat-file'\n }\n\ninterface GeneratorCacheEntry {\n mtimeMs: bigint\n fileContent: string\n}\n\ninterface RouteNodeCacheEntry extends GeneratorCacheEntry {\n routeId: string\n node: RouteNode\n}\n\ntype GeneratorRouteNodeCache = Map</** filePath **/ string, RouteNodeCacheEntry>\n\ninterface CrawlingResult {\n rootRouteNode: RouteNode\n routeFileResult: Array<RouteNode>\n acc: HandleNodeAccumulator\n}\n\nexport class Generator {\n /**\n * why do we have two caches for the route files?\n * During processing, we READ from the cache and WRITE to the shadow cache.\n *\n * After a route file is processed, we write to the shadow cache.\n * If during processing we bail out and re-run, we don't lose this modification\n * but still can track whether the file contributed changes and thus the route tree file needs to be regenerated.\n * After all files are processed, we swap the shadow cache with the main cache and initialize a new shadow cache.\n * That way we also ensure deleted/renamed files don't stay in the cache forever.\n */\n private routeNodeCache: GeneratorRouteNodeCache = new Map()\n private routeNodeShadowCache: GeneratorRouteNodeCache = new Map()\n\n private routeTreeFileCache: GeneratorCacheEntry | undefined\n\n private crawlingResult: CrawlingResult | undefined\n public config: Config\n public targetTemplate: TargetTemplate\n\n private root: string\n private routesDirectoryPath: string\n private sessionId?: string\n private fs: fs\n private logger: Logger\n private generatedRouteTreePath: string\n private runPromise: Promise<void> | undefined\n private fileEventQueue: Array<GeneratorEvent> = []\n private plugins: Array<GeneratorPlugin> = []\n private static routeGroupPatternRegex = /\\(.+\\)/\n private physicalDirectories: Array<string> = []\n\n /**\n * Token regexes are pre-compiled once here and reused throughout route processing.\n * We need TWO types of regex for each token because they match against different inputs:\n *\n * 1. FILENAME regexes: Match token patterns within full file path strings.\n * Example: For file \"routes/dashboard.index.tsx\", we want to detect \".index.\"\n * Pattern: `[./](?:token)[.]` - matches token bounded by path separators/dots\n * Used in: sorting route nodes by file path\n *\n * 2. SEGMENT regexes: Match token against a single logical route segment.\n * Example: For segment \"index\" (extracted from path), match the whole segment\n * Pattern: `^(?:token)$` - matches entire segment exactly\n * Used in: route parsing, determining route types, escape detection\n *\n * We cannot reuse one for the other without false positives or missing matches.\n */\n private indexTokenFilenameRegex: RegExp\n private routeTokenFilenameRegex: RegExp\n private indexTokenSegmentRegex: RegExp\n private routeTokenSegmentRegex: RegExp\n private static componentPieceRegex =\n /[./](component|errorComponent|notFoundComponent|pendingComponent|loader|lazy)[.]/\n\n constructor(opts: { config: Config; root: string; fs?: fs }) {\n this.config = opts.config\n this.logger = logging({ disabled: this.config.disableLogging })\n this.root = opts.root\n this.fs = opts.fs || DefaultFileSystem\n this.generatedRouteTreePath = this.getGeneratedRouteTreePath()\n this.targetTemplate = getTargetTemplate(this.config)\n\n this.routesDirectoryPath = this.getRoutesDirectoryPath()\n this.plugins.push(...(opts.config.plugins || []))\n\n // Create all token regexes once in constructor\n this.indexTokenFilenameRegex = createTokenRegex(this.config.indexToken, {\n type: 'filename',\n })\n this.routeTokenFilenameRegex = createTokenRegex(this.config.routeToken, {\n type: 'filename',\n })\n this.indexTokenSegmentRegex = createTokenRegex(this.config.indexToken, {\n type: 'segment',\n })\n this.routeTokenSegmentRegex = createTokenRegex(this.config.routeToken, {\n type: 'segment',\n })\n\n for (const plugin of this.plugins) {\n plugin.init?.({ generator: this })\n }\n }\n\n private getGeneratedRouteTreePath() {\n const generatedRouteTreePath = path.isAbsolute(\n this.config.generatedRouteTree,\n )\n ? this.config.generatedRouteTree\n : path.resolve(this.root, this.config.generatedRouteTree)\n\n const generatedRouteTreeDir = path.dirname(generatedRouteTreePath)\n\n if (!existsSync(generatedRouteTreeDir)) {\n mkdirSync(generatedRouteTreeDir, { recursive: true })\n }\n\n return generatedRouteTreePath\n }\n\n private getRoutesDirectoryPath() {\n return path.isAbsolute(this.config.routesDirectory)\n ? this.config.routesDirectory\n : path.resolve(this.root, this.config.routesDirectory)\n }\n\n public getRoutesByFileMap(): GetRoutesByFileMapResult {\n return new Map(\n [...this.routeNodeCache.entries()].map(([filePath, cacheEntry]) => [\n filePath,\n { routePath: cacheEntry.routeId },\n ]),\n )\n }\n\n public async run(event?: GeneratorEvent): Promise<void> {\n if (\n event &&\n event.type !== 'rerun' &&\n !this.isFileRelevantForRouteTreeGeneration(event.path)\n ) {\n return\n }\n this.fileEventQueue.push(event ?? { type: 'rerun' })\n // only allow a single run at a time\n if (this.runPromise) {\n return this.runPromise\n }\n\n this.runPromise = (async () => {\n do {\n // synchronously copy and clear the queue since we are going to iterate asynchronously over it\n // and while we do so, a new event could be put into the queue\n const tempQueue = this.fileEventQueue\n this.fileEventQueue = []\n // if we only have 'update' events in the queue\n // and we already have the affected files' latest state in our cache, we can exit early\n const remainingEvents = (\n await Promise.all(\n tempQueue.map(async (e) => {\n if (e.type === 'update') {\n let cacheEntry: GeneratorCacheEntry | undefined\n if (e.path === this.generatedRouteTreePath) {\n cacheEntry = this.routeTreeFileCache\n } else {\n // we only check the routeNodeCache here\n // if the file's state is only up-to-date in the shadow cache we need to re-run\n cacheEntry = this.routeNodeCache.get(e.path)\n }\n const change = await this.didFileChangeComparedToCache(\n { path: e.path },\n cacheEntry,\n )\n if (change.result === false) {\n return null\n }\n }\n return e\n }),\n )\n ).filter((e) => e !== null)\n\n if (remainingEvents.length === 0) {\n break\n }\n\n try {\n await this.generatorInternal()\n } catch (err) {\n const errArray = !Array.isArray(err) ? [err] : err\n\n const recoverableErrors = errArray.filter((e) => isRerun(e))\n if (recoverableErrors.length === errArray.length) {\n this.fileEventQueue.push(...recoverableErrors.map((e) => e.event))\n recoverableErrors.forEach((e) => {\n if (e.msg) {\n this.logger.info(e.msg)\n }\n })\n } else {\n const unrecoverableErrors = errArray.filter((e) => !isRerun(e))\n this.runPromise = undefined\n throw new Error(\n unrecoverableErrors.map((e) => (e as Error).message).join(),\n )\n }\n }\n } while (this.fileEventQueue.length)\n this.runPromise = undefined\n })()\n return this.runPromise\n }\n\n private async generatorInternal() {\n let writeRouteTreeFile: boolean | 'force' = false\n\n let getRouteNodesResult: GetRouteNodesResult\n\n if (this.config.virtualRouteConfig) {\n getRouteNodesResult = await virtualGetRouteNodes(this.config, this.root, {\n indexTokenSegmentRegex: this.indexTokenSegmentRegex,\n routeTokenSegmentRegex: this.routeTokenSegmentRegex,\n })\n } else {\n getRouteNodesResult = await physicalGetRouteNodes(\n this.config,\n this.root,\n {\n indexTokenSegmentRegex: this.indexTokenSegmentRegex,\n routeTokenSegmentRegex: this.routeTokenSegmentRegex,\n },\n )\n }\n\n const {\n rootRouteNode,\n routeNodes: beforeRouteNodes,\n physicalDirectories,\n } = getRouteNodesResult\n if (rootRouteNode === undefined) {\n let errorMessage = `rootRouteNode must not be undefined. Make sure you've added your root route into the route-tree.`\n if (!this.config.virtualRouteConfig) {\n errorMessage += `\\nMake sure that you add a \"${rootPathId}.${this.config.disableTypes ? 'js' : 'tsx'}\" file to your routes directory.\\nAdd the file in: \"${this.config.routesDirectory}/${rootPathId}.${this.config.disableTypes ? 'js' : 'tsx'}\"`\n }\n throw new Error(errorMessage)\n }\n this.physicalDirectories = physicalDirectories\n\n await this.handleRootNode(rootRouteNode)\n\n const preRouteNodes = multiSortBy(beforeRouteNodes, [\n (d) => (d.routePath === '/' ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => (d.filePath.match(this.indexTokenFilenameRegex) ? 1 : -1),\n (d) => (d.filePath.match(Generator.componentPieceRegex) ? 1 : -1),\n (d) => (d.filePath.match(this.routeTokenFilenameRegex) ? -1 : 1),\n (d) => (d.routePath?.endsWith('/') ? -1 : 1),\n (d) => d.routePath,\n ]).filter((d) => {\n // Exclude the root route itself, but keep component/loader pieces for the root\n if (d.routePath === `/${rootPathId}`) {\n return [\n 'component',\n 'errorComponent',\n 'notFoundComponent',\n 'pendingComponent',\n 'loader',\n 'lazy',\n ].includes(d._fsRouteType)\n }\n return true\n })\n\n const routeFileAllResult = await Promise.allSettled(\n preRouteNodes\n // only process routes that are backed by an actual file\n .filter((n) => !n.isVirtualParentRoute && !n.isVirtual)\n .map((n) => this.processRouteNodeFile(n)),\n )\n\n const rejections = routeFileAllResult.filter(\n (result) => result.status === 'rejected',\n )\n if (rejections.length > 0) {\n throw rejections.map((e) => e.reason)\n }\n\n const routeFileResult = routeFileAllResult.flatMap((result) => {\n if (result.status === 'fulfilled' && result.value !== null) {\n if (result.value.shouldWriteTree) {\n writeRouteTreeFile = true\n }\n return result.value.node\n }\n return []\n })\n\n // reset children in case we re-use a node from the cache\n routeFileResult.forEach((r) => (r.children = undefined))\n\n const acc: HandleNodeAccumulator = {\n routeTree: [],\n routeNodes: [],\n routePiecesByPath: {},\n routeNodesByPath: new Map(),\n }\n\n const prefixMap = new RoutePrefixMap(routeFileResult)\n\n for (const node of routeFileResult) {\n Generator.handleNode(node, acc, prefixMap, this.config)\n }\n\n this.crawlingResult = { rootRouteNode, routeFileResult, acc }\n\n // this is the first time the generator runs, so read in the route tree file if it exists yet\n if (!this.routeTreeFileCache) {\n const routeTreeFile = await this.fs.readFile(this.generatedRouteTreePath)\n if (routeTreeFile !== 'file-not-existing') {\n this.routeTreeFileCache = {\n fileContent: routeTreeFile.fileContent,\n mtimeMs: routeTreeFile.stat.mtimeMs,\n }\n }\n writeRouteTreeFile = true\n } else {\n const routeTreeFileChange = await this.didFileChangeComparedToCache(\n { path: this.generatedRouteTreePath },\n this.routeTreeFileCache,\n )\n if (routeTreeFileChange.result !== false) {\n writeRouteTreeFile = 'force'\n if (routeTreeFileChange.result === true) {\n const routeTreeFile = await this.fs.readFile(\n this.generatedRouteTreePath,\n )\n if (routeTreeFile !== 'file-not-existing') {\n this.routeTreeFileCache = {\n fileContent: routeTreeFile.fileContent,\n mtimeMs: routeTreeFile.stat.mtimeMs,\n }\n }\n }\n }\n }\n\n if (!writeRouteTreeFile) {\n // only needs to be done if no other changes have been detected yet\n // compare shadowCache and cache to identify deleted routes\n if (this.routeNodeCache.size !== this.routeNodeShadowCache.size) {\n writeRouteTreeFile = true\n } else {\n for (const fullPath of this.routeNodeCache.keys()) {\n if (!this.routeNodeShadowCache.has(fullPath)) {\n writeRouteTreeFile = true\n break\n }\n }\n }\n }\n\n if (!writeRouteTreeFile) {\n this.swapCaches()\n return\n }\n\n const buildResult = this.buildRouteTree({\n rootRouteNode,\n acc,\n routeFileResult,\n })\n let routeTreeContent = buildResult.routeTreeContent\n\n routeTreeContent = this.config.enableRouteTreeFormatting\n ? await format(routeTreeContent, this.config)\n : routeTreeContent\n\n let newMtimeMs: bigint | undefined\n if (this.routeTreeFileCache) {\n if (\n writeRouteTreeFile !== 'force' &&\n this.routeTreeFileCache.fileContent === routeTreeContent\n ) {\n // existing route tree file is already up-to-date, don't write it\n // we should only get here in the initial run when the route cache is not filled yet\n } else {\n const newRouteTreeFileStat = await this.safeFileWrite({\n filePath: this.generatedRouteTreePath,\n newContent: routeTreeContent,\n strategy: {\n type: 'mtime',\n expectedMtimeMs: this.routeTreeFileCache.mtimeMs,\n },\n })\n newMtimeMs = newRouteTreeFileStat.mtimeMs\n }\n } else {\n const newRouteTreeFileStat = await this.safeFileWrite({\n filePath: this.generatedRouteTreePath,\n newContent: routeTreeContent,\n strategy: {\n type: 'new-file',\n },\n })\n newMtimeMs = newRouteTreeFileStat.mtimeMs\n }\n\n if (newMtimeMs !== undefined) {\n this.routeTreeFileCache = {\n fileContent: routeTreeContent,\n mtimeMs: newMtimeMs,\n }\n }\n\n this.plugins.map((plugin) => {\n return plugin.onRouteTreeChanged?.({\n routeTree: buildResult.routeTree,\n routeNodes: buildResult.routeNodes,\n acc,\n rootRouteNode,\n })\n })\n this.swapCaches()\n }\n\n private swapCaches() {\n this.routeNodeCache = this.routeNodeShadowCache\n this.routeNodeShadowCache = new Map()\n }\n\n public buildRouteTree(opts: {\n rootRouteNode: RouteNode\n acc: HandleNodeAccumulator\n routeFileResult: Array<RouteNode>\n config?: Partial<Config>\n }) {\n const config = { ...this.config, ...(opts.config || {}) }\n\n const { rootRouteNode, acc } = opts\n\n // Use pre-compiled regex if config hasn't been overridden, otherwise create new one\n const indexTokenSegmentRegex =\n config.indexToken === this.config.indexToken\n ? this.indexTokenSegmentRegex\n : createTokenRegex(config.indexToken, { type: 'segment' })\n\n const sortedRouteNodes = multiSortBy(acc.routeNodes, [\n (d) => (d.routePath?.includes(`/${rootPathId}`) ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => {\n const segments = d.routePath?.split('/').filter(Boolean) ?? []\n const last = segments[segments.length - 1] ?? ''\n return indexTokenSegmentRegex.test(last) ? -1 : 1\n },\n (d) => d,\n ])\n\n const routeImports: Array<ImportDeclaration> = []\n const virtualRouteNodes: Array<string> = []\n\n for (const node of sortedRouteNodes) {\n if (node.isVirtual) {\n virtualRouteNodes.push(\n `const ${node.variableName}RouteImport = createFileRoute('${node.routePath}')()`,\n )\n } else {\n routeImports.push(\n getImportForRouteNode(\n node,\n config,\n this.generatedRouteTreePath,\n this.root,\n ),\n )\n }\n }\n\n const imports: Array<ImportDeclaration> = []\n if (virtualRouteNodes.length > 0) {\n imports.push({\n specifiers: [{ imported: 'createFileRoute' }],\n source: this.targetTemplate.fullPkg,\n })\n }\n // Add lazyRouteComponent import if there are component pieces\n let hasComponentPieces = false\n let hasLoaderPieces = false\n for (const node of sortedRouteNodes) {\n const pieces = acc.routePiecesByPath[node.routePath!]\n if (pieces) {\n if (\n pieces.component ||\n pieces.errorComponent ||\n pieces.notFoundComponent ||\n pieces.pendingComponent\n ) {\n hasComponentPieces = true\n }\n if (pieces.loader) {\n hasLoaderPieces = true\n }\n if (hasComponentPieces && hasLoaderPieces) break\n }\n }\n if (hasComponentPieces || hasLoaderPieces) {\n const runtimeImport: ImportDeclaration = {\n specifiers: [],\n source: this.targetTemplate.fullPkg,\n }\n if (hasComponentPieces) {\n runtimeImport.specifiers.push({ imported: 'lazyRouteComponent' })\n }\n if (hasLoaderPieces) {\n runtimeImport.specifiers.push({ imported: 'lazyFn' })\n }\n imports.push(runtimeImport)\n }\n if (config.verboseFileRoutes === false) {\n const typeImport: ImportDeclaration = {\n specifiers: [],\n source: this.targetTemplate.fullPkg,\n importKind: 'type',\n }\n let needsCreateFileRoute = false\n let needsCreateLazyFileRoute = false\n for (const node of sortedRouteNodes) {\n if (isRouteNodeValidForAugmentation(node)) {\n if (node._fsRouteType !== 'lazy') {\n needsCreateFileRoute = true\n }\n if (acc.routePiecesByPath[node.routePath!]?.lazy) {\n needsCreateLazyFileRoute = true\n }\n }\n if (needsCreateFileRoute && needsCreateLazyFileRoute) break\n }\n if (needsCreateFileRoute) {\n typeImport.specifiers.push({ imported: 'CreateFileRoute' })\n }\n if (needsCreateLazyFileRoute) {\n typeImport.specifiers.push({ imported: 'CreateLazyFileRoute' })\n }\n\n if (typeImport.specifiers.length > 0) {\n typeImport.specifiers.push({ imported: 'FileRoutesByPath' })\n imports.push(typeImport)\n }\n }\n\n const routeTreeConfig = buildRouteTreeConfig(\n acc.routeTree,\n config.disableTypes,\n )\n\n const createUpdateRoutes = sortedRouteNodes.map((node) => {\n const pieces = acc.routePiecesByPath[node.routePath!]\n const loaderNode = pieces?.loader\n const componentNode = pieces?.component\n const errorComponentNode = pieces?.errorComponent\n const notFoundComponentNode = pieces?.notFoundComponent\n const pendingComponentNode = pieces?.pendingComponent\n const lazyComponentNode = pieces?.lazy\n\n return [\n [\n `const ${node.variableName}Route = ${node.variableName}RouteImport.update({\n ${[\n `id: '${node.path}'`,\n !node.isNonPath ||\n (node._fsRouteType === 'pathless_layout' && node.cleanedPath)\n ? `path: '${node.cleanedPath}'`\n : undefined,\n `getParentRoute: () => ${findParent(node)}`,\n ]\n .filter(Boolean)\n .join(',')}\n }${config.disableTypes ? '' : 'as any'})`,\n loaderNode\n ? `.updateLoader({ loader: lazyFn(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, loaderNode.filePath),\n ),\n config.addExtensions,\n ),\n )}'), 'loader') })`\n : '',\n componentNode ||\n errorComponentNode ||\n notFoundComponentNode ||\n pendingComponentNode\n ? `.update({\n ${(\n [\n ['component', componentNode],\n ['errorComponent', errorComponentNode],\n ['notFoundComponent', notFoundComponentNode],\n ['pendingComponent', pendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n // For .vue files, use 'default' as the export name since Vue SFCs export default\n const isVueFile = d[1]!.filePath.endsWith('.vue')\n const exportName = isVueFile ? 'default' : d[0]\n // Keep .vue extension for Vue files since Vite requires it\n const importPath = replaceBackslash(\n isVueFile\n ? path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n d[1]!.filePath,\n ),\n )\n : removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n d[1]!.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )\n return `${\n d[0]\n }: lazyRouteComponent(() => import('./${importPath}'), '${exportName}')`\n })\n .join('\\n,')}\n })`\n : '',\n lazyComponentNode\n ? (() => {\n // For .vue files, use 'default' export since Vue SFCs export default\n const isVueFile = lazyComponentNode.filePath.endsWith('.vue')\n const exportAccessor = isVueFile ? 'd.default' : 'd.Route'\n // Keep .vue extension for Vue files since Vite requires it\n const importPath = replaceBackslash(\n isVueFile\n ? path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n )\n : removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )\n return `.lazy(() => import('./${importPath}').then((d) => ${exportAccessor}))`\n })()\n : '',\n ].join(''),\n ].join('\\n\\n')\n })\n\n // Generate update for root route if it has component pieces\n const rootRoutePath = `/${rootPathId}`\n const rootPieces = acc.routePiecesByPath[rootRoutePath]\n const rootComponentNode = rootPieces?.component\n const rootErrorComponentNode = rootPieces?.errorComponent\n const rootNotFoundComponentNode = rootPieces?.notFoundComponent\n const rootPendingComponentNode = rootPieces?.pendingComponent\n\n let rootRouteUpdate = ''\n if (\n rootComponentNode ||\n rootErrorComponentNode ||\n rootNotFoundComponentNode ||\n rootPendingComponentNode\n ) {\n rootRouteUpdate = `const rootRouteWithChildren = rootRouteImport${\n rootComponentNode ||\n rootErrorComponentNode ||\n rootNotFoundComponentNode ||\n rootPendingComponentNode\n ? `.update({\n ${(\n [\n ['component', rootComponentNode],\n ['errorComponent', rootErrorComponentNode],\n ['notFoundComponent', rootNotFoundComponentNode],\n ['pendingComponent', rootPendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n // For .vue files, use 'default' as the export name since Vue SFCs export default\n const isVueFile = d[1]!.filePath.endsWith('.vue')\n const exportName = isVueFile ? 'default' : d[0]\n // Keep .vue extension for Vue files since Vite requires it\n const importPath = replaceBackslash(\n isVueFile\n ? path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, d[1]!.filePath),\n )\n : removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n d[1]!.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )\n return `${d[0]}: lazyRouteComponent(() => import('./${importPath}'), '${exportName}')`\n })\n .join('\\n,')}\n })`\n : ''\n }._addFileChildren(rootRouteChildren)${config.disableTypes ? '' : `._addFileTypes<FileRouteTypes>()`}`\n }\n\n let fileRoutesByPathInterface = ''\n let fileRoutesByFullPath = ''\n\n if (!config.disableTypes) {\n const routeNodesByFullPath = createRouteNodesByFullPath(acc.routeNodes)\n const routeNodesByTo = createRouteNodesByTo(acc.routeNodes)\n const routeNodesById = createRouteNodesById(acc.routeNodes)\n\n fileRoutesByFullPath = [\n `export interface FileRoutesByFullPath {\n${[...routeNodesByFullPath.entries()]\n .filter(([fullPath]) => fullPath)\n .map(([fullPath, routeNode]) => {\n return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n })}\n}`,\n `export interface FileRoutesByTo {\n${[...routeNodesByTo.entries()]\n .filter(([to]) => to)\n .map(([to, routeNode]) => {\n return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n })}\n}`,\n `export interface FileRoutesById {\n'${rootRouteId}': typeof rootRouteImport,\n${[...routeNodesById.entries()].map(([id, routeNode]) => {\n return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n})}\n}`,\n `export interface FileRouteTypes {\nfileRoutesByFullPath: FileRoutesByFullPath\nfullPaths: ${\n acc.routeNodes.length > 0\n ? [...routeNodesByFullPath.keys()]\n .filter((fullPath) => fullPath)\n .map((fullPath) => `'${fullPath}'`)\n .join('|')\n : 'never'\n }\nfileRoutesByTo: FileRoutesByTo\nto: ${\n acc.routeNodes.length > 0\n ? [...routeNodesByTo.keys()]\n .filter((to) => to)\n .map((to) => `'${to}'`)\n .join('|')\n : 'never'\n }\nid: ${[`'${rootRouteId}'`, ...[...routeNodesById.keys()].map((id) => `'${id}'`)].join('|')}\nfileRoutesById: FileRoutesById\n}`,\n `export interface RootRouteChildren {\n${acc.routeTree.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}\n}`,\n ].join('\\n')\n\n fileRoutesByPathInterface = buildFileRoutesByPathInterface({\n module: this.targetTemplate.fullPkg,\n interfaceName: 'FileRoutesByPath',\n routeNodes: sortedRouteNodes,\n config,\n })\n }\n\n const routeTree = [\n `const rootRouteChildren${config.disableTypes ? '' : `: RootRouteChildren`} = {\n ${acc.routeTree\n .map(\n (child) =>\n `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`,\n )\n .join(',')}\n}`,\n rootRouteUpdate\n ? rootRouteUpdate.replace(\n 'const rootRouteWithChildren = ',\n 'export const routeTree = ',\n )\n : `export const routeTree = rootRouteImport._addFileChildren(rootRouteChildren)${config.disableTypes ? '' : `._addFileTypes<FileRouteTypes>()`}`,\n ].join('\\n')\n\n checkRouteFullPathUniqueness(\n sortedRouteNodes.filter(\n (d) => d.children === undefined && 'lazy' !== d._fsRouteType,\n ),\n config,\n )\n\n let mergedImports = mergeImportDeclarations(imports)\n if (config.disableTypes) {\n mergedImports = mergedImports.filter((d) => d.importKind !== 'type')\n }\n\n const importStatements = mergedImports.map(buildImportString)\n\n let moduleAugmentation = ''\n if (config.verboseFileRoutes === false && !config.disableTypes) {\n moduleAugmentation = opts.routeFileResult\n .map((node) => {\n const getModuleDeclaration = (routeNode?: RouteNode) => {\n if (!isRouteNodeValidForAugmentation(routeNode)) {\n return ''\n }\n let moduleAugmentation = ''\n if (routeNode._fsRouteType === 'lazy') {\n moduleAugmentation = `const createLazyFileRoute: CreateLazyFileRoute<FileRoutesByPath['${routeNode.routePath}']['preLoaderRoute']>`\n } else {\n moduleAugmentation = `const createFileRoute: CreateFileRoute<'${routeNode.routePath}',\n FileRoutesByPath['${routeNode.routePath}']['parentRoute'],\n FileRoutesByPath['${routeNode.routePath}']['id'],\n FileRoutesByPath['${routeNode.routePath}']['path'],\n FileRoutesByPath['${routeNode.routePath}']['fullPath']\n >\n `\n }\n\n return `declare module './${getImportPath(routeNode, config, this.generatedRouteTreePath)}' {\n ${moduleAugmentation}\n }`\n }\n return getModuleDeclaration(node)\n })\n .join('\\n')\n }\n\n const rootRouteImport = getImportForRouteNode(\n rootRouteNode,\n config,\n this.generatedRouteTreePath,\n this.root,\n )\n routeImports.unshift(rootRouteImport)\n\n let footer: Array<string> = []\n if (config.routeTreeFileFooter) {\n if (Array.isArray(config.routeTreeFileFooter)) {\n footer = config.routeTreeFileFooter\n } else {\n footer = config.routeTreeFileFooter()\n }\n }\n const routeTreeContent = [\n ...config.routeTreeFileHeader,\n `// This file was automatically generated by TanStack Router.\n// You should NOT make any changes in this file as it will be overwritten.\n// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.`,\n [...importStatements].join('\\n'),\n mergeImportDeclarations(routeImports).map(buildImportString).join('\\n'),\n virtualRouteNodes.join('\\n'),\n createUpdateRoutes.join('\\n'),\n fileRoutesByFullPath,\n fileRoutesByPathInterface,\n moduleAugmentation,\n routeTreeConfig.join('\\n'),\n routeTree,\n ...footer,\n ]\n .filter(Boolean)\n .join('\\n\\n')\n return {\n routeTreeContent,\n routeTree: acc.routeTree,\n routeNodes: acc.routeNodes,\n }\n }\n\n private async processRouteNodeFile(node: RouteNode): Promise<{\n shouldWriteTree: boolean\n cacheEntry: RouteNodeCacheEntry\n node: RouteNode\n } | null> {\n const result = await this.isRouteFileCacheFresh(node)\n\n if (result.status === 'fresh') {\n return {\n node: result.cacheEntry.node,\n shouldWriteTree: false,\n cacheEntry: result.cacheEntry,\n }\n }\n\n const previousCacheEntry = result.cacheEntry\n\n const existingRouteFile = await this.fs.readFile(node.fullPath)\n if (existingRouteFile === 'file-not-existing') {\n throw new Error(`⚠️ File ${node.fullPath} does not exist`)\n }\n\n const updatedCacheEntry: RouteNodeCacheEntry = {\n fileContent: existingRouteFile.fileContent,\n mtimeMs: existingRouteFile.stat.mtimeMs,\n routeId: node.routePath ?? '$$TSR_NO_ROUTE_PATH_ASSIGNED$$',\n node,\n }\n\n const escapedRoutePath = node.routePath?.replaceAll('$', '$$') ?? ''\n\n let shouldWriteRouteFile = false\n let shouldWriteTree = false\n // now we need to either scaffold the file or transform it\n if (!existingRouteFile.fileContent) {\n shouldWriteRouteFile = true\n shouldWriteTree = true\n // Creating a new lazy route file\n if (node._fsRouteType === 'lazy') {\n const tLazyRouteTemplate = this.targetTemplate.lazyRoute\n // Check by default check if the user has a specific lazy route template\n // If not, check if the user has a route template and use that instead\n updatedCacheEntry.fileContent = await fillTemplate(\n this.config,\n (this.config.customScaffolding?.lazyRouteTemplate ||\n this.config.customScaffolding?.routeTemplate) ??\n tLazyRouteTemplate.template(),\n {\n tsrImports: tLazyRouteTemplate.imports.tsrImports(),\n tsrPath: escapedRoutePath.replaceAll(/\\{(.+?)\\}/gm, '$1'),\n tsrExportStart:\n tLazyRouteTemplate.imports.tsrExportStart(escapedRoutePath),\n tsrExportEnd: tLazyRouteTemplate.imports.tsrExportEnd(),\n },\n )\n } else if (\n // Creating a new normal route file\n (['layout', 'static'] satisfies Array<FsRouteType>).some(\n (d) => d === node._fsRouteType,\n ) ||\n (\n [\n 'component',\n 'pendingComponent',\n 'errorComponent',\n 'notFoundComponent',\n 'loader',\n ] satisfies Array<FsRouteType>\n ).every((d) => d !== node._fsRouteType)\n ) {\n const tRouteTemplate = this.targetTemplate.route\n updatedCacheEntry.fileContent = await fillTemplate(\n this.config,\n this.config.customScaffolding?.routeTemplate ??\n tRouteTemplate.template(),\n {\n tsrImports: tRouteTemplate.imports.tsrImports(),\n tsrPath: escapedRoutePath.replaceAll(/\\{(.+?)\\}/gm, '$1'),\n tsrExportStart:\n tRouteTemplate.imports.tsrExportStart(escapedRoutePath),\n tsrExportEnd: tRouteTemplate.imports.tsrExportEnd(),\n },\n )\n } else {\n return null\n }\n }\n\n // Check if this is a Vue component file\n // Vue SFC files (.vue) don't need transformation as they can't have a Route export\n const isVueFile = node.filePath.endsWith('.vue')\n\n if (!isVueFile) {\n // transform the file\n const transformResult = await transform({\n source: updatedCacheEntry.fileContent,\n ctx: {\n target: this.config.target,\n routeId: escapedRoutePath,\n lazy: node._fsRouteType === 'lazy',\n verboseFileRoutes: !(this.config.verboseFileRoutes === false),\n },\n node,\n })\n\n if (transformResult.result === 'no-route-export') {\n const fileName = path.basename(node.fullPath)\n const dirName = path.dirname(node.fullPath)\n const ignorePrefix = this.config.routeFileIgnorePrefix\n const ignorePattern = this.config.routeFileIgnorePattern\n const suggestedFileName = `${ignorePrefix}${fileName}`\n const suggestedFullPath = path.join(dirName, suggestedFileName)\n\n let message = `Warning: Route file \"${node.fullPath}\" does not export a Route. This file will not be included in the route tree.`\n message += `\\n\\nIf this file is not intended to be a route, you can exclude it using one of these options:`\n message += `\\n 1. Rename the file to \"${suggestedFullPath}\" (prefix with \"${ignorePrefix}\")`\n message += `\\n 2. Use 'routeFileIgnorePattern' in your config to match this file`\n message += `\\n\\nCurrent configuration:`\n message += `\\n routeFileIgnorePrefix: \"${ignorePrefix}\"`\n message += `\\n routeFileIgnorePattern: ${ignorePattern ? `\"${ignorePattern}\"` : 'undefined'}`\n\n this.logger.warn(message)\n return null\n }\n if (transformResult.result === 'error') {\n throw new Error(\n `Error transforming route file ${node.fullPath}: ${transformResult.error}`,\n )\n }\n if (transformResult.result === 'modified') {\n updatedCacheEntry.fileContent = transformResult.output\n shouldWriteRouteFile = true\n }\n }\n\n for (const plugin of this.plugins) {\n plugin.afterTransform?.({ node, prevNode: previousCacheEntry?.node })\n }\n\n // file was changed\n if (shouldWriteRouteFile) {\n const stats = await this.safeFileWrite({\n filePath: node.fullPath,\n newContent: updatedCacheEntry.fileContent,\n strategy: {\n type: 'mtime',\n expectedMtimeMs: updatedCacheEntry.mtimeMs,\n },\n })\n updatedCacheEntry.mtimeMs = stats.mtimeMs\n }\n\n this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry)\n return {\n node,\n shouldWriteTree,\n cacheEntry: updatedCacheEntry,\n }\n }\n\n private async didRouteFileChangeComparedToCache(\n file: {\n path: string\n mtimeMs?: bigint\n },\n cache: 'routeNodeCache' | 'routeNodeShadowCache',\n ): Promise<FileCacheChange<RouteNodeCacheEntry>> {\n const cacheEntry = this[cache].get(file.path)\n return this.didFileChangeComparedToCache(file, cacheEntry)\n }\n\n private async didFileChangeComparedToCache<\n TCacheEntry extends GeneratorCacheEntry,\n >(\n file: {\n path: string\n mtimeMs?: bigint\n },\n cacheEntry: TCacheEntry | undefined,\n ): Promise<FileCacheChange<TCacheEntry>> {\n // for now we rely on the modification time of the file\n // to determine if the file has changed\n // we could also compare the file content but this would be slower as we would have to read the file\n\n if (!cacheEntry) {\n return { result: 'file-not-in-cache' }\n }\n let mtimeMs = file.mtimeMs\n\n if (mtimeMs === undefined) {\n try {\n const currentStat = await this.fs.stat(file.path)\n mtimeMs = currentStat.mtimeMs\n } catch {\n return { result: 'cannot-stat-file' }\n }\n }\n return { result: mtimeMs !== cacheEntry.mtimeMs, mtimeMs, cacheEntry }\n }\n\n private async safeFileWrite(opts: {\n filePath: string\n newContent: string\n strategy:\n | {\n type: 'mtime'\n expectedMtimeMs: bigint\n }\n | {\n type: 'new-file'\n }\n }) {\n const tmpPath = this.getTempFileName(opts.filePath)\n await this.fs.writeFile(tmpPath, opts.newContent)\n\n if (opts.strategy.type === 'mtime') {\n const beforeStat = await this.fs.stat(opts.filePath)\n if (beforeStat.mtimeMs !== opts.strategy.expectedMtimeMs) {\n throw rerun({\n msg: `File ${opts.filePath} was modified by another process during processing.`,\n event: { type: 'update', path: opts.filePath },\n })\n }\n const newFileState = await this.fs.stat(tmpPath)\n if (newFileState.mode !== beforeStat.mode) {\n await this.fs.chmod(tmpPath, beforeStat.mode)\n }\n if (\n newFileState.uid !== beforeStat.uid ||\n newFileState.gid !== beforeStat.gid\n ) {\n try {\n await this.fs.chown(tmpPath, beforeStat.uid, beforeStat.gid)\n } catch (err) {\n if (\n typeof err === 'object' &&\n err !== null &&\n 'code' in err &&\n (err as any).code === 'EPERM'\n ) {\n console.warn(\n `[safeFileWrite] chown failed: ${(err as any).message}`,\n )\n } else {\n throw err\n }\n }\n }\n } else {\n if (await checkFileExists(opts.filePath)) {\n throw rerun({\n msg: `File ${opts.filePath} already exists. Cannot overwrite.`,\n event: { type: 'update', path: opts.filePath },\n })\n }\n }\n\n const stat = await this.fs.stat(tmpPath)\n\n await this.fs.rename(tmpPath, opts.filePath)\n\n return stat\n }\n\n private getTempFileName(filePath: string) {\n const absPath = path.resolve(filePath)\n const hash = crypto.createHash('md5').update(absPath).digest('hex')\n // lazy initialize sessionId to only create tmpDir when it is first needed\n if (!this.sessionId) {\n // ensure the directory exists\n mkdirSync(this.config.tmpDir, { recursive: true })\n this.sessionId = crypto.randomBytes(4).toString('hex')\n }\n return path.join(this.config.tmpDir, `${this.sessionId}-${hash}`)\n }\n\n private async isRouteFileCacheFresh(node: RouteNode): Promise<\n | {\n status: 'fresh'\n cacheEntry: RouteNodeCacheEntry\n }\n | { status: 'stale'; cacheEntry?: RouteNodeCacheEntry }\n > {\n const fileChangedCache = await this.didRouteFileChangeComparedToCache(\n { path: node.fullPath },\n 'routeNodeCache',\n )\n if (fileChangedCache.result === false) {\n this.routeNodeShadowCache.set(node.fullPath, fileChangedCache.cacheEntry)\n return {\n status: 'fresh',\n cacheEntry: fileChangedCache.cacheEntry,\n }\n }\n if (fileChangedCache.result === 'cannot-stat-file') {\n throw new Error(`⚠️ expected route file to exist at ${node.fullPath}`)\n }\n const mtimeMs =\n fileChangedCache.result === true ? fileChangedCache.mtimeMs : undefined\n\n const shadowCacheFileChange = await this.didRouteFileChangeComparedToCache(\n { path: node.fullPath, mtimeMs },\n 'routeNodeShadowCache',\n )\n\n if (shadowCacheFileChange.result === 'cannot-stat-file') {\n throw new Error(`⚠️ expected route file to exist at ${node.fullPath}`)\n }\n\n if (shadowCacheFileChange.result === false) {\n // shadow cache has latest file state already\n if (fileChangedCache.result === true) {\n return {\n status: 'fresh',\n cacheEntry: shadowCacheFileChange.cacheEntry,\n }\n }\n }\n\n if (fileChangedCache.result === 'file-not-in-cache') {\n return {\n status: 'stale',\n }\n }\n return { status: 'stale', cacheEntry: fileChangedCache.cacheEntry }\n }\n\n private async handleRootNode(node: RouteNode) {\n const result = await this.isRouteFileCacheFresh(node)\n\n if (result.status === 'fresh') {\n this.routeNodeShadowCache.set(node.fullPath, result.cacheEntry)\n }\n const rootNodeFile = await this.fs.readFile(node.fullPath)\n if (rootNodeFile === 'file-not-existing') {\n throw new Error(`⚠️ expected root route to exist at ${node.fullPath}`)\n }\n\n const updatedCacheEntry: RouteNodeCacheEntry = {\n fileContent: rootNodeFile.fileContent,\n mtimeMs: rootNodeFile.stat.mtimeMs,\n routeId: node.routePath ?? '$$TSR_NO_ROOT_ROUTE_PATH_ASSIGNED$$',\n node,\n }\n\n // scaffold the root route\n if (!rootNodeFile.fileContent) {\n const rootTemplate = this.targetTemplate.rootRoute\n const rootRouteContent = await fillTemplate(\n this.config,\n rootTemplate.template(),\n {\n tsrImports: rootTemplate.imports.tsrImports(),\n tsrPath: rootPathId,\n tsrExportStart: rootTemplate.imports.tsrExportStart(),\n tsrExportEnd: rootTemplate.imports.tsrExportEnd(),\n },\n )\n\n this.logger.log(`🟡 Creating ${node.fullPath}`)\n const stats = await this.safeFileWrite({\n filePath: node.fullPath,\n newContent: rootRouteContent,\n strategy: {\n type: 'mtime',\n expectedMtimeMs: rootNodeFile.stat.mtimeMs,\n },\n })\n updatedCacheEntry.fileContent = rootRouteContent\n updatedCacheEntry.mtimeMs = stats.mtimeMs\n }\n\n this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry)\n }\n\n public async getCrawlingResult(): Promise<CrawlingResult | undefined> {\n await this.runPromise\n return this.crawlingResult\n }\n\n private static handleNode(\n node: RouteNode,\n acc: HandleNodeAccumulator,\n prefixMap: RoutePrefixMap,\n config?: Config,\n ) {\n let parentRoute = hasParentRoute(prefixMap, node, node.routePath)\n\n // Check routeNodesByPath for a closer parent that may not be in prefixMap.\n //\n // Why: The prefixMap excludes lazy routes by design. When lazy-only routes are\n // nested inside a pathless layout, the virtual route created from the lazy file\n // won't be in the prefixMap, but it will be in routeNodesByPath.\n //\n // Example: Given files _layout/path.lazy.tsx and _layout/path.index.lazy.tsx:\n // - prefixMap contains: /_layout (from route.tsx)\n // - routeNodesByPath contains: /_layout AND /_layout/path (virtual from lazy)\n // - For /_layout/path/, hasParentRoute returns /_layout (wrong)\n // - But the correct parent is /_layout/path (the virtual route from path.lazy.tsx)\n //\n // Optimization: Only search if we might find a closer parent. The search walks\n // up from the immediate parent path, so if the first candidate matches what\n // prefixMap found, there's no closer parent to find.\n if (node.routePath) {\n const lastSlash = node.routePath.lastIndexOf('/')\n if (lastSlash > 0) {\n const immediateParentPath = node.routePath.substring(0, lastSlash)\n const candidate = acc.routeNodesByPath.get(immediateParentPath)\n if (\n candidate &&\n candidate.routePath !== node.routePath &&\n candidate !== parentRoute\n ) {\n // Found a closer parent in routeNodesByPath that differs from prefixMap result\n parentRoute = candidate\n }\n }\n }\n\n if (parentRoute) node.parent = parentRoute\n\n node.path = determineNodePath(node)\n\n const trimmedPath = trimPathLeft(node.path ?? '')\n const trimmedOriginalPath = trimPathLeft(\n node.originalRoutePath?.replace(\n node.parent?.originalRoutePath ?? '',\n '',\n ) ?? '',\n )\n\n const split = trimmedPath.split('/')\n const originalSplit = trimmedOriginalPath.split('/')\n const lastRouteSegment = split[split.length - 1] ?? trimmedPath\n const lastOriginalSegment =\n originalSplit[originalSplit.length - 1] ?? trimmedOriginalPath\n\n // A segment is non-path if it starts with underscore AND the underscore is not escaped\n node.isNonPath =\n isSegmentPathless(lastRouteSegment, lastOriginalSegment) ||\n split.every((part) => this.routeGroupPatternRegex.test(part))\n\n // Use escape-aware functions to compute cleanedPath\n node.cleanedPath = removeGroups(\n removeUnderscoresWithEscape(\n removeLayoutSegmentsWithEscape(node.path, node.originalRoutePath),\n node.originalRoutePath,\n ),\n )\n\n if (\n node._fsRouteType === 'layout' ||\n node._fsRouteType === 'pathless_layout'\n ) {\n node.cleanedPath = removeTrailingSlash(node.cleanedPath)\n }\n\n if (\n !node.isVirtual &&\n (\n [\n 'lazy',\n 'loader',\n 'component',\n 'pendingComponent',\n 'errorComponent',\n 'notFoundComponent',\n ] satisfies Array<FsRouteType>\n ).some((d) => d === node._fsRouteType)\n ) {\n acc.routePiecesByPath[node.routePath!] =\n acc.routePiecesByPath[node.routePath!] || {}\n\n const pieceKey =\n node._fsRouteType === 'lazy'\n ? 'lazy'\n : (node._fsRouteType as keyof (typeof acc.routePiecesByPath)[string])\n acc.routePiecesByPath[node.routePath!]![pieceKey] = node\n\n const anchorRoute = acc.routeNodesByPath.get(node.routePath!)\n\n // Don't create virtual routes for root route component pieces - the root route is handled separately\n if (!anchorRoute && node.routePath !== `/${rootPathId}`) {\n this.handleNode(\n {\n ...node,\n isVirtual: true,\n _fsRouteType: 'static',\n },\n acc,\n prefixMap,\n config,\n )\n }\n return\n }\n\n const isPathlessLayoutWithPath =\n node._fsRouteType === 'pathless_layout' &&\n node.cleanedPath &&\n node.cleanedPath.length > 0\n\n // Special handling: pathless layouts with path need to find real ancestor\n if (!node.isVirtual && isPathlessLayoutWithPath) {\n const immediateParentPath =\n removeLastSegmentFromPath(node.routePath) || '/'\n const immediateParentOriginalPath =\n removeLastSegmentFromPath(node.originalRoutePath) || '/'\n let searchPath = immediateParentPath\n\n // Find nearest real (non-virtual, non-index) parent\n while (searchPath) {\n const candidate = acc.routeNodesByPath.get(searchPath)\n if (candidate && !candidate.isVirtual && candidate.path !== '/') {\n node.parent = candidate\n node.path =\n node.routePath?.replace(candidate.routePath ?? '', '') || '/'\n const pathRelativeToParent =\n immediateParentPath.replace(candidate.routePath ?? '', '') || '/'\n const originalPathRelativeToParent =\n immediateParentOriginalPath.replace(\n candidate.originalRoutePath ?? '',\n '',\n ) || '/'\n node.cleanedPath = removeGroups(\n removeUnderscoresWithEscape(\n removeLayoutSegmentsWithEscape(\n pathRelativeToParent,\n originalPathRelativeToParent,\n ),\n originalPathRelativeToParent,\n ),\n )\n break\n }\n if (searchPath === '/') break\n searchPath = removeLastSegmentFromPath(searchPath) || '/'\n }\n }\n\n // Add to parent's children or to root\n if (node.parent) {\n node.parent.children = node.parent.children ?? []\n node.parent.children.push(node)\n } else {\n acc.routeTree.push(node)\n }\n\n acc.routeNodes.push(node)\n if (node.routePath) {\n // Always register routes by path so child routes can find parents.\n // Virtual routes (created from lazy-only files) also need to be registered\n // so that index routes like path.index.lazy.tsx can find their parent path.lazy.tsx.\n // If a non-virtual route is later processed for the same path, it will overwrite.\n acc.routeNodesByPath.set(node.routePath, node)\n }\n }\n\n // only process files that are relevant for the route tree generation\n private isFileRelevantForRouteTreeGeneration(filePath: string): boolean {\n // the generated route tree file\n if (filePath === this.generatedRouteTreePath) {\n return true\n }\n\n // files inside the routes folder\n if (filePath.startsWith(this.routesDirectoryPath)) {\n return true\n }\n\n // the virtual route config file passed into `virtualRouteConfig`\n if (\n typeof this.config.virtualRouteConfig === 'string' &&\n filePath === this.config.virtualRouteConfig\n ) {\n return true\n }\n\n // this covers all files that are mounted via `virtualRouteConfig` or any `__virtual.ts` files\n if (this.routeNodeCache.has(filePath)) {\n return true\n }\n\n // virtual config files such as`__virtual.ts`\n if (isVirtualConfigFile(path.basename(filePath))) {\n return true\n }\n\n // route files inside directories mounted via `physical()` inside a virtual route config\n if (this.physicalDirectories.some((dir) => filePath.startsWith(dir))) {\n return true\n }\n\n return false\n }\n}\n"],"names":["fsp","logging","getTargetTemplate","createTokenRegex","existsSync","mkdirSync","virtualGetRouteNodes","physicalGetRouteNodes","rootPathId","multiSortBy","RoutePrefixMap","format","getImportForRouteNode","isRouteNodeValidForAugmentation","buildRouteTreeConfig","findParent","replaceBackslash","removeExt","createRouteNodesByFullPath","createRouteNodesByTo","createRouteNodesById","getResolvedRouteNodeVariableName","rootRouteId","buildFileRoutesByPathInterface","checkRouteFullPathUniqueness","mergeImportDeclarations","buildImportString","moduleAugmentation","getImportPath","fillTemplate","transform","checkFileExists","hasParentRoute","determineNodePath","trimPathLeft","isSegmentPathless","removeGroups","removeUnderscoresWithEscape","removeLayoutSegmentsWithEscape","removeTrailingSlash","removeLastSegmentFromPath","isVirtualConfigFile"],"mappings":"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"}
@@ -971,16 +971,13 @@ Current configuration:`;
971
971
  }
972
972
  static handleNode(node, acc, prefixMap, config) {
973
973
  let parentRoute = hasParentRoute(prefixMap, node, node.routePath);
974
- if (!parentRoute && node.routePath) {
975
- let searchPath = node.routePath;
976
- while (searchPath.length > 0) {
977
- const lastSlash = searchPath.lastIndexOf("/");
978
- if (lastSlash <= 0) break;
979
- searchPath = searchPath.substring(0, lastSlash);
980
- const candidate = acc.routeNodesByPath.get(searchPath);
981
- if (candidate && candidate.routePath !== node.routePath) {
974
+ if (node.routePath) {
975
+ const lastSlash = node.routePath.lastIndexOf("/");
976
+ if (lastSlash > 0) {
977
+ const immediateParentPath = node.routePath.substring(0, lastSlash);
978
+ const candidate = acc.routeNodesByPath.get(immediateParentPath);
979
+ if (candidate && candidate.routePath !== node.routePath && candidate !== parentRoute) {
982
980
  parentRoute = candidate;
983
- break;
984
981
  }
985
982
  }
986
983
  }
@@ -1 +1 @@
1
- {"version":3,"file":"generator.js","sources":["../../src/generator.ts"],"sourcesContent":["import path from 'node:path'\nimport * as fsp from 'node:fs/promises'\nimport { existsSync, mkdirSync } from 'node:fs'\nimport crypto from 'node:crypto'\nimport { rootRouteId } from '@tanstack/router-core'\nimport { logging } from './logger'\nimport {\n isVirtualConfigFile,\n getRouteNodes as physicalGetRouteNodes,\n} from './filesystem/physical/getRouteNodes'\nimport { getRouteNodes as virtualGetRouteNodes } from './filesystem/virtual/getRouteNodes'\nimport { rootPathId } from './filesystem/physical/rootPathId'\nimport {\n RoutePrefixMap,\n buildFileRoutesByPathInterface,\n buildImportString,\n buildRouteTreeConfig,\n checkFileExists,\n checkRouteFullPathUniqueness,\n createRouteNodesByFullPath,\n createRouteNodesById,\n createRouteNodesByTo,\n createTokenRegex,\n determineNodePath,\n findParent,\n format,\n getImportForRouteNode,\n getImportPath,\n getResolvedRouteNodeVariableName,\n hasParentRoute,\n isRouteNodeValidForAugmentation,\n isSegmentPathless,\n mergeImportDeclarations,\n multiSortBy,\n removeExt,\n removeGroups,\n removeLastSegmentFromPath,\n removeLayoutSegmentsWithEscape,\n removeTrailingSlash,\n removeUnderscoresWithEscape,\n replaceBackslash,\n trimPathLeft,\n} from './utils'\nimport { fillTemplate, getTargetTemplate } from './template'\nimport { transform } from './transform/transform'\nimport type { GeneratorPlugin } from './plugin/types'\nimport type { TargetTemplate } from './template'\nimport type {\n FsRouteType,\n GetRouteNodesResult,\n GetRoutesByFileMapResult,\n HandleNodeAccumulator,\n ImportDeclaration,\n RouteNode,\n} from './types'\nimport type { Config } from './config'\nimport type { Logger } from './logger'\n\ninterface fs {\n stat: (\n filePath: string,\n ) => Promise<{ mtimeMs: bigint; mode: number; uid: number; gid: number }>\n rename: (oldPath: string, newPath: string) => Promise<void>\n writeFile: (filePath: string, content: string) => Promise<void>\n readFile: (\n filePath: string,\n ) => Promise<\n { stat: { mtimeMs: bigint }; fileContent: string } | 'file-not-existing'\n >\n chmod: (filePath: string, mode: number) => Promise<void>\n chown: (filePath: string, uid: number, gid: number) => Promise<void>\n}\n\nconst DefaultFileSystem: fs = {\n stat: async (filePath) => {\n const res = await fsp.stat(filePath, { bigint: true })\n return {\n mtimeMs: res.mtimeMs,\n mode: Number(res.mode),\n uid: Number(res.uid),\n gid: Number(res.gid),\n }\n },\n rename: (oldPath, newPath) => fsp.rename(oldPath, newPath),\n writeFile: (filePath, content) => fsp.writeFile(filePath, content),\n readFile: async (filePath: string) => {\n try {\n const fileHandle = await fsp.open(filePath, 'r')\n const stat = await fileHandle.stat({ bigint: true })\n const fileContent = (await fileHandle.readFile()).toString()\n await fileHandle.close()\n return { stat, fileContent }\n } catch (e: any) {\n if ('code' in e) {\n if (e.code === 'ENOENT') {\n return 'file-not-existing'\n }\n }\n throw e\n }\n },\n chmod: (filePath, mode) => fsp.chmod(filePath, mode),\n chown: (filePath, uid, gid) => fsp.chown(filePath, uid, gid),\n}\n\ninterface Rerun {\n rerun: true\n msg?: string\n event: GeneratorEvent\n}\nfunction rerun(opts: { msg?: string; event?: GeneratorEvent }): Rerun {\n const { event, ...rest } = opts\n return { rerun: true, event: event ?? { type: 'rerun' }, ...rest }\n}\n\nfunction isRerun(result: unknown): result is Rerun {\n return (\n typeof result === 'object' &&\n result !== null &&\n 'rerun' in result &&\n result.rerun === true\n )\n}\n\nexport type FileEventType = 'create' | 'update' | 'delete'\nexport type FileEvent = {\n type: FileEventType\n path: string\n}\nexport type GeneratorEvent = FileEvent | { type: 'rerun' }\n\ntype FileCacheChange<TCacheEntry extends GeneratorCacheEntry> =\n | {\n result: false\n cacheEntry: TCacheEntry\n }\n | { result: true; mtimeMs: bigint; cacheEntry: TCacheEntry }\n | {\n result: 'file-not-in-cache'\n }\n | {\n result: 'cannot-stat-file'\n }\n\ninterface GeneratorCacheEntry {\n mtimeMs: bigint\n fileContent: string\n}\n\ninterface RouteNodeCacheEntry extends GeneratorCacheEntry {\n routeId: string\n node: RouteNode\n}\n\ntype GeneratorRouteNodeCache = Map</** filePath **/ string, RouteNodeCacheEntry>\n\ninterface CrawlingResult {\n rootRouteNode: RouteNode\n routeFileResult: Array<RouteNode>\n acc: HandleNodeAccumulator\n}\n\nexport class Generator {\n /**\n * why do we have two caches for the route files?\n * During processing, we READ from the cache and WRITE to the shadow cache.\n *\n * After a route file is processed, we write to the shadow cache.\n * If during processing we bail out and re-run, we don't lose this modification\n * but still can track whether the file contributed changes and thus the route tree file needs to be regenerated.\n * After all files are processed, we swap the shadow cache with the main cache and initialize a new shadow cache.\n * That way we also ensure deleted/renamed files don't stay in the cache forever.\n */\n private routeNodeCache: GeneratorRouteNodeCache = new Map()\n private routeNodeShadowCache: GeneratorRouteNodeCache = new Map()\n\n private routeTreeFileCache: GeneratorCacheEntry | undefined\n\n private crawlingResult: CrawlingResult | undefined\n public config: Config\n public targetTemplate: TargetTemplate\n\n private root: string\n private routesDirectoryPath: string\n private sessionId?: string\n private fs: fs\n private logger: Logger\n private generatedRouteTreePath: string\n private runPromise: Promise<void> | undefined\n private fileEventQueue: Array<GeneratorEvent> = []\n private plugins: Array<GeneratorPlugin> = []\n private static routeGroupPatternRegex = /\\(.+\\)/\n private physicalDirectories: Array<string> = []\n\n /**\n * Token regexes are pre-compiled once here and reused throughout route processing.\n * We need TWO types of regex for each token because they match against different inputs:\n *\n * 1. FILENAME regexes: Match token patterns within full file path strings.\n * Example: For file \"routes/dashboard.index.tsx\", we want to detect \".index.\"\n * Pattern: `[./](?:token)[.]` - matches token bounded by path separators/dots\n * Used in: sorting route nodes by file path\n *\n * 2. SEGMENT regexes: Match token against a single logical route segment.\n * Example: For segment \"index\" (extracted from path), match the whole segment\n * Pattern: `^(?:token)$` - matches entire segment exactly\n * Used in: route parsing, determining route types, escape detection\n *\n * We cannot reuse one for the other without false positives or missing matches.\n */\n private indexTokenFilenameRegex: RegExp\n private routeTokenFilenameRegex: RegExp\n private indexTokenSegmentRegex: RegExp\n private routeTokenSegmentRegex: RegExp\n private static componentPieceRegex =\n /[./](component|errorComponent|notFoundComponent|pendingComponent|loader|lazy)[.]/\n\n constructor(opts: { config: Config; root: string; fs?: fs }) {\n this.config = opts.config\n this.logger = logging({ disabled: this.config.disableLogging })\n this.root = opts.root\n this.fs = opts.fs || DefaultFileSystem\n this.generatedRouteTreePath = this.getGeneratedRouteTreePath()\n this.targetTemplate = getTargetTemplate(this.config)\n\n this.routesDirectoryPath = this.getRoutesDirectoryPath()\n this.plugins.push(...(opts.config.plugins || []))\n\n // Create all token regexes once in constructor\n this.indexTokenFilenameRegex = createTokenRegex(this.config.indexToken, {\n type: 'filename',\n })\n this.routeTokenFilenameRegex = createTokenRegex(this.config.routeToken, {\n type: 'filename',\n })\n this.indexTokenSegmentRegex = createTokenRegex(this.config.indexToken, {\n type: 'segment',\n })\n this.routeTokenSegmentRegex = createTokenRegex(this.config.routeToken, {\n type: 'segment',\n })\n\n for (const plugin of this.plugins) {\n plugin.init?.({ generator: this })\n }\n }\n\n private getGeneratedRouteTreePath() {\n const generatedRouteTreePath = path.isAbsolute(\n this.config.generatedRouteTree,\n )\n ? this.config.generatedRouteTree\n : path.resolve(this.root, this.config.generatedRouteTree)\n\n const generatedRouteTreeDir = path.dirname(generatedRouteTreePath)\n\n if (!existsSync(generatedRouteTreeDir)) {\n mkdirSync(generatedRouteTreeDir, { recursive: true })\n }\n\n return generatedRouteTreePath\n }\n\n private getRoutesDirectoryPath() {\n return path.isAbsolute(this.config.routesDirectory)\n ? this.config.routesDirectory\n : path.resolve(this.root, this.config.routesDirectory)\n }\n\n public getRoutesByFileMap(): GetRoutesByFileMapResult {\n return new Map(\n [...this.routeNodeCache.entries()].map(([filePath, cacheEntry]) => [\n filePath,\n { routePath: cacheEntry.routeId },\n ]),\n )\n }\n\n public async run(event?: GeneratorEvent): Promise<void> {\n if (\n event &&\n event.type !== 'rerun' &&\n !this.isFileRelevantForRouteTreeGeneration(event.path)\n ) {\n return\n }\n this.fileEventQueue.push(event ?? { type: 'rerun' })\n // only allow a single run at a time\n if (this.runPromise) {\n return this.runPromise\n }\n\n this.runPromise = (async () => {\n do {\n // synchronously copy and clear the queue since we are going to iterate asynchronously over it\n // and while we do so, a new event could be put into the queue\n const tempQueue = this.fileEventQueue\n this.fileEventQueue = []\n // if we only have 'update' events in the queue\n // and we already have the affected files' latest state in our cache, we can exit early\n const remainingEvents = (\n await Promise.all(\n tempQueue.map(async (e) => {\n if (e.type === 'update') {\n let cacheEntry: GeneratorCacheEntry | undefined\n if (e.path === this.generatedRouteTreePath) {\n cacheEntry = this.routeTreeFileCache\n } else {\n // we only check the routeNodeCache here\n // if the file's state is only up-to-date in the shadow cache we need to re-run\n cacheEntry = this.routeNodeCache.get(e.path)\n }\n const change = await this.didFileChangeComparedToCache(\n { path: e.path },\n cacheEntry,\n )\n if (change.result === false) {\n return null\n }\n }\n return e\n }),\n )\n ).filter((e) => e !== null)\n\n if (remainingEvents.length === 0) {\n break\n }\n\n try {\n await this.generatorInternal()\n } catch (err) {\n const errArray = !Array.isArray(err) ? [err] : err\n\n const recoverableErrors = errArray.filter((e) => isRerun(e))\n if (recoverableErrors.length === errArray.length) {\n this.fileEventQueue.push(...recoverableErrors.map((e) => e.event))\n recoverableErrors.forEach((e) => {\n if (e.msg) {\n this.logger.info(e.msg)\n }\n })\n } else {\n const unrecoverableErrors = errArray.filter((e) => !isRerun(e))\n this.runPromise = undefined\n throw new Error(\n unrecoverableErrors.map((e) => (e as Error).message).join(),\n )\n }\n }\n } while (this.fileEventQueue.length)\n this.runPromise = undefined\n })()\n return this.runPromise\n }\n\n private async generatorInternal() {\n let writeRouteTreeFile: boolean | 'force' = false\n\n let getRouteNodesResult: GetRouteNodesResult\n\n if (this.config.virtualRouteConfig) {\n getRouteNodesResult = await virtualGetRouteNodes(this.config, this.root, {\n indexTokenSegmentRegex: this.indexTokenSegmentRegex,\n routeTokenSegmentRegex: this.routeTokenSegmentRegex,\n })\n } else {\n getRouteNodesResult = await physicalGetRouteNodes(\n this.config,\n this.root,\n {\n indexTokenSegmentRegex: this.indexTokenSegmentRegex,\n routeTokenSegmentRegex: this.routeTokenSegmentRegex,\n },\n )\n }\n\n const {\n rootRouteNode,\n routeNodes: beforeRouteNodes,\n physicalDirectories,\n } = getRouteNodesResult\n if (rootRouteNode === undefined) {\n let errorMessage = `rootRouteNode must not be undefined. Make sure you've added your root route into the route-tree.`\n if (!this.config.virtualRouteConfig) {\n errorMessage += `\\nMake sure that you add a \"${rootPathId}.${this.config.disableTypes ? 'js' : 'tsx'}\" file to your routes directory.\\nAdd the file in: \"${this.config.routesDirectory}/${rootPathId}.${this.config.disableTypes ? 'js' : 'tsx'}\"`\n }\n throw new Error(errorMessage)\n }\n this.physicalDirectories = physicalDirectories\n\n await this.handleRootNode(rootRouteNode)\n\n const preRouteNodes = multiSortBy(beforeRouteNodes, [\n (d) => (d.routePath === '/' ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => (d.filePath.match(this.indexTokenFilenameRegex) ? 1 : -1),\n (d) => (d.filePath.match(Generator.componentPieceRegex) ? 1 : -1),\n (d) => (d.filePath.match(this.routeTokenFilenameRegex) ? -1 : 1),\n (d) => (d.routePath?.endsWith('/') ? -1 : 1),\n (d) => d.routePath,\n ]).filter((d) => {\n // Exclude the root route itself, but keep component/loader pieces for the root\n if (d.routePath === `/${rootPathId}`) {\n return [\n 'component',\n 'errorComponent',\n 'notFoundComponent',\n 'pendingComponent',\n 'loader',\n 'lazy',\n ].includes(d._fsRouteType)\n }\n return true\n })\n\n const routeFileAllResult = await Promise.allSettled(\n preRouteNodes\n // only process routes that are backed by an actual file\n .filter((n) => !n.isVirtualParentRoute && !n.isVirtual)\n .map((n) => this.processRouteNodeFile(n)),\n )\n\n const rejections = routeFileAllResult.filter(\n (result) => result.status === 'rejected',\n )\n if (rejections.length > 0) {\n throw rejections.map((e) => e.reason)\n }\n\n const routeFileResult = routeFileAllResult.flatMap((result) => {\n if (result.status === 'fulfilled' && result.value !== null) {\n if (result.value.shouldWriteTree) {\n writeRouteTreeFile = true\n }\n return result.value.node\n }\n return []\n })\n\n // reset children in case we re-use a node from the cache\n routeFileResult.forEach((r) => (r.children = undefined))\n\n const acc: HandleNodeAccumulator = {\n routeTree: [],\n routeNodes: [],\n routePiecesByPath: {},\n routeNodesByPath: new Map(),\n }\n\n const prefixMap = new RoutePrefixMap(routeFileResult)\n\n for (const node of routeFileResult) {\n Generator.handleNode(node, acc, prefixMap, this.config)\n }\n\n this.crawlingResult = { rootRouteNode, routeFileResult, acc }\n\n // this is the first time the generator runs, so read in the route tree file if it exists yet\n if (!this.routeTreeFileCache) {\n const routeTreeFile = await this.fs.readFile(this.generatedRouteTreePath)\n if (routeTreeFile !== 'file-not-existing') {\n this.routeTreeFileCache = {\n fileContent: routeTreeFile.fileContent,\n mtimeMs: routeTreeFile.stat.mtimeMs,\n }\n }\n writeRouteTreeFile = true\n } else {\n const routeTreeFileChange = await this.didFileChangeComparedToCache(\n { path: this.generatedRouteTreePath },\n this.routeTreeFileCache,\n )\n if (routeTreeFileChange.result !== false) {\n writeRouteTreeFile = 'force'\n if (routeTreeFileChange.result === true) {\n const routeTreeFile = await this.fs.readFile(\n this.generatedRouteTreePath,\n )\n if (routeTreeFile !== 'file-not-existing') {\n this.routeTreeFileCache = {\n fileContent: routeTreeFile.fileContent,\n mtimeMs: routeTreeFile.stat.mtimeMs,\n }\n }\n }\n }\n }\n\n if (!writeRouteTreeFile) {\n // only needs to be done if no other changes have been detected yet\n // compare shadowCache and cache to identify deleted routes\n if (this.routeNodeCache.size !== this.routeNodeShadowCache.size) {\n writeRouteTreeFile = true\n } else {\n for (const fullPath of this.routeNodeCache.keys()) {\n if (!this.routeNodeShadowCache.has(fullPath)) {\n writeRouteTreeFile = true\n break\n }\n }\n }\n }\n\n if (!writeRouteTreeFile) {\n this.swapCaches()\n return\n }\n\n const buildResult = this.buildRouteTree({\n rootRouteNode,\n acc,\n routeFileResult,\n })\n let routeTreeContent = buildResult.routeTreeContent\n\n routeTreeContent = this.config.enableRouteTreeFormatting\n ? await format(routeTreeContent, this.config)\n : routeTreeContent\n\n let newMtimeMs: bigint | undefined\n if (this.routeTreeFileCache) {\n if (\n writeRouteTreeFile !== 'force' &&\n this.routeTreeFileCache.fileContent === routeTreeContent\n ) {\n // existing route tree file is already up-to-date, don't write it\n // we should only get here in the initial run when the route cache is not filled yet\n } else {\n const newRouteTreeFileStat = await this.safeFileWrite({\n filePath: this.generatedRouteTreePath,\n newContent: routeTreeContent,\n strategy: {\n type: 'mtime',\n expectedMtimeMs: this.routeTreeFileCache.mtimeMs,\n },\n })\n newMtimeMs = newRouteTreeFileStat.mtimeMs\n }\n } else {\n const newRouteTreeFileStat = await this.safeFileWrite({\n filePath: this.generatedRouteTreePath,\n newContent: routeTreeContent,\n strategy: {\n type: 'new-file',\n },\n })\n newMtimeMs = newRouteTreeFileStat.mtimeMs\n }\n\n if (newMtimeMs !== undefined) {\n this.routeTreeFileCache = {\n fileContent: routeTreeContent,\n mtimeMs: newMtimeMs,\n }\n }\n\n this.plugins.map((plugin) => {\n return plugin.onRouteTreeChanged?.({\n routeTree: buildResult.routeTree,\n routeNodes: buildResult.routeNodes,\n acc,\n rootRouteNode,\n })\n })\n this.swapCaches()\n }\n\n private swapCaches() {\n this.routeNodeCache = this.routeNodeShadowCache\n this.routeNodeShadowCache = new Map()\n }\n\n public buildRouteTree(opts: {\n rootRouteNode: RouteNode\n acc: HandleNodeAccumulator\n routeFileResult: Array<RouteNode>\n config?: Partial<Config>\n }) {\n const config = { ...this.config, ...(opts.config || {}) }\n\n const { rootRouteNode, acc } = opts\n\n // Use pre-compiled regex if config hasn't been overridden, otherwise create new one\n const indexTokenSegmentRegex =\n config.indexToken === this.config.indexToken\n ? this.indexTokenSegmentRegex\n : createTokenRegex(config.indexToken, { type: 'segment' })\n\n const sortedRouteNodes = multiSortBy(acc.routeNodes, [\n (d) => (d.routePath?.includes(`/${rootPathId}`) ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => {\n const segments = d.routePath?.split('/').filter(Boolean) ?? []\n const last = segments[segments.length - 1] ?? ''\n return indexTokenSegmentRegex.test(last) ? -1 : 1\n },\n (d) => d,\n ])\n\n const routeImports: Array<ImportDeclaration> = []\n const virtualRouteNodes: Array<string> = []\n\n for (const node of sortedRouteNodes) {\n if (node.isVirtual) {\n virtualRouteNodes.push(\n `const ${node.variableName}RouteImport = createFileRoute('${node.routePath}')()`,\n )\n } else {\n routeImports.push(\n getImportForRouteNode(\n node,\n config,\n this.generatedRouteTreePath,\n this.root,\n ),\n )\n }\n }\n\n const imports: Array<ImportDeclaration> = []\n if (virtualRouteNodes.length > 0) {\n imports.push({\n specifiers: [{ imported: 'createFileRoute' }],\n source: this.targetTemplate.fullPkg,\n })\n }\n // Add lazyRouteComponent import if there are component pieces\n let hasComponentPieces = false\n let hasLoaderPieces = false\n for (const node of sortedRouteNodes) {\n const pieces = acc.routePiecesByPath[node.routePath!]\n if (pieces) {\n if (\n pieces.component ||\n pieces.errorComponent ||\n pieces.notFoundComponent ||\n pieces.pendingComponent\n ) {\n hasComponentPieces = true\n }\n if (pieces.loader) {\n hasLoaderPieces = true\n }\n if (hasComponentPieces && hasLoaderPieces) break\n }\n }\n if (hasComponentPieces || hasLoaderPieces) {\n const runtimeImport: ImportDeclaration = {\n specifiers: [],\n source: this.targetTemplate.fullPkg,\n }\n if (hasComponentPieces) {\n runtimeImport.specifiers.push({ imported: 'lazyRouteComponent' })\n }\n if (hasLoaderPieces) {\n runtimeImport.specifiers.push({ imported: 'lazyFn' })\n }\n imports.push(runtimeImport)\n }\n if (config.verboseFileRoutes === false) {\n const typeImport: ImportDeclaration = {\n specifiers: [],\n source: this.targetTemplate.fullPkg,\n importKind: 'type',\n }\n let needsCreateFileRoute = false\n let needsCreateLazyFileRoute = false\n for (const node of sortedRouteNodes) {\n if (isRouteNodeValidForAugmentation(node)) {\n if (node._fsRouteType !== 'lazy') {\n needsCreateFileRoute = true\n }\n if (acc.routePiecesByPath[node.routePath!]?.lazy) {\n needsCreateLazyFileRoute = true\n }\n }\n if (needsCreateFileRoute && needsCreateLazyFileRoute) break\n }\n if (needsCreateFileRoute) {\n typeImport.specifiers.push({ imported: 'CreateFileRoute' })\n }\n if (needsCreateLazyFileRoute) {\n typeImport.specifiers.push({ imported: 'CreateLazyFileRoute' })\n }\n\n if (typeImport.specifiers.length > 0) {\n typeImport.specifiers.push({ imported: 'FileRoutesByPath' })\n imports.push(typeImport)\n }\n }\n\n const routeTreeConfig = buildRouteTreeConfig(\n acc.routeTree,\n config.disableTypes,\n )\n\n const createUpdateRoutes = sortedRouteNodes.map((node) => {\n const pieces = acc.routePiecesByPath[node.routePath!]\n const loaderNode = pieces?.loader\n const componentNode = pieces?.component\n const errorComponentNode = pieces?.errorComponent\n const notFoundComponentNode = pieces?.notFoundComponent\n const pendingComponentNode = pieces?.pendingComponent\n const lazyComponentNode = pieces?.lazy\n\n return [\n [\n `const ${node.variableName}Route = ${node.variableName}RouteImport.update({\n ${[\n `id: '${node.path}'`,\n !node.isNonPath ||\n (node._fsRouteType === 'pathless_layout' && node.cleanedPath)\n ? `path: '${node.cleanedPath}'`\n : undefined,\n `getParentRoute: () => ${findParent(node)}`,\n ]\n .filter(Boolean)\n .join(',')}\n }${config.disableTypes ? '' : 'as any'})`,\n loaderNode\n ? `.updateLoader({ loader: lazyFn(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, loaderNode.filePath),\n ),\n config.addExtensions,\n ),\n )}'), 'loader') })`\n : '',\n componentNode ||\n errorComponentNode ||\n notFoundComponentNode ||\n pendingComponentNode\n ? `.update({\n ${(\n [\n ['component', componentNode],\n ['errorComponent', errorComponentNode],\n ['notFoundComponent', notFoundComponentNode],\n ['pendingComponent', pendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n // For .vue files, use 'default' as the export name since Vue SFCs export default\n const isVueFile = d[1]!.filePath.endsWith('.vue')\n const exportName = isVueFile ? 'default' : d[0]\n // Keep .vue extension for Vue files since Vite requires it\n const importPath = replaceBackslash(\n isVueFile\n ? path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n d[1]!.filePath,\n ),\n )\n : removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n d[1]!.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )\n return `${\n d[0]\n }: lazyRouteComponent(() => import('./${importPath}'), '${exportName}')`\n })\n .join('\\n,')}\n })`\n : '',\n lazyComponentNode\n ? (() => {\n // For .vue files, use 'default' export since Vue SFCs export default\n const isVueFile = lazyComponentNode.filePath.endsWith('.vue')\n const exportAccessor = isVueFile ? 'd.default' : 'd.Route'\n // Keep .vue extension for Vue files since Vite requires it\n const importPath = replaceBackslash(\n isVueFile\n ? path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n )\n : removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )\n return `.lazy(() => import('./${importPath}').then((d) => ${exportAccessor}))`\n })()\n : '',\n ].join(''),\n ].join('\\n\\n')\n })\n\n // Generate update for root route if it has component pieces\n const rootRoutePath = `/${rootPathId}`\n const rootPieces = acc.routePiecesByPath[rootRoutePath]\n const rootComponentNode = rootPieces?.component\n const rootErrorComponentNode = rootPieces?.errorComponent\n const rootNotFoundComponentNode = rootPieces?.notFoundComponent\n const rootPendingComponentNode = rootPieces?.pendingComponent\n\n let rootRouteUpdate = ''\n if (\n rootComponentNode ||\n rootErrorComponentNode ||\n rootNotFoundComponentNode ||\n rootPendingComponentNode\n ) {\n rootRouteUpdate = `const rootRouteWithChildren = rootRouteImport${\n rootComponentNode ||\n rootErrorComponentNode ||\n rootNotFoundComponentNode ||\n rootPendingComponentNode\n ? `.update({\n ${(\n [\n ['component', rootComponentNode],\n ['errorComponent', rootErrorComponentNode],\n ['notFoundComponent', rootNotFoundComponentNode],\n ['pendingComponent', rootPendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n // For .vue files, use 'default' as the export name since Vue SFCs export default\n const isVueFile = d[1]!.filePath.endsWith('.vue')\n const exportName = isVueFile ? 'default' : d[0]\n // Keep .vue extension for Vue files since Vite requires it\n const importPath = replaceBackslash(\n isVueFile\n ? path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, d[1]!.filePath),\n )\n : removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n d[1]!.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )\n return `${d[0]}: lazyRouteComponent(() => import('./${importPath}'), '${exportName}')`\n })\n .join('\\n,')}\n })`\n : ''\n }._addFileChildren(rootRouteChildren)${config.disableTypes ? '' : `._addFileTypes<FileRouteTypes>()`}`\n }\n\n let fileRoutesByPathInterface = ''\n let fileRoutesByFullPath = ''\n\n if (!config.disableTypes) {\n const routeNodesByFullPath = createRouteNodesByFullPath(acc.routeNodes)\n const routeNodesByTo = createRouteNodesByTo(acc.routeNodes)\n const routeNodesById = createRouteNodesById(acc.routeNodes)\n\n fileRoutesByFullPath = [\n `export interface FileRoutesByFullPath {\n${[...routeNodesByFullPath.entries()]\n .filter(([fullPath]) => fullPath)\n .map(([fullPath, routeNode]) => {\n return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n })}\n}`,\n `export interface FileRoutesByTo {\n${[...routeNodesByTo.entries()]\n .filter(([to]) => to)\n .map(([to, routeNode]) => {\n return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n })}\n}`,\n `export interface FileRoutesById {\n'${rootRouteId}': typeof rootRouteImport,\n${[...routeNodesById.entries()].map(([id, routeNode]) => {\n return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n})}\n}`,\n `export interface FileRouteTypes {\nfileRoutesByFullPath: FileRoutesByFullPath\nfullPaths: ${\n acc.routeNodes.length > 0\n ? [...routeNodesByFullPath.keys()]\n .filter((fullPath) => fullPath)\n .map((fullPath) => `'${fullPath}'`)\n .join('|')\n : 'never'\n }\nfileRoutesByTo: FileRoutesByTo\nto: ${\n acc.routeNodes.length > 0\n ? [...routeNodesByTo.keys()]\n .filter((to) => to)\n .map((to) => `'${to}'`)\n .join('|')\n : 'never'\n }\nid: ${[`'${rootRouteId}'`, ...[...routeNodesById.keys()].map((id) => `'${id}'`)].join('|')}\nfileRoutesById: FileRoutesById\n}`,\n `export interface RootRouteChildren {\n${acc.routeTree.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}\n}`,\n ].join('\\n')\n\n fileRoutesByPathInterface = buildFileRoutesByPathInterface({\n module: this.targetTemplate.fullPkg,\n interfaceName: 'FileRoutesByPath',\n routeNodes: sortedRouteNodes,\n config,\n })\n }\n\n const routeTree = [\n `const rootRouteChildren${config.disableTypes ? '' : `: RootRouteChildren`} = {\n ${acc.routeTree\n .map(\n (child) =>\n `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`,\n )\n .join(',')}\n}`,\n rootRouteUpdate\n ? rootRouteUpdate.replace(\n 'const rootRouteWithChildren = ',\n 'export const routeTree = ',\n )\n : `export const routeTree = rootRouteImport._addFileChildren(rootRouteChildren)${config.disableTypes ? '' : `._addFileTypes<FileRouteTypes>()`}`,\n ].join('\\n')\n\n checkRouteFullPathUniqueness(\n sortedRouteNodes.filter(\n (d) => d.children === undefined && 'lazy' !== d._fsRouteType,\n ),\n config,\n )\n\n let mergedImports = mergeImportDeclarations(imports)\n if (config.disableTypes) {\n mergedImports = mergedImports.filter((d) => d.importKind !== 'type')\n }\n\n const importStatements = mergedImports.map(buildImportString)\n\n let moduleAugmentation = ''\n if (config.verboseFileRoutes === false && !config.disableTypes) {\n moduleAugmentation = opts.routeFileResult\n .map((node) => {\n const getModuleDeclaration = (routeNode?: RouteNode) => {\n if (!isRouteNodeValidForAugmentation(routeNode)) {\n return ''\n }\n let moduleAugmentation = ''\n if (routeNode._fsRouteType === 'lazy') {\n moduleAugmentation = `const createLazyFileRoute: CreateLazyFileRoute<FileRoutesByPath['${routeNode.routePath}']['preLoaderRoute']>`\n } else {\n moduleAugmentation = `const createFileRoute: CreateFileRoute<'${routeNode.routePath}',\n FileRoutesByPath['${routeNode.routePath}']['parentRoute'],\n FileRoutesByPath['${routeNode.routePath}']['id'],\n FileRoutesByPath['${routeNode.routePath}']['path'],\n FileRoutesByPath['${routeNode.routePath}']['fullPath']\n >\n `\n }\n\n return `declare module './${getImportPath(routeNode, config, this.generatedRouteTreePath)}' {\n ${moduleAugmentation}\n }`\n }\n return getModuleDeclaration(node)\n })\n .join('\\n')\n }\n\n const rootRouteImport = getImportForRouteNode(\n rootRouteNode,\n config,\n this.generatedRouteTreePath,\n this.root,\n )\n routeImports.unshift(rootRouteImport)\n\n let footer: Array<string> = []\n if (config.routeTreeFileFooter) {\n if (Array.isArray(config.routeTreeFileFooter)) {\n footer = config.routeTreeFileFooter\n } else {\n footer = config.routeTreeFileFooter()\n }\n }\n const routeTreeContent = [\n ...config.routeTreeFileHeader,\n `// This file was automatically generated by TanStack Router.\n// You should NOT make any changes in this file as it will be overwritten.\n// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.`,\n [...importStatements].join('\\n'),\n mergeImportDeclarations(routeImports).map(buildImportString).join('\\n'),\n virtualRouteNodes.join('\\n'),\n createUpdateRoutes.join('\\n'),\n fileRoutesByFullPath,\n fileRoutesByPathInterface,\n moduleAugmentation,\n routeTreeConfig.join('\\n'),\n routeTree,\n ...footer,\n ]\n .filter(Boolean)\n .join('\\n\\n')\n return {\n routeTreeContent,\n routeTree: acc.routeTree,\n routeNodes: acc.routeNodes,\n }\n }\n\n private async processRouteNodeFile(node: RouteNode): Promise<{\n shouldWriteTree: boolean\n cacheEntry: RouteNodeCacheEntry\n node: RouteNode\n } | null> {\n const result = await this.isRouteFileCacheFresh(node)\n\n if (result.status === 'fresh') {\n return {\n node: result.cacheEntry.node,\n shouldWriteTree: false,\n cacheEntry: result.cacheEntry,\n }\n }\n\n const previousCacheEntry = result.cacheEntry\n\n const existingRouteFile = await this.fs.readFile(node.fullPath)\n if (existingRouteFile === 'file-not-existing') {\n throw new Error(`⚠️ File ${node.fullPath} does not exist`)\n }\n\n const updatedCacheEntry: RouteNodeCacheEntry = {\n fileContent: existingRouteFile.fileContent,\n mtimeMs: existingRouteFile.stat.mtimeMs,\n routeId: node.routePath ?? '$$TSR_NO_ROUTE_PATH_ASSIGNED$$',\n node,\n }\n\n const escapedRoutePath = node.routePath?.replaceAll('$', '$$') ?? ''\n\n let shouldWriteRouteFile = false\n let shouldWriteTree = false\n // now we need to either scaffold the file or transform it\n if (!existingRouteFile.fileContent) {\n shouldWriteRouteFile = true\n shouldWriteTree = true\n // Creating a new lazy route file\n if (node._fsRouteType === 'lazy') {\n const tLazyRouteTemplate = this.targetTemplate.lazyRoute\n // Check by default check if the user has a specific lazy route template\n // If not, check if the user has a route template and use that instead\n updatedCacheEntry.fileContent = await fillTemplate(\n this.config,\n (this.config.customScaffolding?.lazyRouteTemplate ||\n this.config.customScaffolding?.routeTemplate) ??\n tLazyRouteTemplate.template(),\n {\n tsrImports: tLazyRouteTemplate.imports.tsrImports(),\n tsrPath: escapedRoutePath.replaceAll(/\\{(.+?)\\}/gm, '$1'),\n tsrExportStart:\n tLazyRouteTemplate.imports.tsrExportStart(escapedRoutePath),\n tsrExportEnd: tLazyRouteTemplate.imports.tsrExportEnd(),\n },\n )\n } else if (\n // Creating a new normal route file\n (['layout', 'static'] satisfies Array<FsRouteType>).some(\n (d) => d === node._fsRouteType,\n ) ||\n (\n [\n 'component',\n 'pendingComponent',\n 'errorComponent',\n 'notFoundComponent',\n 'loader',\n ] satisfies Array<FsRouteType>\n ).every((d) => d !== node._fsRouteType)\n ) {\n const tRouteTemplate = this.targetTemplate.route\n updatedCacheEntry.fileContent = await fillTemplate(\n this.config,\n this.config.customScaffolding?.routeTemplate ??\n tRouteTemplate.template(),\n {\n tsrImports: tRouteTemplate.imports.tsrImports(),\n tsrPath: escapedRoutePath.replaceAll(/\\{(.+?)\\}/gm, '$1'),\n tsrExportStart:\n tRouteTemplate.imports.tsrExportStart(escapedRoutePath),\n tsrExportEnd: tRouteTemplate.imports.tsrExportEnd(),\n },\n )\n } else {\n return null\n }\n }\n\n // Check if this is a Vue component file\n // Vue SFC files (.vue) don't need transformation as they can't have a Route export\n const isVueFile = node.filePath.endsWith('.vue')\n\n if (!isVueFile) {\n // transform the file\n const transformResult = await transform({\n source: updatedCacheEntry.fileContent,\n ctx: {\n target: this.config.target,\n routeId: escapedRoutePath,\n lazy: node._fsRouteType === 'lazy',\n verboseFileRoutes: !(this.config.verboseFileRoutes === false),\n },\n node,\n })\n\n if (transformResult.result === 'no-route-export') {\n const fileName = path.basename(node.fullPath)\n const dirName = path.dirname(node.fullPath)\n const ignorePrefix = this.config.routeFileIgnorePrefix\n const ignorePattern = this.config.routeFileIgnorePattern\n const suggestedFileName = `${ignorePrefix}${fileName}`\n const suggestedFullPath = path.join(dirName, suggestedFileName)\n\n let message = `Warning: Route file \"${node.fullPath}\" does not export a Route. This file will not be included in the route tree.`\n message += `\\n\\nIf this file is not intended to be a route, you can exclude it using one of these options:`\n message += `\\n 1. Rename the file to \"${suggestedFullPath}\" (prefix with \"${ignorePrefix}\")`\n message += `\\n 2. Use 'routeFileIgnorePattern' in your config to match this file`\n message += `\\n\\nCurrent configuration:`\n message += `\\n routeFileIgnorePrefix: \"${ignorePrefix}\"`\n message += `\\n routeFileIgnorePattern: ${ignorePattern ? `\"${ignorePattern}\"` : 'undefined'}`\n\n this.logger.warn(message)\n return null\n }\n if (transformResult.result === 'error') {\n throw new Error(\n `Error transforming route file ${node.fullPath}: ${transformResult.error}`,\n )\n }\n if (transformResult.result === 'modified') {\n updatedCacheEntry.fileContent = transformResult.output\n shouldWriteRouteFile = true\n }\n }\n\n for (const plugin of this.plugins) {\n plugin.afterTransform?.({ node, prevNode: previousCacheEntry?.node })\n }\n\n // file was changed\n if (shouldWriteRouteFile) {\n const stats = await this.safeFileWrite({\n filePath: node.fullPath,\n newContent: updatedCacheEntry.fileContent,\n strategy: {\n type: 'mtime',\n expectedMtimeMs: updatedCacheEntry.mtimeMs,\n },\n })\n updatedCacheEntry.mtimeMs = stats.mtimeMs\n }\n\n this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry)\n return {\n node,\n shouldWriteTree,\n cacheEntry: updatedCacheEntry,\n }\n }\n\n private async didRouteFileChangeComparedToCache(\n file: {\n path: string\n mtimeMs?: bigint\n },\n cache: 'routeNodeCache' | 'routeNodeShadowCache',\n ): Promise<FileCacheChange<RouteNodeCacheEntry>> {\n const cacheEntry = this[cache].get(file.path)\n return this.didFileChangeComparedToCache(file, cacheEntry)\n }\n\n private async didFileChangeComparedToCache<\n TCacheEntry extends GeneratorCacheEntry,\n >(\n file: {\n path: string\n mtimeMs?: bigint\n },\n cacheEntry: TCacheEntry | undefined,\n ): Promise<FileCacheChange<TCacheEntry>> {\n // for now we rely on the modification time of the file\n // to determine if the file has changed\n // we could also compare the file content but this would be slower as we would have to read the file\n\n if (!cacheEntry) {\n return { result: 'file-not-in-cache' }\n }\n let mtimeMs = file.mtimeMs\n\n if (mtimeMs === undefined) {\n try {\n const currentStat = await this.fs.stat(file.path)\n mtimeMs = currentStat.mtimeMs\n } catch {\n return { result: 'cannot-stat-file' }\n }\n }\n return { result: mtimeMs !== cacheEntry.mtimeMs, mtimeMs, cacheEntry }\n }\n\n private async safeFileWrite(opts: {\n filePath: string\n newContent: string\n strategy:\n | {\n type: 'mtime'\n expectedMtimeMs: bigint\n }\n | {\n type: 'new-file'\n }\n }) {\n const tmpPath = this.getTempFileName(opts.filePath)\n await this.fs.writeFile(tmpPath, opts.newContent)\n\n if (opts.strategy.type === 'mtime') {\n const beforeStat = await this.fs.stat(opts.filePath)\n if (beforeStat.mtimeMs !== opts.strategy.expectedMtimeMs) {\n throw rerun({\n msg: `File ${opts.filePath} was modified by another process during processing.`,\n event: { type: 'update', path: opts.filePath },\n })\n }\n const newFileState = await this.fs.stat(tmpPath)\n if (newFileState.mode !== beforeStat.mode) {\n await this.fs.chmod(tmpPath, beforeStat.mode)\n }\n if (\n newFileState.uid !== beforeStat.uid ||\n newFileState.gid !== beforeStat.gid\n ) {\n try {\n await this.fs.chown(tmpPath, beforeStat.uid, beforeStat.gid)\n } catch (err) {\n if (\n typeof err === 'object' &&\n err !== null &&\n 'code' in err &&\n (err as any).code === 'EPERM'\n ) {\n console.warn(\n `[safeFileWrite] chown failed: ${(err as any).message}`,\n )\n } else {\n throw err\n }\n }\n }\n } else {\n if (await checkFileExists(opts.filePath)) {\n throw rerun({\n msg: `File ${opts.filePath} already exists. Cannot overwrite.`,\n event: { type: 'update', path: opts.filePath },\n })\n }\n }\n\n const stat = await this.fs.stat(tmpPath)\n\n await this.fs.rename(tmpPath, opts.filePath)\n\n return stat\n }\n\n private getTempFileName(filePath: string) {\n const absPath = path.resolve(filePath)\n const hash = crypto.createHash('md5').update(absPath).digest('hex')\n // lazy initialize sessionId to only create tmpDir when it is first needed\n if (!this.sessionId) {\n // ensure the directory exists\n mkdirSync(this.config.tmpDir, { recursive: true })\n this.sessionId = crypto.randomBytes(4).toString('hex')\n }\n return path.join(this.config.tmpDir, `${this.sessionId}-${hash}`)\n }\n\n private async isRouteFileCacheFresh(node: RouteNode): Promise<\n | {\n status: 'fresh'\n cacheEntry: RouteNodeCacheEntry\n }\n | { status: 'stale'; cacheEntry?: RouteNodeCacheEntry }\n > {\n const fileChangedCache = await this.didRouteFileChangeComparedToCache(\n { path: node.fullPath },\n 'routeNodeCache',\n )\n if (fileChangedCache.result === false) {\n this.routeNodeShadowCache.set(node.fullPath, fileChangedCache.cacheEntry)\n return {\n status: 'fresh',\n cacheEntry: fileChangedCache.cacheEntry,\n }\n }\n if (fileChangedCache.result === 'cannot-stat-file') {\n throw new Error(`⚠️ expected route file to exist at ${node.fullPath}`)\n }\n const mtimeMs =\n fileChangedCache.result === true ? fileChangedCache.mtimeMs : undefined\n\n const shadowCacheFileChange = await this.didRouteFileChangeComparedToCache(\n { path: node.fullPath, mtimeMs },\n 'routeNodeShadowCache',\n )\n\n if (shadowCacheFileChange.result === 'cannot-stat-file') {\n throw new Error(`⚠️ expected route file to exist at ${node.fullPath}`)\n }\n\n if (shadowCacheFileChange.result === false) {\n // shadow cache has latest file state already\n if (fileChangedCache.result === true) {\n return {\n status: 'fresh',\n cacheEntry: shadowCacheFileChange.cacheEntry,\n }\n }\n }\n\n if (fileChangedCache.result === 'file-not-in-cache') {\n return {\n status: 'stale',\n }\n }\n return { status: 'stale', cacheEntry: fileChangedCache.cacheEntry }\n }\n\n private async handleRootNode(node: RouteNode) {\n const result = await this.isRouteFileCacheFresh(node)\n\n if (result.status === 'fresh') {\n this.routeNodeShadowCache.set(node.fullPath, result.cacheEntry)\n }\n const rootNodeFile = await this.fs.readFile(node.fullPath)\n if (rootNodeFile === 'file-not-existing') {\n throw new Error(`⚠️ expected root route to exist at ${node.fullPath}`)\n }\n\n const updatedCacheEntry: RouteNodeCacheEntry = {\n fileContent: rootNodeFile.fileContent,\n mtimeMs: rootNodeFile.stat.mtimeMs,\n routeId: node.routePath ?? '$$TSR_NO_ROOT_ROUTE_PATH_ASSIGNED$$',\n node,\n }\n\n // scaffold the root route\n if (!rootNodeFile.fileContent) {\n const rootTemplate = this.targetTemplate.rootRoute\n const rootRouteContent = await fillTemplate(\n this.config,\n rootTemplate.template(),\n {\n tsrImports: rootTemplate.imports.tsrImports(),\n tsrPath: rootPathId,\n tsrExportStart: rootTemplate.imports.tsrExportStart(),\n tsrExportEnd: rootTemplate.imports.tsrExportEnd(),\n },\n )\n\n this.logger.log(`🟡 Creating ${node.fullPath}`)\n const stats = await this.safeFileWrite({\n filePath: node.fullPath,\n newContent: rootRouteContent,\n strategy: {\n type: 'mtime',\n expectedMtimeMs: rootNodeFile.stat.mtimeMs,\n },\n })\n updatedCacheEntry.fileContent = rootRouteContent\n updatedCacheEntry.mtimeMs = stats.mtimeMs\n }\n\n this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry)\n }\n\n public async getCrawlingResult(): Promise<CrawlingResult | undefined> {\n await this.runPromise\n return this.crawlingResult\n }\n\n private static handleNode(\n node: RouteNode,\n acc: HandleNodeAccumulator,\n prefixMap: RoutePrefixMap,\n config?: Config,\n ) {\n let parentRoute = hasParentRoute(prefixMap, node, node.routePath)\n\n // Fallback: check acc.routeNodesByPath for parents not in prefixMap\n // This handles virtual routes created from lazy-only files that weren't\n // in the initial prefixMap build\n if (!parentRoute && node.routePath) {\n let searchPath = node.routePath\n while (searchPath.length > 0) {\n const lastSlash = searchPath.lastIndexOf('/')\n if (lastSlash <= 0) break\n searchPath = searchPath.substring(0, lastSlash)\n const candidate = acc.routeNodesByPath.get(searchPath)\n if (candidate && candidate.routePath !== node.routePath) {\n parentRoute = candidate\n break\n }\n }\n }\n\n if (parentRoute) node.parent = parentRoute\n\n node.path = determineNodePath(node)\n\n const trimmedPath = trimPathLeft(node.path ?? '')\n const trimmedOriginalPath = trimPathLeft(\n node.originalRoutePath?.replace(\n node.parent?.originalRoutePath ?? '',\n '',\n ) ?? '',\n )\n\n const split = trimmedPath.split('/')\n const originalSplit = trimmedOriginalPath.split('/')\n const lastRouteSegment = split[split.length - 1] ?? trimmedPath\n const lastOriginalSegment =\n originalSplit[originalSplit.length - 1] ?? trimmedOriginalPath\n\n // A segment is non-path if it starts with underscore AND the underscore is not escaped\n node.isNonPath =\n isSegmentPathless(lastRouteSegment, lastOriginalSegment) ||\n split.every((part) => this.routeGroupPatternRegex.test(part))\n\n // Use escape-aware functions to compute cleanedPath\n node.cleanedPath = removeGroups(\n removeUnderscoresWithEscape(\n removeLayoutSegmentsWithEscape(node.path, node.originalRoutePath),\n node.originalRoutePath,\n ),\n )\n\n if (\n node._fsRouteType === 'layout' ||\n node._fsRouteType === 'pathless_layout'\n ) {\n node.cleanedPath = removeTrailingSlash(node.cleanedPath)\n }\n\n if (\n !node.isVirtual &&\n (\n [\n 'lazy',\n 'loader',\n 'component',\n 'pendingComponent',\n 'errorComponent',\n 'notFoundComponent',\n ] satisfies Array<FsRouteType>\n ).some((d) => d === node._fsRouteType)\n ) {\n acc.routePiecesByPath[node.routePath!] =\n acc.routePiecesByPath[node.routePath!] || {}\n\n const pieceKey =\n node._fsRouteType === 'lazy'\n ? 'lazy'\n : (node._fsRouteType as keyof (typeof acc.routePiecesByPath)[string])\n acc.routePiecesByPath[node.routePath!]![pieceKey] = node\n\n const anchorRoute = acc.routeNodesByPath.get(node.routePath!)\n\n // Don't create virtual routes for root route component pieces - the root route is handled separately\n if (!anchorRoute && node.routePath !== `/${rootPathId}`) {\n this.handleNode(\n {\n ...node,\n isVirtual: true,\n _fsRouteType: 'static',\n },\n acc,\n prefixMap,\n config,\n )\n }\n return\n }\n\n const isPathlessLayoutWithPath =\n node._fsRouteType === 'pathless_layout' &&\n node.cleanedPath &&\n node.cleanedPath.length > 0\n\n // Special handling: pathless layouts with path need to find real ancestor\n if (!node.isVirtual && isPathlessLayoutWithPath) {\n const immediateParentPath =\n removeLastSegmentFromPath(node.routePath) || '/'\n const immediateParentOriginalPath =\n removeLastSegmentFromPath(node.originalRoutePath) || '/'\n let searchPath = immediateParentPath\n\n // Find nearest real (non-virtual, non-index) parent\n while (searchPath) {\n const candidate = acc.routeNodesByPath.get(searchPath)\n if (candidate && !candidate.isVirtual && candidate.path !== '/') {\n node.parent = candidate\n node.path =\n node.routePath?.replace(candidate.routePath ?? '', '') || '/'\n const pathRelativeToParent =\n immediateParentPath.replace(candidate.routePath ?? '', '') || '/'\n const originalPathRelativeToParent =\n immediateParentOriginalPath.replace(\n candidate.originalRoutePath ?? '',\n '',\n ) || '/'\n node.cleanedPath = removeGroups(\n removeUnderscoresWithEscape(\n removeLayoutSegmentsWithEscape(\n pathRelativeToParent,\n originalPathRelativeToParent,\n ),\n originalPathRelativeToParent,\n ),\n )\n break\n }\n if (searchPath === '/') break\n searchPath = removeLastSegmentFromPath(searchPath) || '/'\n }\n }\n\n // Add to parent's children or to root\n if (node.parent) {\n node.parent.children = node.parent.children ?? []\n node.parent.children.push(node)\n } else {\n acc.routeTree.push(node)\n }\n\n acc.routeNodes.push(node)\n if (node.routePath) {\n // Always register routes by path so child routes can find parents.\n // Virtual routes (created from lazy-only files) also need to be registered\n // so that index routes like path.index.lazy.tsx can find their parent path.lazy.tsx.\n // If a non-virtual route is later processed for the same path, it will overwrite.\n acc.routeNodesByPath.set(node.routePath, node)\n }\n }\n\n // only process files that are relevant for the route tree generation\n private isFileRelevantForRouteTreeGeneration(filePath: string): boolean {\n // the generated route tree file\n if (filePath === this.generatedRouteTreePath) {\n return true\n }\n\n // files inside the routes folder\n if (filePath.startsWith(this.routesDirectoryPath)) {\n return true\n }\n\n // the virtual route config file passed into `virtualRouteConfig`\n if (\n typeof this.config.virtualRouteConfig === 'string' &&\n filePath === this.config.virtualRouteConfig\n ) {\n return true\n }\n\n // this covers all files that are mounted via `virtualRouteConfig` or any `__virtual.ts` files\n if (this.routeNodeCache.has(filePath)) {\n return true\n }\n\n // virtual config files such as`__virtual.ts`\n if (isVirtualConfigFile(path.basename(filePath))) {\n return true\n }\n\n // route files inside directories mounted via `physical()` inside a virtual route config\n if (this.physicalDirectories.some((dir) => filePath.startsWith(dir))) {\n return true\n }\n\n return false\n }\n}\n"],"names":["virtualGetRouteNodes","physicalGetRouteNodes","moduleAugmentation"],"mappings":"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"}
1
+ {"version":3,"file":"generator.js","sources":["../../src/generator.ts"],"sourcesContent":["import path from 'node:path'\nimport * as fsp from 'node:fs/promises'\nimport { existsSync, mkdirSync } from 'node:fs'\nimport crypto from 'node:crypto'\nimport { rootRouteId } from '@tanstack/router-core'\nimport { logging } from './logger'\nimport {\n isVirtualConfigFile,\n getRouteNodes as physicalGetRouteNodes,\n} from './filesystem/physical/getRouteNodes'\nimport { getRouteNodes as virtualGetRouteNodes } from './filesystem/virtual/getRouteNodes'\nimport { rootPathId } from './filesystem/physical/rootPathId'\nimport {\n RoutePrefixMap,\n buildFileRoutesByPathInterface,\n buildImportString,\n buildRouteTreeConfig,\n checkFileExists,\n checkRouteFullPathUniqueness,\n createRouteNodesByFullPath,\n createRouteNodesById,\n createRouteNodesByTo,\n createTokenRegex,\n determineNodePath,\n findParent,\n format,\n getImportForRouteNode,\n getImportPath,\n getResolvedRouteNodeVariableName,\n hasParentRoute,\n isRouteNodeValidForAugmentation,\n isSegmentPathless,\n mergeImportDeclarations,\n multiSortBy,\n removeExt,\n removeGroups,\n removeLastSegmentFromPath,\n removeLayoutSegmentsWithEscape,\n removeTrailingSlash,\n removeUnderscoresWithEscape,\n replaceBackslash,\n trimPathLeft,\n} from './utils'\nimport { fillTemplate, getTargetTemplate } from './template'\nimport { transform } from './transform/transform'\nimport type { GeneratorPlugin } from './plugin/types'\nimport type { TargetTemplate } from './template'\nimport type {\n FsRouteType,\n GetRouteNodesResult,\n GetRoutesByFileMapResult,\n HandleNodeAccumulator,\n ImportDeclaration,\n RouteNode,\n} from './types'\nimport type { Config } from './config'\nimport type { Logger } from './logger'\n\ninterface fs {\n stat: (\n filePath: string,\n ) => Promise<{ mtimeMs: bigint; mode: number; uid: number; gid: number }>\n rename: (oldPath: string, newPath: string) => Promise<void>\n writeFile: (filePath: string, content: string) => Promise<void>\n readFile: (\n filePath: string,\n ) => Promise<\n { stat: { mtimeMs: bigint }; fileContent: string } | 'file-not-existing'\n >\n chmod: (filePath: string, mode: number) => Promise<void>\n chown: (filePath: string, uid: number, gid: number) => Promise<void>\n}\n\nconst DefaultFileSystem: fs = {\n stat: async (filePath) => {\n const res = await fsp.stat(filePath, { bigint: true })\n return {\n mtimeMs: res.mtimeMs,\n mode: Number(res.mode),\n uid: Number(res.uid),\n gid: Number(res.gid),\n }\n },\n rename: (oldPath, newPath) => fsp.rename(oldPath, newPath),\n writeFile: (filePath, content) => fsp.writeFile(filePath, content),\n readFile: async (filePath: string) => {\n try {\n const fileHandle = await fsp.open(filePath, 'r')\n const stat = await fileHandle.stat({ bigint: true })\n const fileContent = (await fileHandle.readFile()).toString()\n await fileHandle.close()\n return { stat, fileContent }\n } catch (e: any) {\n if ('code' in e) {\n if (e.code === 'ENOENT') {\n return 'file-not-existing'\n }\n }\n throw e\n }\n },\n chmod: (filePath, mode) => fsp.chmod(filePath, mode),\n chown: (filePath, uid, gid) => fsp.chown(filePath, uid, gid),\n}\n\ninterface Rerun {\n rerun: true\n msg?: string\n event: GeneratorEvent\n}\nfunction rerun(opts: { msg?: string; event?: GeneratorEvent }): Rerun {\n const { event, ...rest } = opts\n return { rerun: true, event: event ?? { type: 'rerun' }, ...rest }\n}\n\nfunction isRerun(result: unknown): result is Rerun {\n return (\n typeof result === 'object' &&\n result !== null &&\n 'rerun' in result &&\n result.rerun === true\n )\n}\n\nexport type FileEventType = 'create' | 'update' | 'delete'\nexport type FileEvent = {\n type: FileEventType\n path: string\n}\nexport type GeneratorEvent = FileEvent | { type: 'rerun' }\n\ntype FileCacheChange<TCacheEntry extends GeneratorCacheEntry> =\n | {\n result: false\n cacheEntry: TCacheEntry\n }\n | { result: true; mtimeMs: bigint; cacheEntry: TCacheEntry }\n | {\n result: 'file-not-in-cache'\n }\n | {\n result: 'cannot-stat-file'\n }\n\ninterface GeneratorCacheEntry {\n mtimeMs: bigint\n fileContent: string\n}\n\ninterface RouteNodeCacheEntry extends GeneratorCacheEntry {\n routeId: string\n node: RouteNode\n}\n\ntype GeneratorRouteNodeCache = Map</** filePath **/ string, RouteNodeCacheEntry>\n\ninterface CrawlingResult {\n rootRouteNode: RouteNode\n routeFileResult: Array<RouteNode>\n acc: HandleNodeAccumulator\n}\n\nexport class Generator {\n /**\n * why do we have two caches for the route files?\n * During processing, we READ from the cache and WRITE to the shadow cache.\n *\n * After a route file is processed, we write to the shadow cache.\n * If during processing we bail out and re-run, we don't lose this modification\n * but still can track whether the file contributed changes and thus the route tree file needs to be regenerated.\n * After all files are processed, we swap the shadow cache with the main cache and initialize a new shadow cache.\n * That way we also ensure deleted/renamed files don't stay in the cache forever.\n */\n private routeNodeCache: GeneratorRouteNodeCache = new Map()\n private routeNodeShadowCache: GeneratorRouteNodeCache = new Map()\n\n private routeTreeFileCache: GeneratorCacheEntry | undefined\n\n private crawlingResult: CrawlingResult | undefined\n public config: Config\n public targetTemplate: TargetTemplate\n\n private root: string\n private routesDirectoryPath: string\n private sessionId?: string\n private fs: fs\n private logger: Logger\n private generatedRouteTreePath: string\n private runPromise: Promise<void> | undefined\n private fileEventQueue: Array<GeneratorEvent> = []\n private plugins: Array<GeneratorPlugin> = []\n private static routeGroupPatternRegex = /\\(.+\\)/\n private physicalDirectories: Array<string> = []\n\n /**\n * Token regexes are pre-compiled once here and reused throughout route processing.\n * We need TWO types of regex for each token because they match against different inputs:\n *\n * 1. FILENAME regexes: Match token patterns within full file path strings.\n * Example: For file \"routes/dashboard.index.tsx\", we want to detect \".index.\"\n * Pattern: `[./](?:token)[.]` - matches token bounded by path separators/dots\n * Used in: sorting route nodes by file path\n *\n * 2. SEGMENT regexes: Match token against a single logical route segment.\n * Example: For segment \"index\" (extracted from path), match the whole segment\n * Pattern: `^(?:token)$` - matches entire segment exactly\n * Used in: route parsing, determining route types, escape detection\n *\n * We cannot reuse one for the other without false positives or missing matches.\n */\n private indexTokenFilenameRegex: RegExp\n private routeTokenFilenameRegex: RegExp\n private indexTokenSegmentRegex: RegExp\n private routeTokenSegmentRegex: RegExp\n private static componentPieceRegex =\n /[./](component|errorComponent|notFoundComponent|pendingComponent|loader|lazy)[.]/\n\n constructor(opts: { config: Config; root: string; fs?: fs }) {\n this.config = opts.config\n this.logger = logging({ disabled: this.config.disableLogging })\n this.root = opts.root\n this.fs = opts.fs || DefaultFileSystem\n this.generatedRouteTreePath = this.getGeneratedRouteTreePath()\n this.targetTemplate = getTargetTemplate(this.config)\n\n this.routesDirectoryPath = this.getRoutesDirectoryPath()\n this.plugins.push(...(opts.config.plugins || []))\n\n // Create all token regexes once in constructor\n this.indexTokenFilenameRegex = createTokenRegex(this.config.indexToken, {\n type: 'filename',\n })\n this.routeTokenFilenameRegex = createTokenRegex(this.config.routeToken, {\n type: 'filename',\n })\n this.indexTokenSegmentRegex = createTokenRegex(this.config.indexToken, {\n type: 'segment',\n })\n this.routeTokenSegmentRegex = createTokenRegex(this.config.routeToken, {\n type: 'segment',\n })\n\n for (const plugin of this.plugins) {\n plugin.init?.({ generator: this })\n }\n }\n\n private getGeneratedRouteTreePath() {\n const generatedRouteTreePath = path.isAbsolute(\n this.config.generatedRouteTree,\n )\n ? this.config.generatedRouteTree\n : path.resolve(this.root, this.config.generatedRouteTree)\n\n const generatedRouteTreeDir = path.dirname(generatedRouteTreePath)\n\n if (!existsSync(generatedRouteTreeDir)) {\n mkdirSync(generatedRouteTreeDir, { recursive: true })\n }\n\n return generatedRouteTreePath\n }\n\n private getRoutesDirectoryPath() {\n return path.isAbsolute(this.config.routesDirectory)\n ? this.config.routesDirectory\n : path.resolve(this.root, this.config.routesDirectory)\n }\n\n public getRoutesByFileMap(): GetRoutesByFileMapResult {\n return new Map(\n [...this.routeNodeCache.entries()].map(([filePath, cacheEntry]) => [\n filePath,\n { routePath: cacheEntry.routeId },\n ]),\n )\n }\n\n public async run(event?: GeneratorEvent): Promise<void> {\n if (\n event &&\n event.type !== 'rerun' &&\n !this.isFileRelevantForRouteTreeGeneration(event.path)\n ) {\n return\n }\n this.fileEventQueue.push(event ?? { type: 'rerun' })\n // only allow a single run at a time\n if (this.runPromise) {\n return this.runPromise\n }\n\n this.runPromise = (async () => {\n do {\n // synchronously copy and clear the queue since we are going to iterate asynchronously over it\n // and while we do so, a new event could be put into the queue\n const tempQueue = this.fileEventQueue\n this.fileEventQueue = []\n // if we only have 'update' events in the queue\n // and we already have the affected files' latest state in our cache, we can exit early\n const remainingEvents = (\n await Promise.all(\n tempQueue.map(async (e) => {\n if (e.type === 'update') {\n let cacheEntry: GeneratorCacheEntry | undefined\n if (e.path === this.generatedRouteTreePath) {\n cacheEntry = this.routeTreeFileCache\n } else {\n // we only check the routeNodeCache here\n // if the file's state is only up-to-date in the shadow cache we need to re-run\n cacheEntry = this.routeNodeCache.get(e.path)\n }\n const change = await this.didFileChangeComparedToCache(\n { path: e.path },\n cacheEntry,\n )\n if (change.result === false) {\n return null\n }\n }\n return e\n }),\n )\n ).filter((e) => e !== null)\n\n if (remainingEvents.length === 0) {\n break\n }\n\n try {\n await this.generatorInternal()\n } catch (err) {\n const errArray = !Array.isArray(err) ? [err] : err\n\n const recoverableErrors = errArray.filter((e) => isRerun(e))\n if (recoverableErrors.length === errArray.length) {\n this.fileEventQueue.push(...recoverableErrors.map((e) => e.event))\n recoverableErrors.forEach((e) => {\n if (e.msg) {\n this.logger.info(e.msg)\n }\n })\n } else {\n const unrecoverableErrors = errArray.filter((e) => !isRerun(e))\n this.runPromise = undefined\n throw new Error(\n unrecoverableErrors.map((e) => (e as Error).message).join(),\n )\n }\n }\n } while (this.fileEventQueue.length)\n this.runPromise = undefined\n })()\n return this.runPromise\n }\n\n private async generatorInternal() {\n let writeRouteTreeFile: boolean | 'force' = false\n\n let getRouteNodesResult: GetRouteNodesResult\n\n if (this.config.virtualRouteConfig) {\n getRouteNodesResult = await virtualGetRouteNodes(this.config, this.root, {\n indexTokenSegmentRegex: this.indexTokenSegmentRegex,\n routeTokenSegmentRegex: this.routeTokenSegmentRegex,\n })\n } else {\n getRouteNodesResult = await physicalGetRouteNodes(\n this.config,\n this.root,\n {\n indexTokenSegmentRegex: this.indexTokenSegmentRegex,\n routeTokenSegmentRegex: this.routeTokenSegmentRegex,\n },\n )\n }\n\n const {\n rootRouteNode,\n routeNodes: beforeRouteNodes,\n physicalDirectories,\n } = getRouteNodesResult\n if (rootRouteNode === undefined) {\n let errorMessage = `rootRouteNode must not be undefined. Make sure you've added your root route into the route-tree.`\n if (!this.config.virtualRouteConfig) {\n errorMessage += `\\nMake sure that you add a \"${rootPathId}.${this.config.disableTypes ? 'js' : 'tsx'}\" file to your routes directory.\\nAdd the file in: \"${this.config.routesDirectory}/${rootPathId}.${this.config.disableTypes ? 'js' : 'tsx'}\"`\n }\n throw new Error(errorMessage)\n }\n this.physicalDirectories = physicalDirectories\n\n await this.handleRootNode(rootRouteNode)\n\n const preRouteNodes = multiSortBy(beforeRouteNodes, [\n (d) => (d.routePath === '/' ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => (d.filePath.match(this.indexTokenFilenameRegex) ? 1 : -1),\n (d) => (d.filePath.match(Generator.componentPieceRegex) ? 1 : -1),\n (d) => (d.filePath.match(this.routeTokenFilenameRegex) ? -1 : 1),\n (d) => (d.routePath?.endsWith('/') ? -1 : 1),\n (d) => d.routePath,\n ]).filter((d) => {\n // Exclude the root route itself, but keep component/loader pieces for the root\n if (d.routePath === `/${rootPathId}`) {\n return [\n 'component',\n 'errorComponent',\n 'notFoundComponent',\n 'pendingComponent',\n 'loader',\n 'lazy',\n ].includes(d._fsRouteType)\n }\n return true\n })\n\n const routeFileAllResult = await Promise.allSettled(\n preRouteNodes\n // only process routes that are backed by an actual file\n .filter((n) => !n.isVirtualParentRoute && !n.isVirtual)\n .map((n) => this.processRouteNodeFile(n)),\n )\n\n const rejections = routeFileAllResult.filter(\n (result) => result.status === 'rejected',\n )\n if (rejections.length > 0) {\n throw rejections.map((e) => e.reason)\n }\n\n const routeFileResult = routeFileAllResult.flatMap((result) => {\n if (result.status === 'fulfilled' && result.value !== null) {\n if (result.value.shouldWriteTree) {\n writeRouteTreeFile = true\n }\n return result.value.node\n }\n return []\n })\n\n // reset children in case we re-use a node from the cache\n routeFileResult.forEach((r) => (r.children = undefined))\n\n const acc: HandleNodeAccumulator = {\n routeTree: [],\n routeNodes: [],\n routePiecesByPath: {},\n routeNodesByPath: new Map(),\n }\n\n const prefixMap = new RoutePrefixMap(routeFileResult)\n\n for (const node of routeFileResult) {\n Generator.handleNode(node, acc, prefixMap, this.config)\n }\n\n this.crawlingResult = { rootRouteNode, routeFileResult, acc }\n\n // this is the first time the generator runs, so read in the route tree file if it exists yet\n if (!this.routeTreeFileCache) {\n const routeTreeFile = await this.fs.readFile(this.generatedRouteTreePath)\n if (routeTreeFile !== 'file-not-existing') {\n this.routeTreeFileCache = {\n fileContent: routeTreeFile.fileContent,\n mtimeMs: routeTreeFile.stat.mtimeMs,\n }\n }\n writeRouteTreeFile = true\n } else {\n const routeTreeFileChange = await this.didFileChangeComparedToCache(\n { path: this.generatedRouteTreePath },\n this.routeTreeFileCache,\n )\n if (routeTreeFileChange.result !== false) {\n writeRouteTreeFile = 'force'\n if (routeTreeFileChange.result === true) {\n const routeTreeFile = await this.fs.readFile(\n this.generatedRouteTreePath,\n )\n if (routeTreeFile !== 'file-not-existing') {\n this.routeTreeFileCache = {\n fileContent: routeTreeFile.fileContent,\n mtimeMs: routeTreeFile.stat.mtimeMs,\n }\n }\n }\n }\n }\n\n if (!writeRouteTreeFile) {\n // only needs to be done if no other changes have been detected yet\n // compare shadowCache and cache to identify deleted routes\n if (this.routeNodeCache.size !== this.routeNodeShadowCache.size) {\n writeRouteTreeFile = true\n } else {\n for (const fullPath of this.routeNodeCache.keys()) {\n if (!this.routeNodeShadowCache.has(fullPath)) {\n writeRouteTreeFile = true\n break\n }\n }\n }\n }\n\n if (!writeRouteTreeFile) {\n this.swapCaches()\n return\n }\n\n const buildResult = this.buildRouteTree({\n rootRouteNode,\n acc,\n routeFileResult,\n })\n let routeTreeContent = buildResult.routeTreeContent\n\n routeTreeContent = this.config.enableRouteTreeFormatting\n ? await format(routeTreeContent, this.config)\n : routeTreeContent\n\n let newMtimeMs: bigint | undefined\n if (this.routeTreeFileCache) {\n if (\n writeRouteTreeFile !== 'force' &&\n this.routeTreeFileCache.fileContent === routeTreeContent\n ) {\n // existing route tree file is already up-to-date, don't write it\n // we should only get here in the initial run when the route cache is not filled yet\n } else {\n const newRouteTreeFileStat = await this.safeFileWrite({\n filePath: this.generatedRouteTreePath,\n newContent: routeTreeContent,\n strategy: {\n type: 'mtime',\n expectedMtimeMs: this.routeTreeFileCache.mtimeMs,\n },\n })\n newMtimeMs = newRouteTreeFileStat.mtimeMs\n }\n } else {\n const newRouteTreeFileStat = await this.safeFileWrite({\n filePath: this.generatedRouteTreePath,\n newContent: routeTreeContent,\n strategy: {\n type: 'new-file',\n },\n })\n newMtimeMs = newRouteTreeFileStat.mtimeMs\n }\n\n if (newMtimeMs !== undefined) {\n this.routeTreeFileCache = {\n fileContent: routeTreeContent,\n mtimeMs: newMtimeMs,\n }\n }\n\n this.plugins.map((plugin) => {\n return plugin.onRouteTreeChanged?.({\n routeTree: buildResult.routeTree,\n routeNodes: buildResult.routeNodes,\n acc,\n rootRouteNode,\n })\n })\n this.swapCaches()\n }\n\n private swapCaches() {\n this.routeNodeCache = this.routeNodeShadowCache\n this.routeNodeShadowCache = new Map()\n }\n\n public buildRouteTree(opts: {\n rootRouteNode: RouteNode\n acc: HandleNodeAccumulator\n routeFileResult: Array<RouteNode>\n config?: Partial<Config>\n }) {\n const config = { ...this.config, ...(opts.config || {}) }\n\n const { rootRouteNode, acc } = opts\n\n // Use pre-compiled regex if config hasn't been overridden, otherwise create new one\n const indexTokenSegmentRegex =\n config.indexToken === this.config.indexToken\n ? this.indexTokenSegmentRegex\n : createTokenRegex(config.indexToken, { type: 'segment' })\n\n const sortedRouteNodes = multiSortBy(acc.routeNodes, [\n (d) => (d.routePath?.includes(`/${rootPathId}`) ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => {\n const segments = d.routePath?.split('/').filter(Boolean) ?? []\n const last = segments[segments.length - 1] ?? ''\n return indexTokenSegmentRegex.test(last) ? -1 : 1\n },\n (d) => d,\n ])\n\n const routeImports: Array<ImportDeclaration> = []\n const virtualRouteNodes: Array<string> = []\n\n for (const node of sortedRouteNodes) {\n if (node.isVirtual) {\n virtualRouteNodes.push(\n `const ${node.variableName}RouteImport = createFileRoute('${node.routePath}')()`,\n )\n } else {\n routeImports.push(\n getImportForRouteNode(\n node,\n config,\n this.generatedRouteTreePath,\n this.root,\n ),\n )\n }\n }\n\n const imports: Array<ImportDeclaration> = []\n if (virtualRouteNodes.length > 0) {\n imports.push({\n specifiers: [{ imported: 'createFileRoute' }],\n source: this.targetTemplate.fullPkg,\n })\n }\n // Add lazyRouteComponent import if there are component pieces\n let hasComponentPieces = false\n let hasLoaderPieces = false\n for (const node of sortedRouteNodes) {\n const pieces = acc.routePiecesByPath[node.routePath!]\n if (pieces) {\n if (\n pieces.component ||\n pieces.errorComponent ||\n pieces.notFoundComponent ||\n pieces.pendingComponent\n ) {\n hasComponentPieces = true\n }\n if (pieces.loader) {\n hasLoaderPieces = true\n }\n if (hasComponentPieces && hasLoaderPieces) break\n }\n }\n if (hasComponentPieces || hasLoaderPieces) {\n const runtimeImport: ImportDeclaration = {\n specifiers: [],\n source: this.targetTemplate.fullPkg,\n }\n if (hasComponentPieces) {\n runtimeImport.specifiers.push({ imported: 'lazyRouteComponent' })\n }\n if (hasLoaderPieces) {\n runtimeImport.specifiers.push({ imported: 'lazyFn' })\n }\n imports.push(runtimeImport)\n }\n if (config.verboseFileRoutes === false) {\n const typeImport: ImportDeclaration = {\n specifiers: [],\n source: this.targetTemplate.fullPkg,\n importKind: 'type',\n }\n let needsCreateFileRoute = false\n let needsCreateLazyFileRoute = false\n for (const node of sortedRouteNodes) {\n if (isRouteNodeValidForAugmentation(node)) {\n if (node._fsRouteType !== 'lazy') {\n needsCreateFileRoute = true\n }\n if (acc.routePiecesByPath[node.routePath!]?.lazy) {\n needsCreateLazyFileRoute = true\n }\n }\n if (needsCreateFileRoute && needsCreateLazyFileRoute) break\n }\n if (needsCreateFileRoute) {\n typeImport.specifiers.push({ imported: 'CreateFileRoute' })\n }\n if (needsCreateLazyFileRoute) {\n typeImport.specifiers.push({ imported: 'CreateLazyFileRoute' })\n }\n\n if (typeImport.specifiers.length > 0) {\n typeImport.specifiers.push({ imported: 'FileRoutesByPath' })\n imports.push(typeImport)\n }\n }\n\n const routeTreeConfig = buildRouteTreeConfig(\n acc.routeTree,\n config.disableTypes,\n )\n\n const createUpdateRoutes = sortedRouteNodes.map((node) => {\n const pieces = acc.routePiecesByPath[node.routePath!]\n const loaderNode = pieces?.loader\n const componentNode = pieces?.component\n const errorComponentNode = pieces?.errorComponent\n const notFoundComponentNode = pieces?.notFoundComponent\n const pendingComponentNode = pieces?.pendingComponent\n const lazyComponentNode = pieces?.lazy\n\n return [\n [\n `const ${node.variableName}Route = ${node.variableName}RouteImport.update({\n ${[\n `id: '${node.path}'`,\n !node.isNonPath ||\n (node._fsRouteType === 'pathless_layout' && node.cleanedPath)\n ? `path: '${node.cleanedPath}'`\n : undefined,\n `getParentRoute: () => ${findParent(node)}`,\n ]\n .filter(Boolean)\n .join(',')}\n }${config.disableTypes ? '' : 'as any'})`,\n loaderNode\n ? `.updateLoader({ loader: lazyFn(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, loaderNode.filePath),\n ),\n config.addExtensions,\n ),\n )}'), 'loader') })`\n : '',\n componentNode ||\n errorComponentNode ||\n notFoundComponentNode ||\n pendingComponentNode\n ? `.update({\n ${(\n [\n ['component', componentNode],\n ['errorComponent', errorComponentNode],\n ['notFoundComponent', notFoundComponentNode],\n ['pendingComponent', pendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n // For .vue files, use 'default' as the export name since Vue SFCs export default\n const isVueFile = d[1]!.filePath.endsWith('.vue')\n const exportName = isVueFile ? 'default' : d[0]\n // Keep .vue extension for Vue files since Vite requires it\n const importPath = replaceBackslash(\n isVueFile\n ? path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n d[1]!.filePath,\n ),\n )\n : removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n d[1]!.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )\n return `${\n d[0]\n }: lazyRouteComponent(() => import('./${importPath}'), '${exportName}')`\n })\n .join('\\n,')}\n })`\n : '',\n lazyComponentNode\n ? (() => {\n // For .vue files, use 'default' export since Vue SFCs export default\n const isVueFile = lazyComponentNode.filePath.endsWith('.vue')\n const exportAccessor = isVueFile ? 'd.default' : 'd.Route'\n // Keep .vue extension for Vue files since Vite requires it\n const importPath = replaceBackslash(\n isVueFile\n ? path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n )\n : removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )\n return `.lazy(() => import('./${importPath}').then((d) => ${exportAccessor}))`\n })()\n : '',\n ].join(''),\n ].join('\\n\\n')\n })\n\n // Generate update for root route if it has component pieces\n const rootRoutePath = `/${rootPathId}`\n const rootPieces = acc.routePiecesByPath[rootRoutePath]\n const rootComponentNode = rootPieces?.component\n const rootErrorComponentNode = rootPieces?.errorComponent\n const rootNotFoundComponentNode = rootPieces?.notFoundComponent\n const rootPendingComponentNode = rootPieces?.pendingComponent\n\n let rootRouteUpdate = ''\n if (\n rootComponentNode ||\n rootErrorComponentNode ||\n rootNotFoundComponentNode ||\n rootPendingComponentNode\n ) {\n rootRouteUpdate = `const rootRouteWithChildren = rootRouteImport${\n rootComponentNode ||\n rootErrorComponentNode ||\n rootNotFoundComponentNode ||\n rootPendingComponentNode\n ? `.update({\n ${(\n [\n ['component', rootComponentNode],\n ['errorComponent', rootErrorComponentNode],\n ['notFoundComponent', rootNotFoundComponentNode],\n ['pendingComponent', rootPendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n // For .vue files, use 'default' as the export name since Vue SFCs export default\n const isVueFile = d[1]!.filePath.endsWith('.vue')\n const exportName = isVueFile ? 'default' : d[0]\n // Keep .vue extension for Vue files since Vite requires it\n const importPath = replaceBackslash(\n isVueFile\n ? path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, d[1]!.filePath),\n )\n : removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n d[1]!.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )\n return `${d[0]}: lazyRouteComponent(() => import('./${importPath}'), '${exportName}')`\n })\n .join('\\n,')}\n })`\n : ''\n }._addFileChildren(rootRouteChildren)${config.disableTypes ? '' : `._addFileTypes<FileRouteTypes>()`}`\n }\n\n let fileRoutesByPathInterface = ''\n let fileRoutesByFullPath = ''\n\n if (!config.disableTypes) {\n const routeNodesByFullPath = createRouteNodesByFullPath(acc.routeNodes)\n const routeNodesByTo = createRouteNodesByTo(acc.routeNodes)\n const routeNodesById = createRouteNodesById(acc.routeNodes)\n\n fileRoutesByFullPath = [\n `export interface FileRoutesByFullPath {\n${[...routeNodesByFullPath.entries()]\n .filter(([fullPath]) => fullPath)\n .map(([fullPath, routeNode]) => {\n return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n })}\n}`,\n `export interface FileRoutesByTo {\n${[...routeNodesByTo.entries()]\n .filter(([to]) => to)\n .map(([to, routeNode]) => {\n return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n })}\n}`,\n `export interface FileRoutesById {\n'${rootRouteId}': typeof rootRouteImport,\n${[...routeNodesById.entries()].map(([id, routeNode]) => {\n return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n})}\n}`,\n `export interface FileRouteTypes {\nfileRoutesByFullPath: FileRoutesByFullPath\nfullPaths: ${\n acc.routeNodes.length > 0\n ? [...routeNodesByFullPath.keys()]\n .filter((fullPath) => fullPath)\n .map((fullPath) => `'${fullPath}'`)\n .join('|')\n : 'never'\n }\nfileRoutesByTo: FileRoutesByTo\nto: ${\n acc.routeNodes.length > 0\n ? [...routeNodesByTo.keys()]\n .filter((to) => to)\n .map((to) => `'${to}'`)\n .join('|')\n : 'never'\n }\nid: ${[`'${rootRouteId}'`, ...[...routeNodesById.keys()].map((id) => `'${id}'`)].join('|')}\nfileRoutesById: FileRoutesById\n}`,\n `export interface RootRouteChildren {\n${acc.routeTree.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}\n}`,\n ].join('\\n')\n\n fileRoutesByPathInterface = buildFileRoutesByPathInterface({\n module: this.targetTemplate.fullPkg,\n interfaceName: 'FileRoutesByPath',\n routeNodes: sortedRouteNodes,\n config,\n })\n }\n\n const routeTree = [\n `const rootRouteChildren${config.disableTypes ? '' : `: RootRouteChildren`} = {\n ${acc.routeTree\n .map(\n (child) =>\n `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`,\n )\n .join(',')}\n}`,\n rootRouteUpdate\n ? rootRouteUpdate.replace(\n 'const rootRouteWithChildren = ',\n 'export const routeTree = ',\n )\n : `export const routeTree = rootRouteImport._addFileChildren(rootRouteChildren)${config.disableTypes ? '' : `._addFileTypes<FileRouteTypes>()`}`,\n ].join('\\n')\n\n checkRouteFullPathUniqueness(\n sortedRouteNodes.filter(\n (d) => d.children === undefined && 'lazy' !== d._fsRouteType,\n ),\n config,\n )\n\n let mergedImports = mergeImportDeclarations(imports)\n if (config.disableTypes) {\n mergedImports = mergedImports.filter((d) => d.importKind !== 'type')\n }\n\n const importStatements = mergedImports.map(buildImportString)\n\n let moduleAugmentation = ''\n if (config.verboseFileRoutes === false && !config.disableTypes) {\n moduleAugmentation = opts.routeFileResult\n .map((node) => {\n const getModuleDeclaration = (routeNode?: RouteNode) => {\n if (!isRouteNodeValidForAugmentation(routeNode)) {\n return ''\n }\n let moduleAugmentation = ''\n if (routeNode._fsRouteType === 'lazy') {\n moduleAugmentation = `const createLazyFileRoute: CreateLazyFileRoute<FileRoutesByPath['${routeNode.routePath}']['preLoaderRoute']>`\n } else {\n moduleAugmentation = `const createFileRoute: CreateFileRoute<'${routeNode.routePath}',\n FileRoutesByPath['${routeNode.routePath}']['parentRoute'],\n FileRoutesByPath['${routeNode.routePath}']['id'],\n FileRoutesByPath['${routeNode.routePath}']['path'],\n FileRoutesByPath['${routeNode.routePath}']['fullPath']\n >\n `\n }\n\n return `declare module './${getImportPath(routeNode, config, this.generatedRouteTreePath)}' {\n ${moduleAugmentation}\n }`\n }\n return getModuleDeclaration(node)\n })\n .join('\\n')\n }\n\n const rootRouteImport = getImportForRouteNode(\n rootRouteNode,\n config,\n this.generatedRouteTreePath,\n this.root,\n )\n routeImports.unshift(rootRouteImport)\n\n let footer: Array<string> = []\n if (config.routeTreeFileFooter) {\n if (Array.isArray(config.routeTreeFileFooter)) {\n footer = config.routeTreeFileFooter\n } else {\n footer = config.routeTreeFileFooter()\n }\n }\n const routeTreeContent = [\n ...config.routeTreeFileHeader,\n `// This file was automatically generated by TanStack Router.\n// You should NOT make any changes in this file as it will be overwritten.\n// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.`,\n [...importStatements].join('\\n'),\n mergeImportDeclarations(routeImports).map(buildImportString).join('\\n'),\n virtualRouteNodes.join('\\n'),\n createUpdateRoutes.join('\\n'),\n fileRoutesByFullPath,\n fileRoutesByPathInterface,\n moduleAugmentation,\n routeTreeConfig.join('\\n'),\n routeTree,\n ...footer,\n ]\n .filter(Boolean)\n .join('\\n\\n')\n return {\n routeTreeContent,\n routeTree: acc.routeTree,\n routeNodes: acc.routeNodes,\n }\n }\n\n private async processRouteNodeFile(node: RouteNode): Promise<{\n shouldWriteTree: boolean\n cacheEntry: RouteNodeCacheEntry\n node: RouteNode\n } | null> {\n const result = await this.isRouteFileCacheFresh(node)\n\n if (result.status === 'fresh') {\n return {\n node: result.cacheEntry.node,\n shouldWriteTree: false,\n cacheEntry: result.cacheEntry,\n }\n }\n\n const previousCacheEntry = result.cacheEntry\n\n const existingRouteFile = await this.fs.readFile(node.fullPath)\n if (existingRouteFile === 'file-not-existing') {\n throw new Error(`⚠️ File ${node.fullPath} does not exist`)\n }\n\n const updatedCacheEntry: RouteNodeCacheEntry = {\n fileContent: existingRouteFile.fileContent,\n mtimeMs: existingRouteFile.stat.mtimeMs,\n routeId: node.routePath ?? '$$TSR_NO_ROUTE_PATH_ASSIGNED$$',\n node,\n }\n\n const escapedRoutePath = node.routePath?.replaceAll('$', '$$') ?? ''\n\n let shouldWriteRouteFile = false\n let shouldWriteTree = false\n // now we need to either scaffold the file or transform it\n if (!existingRouteFile.fileContent) {\n shouldWriteRouteFile = true\n shouldWriteTree = true\n // Creating a new lazy route file\n if (node._fsRouteType === 'lazy') {\n const tLazyRouteTemplate = this.targetTemplate.lazyRoute\n // Check by default check if the user has a specific lazy route template\n // If not, check if the user has a route template and use that instead\n updatedCacheEntry.fileContent = await fillTemplate(\n this.config,\n (this.config.customScaffolding?.lazyRouteTemplate ||\n this.config.customScaffolding?.routeTemplate) ??\n tLazyRouteTemplate.template(),\n {\n tsrImports: tLazyRouteTemplate.imports.tsrImports(),\n tsrPath: escapedRoutePath.replaceAll(/\\{(.+?)\\}/gm, '$1'),\n tsrExportStart:\n tLazyRouteTemplate.imports.tsrExportStart(escapedRoutePath),\n tsrExportEnd: tLazyRouteTemplate.imports.tsrExportEnd(),\n },\n )\n } else if (\n // Creating a new normal route file\n (['layout', 'static'] satisfies Array<FsRouteType>).some(\n (d) => d === node._fsRouteType,\n ) ||\n (\n [\n 'component',\n 'pendingComponent',\n 'errorComponent',\n 'notFoundComponent',\n 'loader',\n ] satisfies Array<FsRouteType>\n ).every((d) => d !== node._fsRouteType)\n ) {\n const tRouteTemplate = this.targetTemplate.route\n updatedCacheEntry.fileContent = await fillTemplate(\n this.config,\n this.config.customScaffolding?.routeTemplate ??\n tRouteTemplate.template(),\n {\n tsrImports: tRouteTemplate.imports.tsrImports(),\n tsrPath: escapedRoutePath.replaceAll(/\\{(.+?)\\}/gm, '$1'),\n tsrExportStart:\n tRouteTemplate.imports.tsrExportStart(escapedRoutePath),\n tsrExportEnd: tRouteTemplate.imports.tsrExportEnd(),\n },\n )\n } else {\n return null\n }\n }\n\n // Check if this is a Vue component file\n // Vue SFC files (.vue) don't need transformation as they can't have a Route export\n const isVueFile = node.filePath.endsWith('.vue')\n\n if (!isVueFile) {\n // transform the file\n const transformResult = await transform({\n source: updatedCacheEntry.fileContent,\n ctx: {\n target: this.config.target,\n routeId: escapedRoutePath,\n lazy: node._fsRouteType === 'lazy',\n verboseFileRoutes: !(this.config.verboseFileRoutes === false),\n },\n node,\n })\n\n if (transformResult.result === 'no-route-export') {\n const fileName = path.basename(node.fullPath)\n const dirName = path.dirname(node.fullPath)\n const ignorePrefix = this.config.routeFileIgnorePrefix\n const ignorePattern = this.config.routeFileIgnorePattern\n const suggestedFileName = `${ignorePrefix}${fileName}`\n const suggestedFullPath = path.join(dirName, suggestedFileName)\n\n let message = `Warning: Route file \"${node.fullPath}\" does not export a Route. This file will not be included in the route tree.`\n message += `\\n\\nIf this file is not intended to be a route, you can exclude it using one of these options:`\n message += `\\n 1. Rename the file to \"${suggestedFullPath}\" (prefix with \"${ignorePrefix}\")`\n message += `\\n 2. Use 'routeFileIgnorePattern' in your config to match this file`\n message += `\\n\\nCurrent configuration:`\n message += `\\n routeFileIgnorePrefix: \"${ignorePrefix}\"`\n message += `\\n routeFileIgnorePattern: ${ignorePattern ? `\"${ignorePattern}\"` : 'undefined'}`\n\n this.logger.warn(message)\n return null\n }\n if (transformResult.result === 'error') {\n throw new Error(\n `Error transforming route file ${node.fullPath}: ${transformResult.error}`,\n )\n }\n if (transformResult.result === 'modified') {\n updatedCacheEntry.fileContent = transformResult.output\n shouldWriteRouteFile = true\n }\n }\n\n for (const plugin of this.plugins) {\n plugin.afterTransform?.({ node, prevNode: previousCacheEntry?.node })\n }\n\n // file was changed\n if (shouldWriteRouteFile) {\n const stats = await this.safeFileWrite({\n filePath: node.fullPath,\n newContent: updatedCacheEntry.fileContent,\n strategy: {\n type: 'mtime',\n expectedMtimeMs: updatedCacheEntry.mtimeMs,\n },\n })\n updatedCacheEntry.mtimeMs = stats.mtimeMs\n }\n\n this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry)\n return {\n node,\n shouldWriteTree,\n cacheEntry: updatedCacheEntry,\n }\n }\n\n private async didRouteFileChangeComparedToCache(\n file: {\n path: string\n mtimeMs?: bigint\n },\n cache: 'routeNodeCache' | 'routeNodeShadowCache',\n ): Promise<FileCacheChange<RouteNodeCacheEntry>> {\n const cacheEntry = this[cache].get(file.path)\n return this.didFileChangeComparedToCache(file, cacheEntry)\n }\n\n private async didFileChangeComparedToCache<\n TCacheEntry extends GeneratorCacheEntry,\n >(\n file: {\n path: string\n mtimeMs?: bigint\n },\n cacheEntry: TCacheEntry | undefined,\n ): Promise<FileCacheChange<TCacheEntry>> {\n // for now we rely on the modification time of the file\n // to determine if the file has changed\n // we could also compare the file content but this would be slower as we would have to read the file\n\n if (!cacheEntry) {\n return { result: 'file-not-in-cache' }\n }\n let mtimeMs = file.mtimeMs\n\n if (mtimeMs === undefined) {\n try {\n const currentStat = await this.fs.stat(file.path)\n mtimeMs = currentStat.mtimeMs\n } catch {\n return { result: 'cannot-stat-file' }\n }\n }\n return { result: mtimeMs !== cacheEntry.mtimeMs, mtimeMs, cacheEntry }\n }\n\n private async safeFileWrite(opts: {\n filePath: string\n newContent: string\n strategy:\n | {\n type: 'mtime'\n expectedMtimeMs: bigint\n }\n | {\n type: 'new-file'\n }\n }) {\n const tmpPath = this.getTempFileName(opts.filePath)\n await this.fs.writeFile(tmpPath, opts.newContent)\n\n if (opts.strategy.type === 'mtime') {\n const beforeStat = await this.fs.stat(opts.filePath)\n if (beforeStat.mtimeMs !== opts.strategy.expectedMtimeMs) {\n throw rerun({\n msg: `File ${opts.filePath} was modified by another process during processing.`,\n event: { type: 'update', path: opts.filePath },\n })\n }\n const newFileState = await this.fs.stat(tmpPath)\n if (newFileState.mode !== beforeStat.mode) {\n await this.fs.chmod(tmpPath, beforeStat.mode)\n }\n if (\n newFileState.uid !== beforeStat.uid ||\n newFileState.gid !== beforeStat.gid\n ) {\n try {\n await this.fs.chown(tmpPath, beforeStat.uid, beforeStat.gid)\n } catch (err) {\n if (\n typeof err === 'object' &&\n err !== null &&\n 'code' in err &&\n (err as any).code === 'EPERM'\n ) {\n console.warn(\n `[safeFileWrite] chown failed: ${(err as any).message}`,\n )\n } else {\n throw err\n }\n }\n }\n } else {\n if (await checkFileExists(opts.filePath)) {\n throw rerun({\n msg: `File ${opts.filePath} already exists. Cannot overwrite.`,\n event: { type: 'update', path: opts.filePath },\n })\n }\n }\n\n const stat = await this.fs.stat(tmpPath)\n\n await this.fs.rename(tmpPath, opts.filePath)\n\n return stat\n }\n\n private getTempFileName(filePath: string) {\n const absPath = path.resolve(filePath)\n const hash = crypto.createHash('md5').update(absPath).digest('hex')\n // lazy initialize sessionId to only create tmpDir when it is first needed\n if (!this.sessionId) {\n // ensure the directory exists\n mkdirSync(this.config.tmpDir, { recursive: true })\n this.sessionId = crypto.randomBytes(4).toString('hex')\n }\n return path.join(this.config.tmpDir, `${this.sessionId}-${hash}`)\n }\n\n private async isRouteFileCacheFresh(node: RouteNode): Promise<\n | {\n status: 'fresh'\n cacheEntry: RouteNodeCacheEntry\n }\n | { status: 'stale'; cacheEntry?: RouteNodeCacheEntry }\n > {\n const fileChangedCache = await this.didRouteFileChangeComparedToCache(\n { path: node.fullPath },\n 'routeNodeCache',\n )\n if (fileChangedCache.result === false) {\n this.routeNodeShadowCache.set(node.fullPath, fileChangedCache.cacheEntry)\n return {\n status: 'fresh',\n cacheEntry: fileChangedCache.cacheEntry,\n }\n }\n if (fileChangedCache.result === 'cannot-stat-file') {\n throw new Error(`⚠️ expected route file to exist at ${node.fullPath}`)\n }\n const mtimeMs =\n fileChangedCache.result === true ? fileChangedCache.mtimeMs : undefined\n\n const shadowCacheFileChange = await this.didRouteFileChangeComparedToCache(\n { path: node.fullPath, mtimeMs },\n 'routeNodeShadowCache',\n )\n\n if (shadowCacheFileChange.result === 'cannot-stat-file') {\n throw new Error(`⚠️ expected route file to exist at ${node.fullPath}`)\n }\n\n if (shadowCacheFileChange.result === false) {\n // shadow cache has latest file state already\n if (fileChangedCache.result === true) {\n return {\n status: 'fresh',\n cacheEntry: shadowCacheFileChange.cacheEntry,\n }\n }\n }\n\n if (fileChangedCache.result === 'file-not-in-cache') {\n return {\n status: 'stale',\n }\n }\n return { status: 'stale', cacheEntry: fileChangedCache.cacheEntry }\n }\n\n private async handleRootNode(node: RouteNode) {\n const result = await this.isRouteFileCacheFresh(node)\n\n if (result.status === 'fresh') {\n this.routeNodeShadowCache.set(node.fullPath, result.cacheEntry)\n }\n const rootNodeFile = await this.fs.readFile(node.fullPath)\n if (rootNodeFile === 'file-not-existing') {\n throw new Error(`⚠️ expected root route to exist at ${node.fullPath}`)\n }\n\n const updatedCacheEntry: RouteNodeCacheEntry = {\n fileContent: rootNodeFile.fileContent,\n mtimeMs: rootNodeFile.stat.mtimeMs,\n routeId: node.routePath ?? '$$TSR_NO_ROOT_ROUTE_PATH_ASSIGNED$$',\n node,\n }\n\n // scaffold the root route\n if (!rootNodeFile.fileContent) {\n const rootTemplate = this.targetTemplate.rootRoute\n const rootRouteContent = await fillTemplate(\n this.config,\n rootTemplate.template(),\n {\n tsrImports: rootTemplate.imports.tsrImports(),\n tsrPath: rootPathId,\n tsrExportStart: rootTemplate.imports.tsrExportStart(),\n tsrExportEnd: rootTemplate.imports.tsrExportEnd(),\n },\n )\n\n this.logger.log(`🟡 Creating ${node.fullPath}`)\n const stats = await this.safeFileWrite({\n filePath: node.fullPath,\n newContent: rootRouteContent,\n strategy: {\n type: 'mtime',\n expectedMtimeMs: rootNodeFile.stat.mtimeMs,\n },\n })\n updatedCacheEntry.fileContent = rootRouteContent\n updatedCacheEntry.mtimeMs = stats.mtimeMs\n }\n\n this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry)\n }\n\n public async getCrawlingResult(): Promise<CrawlingResult | undefined> {\n await this.runPromise\n return this.crawlingResult\n }\n\n private static handleNode(\n node: RouteNode,\n acc: HandleNodeAccumulator,\n prefixMap: RoutePrefixMap,\n config?: Config,\n ) {\n let parentRoute = hasParentRoute(prefixMap, node, node.routePath)\n\n // Check routeNodesByPath for a closer parent that may not be in prefixMap.\n //\n // Why: The prefixMap excludes lazy routes by design. When lazy-only routes are\n // nested inside a pathless layout, the virtual route created from the lazy file\n // won't be in the prefixMap, but it will be in routeNodesByPath.\n //\n // Example: Given files _layout/path.lazy.tsx and _layout/path.index.lazy.tsx:\n // - prefixMap contains: /_layout (from route.tsx)\n // - routeNodesByPath contains: /_layout AND /_layout/path (virtual from lazy)\n // - For /_layout/path/, hasParentRoute returns /_layout (wrong)\n // - But the correct parent is /_layout/path (the virtual route from path.lazy.tsx)\n //\n // Optimization: Only search if we might find a closer parent. The search walks\n // up from the immediate parent path, so if the first candidate matches what\n // prefixMap found, there's no closer parent to find.\n if (node.routePath) {\n const lastSlash = node.routePath.lastIndexOf('/')\n if (lastSlash > 0) {\n const immediateParentPath = node.routePath.substring(0, lastSlash)\n const candidate = acc.routeNodesByPath.get(immediateParentPath)\n if (\n candidate &&\n candidate.routePath !== node.routePath &&\n candidate !== parentRoute\n ) {\n // Found a closer parent in routeNodesByPath that differs from prefixMap result\n parentRoute = candidate\n }\n }\n }\n\n if (parentRoute) node.parent = parentRoute\n\n node.path = determineNodePath(node)\n\n const trimmedPath = trimPathLeft(node.path ?? '')\n const trimmedOriginalPath = trimPathLeft(\n node.originalRoutePath?.replace(\n node.parent?.originalRoutePath ?? '',\n '',\n ) ?? '',\n )\n\n const split = trimmedPath.split('/')\n const originalSplit = trimmedOriginalPath.split('/')\n const lastRouteSegment = split[split.length - 1] ?? trimmedPath\n const lastOriginalSegment =\n originalSplit[originalSplit.length - 1] ?? trimmedOriginalPath\n\n // A segment is non-path if it starts with underscore AND the underscore is not escaped\n node.isNonPath =\n isSegmentPathless(lastRouteSegment, lastOriginalSegment) ||\n split.every((part) => this.routeGroupPatternRegex.test(part))\n\n // Use escape-aware functions to compute cleanedPath\n node.cleanedPath = removeGroups(\n removeUnderscoresWithEscape(\n removeLayoutSegmentsWithEscape(node.path, node.originalRoutePath),\n node.originalRoutePath,\n ),\n )\n\n if (\n node._fsRouteType === 'layout' ||\n node._fsRouteType === 'pathless_layout'\n ) {\n node.cleanedPath = removeTrailingSlash(node.cleanedPath)\n }\n\n if (\n !node.isVirtual &&\n (\n [\n 'lazy',\n 'loader',\n 'component',\n 'pendingComponent',\n 'errorComponent',\n 'notFoundComponent',\n ] satisfies Array<FsRouteType>\n ).some((d) => d === node._fsRouteType)\n ) {\n acc.routePiecesByPath[node.routePath!] =\n acc.routePiecesByPath[node.routePath!] || {}\n\n const pieceKey =\n node._fsRouteType === 'lazy'\n ? 'lazy'\n : (node._fsRouteType as keyof (typeof acc.routePiecesByPath)[string])\n acc.routePiecesByPath[node.routePath!]![pieceKey] = node\n\n const anchorRoute = acc.routeNodesByPath.get(node.routePath!)\n\n // Don't create virtual routes for root route component pieces - the root route is handled separately\n if (!anchorRoute && node.routePath !== `/${rootPathId}`) {\n this.handleNode(\n {\n ...node,\n isVirtual: true,\n _fsRouteType: 'static',\n },\n acc,\n prefixMap,\n config,\n )\n }\n return\n }\n\n const isPathlessLayoutWithPath =\n node._fsRouteType === 'pathless_layout' &&\n node.cleanedPath &&\n node.cleanedPath.length > 0\n\n // Special handling: pathless layouts with path need to find real ancestor\n if (!node.isVirtual && isPathlessLayoutWithPath) {\n const immediateParentPath =\n removeLastSegmentFromPath(node.routePath) || '/'\n const immediateParentOriginalPath =\n removeLastSegmentFromPath(node.originalRoutePath) || '/'\n let searchPath = immediateParentPath\n\n // Find nearest real (non-virtual, non-index) parent\n while (searchPath) {\n const candidate = acc.routeNodesByPath.get(searchPath)\n if (candidate && !candidate.isVirtual && candidate.path !== '/') {\n node.parent = candidate\n node.path =\n node.routePath?.replace(candidate.routePath ?? '', '') || '/'\n const pathRelativeToParent =\n immediateParentPath.replace(candidate.routePath ?? '', '') || '/'\n const originalPathRelativeToParent =\n immediateParentOriginalPath.replace(\n candidate.originalRoutePath ?? '',\n '',\n ) || '/'\n node.cleanedPath = removeGroups(\n removeUnderscoresWithEscape(\n removeLayoutSegmentsWithEscape(\n pathRelativeToParent,\n originalPathRelativeToParent,\n ),\n originalPathRelativeToParent,\n ),\n )\n break\n }\n if (searchPath === '/') break\n searchPath = removeLastSegmentFromPath(searchPath) || '/'\n }\n }\n\n // Add to parent's children or to root\n if (node.parent) {\n node.parent.children = node.parent.children ?? []\n node.parent.children.push(node)\n } else {\n acc.routeTree.push(node)\n }\n\n acc.routeNodes.push(node)\n if (node.routePath) {\n // Always register routes by path so child routes can find parents.\n // Virtual routes (created from lazy-only files) also need to be registered\n // so that index routes like path.index.lazy.tsx can find their parent path.lazy.tsx.\n // If a non-virtual route is later processed for the same path, it will overwrite.\n acc.routeNodesByPath.set(node.routePath, node)\n }\n }\n\n // only process files that are relevant for the route tree generation\n private isFileRelevantForRouteTreeGeneration(filePath: string): boolean {\n // the generated route tree file\n if (filePath === this.generatedRouteTreePath) {\n return true\n }\n\n // files inside the routes folder\n if (filePath.startsWith(this.routesDirectoryPath)) {\n return true\n }\n\n // the virtual route config file passed into `virtualRouteConfig`\n if (\n typeof this.config.virtualRouteConfig === 'string' &&\n filePath === this.config.virtualRouteConfig\n ) {\n return true\n }\n\n // this covers all files that are mounted via `virtualRouteConfig` or any `__virtual.ts` files\n if (this.routeNodeCache.has(filePath)) {\n return true\n }\n\n // virtual config files such as`__virtual.ts`\n if (isVirtualConfigFile(path.basename(filePath))) {\n return true\n }\n\n // route files inside directories mounted via `physical()` inside a virtual route config\n if (this.physicalDirectories.some((dir) => filePath.startsWith(dir))) {\n return true\n }\n\n return false\n }\n}\n"],"names":["virtualGetRouteNodes","physicalGetRouteNodes","moduleAugmentation"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/router-generator",
3
- "version": "1.151.3",
3
+ "version": "1.151.5",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -54,8 +54,8 @@
54
54
  "source-map": "^0.7.4",
55
55
  "tsx": "^4.19.2",
56
56
  "zod": "^3.24.2",
57
- "@tanstack/router-utils": "1.143.11",
58
57
  "@tanstack/router-core": "1.151.3",
58
+ "@tanstack/router-utils": "1.143.11",
59
59
  "@tanstack/virtual-file-routes": "1.145.4"
60
60
  },
61
61
  "devDependencies": {
package/src/generator.ts CHANGED
@@ -1422,19 +1422,33 @@ ${acc.routeTree.map((child) => `${child.variableName}Route: typeof ${getResolved
1422
1422
  ) {
1423
1423
  let parentRoute = hasParentRoute(prefixMap, node, node.routePath)
1424
1424
 
1425
- // Fallback: check acc.routeNodesByPath for parents not in prefixMap
1426
- // This handles virtual routes created from lazy-only files that weren't
1427
- // in the initial prefixMap build
1428
- if (!parentRoute && node.routePath) {
1429
- let searchPath = node.routePath
1430
- while (searchPath.length > 0) {
1431
- const lastSlash = searchPath.lastIndexOf('/')
1432
- if (lastSlash <= 0) break
1433
- searchPath = searchPath.substring(0, lastSlash)
1434
- const candidate = acc.routeNodesByPath.get(searchPath)
1435
- if (candidate && candidate.routePath !== node.routePath) {
1425
+ // Check routeNodesByPath for a closer parent that may not be in prefixMap.
1426
+ //
1427
+ // Why: The prefixMap excludes lazy routes by design. When lazy-only routes are
1428
+ // nested inside a pathless layout, the virtual route created from the lazy file
1429
+ // won't be in the prefixMap, but it will be in routeNodesByPath.
1430
+ //
1431
+ // Example: Given files _layout/path.lazy.tsx and _layout/path.index.lazy.tsx:
1432
+ // - prefixMap contains: /_layout (from route.tsx)
1433
+ // - routeNodesByPath contains: /_layout AND /_layout/path (virtual from lazy)
1434
+ // - For /_layout/path/, hasParentRoute returns /_layout (wrong)
1435
+ // - But the correct parent is /_layout/path (the virtual route from path.lazy.tsx)
1436
+ //
1437
+ // Optimization: Only search if we might find a closer parent. The search walks
1438
+ // up from the immediate parent path, so if the first candidate matches what
1439
+ // prefixMap found, there's no closer parent to find.
1440
+ if (node.routePath) {
1441
+ const lastSlash = node.routePath.lastIndexOf('/')
1442
+ if (lastSlash > 0) {
1443
+ const immediateParentPath = node.routePath.substring(0, lastSlash)
1444
+ const candidate = acc.routeNodesByPath.get(immediateParentPath)
1445
+ if (
1446
+ candidate &&
1447
+ candidate.routePath !== node.routePath &&
1448
+ candidate !== parentRoute
1449
+ ) {
1450
+ // Found a closer parent in routeNodesByPath that differs from prefixMap result
1436
1451
  parentRoute = candidate
1437
- break
1438
1452
  }
1439
1453
  }
1440
1454
  }