@tanstack/router-generator 1.147.1 → 1.149.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/cjs/config.cjs +29 -6
  2. package/dist/cjs/config.cjs.map +1 -1
  3. package/dist/cjs/config.d.cts +94 -12
  4. package/dist/cjs/filesystem/physical/getRouteNodes.cjs +50 -27
  5. package/dist/cjs/filesystem/physical/getRouteNodes.cjs.map +1 -1
  6. package/dist/cjs/filesystem/physical/getRouteNodes.d.cts +12 -3
  7. package/dist/cjs/filesystem/virtual/getRouteNodes.cjs +12 -5
  8. package/dist/cjs/filesystem/virtual/getRouteNodes.cjs.map +1 -1
  9. package/dist/cjs/filesystem/virtual/getRouteNodes.d.cts +3 -2
  10. package/dist/cjs/generator.cjs +32 -7
  11. package/dist/cjs/generator.cjs.map +1 -1
  12. package/dist/cjs/generator.d.cts +20 -2
  13. package/dist/cjs/utils.cjs +47 -0
  14. package/dist/cjs/utils.cjs.map +1 -1
  15. package/dist/cjs/utils.d.cts +6 -1
  16. package/dist/esm/config.d.ts +94 -12
  17. package/dist/esm/config.js +29 -6
  18. package/dist/esm/config.js.map +1 -1
  19. package/dist/esm/filesystem/physical/getRouteNodes.d.ts +12 -3
  20. package/dist/esm/filesystem/physical/getRouteNodes.js +51 -28
  21. package/dist/esm/filesystem/physical/getRouteNodes.js.map +1 -1
  22. package/dist/esm/filesystem/virtual/getRouteNodes.d.ts +3 -2
  23. package/dist/esm/filesystem/virtual/getRouteNodes.js +12 -5
  24. package/dist/esm/filesystem/virtual/getRouteNodes.js.map +1 -1
  25. package/dist/esm/generator.d.ts +20 -2
  26. package/dist/esm/generator.js +33 -8
  27. package/dist/esm/generator.js.map +1 -1
  28. package/dist/esm/utils.d.ts +6 -1
  29. package/dist/esm/utils.js +47 -0
  30. package/dist/esm/utils.js.map +1 -1
  31. package/package.json +2 -2
  32. package/src/config.ts +58 -6
  33. package/src/filesystem/physical/getRouteNodes.ts +105 -43
  34. package/src/filesystem/virtual/getRouteNodes.ts +12 -2
  35. package/src/generator.ts +59 -9
  36. package/src/utils.ts +73 -1
@@ -22,7 +22,7 @@ function flattenTree(node) {
22
22
  delete node.children;
23
23
  return result;
24
24
  }
