@tanstack/router-generator 1.132.0-alpha.1 → 1.132.0-alpha.15

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.
@@ -82,7 +82,7 @@ class Generator {
82
82
  this.logger = logger.logging({ disabled: this.config.disableLogging });
83
83
  this.root = opts.root;
84
84
  this.fs = opts.fs || DefaultFileSystem;
85
- this.generatedRouteTreePath = path.resolve(this.config.generatedRouteTree);
85
+ this.generatedRouteTreePath = this.getGeneratedRouteTreePath();
86
86
  this.targetTemplate = template.getTargetTemplate(this.config);
87
87
  this.routesDirectoryPath = this.getRoutesDirectoryPath();
88
88
  this.plugins.push(...opts.config.plugins || []);
@@ -98,6 +98,16 @@ class Generator {
98
98
  }
99
99
  });
100
100
  }
101
+ getGeneratedRouteTreePath() {
102
+ const generatedRouteTreePath = path.isAbsolute(
103
+ this.config.generatedRouteTree
104
+ ) ? this.config.generatedRouteTree : path.resolve(this.root, this.config.generatedRouteTree);
105
+ const generatedRouteTreeDir = path.dirname(generatedRouteTreePath);
106
+ if (!node_fs.existsSync(generatedRouteTreeDir)) {
107
+ node_fs.mkdirSync(generatedRouteTreeDir, { recursive: true });
108
+ }
109
+ return generatedRouteTreePath;
110
+ }
101
111
  getRoutesDirectoryPath() {
102
112
  return path.isAbsolute(this.config.routesDirectory) ? this.config.routesDirectory : path.resolve(this.root, this.config.routesDirectory);
103
113
  }
