@tanstack/router-cli 1.1.6 → 1.1.8

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.
@@ -19,7 +19,10 @@ const configSchema = zod.z.object({
19
19
  routeFileIgnorePrefix: zod.z.string().optional(),
20
20
  routesDirectory: zod.z.string(),
21
21
  generatedRouteTree: zod.z.string(),
22
- quoteStyle: zod.z.enum(['single', 'double']).optional().default('single')
22
+ quoteStyle: zod.z.enum(['single', 'double']).optional().default('single'),
23
+ future: zod.z.object({
24
+ unstable_codeSplitting: zod.z.boolean().optional()
25
+ }).optional()
23
26
  });
24
27
  const configFilePathJson = path.resolve(process.cwd(), 'tsr.config.json');
25
28
  async function getConfig() {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sources":["../../src/config.ts"],"sourcesContent":["import path from 'path'\nimport fs from 'fs-extra'\nimport { z } from 'zod'\n\nconst configSchema = z.object({\n routeFilePrefix: z.string().optional(),\n routeFileIgnorePrefix: z.string().optional(),\n routesDirectory: z.string(),\n generatedRouteTree: z.string(),\n quoteStyle: z.enum(['single', 'double']).optional().default('single'),\n})\n\nexport type Config = z.infer<typeof configSchema>\n\nconst configFilePathJson = path.resolve(process.cwd(), 'tsr.config.json')\n\nexport async function getConfig(): Promise<Config> {\n const config = (await fs.readJson(configFilePathJson)) as unknown as Config\n\n return { routeFileIgnorePrefix: '-', ...configSchema.parse(config) }\n}\n"],"names":["configSchema","z","object","routeFilePrefix","string","optional","routeFileIgnorePrefix","routesDirectory","generatedRouteTree","quoteStyle","enum","default","configFilePathJson","path","resolve","process","cwd","getConfig","config","fs","readJson","parse"],"mappings":";;;;;;;;;;;;;;;;AAIA,MAAMA,YAAY,GAAGC,KAAC,CAACC,MAAM,CAAC;EAC5BC,eAAe,EAAEF,KAAC,CAACG,MAAM,EAAE,CAACC,QAAQ,EAAE;EACtCC,qBAAqB,EAAEL,KAAC,CAACG,MAAM,EAAE,CAACC,QAAQ,EAAE;AAC5CE,EAAAA,eAAe,EAAEN,KAAC,CAACG,MAAM,EAAE;AAC3BI,EAAAA,kBAAkB,EAAEP,KAAC,CAACG,MAAM,EAAE;AAC9BK,EAAAA,UAAU,EAAER,KAAC,CAACS,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAACL,QAAQ,EAAE,CAACM,OAAO,CAAC,QAAQ,CAAA;AACtE,CAAC,CAAC,CAAA;AAIF,MAAMC,kBAAkB,GAAGC,IAAI,CAACC,OAAO,CAACC,OAAO,CAACC,GAAG,EAAE,EAAE,iBAAiB,CAAC,CAAA;AAElE,eAAeC,SAASA,GAAoB;EACjD,MAAMC,MAAM,GAAI,MAAMC,EAAE,CAACC,QAAQ,CAACR,kBAAkB,CAAuB,CAAA;EAE3E,OAAO;AAAEN,IAAAA,qBAAqB,EAAE,GAAG;AAAE,IAAA,GAAGN,YAAY,CAACqB,KAAK,CAACH,MAAM,CAAA;GAAG,CAAA;AACtE;;;;"}
1
+ {"version":3,"file":"config.js","sources":["../../src/config.ts"],"sourcesContent":["import path from 'path'\nimport fs from 'fs-extra'\nimport { z } from 'zod'\n\nconst configSchema = z.object({\n routeFilePrefix: z.string().optional(),\n routeFileIgnorePrefix: z.string().optional(),\n routesDirectory: z.string(),\n generatedRouteTree: z.string(),\n quoteStyle: z.enum(['single', 'double']).optional().default('single'),\n future: z\n .object({\n unstable_codeSplitting: z.boolean().optional(),\n })\n .optional(),\n})\n\nexport type Config = z.infer<typeof configSchema>\n\nconst configFilePathJson = path.resolve(process.cwd(), 'tsr.config.json')\n\nexport async function getConfig(): Promise<Config> {\n const config = (await fs.readJson(configFilePathJson)) as unknown as Config\n\n return { routeFileIgnorePrefix: '-', ...configSchema.parse(config) }\n}\n"],"names":["configSchema","z","object","routeFilePrefix","string","optional","routeFileIgnorePrefix","routesDirectory","generatedRouteTree","quoteStyle","enum","default","future","unstable_codeSplitting","boolean","configFilePathJson","path","resolve","process","cwd","getConfig","config","fs","readJson","parse"],"mappings":";;;;;;;;;;;;;;;;AAIA,MAAMA,YAAY,GAAGC,KAAC,CAACC,MAAM,CAAC;EAC5BC,eAAe,EAAEF,KAAC,CAACG,MAAM,EAAE,CAACC,QAAQ,EAAE;EACtCC,qBAAqB,EAAEL,KAAC,CAACG,MAAM,EAAE,CAACC,QAAQ,EAAE;AAC5CE,EAAAA,eAAe,EAAEN,KAAC,CAACG,MAAM,EAAE;AAC3BI,EAAAA,kBAAkB,EAAEP,KAAC,CAACG,MAAM,EAAE;AAC9BK,EAAAA,UAAU,EAAER,KAAC,CAACS,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAACL,QAAQ,EAAE,CAACM,OAAO,CAAC,QAAQ,CAAC;AACrEC,EAAAA,MAAM,EAAEX,KAAC,CACNC,MAAM,CAAC;IACNW,sBAAsB,EAAEZ,KAAC,CAACa,OAAO,EAAE,CAACT,QAAQ,EAAC;GAC9C,CAAC,CACDA,QAAQ,EAAC;AACd,CAAC,CAAC,CAAA;AAIF,MAAMU,kBAAkB,GAAGC,IAAI,CAACC,OAAO,CAACC,OAAO,CAACC,GAAG,EAAE,EAAE,iBAAiB,CAAC,CAAA;AAElE,eAAeC,SAASA,GAAoB;EACjD,MAAMC,MAAM,GAAI,MAAMC,EAAE,CAACC,QAAQ,CAACR,kBAAkB,CAAuB,CAAA;EAE3E,OAAO;AAAET,IAAAA,qBAAqB,EAAE,GAAG;AAAE,IAAA,GAAGN,YAAY,CAACwB,KAAK,CAACH,MAAM,CAAA;GAAG,CAAA;AACtE;;;;"}
@@ -110,21 +110,26 @@ async function generator(config) {
110
110
  };
111
111
  const start = Date.now();
112
112
  const routePathIdPrefix = config.routeFilePrefix ?? '';
113
- let routeNodes = await getRouteNodes(config);
114
- routeNodes = multiSortBy(routeNodes, [d => d.routePath === '/' ? -1 : 1, d => d.routePath?.split('/').length, d => d.routePath?.endsWith('/') ? -1 : 1, d => d.routePath]).filter(d => d.routePath !== `/${routePathIdPrefix + rootPathId}`);
113
+ let preRouteNodes = await getRouteNodes(config);
114
+ const sortRouteNodes = nodes => {
115
+ return multiSortBy(nodes, [d => d.routePath === '/' ? -1 : 1, d => d.routePath?.split('/').length, d => d.routePath?.endsWith('/') ? -1 : 1, d => d.routePath]).filter(d => d.routePath !== `/${routePathIdPrefix + rootPathId}`);
116
+ };
117
+ preRouteNodes = sortRouteNodes(preRouteNodes);
115
118
  const routeTree = [];
119
+ const routePiecesByPath = {};
116
120
 
117
121
  // Loop over the flat list of routeNodes and
118
122
  // build up a tree based on the routeNodes' routePath
119
- routeNodes.forEach(node => {
120
- // routeNodes.forEach((existingNode) => {
121
- // if (
122
- // node.routePath?.startsWith(`${existingNode?.routePath ?? ''}/`)
123
- // // node.routePath.length > existingNode.routePath!.length
124
- // ) {
125
- // node.parent = existingNode
126
- // }
127
- // })
123
+ let routeNodes = [];
124
+ const handleNode = node => {
125
+ if (config.future?.unstable_codeSplitting) {
126
+ node.isRoute = node.routePath?.endsWith('/route');
127
+ node.isComponent = node.routePath?.endsWith('/component');
128
+ node.isLoader = node.routePath?.endsWith('/loader');
129
+ if (node.isComponent || node.isLoader || node.isRoute) {
130
+ node.routePath = node.routePath?.replace(/\/(component|loader|route)$/, '');
131
+ }
132
+ }
128
133
  const parentRoute = hasParentRoute(routeNodes, node.routePath);
129
134
  if (parentRoute) node.parent = parentRoute;
130
135
  node.path = node.parent ? node.routePath?.replace(node.parent.routePath, '') || '/' : node.routePath;
@@ -134,13 +139,35 @@ async function generator(config) {
134
139
  node.isNonPath = first.startsWith('_');
135
140
  node.isNonLayout = first.endsWith('_');
136
141
  node.cleanedPath = removeUnderscores(node.path) ?? '';
142
+ if (config.future?.unstable_codeSplitting) {
143
+ if (node.isLoader || node.isComponent) {
144
+ routePiecesByPath[node.routePath] = routePiecesByPath[node.routePath] || {};
145
+ routePiecesByPath[node.routePath][node.isLoader ? 'loader' : 'component'] = node;
146
+ return;
147
+ }
148
+ }
137
149
  if (node.parent) {
138
150
  node.parent.children = node.parent.children ?? [];
139
151
  node.parent.children.push(node);
140
152
  } else {
141
153
  routeTree.push(node);
142
154
  }
143
- });
155
+ routeNodes.push(node);
156
+ };
157
+ preRouteNodes.forEach(node => handleNode(node));
158
+ if (config.future?.unstable_codeSplitting) {
159
+ Object.keys(routePiecesByPath).forEach(routePath => {
160
+ const found = routeNodes.find(d => d.routePath === routePath);
161
+ if (!found) {
162
+ const pieces = routePiecesByPath[routePath];
163
+ const componentOrLoader = pieces.component || pieces.loader;
164
+ if (componentOrLoader) {
165
+ componentOrLoader.isVirtual = true;
166
+ handleNode(componentOrLoader);
167
+ }
168
+ }
169
+ });
170
+ }
144
171
  async function buildRouteConfig(nodes, depth = 1) {
145
172
  const children = nodes.map(async node => {
146
173
  const routeCode = await fs.readFile(node.fullPath, 'utf-8');
@@ -171,39 +198,30 @@ async function generator(config) {
171
198
  return (await Promise.all(children)).filter(Boolean).join(`,`);
172
199
  }
173
200
  const routeConfigChildrenText = await buildRouteConfig(routeTree);
174
- const routeImports = [`import { Route as rootRoute } from './${sanitize(path.relative(path.dirname(config.generatedRouteTree), path.resolve(config.routesDirectory, routePathIdPrefix + rootPathId)))}'`, ...multiSortBy(routeNodes, [d => d.routePath?.includes(`/${routePathIdPrefix + rootPathId}`) ? -1 : 1, d => d.routePath?.split('/').length, d => d.routePath?.endsWith("index'") ? -1 : 1, d => d]).map(node => {
175
- return `import { Route as ${node.variableName}Route } from './${sanitize(removeExt(path.relative(path.dirname(config.generatedRouteTree), path.resolve(config.routesDirectory, node.filePath))))}'`;
176
- })].join('\n');
201
+ const sortedRouteNodes = multiSortBy(routeNodes, [d => d.routePath?.includes(`/${routePathIdPrefix + rootPathId}`) ? -1 : 1, d => d.routePath?.split('/').length, d => d.routePath?.endsWith("index'") ? -1 : 1, d => d]);
202
+ const routeImports = [`import { FileRoute, lazyFn, lazyRouteComponent } from '@tanstack/react-router'`, '\n', `import { Route as rootRoute } from './${sanitize(path.relative(path.dirname(config.generatedRouteTree), path.resolve(config.routesDirectory, routePathIdPrefix + rootPathId)))}'`, ...sortedRouteNodes.filter(d => !d.isVirtual).map(node => {
203
+ return `import { Route as ${node.variableName}Import } from './${sanitize(removeExt(path.relative(path.dirname(config.generatedRouteTree), path.resolve(config.routesDirectory, node.filePath))))}'`;
204
+ }), '\n', sortedRouteNodes.filter(d => d.isVirtual).map(node => {
205
+ return `const ${node.variableName}Import = new FileRoute('${node.routePath}').createRoute()`;
206
+ }).join('\n'), '\n', sortedRouteNodes.map(node => {
207
+ const loaderNode = routePiecesByPath[node.routePath]?.loader;
208
+ const componentNode = routePiecesByPath[node.routePath]?.component;
209
+ return [`const ${node.variableName}Route = ${node.variableName}Import.update({
210
+ ${[node.isNonPath ? `id: '${node.path}'` : `path: '${node.cleanedPath}'`, `getParentRoute: () => ${node.parent?.variableName ?? 'root'}Route`].filter(Boolean).join(',')}
211
+ } as any)`, loaderNode ? `.updateLoader({ loader: lazyFn(() => import('./${sanitize(removeExt(path.relative(path.dirname(config.generatedRouteTree), path.resolve(config.routesDirectory, loaderNode.filePath))))}'), 'loader') })` : '', componentNode ? `.update({ component: lazyRouteComponent(() => import('./${sanitize(removeExt(path.relative(path.dirname(config.generatedRouteTree), path.resolve(config.routesDirectory, componentNode.filePath))))}'), 'component') })` : ''].join('');
212
+ }).join('\n\n')].join('\n');
177
213
  const routeTypes = `declare module '@tanstack/react-router' {
178
214
  interface FileRoutesByPath {
179
215
  ${routeNodes.map(routeNode => {
180
216
  return `'${routeNode.routePath}': {
217
+ preLoaderRoute: typeof ${routeNode.variableName}Import
181
218
  parentRoute: typeof ${routeNode.parent?.variableName ?? 'root'}Route
182
219
  }`;
183
220
  }).join('\n')}
184
221
  }
185
222
  }`;
186
- const routeOptions = routeNodes.map(routeNode => {
187
- return `Object.assign(${routeNode.variableName ?? 'root'}Route.options, {
188
- ${[routeNode.isNonPath ? `id: '${routeNode.path}'` : `path: '${routeNode.cleanedPath}'`, `getParentRoute: () => ${routeNode.parent?.variableName ?? 'root'}Route`
189
- // `\n// ${JSON.stringify(
190
- // {
191
- // ...routeNode,
192
- // parent: undefined,
193
- // children: undefined,
194
- // fullPath: undefined,
195
- // variableName: undefined,
196
- // },
197
- // null,
198
- // 2,
199
- // )
200
- // .split('\n')
201
- // .join('\n// ')}`,
202
- ].filter(Boolean).join(',')}
203
- })`;
204
- }).join('\n\n');
205
223
  const routeConfig = `export const routeTree = rootRoute.addChildren([${routeConfigChildrenText}])`;
206
- const routeConfigFileContent = await prettier__namespace.format([routeImports, routeTypes, routeOptions, routeConfig].join('\n\n'), {
224
+ const routeConfigFileContent = await prettier__namespace.format([routeImports, routeTypes, routeConfig].join('\n\n'), {
207
225
  semi: false,
208
226
  parser: 'typescript'
209
227
  });
@@ -264,21 +282,21 @@ function removeUnderscores(s) {
264
282
  function replaceBackslash(s) {
265
283
  return s?.replace(/\\/gi, '/');
266
284
  }
267
- function hasParentRoute(routes, routeToCheck) {
268
- if (!routeToCheck || routeToCheck === '/') {
285
+ function hasParentRoute(routes, routePathToCheck) {
286
+ if (!routePathToCheck || routePathToCheck === '/') {
269
287
  return null;
270
288
  }
271
289
  const sortedNodes = multiSortBy(routes, [d => d.routePath.length * -1, d => d.variableName]).filter(d => d.routePath !== `/${rootPathId}`);
272
290
  for (const route of sortedNodes) {
273
291
  if (route.routePath === '/') continue;
274
- if (routeToCheck.startsWith(`${route.routePath}/`) && route.routePath !== routeToCheck) {
292
+ if (routePathToCheck.startsWith(`${route.routePath}/`) && route.routePath !== routePathToCheck) {
275
293
  return route;
276
294
  }
277
295
  }
278
- const segments = routeToCheck.split('/');
296
+ const segments = routePathToCheck.split('/');
279
297
  segments.pop(); // Remove the last segment
280
- const parentRoute = segments.join('/');
281
- return hasParentRoute(routes, parentRoute);
298
+ const parentRoutePath = segments.join('/');
299
+ return hasParentRoute(routes, parentRoutePath);
282
300
  }
283
301
 
284
302
  exports.fileRouteRegex = fileRouteRegex;
@@ -1 +1 @@
1
- {"version":3,"file":"generator.js","sources":["../../src/generator.ts"],"sourcesContent":["import path from 'path'\nimport fs from 'fs-extra'\nimport * as prettier from 'prettier'\nimport { Config } from './config'\nimport { cleanPath, trimPathLeft } from '@tanstack/react-router'\n\nlet latestTask = 0\nexport const rootPathId = '__root'\nexport const fileRouteRegex = /new\\s+FileRoute\\(([^)]*)\\)/g\n\nexport type RouteNode = {\n filePath: string\n fullPath: string\n variableName: string\n routePath?: string\n cleanedPath?: string\n path?: string\n isNonPath?: boolean\n isNonLayout?: boolean\n isRoot?: boolean\n children?: RouteNode[]\n parent?: RouteNode\n}\n\nasync function getRouteNodes(config: Config) {\n const { routeFilePrefix, routeFileIgnorePrefix } = config\n\n let routeNodes: RouteNode[] = []\n\n async function recurse(dir: string) {\n const fullDir = path.resolve(config.routesDirectory, dir)\n let dirList = await fs.readdir(fullDir)\n\n dirList = dirList.filter((d) => {\n if (\n d.startsWith('.') ||\n (routeFileIgnorePrefix && d.startsWith(routeFileIgnorePrefix))\n ) {\n return false\n }\n\n if (routeFilePrefix) {\n return d.startsWith(routeFilePrefix)\n }\n\n return true\n })\n\n await Promise.all(\n dirList.map(async (fileName) => {\n const fullPath = path.join(fullDir, fileName)\n const relativePath = path.join(dir, fileName)\n const stat = await fs.stat(fullPath)\n\n if (stat.isDirectory()) {\n await recurse(relativePath)\n } else {\n const filePath = path.join(dir, fileName)\n const filePathNoExt = removeExt(filePath)\n let routePath =\n replaceBackslash(\n cleanPath(`/${filePathNoExt.split('.').join('/')}`),\n ) ?? ''\n const variableName = fileToVariable(routePath)\n\n // Remove the index from the route path and\n // if the route path is empty, use `/'\n if (routePath === 'index') {\n routePath = '/'\n } else if (routePath.endsWith('/index')) {\n routePath = routePath.replace(/\\/index$/, '/')\n }\n\n routeNodes.push({\n filePath,\n fullPath,\n routePath,\n variableName,\n })\n }\n }),\n )\n\n return routeNodes\n }\n\n await recurse('./')\n\n return routeNodes\n}\n\nlet first = false\nlet skipMessage = false\n\nexport async function generator(config: Config) {\n console.log()\n\n if (!first) {\n console.log('🔄 Generating routes...')\n first = true\n } else if (skipMessage) {\n skipMessage = false\n } else {\n console.log('♻️ Regenerating routes...')\n }\n\n const taskId = latestTask + 1\n latestTask = taskId\n\n const checkLatest = () => {\n if (latestTask !== taskId) {\n skipMessage = true\n return false\n }\n\n return true\n }\n\n const start = Date.now()\n const routePathIdPrefix = config.routeFilePrefix ?? ''\n\n let routeNodes = await getRouteNodes(config)\n\n routeNodes = multiSortBy(routeNodes, [\n (d) => (d.routePath === '/' ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => (d.routePath?.endsWith('/') ? -1 : 1),\n (d) => d.routePath,\n ]).filter((d) => d.routePath !== `/${routePathIdPrefix + rootPathId}`)\n\n const routeTree: RouteNode[] = []\n\n // Loop over the flat list of routeNodes and\n // build up a tree based on the routeNodes' routePath\n routeNodes.forEach((node) => {\n // routeNodes.forEach((existingNode) => {\n // if (\n // node.routePath?.startsWith(`${existingNode?.routePath ?? ''}/`)\n // // node.routePath.length > existingNode.routePath!.length\n // ) {\n // node.parent = existingNode\n // }\n // })\n const parentRoute = hasParentRoute(routeNodes, node.routePath)\n if (parentRoute) node.parent = parentRoute\n\n node.path = node.parent\n ? node.routePath?.replace(node.parent.routePath!, '') || '/'\n : node.routePath\n\n const trimmedPath = trimPathLeft(node.path ?? '')\n\n const split = trimmedPath?.split('/') ?? []\n let first = split[0] ?? trimmedPath ?? ''\n\n node.isNonPath = first.startsWith('_')\n node.isNonLayout = first.endsWith('_')\n\n node.cleanedPath = removeUnderscores(node.path) ?? ''\n\n if (node.parent) {\n node.parent.children = node.parent.children ?? []\n node.parent.children.push(node)\n } else {\n routeTree.push(node)\n }\n })\n\n async function buildRouteConfig(\n nodes: RouteNode[],\n depth = 1,\n ): Promise<string> {\n const children = nodes.map(async (node) => {\n const routeCode = await fs.readFile(node.fullPath, 'utf-8')\n\n // Ensure the boilerplate for the route exists\n if (node.isRoot) {\n return\n }\n\n // Ensure that new FileRoute(anything?) is replaced with FileRoute(${node.routePath})\n // routePath can contain $ characters, which have special meaning when used in replace\n // so we have to escape it by turning all $ into $$. But since we do it through a replace call\n // we have to double escape it into $$$$. For more information, see\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_the_replacement\n const escapedRoutePath = node.routePath?.replaceAll('$', '$$$$') ?? ''\n const quote = config.quoteStyle === 'single' ? `'` : `\"`\n const replaced = routeCode.replace(\n fileRouteRegex,\n `new FileRoute(${quote}${escapedRoutePath}${quote})`,\n )\n\n if (replaced !== routeCode) {\n await fs.writeFile(node.fullPath, replaced)\n }\n\n const route = `${node.variableName}Route`\n\n if (node.children?.length) {\n const childConfigs = await buildRouteConfig(node.children, depth + 1)\n return `${route}.addChildren([${spaces(depth * 4)}${childConfigs}])`\n }\n\n return route\n })\n\n return (await Promise.all(children)).filter(Boolean).join(`,`)\n }\n\n const routeConfigChildrenText = await buildRouteConfig(routeTree)\n\n const routeImports = [\n `import { Route as rootRoute } from './${sanitize(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, routePathIdPrefix + rootPathId),\n ),\n )}'`,\n ...multiSortBy(routeNodes, [\n (d) =>\n d.routePath?.includes(`/${routePathIdPrefix + rootPathId}`) ? -1 : 1,\n (d) => d.routePath?.split('/').length,\n (d) => (d.routePath?.endsWith(\"index'\") ? -1 : 1),\n (d) => d,\n ]).map((node) => {\n return `import { Route as ${node.variableName}Route } from './${sanitize(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, node.filePath),\n ),\n ),\n )}'`\n }),\n ].join('\\n')\n\n const routeTypes = `declare module '@tanstack/react-router' {\n interface FileRoutesByPath {\n ${routeNodes\n .map((routeNode) => {\n return `'${routeNode.routePath}': {\n parentRoute: typeof ${routeNode.parent?.variableName ?? 'root'}Route\n }`\n })\n .join('\\n')}\n }\n}`\n\n const routeOptions = routeNodes\n .map((routeNode) => {\n return `Object.assign(${routeNode.variableName ?? 'root'}Route.options, {\n ${[\n routeNode.isNonPath\n ? `id: '${routeNode.path}'`\n : `path: '${routeNode.cleanedPath}'`,\n `getParentRoute: () => ${\n routeNode.parent?.variableName ?? 'root'\n }Route`,\n // `\\n// ${JSON.stringify(\n // {\n // ...routeNode,\n // parent: undefined,\n // children: undefined,\n // fullPath: undefined,\n // variableName: undefined,\n // },\n // null,\n // 2,\n // )\n // .split('\\n')\n // .join('\\n// ')}`,\n ]\n .filter(Boolean)\n .join(',')}\n })`\n })\n .join('\\n\\n')\n\n const routeConfig = `export const routeTree = rootRoute.addChildren([${routeConfigChildrenText}])`\n\n const routeConfigFileContent = await prettier.format(\n [routeImports, routeTypes, routeOptions, routeConfig].join('\\n\\n'),\n {\n semi: false,\n parser: 'typescript',\n },\n )\n\n const routeTreeContent = await fs\n .readFile(path.resolve(config.generatedRouteTree), 'utf-8')\n .catch((err: any) => {\n if (err.code === 'ENOENT') {\n return undefined\n }\n throw err\n })\n\n if (!checkLatest()) return\n\n if (routeTreeContent !== routeConfigFileContent) {\n await fs.ensureDir(path.dirname(path.resolve(config.generatedRouteTree)))\n if (!checkLatest()) return\n await fs.writeFile(\n path.resolve(config.generatedRouteTree),\n routeConfigFileContent,\n )\n }\n\n console.log(\n `🌲 Processed ${routeNodes.length} routes in ${Date.now() - start}ms`,\n )\n}\n\nfunction fileToVariable(d: string): string {\n return (\n removeUnderscores(d)\n ?.replace(/\\$/g, '')\n ?.split(/[/-]/g)\n .map((d, i) => (i > 0 ? capitalize(d) : d))\n .join('')\n .replace(/([^a-zA-Z0-9]|[\\.])/gm, '') ?? ''\n )\n}\n\nexport function removeExt(d: string) {\n return d.substring(0, d.lastIndexOf('.')) || d\n}\n\nfunction spaces(d: number): string {\n return Array.from({ length: d })\n .map(() => ' ')\n .join('')\n}\n\nexport function multiSortBy<T>(\n arr: T[],\n accessors: ((item: T) => any)[] = [(d) => d],\n): 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\nfunction capitalize(s: string) {\n if (typeof s !== 'string') return ''\n return s.charAt(0).toUpperCase() + s.slice(1)\n}\n\nfunction sanitize(s?: string) {\n return replaceBackslash(s?.replace(/\\\\index/gi, ''))\n}\n\nfunction removeUnderscores(s?: string) {\n return s?.replace(/(^_|_$)/, '').replace(/(\\/_|_\\/)/, '/')\n}\n\nfunction replaceBackslash(s?: string) {\n return s?.replace(/\\\\/gi, '/')\n}\n\nexport function hasParentRoute(\n routes: RouteNode[],\n routeToCheck: string | undefined,\n): RouteNode | null {\n if (!routeToCheck || routeToCheck === '/') {\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 routeToCheck.startsWith(`${route.routePath}/`) &&\n route.routePath !== routeToCheck\n ) {\n return route\n }\n }\n const segments = routeToCheck.split('/')\n segments.pop() // Remove the last segment\n const parentRoute = segments.join('/')\n\n return hasParentRoute(routes, parentRoute)\n}\n"],"names":["latestTask","rootPathId","fileRouteRegex","getRouteNodes","config","routeFilePrefix","routeFileIgnorePrefix","routeNodes","recurse","dir","fullDir","path","resolve","routesDirectory","dirList","fs","readdir","filter","d","startsWith","Promise","all","map","fileName","fullPath","join","relativePath","stat","isDirectory","filePath","filePathNoExt","removeExt","routePath","replaceBackslash","cleanPath","split","variableName","fileToVariable","endsWith","replace","push","first","skipMessage","generator","console","log","taskId","checkLatest","start","Date","now","routePathIdPrefix","multiSortBy","length","routeTree","forEach","node","parentRoute","hasParentRoute","parent","trimmedPath","trimPathLeft","isNonPath","isNonLayout","cleanedPath","removeUnderscores","children","buildRouteConfig","nodes","depth","routeCode","readFile","isRoot","escapedRoutePath","replaceAll","quote","quoteStyle","replaced","writeFile","route","childConfigs","spaces","Boolean","routeConfigChildrenText","routeImports","sanitize","relative","dirname","generatedRouteTree","includes","routeTypes","routeNode","routeOptions","routeConfig","routeConfigFileContent","prettier","format","semi","parser","routeTreeContent","catch","err","code","undefined","ensureDir","i","capitalize","substring","lastIndexOf","Array","from","arr","accessors","sort","a","ai","b","bi","accessor","ao","bo","s","charAt","toUpperCase","slice","routes","routeToCheck","sortedNodes","segments","pop"],"mappings":"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"}
1
+ {"version":3,"file":"generator.js","sources":["../../src/generator.ts"],"sourcesContent":["import path from 'path'\nimport fs from 'fs-extra'\nimport * as prettier from 'prettier'\nimport { Config } from './config'\nimport { cleanPath, trimPathLeft } from '@tanstack/react-router'\n\nlet latestTask = 0\nexport const rootPathId = '__root'\nexport const fileRouteRegex = /new\\s+FileRoute\\(([^)]*)\\)/g\n\nexport type RouteNode = {\n filePath: string\n fullPath: string\n variableName: string\n routePath?: string\n cleanedPath?: string\n path?: string\n isNonPath?: boolean\n isNonLayout?: boolean\n isRoute?: boolean\n isLoader?: boolean\n isComponent?: boolean\n isVirtual?: boolean\n isRoot?: boolean\n children?: RouteNode[]\n parent?: RouteNode\n}\n\nasync function getRouteNodes(config: Config) {\n const { routeFilePrefix, routeFileIgnorePrefix } = config\n\n let routeNodes: RouteNode[] = []\n\n async function recurse(dir: string) {\n const fullDir = path.resolve(config.routesDirectory, dir)\n let dirList = await fs.readdir(fullDir)\n\n dirList = dirList.filter((d) => {\n if (\n d.startsWith('.') ||\n (routeFileIgnorePrefix && d.startsWith(routeFileIgnorePrefix))\n ) {\n return false\n }\n\n if (routeFilePrefix) {\n return d.startsWith(routeFilePrefix)\n }\n\n return true\n })\n\n await Promise.all(\n dirList.map(async (fileName) => {\n const fullPath = path.join(fullDir, fileName)\n const relativePath = path.join(dir, fileName)\n const stat = await fs.stat(fullPath)\n\n if (stat.isDirectory()) {\n await recurse(relativePath)\n } else {\n const filePath = path.join(dir, fileName)\n const filePathNoExt = removeExt(filePath)\n let routePath =\n replaceBackslash(\n cleanPath(`/${filePathNoExt.split('.').join('/')}`),\n ) ?? ''\n const variableName = fileToVariable(routePath)\n\n // Remove the index from the route path and\n // if the route path is empty, use `/'\n if (routePath === 'index') {\n routePath = '/'\n } else if (routePath.endsWith('/index')) {\n routePath = routePath.replace(/\\/index$/, '/')\n }\n\n routeNodes.push({\n filePath,\n fullPath,\n routePath,\n variableName,\n })\n }\n }),\n )\n\n return routeNodes\n }\n\n await recurse('./')\n\n return routeNodes\n}\n\nlet first = false\nlet skipMessage = false\n\ntype RouteSubNode = {\n component?: RouteNode\n loader?: RouteNode\n}\n\nexport async function generator(config: Config) {\n console.log()\n\n if (!first) {\n console.log('🔄 Generating routes...')\n first = true\n } else if (skipMessage) {\n skipMessage = false\n } else {\n console.log('♻️ Regenerating routes...')\n }\n\n const taskId = latestTask + 1\n latestTask = taskId\n\n const checkLatest = () => {\n if (latestTask !== taskId) {\n skipMessage = true\n return false\n }\n\n return true\n }\n\n const start = Date.now()\n const routePathIdPrefix = config.routeFilePrefix ?? ''\n\n let preRouteNodes = await getRouteNodes(config)\n\n const sortRouteNodes = (nodes: RouteNode[]): RouteNode[] => {\n return multiSortBy(nodes, [\n (d) => (d.routePath === '/' ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => (d.routePath?.endsWith('/') ? -1 : 1),\n (d) => d.routePath,\n ]).filter((d) => d.routePath !== `/${routePathIdPrefix + rootPathId}`)\n }\n\n preRouteNodes = sortRouteNodes(preRouteNodes)\n\n const routeTree: RouteNode[] = []\n const routePiecesByPath: Record<string, RouteSubNode> = {}\n\n // Loop over the flat list of routeNodes and\n // build up a tree based on the routeNodes' routePath\n let routeNodes: RouteNode[] = []\n\n const handleNode = (node: RouteNode) => {\n if (config.future?.unstable_codeSplitting) {\n node.isRoute = node.routePath?.endsWith('/route')\n node.isComponent = node.routePath?.endsWith('/component')\n node.isLoader = node.routePath?.endsWith('/loader')\n\n if (node.isComponent || node.isLoader || node.isRoute) {\n node.routePath = node.routePath?.replace(\n /\\/(component|loader|route)$/,\n '',\n )\n }\n }\n\n const parentRoute = hasParentRoute(routeNodes, node.routePath)\n if (parentRoute) node.parent = parentRoute\n\n node.path = node.parent\n ? node.routePath?.replace(node.parent.routePath!, '') || '/'\n : node.routePath\n\n const trimmedPath = trimPathLeft(node.path ?? '')\n\n const split = trimmedPath?.split('/') ?? []\n let first = split[0] ?? trimmedPath ?? ''\n\n node.isNonPath = first.startsWith('_')\n node.isNonLayout = first.endsWith('_')\n\n node.cleanedPath = removeUnderscores(node.path) ?? ''\n\n if (config.future?.unstable_codeSplitting) {\n if (node.isLoader || node.isComponent) {\n routePiecesByPath[node.routePath!] =\n routePiecesByPath[node.routePath!] || {}\n\n routePiecesByPath[node.routePath!]![\n node.isLoader ? 'loader' : 'component'\n ] = node\n\n return\n }\n }\n\n if (node.parent) {\n node.parent.children = node.parent.children ?? []\n node.parent.children.push(node)\n } else {\n routeTree.push(node)\n }\n\n routeNodes.push(node)\n }\n\n preRouteNodes.forEach((node) => handleNode(node))\n\n if (config.future?.unstable_codeSplitting) {\n Object.keys(routePiecesByPath).forEach((routePath) => {\n const found = routeNodes.find((d) => d.routePath === routePath)\n\n if (!found) {\n const pieces = routePiecesByPath[routePath]!\n const componentOrLoader = pieces.component || pieces.loader\n if (componentOrLoader) {\n componentOrLoader.isVirtual = true\n handleNode(componentOrLoader)\n }\n }\n })\n }\n\n async function buildRouteConfig(\n nodes: RouteNode[],\n depth = 1,\n ): Promise<string> {\n const children = nodes.map(async (node) => {\n const routeCode = await fs.readFile(node.fullPath, 'utf-8')\n\n // Ensure the boilerplate for the route exists\n if (node.isRoot) {\n return\n }\n\n // Ensure that new FileRoute(anything?) is replaced with FileRoute(${node.routePath})\n // routePath can contain $ characters, which have special meaning when used in replace\n // so we have to escape it by turning all $ into $$. But since we do it through a replace call\n // we have to double escape it into $$$$. For more information, see\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_the_replacement\n const escapedRoutePath = node.routePath?.replaceAll('$', '$$$$') ?? ''\n const quote = config.quoteStyle === 'single' ? `'` : `\"`\n const replaced = routeCode.replace(\n fileRouteRegex,\n `new FileRoute(${quote}${escapedRoutePath}${quote})`,\n )\n\n if (replaced !== routeCode) {\n await fs.writeFile(node.fullPath, replaced)\n }\n\n const route = `${node.variableName}Route`\n\n if (node.children?.length) {\n const childConfigs = await buildRouteConfig(node.children, depth + 1)\n return `${route}.addChildren([${spaces(depth * 4)}${childConfigs}])`\n }\n\n return route\n })\n\n return (await Promise.all(children)).filter(Boolean).join(`,`)\n }\n\n const routeConfigChildrenText = await buildRouteConfig(routeTree)\n\n const sortedRouteNodes = multiSortBy(routeNodes, [\n (d) =>\n d.routePath?.includes(`/${routePathIdPrefix + rootPathId}`) ? -1 : 1,\n (d) => d.routePath?.split('/').length,\n (d) => (d.routePath?.endsWith(\"index'\") ? -1 : 1),\n (d) => d,\n ])\n\n const routeImports = [\n `import { FileRoute, lazyFn, lazyRouteComponent } from '@tanstack/react-router'`,\n '\\n',\n `import { Route as rootRoute } from './${sanitize(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, routePathIdPrefix + rootPathId),\n ),\n )}'`,\n ...sortedRouteNodes\n .filter((d) => !d.isVirtual)\n .map((node) => {\n return `import { Route as ${\n node.variableName\n }Import } from './${sanitize(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, node.filePath),\n ),\n ),\n )}'`\n }),\n '\\n',\n sortedRouteNodes\n .filter((d) => d.isVirtual)\n .map((node) => {\n return `const ${node.variableName}Import = new FileRoute('${node.routePath}').createRoute()`\n })\n .join('\\n'),\n '\\n',\n sortedRouteNodes\n .map((node) => {\n const loaderNode = routePiecesByPath[node.routePath!]?.loader\n const componentNode = routePiecesByPath[node.routePath!]?.component\n\n return [\n `const ${node.variableName}Route = ${node.variableName}Import.update({\n ${[\n node.isNonPath\n ? `id: '${node.path}'`\n : `path: '${node.cleanedPath}'`,\n `getParentRoute: () => ${node.parent?.variableName ?? 'root'}Route`,\n ]\n .filter(Boolean)\n .join(',')}\n } as any)`,\n loaderNode\n ? `.updateLoader({ loader: lazyFn(() => import('./${sanitize(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, loaderNode.filePath),\n ),\n ),\n )}'), 'loader') })`\n : '',\n componentNode\n ? `.update({ component: lazyRouteComponent(() => import('./${sanitize(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n componentNode.filePath,\n ),\n ),\n ),\n )}'), 'component') })`\n : '',\n ].join('')\n })\n .join('\\n\\n'),\n ].join('\\n')\n\n const routeTypes = `declare module '@tanstack/react-router' {\n interface FileRoutesByPath {\n ${routeNodes\n .map((routeNode) => {\n return `'${routeNode.routePath}': {\n preLoaderRoute: typeof ${routeNode.variableName}Import\n parentRoute: typeof ${routeNode.parent?.variableName ?? 'root'}Route\n }`\n })\n .join('\\n')}\n }\n}`\n\n const routeConfig = `export const routeTree = rootRoute.addChildren([${routeConfigChildrenText}])`\n\n const routeConfigFileContent = await prettier.format(\n [routeImports, routeTypes, routeConfig].join('\\n\\n'),\n {\n semi: false,\n parser: 'typescript',\n },\n )\n\n const routeTreeContent = await fs\n .readFile(path.resolve(config.generatedRouteTree), 'utf-8')\n .catch((err: any) => {\n if (err.code === 'ENOENT') {\n return undefined\n }\n throw err\n })\n\n if (!checkLatest()) return\n\n if (routeTreeContent !== routeConfigFileContent) {\n await fs.ensureDir(path.dirname(path.resolve(config.generatedRouteTree)))\n if (!checkLatest()) return\n await fs.writeFile(\n path.resolve(config.generatedRouteTree),\n routeConfigFileContent,\n )\n }\n\n console.log(\n `🌲 Processed ${routeNodes.length} routes in ${Date.now() - start}ms`,\n )\n}\n\nfunction fileToVariable(d: string): string {\n return (\n removeUnderscores(d)\n ?.replace(/\\$/g, '')\n ?.split(/[/-]/g)\n .map((d, i) => (i > 0 ? capitalize(d) : d))\n .join('')\n .replace(/([^a-zA-Z0-9]|[\\.])/gm, '') ?? ''\n )\n}\n\nexport function removeExt(d: string) {\n return d.substring(0, d.lastIndexOf('.')) || d\n}\n\nfunction spaces(d: number): string {\n return Array.from({ length: d })\n .map(() => ' ')\n .join('')\n}\n\nexport function multiSortBy<T>(\n arr: T[],\n accessors: ((item: T) => any)[] = [(d) => d],\n): 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\nfunction capitalize(s: string) {\n if (typeof s !== 'string') return ''\n return s.charAt(0).toUpperCase() + s.slice(1)\n}\n\nfunction sanitize(s?: string) {\n return replaceBackslash(s?.replace(/\\\\index/gi, ''))\n}\n\nfunction removeUnderscores(s?: string) {\n return s?.replace(/(^_|_$)/, '').replace(/(\\/_|_\\/)/, '/')\n}\n\nfunction replaceBackslash(s?: string) {\n return s?.replace(/\\\\/gi, '/')\n}\n\nexport function hasParentRoute(\n routes: 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 const segments = routePathToCheck.split('/')\n segments.pop() // Remove the last segment\n const parentRoutePath = segments.join('/')\n\n return hasParentRoute(routes, parentRoutePath)\n}\n"],"names":["latestTask","rootPathId","fileRouteRegex","getRouteNodes","config","routeFilePrefix","routeFileIgnorePrefix","routeNodes","recurse","dir","fullDir","path","resolve","routesDirectory","dirList","fs","readdir","filter","d","startsWith","Promise","all","map","fileName","fullPath","join","relativePath","stat","isDirectory","filePath","filePathNoExt","removeExt","routePath","replaceBackslash","cleanPath","split","variableName","fileToVariable","endsWith","replace","push","first","skipMessage","generator","console","log","taskId","checkLatest","start","Date","now","routePathIdPrefix","preRouteNodes","sortRouteNodes","nodes","multiSortBy","length","routeTree","routePiecesByPath","handleNode","node","future","unstable_codeSplitting","isRoute","isComponent","isLoader","parentRoute","hasParentRoute","parent","trimmedPath","trimPathLeft","isNonPath","isNonLayout","cleanedPath","removeUnderscores","children","forEach","Object","keys","found","find","pieces","componentOrLoader","component","loader","isVirtual","buildRouteConfig","depth","routeCode","readFile","isRoot","escapedRoutePath","replaceAll","quote","quoteStyle","replaced","writeFile","route","childConfigs","spaces","Boolean","routeConfigChildrenText","sortedRouteNodes","includes","routeImports","sanitize","relative","dirname","generatedRouteTree","loaderNode","componentNode","routeTypes","routeNode","routeConfig","routeConfigFileContent","prettier","format","semi","parser","routeTreeContent","catch","err","code","undefined","ensureDir","i","capitalize","substring","lastIndexOf","Array","from","arr","accessors","sort","a","ai","b","bi","accessor","ao","bo","s","charAt","toUpperCase","slice","routes","routePathToCheck","sortedNodes","segments","pop","parentRoutePath"],"mappings":"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"}
@@ -5,18 +5,31 @@ declare const configSchema: z.ZodObject<{
5
5
  routesDirectory: z.ZodString;
6
6
  generatedRouteTree: z.ZodString;
7
7
  quoteStyle: z.ZodDefault<z.ZodOptional<z.ZodEnum<["single", "double"]>>>;
8
+ future: z.ZodOptional<z.ZodObject<{
9
+ unstable_codeSplitting: z.ZodOptional<z.ZodBoolean>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ unstable_codeSplitting?: boolean | undefined;
12
+ }, {
13
+ unstable_codeSplitting?: boolean | undefined;
14
+ }>>;
8
15
  }, "strip", z.ZodTypeAny, {
9
16
  routesDirectory: string;
10
17
  generatedRouteTree: string;
11
18
  quoteStyle: "single" | "double";
12
19
  routeFilePrefix?: string | undefined;
13
20
  routeFileIgnorePrefix?: string | undefined;
21
+ future?: {
22
+ unstable_codeSplitting?: boolean | undefined;
23
+ } | undefined;
14
24
  }, {
15
25
  routesDirectory: string;
16
26
  generatedRouteTree: string;
17
27
  routeFilePrefix?: string | undefined;
18
28
  routeFileIgnorePrefix?: string | undefined;
19
29
  quoteStyle?: "single" | "double" | undefined;
30
+ future?: {
31
+ unstable_codeSplitting?: boolean | undefined;
32
+ } | undefined;
20
33
  }>;
21
34
  export type Config = z.infer<typeof configSchema>;
22
35
  export declare function getConfig(): Promise<Config>;
@@ -10,6 +10,10 @@ export type RouteNode = {
10
10
  path?: string;
11
11
  isNonPath?: boolean;
12
12
  isNonLayout?: boolean;
13
+ isRoute?: boolean;
14
+ isLoader?: boolean;
15
+ isComponent?: boolean;
16
+ isVirtual?: boolean;
13
17
  isRoot?: boolean;
14
18
  children?: RouteNode[];
15
19
  parent?: RouteNode;
@@ -17,4 +21,4 @@ export type RouteNode = {
17
21
  export declare function generator(config: Config): Promise<void>;
18
22
  export declare function removeExt(d: string): string;
19
23
  export declare function multiSortBy<T>(arr: T[], accessors?: ((item: T) => any)[]): T[];
20
- export declare function hasParentRoute(routes: RouteNode[], routeToCheck: string | undefined): RouteNode | null;
24
+ export declare function hasParentRoute(routes: RouteNode[], routePathToCheck: string | undefined): RouteNode | null;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/router-cli",
3
3
  "author": "Tanner Linsley",
4
- "version": "1.1.6",
4
+ "version": "1.1.8",
5
5
  "license": "MIT",
6
6
  "repository": "tanstack/router",
7
7
  "homepage": "https://tanstack.com/router",
@@ -59,7 +59,7 @@
59
59
  "through2": "^4.0.2",
60
60
  "yargs": "^17.6.2",
61
61
  "zod": "^3.19.1",
62
- "@tanstack/react-router": "1.1.6"
62
+ "@tanstack/react-router": "1.1.8"
63
63
  },
64
64
  "scripts": {
65
65
  "build": "rollup --config rollup.config.js"
package/src/config.ts CHANGED
@@ -8,6 +8,11 @@ const configSchema = z.object({
8
8
  routesDirectory: z.string(),
9
9
  generatedRouteTree: z.string(),
10
10
  quoteStyle: z.enum(['single', 'double']).optional().default('single'),
11
+ future: z
12
+ .object({
13
+ unstable_codeSplitting: z.boolean().optional(),
14
+ })
15
+ .optional(),
11
16
  })
12
17
 
13
18
  export type Config = z.infer<typeof configSchema>
package/src/generator.ts CHANGED
@@ -17,6 +17,10 @@ export type RouteNode = {
17
17
  path?: string
18
18
  isNonPath?: boolean
19
19
  isNonLayout?: boolean
20
+ isRoute?: boolean
21
+ isLoader?: boolean
22
+ isComponent?: boolean
23
+ isVirtual?: boolean
20
24
  isRoot?: boolean
21
25
  children?: RouteNode[]
22
26
  parent?: RouteNode
@@ -92,6 +96,11 @@ async function getRouteNodes(config: Config) {
92
96
  let first = false
93
97
  let skipMessage = false
94
98
 
99
+ type RouteSubNode = {
100
+ component?: RouteNode
101
+ loader?: RouteNode
102
+ }
103
+
95
104
  export async function generator(config: Config) {
96
105
  console.log()
97
106
 
@@ -119,28 +128,40 @@ export async function generator(config: Config) {
119
128
  const start = Date.now()
120
129
  const routePathIdPrefix = config.routeFilePrefix ?? ''
121
130
 
122
- let routeNodes = await getRouteNodes(config)
131
+ let preRouteNodes = await getRouteNodes(config)
123
132
 
124
- routeNodes = multiSortBy(routeNodes, [
125
- (d) => (d.routePath === '/' ? -1 : 1),
126
- (d) => d.routePath?.split('/').length,
127
- (d) => (d.routePath?.endsWith('/') ? -1 : 1),
128
- (d) => d.routePath,
129
- ]).filter((d) => d.routePath !== `/${routePathIdPrefix + rootPathId}`)
133
+ const sortRouteNodes = (nodes: RouteNode[]): RouteNode[] => {
134
+ return multiSortBy(nodes, [
135
+ (d) => (d.routePath === '/' ? -1 : 1),
136
+ (d) => d.routePath?.split('/').length,
137
+ (d) => (d.routePath?.endsWith('/') ? -1 : 1),
138
+ (d) => d.routePath,
139
+ ]).filter((d) => d.routePath !== `/${routePathIdPrefix + rootPathId}`)
140
+ }
141
+
142
+ preRouteNodes = sortRouteNodes(preRouteNodes)
130
143
 
131
144
  const routeTree: RouteNode[] = []
145
+ const routePiecesByPath: Record<string, RouteSubNode> = {}
132
146
 
133
147
  // Loop over the flat list of routeNodes and
134
148
  // build up a tree based on the routeNodes' routePath
135
- routeNodes.forEach((node) => {
136
- // routeNodes.forEach((existingNode) => {
137
- // if (
138
- // node.routePath?.startsWith(`${existingNode?.routePath ?? ''}/`)
139
- // // node.routePath.length > existingNode.routePath!.length
140
- // ) {
141
- // node.parent = existingNode
142
- // }
143
- // })
149
+ let routeNodes: RouteNode[] = []
150
+
151
+ const handleNode = (node: RouteNode) => {
152
+ if (config.future?.unstable_codeSplitting) {
153
+ node.isRoute = node.routePath?.endsWith('/route')
154
+ node.isComponent = node.routePath?.endsWith('/component')
155
+ node.isLoader = node.routePath?.endsWith('/loader')
156
+
157
+ if (node.isComponent || node.isLoader || node.isRoute) {
158
+ node.routePath = node.routePath?.replace(
159
+ /\/(component|loader|route)$/,
160
+ '',
161
+ )
162
+ }
163
+ }
164
+
144
165
  const parentRoute = hasParentRoute(routeNodes, node.routePath)
145
166
  if (parentRoute) node.parent = parentRoute
146
167
 
@@ -158,13 +179,45 @@ export async function generator(config: Config) {
158
179
 
159
180
  node.cleanedPath = removeUnderscores(node.path) ?? ''
160
181
 
182
+ if (config.future?.unstable_codeSplitting) {
183
+ if (node.isLoader || node.isComponent) {
184
+ routePiecesByPath[node.routePath!] =
185
+ routePiecesByPath[node.routePath!] || {}
186
+
187
+ routePiecesByPath[node.routePath!]![
188
+ node.isLoader ? 'loader' : 'component'
189
+ ] = node
190
+
191
+ return
192
+ }
193
+ }
194
+
161
195
  if (node.parent) {
162
196
  node.parent.children = node.parent.children ?? []
163
197
  node.parent.children.push(node)
164
198
  } else {
165
199
  routeTree.push(node)
166
200
  }
167
- })
201
+
202
+ routeNodes.push(node)
203
+ }
204
+
205
+ preRouteNodes.forEach((node) => handleNode(node))
206
+
207
+ if (config.future?.unstable_codeSplitting) {
208
+ Object.keys(routePiecesByPath).forEach((routePath) => {
209
+ const found = routeNodes.find((d) => d.routePath === routePath)
210
+
211
+ if (!found) {
212
+ const pieces = routePiecesByPath[routePath]!
213
+ const componentOrLoader = pieces.component || pieces.loader
214
+ if (componentOrLoader) {
215
+ componentOrLoader.isVirtual = true
216
+ handleNode(componentOrLoader)
217
+ }
218
+ }
219
+ })
220
+ }
168
221
 
169
222
  async function buildRouteConfig(
170
223
  nodes: RouteNode[],
@@ -209,29 +262,87 @@ export async function generator(config: Config) {
209
262
 
210
263
  const routeConfigChildrenText = await buildRouteConfig(routeTree)
211
264
 
265
+ const sortedRouteNodes = multiSortBy(routeNodes, [
266
+ (d) =>
267
+ d.routePath?.includes(`/${routePathIdPrefix + rootPathId}`) ? -1 : 1,
268
+ (d) => d.routePath?.split('/').length,
269
+ (d) => (d.routePath?.endsWith("index'") ? -1 : 1),
270
+ (d) => d,
271
+ ])
272
+
212
273
  const routeImports = [
274
+ `import { FileRoute, lazyFn, lazyRouteComponent } from '@tanstack/react-router'`,
275
+ '\n',
213
276
  `import { Route as rootRoute } from './${sanitize(
214
277
  path.relative(
215
278
  path.dirname(config.generatedRouteTree),
216
279
  path.resolve(config.routesDirectory, routePathIdPrefix + rootPathId),
217
280
  ),
218
281
  )}'`,
219
- ...multiSortBy(routeNodes, [
220
- (d) =>
221
- d.routePath?.includes(`/${routePathIdPrefix + rootPathId}`) ? -1 : 1,
222
- (d) => d.routePath?.split('/').length,
223
- (d) => (d.routePath?.endsWith("index'") ? -1 : 1),
224
- (d) => d,
225
- ]).map((node) => {
226
- return `import { Route as ${node.variableName}Route } from './${sanitize(
227
- removeExt(
228
- path.relative(
229
- path.dirname(config.generatedRouteTree),
230
- path.resolve(config.routesDirectory, node.filePath),
282
+ ...sortedRouteNodes
283
+ .filter((d) => !d.isVirtual)
284
+ .map((node) => {
285
+ return `import { Route as ${
286
+ node.variableName
287
+ }Import } from './${sanitize(
288
+ removeExt(
289
+ path.relative(
290
+ path.dirname(config.generatedRouteTree),
291
+ path.resolve(config.routesDirectory, node.filePath),
292
+ ),
231
293
  ),
232
- ),
233
- )}'`
234
- }),
294
+ )}'`
295
+ }),
296
+ '\n',
297
+ sortedRouteNodes
298
+ .filter((d) => d.isVirtual)
299
+ .map((node) => {
300
+ return `const ${node.variableName}Import = new FileRoute('${node.routePath}').createRoute()`
301
+ })
302
+ .join('\n'),
303
+ '\n',
304
+ sortedRouteNodes
305
+ .map((node) => {
306
+ const loaderNode = routePiecesByPath[node.routePath!]?.loader
307
+ const componentNode = routePiecesByPath[node.routePath!]?.component
308
+
309
+ return [
310
+ `const ${node.variableName}Route = ${node.variableName}Import.update({
311
+ ${[
312
+ node.isNonPath
313
+ ? `id: '${node.path}'`
314
+ : `path: '${node.cleanedPath}'`,
315
+ `getParentRoute: () => ${node.parent?.variableName ?? 'root'}Route`,
316
+ ]
317
+ .filter(Boolean)
318
+ .join(',')}
319
+ } as any)`,
320
+ loaderNode
321
+ ? `.updateLoader({ loader: lazyFn(() => import('./${sanitize(
322
+ removeExt(
323
+ path.relative(
324
+ path.dirname(config.generatedRouteTree),
325
+ path.resolve(config.routesDirectory, loaderNode.filePath),
326
+ ),
327
+ ),
328
+ )}'), 'loader') })`
329
+ : '',
330
+ componentNode
331
+ ? `.update({ component: lazyRouteComponent(() => import('./${sanitize(
332
+ removeExt(
333
+ path.relative(
334
+ path.dirname(config.generatedRouteTree),
335
+ path.resolve(
336
+ config.routesDirectory,
337
+ componentNode.filePath,
338
+ ),
339
+ ),
340
+ ),
341
+ )}'), 'component') })`
342
+ : '',
343
+ ].join('')
344
+ })
345
+ .join('\n\n'),
235
346
  ].join('\n')
236
347
 
237
348
  const routeTypes = `declare module '@tanstack/react-router' {
@@ -239,6 +350,7 @@ export async function generator(config: Config) {
239
350
  ${routeNodes
240
351
  .map((routeNode) => {
241
352
  return `'${routeNode.routePath}': {
353
+ preLoaderRoute: typeof ${routeNode.variableName}Import
242
354
  parentRoute: typeof ${routeNode.parent?.variableName ?? 'root'}Route
243
355
  }`
244
356
  })
@@ -246,40 +358,10 @@ export async function generator(config: Config) {
246
358
  }
247
359
  }`
248
360
 
249
- const routeOptions = routeNodes
250
- .map((routeNode) => {
251
- return `Object.assign(${routeNode.variableName ?? 'root'}Route.options, {
252
- ${[
253
- routeNode.isNonPath
254
- ? `id: '${routeNode.path}'`
255
- : `path: '${routeNode.cleanedPath}'`,
256
- `getParentRoute: () => ${
257
- routeNode.parent?.variableName ?? 'root'
258
- }Route`,
259
- // `\n// ${JSON.stringify(
260
- // {
261
- // ...routeNode,
262
- // parent: undefined,
263
- // children: undefined,
264
- // fullPath: undefined,
265
- // variableName: undefined,
266
- // },
267
- // null,
268
- // 2,
269
- // )
270
- // .split('\n')
271
- // .join('\n// ')}`,
272
- ]
273
- .filter(Boolean)
274
- .join(',')}
275
- })`
276
- })
277
- .join('\n\n')
278
-
279
361
  const routeConfig = `export const routeTree = rootRoute.addChildren([${routeConfigChildrenText}])`
280
362
 
281
363
  const routeConfigFileContent = await prettier.format(
282
- [routeImports, routeTypes, routeOptions, routeConfig].join('\n\n'),
364
+ [routeImports, routeTypes, routeConfig].join('\n\n'),
283
365
  {
284
366
  semi: false,
285
367
  parser: 'typescript',
@@ -381,9 +463,9 @@ function replaceBackslash(s?: string) {
381
463
 
382
464
  export function hasParentRoute(
383
465
  routes: RouteNode[],
384
- routeToCheck: string | undefined,
466
+ routePathToCheck: string | undefined,
385
467
  ): RouteNode | null {
386
- if (!routeToCheck || routeToCheck === '/') {
468
+ if (!routePathToCheck || routePathToCheck === '/') {
387
469
  return null
388
470
  }
389
471
 
@@ -396,15 +478,15 @@ export function hasParentRoute(
396
478
  if (route.routePath === '/') continue
397
479
 
398
480
  if (
399
- routeToCheck.startsWith(`${route.routePath}/`) &&
400
- route.routePath !== routeToCheck
481
+ routePathToCheck.startsWith(`${route.routePath}/`) &&
482
+ route.routePath !== routePathToCheck
401
483
  ) {
402
484
  return route
403
485
  }
404
486
  }
405
- const segments = routeToCheck.split('/')
487
+ const segments = routePathToCheck.split('/')
406
488
  segments.pop() // Remove the last segment
407
- const parentRoute = segments.join('/')
489
+ const parentRoutePath = segments.join('/')
408
490
 
409
- return hasParentRoute(routes, parentRoute)
491
+ return hasParentRoute(routes, parentRoutePath)
410
492
  }