25
- async function getRouteNodes(tsrConfig, root) {
25
+ async function getRouteNodes(tsrConfig, root, tokenRegexes) {
26
26
  const fullDir = path.resolve(tsrConfig.routesDirectory);
27
27
  if (tsrConfig.virtualRouteConfig === void 0) {
28
28
  throw new Error(`virtualRouteConfig is undefined`);
@@ -40,7 +40,8 @@ async function getRouteNodes(tsrConfig, root) {
40
40
  tsrConfig,
41
41
  root,
42
42
  fullDir,
43
- virtualRouteConfig.children
43
+ virtualRouteConfig.children,
44
+ tokenRegexes
44
45
  );
45
46
  const allNodes = flattenTree({
46
47
  children,
@@ -67,7 +68,7 @@ async function getVirtualRouteConfigFromFileExport(tsrConfig, root) {
67
68
  const virtualRouteConfig = "routes" in exports2 ? exports2.routes : exports2.default;
68
69
  return config.virtualRootRouteSchema.parse(virtualRouteConfig);
69
70
  }
70
- async function getRouteNodesRecursive(tsrConfig, root, fullDir, nodes, parent) {
71
+ async function getRouteNodesRecursive(tsrConfig, root, fullDir, nodes, tokenRegexes, parent) {
71
72
  if (nodes === void 0) {
72
73
  return { children: [], physicalDirectories: [] };
73
74
  }
@@ -80,9 +81,13 @@ async function getRouteNodesRecursive(tsrConfig, root, fullDir, nodes, parent) {
80
81
  ...tsrConfig,
81
82
  routesDirectory: path.resolve(fullDir, node.directory)
82
83
  },
83
- root
84
+ root,
85
+ tokenRegexes
86
+ );
87
+ allPhysicalDirectories.push(
88
+ path.resolve(fullDir, node.directory),
89
+ ...physicalDirectories
84
90
  );
85
- allPhysicalDirectories.push(node.directory);
86
91
  routeNodes.forEach((subtreeNode) => {
87
92
  subtreeNode.variableName = utils.routePathToVariable(
88
93
  `${node.pathPrefix}/${utils.removeExt(subtreeNode.filePath)}`
@@ -150,6 +155,7 @@ async function getRouteNodesRecursive(tsrConfig, root, fullDir, nodes, parent) {
150
155
  root,
151
156
  fullDir,
152
157
  node.children,
158
+ tokenRegexes,
153
159
  routeNode
154
160
  );
155
161
  routeNode.children = children2;
@@ -188,6 +194,7 @@ async function getRouteNodesRecursive(tsrConfig, root, fullDir, nodes, parent) {
188
194
  root,
189
195
  fullDir,
190
196
  node.children,
197
+ tokenRegexes,
191
198
  routeNode
192
199
  );
193
200
  routeNode.children = children2;
@@ -1 +1 @@
1
- {"version":3,"file":"getRouteNodes.cjs","sources":["../../../../src/filesystem/virtual/getRouteNodes.ts"],"sourcesContent":["import path, { join, resolve } from 'node:path'\nimport {\n determineInitialRoutePath,\n removeExt,\n removeLeadingSlash,\n removeTrailingSlash,\n replaceBackslash,\n routePathToVariable,\n} from '../../utils'\nimport { getRouteNodes as getRouteNodesPhysical } from '../physical/getRouteNodes'\nimport { rootPathId } from '../physical/rootPathId'\nimport { virtualRootRouteSchema } from './config'\nimport { loadConfigFile } from './loadConfigFile'\nimport type {\n VirtualRootRoute,\n VirtualRouteNode,\n} from '@tanstack/virtual-file-routes'\nimport type { GetRouteNodesResult, RouteNode } from '../../types'\nimport type { Config } from '../../config'\n\nfunction ensureLeadingUnderScore(id: string) {\n if (id.startsWith('_')) {\n return id\n }\n return `_${id}`\n}\n\nfunction flattenTree(node: RouteNode): Array<RouteNode> {\n const result = [node]\n\n if (node.children) {\n for (const child of node.children) {\n result.push(...flattenTree(child))\n }\n }\n delete node.children\n\n return result\n}\n\nexport async function getRouteNodes(\n tsrConfig: Pick<\n Config,\n | 'routesDirectory'\n | 'virtualRouteConfig'\n | 'routeFileIgnorePrefix'\n | 'disableLogging'\n | 'indexToken'\n | 'routeToken'\n >,\n root: string,\n): Promise<GetRouteNodesResult> {\n const fullDir = resolve(tsrConfig.routesDirectory)\n if (tsrConfig.virtualRouteConfig === undefined) {\n throw new Error(`virtualRouteConfig is undefined`)\n }\n let virtualRouteConfig: VirtualRootRoute\n if (typeof tsrConfig.virtualRouteConfig === 'string') {\n virtualRouteConfig = await getVirtualRouteConfigFromFileExport(\n tsrConfig,\n root,\n )\n } else {\n virtualRouteConfig = tsrConfig.virtualRouteConfig\n }\n const { children, physicalDirectories } = await getRouteNodesRecursive(\n tsrConfig,\n root,\n fullDir,\n virtualRouteConfig.children,\n )\n const allNodes = flattenTree({\n children,\n filePath: virtualRouteConfig.file,\n fullPath: replaceBackslash(join(fullDir, virtualRouteConfig.file)),\n variableName: 'root',\n routePath: `/${rootPathId}`,\n _fsRouteType: '__root',\n })\n\n const rootRouteNode = allNodes[0]\n const routeNodes = allNodes.slice(1)\n\n return { rootRouteNode, routeNodes, physicalDirectories }\n}\n\n/**\n * Get the virtual route config from a file export\n *\n * @example\n * ```ts\n * // routes.ts\n * import { rootRoute } from '@tanstack/virtual-file-routes'\n *\n * export const routes = rootRoute({ ... })\n * // or\n * export default rootRoute({ ... })\n * ```\n *\n */\nasync function getVirtualRouteConfigFromFileExport(\n tsrConfig: Pick<Config, 'virtualRouteConfig'>,\n root: string,\n): Promise<VirtualRootRoute> {\n if (\n tsrConfig.virtualRouteConfig === undefined ||\n typeof tsrConfig.virtualRouteConfig !== 'string' ||\n tsrConfig.virtualRouteConfig === ''\n ) {\n throw new Error(`virtualRouteConfig is undefined or empty`)\n }\n const exports = await loadConfigFile(join(root, tsrConfig.virtualRouteConfig))\n\n if (!('routes' in exports) && !('default' in exports)) {\n throw new Error(\n `routes not found in ${tsrConfig.virtualRouteConfig}. The routes export must be named like 'export const routes = ...' or done using 'export default ...'`,\n )\n }\n\n const virtualRouteConfig =\n 'routes' in exports ? exports.routes : exports.default\n\n return virtualRootRouteSchema.parse(virtualRouteConfig)\n}\n\nexport async function getRouteNodesRecursive(\n tsrConfig: Pick<\n Config,\n | 'routesDirectory'\n | 'routeFileIgnorePrefix'\n | 'disableLogging'\n | 'indexToken'\n | 'routeToken'\n >,\n root: string,\n fullDir: string,\n nodes?: Array<VirtualRouteNode>,\n parent?: RouteNode,\n): Promise<{ children: Array<RouteNode>; physicalDirectories: Array<string> }> {\n if (nodes === undefined) {\n return { children: [], physicalDirectories: [] }\n }\n const allPhysicalDirectories: Array<string> = []\n const children = await Promise.all(\n nodes.map(async (node) => {\n if (node.type === 'physical') {\n const { routeNodes, physicalDirectories } = await getRouteNodesPhysical(\n {\n ...tsrConfig,\n routesDirectory: resolve(fullDir, node.directory),\n },\n root,\n )\n allPhysicalDirectories.push(node.directory)\n routeNodes.forEach((subtreeNode) => {\n subtreeNode.variableName = routePathToVariable(\n `${node.pathPrefix}/${removeExt(subtreeNode.filePath)}`,\n )\n subtreeNode.routePath = `${parent?.routePath ?? ''}${node.pathPrefix}${subtreeNode.routePath}`\n // Keep originalRoutePath aligned with routePath for escape detection\n if (subtreeNode.originalRoutePath) {\n subtreeNode.originalRoutePath = `${parent?.routePath ?? ''}${node.pathPrefix}${subtreeNode.originalRoutePath}`\n }\n subtreeNode.filePath = `${node.directory}/${subtreeNode.filePath}`\n })\n return routeNodes\n }\n\n function getFile(file: string) {\n const filePath = file\n const variableName = routePathToVariable(removeExt(filePath))\n const fullPath = replaceBackslash(join(fullDir, filePath))\n return { filePath, variableName, fullPath }\n }\n const parentRoutePath = removeTrailingSlash(parent?.routePath ?? '/')\n\n switch (node.type) {\n case 'index': {\n const { filePath, variableName, fullPath } = getFile(node.file)\n const routePath = `${parentRoutePath}/`\n return {\n filePath,\n fullPath,\n variableName,\n routePath,\n _fsRouteType: 'static',\n } satisfies RouteNode\n }\n\n case 'route': {\n const lastSegment = node.path\n let routeNode: RouteNode\n\n // Process the segment to handle escape sequences like [_]\n const {\n routePath: escapedSegment,\n originalRoutePath: originalSegment,\n } = determineInitialRoutePath(removeLeadingSlash(lastSegment))\n const routePath = `${parentRoutePath}${escapedSegment}`\n // Store the original path with brackets for escape detection\n const originalRoutePath = `${parentRoutePath}${originalSegment}`\n\n if (node.file) {\n const { filePath, variableName, fullPath } = getFile(node.file)\n routeNode = {\n filePath,\n fullPath,\n variableName,\n routePath,\n originalRoutePath,\n _fsRouteType: 'static',\n }\n } else {\n routeNode = {\n filePath: '',\n fullPath: '',\n variableName: routePathToVariable(routePath),\n routePath,\n originalRoutePath,\n isVirtual: true,\n _fsRouteType: 'static',\n }\n }\n\n if (node.children !== undefined) {\n const { children, physicalDirectories } =\n await getRouteNodesRecursive(\n tsrConfig,\n root,\n fullDir,\n node.children,\n routeNode,\n )\n routeNode.children = children\n allPhysicalDirectories.push(...physicalDirectories)\n\n // If the route has children, it should be a layout\n routeNode._fsRouteType = 'layout'\n }\n return routeNode\n }\n case 'layout': {\n const { filePath, variableName, fullPath } = getFile(node.file)\n\n if (node.id !== undefined) {\n node.id = ensureLeadingUnderScore(node.id)\n } else {\n const baseName = path.basename(filePath)\n const fileNameWithoutExt = path.parse(baseName).name\n node.id = ensureLeadingUnderScore(fileNameWithoutExt)\n }\n const lastSegment = node.id\n // Process the segment to handle escape sequences like [_]\n const {\n routePath: escapedSegment,\n originalRoutePath: originalSegment,\n } = determineInitialRoutePath(removeLeadingSlash(lastSegment))\n const routePath = `${parentRoutePath}${escapedSegment}`\n // Store the original path with brackets for escape detection\n const originalRoutePath = `${parentRoutePath}${originalSegment}`\n\n const routeNode: RouteNode = {\n fullPath,\n filePath,\n variableName,\n routePath,\n originalRoutePath,\n _fsRouteType: 'pathless_layout',\n }\n\n if (node.children !== undefined) {\n const { children, physicalDirectories } =\n await getRouteNodesRecursive(\n tsrConfig,\n root,\n fullDir,\n node.children,\n routeNode,\n )\n routeNode.children = children\n allPhysicalDirectories.push(...physicalDirectories)\n }\n return routeNode\n }\n }\n }),\n )\n return {\n children: children.flat(),\n physicalDirectories: allPhysicalDirectories,\n }\n}\n"],"names":["resolve","replaceBackslash","join","rootPathId","exports","loadConfigFile","virtualRootRouteSchema","getRouteNodesPhysical","routePathToVariable","removeExt","removeTrailingSlash","determineInitialRoutePath","removeLeadingSlash","children"],"mappings":"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"}
1
+ {"version":3,"file":"getRouteNodes.cjs","sources":["../../../../src/filesystem/virtual/getRouteNodes.ts"],"sourcesContent":["import path, { join, resolve } from 'node:path'\nimport {\n determineInitialRoutePath,\n removeExt,\n removeLeadingSlash,\n removeTrailingSlash,\n replaceBackslash,\n routePathToVariable,\n} from '../../utils'\nimport { getRouteNodes as getRouteNodesPhysical } from '../physical/getRouteNodes'\nimport { rootPathId } from '../physical/rootPathId'\nimport { virtualRootRouteSchema } from './config'\nimport { loadConfigFile } from './loadConfigFile'\nimport type {\n VirtualRootRoute,\n VirtualRouteNode,\n} from '@tanstack/virtual-file-routes'\nimport type { GetRouteNodesResult, RouteNode } from '../../types'\nimport type { Config } from '../../config'\nimport type { TokenRegexBundle } from '../physical/getRouteNodes'\n\nfunction ensureLeadingUnderScore(id: string) {\n if (id.startsWith('_')) {\n return id\n }\n return `_${id}`\n}\n\nfunction flattenTree(node: RouteNode): Array<RouteNode> {\n const result = [node]\n\n if (node.children) {\n for (const child of node.children) {\n result.push(...flattenTree(child))\n }\n }\n delete node.children\n\n return result\n}\n\nexport async function getRouteNodes(\n tsrConfig: Pick<\n Config,\n | 'routesDirectory'\n | 'virtualRouteConfig'\n | 'routeFileIgnorePrefix'\n | 'disableLogging'\n | 'indexToken'\n | 'routeToken'\n >,\n root: string,\n tokenRegexes: TokenRegexBundle,\n): Promise<GetRouteNodesResult> {\n const fullDir = resolve(tsrConfig.routesDirectory)\n if (tsrConfig.virtualRouteConfig === undefined) {\n throw new Error(`virtualRouteConfig is undefined`)\n }\n let virtualRouteConfig: VirtualRootRoute\n if (typeof tsrConfig.virtualRouteConfig === 'string') {\n virtualRouteConfig = await getVirtualRouteConfigFromFileExport(\n tsrConfig,\n root,\n )\n } else {\n virtualRouteConfig = tsrConfig.virtualRouteConfig\n }\n const { children, physicalDirectories } = await getRouteNodesRecursive(\n tsrConfig,\n root,\n fullDir,\n virtualRouteConfig.children,\n tokenRegexes,\n )\n const allNodes = flattenTree({\n children,\n filePath: virtualRouteConfig.file,\n fullPath: replaceBackslash(join(fullDir, virtualRouteConfig.file)),\n variableName: 'root',\n routePath: `/${rootPathId}`,\n _fsRouteType: '__root',\n })\n\n const rootRouteNode = allNodes[0]\n const routeNodes = allNodes.slice(1)\n\n return { rootRouteNode, routeNodes, physicalDirectories }\n}\n\n/**\n * Get the virtual route config from a file export\n *\n * @example\n * ```ts\n * // routes.ts\n * import { rootRoute } from '@tanstack/virtual-file-routes'\n *\n * export const routes = rootRoute({ ... })\n * // or\n * export default rootRoute({ ... })\n * ```\n *\n */\nasync function getVirtualRouteConfigFromFileExport(\n tsrConfig: Pick<Config, 'virtualRouteConfig'>,\n root: string,\n): Promise<VirtualRootRoute> {\n if (\n tsrConfig.virtualRouteConfig === undefined ||\n typeof tsrConfig.virtualRouteConfig !== 'string' ||\n tsrConfig.virtualRouteConfig === ''\n ) {\n throw new Error(`virtualRouteConfig is undefined or empty`)\n }\n const exports = await loadConfigFile(join(root, tsrConfig.virtualRouteConfig))\n\n if (!('routes' in exports) && !('default' in exports)) {\n throw new Error(\n `routes not found in ${tsrConfig.virtualRouteConfig}. The routes export must be named like 'export const routes = ...' or done using 'export default ...'`,\n )\n }\n\n const virtualRouteConfig =\n 'routes' in exports ? exports.routes : exports.default\n\n return virtualRootRouteSchema.parse(virtualRouteConfig)\n}\n\nexport async function getRouteNodesRecursive(\n tsrConfig: Pick<\n Config,\n | 'routesDirectory'\n | 'routeFileIgnorePrefix'\n | 'disableLogging'\n | 'indexToken'\n | 'routeToken'\n >,\n root: string,\n fullDir: string,\n nodes: Array<VirtualRouteNode> | undefined,\n tokenRegexes: TokenRegexBundle,\n parent?: RouteNode,\n): Promise<{ children: Array<RouteNode>; physicalDirectories: Array<string> }> {\n if (nodes === undefined) {\n return { children: [], physicalDirectories: [] }\n }\n const allPhysicalDirectories: Array<string> = []\n const children = await Promise.all(\n nodes.map(async (node) => {\n if (node.type === 'physical') {\n const { routeNodes, physicalDirectories } = await getRouteNodesPhysical(\n {\n ...tsrConfig,\n routesDirectory: resolve(fullDir, node.directory),\n },\n root,\n tokenRegexes,\n )\n allPhysicalDirectories.push(\n resolve(fullDir, node.directory),\n ...physicalDirectories,\n )\n routeNodes.forEach((subtreeNode) => {\n subtreeNode.variableName = routePathToVariable(\n `${node.pathPrefix}/${removeExt(subtreeNode.filePath)}`,\n )\n subtreeNode.routePath = `${parent?.routePath ?? ''}${node.pathPrefix}${subtreeNode.routePath}`\n // Keep originalRoutePath aligned with routePath for escape detection\n if (subtreeNode.originalRoutePath) {\n subtreeNode.originalRoutePath = `${parent?.routePath ?? ''}${node.pathPrefix}${subtreeNode.originalRoutePath}`\n }\n subtreeNode.filePath = `${node.directory}/${subtreeNode.filePath}`\n })\n return routeNodes\n }\n\n function getFile(file: string) {\n const filePath = file\n const variableName = routePathToVariable(removeExt(filePath))\n const fullPath = replaceBackslash(join(fullDir, filePath))\n return { filePath, variableName, fullPath }\n }\n const parentRoutePath = removeTrailingSlash(parent?.routePath ?? '/')\n\n switch (node.type) {\n case 'index': {\n const { filePath, variableName, fullPath } = getFile(node.file)\n const routePath = `${parentRoutePath}/`\n return {\n filePath,\n fullPath,\n variableName,\n routePath,\n _fsRouteType: 'static',\n } satisfies RouteNode\n }\n\n case 'route': {\n const lastSegment = node.path\n let routeNode: RouteNode\n\n // Process the segment to handle escape sequences like [_]\n const {\n routePath: escapedSegment,\n originalRoutePath: originalSegment,\n } = determineInitialRoutePath(removeLeadingSlash(lastSegment))\n const routePath = `${parentRoutePath}${escapedSegment}`\n // Store the original path with brackets for escape detection\n const originalRoutePath = `${parentRoutePath}${originalSegment}`\n\n if (node.file) {\n const { filePath, variableName, fullPath } = getFile(node.file)\n routeNode = {\n filePath,\n fullPath,\n variableName,\n routePath,\n originalRoutePath,\n _fsRouteType: 'static',\n }\n } else {\n routeNode = {\n filePath: '',\n fullPath: '',\n variableName: routePathToVariable(routePath),\n routePath,\n originalRoutePath,\n isVirtual: true,\n _fsRouteType: 'static',\n }\n }\n\n if (node.children !== undefined) {\n const { children, physicalDirectories } =\n await getRouteNodesRecursive(\n tsrConfig,\n root,\n fullDir,\n node.children,\n tokenRegexes,\n routeNode,\n )\n routeNode.children = children\n allPhysicalDirectories.push(...physicalDirectories)\n\n // If the route has children, it should be a layout\n routeNode._fsRouteType = 'layout'\n }\n return routeNode\n }\n case 'layout': {\n const { filePath, variableName, fullPath } = getFile(node.file)\n\n if (node.id !== undefined) {\n node.id = ensureLeadingUnderScore(node.id)\n } else {\n const baseName = path.basename(filePath)\n const fileNameWithoutExt = path.parse(baseName).name\n node.id = ensureLeadingUnderScore(fileNameWithoutExt)\n }\n const lastSegment = node.id\n // Process the segment to handle escape sequences like [_]\n const {\n routePath: escapedSegment,\n originalRoutePath: originalSegment,\n } = determineInitialRoutePath(removeLeadingSlash(lastSegment))\n const routePath = `${parentRoutePath}${escapedSegment}`\n // Store the original path with brackets for escape detection\n const originalRoutePath = `${parentRoutePath}${originalSegment}`\n\n const routeNode: RouteNode = {\n fullPath,\n filePath,\n variableName,\n routePath,\n originalRoutePath,\n _fsRouteType: 'pathless_layout',\n }\n\n if (node.children !== undefined) {\n const { children, physicalDirectories } =\n await getRouteNodesRecursive(\n tsrConfig,\n root,\n fullDir,\n node.children,\n tokenRegexes,\n routeNode,\n )\n routeNode.children = children\n allPhysicalDirectories.push(...physicalDirectories)\n }\n return routeNode\n }\n }\n }),\n )\n return {\n children: children.flat(),\n physicalDirectories: allPhysicalDirectories,\n }\n}\n"],"names":["resolve","replaceBackslash","join","rootPathId","exports","loadConfigFile","virtualRootRouteSchema","getRouteNodesPhysical","routePathToVariable","removeExt","removeTrailingSlash","determineInitialRoutePath","removeLeadingSlash","children"],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  import { VirtualRouteNode } from '@tanstack/virtual-file-routes';
2
2
  import { GetRouteNodesResult, RouteNode } from '../../types.cjs';
3
3
  import { Config } from '../../config.cjs';
4
- export declare function getRouteNodes(tsrConfig: Pick<Config, 'routesDirectory' | 'virtualRouteConfig' | 'routeFileIgnorePrefix' | 'disableLogging' | 'indexToken' | 'routeToken'>, root: string): Promise<GetRouteNodesResult>;
5
- export declare function getRouteNodesRecursive(tsrConfig: Pick<Config, 'routesDirectory' | 'routeFileIgnorePrefix' | 'disableLogging' | 'indexToken' | 'routeToken'>, root: string, fullDir: string, nodes?: Array<VirtualRouteNode>, parent?: RouteNode): Promise<{
4
+ import { TokenRegexBundle } from '../physical/getRouteNodes.cjs';
5
+ export declare function getRouteNodes(tsrConfig: Pick<Config, 'routesDirectory' | 'virtualRouteConfig' | 'routeFileIgnorePrefix' | 'disableLogging' | 'indexToken' | 'routeToken'>, root: string, tokenRegexes: TokenRegexBundle): Promise<GetRouteNodesResult>;
6
+ export declare function getRouteNodesRecursive(tsrConfig: Pick<Config, 'routesDirectory' | 'routeFileIgnorePrefix' | 'disableLogging' | 'indexToken' | 'routeToken'>, root: string, fullDir: string, nodes: Array<VirtualRouteNode> | undefined, tokenRegexes: TokenRegexBundle, parent?: RouteNode): Promise<{
6
7
  children: Array<RouteNode>;
7
8
  physicalDirectories: Array<string>;
8
9
  }>;
@@ -82,8 +82,18 @@ const _Generator = class _Generator {
82
82
  this.targetTemplate = template.getTargetTemplate(this.config);
83
83
  this.routesDirectoryPath = this.getRoutesDirectoryPath();
84
84
  this.plugins.push(...opts.config.plugins || []);
85
- this.indexTokenRegex = new RegExp(`[./]${this.config.indexToken}[.]`);
86
- this.routeTokenRegex = new RegExp(`[./]${this.config.routeToken}[.]`);
85
+ this.indexTokenFilenameRegex = utils.createTokenRegex(this.config.indexToken, {
86
+ type: "filename"
87
+ });
88
+ this.routeTokenFilenameRegex = utils.createTokenRegex(this.config.routeToken, {
89
+ type: "filename"
90
+ });
91
+ this.indexTokenSegmentRegex = utils.createTokenRegex(this.config.indexToken, {
92
+ type: "segment"
93
+ });
94
+ this.routeTokenSegmentRegex = utils.createTokenRegex(this.config.routeToken, {
95
+ type: "segment"
96
+ });
87
97
  for (const plugin of this.plugins) {
88
98
  plugin.init?.({ generator: this });
89
99
  }
@@ -173,9 +183,19 @@ const _Generator = class _Generator {
173
183
  let writeRouteTreeFile = false;
174
184
  let getRouteNodesResult;
175
185
  if (this.config.virtualRouteConfig) {
176
- getRouteNodesResult = await getRouteNodes.getRouteNodes(this.config, this.root);
186
+ getRouteNodesResult = await getRouteNodes.getRouteNodes(this.config, this.root, {
187
+ indexTokenSegmentRegex: this.indexTokenSegmentRegex,
188
+ routeTokenSegmentRegex: this.routeTokenSegmentRegex
189
+ });
177
190
  } else {
178
- getRouteNodesResult = await getRouteNodes$1.getRouteNodes(this.config, this.root);
191
+ getRouteNodesResult = await getRouteNodes$1.getRouteNodes(
192
+ this.config,
193
+ this.root,
194
+ {
195
+ indexTokenSegmentRegex: this.indexTokenSegmentRegex,
196
+ routeTokenSegmentRegex: this.routeTokenSegmentRegex
197
+ }
198
+ );
179
199
  }
180
200
  const {
181
201
  rootRouteNode,
@@ -196,9 +216,9 @@ Add the file in: "${this.config.routesDirectory}/${rootPathId.rootPathId}.${this
196
216
  const preRouteNodes = utils.multiSortBy(beforeRouteNodes, [
197
217
  (d) => d.routePath === "/" ? -1 : 1,
198
218
  (d) => d.routePath?.split("/").length,
199
- (d) => d.filePath.match(this.indexTokenRegex) ? 1 : -1,
219
+ (d) => d.filePath.match(this.indexTokenFilenameRegex) ? 1 : -1,
200
220
  (d) => d.filePath.match(_Generator.componentPieceRegex) ? 1 : -1,
201
- (d) => d.filePath.match(this.routeTokenRegex) ? -1 : 1,
221
+ (d) => d.filePath.match(this.routeTokenFilenameRegex) ? -1 : 1,
202
222
  (d) => d.routePath?.endsWith("/") ? -1 : 1,
203
223
  (d) => d.routePath
204
224
  ]).filter((d) => {
@@ -343,10 +363,15 @@ Add the file in: "${this.config.routesDirectory}/${rootPathId.rootPathId}.${this
343
363
  buildRouteTree(opts) {
344
364
  const config = { ...this.config, ...opts.config || {} };
345
365
  const { rootRouteNode, acc } = opts;
366
+ const indexTokenSegmentRegex = config.indexToken === this.config.indexToken ? this.indexTokenSegmentRegex : utils.createTokenRegex(config.indexToken, { type: "segment" });
346
367
  const sortedRouteNodes = utils.multiSortBy(acc.routeNodes, [
347
368
  (d) => d.routePath?.includes(`/${rootPathId.rootPathId}`) ? -1 : 1,
348
369
  (d) => d.routePath?.split("/").length,
349
- (d) => d.routePath?.endsWith(config.indexToken) ? -1 : 1,
370
+ (d) => {
371
+ const segments = d.routePath?.split("/").filter(Boolean) ?? [];
372
+ const last = segments[segments.length - 1] ?? "";
373
+ return indexTokenSegmentRegex.test(last) ? -1 : 1;
374
+ },
350
375
  (d) => d
351
376
  ]);
352
377
  const routeImports = [];