@@ -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 { mkdirSync } from 'node:fs'\nimport crypto from 'node:crypto'\nimport { deepEqual, 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 buildFileRoutesByPathInterface,\n buildImportString,\n buildRouteTreeConfig,\n checkFileExists,\n createRouteNodesByFullPath,\n createRouteNodesById,\n createRouteNodesByTo,\n determineNodePath,\n findParent,\n format,\n getResolvedRouteNodeVariableName,\n hasParentRoute,\n isRouteNodeValidForAugmentation,\n lowerCaseFirstChar,\n mergeImportDeclarations,\n multiSortBy,\n removeExt,\n removeGroups,\n removeLastSegmentFromPath,\n removeLayoutSegments,\n removeUnderscores,\n replaceBackslash,\n resetRegex,\n routePathToVariable,\n trimPathLeft,\n} from './utils'\nimport { fillTemplate, getTargetTemplate } from './template'\nimport { transform } from './transform/transform'\nimport { defaultGeneratorPlugin } from './plugin/default-generator-plugin'\nimport type {\n GeneratorPlugin,\n GeneratorPluginWithTransform,\n} 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'\nimport type { TransformPlugin } from './transform/types'\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 exports: Array<string>\n routeId: string\n}\n\ntype GeneratorRouteNodeCache = Map</** filePath **/ string, RouteNodeCacheEntry>\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 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> = [defaultGeneratorPlugin()]\n private pluginsWithTransform: Array<GeneratorPluginWithTransform> = []\n // this is just a cache for the transform plugins since we need them for each route file that is to be processed\n private transformPlugins: Array<TransformPlugin> = []\n private routeGroupPatternRegex = /\\(.+\\)/g\n private physicalDirectories: Array<string> = []\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 = path.resolve(this.config.generatedRouteTree)\n this.targetTemplate = getTargetTemplate(this.config)\n\n this.routesDirectoryPath = this.getRoutesDirectoryPath()\n this.plugins.push(...(opts.config.plugins || []))\n this.plugins.forEach((plugin) => {\n if ('transformPlugin' in plugin) {\n if (this.pluginsWithTransform.find((p) => p.name === plugin.name)) {\n throw new Error(\n `Plugin with name \"${plugin.name}\" is already registered for export ${plugin.transformPlugin.exportName}!`,\n )\n }\n this.pluginsWithTransform.push(plugin)\n this.transformPlugins.push(plugin.transformPlugin)\n }\n })\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 const start = performance.now()\n await this.generatorInternal()\n const end = performance.now()\n this.logger.info(\n `Generated route tree in ${Math.round(end - start)}ms`,\n )\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 } else {\n getRouteNodesResult = await physicalGetRouteNodes(this.config, this.root)\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 writeRouteTreeFile = await this.handleRootNode(rootRouteNode)\n\n const preRouteNodes = multiSortBy(beforeRouteNodes, [\n (d) => (d.routePath === '/' ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) =>\n d.filePath.match(new RegExp(`[./]${this.config.indexToken}[.]`))\n ? 1\n : -1,\n (d) =>\n d.filePath.match(\n /[./](component|errorComponent|pendingComponent|loader|lazy)[.]/,\n )\n ? 1\n : -1,\n (d) =>\n d.filePath.match(new RegExp(`[./]${this.config.routeToken}[.]`))\n ? -1\n : 1,\n (d) => (d.routePath?.endsWith('/') ? -1 : 1),\n (d) => d.routePath,\n ]).filter((d) => ![`/${rootPathId}`].includes(d.routePath || ''))\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 return result.value\n }\n return []\n })\n\n routeFileResult.forEach((result) => {\n if (!result.node.exports?.length) {\n this.logger.warn(\n `Route file \"${result.cacheEntry.fileContent}\" does not export any route piece. This is likely a mistake.`,\n )\n }\n })\n if (routeFileResult.find((r) => r.shouldWriteTree)) {\n writeRouteTreeFile = true\n }\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 for (const fullPath of this.routeNodeCache.keys()) {\n if (!this.routeNodeShadowCache.has(fullPath)) {\n writeRouteTreeFile = true\n break\n }\n }\n }\n\n if (!writeRouteTreeFile) {\n this.swapCaches()\n return\n }\n\n let routeTreeContent = this.buildRouteTreeFileContent(\n rootRouteNode,\n preRouteNodes,\n routeFileResult,\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.swapCaches()\n }\n\n private swapCaches() {\n this.routeNodeCache = this.routeNodeShadowCache\n this.routeNodeShadowCache = new Map()\n }\n\n private buildRouteTreeFileContent(\n rootRouteNode: RouteNode,\n preRouteNodes: Array<RouteNode>,\n routeFileResult: Array<{\n cacheEntry: RouteNodeCacheEntry\n node: RouteNode\n }>,\n ) {\n const getImportForRouteNode = (node: RouteNode, exportName: string) => {\n if (node.exports?.includes(exportName)) {\n return {\n source: `./${this.getImportPath(node)}`,\n specifiers: [\n {\n imported: exportName,\n local: `${node.variableName}${exportName}Import`,\n },\n ],\n } satisfies ImportDeclaration\n }\n return undefined\n }\n\n const buildRouteTreeForExport = (plugin: GeneratorPluginWithTransform) => {\n const exportName = plugin.transformPlugin.exportName\n const acc: HandleNodeAccumulator = {\n routeTree: [],\n routeNodes: [],\n routePiecesByPath: {},\n }\n for (const node of preRouteNodes) {\n if (node.exports?.includes(plugin.transformPlugin.exportName)) {\n this.handleNode(node, acc)\n }\n }\n\n const sortedRouteNodes = multiSortBy(acc.routeNodes, [\n (d) => (d.routePath?.includes(`/${rootPathId}`) ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => (d.routePath?.endsWith(this.config.indexToken) ? -1 : 1),\n (d) => d,\n ])\n\n const pluginConfig = plugin.config({\n generator: this,\n rootRouteNode,\n sortedRouteNodes,\n })\n\n const routeImports = sortedRouteNodes\n .filter((d) => !d.isVirtual)\n .flatMap((node) => getImportForRouteNode(node, exportName) ?? [])\n\n const hasMatchingRouteFiles =\n acc.routeNodes.length > 0 || rootRouteNode.exports?.includes(exportName)\n\n const virtualRouteNodes = sortedRouteNodes\n .filter((d) => d.isVirtual)\n .map((node) => {\n return `const ${\n node.variableName\n }${exportName}Import = ${plugin.createVirtualRouteCode({ node })}`\n })\n if (\n !rootRouteNode.exports?.includes(exportName) &&\n pluginConfig.virtualRootRoute\n ) {\n virtualRouteNodes.unshift(\n `const ${rootRouteNode.variableName}${exportName}Import = ${plugin.createRootRouteCode()}`,\n )\n }\n\n const imports = plugin.imports({\n sortedRouteNodes,\n acc,\n generator: this,\n rootRouteNode,\n })\n\n const routeTreeConfig = buildRouteTreeConfig(\n acc.routeTree,\n exportName,\n this.config.disableTypes,\n )\n\n const createUpdateRoutes = sortedRouteNodes.map((node) => {\n const loaderNode = acc.routePiecesByPath[node.routePath!]?.loader\n const componentNode = acc.routePiecesByPath[node.routePath!]?.component\n const errorComponentNode =\n acc.routePiecesByPath[node.routePath!]?.errorComponent\n const pendingComponentNode =\n acc.routePiecesByPath[node.routePath!]?.pendingComponent\n const lazyComponentNode = acc.routePiecesByPath[node.routePath!]?.lazy\n\n return [\n [\n `const ${node.variableName}${exportName} = ${node.variableName}${exportName}Import.update({\n ${[\n `id: '${node.path}'`,\n !node.isNonPath ? `path: '${node.cleanedPath}'` : undefined,\n `getParentRoute: () => ${findParent(node, exportName)}`,\n ]\n .filter(Boolean)\n .join(',')}\n }${this.config.disableTypes ? '' : 'as any'})`,\n loaderNode\n ? `.updateLoader({ loader: lazyFn(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(this.config.generatedRouteTree),\n path.resolve(\n this.config.routesDirectory,\n loaderNode.filePath,\n ),\n ),\n this.config.addExtensions,\n ),\n )}'), 'loader') })`\n : '',\n componentNode || errorComponentNode || pendingComponentNode\n ? `.update({\n ${(\n [\n ['component', componentNode],\n ['errorComponent', errorComponentNode],\n ['pendingComponent', pendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n return `${\n d[0]\n }: lazyRouteComponent(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(this.config.generatedRouteTree),\n path.resolve(\n this.config.routesDirectory,\n d[1]!.filePath,\n ),\n ),\n this.config.addExtensions,\n ),\n )}'), '${d[0]}')`\n })\n .join('\\n,')}\n })`\n : '',\n lazyComponentNode\n ? `.lazy(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(this.config.generatedRouteTree),\n path.resolve(\n this.config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n ),\n this.config.addExtensions,\n ),\n )}').then((d) => d.${exportName}))`\n : '',\n ].join(''),\n ].join('\\n\\n')\n })\n\n let fileRoutesByPathInterfacePerPlugin = ''\n let fileRoutesByFullPathPerPlugin = ''\n\n if (!this.config.disableTypes && hasMatchingRouteFiles) {\n fileRoutesByFullPathPerPlugin = [\n `export interface File${exportName}sByFullPath {\n${[...createRouteNodesByFullPath(acc.routeNodes).entries()]\n .filter(([fullPath]) => fullPath)\n .map(([fullPath, routeNode]) => {\n return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode, exportName)}`\n })}\n}`,\n `export interface File${exportName}sByTo {\n${[...createRouteNodesByTo(acc.routeNodes).entries()]\n .filter(([to]) => to)\n .map(([to, routeNode]) => {\n return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode, exportName)}`\n })}\n}`,\n `export interface File${exportName}sById {\n'${rootRouteId}': typeof root${exportName}Import,\n${[...createRouteNodesById(acc.routeNodes).entries()].map(([id, routeNode]) => {\n return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode, exportName)}`\n})}\n}`,\n `export interface File${exportName}Types {\nfile${exportName}sByFullPath: File${exportName}sByFullPath\nfullPaths: ${\n acc.routeNodes.length > 0\n ? [...createRouteNodesByFullPath(acc.routeNodes).keys()]\n .filter((fullPath) => fullPath)\n .map((fullPath) => `'${fullPath}'`)\n .join('|')\n : 'never'\n }\nfile${exportName}sByTo: File${exportName}sByTo\nto: ${\n acc.routeNodes.length > 0\n ? [...createRouteNodesByTo(acc.routeNodes).keys()]\n .filter((to) => to)\n .map((to) => `'${to}'`)\n .join('|')\n : 'never'\n }\nid: ${[`'${rootRouteId}'`, ...[...createRouteNodesById(acc.routeNodes).keys()].map((id) => `'${id}'`)].join('|')}\nfile${exportName}sById: File${exportName}sById\n}`,\n `export interface Root${exportName}Children {\n${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${getResolvedRouteNodeVariableName(child, exportName)}`).join(',')}\n}`,\n ].join('\\n')\n\n fileRoutesByPathInterfacePerPlugin = buildFileRoutesByPathInterface({\n ...plugin.moduleAugmentation({ generator: this }),\n routeNodes:\n this.config.verboseFileRoutes !== false\n ? sortedRouteNodes\n : [\n ...routeFileResult.map(({ node }) => node),\n ...sortedRouteNodes.filter((d) => d.isVirtual),\n ],\n exportName,\n })\n }\n\n let routeTree = ''\n if (hasMatchingRouteFiles) {\n routeTree = [\n `const root${exportName}Children${this.config.disableTypes ? '' : `: Root${exportName}Children`} = {\n ${acc.routeTree\n .map(\n (child) =>\n `${child.variableName}${exportName}: ${getResolvedRouteNodeVariableName(child, exportName)}`,\n )\n .join(',')}\n}`,\n `export const ${lowerCaseFirstChar(exportName)}Tree = root${exportName}Import._addFileChildren(root${exportName}Children)${this.config.disableTypes ? '' : `._addFileTypes<File${exportName}Types>()`}`,\n ].join('\\n')\n }\n\n return {\n routeImports,\n sortedRouteNodes,\n acc,\n virtualRouteNodes,\n routeTreeConfig,\n routeTree,\n imports,\n createUpdateRoutes,\n fileRoutesByFullPathPerPlugin,\n fileRoutesByPathInterfacePerPlugin,\n }\n }\n\n const routeTrees = this.pluginsWithTransform.map((plugin) => ({\n exportName: plugin.transformPlugin.exportName,\n ...buildRouteTreeForExport(plugin),\n }))\n\n this.plugins.map((plugin) => {\n return plugin.onRouteTreesChanged?.({\n routeTrees,\n rootRouteNode,\n generator: this,\n })\n })\n\n let mergedImports = mergeImportDeclarations(\n routeTrees.flatMap((d) => d.imports),\n )\n if (this.config.disableTypes) {\n mergedImports = mergedImports.filter((d) => d.importKind !== 'type')\n }\n\n const importStatements = mergedImports.map(buildImportString)\n\n let moduleAugmentation = ''\n if (this.config.verboseFileRoutes === false && !this.config.disableTypes) {\n moduleAugmentation = routeFileResult\n .map(({ node }) => {\n const getModuleDeclaration = (routeNode?: RouteNode) => {\n if (!isRouteNodeValidForAugmentation(routeNode)) {\n return ''\n }\n const moduleAugmentation = this.pluginsWithTransform\n .map((plugin) => {\n return plugin.routeModuleAugmentation({\n routeNode,\n })\n })\n .filter(Boolean)\n .join('\\n')\n\n return `declare module './${this.getImportPath(routeNode)}' {\n ${moduleAugmentation}\n }`\n }\n return getModuleDeclaration(node)\n })\n .join('\\n')\n }\n\n const routeImports = routeTrees.flatMap((t) => t.routeImports)\n const rootRouteImports = this.pluginsWithTransform.flatMap(\n (p) =>\n getImportForRouteNode(rootRouteNode, p.transformPlugin.exportName) ??\n [],\n )\n if (rootRouteImports.length > 0) {\n routeImports.unshift(...rootRouteImports)\n }\n const routeTreeContent = [\n ...this.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 routeTrees.flatMap((t) => t.virtualRouteNodes).join('\\n'),\n routeTrees.flatMap((t) => t.createUpdateRoutes).join('\\n'),\n\n routeTrees.map((t) => t.fileRoutesByFullPathPerPlugin).join('\\n'),\n routeTrees.map((t) => t.fileRoutesByPathInterfacePerPlugin).join('\\n'),\n moduleAugmentation,\n routeTrees.flatMap((t) => t.routeTreeConfig).join('\\n'),\n routeTrees.map((t) => t.routeTree).join('\\n'),\n ...this.config.routeTreeFileFooter,\n ]\n .filter(Boolean)\n .join('\\n\\n')\n return routeTreeContent\n }\n\n private getImportPath(node: RouteNode) {\n return replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(this.config.generatedRouteTree),\n path.resolve(this.config.routesDirectory, node.filePath),\n ),\n this.config.addExtensions,\n ),\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 node.exports = result.cacheEntry.exports\n return {\n node,\n shouldWriteTree: result.exportsChanged,\n cacheEntry: result.cacheEntry,\n }\n }\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 exports: [],\n routeId: node.routePath ?? '$$TSR_NO_ROUTE_PATH_ASSIGNED$$',\n }\n\n const escapedRoutePath = node.routePath?.replaceAll('$', '$$') ?? ''\n\n let shouldWriteRouteFile = false\n // now we need to either scaffold the file or transform it\n if (!existingRouteFile.fileContent) {\n shouldWriteRouteFile = 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 updatedCacheEntry.exports = ['Route']\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 '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 updatedCacheEntry.exports = ['Route']\n } else {\n return null\n }\n } else {\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 plugins: this.transformPlugins,\n })\n\n if (transformResult.result === 'error') {\n throw new Error(\n `Error transforming route file ${node.fullPath}: ${transformResult.error}`,\n )\n }\n updatedCacheEntry.exports = transformResult.exports\n if (transformResult.result === 'modified') {\n updatedCacheEntry.fileContent = transformResult.output\n shouldWriteRouteFile = true\n }\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 node.exports = updatedCacheEntry.exports\n const shouldWriteTree = !deepEqual(\n result.cacheEntry?.exports,\n updatedCacheEntry.exports,\n )\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 exportsChanged: boolean\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 exportsChanged: false,\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 // compare shadowCache against cache to determine whether exports changed\n // if they didn't, cache is fresh\n if (fileChangedCache.result === true) {\n if (\n deepEqual(\n fileChangedCache.cacheEntry.exports,\n shadowCacheFileChange.cacheEntry.exports,\n )\n ) {\n return {\n status: 'fresh',\n exportsChanged: false,\n cacheEntry: shadowCacheFileChange.cacheEntry,\n }\n }\n return {\n status: 'fresh',\n exportsChanged: true,\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 node.exports = result.cacheEntry.exports\n this.routeNodeShadowCache.set(node.fullPath, result.cacheEntry)\n return result.exportsChanged\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 exports: [],\n routeId: node.routePath ?? '$$TSR_NO_ROOT_ROUTE_PATH_ASSIGNED$$',\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 const rootRouteExports: Array<string> = []\n for (const plugin of this.pluginsWithTransform) {\n const exportName = plugin.transformPlugin.exportName\n // TODO we need to parse instead of just string match\n // otherwise a commented out export will still be detected\n if (rootNodeFile.fileContent.includes(`export const ${exportName}`)) {\n rootRouteExports.push(exportName)\n }\n }\n\n updatedCacheEntry.exports = rootRouteExports\n node.exports = rootRouteExports\n this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry)\n\n const shouldWriteTree = !deepEqual(\n result.cacheEntry?.exports,\n rootRouteExports,\n )\n return shouldWriteTree\n }\n\n private handleNode(node: RouteNode, acc: HandleNodeAccumulator) {\n // Do not remove this as we need to set the lastIndex to 0 as it\n // is necessary to reset the regex's index when using the global flag\n // otherwise it might not match the next time it's used\n resetRegex(this.routeGroupPatternRegex)\n\n let parentRoute = hasParentRoute(acc.routeNodes, node, node.routePath)\n\n // if the parent route is a virtual parent route, we need to find the real parent route\n if (parentRoute?.isVirtualParentRoute && parentRoute.children?.length) {\n // only if this sub-parent route returns a valid parent route, we use it, if not leave it as it\n const possibleParentRoute = hasParentRoute(\n parentRoute.children,\n node,\n node.routePath,\n )\n if (possibleParentRoute) {\n parentRoute = possibleParentRoute\n }\n }\n\n if (parentRoute) node.parent = parentRoute\n\n node.path = determineNodePath(node)\n\n const trimmedPath = trimPathLeft(node.path ?? '')\n\n const split = trimmedPath.split('/')\n const lastRouteSegment = split[split.length - 1] ?? trimmedPath\n\n node.isNonPath =\n lastRouteSegment.startsWith('_') ||\n split.every((part) => this.routeGroupPatternRegex.test(part))\n\n node.cleanedPath = removeGroups(\n removeUnderscores(removeLayoutSegments(node.path)) ?? '',\n )\n\n if (\n !node.isVirtual &&\n (\n [\n 'lazy',\n 'loader',\n 'component',\n 'pendingComponent',\n 'errorComponent',\n ] satisfies Array<FsRouteType>\n ).some((d) => d === node._fsRouteType)\n ) {\n acc.routePiecesByPath[node.routePath!] =\n acc.routePiecesByPath[node.routePath!] || {}\n\n acc.routePiecesByPath[node.routePath!]![\n node._fsRouteType === 'lazy'\n ? 'lazy'\n : node._fsRouteType === 'loader'\n ? 'loader'\n : node._fsRouteType === 'errorComponent'\n ? 'errorComponent'\n : node._fsRouteType === 'pendingComponent'\n ? 'pendingComponent'\n : 'component'\n ] = node\n\n const anchorRoute = acc.routeNodes.find(\n (d) => d.routePath === node.routePath,\n )\n\n if (!anchorRoute) {\n this.handleNode(\n {\n ...node,\n isVirtual: true,\n _fsRouteType: 'static',\n },\n acc,\n )\n }\n return\n }\n\n const cleanedPathIsEmpty = (node.cleanedPath || '').length === 0\n const nonPathRoute =\n node._fsRouteType === 'pathless_layout' && node.isNonPath\n\n node.isVirtualParentRequired =\n node._fsRouteType === 'pathless_layout' || nonPathRoute\n ? !cleanedPathIsEmpty\n : false\n\n if (!node.isVirtual && node.isVirtualParentRequired) {\n const parentRoutePath = removeLastSegmentFromPath(node.routePath) || '/'\n const parentVariableName = routePathToVariable(parentRoutePath)\n\n const anchorRoute = acc.routeNodes.find(\n (d) => d.routePath === parentRoutePath,\n )\n\n if (!anchorRoute) {\n const parentNode: RouteNode = {\n ...node,\n path: removeLastSegmentFromPath(node.path) || '/',\n filePath: removeLastSegmentFromPath(node.filePath) || '/',\n fullPath: removeLastSegmentFromPath(node.fullPath) || '/',\n routePath: parentRoutePath,\n variableName: parentVariableName,\n isVirtual: true,\n _fsRouteType: 'layout', // layout since this route will wrap other routes\n isVirtualParentRoute: true,\n isVirtualParentRequired: false,\n }\n\n parentNode.children = parentNode.children ?? []\n parentNode.children.push(node)\n\n node.parent = parentNode\n\n if (node._fsRouteType === 'pathless_layout') {\n // since `node.path` is used as the `id` on the route definition, we need to update it\n node.path = determineNodePath(node)\n }\n\n this.handleNode(parentNode, acc)\n } else {\n anchorRoute.children = anchorRoute.children ?? []\n anchorRoute.children.push(node)\n\n node.parent = anchorRoute\n }\n }\n\n if (node.parent) {\n if (!node.isVirtualParentRequired) {\n node.parent.children = node.parent.children ?? []\n node.parent.children.push(node)\n }\n } else {\n acc.routeTree.push(node)\n }\n\n acc.routeNodes.push(node)\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","defaultGeneratorPlugin","logging","getTargetTemplate","virtualGetRouteNodes","physicalGetRouteNodes","rootPathId","multiSortBy","format","routeImports","buildRouteTreeConfig","findParent","replaceBackslash","removeExt","createRouteNodesByFullPath","getResolvedRouteNodeVariableName","createRouteNodesByTo","rootRouteId","createRouteNodesById","buildFileRoutesByPathInterface","lowerCaseFirstChar","mergeImportDeclarations","buildImportString","isRouteNodeValidForAugmentation","moduleAugmentation","fillTemplate","transform","deepEqual","checkFileExists","mkdirSync","resetRegex","hasParentRoute","determineNodePath","trimPathLeft","removeGroups","removeUnderscores","removeLayoutSegments","removeLastSegmentFromPath","routePathToVariable","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 { deepEqual, 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 buildFileRoutesByPathInterface,\n buildImportString,\n buildRouteTreeConfig,\n checkFileExists,\n createRouteNodesByFullPath,\n createRouteNodesById,\n createRouteNodesByTo,\n determineNodePath,\n findParent,\n format,\n getResolvedRouteNodeVariableName,\n hasParentRoute,\n isRouteNodeValidForAugmentation,\n lowerCaseFirstChar,\n mergeImportDeclarations,\n multiSortBy,\n removeExt,\n removeGroups,\n removeLastSegmentFromPath,\n removeLayoutSegments,\n removeUnderscores,\n replaceBackslash,\n resetRegex,\n routePathToVariable,\n trimPathLeft,\n} from './utils'\nimport { fillTemplate, getTargetTemplate } from './template'\nimport { transform } from './transform/transform'\nimport { defaultGeneratorPlugin } from './plugin/default-generator-plugin'\nimport type {\n GeneratorPlugin,\n GeneratorPluginWithTransform,\n} 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'\nimport type { TransformPlugin } from './transform/types'\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 exports: Array<string>\n routeId: string\n}\n\ntype GeneratorRouteNodeCache = Map</** filePath **/ string, RouteNodeCacheEntry>\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 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> = [defaultGeneratorPlugin()]\n private pluginsWithTransform: Array<GeneratorPluginWithTransform> = []\n // this is just a cache for the transform plugins since we need them for each route file that is to be processed\n private transformPlugins: Array<TransformPlugin> = []\n private routeGroupPatternRegex = /\\(.+\\)/g\n private physicalDirectories: Array<string> = []\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 this.plugins.forEach((plugin) => {\n if ('transformPlugin' in plugin) {\n if (this.pluginsWithTransform.find((p) => p.name === plugin.name)) {\n throw new Error(\n `Plugin with name \"${plugin.name}\" is already registered for export ${plugin.transformPlugin.exportName}!`,\n )\n }\n this.pluginsWithTransform.push(plugin)\n this.transformPlugins.push(plugin.transformPlugin)\n }\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 const start = performance.now()\n await this.generatorInternal()\n const end = performance.now()\n this.logger.info(\n `Generated route tree in ${Math.round(end - start)}ms`,\n )\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 } else {\n getRouteNodesResult = await physicalGetRouteNodes(this.config, this.root)\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 writeRouteTreeFile = await this.handleRootNode(rootRouteNode)\n\n const preRouteNodes = multiSortBy(beforeRouteNodes, [\n (d) => (d.routePath === '/' ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) =>\n d.filePath.match(new RegExp(`[./]${this.config.indexToken}[.]`))\n ? 1\n : -1,\n (d) =>\n d.filePath.match(\n /[./](component|errorComponent|pendingComponent|loader|lazy)[.]/,\n )\n ? 1\n : -1,\n (d) =>\n d.filePath.match(new RegExp(`[./]${this.config.routeToken}[.]`))\n ? -1\n : 1,\n (d) => (d.routePath?.endsWith('/') ? -1 : 1),\n (d) => d.routePath,\n ]).filter((d) => ![`/${rootPathId}`].includes(d.routePath || ''))\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 return result.value\n }\n return []\n })\n\n routeFileResult.forEach((result) => {\n if (!result.node.exports?.length) {\n this.logger.warn(\n `Route file \"${result.cacheEntry.fileContent}\" does not export any route piece. This is likely a mistake.`,\n )\n }\n })\n if (routeFileResult.find((r) => r.shouldWriteTree)) {\n writeRouteTreeFile = true\n }\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 for (const fullPath of this.routeNodeCache.keys()) {\n if (!this.routeNodeShadowCache.has(fullPath)) {\n writeRouteTreeFile = true\n break\n }\n }\n }\n\n if (!writeRouteTreeFile) {\n this.swapCaches()\n return\n }\n\n let routeTreeContent = this.buildRouteTreeFileContent(\n rootRouteNode,\n preRouteNodes,\n routeFileResult,\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.swapCaches()\n }\n\n private swapCaches() {\n this.routeNodeCache = this.routeNodeShadowCache\n this.routeNodeShadowCache = new Map()\n }\n\n private buildRouteTreeFileContent(\n rootRouteNode: RouteNode,\n preRouteNodes: Array<RouteNode>,\n routeFileResult: Array<{\n cacheEntry: RouteNodeCacheEntry\n node: RouteNode\n }>,\n ) {\n const getImportForRouteNode = (node: RouteNode, exportName: string) => {\n if (node.exports?.includes(exportName)) {\n return {\n source: `./${this.getImportPath(node)}`,\n specifiers: [\n {\n imported: exportName,\n local: `${node.variableName}${exportName}Import`,\n },\n ],\n } satisfies ImportDeclaration\n }\n return undefined\n }\n\n const buildRouteTreeForExport = (plugin: GeneratorPluginWithTransform) => {\n const exportName = plugin.transformPlugin.exportName\n const acc: HandleNodeAccumulator = {\n routeTree: [],\n routeNodes: [],\n routePiecesByPath: {},\n }\n for (const node of preRouteNodes) {\n if (node.exports?.includes(plugin.transformPlugin.exportName)) {\n this.handleNode(node, acc)\n }\n }\n\n const sortedRouteNodes = multiSortBy(acc.routeNodes, [\n (d) => (d.routePath?.includes(`/${rootPathId}`) ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => (d.routePath?.endsWith(this.config.indexToken) ? -1 : 1),\n (d) => d,\n ])\n\n const pluginConfig = plugin.config({\n generator: this,\n rootRouteNode,\n sortedRouteNodes,\n })\n\n const routeImports = sortedRouteNodes\n .filter((d) => !d.isVirtual)\n .flatMap((node) => getImportForRouteNode(node, exportName) ?? [])\n\n const hasMatchingRouteFiles =\n acc.routeNodes.length > 0 || rootRouteNode.exports?.includes(exportName)\n\n const virtualRouteNodes = sortedRouteNodes\n .filter((d) => d.isVirtual)\n .map((node) => {\n return `const ${\n node.variableName\n }${exportName}Import = ${plugin.createVirtualRouteCode({ node })}`\n })\n if (\n !rootRouteNode.exports?.includes(exportName) &&\n pluginConfig.virtualRootRoute\n ) {\n virtualRouteNodes.unshift(\n `const ${rootRouteNode.variableName}${exportName}Import = ${plugin.createRootRouteCode()}`,\n )\n }\n\n const imports = plugin.imports({\n sortedRouteNodes,\n acc,\n generator: this,\n rootRouteNode,\n })\n\n const routeTreeConfig = buildRouteTreeConfig(\n acc.routeTree,\n exportName,\n this.config.disableTypes,\n )\n\n const createUpdateRoutes = sortedRouteNodes.map((node) => {\n const loaderNode = acc.routePiecesByPath[node.routePath!]?.loader\n const componentNode = acc.routePiecesByPath[node.routePath!]?.component\n const errorComponentNode =\n acc.routePiecesByPath[node.routePath!]?.errorComponent\n const pendingComponentNode =\n acc.routePiecesByPath[node.routePath!]?.pendingComponent\n const lazyComponentNode = acc.routePiecesByPath[node.routePath!]?.lazy\n\n return [\n [\n `const ${node.variableName}${exportName} = ${node.variableName}${exportName}Import.update({\n ${[\n `id: '${node.path}'`,\n !node.isNonPath ? `path: '${node.cleanedPath}'` : undefined,\n `getParentRoute: () => ${findParent(node, exportName)}`,\n ]\n .filter(Boolean)\n .join(',')}\n }${this.config.disableTypes ? '' : 'as any'})`,\n loaderNode\n ? `.updateLoader({ loader: lazyFn(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(this.config.generatedRouteTree),\n path.resolve(\n this.config.routesDirectory,\n loaderNode.filePath,\n ),\n ),\n this.config.addExtensions,\n ),\n )}'), 'loader') })`\n : '',\n componentNode || errorComponentNode || pendingComponentNode\n ? `.update({\n ${(\n [\n ['component', componentNode],\n ['errorComponent', errorComponentNode],\n ['pendingComponent', pendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n return `${\n d[0]\n }: lazyRouteComponent(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(this.config.generatedRouteTree),\n path.resolve(\n this.config.routesDirectory,\n d[1]!.filePath,\n ),\n ),\n this.config.addExtensions,\n ),\n )}'), '${d[0]}')`\n })\n .join('\\n,')}\n })`\n : '',\n lazyComponentNode\n ? `.lazy(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(this.config.generatedRouteTree),\n path.resolve(\n this.config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n ),\n this.config.addExtensions,\n ),\n )}').then((d) => d.${exportName}))`\n : '',\n ].join(''),\n ].join('\\n\\n')\n })\n\n let fileRoutesByPathInterfacePerPlugin = ''\n let fileRoutesByFullPathPerPlugin = ''\n\n if (!this.config.disableTypes && hasMatchingRouteFiles) {\n fileRoutesByFullPathPerPlugin = [\n `export interface File${exportName}sByFullPath {\n${[...createRouteNodesByFullPath(acc.routeNodes).entries()]\n .filter(([fullPath]) => fullPath)\n .map(([fullPath, routeNode]) => {\n return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode, exportName)}`\n })}\n}`,\n `export interface File${exportName}sByTo {\n${[...createRouteNodesByTo(acc.routeNodes).entries()]\n .filter(([to]) => to)\n .map(([to, routeNode]) => {\n return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode, exportName)}`\n })}\n}`,\n `export interface File${exportName}sById {\n'${rootRouteId}': typeof root${exportName}Import,\n${[...createRouteNodesById(acc.routeNodes).entries()].map(([id, routeNode]) => {\n return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode, exportName)}`\n})}\n}`,\n `export interface File${exportName}Types {\nfile${exportName}sByFullPath: File${exportName}sByFullPath\nfullPaths: ${\n acc.routeNodes.length > 0\n ? [...createRouteNodesByFullPath(acc.routeNodes).keys()]\n .filter((fullPath) => fullPath)\n .map((fullPath) => `'${fullPath}'`)\n .join('|')\n : 'never'\n }\nfile${exportName}sByTo: File${exportName}sByTo\nto: ${\n acc.routeNodes.length > 0\n ? [...createRouteNodesByTo(acc.routeNodes).keys()]\n .filter((to) => to)\n .map((to) => `'${to}'`)\n .join('|')\n : 'never'\n }\nid: ${[`'${rootRouteId}'`, ...[...createRouteNodesById(acc.routeNodes).keys()].map((id) => `'${id}'`)].join('|')}\nfile${exportName}sById: File${exportName}sById\n}`,\n `export interface Root${exportName}Children {\n${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${getResolvedRouteNodeVariableName(child, exportName)}`).join(',')}\n}`,\n ].join('\\n')\n\n fileRoutesByPathInterfacePerPlugin = buildFileRoutesByPathInterface({\n ...plugin.moduleAugmentation({ generator: this }),\n routeNodes:\n this.config.verboseFileRoutes !== false\n ? sortedRouteNodes\n : [\n ...routeFileResult.map(({ node }) => node),\n ...sortedRouteNodes.filter((d) => d.isVirtual),\n ],\n exportName,\n })\n }\n\n let routeTree = ''\n if (hasMatchingRouteFiles) {\n routeTree = [\n `const root${exportName}Children${this.config.disableTypes ? '' : `: Root${exportName}Children`} = {\n ${acc.routeTree\n .map(\n (child) =>\n `${child.variableName}${exportName}: ${getResolvedRouteNodeVariableName(child, exportName)}`,\n )\n .join(',')}\n}`,\n `export const ${lowerCaseFirstChar(exportName)}Tree = root${exportName}Import._addFileChildren(root${exportName}Children)${this.config.disableTypes ? '' : `._addFileTypes<File${exportName}Types>()`}`,\n ].join('\\n')\n }\n\n return {\n routeImports,\n sortedRouteNodes,\n acc,\n virtualRouteNodes,\n routeTreeConfig,\n routeTree,\n imports,\n createUpdateRoutes,\n fileRoutesByFullPathPerPlugin,\n fileRoutesByPathInterfacePerPlugin,\n }\n }\n\n const routeTrees = this.pluginsWithTransform.map((plugin) => ({\n exportName: plugin.transformPlugin.exportName,\n ...buildRouteTreeForExport(plugin),\n }))\n\n this.plugins.map((plugin) => {\n return plugin.onRouteTreesChanged?.({\n routeTrees,\n rootRouteNode,\n generator: this,\n })\n })\n\n let mergedImports = mergeImportDeclarations(\n routeTrees.flatMap((d) => d.imports),\n )\n if (this.config.disableTypes) {\n mergedImports = mergedImports.filter((d) => d.importKind !== 'type')\n }\n\n const importStatements = mergedImports.map(buildImportString)\n\n let moduleAugmentation = ''\n if (this.config.verboseFileRoutes === false && !this.config.disableTypes) {\n moduleAugmentation = routeFileResult\n .map(({ node }) => {\n const getModuleDeclaration = (routeNode?: RouteNode) => {\n if (!isRouteNodeValidForAugmentation(routeNode)) {\n return ''\n }\n const moduleAugmentation = this.pluginsWithTransform\n .map((plugin) => {\n return plugin.routeModuleAugmentation({\n routeNode,\n })\n })\n .filter(Boolean)\n .join('\\n')\n\n return `declare module './${this.getImportPath(routeNode)}' {\n ${moduleAugmentation}\n }`\n }\n return getModuleDeclaration(node)\n })\n .join('\\n')\n }\n\n const routeImports = routeTrees.flatMap((t) => t.routeImports)\n const rootRouteImports = this.pluginsWithTransform.flatMap(\n (p) =>\n getImportForRouteNode(rootRouteNode, p.transformPlugin.exportName) ??\n [],\n )\n if (rootRouteImports.length > 0) {\n routeImports.unshift(...rootRouteImports)\n }\n const routeTreeContent = [\n ...this.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 routeTrees.flatMap((t) => t.virtualRouteNodes).join('\\n'),\n routeTrees.flatMap((t) => t.createUpdateRoutes).join('\\n'),\n\n routeTrees.map((t) => t.fileRoutesByFullPathPerPlugin).join('\\n'),\n routeTrees.map((t) => t.fileRoutesByPathInterfacePerPlugin).join('\\n'),\n moduleAugmentation,\n routeTrees.flatMap((t) => t.routeTreeConfig).join('\\n'),\n routeTrees.map((t) => t.routeTree).join('\\n'),\n ...this.config.routeTreeFileFooter,\n ]\n .filter(Boolean)\n .join('\\n\\n')\n return routeTreeContent\n }\n\n private getImportPath(node: RouteNode) {\n return replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(this.config.generatedRouteTree),\n path.resolve(this.config.routesDirectory, node.filePath),\n ),\n this.config.addExtensions,\n ),\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 node.exports = result.cacheEntry.exports\n return {\n node,\n shouldWriteTree: result.exportsChanged,\n cacheEntry: result.cacheEntry,\n }\n }\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 exports: [],\n routeId: node.routePath ?? '$$TSR_NO_ROUTE_PATH_ASSIGNED$$',\n }\n\n const escapedRoutePath = node.routePath?.replaceAll('$', '$$') ?? ''\n\n let shouldWriteRouteFile = false\n // now we need to either scaffold the file or transform it\n if (!existingRouteFile.fileContent) {\n shouldWriteRouteFile = 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 updatedCacheEntry.exports = ['Route']\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 '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 updatedCacheEntry.exports = ['Route']\n } else {\n return null\n }\n } else {\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 plugins: this.transformPlugins,\n })\n\n if (transformResult.result === 'error') {\n throw new Error(\n `Error transforming route file ${node.fullPath}: ${transformResult.error}`,\n )\n }\n updatedCacheEntry.exports = transformResult.exports\n if (transformResult.result === 'modified') {\n updatedCacheEntry.fileContent = transformResult.output\n shouldWriteRouteFile = true\n }\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 node.exports = updatedCacheEntry.exports\n const shouldWriteTree = !deepEqual(\n result.cacheEntry?.exports,\n updatedCacheEntry.exports,\n )\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 exportsChanged: boolean\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 exportsChanged: false,\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 // compare shadowCache against cache to determine whether exports changed\n // if they didn't, cache is fresh\n if (fileChangedCache.result === true) {\n if (\n deepEqual(\n fileChangedCache.cacheEntry.exports,\n shadowCacheFileChange.cacheEntry.exports,\n )\n ) {\n return {\n status: 'fresh',\n exportsChanged: false,\n cacheEntry: shadowCacheFileChange.cacheEntry,\n }\n }\n return {\n status: 'fresh',\n exportsChanged: true,\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 node.exports = result.cacheEntry.exports\n this.routeNodeShadowCache.set(node.fullPath, result.cacheEntry)\n return result.exportsChanged\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 exports: [],\n routeId: node.routePath ?? '$$TSR_NO_ROOT_ROUTE_PATH_ASSIGNED$$',\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 const rootRouteExports: Array<string> = []\n for (const plugin of this.pluginsWithTransform) {\n const exportName = plugin.transformPlugin.exportName\n // TODO we need to parse instead of just string match\n // otherwise a commented out export will still be detected\n if (rootNodeFile.fileContent.includes(`export const ${exportName}`)) {\n rootRouteExports.push(exportName)\n }\n }\n\n updatedCacheEntry.exports = rootRouteExports\n node.exports = rootRouteExports\n this.routeNodeShadowCache.set(node.fullPath, updatedCacheEntry)\n\n const shouldWriteTree = !deepEqual(\n result.cacheEntry?.exports,\n rootRouteExports,\n )\n return shouldWriteTree\n }\n\n private handleNode(node: RouteNode, acc: HandleNodeAccumulator) {\n // Do not remove this as we need to set the lastIndex to 0 as it\n // is necessary to reset the regex's index when using the global flag\n // otherwise it might not match the next time it's used\n resetRegex(this.routeGroupPatternRegex)\n\n let parentRoute = hasParentRoute(acc.routeNodes, node, node.routePath)\n\n // if the parent route is a virtual parent route, we need to find the real parent route\n if (parentRoute?.isVirtualParentRoute && parentRoute.children?.length) {\n // only if this sub-parent route returns a valid parent route, we use it, if not leave it as it\n const possibleParentRoute = hasParentRoute(\n parentRoute.children,\n node,\n node.routePath,\n )\n if (possibleParentRoute) {\n parentRoute = possibleParentRoute\n }\n }\n\n if (parentRoute) node.parent = parentRoute\n\n node.path = determineNodePath(node)\n\n const trimmedPath = trimPathLeft(node.path ?? '')\n\n const split = trimmedPath.split('/')\n const lastRouteSegment = split[split.length - 1] ?? trimmedPath\n\n node.isNonPath =\n lastRouteSegment.startsWith('_') ||\n split.every((part) => this.routeGroupPatternRegex.test(part))\n\n node.cleanedPath = removeGroups(\n removeUnderscores(removeLayoutSegments(node.path)) ?? '',\n )\n\n if (\n !node.isVirtual &&\n (\n [\n 'lazy',\n 'loader',\n 'component',\n 'pendingComponent',\n 'errorComponent',\n ] satisfies Array<FsRouteType>\n ).some((d) => d === node._fsRouteType)\n ) {\n acc.routePiecesByPath[node.routePath!] =\n acc.routePiecesByPath[node.routePath!] || {}\n\n acc.routePiecesByPath[node.routePath!]![\n node._fsRouteType === 'lazy'\n ? 'lazy'\n : node._fsRouteType === 'loader'\n ? 'loader'\n : node._fsRouteType === 'errorComponent'\n ? 'errorComponent'\n : node._fsRouteType === 'pendingComponent'\n ? 'pendingComponent'\n : 'component'\n ] = node\n\n const anchorRoute = acc.routeNodes.find(\n (d) => d.routePath === node.routePath,\n )\n\n if (!anchorRoute) {\n this.handleNode(\n {\n ...node,\n isVirtual: true,\n _fsRouteType: 'static',\n },\n acc,\n )\n }\n return\n }\n\n const cleanedPathIsEmpty = (node.cleanedPath || '').length === 0\n const nonPathRoute =\n node._fsRouteType === 'pathless_layout' && node.isNonPath\n\n node.isVirtualParentRequired =\n node._fsRouteType === 'pathless_layout' || nonPathRoute\n ? !cleanedPathIsEmpty\n : false\n\n if (!node.isVirtual && node.isVirtualParentRequired) {\n const parentRoutePath = removeLastSegmentFromPath(node.routePath) || '/'\n const parentVariableName = routePathToVariable(parentRoutePath)\n\n const anchorRoute = acc.routeNodes.find(\n (d) => d.routePath === parentRoutePath,\n )\n\n if (!anchorRoute) {\n const parentNode: RouteNode = {\n ...node,\n path: removeLastSegmentFromPath(node.path) || '/',\n filePath: removeLastSegmentFromPath(node.filePath) || '/',\n fullPath: removeLastSegmentFromPath(node.fullPath) || '/',\n routePath: parentRoutePath,\n variableName: parentVariableName,\n isVirtual: true,\n _fsRouteType: 'layout', // layout since this route will wrap other routes\n isVirtualParentRoute: true,\n isVirtualParentRequired: false,\n }\n\n parentNode.children = parentNode.children ?? []\n parentNode.children.push(node)\n\n node.parent = parentNode\n\n if (node._fsRouteType === 'pathless_layout') {\n // since `node.path` is used as the `id` on the route definition, we need to update it\n node.path = determineNodePath(node)\n }\n\n this.handleNode(parentNode, acc)\n } else {\n anchorRoute.children = anchorRoute.children ?? []\n anchorRoute.children.push(node)\n\n node.parent = anchorRoute\n }\n }\n\n if (node.parent) {\n if (!node.isVirtualParentRequired) {\n node.parent.children = node.parent.children ?? []\n node.parent.children.push(node)\n }\n } else {\n acc.routeTree.push(node)\n }\n\n acc.routeNodes.push(node)\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","defaultGeneratorPlugin","logging","getTargetTemplate","existsSync","mkdirSync","virtualGetRouteNodes","physicalGetRouteNodes","rootPathId","multiSortBy","format","routeImports","buildRouteTreeConfig","findParent","replaceBackslash","removeExt","createRouteNodesByFullPath","getResolvedRouteNodeVariableName","createRouteNodesByTo","rootRouteId","createRouteNodesById","buildFileRoutesByPathInterface","lowerCaseFirstChar","mergeImportDeclarations","buildImportString","isRouteNodeValidForAugmentation","moduleAugmentation","fillTemplate","transform","deepEqual","checkFileExists","resetRegex","hasParentRoute","determineNodePath","trimPathLeft","removeGroups","removeUnderscores","removeLayoutSegments","removeLastSegmentFromPath","routePathToVariable","isVirtualConfigFile"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0EA,MAAM,oBAAwB;AAAA,EAC5B,MAAM,OAAO,aAAa;AACxB,UAAM,MAAM,MAAMA,eAAI,KAAK,UAAU,EAAE,QAAQ,MAAM;AACrD,WAAO;AAAA,MACL,SAAS,IAAI;AAAA,MACb,MAAM,OAAO,IAAI,IAAI;AAAA,MACrB,KAAK,OAAO,IAAI,GAAG;AAAA,MACnB,KAAK,OAAO,IAAI,GAAG;AAAA,IAAA;AAAA,EAEvB;AAAA,EACA,QAAQ,CAAC,SAAS,YAAYA,eAAI,OAAO,SAAS,OAAO;AAAA,EACzD,WAAW,CAAC,UAAU,YAAYA,eAAI,UAAU,UAAU,OAAO;AAAA,EACjE,UAAU,OAAO,aAAqB;AACpC,QAAI;AACF,YAAM,aAAa,MAAMA,eAAI,KAAK,UAAU,GAAG;AAC/C,YAAM,OAAO,MAAM,WAAW,KAAK,EAAE,QAAQ,MAAM;AACnD,YAAM,eAAe,MAAM,WAAW,SAAA,GAAY,SAAA;AAClD,YAAM,WAAW,MAAA;AACjB,aAAO,EAAE,MAAM,YAAA;AAAA,IACjB,SAAS,GAAQ;AACf,UAAI,UAAU,GAAG;AACf,YAAI,EAAE,SAAS,UAAU;AACvB,iBAAO;AAAA,QACT;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EACA,OAAO,CAAC,UAAU,SAASA,eAAI,MAAM,UAAU,IAAI;AAAA,EACnD,OAAO,CAAC,UAAU,KAAK,QAAQA,eAAI,MAAM,UAAU,KAAK,GAAG;AAC7D;AAOA,SAAS,MAAM,MAAuD;AACpE,QAAM,EAAE,OAAO,GAAG,KAAA,IAAS;AAC3B,SAAO,EAAE,OAAO,MAAM,OAAO,SAAS,EAAE,MAAM,WAAW,GAAG,KAAA;AAC9D;AAEA,SAAS,QAAQ,QAAkC;AACjD,SACE,OAAO,WAAW,YAClB,WAAW,QACX,WAAW,UACX,OAAO,UAAU;AAErB;AAkCO,MAAM,UAAU;AAAA,EAkCrB,YAAY,MAAiD;AAvB7D,SAAQ,qCAA8C,IAAA;AACtD,SAAQ,2CAAoD,IAAA;AAc5D,SAAQ,iBAAwC,CAAA;AAChD,SAAQ,UAAkC,CAACC,uBAAAA,wBAAwB;AACnE,SAAQ,uBAA4D,CAAA;AAEpE,SAAQ,mBAA2C,CAAA;AACnD,SAAQ,yBAAyB;AACjC,SAAQ,sBAAqC,CAAA;AAG3C,SAAK,SAAS,KAAK;AACnB,SAAK,SAASC,eAAQ,EAAE,UAAU,KAAK,OAAO,gBAAgB;AAC9D,SAAK,OAAO,KAAK;AACjB,SAAK,KAAK,KAAK,MAAM;AACrB,SAAK,yBAAyB,KAAK,0BAAA;AACnC,SAAK,iBAAiBC,2BAAkB,KAAK,MAAM;AAEnD,SAAK,sBAAsB,KAAK,uBAAA;AAChC,SAAK,QAAQ,KAAK,GAAI,KAAK,OAAO,WAAW,EAAG;AAChD,SAAK,QAAQ,QAAQ,CAAC,WAAW;AAC/B,UAAI,qBAAqB,QAAQ;AAC/B,YAAI,KAAK,qBAAqB,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,IAAI,GAAG;AACjE,gBAAM,IAAI;AAAA,YACR,qBAAqB,OAAO,IAAI,sCAAsC,OAAO,gBAAgB,UAAU;AAAA,UAAA;AAAA,QAE3G;AACA,aAAK,qBAAqB,KAAK,MAAM;AACrC,aAAK,iBAAiB,KAAK,OAAO,eAAe;AAAA,MACnD;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,4BAA4B;AAClC,UAAM,yBAAyB,KAAK;AAAA,MAClC,KAAK,OAAO;AAAA,IAAA,IAEV,KAAK,OAAO,qBACZ,KAAK,QAAQ,KAAK,MAAM,KAAK,OAAO,kBAAkB;AAE1D,UAAM,wBAAwB,KAAK,QAAQ,sBAAsB;AAEjE,QAAI,CAACC,QAAAA,WAAW,qBAAqB,GAAG;AACtCC,cAAAA,UAAU,uBAAuB,EAAE,WAAW,KAAA,CAAM;AAAA,IACtD;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,yBAAyB;AAC/B,WAAO,KAAK,WAAW,KAAK,OAAO,eAAe,IAC9C,KAAK,OAAO,kBACZ,KAAK,QAAQ,KAAK,MAAM,KAAK,OAAO,eAAe;AAAA,EACzD;AAAA,EAEO,qBAA+C;AACpD,WAAO,IAAI;AAAA,MACT,CAAC,GAAG,KAAK,eAAe,QAAA,CAAS,EAAE,IAAI,CAAC,CAAC,UAAU,UAAU,MAAM;AAAA,QACjE;AAAA,QACA,EAAE,WAAW,WAAW,QAAA;AAAA,MAAQ,CACjC;AAAA,IAAA;AAAA,EAEL;AAAA,EAEA,MAAa,IAAI,OAAuC;AACtD,QACE,SACA,MAAM,SAAS,WACf,CAAC,KAAK,qCAAqC,MAAM,IAAI,GACrD;AACA;AAAA,IACF;AACA,SAAK,eAAe,KAAK,SAAS,EAAE,MAAM,SAAS;AAEnD,QAAI,KAAK,YAAY;AACnB,aAAO,KAAK;AAAA,IACd;AAEA,SAAK,cAAc,YAAY;AAC7B,SAAG;AAGD,cAAM,YAAY,KAAK;AACvB,aAAK,iBAAiB,CAAA;AAGtB,cAAM,mBACJ,MAAM,QAAQ;AAAA,UACZ,UAAU,IAAI,OAAO,MAAM;AACzB,gBAAI,EAAE,SAAS,UAAU;AACvB,kBAAI;AACJ,kBAAI,EAAE,SAAS,KAAK,wBAAwB;AAC1C,6BAAa,KAAK;AAAA,cACpB,OAAO;AAGL,6BAAa,KAAK,eAAe,IAAI,EAAE,IAAI;AAAA,cAC7C;AACA,oBAAM,SAAS,MAAM,KAAK;AAAA,gBACxB,EAAE,MAAM,EAAE,KAAA;AAAA,gBACV;AAAA,cAAA;AAEF,kBAAI,OAAO,WAAW,OAAO;AAC3B,uBAAO;AAAA,cACT;AAAA,YACF;AACA,mBAAO;AAAA,UACT,CAAC;AAAA,QAAA,GAEH,OAAO,CAAC,MAAM,MAAM,IAAI;AAE1B,YAAI,gBAAgB,WAAW,GAAG;AAChC;AAAA,QACF;AAEA,YAAI;AACF,gBAAM,QAAQ,YAAY,IAAA;AAC1B,gBAAM,KAAK,kBAAA;AACX,gBAAM,MAAM,YAAY,IAAA;AACxB,eAAK,OAAO;AAAA,YACV,2BAA2B,KAAK,MAAM,MAAM,KAAK,CAAC;AAAA,UAAA;AAAA,QAEtD,SAAS,KAAK;AACZ,gBAAM,WAAW,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,IAAI;AAE/C,gBAAM,oBAAoB,SAAS,OAAO,CAAC,MAAM,QAAQ,CAAC,CAAC;AAC3D,cAAI,kBAAkB,WAAW,SAAS,QAAQ;AAChD,iBAAK,eAAe,KAAK,GAAG,kBAAkB,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACjE,8BAAkB,QAAQ,CAAC,MAAM;AAC/B,kBAAI,EAAE,KAAK;AACT,qBAAK,OAAO,KAAK,EAAE,GAAG;AAAA,cACxB;AAAA,YACF,CAAC;AAAA,UACH,OAAO;AACL,kBAAM,sBAAsB,SAAS,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC9D,iBAAK,aAAa;AAClB,kBAAM,IAAI;AAAA,cACR,oBAAoB,IAAI,CAAC,MAAO,EAAY,OAAO,EAAE,KAAA;AAAA,YAAK;AAAA,UAE9D;AAAA,QACF;AAAA,MACF,SAAS,KAAK,eAAe;AAC7B,WAAK,aAAa;AAAA,IACpB,GAAA;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,oBAAoB;AAChC,QAAI,qBAAwC;AAE5C,QAAI;AAEJ,QAAI,KAAK,OAAO,oBAAoB;AAClC,4BAAsB,MAAMC,cAAAA,cAAqB,KAAK,QAAQ,KAAK,IAAI;AAAA,IACzE,OAAO;AACL,4BAAsB,MAAMC,gBAAAA,cAAsB,KAAK,QAAQ,KAAK,IAAI;AAAA,IAC1E;AAEA,UAAM;AAAA,MACJ;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,IAAA,IACE;AACJ,QAAI,kBAAkB,QAAW;AAC/B,UAAI,eAAe;AACnB,UAAI,CAAC,KAAK,OAAO,oBAAoB;AACnC,wBAAgB;AAAA,4BAA+BC,WAAAA,UAAU,IAAI,KAAK,OAAO,eAAe,OAAO,KAAK;AAAA,oBAAuD,KAAK,OAAO,eAAe,IAAIA,WAAAA,UAAU,IAAI,KAAK,OAAO,eAAe,OAAO,KAAK;AAAA,MACjP;AACA,YAAM,IAAI,MAAM,YAAY;AAAA,IAC9B;AACA,SAAK,sBAAsB;AAE3B,yBAAqB,MAAM,KAAK,eAAe,aAAa;AAE5D,UAAM,gBAAgBC,MAAAA,YAAY,kBAAkB;AAAA,MAClD,CAAC,MAAO,EAAE,cAAc,MAAM,KAAK;AAAA,MACnC,CAAC,MAAM,EAAE,WAAW,MAAM,GAAG,EAAE;AAAA,MAC/B,CAAC,MACC,EAAE,SAAS,MAAM,IAAI,OAAO,OAAO,KAAK,OAAO,UAAU,KAAK,CAAC,IAC3D,IACA;AAAA,MACN,CAAC,MACC,EAAE,SAAS;AAAA,QACT;AAAA,MAAA,IAEE,IACA;AAAA,MACN,CAAC,MACC,EAAE,SAAS,MAAM,IAAI,OAAO,OAAO,KAAK,OAAO,UAAU,KAAK,CAAC,IAC3D,KACA;AAAA,MACN,CAAC,MAAO,EAAE,WAAW,SAAS,GAAG,IAAI,KAAK;AAAA,MAC1C,CAAC,MAAM,EAAE;AAAA,IAAA,CACV,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAID,qBAAU,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;AAEhE,UAAM,qBAAqB,MAAM,QAAQ;AAAA,MACvC,cAEG,OAAO,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAC,EAAE,SAAS,EACrD,IAAI,CAAC,MAAM,KAAK,qBAAqB,CAAC,CAAC;AAAA,IAAA;AAG5C,UAAM,aAAa,mBAAmB;AAAA,MACpC,CAAC,WAAW,OAAO,WAAW;AAAA,IAAA;AAEhC,QAAI,WAAW,SAAS,GAAG;AACzB,YAAM,WAAW,IAAI,CAAC,MAAM,EAAE,MAAM;AAAA,IACtC;AAEA,UAAM,kBAAkB,mBAAmB,QAAQ,CAAC,WAAW;AAC7D,UAAI,OAAO,WAAW,eAAe,OAAO,UAAU,MAAM;AAC1D,eAAO,OAAO;AAAA,MAChB;AACA,aAAO,CAAA;AAAA,IACT,CAAC;AAED,oBAAgB,QAAQ,CAAC,WAAW;AAClC,UAAI,CAAC,OAAO,KAAK,SAAS,QAAQ;AAChC,aAAK,OAAO;AAAA,UACV,eAAe,OAAO,WAAW,WAAW;AAAA,QAAA;AAAA,MAEhD;AAAA,IACF,CAAC;AACD,QAAI,gBAAgB,KAAK,CAAC,MAAM,EAAE,eAAe,GAAG;AAClD,2BAAqB;AAAA,IACvB;AAGA,QAAI,CAAC,KAAK,oBAAoB;AAC5B,YAAM,gBAAgB,MAAM,KAAK,GAAG,SAAS,KAAK,sBAAsB;AACxE,UAAI,kBAAkB,qBAAqB;AACzC,aAAK,qBAAqB;AAAA,UACxB,aAAa,cAAc;AAAA,UAC3B,SAAS,cAAc,KAAK;AAAA,QAAA;AAAA,MAEhC;AACA,2BAAqB;AAAA,IACvB,OAAO;AACL,YAAM,sBAAsB,MAAM,KAAK;AAAA,QACrC,EAAE,MAAM,KAAK,uBAAA;AAAA,QACb,KAAK;AAAA,MAAA;AAEP,UAAI,oBAAoB,WAAW,OAAO;AACxC,6BAAqB;AACrB,YAAI,oBAAoB,WAAW,MAAM;AACvC,gBAAM,gBAAgB,MAAM,KAAK,GAAG;AAAA,YAClC,KAAK;AAAA,UAAA;AAEP,cAAI,kBAAkB,qBAAqB;AACzC,iBAAK,qBAAqB;AAAA,cACxB,aAAa,cAAc;AAAA,cAC3B,SAAS,cAAc,KAAK;AAAA,YAAA;AAAA,UAEhC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,oBAAoB;AAGvB,iBAAW,YAAY,KAAK,eAAe,KAAA,GAAQ;AACjD,YAAI,CAAC,KAAK,qBAAqB,IAAI,QAAQ,GAAG;AAC5C,+BAAqB;AACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,oBAAoB;AACvB,WAAK,WAAA;AACL;AAAA,IACF;AAEA,QAAI,mBAAmB,KAAK;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAEF,uBAAmB,KAAK,OAAO,4BAC3B,MAAME,MAAAA,OAAO,kBAAkB,KAAK,MAAM,IAC1C;AAEJ,QAAI;AACJ,QAAI,KAAK,oBAAoB;AAC3B,UACE,uBAAuB,WACvB,KAAK,mBAAmB,gBAAgB,iBACxC;AAAA,WAGK;AACL,cAAM,uBAAuB,MAAM,KAAK,cAAc;AAAA,UACpD,UAAU,KAAK;AAAA,UACf,YAAY;AAAA,UACZ,UAAU;AAAA,YACR,MAAM;AAAA,YACN,iBAAiB,KAAK,mBAAmB;AAAA,UAAA;AAAA,QAC3C,CACD;AACD,qBAAa,qBAAqB;AAAA,MACpC;AAAA,IACF,OAAO;AACL,YAAM,uBAAuB,MAAM,KAAK,cAAc;AAAA,QACpD,UAAU,KAAK;AAAA,QACf,YAAY;AAAA,QACZ,UAAU;AAAA,UACR,MAAM;AAAA,QAAA;AAAA,MACR,CACD;AACD,mBAAa,qBAAqB;AAAA,IACpC;AAEA,QAAI,eAAe,QAAW;AAC5B,WAAK,qBAAqB;AAAA,QACxB,aAAa;AAAA,QACb,SAAS;AAAA,MAAA;AAAA,IAEb;AAEA,SAAK,WAAA;AAAA,EACP;AAAA,EAEQ,aAAa;AACnB,SAAK,iBAAiB,KAAK;AAC3B,SAAK,2CAA2B,IAAA;AAAA,EAClC;AAAA,EAEQ,0BACN,eACA,eACA,iBAIA;AACA,UAAM,wBAAwB,CAAC,MAAiB,eAAuB;AACrE,UAAI,KAAK,SAAS,SAAS,UAAU,GAAG;AACtC,eAAO;AAAA,UACL,QAAQ,KAAK,KAAK,cAAc,IAAI,CAAC;AAAA,UACrC,YAAY;AAAA,YACV;AAAA,cACE,UAAU;AAAA,cACV,OAAO,GAAG,KAAK,YAAY,GAAG,UAAU;AAAA,YAAA;AAAA,UAC1C;AAAA,QACF;AAAA,MAEJ;AACA,aAAO;AAAA,IACT;AAEA,UAAM,0BAA0B,CAAC,WAAyC;AACxE,YAAM,aAAa,OAAO,gBAAgB;AAC1C,YAAM,MAA6B;AAAA,QACjC,WAAW,CAAA;AAAA,QACX,YAAY,CAAA;AAAA,QACZ,mBAAmB,CAAA;AAAA,MAAC;AAEtB,iBAAW,QAAQ,eAAe;AAChC,YAAI,KAAK,SAAS,SAAS,OAAO,gBAAgB,UAAU,GAAG;AAC7D,eAAK,WAAW,MAAM,GAAG;AAAA,QAC3B;AAAA,MACF;AAEA,YAAM,mBAAmBD,MAAAA,YAAY,IAAI,YAAY;AAAA,QACnD,CAAC,MAAO,EAAE,WAAW,SAAS,IAAID,qBAAU,EAAE,IAAI,KAAK;AAAA,QACvD,CAAC,MAAM,EAAE,WAAW,MAAM,GAAG,EAAE;AAAA,QAC/B,CAAC,MAAO,EAAE,WAAW,SAAS,KAAK,OAAO,UAAU,IAAI,KAAK;AAAA,QAC7D,CAAC,MAAM;AAAA,MAAA,CACR;AAED,YAAM,eAAe,OAAO,OAAO;AAAA,QACjC,WAAW;AAAA,QACX;AAAA,QACA;AAAA,MAAA,CACD;AAED,YAAMG,gBAAe,iBAClB,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS,EAC1B,QAAQ,CAAC,SAAS,sBAAsB,MAAM,UAAU,KAAK,EAAE;AAElE,YAAM,wBACJ,IAAI,WAAW,SAAS,KAAK,cAAc,SAAS,SAAS,UAAU;AAEzE,YAAM,oBAAoB,iBACvB,OAAO,CAAC,MAAM,EAAE,SAAS,EACzB,IAAI,CAAC,SAAS;AACb,eAAO,SACL,KAAK,YACP,GAAG,UAAU,YAAY,OAAO,uBAAuB,EAAE,KAAA,CAAM,CAAC;AAAA,MAClE,CAAC;AACH,UACE,CAAC,cAAc,SAAS,SAAS,UAAU,KAC3C,aAAa,kBACb;AACA,0BAAkB;AAAA,UAChB,SAAS,cAAc,YAAY,GAAG,UAAU,YAAY,OAAO,qBAAqB;AAAA,QAAA;AAAA,MAE5F;AAEA,YAAM,UAAU,OAAO,QAAQ;AAAA,QAC7B;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QACX;AAAA,MAAA,CACD;AAED,YAAM,kBAAkBC,MAAAA;AAAAA,QACtB,IAAI;AAAA,QACJ;AAAA,QACA,KAAK,OAAO;AAAA,MAAA;AAGd,YAAM,qBAAqB,iBAAiB,IAAI,CAAC,SAAS;AACxD,cAAM,aAAa,IAAI,kBAAkB,KAAK,SAAU,GAAG;AAC3D,cAAM,gBAAgB,IAAI,kBAAkB,KAAK,SAAU,GAAG;AAC9D,cAAM,qBACJ,IAAI,kBAAkB,KAAK,SAAU,GAAG;AAC1C,cAAM,uBACJ,IAAI,kBAAkB,KAAK,SAAU,GAAG;AAC1C,cAAM,oBAAoB,IAAI,kBAAkB,KAAK,SAAU,GAAG;AAElE,eAAO;AAAA,UACL;AAAA,YACE,SAAS,KAAK,YAAY,GAAG,UAAU,MAAM,KAAK,YAAY,GAAG,UAAU;AAAA,cACzE;AAAA,cACA,QAAQ,KAAK,IAAI;AAAA,cACjB,CAAC,KAAK,YAAY,UAAU,KAAK,WAAW,MAAM;AAAA,cAClD,yBAAyBC,MAAAA,WAAW,MAAM,UAAU,CAAC;AAAA,YAAA,EAEpD,OAAO,OAAO,EACd,KAAK,GAAG,CAAC;AAAA,aACX,KAAK,OAAO,eAAe,KAAK,QAAQ;AAAA,YACzC,aACI,kDAAkDC,MAAAA;AAAAA,cAChDC,MAAAA;AAAAA,gBACE,KAAK;AAAA,kBACH,KAAK,QAAQ,KAAK,OAAO,kBAAkB;AAAA,kBAC3C,KAAK;AAAA,oBACH,KAAK,OAAO;AAAA,oBACZ,WAAW;AAAA,kBAAA;AAAA,gBACb;AAAA,gBAEF,KAAK,OAAO;AAAA,cAAA;AAAA,YACd,CACD,qBACD;AAAA,YACJ,iBAAiB,sBAAsB,uBACnC;AAAA,kBAEE;AAAA,cACE,CAAC,aAAa,aAAa;AAAA,cAC3B,CAAC,kBAAkB,kBAAkB;AAAA,cACrC,CAAC,oBAAoB,oBAAoB;AAAA,YAAA,EAG1C,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,EAClB,IAAI,CAAC,MAAM;AACV,qBAAO,GACL,EAAE,CAAC,CACL,wCAAwCD,MAAAA;AAAAA,gBACtCC,MAAAA;AAAAA,kBACE,KAAK;AAAA,oBACH,KAAK,QAAQ,KAAK,OAAO,kBAAkB;AAAA,oBAC3C,KAAK;AAAA,sBACH,KAAK,OAAO;AAAA,sBACZ,EAAE,CAAC,EAAG;AAAA,oBAAA;AAAA,kBACR;AAAA,kBAEF,KAAK,OAAO;AAAA,gBAAA;AAAA,cACd,CACD,QAAQ,EAAE,CAAC,CAAC;AAAA,YACf,CAAC,EACA,KAAK,KAAK,CAAC;AAAA,oBAEd;AAAA,YACJ,oBACI,yBAAyBD,MAAAA;AAAAA,cACvBC,MAAAA;AAAAA,gBACE,KAAK;AAAA,kBACH,KAAK,QAAQ,KAAK,OAAO,kBAAkB;AAAA,kBAC3C,KAAK;AAAA,oBACH,KAAK,OAAO;AAAA,oBACZ,kBAAkB;AAAA,kBAAA;AAAA,gBACpB;AAAA,gBAEF,KAAK,OAAO;AAAA,cAAA;AAAA,YACd,CACD,oBAAoB,UAAU,OAC/B;AAAA,UAAA,EACJ,KAAK,EAAE;AAAA,QAAA,EACT,KAAK,MAAM;AAAA,MACf,CAAC;AAED,UAAI,qCAAqC;AACzC,UAAI,gCAAgC;AAEpC,UAAI,CAAC,KAAK,OAAO,gBAAgB,uBAAuB;AACtD,wCAAgC;AAAA,UAC9B,wBAAwB,UAAU;AAAA,EAC1C,CAAC,GAAGC,MAAAA,2BAA2B,IAAI,UAAU,EAAE,QAAA,CAAS,EACvD,OAAO,CAAC,CAAC,QAAQ,MAAM,QAAQ,EAC/B,IAAI,CAAC,CAAC,UAAU,SAAS,MAAM;AAC9B,mBAAO,IAAI,QAAQ,aAAaC,MAAAA,iCAAiC,WAAW,UAAU,CAAC;AAAA,UACzF,CAAC,CAAC;AAAA;AAAA,UAEM,wBAAwB,UAAU;AAAA,EAC1C,CAAC,GAAGC,MAAAA,qBAAqB,IAAI,UAAU,EAAE,QAAA,CAAS,EACjD,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,EACnB,IAAI,CAAC,CAAC,IAAI,SAAS,MAAM;AACxB,mBAAO,IAAI,EAAE,aAAaD,MAAAA,iCAAiC,WAAW,UAAU,CAAC;AAAA,UACnF,CAAC,CAAC;AAAA;AAAA,UAEM,wBAAwB,UAAU;AAAA,GACzCE,WAAAA,WAAW,iBAAiB,UAAU;AAAA,EACvC,CAAC,GAAGC,MAAAA,qBAAqB,IAAI,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,IAAI,SAAS,MAAM;AAC7E,mBAAO,IAAI,EAAE,aAAaH,MAAAA,iCAAiC,WAAW,UAAU,CAAC;AAAA,UACnF,CAAC,CAAC;AAAA;AAAA,UAEQ,wBAAwB,UAAU;AAAA,MACtC,UAAU,oBAAoB,UAAU;AAAA,aAElC,IAAI,WAAW,SAAS,IACpB,CAAC,GAAGD,iCAA2B,IAAI,UAAU,EAAE,KAAA,CAAM,EAClD,OAAO,CAAC,aAAa,QAAQ,EAC7B,IAAI,CAAC,aAAa,IAAI,QAAQ,GAAG,EACjC,KAAK,GAAG,IACX,OACN;AAAA,MACJ,UAAU,cAAc,UAAU;AAAA,MAE5B,IAAI,WAAW,SAAS,IACpB,CAAC,GAAGE,2BAAqB,IAAI,UAAU,EAAE,KAAA,CAAM,EAC5C,OAAO,CAAC,OAAO,EAAE,EACjB,IAAI,CAAC,OAAO,IAAI,EAAE,GAAG,EACrB,KAAK,GAAG,IACX,OACN;AAAA,MACJ,CAAC,IAAIC,WAAAA,WAAW,KAAK,GAAG,CAAC,GAAGC,MAAAA,qBAAqB,IAAI,UAAU,EAAE,KAAA,CAAM,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC;AAAA,MAC1G,UAAU,cAAc,UAAU;AAAA;AAAA,UAE9B,wBAAwB,UAAU;AAAA,EAC1C,IAAI,UAAU,IAAI,CAAC,UAAU,GAAG,MAAM,YAAY,GAAG,UAAU,YAAYH,MAAAA,iCAAiC,OAAO,UAAU,CAAC,EAAE,EAAE,KAAK,GAAG,CAAC;AAAA;AAAA,QAAA,EAEnI,KAAK,IAAI;AAEX,6CAAqCI,MAAAA,+BAA+B;AAAA,UAClE,GAAG,OAAO,mBAAmB,EAAE,WAAW,MAAM;AAAA,UAChD,YACE,KAAK,OAAO,sBAAsB,QAC9B,mBACA;AAAA,YACE,GAAG,gBAAgB,IAAI,CAAC,EAAE,KAAA,MAAW,IAAI;AAAA,YACzC,GAAG,iBAAiB,OAAO,CAAC,MAAM,EAAE,SAAS;AAAA,UAAA;AAAA,UAErD;AAAA,QAAA,CACD;AAAA,MACH;AAEA,UAAI,YAAY;AAChB,UAAI,uBAAuB;AACzB,oBAAY;AAAA,UACV,aAAa,UAAU,WAAW,KAAK,OAAO,eAAe,KAAK,SAAS,UAAU,UAAU;AAAA,IACrG,IAAI,UACH;AAAA,YACC,CAAC,UACC,GAAG,MAAM,YAAY,GAAG,UAAU,KAAKJ,MAAAA,iCAAiC,OAAO,UAAU,CAAC;AAAA,UAAA,EAE7F,KAAK,GAAG,CAAC;AAAA;AAAA,UAEJ,gBAAgBK,MAAAA,mBAAmB,UAAU,CAAC,cAAc,UAAU,+BAA+B,UAAU,YAAY,KAAK,OAAO,eAAe,KAAK,sBAAsB,UAAU,UAAU;AAAA,QAAA,EACrM,KAAK,IAAI;AAAA,MACb;AAEA,aAAO;AAAA,QACL,cAAAX;AAAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ;AAEA,UAAM,aAAa,KAAK,qBAAqB,IAAI,CAAC,YAAY;AAAA,MAC5D,YAAY,OAAO,gBAAgB;AAAA,MACnC,GAAG,wBAAwB,MAAM;AAAA,IAAA,EACjC;AAEF,SAAK,QAAQ,IAAI,CAAC,WAAW;AAC3B,aAAO,OAAO,sBAAsB;AAAA,QAClC;AAAA,QACA;AAAA,QACA,WAAW;AAAA,MAAA,CACZ;AAAA,IACH,CAAC;AAED,QAAI,gBAAgBY,MAAAA;AAAAA,MAClB,WAAW,QAAQ,CAAC,MAAM,EAAE,OAAO;AAAA,IAAA;AAErC,QAAI,KAAK,OAAO,cAAc;AAC5B,sBAAgB,cAAc,OAAO,CAAC,MAAM,EAAE,eAAe,MAAM;AAAA,IACrE;AAEA,UAAM,mBAAmB,cAAc,IAAIC,uBAAiB;AAE5D,QAAI,qBAAqB;AACzB,QAAI,KAAK,OAAO,sBAAsB,SAAS,CAAC,KAAK,OAAO,cAAc;AACxE,2BAAqB,gBAClB,IAAI,CAAC,EAAE,WAAW;AACjB,cAAM,uBAAuB,CAAC,cAA0B;AACtD,cAAI,CAACC,MAAAA,gCAAgC,SAAS,GAAG;AAC/C,mBAAO;AAAA,UACT;AACA,gBAAMC,sBAAqB,KAAK,qBAC7B,IAAI,CAAC,WAAW;AACf,mBAAO,OAAO,wBAAwB;AAAA,cACpC;AAAA,YAAA,CACD;AAAA,UACH,CAAC,EACA,OAAO,OAAO,EACd,KAAK,IAAI;AAEZ,iBAAO,qBAAqB,KAAK,cAAc,SAAS,CAAC;AAAA,wBAC7CA,mBAAkB;AAAA;AAAA,QAEhC;AACA,eAAO,qBAAqB,IAAI;AAAA,MAClC,CAAC,EACA,KAAK,IAAI;AAAA,IACd;AAEA,UAAM,eAAe,WAAW,QAAQ,CAAC,MAAM,EAAE,YAAY;AAC7D,UAAM,mBAAmB,KAAK,qBAAqB;AAAA,MACjD,CAAC,MACC,sBAAsB,eAAe,EAAE,gBAAgB,UAAU,KACjE,CAAA;AAAA,IAAC;AAEL,QAAI,iBAAiB,SAAS,GAAG;AAC/B,mBAAa,QAAQ,GAAG,gBAAgB;AAAA,IAC1C;AACA,UAAM,mBAAmB;AAAA,MACvB,GAAG,KAAK,OAAO;AAAA,MACf;AAAA;AAAA;AAAA,MAGA,CAAC,GAAG,gBAAgB,EAAE,KAAK,IAAI;AAAA,MAC/BH,MAAAA,wBAAwB,YAAY,EAAE,IAAIC,MAAAA,iBAAiB,EAAE,KAAK,IAAI;AAAA,MACtE,WAAW,QAAQ,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,IAAI;AAAA,MACxD,WAAW,QAAQ,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,IAAI;AAAA,MAEzD,WAAW,IAAI,CAAC,MAAM,EAAE,6BAA6B,EAAE,KAAK,IAAI;AAAA,MAChE,WAAW,IAAI,CAAC,MAAM,EAAE,kCAAkC,EAAE,KAAK,IAAI;AAAA,MACrE;AAAA,MACA,WAAW,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,IAAI;AAAA,MACtD,WAAW,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI;AAAA,MAC5C,GAAG,KAAK,OAAO;AAAA,IAAA,EAEd,OAAO,OAAO,EACd,KAAK,MAAM;AACd,WAAO;AAAA,EACT;AAAA,EAEQ,cAAc,MAAiB;AACrC,WAAOV,MAAAA;AAAAA,MACLC,MAAAA;AAAAA,QACE,KAAK;AAAA,UACH,KAAK,QAAQ,KAAK,OAAO,kBAAkB;AAAA,UAC3C,KAAK,QAAQ,KAAK,OAAO,iBAAiB,KAAK,QAAQ;AAAA,QAAA;AAAA,QAEzD,KAAK,OAAO;AAAA,MAAA;AAAA,IACd;AAAA,EAEJ;AAAA,EAEA,MAAc,qBAAqB,MAIzB;AACR,UAAM,SAAS,MAAM,KAAK,sBAAsB,IAAI;AAEpD,QAAI,OAAO,WAAW,SAAS;AAC7B,WAAK,UAAU,OAAO,WAAW;AACjC,aAAO;AAAA,QACL;AAAA,QACA,iBAAiB,OAAO;AAAA,QACxB,YAAY,OAAO;AAAA,MAAA;AAAA,IAEvB;AAEA,UAAM,oBAAoB,MAAM,KAAK,GAAG,SAAS,KAAK,QAAQ;AAC9D,QAAI,sBAAsB,qBAAqB;AAC7C,YAAM,IAAI,MAAM,WAAW,KAAK,QAAQ,iBAAiB;AAAA,IAC3D;AAEA,UAAM,oBAAyC;AAAA,MAC7C,aAAa,kBAAkB;AAAA,MAC/B,SAAS,kBAAkB,KAAK;AAAA,MAChC,SAAS,CAAA;AAAA,MACT,SAAS,KAAK,aAAa;AAAA,IAAA;AAG7B,UAAM,mBAAmB,KAAK,WAAW,WAAW,KAAK,IAAI,KAAK;AAElE,QAAI,uBAAuB;AAE3B,QAAI,CAAC,kBAAkB,aAAa;AAClC,6BAAuB;AAEvB,UAAI,KAAK,iBAAiB,QAAQ;AAChC,cAAM,qBAAqB,KAAK,eAAe;AAG/C,0BAAkB,cAAc,MAAMY,SAAAA;AAAAA,UACpC,KAAK;AAAA,WACJ,KAAK,OAAO,mBAAmB,qBAC9B,KAAK,OAAO,mBAAmB,kBAC/B,mBAAmB,SAAA;AAAA,UACrB;AAAA,YACE,YAAY,mBAAmB,QAAQ,WAAA;AAAA,YACvC,SAAS,iBAAiB,WAAW,eAAe,IAAI;AAAA,YACxD,gBACE,mBAAmB,QAAQ,eAAe,gBAAgB;AAAA,YAC5D,cAAc,mBAAmB,QAAQ,aAAA;AAAA,UAAa;AAAA,QACxD;AAEF,0BAAkB,UAAU,CAAC,OAAO;AAAA,MACtC;AAAA;AAAA,QAEG,CAAC,UAAU,QAAQ,EAAgC;AAAA,UAClD,CAAC,MAAM,MAAM,KAAK;AAAA,QAAA,KAGlB;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,EAEF,MAAM,CAAC,MAAM,MAAM,KAAK,YAAY;AAAA,QACtC;AACA,cAAM,iBAAiB,KAAK,eAAe;AAC3C,0BAAkB,cAAc,MAAMA,SAAAA;AAAAA,UACpC,KAAK;AAAA,UACL,KAAK,OAAO,mBAAmB,iBAC7B,eAAe,SAAA;AAAA,UACjB;AAAA,YACE,YAAY,eAAe,QAAQ,WAAA;AAAA,YACnC,SAAS,iBAAiB,WAAW,eAAe,IAAI;AAAA,YACxD,gBACE,eAAe,QAAQ,eAAe,gBAAgB;AAAA,YACxD,cAAc,eAAe,QAAQ,aAAA;AAAA,UAAa;AAAA,QACpD;AAEF,0BAAkB,UAAU,CAAC,OAAO;AAAA,MACtC,OAAO;AACL,eAAO;AAAA,MACT;AAAA,IACF,OAAO;AAEL,YAAM,kBAAkB,MAAMC,oBAAU;AAAA,QACtC,QAAQ,kBAAkB;AAAA,QAC1B,KAAK;AAAA,UACH,QAAQ,KAAK,OAAO;AAAA,UACpB,SAAS;AAAA,UACT,MAAM,KAAK,iBAAiB;AAAA,UAC5B,mBAAmB,EAAE,KAAK,OAAO,sBAAsB;AAAA,QAAA;AAAA,QAEzD,SAAS,KAAK;AAAA,MAAA,CACf;AAED,UAAI,gBAAgB,WAAW,SAAS;AACtC,cAAM,IAAI;AAAA,UACR,iCAAiC,KAAK,QAAQ,KAAK,gBAAgB,KAAK;AAAA,QAAA;AAAA,MAE5E;AACA,wBAAkB,UAAU,gBAAgB;AAC5C,UAAI,gBAAgB,WAAW,YAAY;AACzC,0BAAkB,cAAc,gBAAgB;AAChD,+BAAuB;AAAA,MACzB;AAAA,IACF;AAGA,QAAI,sBAAsB;AACxB,YAAM,QAAQ,MAAM,KAAK,cAAc;AAAA,QACrC,UAAU,KAAK;AAAA,QACf,YAAY,kBAAkB;AAAA,QAC9B,UAAU;AAAA,UACR,MAAM;AAAA,UACN,iBAAiB,kBAAkB;AAAA,QAAA;AAAA,MACrC,CACD;AACD,wBAAkB,UAAU,MAAM;AAAA,IACpC;AAEA,SAAK,qBAAqB,IAAI,KAAK,UAAU,iBAAiB;AAC9D,SAAK,UAAU,kBAAkB;AACjC,UAAM,kBAAkB,CAACC,WAAAA;AAAAA,MACvB,OAAO,YAAY;AAAA,MACnB,kBAAkB;AAAA,IAAA;AAEpB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,YAAY;AAAA,IAAA;AAAA,EAEhB;AAAA,EAEA,MAAc,kCACZ,MAIA,OAC+C;AAC/C,UAAM,aAAa,KAAK,KAAK,EAAE,IAAI,KAAK,IAAI;AAC5C,WAAO,KAAK,6BAA6B,MAAM,UAAU;AAAA,EAC3D;AAAA,EAEA,MAAc,6BAGZ,MAIA,YACuC;AAKvC,QAAI,CAAC,YAAY;AACf,aAAO,EAAE,QAAQ,oBAAA;AAAA,IACnB;AACA,QAAI,UAAU,KAAK;AAEnB,QAAI,YAAY,QAAW;AACzB,UAAI;AACF,cAAM,cAAc,MAAM,KAAK,GAAG,KAAK,KAAK,IAAI;AAChD,kBAAU,YAAY;AAAA,MACxB,QAAQ;AACN,eAAO,EAAE,QAAQ,mBAAA;AAAA,MACnB;AAAA,IACF;AACA,WAAO,EAAE,QAAQ,YAAY,WAAW,SAAS,SAAS,WAAA;AAAA,EAC5D;AAAA,EAEA,MAAc,cAAc,MAWzB;AACD,UAAM,UAAU,KAAK,gBAAgB,KAAK,QAAQ;AAClD,UAAM,KAAK,GAAG,UAAU,SAAS,KAAK,UAAU;AAEhD,QAAI,KAAK,SAAS,SAAS,SAAS;AAClC,YAAM,aAAa,MAAM,KAAK,GAAG,KAAK,KAAK,QAAQ;AACnD,UAAI,WAAW,YAAY,KAAK,SAAS,iBAAiB;AACxD,cAAM,MAAM;AAAA,UACV,KAAK,QAAQ,KAAK,QAAQ;AAAA,UAC1B,OAAO,EAAE,MAAM,UAAU,MAAM,KAAK,SAAA;AAAA,QAAS,CAC9C;AAAA,MACH;AACA,YAAM,eAAe,MAAM,KAAK,GAAG,KAAK,OAAO;AAC/C,UAAI,aAAa,SAAS,WAAW,MAAM;AACzC,cAAM,KAAK,GAAG,MAAM,SAAS,WAAW,IAAI;AAAA,MAC9C;AACA,UACE,aAAa,QAAQ,WAAW,OAChC,aAAa,QAAQ,WAAW,KAChC;AACA,YAAI;AACF,gBAAM,KAAK,GAAG,MAAM,SAAS,WAAW,KAAK,WAAW,GAAG;AAAA,QAC7D,SAAS,KAAK;AACZ,cACE,OAAO,QAAQ,YACf,QAAQ,QACR,UAAU,OACT,IAAY,SAAS,SACtB;AACA,oBAAQ;AAAA,cACN,iCAAkC,IAAY,OAAO;AAAA,YAAA;AAAA,UAEzD,OAAO;AACL,kBAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,UAAI,MAAMC,MAAAA,gBAAgB,KAAK,QAAQ,GAAG;AACxC,cAAM,MAAM;AAAA,UACV,KAAK,QAAQ,KAAK,QAAQ;AAAA,UAC1B,OAAO,EAAE,MAAM,UAAU,MAAM,KAAK,SAAA;AAAA,QAAS,CAC9C;AAAA,MACH;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,KAAK,GAAG,KAAK,OAAO;AAEvC,UAAM,KAAK,GAAG,OAAO,SAAS,KAAK,QAAQ;AAE3C,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAgB,UAAkB;AACxC,UAAM,UAAU,KAAK,QAAQ,QAAQ;AACrC,UAAM,OAAO,OAAO,WAAW,KAAK,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AAElE,QAAI,CAAC,KAAK,WAAW;AAEnBzB,cAAAA,UAAU,KAAK,OAAO,QAAQ,EAAE,WAAW,MAAM;AACjD,WAAK,YAAY,OAAO,YAAY,CAAC,EAAE,SAAS,KAAK;AAAA,IACvD;AACA,WAAO,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,KAAK,SAAS,IAAI,IAAI,EAAE;AAAA,EAClE;AAAA,EAEA,MAAc,sBAAsB,MAOlC;AACA,UAAM,mBAAmB,MAAM,KAAK;AAAA,MAClC,EAAE,MAAM,KAAK,SAAA;AAAA,MACb;AAAA,IAAA;AAEF,QAAI,iBAAiB,WAAW,OAAO;AACrC,WAAK,qBAAqB,IAAI,KAAK,UAAU,iBAAiB,UAAU;AACxE,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,YAAY,iBAAiB;AAAA,MAAA;AAAA,IAEjC;AACA,QAAI,iBAAiB,WAAW,oBAAoB;AAClD,YAAM,IAAI,MAAM,sCAAsC,KAAK,QAAQ,EAAE;AAAA,IACvE;AACA,UAAM,UACJ,iBAAiB,WAAW,OAAO,iBAAiB,UAAU;AAEhE,UAAM,wBAAwB,MAAM,KAAK;AAAA,MACvC,EAAE,MAAM,KAAK,UAAU,QAAA;AAAA,MACvB;AAAA,IAAA;AAGF,QAAI,sBAAsB,WAAW,oBAAoB;AACvD,YAAM,IAAI,MAAM,sCAAsC,KAAK,QAAQ,EAAE;AAAA,IACvE;AAEA,QAAI,sBAAsB,WAAW,OAAO;AAI1C,UAAI,iBAAiB,WAAW,MAAM;AACpC,YACEwB,WAAAA;AAAAA,UACE,iBAAiB,WAAW;AAAA,UAC5B,sBAAsB,WAAW;AAAA,QAAA,GAEnC;AACA,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,gBAAgB;AAAA,YAChB,YAAY,sBAAsB;AAAA,UAAA;AAAA,QAEtC;AACA,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,YAAY,sBAAsB;AAAA,QAAA;AAAA,MAEtC;AAAA,IACF;AAEA,QAAI,iBAAiB,WAAW,qBAAqB;AACnD,aAAO;AAAA,QACL,QAAQ;AAAA,MAAA;AAAA,IAEZ;AACA,WAAO,EAAE,QAAQ,SAAS,YAAY,iBAAiB,WAAA;AAAA,EACzD;AAAA,EAEA,MAAc,eAAe,MAAiB;AAC5C,UAAM,SAAS,MAAM,KAAK,sBAAsB,IAAI;AAEpD,QAAI,OAAO,WAAW,SAAS;AAC7B,WAAK,UAAU,OAAO,WAAW;AACjC,WAAK,qBAAqB,IAAI,KAAK,UAAU,OAAO,UAAU;AAC9D,aAAO,OAAO;AAAA,IAChB;AACA,UAAM,eAAe,MAAM,KAAK,GAAG,SAAS,KAAK,QAAQ;AACzD,QAAI,iBAAiB,qBAAqB;AACxC,YAAM,IAAI,MAAM,sCAAsC,KAAK,QAAQ,EAAE;AAAA,IACvE;AAEA,UAAM,oBAAyC;AAAA,MAC7C,aAAa,aAAa;AAAA,MAC1B,SAAS,aAAa,KAAK;AAAA,MAC3B,SAAS,CAAA;AAAA,MACT,SAAS,KAAK,aAAa;AAAA,IAAA;AAI7B,QAAI,CAAC,aAAa,aAAa;AAC7B,YAAM,eAAe,KAAK,eAAe;AACzC,YAAM,mBAAmB,MAAMF,SAAAA;AAAAA,QAC7B,KAAK;AAAA,QACL,aAAa,SAAA;AAAA,QACb;AAAA,UACE,YAAY,aAAa,QAAQ,WAAA;AAAA,UACjC,SAASnB,WAAAA;AAAAA,UACT,gBAAgB,aAAa,QAAQ,eAAA;AAAA,UACrC,cAAc,aAAa,QAAQ,aAAA;AAAA,QAAa;AAAA,MAClD;AAGF,WAAK,OAAO,IAAI,eAAe,KAAK,QAAQ,EAAE;AAC9C,YAAM,QAAQ,MAAM,KAAK,cAAc;AAAA,QACrC,UAAU,KAAK;AAAA,QACf,YAAY;AAAA,QACZ,UAAU;AAAA,UACR,MAAM;AAAA,UACN,iBAAiB,aAAa,KAAK;AAAA,QAAA;AAAA,MACrC,CACD;AACD,wBAAkB,cAAc;AAChC,wBAAkB,UAAU,MAAM;AAAA,IACpC;AAEA,UAAM,mBAAkC,CAAA;AACxC,eAAW,UAAU,KAAK,sBAAsB;AAC9C,YAAM,aAAa,OAAO,gBAAgB;AAG1C,UAAI,aAAa,YAAY,SAAS,gBAAgB,UAAU,EAAE,GAAG;AACnE,yBAAiB,KAAK,UAAU;AAAA,MAClC;AAAA,IACF;AAEA,sBAAkB,UAAU;AAC5B,SAAK,UAAU;AACf,SAAK,qBAAqB,IAAI,KAAK,UAAU,iBAAiB;AAE9D,UAAM,kBAAkB,CAACqB,WAAAA;AAAAA,MACvB,OAAO,YAAY;AAAA,MACnB;AAAA,IAAA;AAEF,WAAO;AAAA,EACT;AAAA,EAEQ,WAAW,MAAiB,KAA4B;AAI9DE,UAAAA,WAAW,KAAK,sBAAsB;AAEtC,QAAI,cAAcC,MAAAA,eAAe,IAAI,YAAY,MAAM,KAAK,SAAS;AAGrE,QAAI,aAAa,wBAAwB,YAAY,UAAU,QAAQ;AAErE,YAAM,sBAAsBA,MAAAA;AAAAA,QAC1B,YAAY;AAAA,QACZ;AAAA,QACA,KAAK;AAAA,MAAA;AAEP,UAAI,qBAAqB;AACvB,sBAAc;AAAA,MAChB;AAAA,IACF;AAEA,QAAI,kBAAkB,SAAS;AAE/B,SAAK,OAAOC,MAAAA,kBAAkB,IAAI;AAElC,UAAM,cAAcC,MAAAA,aAAa,KAAK,QAAQ,EAAE;AAEhD,UAAM,QAAQ,YAAY,MAAM,GAAG;AACnC,UAAM,mBAAmB,MAAM,MAAM,SAAS,CAAC,KAAK;AAEpD,SAAK,YACH,iBAAiB,WAAW,GAAG,KAC/B,MAAM,MAAM,CAAC,SAAS,KAAK,uBAAuB,KAAK,IAAI,CAAC;AAE9D,SAAK,cAAcC,MAAAA;AAAAA,MACjBC,MAAAA,kBAAkBC,MAAAA,qBAAqB,KAAK,IAAI,CAAC,KAAK;AAAA,IAAA;AAGxD,QACE,CAAC,KAAK,aAEJ;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,EAEF,KAAK,CAAC,MAAM,MAAM,KAAK,YAAY,GACrC;AACA,UAAI,kBAAkB,KAAK,SAAU,IACnC,IAAI,kBAAkB,KAAK,SAAU,KAAK,CAAA;AAE5C,UAAI,kBAAkB,KAAK,SAAU,EACnC,KAAK,iBAAiB,SAClB,SACA,KAAK,iBAAiB,WACpB,WACA,KAAK,iBAAiB,mBACpB,mBACA,KAAK,iBAAiB,qBACpB,qBACA,WACZ,IAAI;AAEJ,YAAM,cAAc,IAAI,WAAW;AAAA,QACjC,CAAC,MAAM,EAAE,cAAc,KAAK;AAAA,MAAA;AAG9B,UAAI,CAAC,aAAa;AAChB,aAAK;AAAA,UACH;AAAA,YACE,GAAG;AAAA,YACH,WAAW;AAAA,YACX,cAAc;AAAA,UAAA;AAAA,UAEhB;AAAA,QAAA;AAAA,MAEJ;AACA;AAAA,IACF;AAEA,UAAM,sBAAsB,KAAK,eAAe,IAAI,WAAW;AAC/D,UAAM,eACJ,KAAK,iBAAiB,qBAAqB,KAAK;AAElD,SAAK,0BACH,KAAK,iBAAiB,qBAAqB,eACvC,CAAC,qBACD;AAEN,QAAI,CAAC,KAAK,aAAa,KAAK,yBAAyB;AACnD,YAAM,kBAAkBC,MAAAA,0BAA0B,KAAK,SAAS,KAAK;AACrE,YAAM,qBAAqBC,MAAAA,oBAAoB,eAAe;AAE9D,YAAM,cAAc,IAAI,WAAW;AAAA,QACjC,CAAC,MAAM,EAAE,cAAc;AAAA,MAAA;AAGzB,UAAI,CAAC,aAAa;AAChB,cAAM,aAAwB;AAAA,UAC5B,GAAG;AAAA,UACH,MAAMD,MAAAA,0BAA0B,KAAK,IAAI,KAAK;AAAA,UAC9C,UAAUA,MAAAA,0BAA0B,KAAK,QAAQ,KAAK;AAAA,UACtD,UAAUA,MAAAA,0BAA0B,KAAK,QAAQ,KAAK;AAAA,UACtD,WAAW;AAAA,UACX,cAAc;AAAA,UACd,WAAW;AAAA,UACX,cAAc;AAAA;AAAA,UACd,sBAAsB;AAAA,UACtB,yBAAyB;AAAA,QAAA;AAG3B,mBAAW,WAAW,WAAW,YAAY,CAAA;AAC7C,mBAAW,SAAS,KAAK,IAAI;AAE7B,aAAK,SAAS;AAEd,YAAI,KAAK,iBAAiB,mBAAmB;AAE3C,eAAK,OAAOL,MAAAA,kBAAkB,IAAI;AAAA,QACpC;AAEA,aAAK,WAAW,YAAY,GAAG;AAAA,MACjC,OAAO;AACL,oBAAY,WAAW,YAAY,YAAY,CAAA;AAC/C,oBAAY,SAAS,KAAK,IAAI;AAE9B,aAAK,SAAS;AAAA,MAChB;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ;AACf,UAAI,CAAC,KAAK,yBAAyB;AACjC,aAAK,OAAO,WAAW,KAAK,OAAO,YAAY,CAAA;AAC/C,aAAK,OAAO,SAAS,KAAK,IAAI;AAAA,MAChC;AAAA,IACF,OAAO;AACL,UAAI,UAAU,KAAK,IAAI;AAAA,IACzB;AAEA,QAAI,WAAW,KAAK,IAAI;AAAA,EAC1B;AAAA;AAAA,EAGQ,qCAAqC,UAA2B;AAEtE,QAAI,aAAa,KAAK,wBAAwB;AAC5C,aAAO;AAAA,IACT;AAGA,QAAI,SAAS,WAAW,KAAK,mBAAmB,GAAG;AACjD,aAAO;AAAA,IACT;AAGA,QACE,OAAO,KAAK,OAAO,uBAAuB,YAC1C,aAAa,KAAK,OAAO,oBACzB;AACA,aAAO;AAAA,IACT;AAGA,QAAI,KAAK,eAAe,IAAI,QAAQ,GAAG;AACrC,aAAO;AAAA,IACT;AAGA,QAAIO,gBAAAA,oBAAoB,KAAK,SAAS,QAAQ,CAAC,GAAG;AAChD,aAAO;AAAA,IACT;AAGA,QAAI,KAAK,oBAAoB,KAAK,CAAC,QAAQ,SAAS,WAAW,GAAG,CAAC,GAAG;AACpE,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AACF;;"}
@@ -61,6 +61,7 @@ export declare class Generator {
61
61
  root: string;
62
62
  fs?: fs;
63
63
  });
