{"version":3,"file":"generator.cjs","names":[],"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  getResolvedRouteNodeVariableName,\n  hasParentRoute,\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 { validateRouteParams } from './validate-route-params'\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        { routeId: 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 (this.routeTreeFileCache.fileContent === routeTreeContent) {\n        // existing route tree file is already up-to-date, don't write it.\n        // When 'force' was set because an external change was detected,\n        // we still re-read and re-check here, but if the generated content\n        // matches we skip the write to avoid triggering another watcher cycle.\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    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    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      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    if (node.routePath) {\n      validateRouteParams(node.routePath, node.filePath, this.logger)\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        },\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    await this.fs.rename(tmpPath, opts.filePath)\n\n    // stat the target file AFTER rename so the cached mtime matches\n    // what the filesystem reports for the actual file path.\n    // Previously we stat'd the temp file before rename, but rename()\n    // can assign a different mtime to the target on some filesystems,\n    // causing the cache to be permanently stale.\n    const stat = await this.fs.stat(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    // We walk up the path segments to find the closest registered parent. This handles\n    // cases where multiple path segments (e.g., $a/$b) don't have intermediate routes.\n    if (node.routePath) {\n      let searchPath = node.routePath\n      while (searchPath.length > 0) {\n        const lastSlash = searchPath.lastIndexOf('/')\n        if (lastSlash <= 0) break\n\n        searchPath = searchPath.substring(0, lastSlash)\n        const candidate = acc.routeNodesByPath.get(searchPath)\n        if (candidate && candidate.routePath !== node.routePath) {\n          // Found a parent in routeNodesByPath\n          // If it's different from what prefixMap found AND is a closer match, use it\n          if (candidate !== parentRoute) {\n            // Check if this candidate is a closer parent than what prefixMap found\n            // (longer path prefix means closer parent)\n            if (\n              !parentRoute ||\n              (candidate.routePath?.length ?? 0) >\n                (parentRoute.routePath?.length ?? 0)\n            ) {\n              parentRoute = candidate\n            }\n          }\n          break\n        }\n      }\n    }\n\n    // Virtual routes may have an explicit parent from virtual config.\n    // If we can find that exact parent, use it to prevent auto-nesting siblings\n    // based on path prefix matching (#5822, #5431).\n    if (node._virtualParentRoutePath !== undefined) {\n      const explicitParent = acc.routeNodesByPath.get(\n        node._virtualParentRoutePath,\n      )\n      if (explicitParent) {\n        parentRoute = explicitParent\n      } else if (node._virtualParentRoutePath === `/${rootPathId}`) {\n        // The explicit parent is the root route (handled separately).\n        // Override path-based inference so this node stays at root level.\n        parentRoute = null\n      }\n      // Otherwise the explicit parent was a virtual file-less route that got\n      // filtered out. Fall back to the path-based parentRoute already computed.\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"],"mappings":"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"}