64
+ private getGeneratedRouteTreePath;
64
65
  private getRoutesDirectoryPath;
65
66
  getRoutesByFileMap(): GetRoutesByFileMapResult;
66
67
  run(event?: GeneratorEvent): Promise<void>;
@@ -53,6 +53,7 @@ function removeLeadingSlash(path2) {
53
53
  function removeTrailingSlash(s) {
54
54
  return s.replace(/\/$/, "");
55
55
  }
56
+ const BRACKET_CONTENT_RE = /\[(.*?)\]/g;
56
57
  function determineInitialRoutePath(routePath) {
57
58
  const DISALLOWED_ESCAPE_CHARS = /* @__PURE__ */ new Set([
58
59
  "/",
@@ -70,7 +71,6 @@ function determineInitialRoutePath(routePath) {
70
71
  ]);
71
72
  const parts = routePath.split(new RegExp("(?<!\\[)\\.(?!\\])", "g"));
72
73
  const escapedParts = parts.map((part) => {
73
- const BRACKET_CONTENT_RE = /\[(.*?)\]/g;
74
74
  let match;
75
75
  while ((match = BRACKET_CONTENT_RE.exec(part)) !== null) {
76
76
  const character = match[1];
@@ -86,7 +86,7 @@ Please remove and/or replace them.`
86
86
  process.exit(1);
87
87
  }
88
88
  }
89
- return part.replace(/\[(.)\]/g, "$1");
89
+ return part.replace(BRACKET_CONTENT_RE, "$1");
90
90
  });
91
91
  const final = cleanPath(`/${escapedParts.join("/")}`) || "";
92
92
  return final;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import * as fsp from 'node:fs/promises'\nimport path from 'node:path'\nimport * as prettier from 'prettier'\nimport { rootPathId } from './filesystem/physical/rootPathId'\nimport type { Config } from './config'\nimport type { ImportDeclaration, RouteNode } from './types'\n\nexport function multiSortBy<T>(\n arr: Array<T>,\n accessors: Array<(item: T) => any> = [(d) => d],\n): Array<T> {\n return arr\n .map((d, i) => [d, i] as const)\n .sort(([a, ai], [b, bi]) => {\n for (const accessor of accessors) {\n const ao = accessor(a)\n const bo = accessor(b)\n\n if (typeof ao === 'undefined') {\n if (typeof bo === 'undefined') {\n continue\n }\n return 1\n }\n\n if (ao === bo) {\n continue\n }\n\n return ao > bo ? 1 : -1\n }\n\n return ai - bi\n })\n .map(([d]) => d)\n}\n\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\nexport function removeLeadingSlash(path: string): string {\n return path.replace(/^\\//, '')\n}\n\nexport function removeTrailingSlash(s: string) {\n return s.replace(/\\/$/, '')\n}\n\nexport function determineInitialRoutePath(routePath: string) {\n const DISALLOWED_ESCAPE_CHARS = new Set([\n '/',\n '\\\\',\n '?',\n '#',\n ':',\n '*',\n '<',\n '>',\n '|',\n '!',\n '$',\n '%',\n ])\n\n const parts = routePath.split(/(?<!\\[)\\.(?!\\])/g)\n\n // Escape any characters that in square brackets\n const escapedParts = parts.map((part) => {\n // Check if any disallowed characters are used in brackets\n const BRACKET_CONTENT_RE = /\\[(.*?)\\]/g\n\n let match\n while ((match = BRACKET_CONTENT_RE.exec(part)) !== null) {\n const character = match[1]\n if (character === undefined) continue\n if (DISALLOWED_ESCAPE_CHARS.has(character)) {\n console.error(\n `Error: Disallowed character \"${character}\" found in square brackets in route path \"${routePath}\".\\nYou cannot use any of the following characters in square brackets: ${Array.from(\n DISALLOWED_ESCAPE_CHARS,\n ).join(', ')}\\nPlease remove and/or replace them.`,\n )\n process.exit(1)\n }\n }\n\n // Since this split segment is safe at this point, we can\n // remove the brackets and replace them with the content inside\n return part.replace(/\\[(.)\\]/g, '$1')\n })\n\n // If the syntax for prefix/suffix is different, from the path\n // matching internals of router-core, we'd perform those changes here\n // on the `escapedParts` array before it is joined back together in\n // `final`\n\n const final = cleanPath(`/${escapedParts.join('/')}`) || ''\n\n return final\n}\n\nexport function replaceBackslash(s: string) {\n return s.replaceAll(/\\\\/gi, '/')\n}\n\nexport function routePathToVariable(routePath: string): string {\n const toVariableSafeChar = (char: string): string => {\n if (/[a-zA-Z0-9_]/.test(char)) {\n return char // Keep alphanumeric characters and underscores as is\n }\n\n // Replace special characters with meaningful text equivalents\n switch (char) {\n case '.':\n return 'Dot'\n case '-':\n return 'Dash'\n case '@':\n return 'At'\n case '(':\n return '' // Removed since route groups use parentheses\n case ')':\n return '' // Removed since route groups use parentheses\n case ' ':\n return '' // Remove spaces\n default:\n return `Char${char.charCodeAt(0)}` // For any other characters\n }\n }\n\n return (\n removeUnderscores(routePath)\n ?.replace(/\\/\\$\\//g, '/splat/')\n .replace(/\\$$/g, 'splat')\n .replace(/\\$\\{\\$\\}/g, 'splat')\n .replace(/\\$/g, '')\n .split(/[/-]/g)\n .map((d, i) => (i > 0 ? capitalize(d) : d))\n .join('')\n .split('')\n .map(toVariableSafeChar)\n .join('')\n // .replace(/([^a-zA-Z0-9]|[.])/gm, '')\n .replace(/^(\\d)/g, 'R$1') ?? ''\n )\n}\n\nexport function removeUnderscores(s?: string) {\n return s?.replaceAll(/(^_|_$)/gi, '').replaceAll(/(\\/_|_\\/)/gi, '/')\n}\n\nexport function capitalize(s: string) {\n if (typeof s !== 'string') return ''\n return s.charAt(0).toUpperCase() + s.slice(1)\n}\n\nexport function removeExt(d: string, keepExtension: boolean = false) {\n return keepExtension ? d : d.substring(0, d.lastIndexOf('.')) || d\n}\n\n/**\n * This function writes to a file if the content is different.\n *\n * @param filepath The path to the file\n * @param content Original content\n * @param incomingContent New content\n * @param callbacks Callbacks to run before and after writing\n * @returns Whether the file was written\n */\nexport async function writeIfDifferent(\n filepath: string,\n content: string,\n incomingContent: string,\n callbacks?: { beforeWrite?: () => void; afterWrite?: () => void },\n): Promise<boolean> {\n if (content !== incomingContent) {\n callbacks?.beforeWrite?.()\n await fsp.writeFile(filepath, incomingContent)\n callbacks?.afterWrite?.()\n return true\n }\n return false\n}\n\n/**\n * This function formats the source code using the default formatter (Prettier).\n *\n * @param source The content to format\n * @param config The configuration object\n * @returns The formatted content\n */\nexport async function format(\n source: string,\n config: {\n quoteStyle: 'single' | 'double'\n semicolons: boolean\n },\n): Promise<string> {\n const prettierOptions: prettier.Config = {\n semi: config.semicolons,\n singleQuote: config.quoteStyle === 'single',\n parser: 'typescript',\n }\n return prettier.format(source, prettierOptions)\n}\n\n/**\n * This function resets the regex index to 0 so that it can be reused\n * without having to create a new regex object or worry about the last\n * state when using the global flag.\n *\n * @param regex The regex object to reset\n * @returns\n */\nexport function resetRegex(regex: RegExp) {\n regex.lastIndex = 0\n return\n}\n\n/**\n * This function checks if a file exists.\n *\n * @param file The path to the file\n * @returns Whether the file exists\n */\nexport async function checkFileExists(file: string) {\n try {\n await fsp.access(file, fsp.constants.F_OK)\n return true\n } catch {\n return false\n }\n}\n\nconst possiblyNestedRouteGroupPatternRegex = /\\([^/]+\\)\\/?/g\nexport function removeGroups(s: string) {\n return s.replace(possiblyNestedRouteGroupPatternRegex, '')\n}\n\n/**\n * Removes all segments from a given path that start with an underscore ('_').\n *\n * @param {string} routePath - The path from which to remove segments. Defaults to '/'.\n * @returns {string} The path with all underscore-prefixed segments removed.\n * @example\n * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'\n */\nexport function removeLayoutSegments(routePath: string = '/'): string {\n const segments = routePath.split('/')\n const newSegments = segments.filter((segment) => !segment.startsWith('_'))\n return newSegments.join('/')\n}\n\n/**\n * The `node.path` is used as the `id` in the route definition.\n * This function checks if the given node has a parent and if so, it determines the correct path for the given node.\n * @param node - The node to determine the path for.\n * @returns The correct path for the given node.\n */\nexport function determineNodePath(node: RouteNode) {\n return (node.path = node.parent\n ? node.routePath?.replace(node.parent.routePath ?? '', '') || '/'\n : node.routePath)\n}\n\n/**\n * Removes the last segment from a given path. Segments are considered to be separated by a '/'.\n *\n * @param {string} routePath - The path from which to remove the last segment. Defaults to '/'.\n * @returns {string} The path with the last segment removed.\n * @example\n * removeLastSegmentFromPath('/workspace/_auth/foo') // '/workspace/_auth'\n */\nexport function removeLastSegmentFromPath(routePath: string = '/'): string {\n const segments = routePath.split('/')\n segments.pop() // Remove the last segment\n return segments.join('/')\n}\n\nexport function hasParentRoute(\n routes: Array<RouteNode>,\n node: RouteNode,\n routePathToCheck: string | undefined,\n): RouteNode | null {\n if (!routePathToCheck || routePathToCheck === '/') {\n return null\n }\n\n const sortedNodes = multiSortBy(routes, [\n (d) => d.routePath!.length * -1,\n (d) => d.variableName,\n ]).filter((d) => d.routePath !== `/${rootPathId}`)\n\n for (const route of sortedNodes) {\n if (route.routePath === '/') continue\n\n if (\n routePathToCheck.startsWith(`${route.routePath}/`) &&\n route.routePath !== routePathToCheck\n ) {\n return route\n }\n }\n\n const segments = routePathToCheck.split('/')\n segments.pop() // Remove the last segment\n const parentRoutePath = segments.join('/')\n\n return hasParentRoute(routes, node, parentRoutePath)\n}\n\n/**\n * Gets the final variable name for a route\n */\nexport const getResolvedRouteNodeVariableName = (\n routeNode: RouteNode,\n variableNameSuffix: string,\n): string => {\n return routeNode.children?.length\n ? `${routeNode.variableName}${variableNameSuffix}WithChildren`\n : `${routeNode.variableName}${variableNameSuffix}`\n}\n\n/**\n * Checks if a given RouteNode is valid for augmenting it with typing based on conditions.\n * Also asserts that the RouteNode is defined.\n *\n * @param routeNode - The RouteNode to check.\n * @returns A boolean indicating whether the RouteNode is defined.\n */\nexport function isRouteNodeValidForAugmentation(\n routeNode?: RouteNode,\n): routeNode is RouteNode {\n if (!routeNode || routeNode.isVirtual) {\n return false\n }\n return true\n}\n\n/**\n * Infers the path for use by TS\n */\nexport const inferPath = (routeNode: RouteNode): string => {\n return routeNode.cleanedPath === '/'\n ? routeNode.cleanedPath\n : (routeNode.cleanedPath?.replace(/\\/$/, '') ?? '')\n}\n\n/**\n * Infers the full path for use by TS\n */\nexport const inferFullPath = (routeNode: RouteNode): string => {\n const fullPath = removeGroups(\n removeUnderscores(removeLayoutSegments(routeNode.routePath)) ?? '',\n )\n\n return routeNode.cleanedPath === '/' ? fullPath : fullPath.replace(/\\/$/, '')\n}\n\n/**\n * Creates a map from fullPath to routeNode\n */\nexport const createRouteNodesByFullPath = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n routeNodes.map((routeNode) => [inferFullPath(routeNode), routeNode]),\n )\n}\n\n/**\n * Create a map from 'to' to a routeNode\n */\nexport const createRouteNodesByTo = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n dedupeBranchesAndIndexRoutes(routeNodes).map((routeNode) => [\n inferTo(routeNode),\n routeNode,\n ]),\n )\n}\n\n/**\n * Create a map from 'id' to a routeNode\n */\nexport const createRouteNodesById = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n routeNodes.map((routeNode) => {\n const id = routeNode.routePath ?? ''\n return [id, routeNode]\n }),\n )\n}\n\n/**\n * Infers to path\n */\nexport const inferTo = (routeNode: RouteNode): string => {\n const fullPath = inferFullPath(routeNode)\n\n if (fullPath === '/') return fullPath\n\n return fullPath.replace(/\\/$/, '')\n}\n\n/**\n * Dedupes branches and index routes\n */\nexport const dedupeBranchesAndIndexRoutes = (\n routes: Array<RouteNode>,\n): Array<RouteNode> => {\n return routes.filter((route) => {\n if (route.children?.find((child) => child.cleanedPath === '/')) return false\n return true\n })\n}\n\nfunction checkUnique<TElement>(routes: Array<TElement>, key: keyof TElement) {\n // Check no two routes have the same `key`\n // if they do, throw an error with the conflicting filePaths\n const keys = routes.map((d) => d[key])\n const uniqueKeys = new Set(keys)\n if (keys.length !== uniqueKeys.size) {\n const duplicateKeys = keys.filter((d, i) => keys.indexOf(d) !== i)\n const conflictingFiles = routes.filter((d) =>\n duplicateKeys.includes(d[key]),\n )\n return conflictingFiles\n }\n return undefined\n}\n\nexport function checkRouteFullPathUniqueness(\n _routes: Array<RouteNode>,\n config: Config,\n) {\n const routes = _routes.map((d) => {\n const inferredFullPath = inferFullPath(d)\n return { ...d, inferredFullPath }\n })\n\n const conflictingFiles = checkUnique(routes, 'inferredFullPath')\n\n if (conflictingFiles !== undefined) {\n const errorMessage = `Conflicting configuration paths were found for the following route${conflictingFiles.length > 1 ? 's' : ''}: ${conflictingFiles\n .map((p) => `\"${p.inferredFullPath}\"`)\n .join(', ')}.\nPlease ensure each Route has a unique full path.\nConflicting files: \\n ${conflictingFiles.map((d) => path.resolve(config.routesDirectory, d.filePath)).join('\\n ')}\\n`\n throw new Error(errorMessage)\n }\n}\n\nexport function buildRouteTreeConfig(\n nodes: Array<RouteNode>,\n exportName: string,\n disableTypes: boolean,\n depth = 1,\n): Array<string> {\n const children = nodes\n .filter((n) => n.exports?.includes(exportName))\n .map((node) => {\n if (node._fsRouteType === '__root') {\n return\n }\n\n if (node._fsRouteType === 'pathless_layout' && !node.children?.length) {\n return\n }\n\n const route = `${node.variableName}`\n\n if (node.children?.length) {\n const childConfigs = buildRouteTreeConfig(\n node.children,\n exportName,\n disableTypes,\n depth + 1,\n )\n\n const childrenDeclaration = disableTypes\n ? ''\n : `interface ${route}${exportName}Children {\n ${node.children\n .filter((n) => n.exports?.includes(exportName))\n .map(\n (child) =>\n `${child.variableName}${exportName}: typeof ${getResolvedRouteNodeVariableName(child, exportName)}`,\n )\n .join(',')}\n}`\n\n const children = `const ${route}${exportName}Children${disableTypes ? '' : `: ${route}${exportName}Children`} = {\n ${node.children\n .filter((n) => n.exports?.includes(exportName))\n .map(\n (child) =>\n `${child.variableName}${exportName}: ${getResolvedRouteNodeVariableName(child, exportName)}`,\n )\n .join(',')}\n}`\n\n const routeWithChildren = `const ${route}${exportName}WithChildren = ${route}${exportName}._addFileChildren(${route}${exportName}Children)`\n\n return [\n childConfigs.join('\\n'),\n childrenDeclaration,\n children,\n routeWithChildren,\n ].join('\\n\\n')\n }\n\n return undefined\n })\n\n return children.filter((x) => x !== undefined)\n}\n\nexport function buildImportString(\n importDeclaration: ImportDeclaration,\n): string {\n const { source, specifiers, importKind } = importDeclaration\n return specifiers.length\n ? `import ${importKind === 'type' ? 'type ' : ''}{ ${specifiers.map((s) => (s.local ? `${s.imported} as ${s.local}` : s.imported)).join(', ')} } from '${source}'`\n : ''\n}\n\nexport function lowerCaseFirstChar(value: string) {\n if (!value[0]) {\n return value\n }\n\n return value[0].toLowerCase() + value.slice(1)\n}\n\nexport function mergeImportDeclarations(\n imports: Array<ImportDeclaration>,\n): Array<ImportDeclaration> {\n const merged: Record<string, ImportDeclaration> = {}\n\n for (const imp of imports) {\n const key = `${imp.source}-${imp.importKind}`\n if (!merged[key]) {\n merged[key] = { ...imp, specifiers: [] }\n }\n for (const specifier of imp.specifiers) {\n // check if the specifier already exists in the merged import\n if (\n !merged[key].specifiers.some(\n (existing) =>\n existing.imported === specifier.imported &&\n existing.local === specifier.local,\n )\n ) {\n merged[key].specifiers.push(specifier)\n }\n }\n }\n\n return Object.values(merged)\n}\n\nexport function hasChildWithExport(\n node: RouteNode,\n exportName: string,\n): boolean {\n return (\n node.children?.some((child) => hasChildWithExport(child, exportName)) ??\n false\n )\n}\n\nexport const findParent = (\n node: RouteNode | undefined,\n exportName: string,\n): string => {\n if (!node) {\n return `root${exportName}Import`\n }\n if (node.parent) {\n if (node.parent.exports?.includes(exportName)) {\n if (node.isVirtualParentRequired) {\n return `${node.parent.variableName}${exportName}`\n } else {\n return `${node.parent.variableName}${exportName}`\n }\n }\n }\n return findParent(node.parent, exportName)\n}\n\nexport function buildFileRoutesByPathInterface(opts: {\n routeNodes: Array<RouteNode>\n module: string\n interfaceName: string\n exportName: string\n}): string {\n return `declare module '${opts.module}' {\n interface ${opts.interfaceName} {\n ${opts.routeNodes\n .map((routeNode) => {\n const filePathId = routeNode.routePath\n let preloaderRoute = ''\n\n if (routeNode.exports?.includes(opts.exportName)) {\n preloaderRoute = `typeof ${routeNode.variableName}${opts.exportName}Import`\n } else {\n preloaderRoute = 'unknown'\n }\n\n const parent = findParent(routeNode, opts.exportName)\n\n return `'${filePathId}': {\n id: '${filePathId}'\n path: '${inferPath(routeNode)}'\n fullPath: '${inferFullPath(routeNode)}'\n preLoaderRoute: ${preloaderRoute}\n parentRoute: typeof ${parent}\n }`\n })\n .join('\\n')}\n }\n}`\n}\n"],"names":["path","fsp","prettier","rootPathId","children"],"mappings":"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"}
1
+ {"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import * as fsp from 'node:fs/promises'\nimport path from 'node:path'\nimport * as prettier from 'prettier'\nimport { rootPathId } from './filesystem/physical/rootPathId'\nimport type { Config } from './config'\nimport type { ImportDeclaration, RouteNode } from './types'\n\nexport function multiSortBy<T>(\n arr: Array<T>,\n accessors: Array<(item: T) => any> = [(d) => d],\n): Array<T> {\n return arr\n .map((d, i) => [d, i] as const)\n .sort(([a, ai], [b, bi]) => {\n for (const accessor of accessors) {\n const ao = accessor(a)\n const bo = accessor(b)\n\n if (typeof ao === 'undefined') {\n if (typeof bo === 'undefined') {\n continue\n }\n return 1\n }\n\n if (ao === bo) {\n continue\n }\n\n return ao > bo ? 1 : -1\n }\n\n return ai - bi\n })\n .map(([d]) => d)\n}\n\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\nexport function removeLeadingSlash(path: string): string {\n return path.replace(/^\\//, '')\n}\n\nexport function removeTrailingSlash(s: string) {\n return s.replace(/\\/$/, '')\n}\n\nconst BRACKET_CONTENT_RE = /\\[(.*?)\\]/g\n\nexport function determineInitialRoutePath(routePath: string) {\n const DISALLOWED_ESCAPE_CHARS = new Set([\n '/',\n '\\\\',\n '?',\n '#',\n ':',\n '*',\n '<',\n '>',\n '|',\n '!',\n '$',\n '%',\n ])\n\n const parts = routePath.split(/(?<!\\[)\\.(?!\\])/g)\n\n // Escape any characters that in square brackets\n const escapedParts = parts.map((part) => {\n // Check if any disallowed characters are used in brackets\n\n let match\n while ((match = BRACKET_CONTENT_RE.exec(part)) !== null) {\n const character = match[1]\n if (character === undefined) continue\n if (DISALLOWED_ESCAPE_CHARS.has(character)) {\n console.error(\n `Error: Disallowed character \"${character}\" found in square brackets in route path \"${routePath}\".\\nYou cannot use any of the following characters in square brackets: ${Array.from(\n DISALLOWED_ESCAPE_CHARS,\n ).join(', ')}\\nPlease remove and/or replace them.`,\n )\n process.exit(1)\n }\n }\n\n // Since this split segment is safe at this point, we can\n // remove the brackets and replace them with the content inside\n return part.replace(BRACKET_CONTENT_RE, '$1')\n })\n\n // If the syntax for prefix/suffix is different, from the path\n // matching internals of router-core, we'd perform those changes here\n // on the `escapedParts` array before it is joined back together in\n // `final`\n\n const final = cleanPath(`/${escapedParts.join('/')}`) || ''\n\n return final\n}\n\nexport function replaceBackslash(s: string) {\n return s.replaceAll(/\\\\/gi, '/')\n}\n\nexport function routePathToVariable(routePath: string): string {\n const toVariableSafeChar = (char: string): string => {\n if (/[a-zA-Z0-9_]/.test(char)) {\n return char // Keep alphanumeric characters and underscores as is\n }\n\n // Replace special characters with meaningful text equivalents\n switch (char) {\n case '.':\n return 'Dot'\n case '-':\n return 'Dash'\n case '@':\n return 'At'\n case '(':\n return '' // Removed since route groups use parentheses\n case ')':\n return '' // Removed since route groups use parentheses\n case ' ':\n return '' // Remove spaces\n default:\n return `Char${char.charCodeAt(0)}` // For any other characters\n }\n }\n\n return (\n removeUnderscores(routePath)\n ?.replace(/\\/\\$\\//g, '/splat/')\n .replace(/\\$$/g, 'splat')\n .replace(/\\$\\{\\$\\}/g, 'splat')\n .replace(/\\$/g, '')\n .split(/[/-]/g)\n .map((d, i) => (i > 0 ? capitalize(d) : d))\n .join('')\n .split('')\n .map(toVariableSafeChar)\n .join('')\n // .replace(/([^a-zA-Z0-9]|[.])/gm, '')\n .replace(/^(\\d)/g, 'R$1') ?? ''\n )\n}\n\nexport function removeUnderscores(s?: string) {\n return s?.replaceAll(/(^_|_$)/gi, '').replaceAll(/(\\/_|_\\/)/gi, '/')\n}\n\nexport function capitalize(s: string) {\n if (typeof s !== 'string') return ''\n return s.charAt(0).toUpperCase() + s.slice(1)\n}\n\nexport function removeExt(d: string, keepExtension: boolean = false) {\n return keepExtension ? d : d.substring(0, d.lastIndexOf('.')) || d\n}\n\n/**\n * This function writes to a file if the content is different.\n *\n * @param filepath The path to the file\n * @param content Original content\n * @param incomingContent New content\n * @param callbacks Callbacks to run before and after writing\n * @returns Whether the file was written\n */\nexport async function writeIfDifferent(\n filepath: string,\n content: string,\n incomingContent: string,\n callbacks?: { beforeWrite?: () => void; afterWrite?: () => void },\n): Promise<boolean> {\n if (content !== incomingContent) {\n callbacks?.beforeWrite?.()\n await fsp.writeFile(filepath, incomingContent)\n callbacks?.afterWrite?.()\n return true\n }\n return false\n}\n\n/**\n * This function formats the source code using the default formatter (Prettier).\n *\n * @param source The content to format\n * @param config The configuration object\n * @returns The formatted content\n */\nexport async function format(\n source: string,\n config: {\n quoteStyle: 'single' | 'double'\n semicolons: boolean\n },\n): Promise<string> {\n const prettierOptions: prettier.Config = {\n semi: config.semicolons,\n singleQuote: config.quoteStyle === 'single',\n parser: 'typescript',\n }\n return prettier.format(source, prettierOptions)\n}\n\n/**\n * This function resets the regex index to 0 so that it can be reused\n * without having to create a new regex object or worry about the last\n * state when using the global flag.\n *\n * @param regex The regex object to reset\n * @returns\n */\nexport function resetRegex(regex: RegExp) {\n regex.lastIndex = 0\n return\n}\n\n/**\n * This function checks if a file exists.\n *\n * @param file The path to the file\n * @returns Whether the file exists\n */\nexport async function checkFileExists(file: string) {\n try {\n await fsp.access(file, fsp.constants.F_OK)\n return true\n } catch {\n return false\n }\n}\n\nconst possiblyNestedRouteGroupPatternRegex = /\\([^/]+\\)\\/?/g\nexport function removeGroups(s: string) {\n return s.replace(possiblyNestedRouteGroupPatternRegex, '')\n}\n\n/**\n * Removes all segments from a given path that start with an underscore ('_').\n *\n * @param {string} routePath - The path from which to remove segments. Defaults to '/'.\n * @returns {string} The path with all underscore-prefixed segments removed.\n * @example\n * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'\n */\nexport function removeLayoutSegments(routePath: string = '/'): string {\n const segments = routePath.split('/')\n const newSegments = segments.filter((segment) => !segment.startsWith('_'))\n return newSegments.join('/')\n}\n\n/**\n * The `node.path` is used as the `id` in the route definition.\n * This function checks if the given node has a parent and if so, it determines the correct path for the given node.\n * @param node - The node to determine the path for.\n * @returns The correct path for the given node.\n */\nexport function determineNodePath(node: RouteNode) {\n return (node.path = node.parent\n ? node.routePath?.replace(node.parent.routePath ?? '', '') || '/'\n : node.routePath)\n}\n\n/**\n * Removes the last segment from a given path. Segments are considered to be separated by a '/'.\n *\n * @param {string} routePath - The path from which to remove the last segment. Defaults to '/'.\n * @returns {string} The path with the last segment removed.\n * @example\n * removeLastSegmentFromPath('/workspace/_auth/foo') // '/workspace/_auth'\n */\nexport function removeLastSegmentFromPath(routePath: string = '/'): string {\n const segments = routePath.split('/')\n segments.pop() // Remove the last segment\n return segments.join('/')\n}\n\nexport function hasParentRoute(\n routes: Array<RouteNode>,\n node: RouteNode,\n routePathToCheck: string | undefined,\n): RouteNode | null {\n if (!routePathToCheck || routePathToCheck === '/') {\n return null\n }\n\n const sortedNodes = multiSortBy(routes, [\n (d) => d.routePath!.length * -1,\n (d) => d.variableName,\n ]).filter((d) => d.routePath !== `/${rootPathId}`)\n\n for (const route of sortedNodes) {\n if (route.routePath === '/') continue\n\n if (\n routePathToCheck.startsWith(`${route.routePath}/`) &&\n route.routePath !== routePathToCheck\n ) {\n return route\n }\n }\n\n const segments = routePathToCheck.split('/')\n segments.pop() // Remove the last segment\n const parentRoutePath = segments.join('/')\n\n return hasParentRoute(routes, node, parentRoutePath)\n}\n\n/**\n * Gets the final variable name for a route\n */\nexport const getResolvedRouteNodeVariableName = (\n routeNode: RouteNode,\n variableNameSuffix: string,\n): string => {\n return routeNode.children?.length\n ? `${routeNode.variableName}${variableNameSuffix}WithChildren`\n : `${routeNode.variableName}${variableNameSuffix}`\n}\n\n/**\n * Checks if a given RouteNode is valid for augmenting it with typing based on conditions.\n * Also asserts that the RouteNode is defined.\n *\n * @param routeNode - The RouteNode to check.\n * @returns A boolean indicating whether the RouteNode is defined.\n */\nexport function isRouteNodeValidForAugmentation(\n routeNode?: RouteNode,\n): routeNode is RouteNode {\n if (!routeNode || routeNode.isVirtual) {\n return false\n }\n return true\n}\n\n/**\n * Infers the path for use by TS\n */\nexport const inferPath = (routeNode: RouteNode): string => {\n return routeNode.cleanedPath === '/'\n ? routeNode.cleanedPath\n : (routeNode.cleanedPath?.replace(/\\/$/, '') ?? '')\n}\n\n/**\n * Infers the full path for use by TS\n */\nexport const inferFullPath = (routeNode: RouteNode): string => {\n const fullPath = removeGroups(\n removeUnderscores(removeLayoutSegments(routeNode.routePath)) ?? '',\n )\n\n return routeNode.cleanedPath === '/' ? fullPath : fullPath.replace(/\\/$/, '')\n}\n\n/**\n * Creates a map from fullPath to routeNode\n */\nexport const createRouteNodesByFullPath = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n routeNodes.map((routeNode) => [inferFullPath(routeNode), routeNode]),\n )\n}\n\n/**\n * Create a map from 'to' to a routeNode\n */\nexport const createRouteNodesByTo = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n dedupeBranchesAndIndexRoutes(routeNodes).map((routeNode) => [\n inferTo(routeNode),\n routeNode,\n ]),\n )\n}\n\n/**\n * Create a map from 'id' to a routeNode\n */\nexport const createRouteNodesById = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n routeNodes.map((routeNode) => {\n const id = routeNode.routePath ?? ''\n return [id, routeNode]\n }),\n )\n}\n\n/**\n * Infers to path\n */\nexport const inferTo = (routeNode: RouteNode): string => {\n const fullPath = inferFullPath(routeNode)\n\n if (fullPath === '/') return fullPath\n\n return fullPath.replace(/\\/$/, '')\n}\n\n/**\n * Dedupes branches and index routes\n */\nexport const dedupeBranchesAndIndexRoutes = (\n routes: Array<RouteNode>,\n): Array<RouteNode> => {\n return routes.filter((route) => {\n if (route.children?.find((child) => child.cleanedPath === '/')) return false\n return true\n })\n}\n\nfunction checkUnique<TElement>(routes: Array<TElement>, key: keyof TElement) {\n // Check no two routes have the same `key`\n // if they do, throw an error with the conflicting filePaths\n const keys = routes.map((d) => d[key])\n const uniqueKeys = new Set(keys)\n if (keys.length !== uniqueKeys.size) {\n const duplicateKeys = keys.filter((d, i) => keys.indexOf(d) !== i)\n const conflictingFiles = routes.filter((d) =>\n duplicateKeys.includes(d[key]),\n )\n return conflictingFiles\n }\n return undefined\n}\n\nexport function checkRouteFullPathUniqueness(\n _routes: Array<RouteNode>,\n config: Config,\n) {\n const routes = _routes.map((d) => {\n const inferredFullPath = inferFullPath(d)\n return { ...d, inferredFullPath }\n })\n\n const conflictingFiles = checkUnique(routes, 'inferredFullPath')\n\n if (conflictingFiles !== undefined) {\n const errorMessage = `Conflicting configuration paths were found for the following route${conflictingFiles.length > 1 ? 's' : ''}: ${conflictingFiles\n .map((p) => `\"${p.inferredFullPath}\"`)\n .join(', ')}.\nPlease ensure each Route has a unique full path.\nConflicting files: \\n ${conflictingFiles.map((d) => path.resolve(config.routesDirectory, d.filePath)).join('\\n ')}\\n`\n throw new Error(errorMessage)\n }\n}\n\nexport function buildRouteTreeConfig(\n nodes: Array<RouteNode>,\n exportName: string,\n disableTypes: boolean,\n depth = 1,\n): Array<string> {\n const children = nodes\n .filter((n) => n.exports?.includes(exportName))\n .map((node) => {\n if (node._fsRouteType === '__root') {\n return\n }\n\n if (node._fsRouteType === 'pathless_layout' && !node.children?.length) {\n return\n }\n\n const route = `${node.variableName}`\n\n if (node.children?.length) {\n const childConfigs = buildRouteTreeConfig(\n node.children,\n exportName,\n disableTypes,\n depth + 1,\n )\n\n const childrenDeclaration = disableTypes\n ? ''\n : `interface ${route}${exportName}Children {\n ${node.children\n .filter((n) => n.exports?.includes(exportName))\n .map(\n (child) =>\n `${child.variableName}${exportName}: typeof ${getResolvedRouteNodeVariableName(child, exportName)}`,\n )\n .join(',')}\n}`\n\n const children = `const ${route}${exportName}Children${disableTypes ? '' : `: ${route}${exportName}Children`} = {\n ${node.children\n .filter((n) => n.exports?.includes(exportName))\n .map(\n (child) =>\n `${child.variableName}${exportName}: ${getResolvedRouteNodeVariableName(child, exportName)}`,\n )\n .join(',')}\n}`\n\n const routeWithChildren = `const ${route}${exportName}WithChildren = ${route}${exportName}._addFileChildren(${route}${exportName}Children)`\n\n return [\n childConfigs.join('\\n'),\n childrenDeclaration,\n children,\n routeWithChildren,\n ].join('\\n\\n')\n }\n\n return undefined\n })\n\n return children.filter((x) => x !== undefined)\n}\n\nexport function buildImportString(\n importDeclaration: ImportDeclaration,\n): string {\n const { source, specifiers, importKind } = importDeclaration\n return specifiers.length\n ? `import ${importKind === 'type' ? 'type ' : ''}{ ${specifiers.map((s) => (s.local ? `${s.imported} as ${s.local}` : s.imported)).join(', ')} } from '${source}'`\n : ''\n}\n\nexport function lowerCaseFirstChar(value: string) {\n if (!value[0]) {\n return value\n }\n\n return value[0].toLowerCase() + value.slice(1)\n}\n\nexport function mergeImportDeclarations(\n imports: Array<ImportDeclaration>,\n): Array<ImportDeclaration> {\n const merged: Record<string, ImportDeclaration> = {}\n\n for (const imp of imports) {\n const key = `${imp.source}-${imp.importKind}`\n if (!merged[key]) {\n merged[key] = { ...imp, specifiers: [] }\n }\n for (const specifier of imp.specifiers) {\n // check if the specifier already exists in the merged import\n if (\n !merged[key].specifiers.some(\n (existing) =>\n existing.imported === specifier.imported &&\n existing.local === specifier.local,\n )\n ) {\n merged[key].specifiers.push(specifier)\n }\n }\n }\n\n return Object.values(merged)\n}\n\nexport function hasChildWithExport(\n node: RouteNode,\n exportName: string,\n): boolean {\n return (\n node.children?.some((child) => hasChildWithExport(child, exportName)) ??\n false\n )\n}\n\nexport const findParent = (\n node: RouteNode | undefined,\n exportName: string,\n): string => {\n if (!node) {\n return `root${exportName}Import`\n }\n if (node.parent) {\n if (node.parent.exports?.includes(exportName)) {\n if (node.isVirtualParentRequired) {\n return `${node.parent.variableName}${exportName}`\n } else {\n return `${node.parent.variableName}${exportName}`\n }\n }\n }\n return findParent(node.parent, exportName)\n}\n\nexport function buildFileRoutesByPathInterface(opts: {\n routeNodes: Array<RouteNode>\n module: string\n interfaceName: string\n exportName: string\n}): string {\n return `declare module '${opts.module}' {\n interface ${opts.interfaceName} {\n ${opts.routeNodes\n .map((routeNode) => {\n const filePathId = routeNode.routePath\n let preloaderRoute = ''\n\n if (routeNode.exports?.includes(opts.exportName)) {\n preloaderRoute = `typeof ${routeNode.variableName}${opts.exportName}Import`\n } else {\n preloaderRoute = 'unknown'\n }\n\n const parent = findParent(routeNode, opts.exportName)\n\n return `'${filePathId}': {\n id: '${filePathId}'\n path: '${inferPath(routeNode)}'\n fullPath: '${inferFullPath(routeNode)}'\n preLoaderRoute: ${preloaderRoute}\n parentRoute: typeof ${parent}\n }`\n })\n .join('\\n')}\n }\n}`\n}\n"],"names":["path","fsp","prettier","rootPathId","children"],"mappings":"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"}
@@ -61,6 +61,7 @@ export declare class Generator {
61
61
  root: string;
62
62
  fs?: fs;
63
63
  });
64
+ private getGeneratedRouteTreePath;
64
65
  private getRoutesDirectoryPath;
65
66
  getRoutesByFileMap(): GetRoutesByFileMapResult;
66
67
  run(event?: GeneratorEvent): Promise<void>;
@@ -1,6 +1,6 @@
1
1
  import path from "node:path";
2
2
  import * as fsp from "node:fs/promises";
3
- import { mkdirSync } from "node:fs";
3
+ import { existsSync, mkdirSync } from "node:fs";
4
4
  import crypto from "node:crypto";
5
5
  import { deepEqual, rootRouteId } from "@tanstack/router-core";
6
6
  import { logging } from "./logger.js";
@@ -63,7 +63,7 @@ class Generator {
63
63
  this.logger = logging({ disabled: this.config.disableLogging });
64
64
  this.root = opts.root;
65
65
  this.fs = opts.fs || DefaultFileSystem;
66
- this.generatedRouteTreePath = path.resolve(this.config.generatedRouteTree);
66
+ this.generatedRouteTreePath = this.getGeneratedRouteTreePath();
67
67
  this.targetTemplate = getTargetTemplate(this.config);
68
68
  this.routesDirectoryPath = this.getRoutesDirectoryPath();
69
69
  this.plugins.push(...opts.config.plugins || []);
@@ -79,6 +79,16 @@ class Generator {
79
79
  }
80
80
  });
81
81
  }
82
+ getGeneratedRouteTreePath() {
83
+ const generatedRouteTreePath = path.isAbsolute(
84
+ this.config.generatedRouteTree
85
+ ) ? this.config.generatedRouteTree : path.resolve(this.root, this.config.generatedRouteTree);
86
+ const generatedRouteTreeDir = path.dirname(generatedRouteTreePath);
87
+ if (!existsSync(generatedRouteTreeDir)) {
88
+ mkdirSync(generatedRouteTreeDir, { recursive: true });
89
+ }
90
+ return generatedRouteTreePath;
91
+ }
82
92
  getRoutesDirectoryPath() {
83
93
  return path.isAbsolute(this.config.routesDirectory) ? this.config.routesDirectory : path.resolve(this.root, this.config.routesDirectory);
84
94
  }