@tanstack/router-cli 1.1.6 → 1.1.7
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.
- package/build/cjs/config.js +4 -1
- package/build/cjs/config.js.map +1 -1
- package/build/cjs/generator.js +34 -36
- package/build/cjs/generator.js.map +1 -1
- package/build/types/config.d.ts +13 -0
- package/build/types/generator.d.ts +4 -1
- package/package.json +2 -2
- package/src/config.ts +5 -0
- package/src/generator.ts +99 -53
package/build/cjs/config.js
CHANGED
|
@@ -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() {
|
package/build/cjs/config.js.map
CHANGED
|
@@ -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,
|
|
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;;;;"}
|
package/build/cjs/generator.js
CHANGED
|
@@ -113,18 +113,19 @@ async function generator(config) {
|
|
|
113
113
|
let routeNodes = await getRouteNodes(config);
|
|
114
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}`);
|
|
115
115
|
const routeTree = [];
|
|
116
|
+
const routePiecesByPath = {};
|
|
116
117
|
|
|
117
118
|
// Loop over the flat list of routeNodes and
|
|
118
119
|
// build up a tree based on the routeNodes' routePath
|
|
119
|
-
routeNodes.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
120
|
+
routeNodes = routeNodes.filter(node => {
|
|
121
|
+
if (config.future?.unstable_codeSplitting) {
|
|
122
|
+
node.isRoute = node.routePath?.endsWith('/route');
|
|
123
|
+
node.isComponent = node.routePath?.endsWith('/component');
|
|
124
|
+
node.isLoader = node.routePath?.endsWith('/loader');
|
|
125
|
+
if (node.isComponent || node.isLoader || node.isRoute) {
|
|
126
|
+
node.routePath = node.routePath?.replace(/\/(component|loader|route)$/, '');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
128
129
|
const parentRoute = hasParentRoute(routeNodes, node.routePath);
|
|
129
130
|
if (parentRoute) node.parent = parentRoute;
|
|
130
131
|
node.path = node.parent ? node.routePath?.replace(node.parent.routePath, '') || '/' : node.routePath;
|
|
@@ -134,12 +135,20 @@ async function generator(config) {
|
|
|
134
135
|
node.isNonPath = first.startsWith('_');
|
|
135
136
|
node.isNonLayout = first.endsWith('_');
|
|
136
137
|
node.cleanedPath = removeUnderscores(node.path) ?? '';
|
|
138
|
+
if (config.future?.unstable_codeSplitting) {
|
|
139
|
+
if (node.isLoader || node.isComponent) {
|
|
140
|
+
routePiecesByPath[node.routePath] = routePiecesByPath[node.routePath] || {};
|
|
141
|
+
routePiecesByPath[node.routePath][node.isLoader ? 'loader' : 'component'] = node;
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
137
145
|
if (node.parent) {
|
|
138
146
|
node.parent.children = node.parent.children ?? [];
|
|
139
147
|
node.parent.children.push(node);
|
|
140
148
|
} else {
|
|
141
149
|
routeTree.push(node);
|
|
142
150
|
}
|
|
151
|
+
return true;
|
|
143
152
|
});
|
|
144
153
|
async function buildRouteConfig(nodes, depth = 1) {
|
|
145
154
|
const children = nodes.map(async node => {
|
|
@@ -171,39 +180,28 @@ async function generator(config) {
|
|
|
171
180
|
return (await Promise.all(children)).filter(Boolean).join(`,`);
|
|
172
181
|
}
|
|
173
182
|
const routeConfigChildrenText = await buildRouteConfig(routeTree);
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
183
|
+
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]);
|
|
184
|
+
const routeImports = [`import { 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.map(node => {
|
|
185
|
+
return `import { Route as ${node.variableName}Import } from './${sanitize(removeExt(path.relative(path.dirname(config.generatedRouteTree), path.resolve(config.routesDirectory, node.filePath))))}'`;
|
|
186
|
+
}), '\n', sortedRouteNodes.map(node => {
|
|
187
|
+
const loaderNode = routePiecesByPath[node.routePath]?.loader;
|
|
188
|
+
const componentNode = routePiecesByPath[node.routePath]?.component;
|
|
189
|
+
return [`const ${node.variableName}Route = ${node.variableName}Import.update({
|
|
190
|
+
${[node.isNonPath ? `id: '${node.path}'` : `path: '${node.cleanedPath}'`, `getParentRoute: () => ${node.parent?.variableName ?? 'root'}Route`].filter(Boolean).join(',')}
|
|
191
|
+
} 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('');
|
|
192
|
+
}).join('\n\n')].join('\n');
|
|
177
193
|
const routeTypes = `declare module '@tanstack/react-router' {
|
|
178
194
|
interface FileRoutesByPath {
|
|
179
195
|
${routeNodes.map(routeNode => {
|
|
180
196
|
return `'${routeNode.routePath}': {
|
|
197
|
+
preLoaderRoute: typeof ${routeNode.variableName}Import
|
|
181
198
|
parentRoute: typeof ${routeNode.parent?.variableName ?? 'root'}Route
|
|
182
199
|
}`;
|
|
183
200
|
}).join('\n')}
|
|
184
201
|
}
|
|
185
202
|
}`;
|
|
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
203
|
const routeConfig = `export const routeTree = rootRoute.addChildren([${routeConfigChildrenText}])`;
|
|
206
|
-
const routeConfigFileContent = await prettier__namespace.format([routeImports, routeTypes,
|
|
204
|
+
const routeConfigFileContent = await prettier__namespace.format([routeImports, routeTypes, routeConfig].join('\n\n'), {
|
|
207
205
|
semi: false,
|
|
208
206
|
parser: 'typescript'
|
|
209
207
|
});
|
|
@@ -264,18 +262,18 @@ function removeUnderscores(s) {
|
|
|
264
262
|
function replaceBackslash(s) {
|
|
265
263
|
return s?.replace(/\\/gi, '/');
|
|
266
264
|
}
|
|
267
|
-
function hasParentRoute(routes,
|
|
268
|
-
if (!
|
|
265
|
+
function hasParentRoute(routes, routePathToCheck) {
|
|
266
|
+
if (!routePathToCheck || routePathToCheck === '/') {
|
|
269
267
|
return null;
|
|
270
268
|
}
|
|
271
269
|
const sortedNodes = multiSortBy(routes, [d => d.routePath.length * -1, d => d.variableName]).filter(d => d.routePath !== `/${rootPathId}`);
|
|
272
270
|
for (const route of sortedNodes) {
|
|
273
271
|
if (route.routePath === '/') continue;
|
|
274
|
-
if (
|
|
272
|
+
if (routePathToCheck.startsWith(`${route.routePath}/`) && route.routePath !== routePathToCheck) {
|
|
275
273
|
return route;
|
|
276
274
|
}
|
|
277
275
|
}
|
|
278
|
-
const segments =
|
|
276
|
+
const segments = routePathToCheck.split('/');
|
|
279
277
|
segments.pop(); // Remove the last segment
|
|
280
278
|
const parentRoute = segments.join('/');
|
|
281
279
|
return hasParentRoute(routes, parentRoute);
|
|
@@ -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 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 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 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 routeNodes = routeNodes.filter((node) => {\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 return false\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 return true\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 { 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.map((node) => {\n return `import { Route as ${node.variableName}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 .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 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","routePiecesByPath","node","future","unstable_codeSplitting","isRoute","isComponent","isLoader","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","sortedRouteNodes","includes","routeImports","sanitize","relative","dirname","generatedRouteTree","loaderNode","loader","componentNode","component","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"],"mappings":"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"}
|
package/build/types/config.d.ts
CHANGED
|
@@ -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,9 @@ export type RouteNode = {
|
|
|
10
10
|
path?: string;
|
|
11
11
|
isNonPath?: boolean;
|
|
12
12
|
isNonLayout?: boolean;
|
|
13
|
+
isRoute?: boolean;
|
|
14
|
+
isLoader?: boolean;
|
|
15
|
+
isComponent?: boolean;
|
|
13
16
|
isRoot?: boolean;
|
|
14
17
|
children?: RouteNode[];
|
|
15
18
|
parent?: RouteNode;
|
|
@@ -17,4 +20,4 @@ export type RouteNode = {
|
|
|
17
20
|
export declare function generator(config: Config): Promise<void>;
|
|
18
21
|
export declare function removeExt(d: string): string;
|
|
19
22
|
export declare function multiSortBy<T>(arr: T[], accessors?: ((item: T) => any)[]): T[];
|
|
20
|
-
export declare function hasParentRoute(routes: RouteNode[],
|
|
23
|
+
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.
|
|
4
|
+
"version": "1.1.7",
|
|
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.
|
|
62
|
+
"@tanstack/react-router": "1.1.7"
|
|
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,9 @@ export type RouteNode = {
|
|
|
17
17
|
path?: string
|
|
18
18
|
isNonPath?: boolean
|
|
19
19
|
isNonLayout?: boolean
|
|
20
|
+
isRoute?: boolean
|
|
21
|
+
isLoader?: boolean
|
|
22
|
+
isComponent?: boolean
|
|
20
23
|
isRoot?: boolean
|
|
21
24
|
children?: RouteNode[]
|
|
22
25
|
parent?: RouteNode
|
|
@@ -92,6 +95,11 @@ async function getRouteNodes(config: Config) {
|
|
|
92
95
|
let first = false
|
|
93
96
|
let skipMessage = false
|
|
94
97
|
|
|
98
|
+
type RouteSubNode = {
|
|
99
|
+
component?: RouteNode
|
|
100
|
+
loader?: RouteNode
|
|
101
|
+
}
|
|
102
|
+
|
|
95
103
|
export async function generator(config: Config) {
|
|
96
104
|
console.log()
|
|
97
105
|
|
|
@@ -129,18 +137,24 @@ export async function generator(config: Config) {
|
|
|
129
137
|
]).filter((d) => d.routePath !== `/${routePathIdPrefix + rootPathId}`)
|
|
130
138
|
|
|
131
139
|
const routeTree: RouteNode[] = []
|
|
140
|
+
const routePiecesByPath: Record<string, RouteSubNode> = {}
|
|
132
141
|
|
|
133
142
|
// Loop over the flat list of routeNodes and
|
|
134
143
|
// build up a tree based on the routeNodes' routePath
|
|
135
|
-
routeNodes.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
+
routeNodes = routeNodes.filter((node) => {
|
|
145
|
+
if (config.future?.unstable_codeSplitting) {
|
|
146
|
+
node.isRoute = node.routePath?.endsWith('/route')
|
|
147
|
+
node.isComponent = node.routePath?.endsWith('/component')
|
|
148
|
+
node.isLoader = node.routePath?.endsWith('/loader')
|
|
149
|
+
|
|
150
|
+
if (node.isComponent || node.isLoader || node.isRoute) {
|
|
151
|
+
node.routePath = node.routePath?.replace(
|
|
152
|
+
/\/(component|loader|route)$/,
|
|
153
|
+
'',
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
144
158
|
const parentRoute = hasParentRoute(routeNodes, node.routePath)
|
|
145
159
|
if (parentRoute) node.parent = parentRoute
|
|
146
160
|
|
|
@@ -158,12 +172,26 @@ export async function generator(config: Config) {
|
|
|
158
172
|
|
|
159
173
|
node.cleanedPath = removeUnderscores(node.path) ?? ''
|
|
160
174
|
|
|
175
|
+
if (config.future?.unstable_codeSplitting) {
|
|
176
|
+
if (node.isLoader || node.isComponent) {
|
|
177
|
+
routePiecesByPath[node.routePath!] =
|
|
178
|
+
routePiecesByPath[node.routePath!] || {}
|
|
179
|
+
|
|
180
|
+
routePiecesByPath[node.routePath!]![
|
|
181
|
+
node.isLoader ? 'loader' : 'component'
|
|
182
|
+
] = node
|
|
183
|
+
return false
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
161
187
|
if (node.parent) {
|
|
162
188
|
node.parent.children = node.parent.children ?? []
|
|
163
189
|
node.parent.children.push(node)
|
|
164
190
|
} else {
|
|
165
191
|
routeTree.push(node)
|
|
166
192
|
}
|
|
193
|
+
|
|
194
|
+
return true
|
|
167
195
|
})
|
|
168
196
|
|
|
169
197
|
async function buildRouteConfig(
|
|
@@ -209,21 +237,25 @@ export async function generator(config: Config) {
|
|
|
209
237
|
|
|
210
238
|
const routeConfigChildrenText = await buildRouteConfig(routeTree)
|
|
211
239
|
|
|
240
|
+
const sortedRouteNodes = multiSortBy(routeNodes, [
|
|
241
|
+
(d) =>
|
|
242
|
+
d.routePath?.includes(`/${routePathIdPrefix + rootPathId}`) ? -1 : 1,
|
|
243
|
+
(d) => d.routePath?.split('/').length,
|
|
244
|
+
(d) => (d.routePath?.endsWith("index'") ? -1 : 1),
|
|
245
|
+
(d) => d,
|
|
246
|
+
])
|
|
247
|
+
|
|
212
248
|
const routeImports = [
|
|
249
|
+
`import { lazyFn, lazyRouteComponent } from '@tanstack/react-router'`,
|
|
250
|
+
'\n',
|
|
213
251
|
`import { Route as rootRoute } from './${sanitize(
|
|
214
252
|
path.relative(
|
|
215
253
|
path.dirname(config.generatedRouteTree),
|
|
216
254
|
path.resolve(config.routesDirectory, routePathIdPrefix + rootPathId),
|
|
217
255
|
),
|
|
218
256
|
)}'`,
|
|
219
|
-
...
|
|
220
|
-
(
|
|
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(
|
|
257
|
+
...sortedRouteNodes.map((node) => {
|
|
258
|
+
return `import { Route as ${node.variableName}Import } from './${sanitize(
|
|
227
259
|
removeExt(
|
|
228
260
|
path.relative(
|
|
229
261
|
path.dirname(config.generatedRouteTree),
|
|
@@ -232,6 +264,49 @@ export async function generator(config: Config) {
|
|
|
232
264
|
),
|
|
233
265
|
)}'`
|
|
234
266
|
}),
|
|
267
|
+
'\n',
|
|
268
|
+
sortedRouteNodes
|
|
269
|
+
.map((node) => {
|
|
270
|
+
const loaderNode = routePiecesByPath[node.routePath!]?.loader
|
|
271
|
+
const componentNode = routePiecesByPath[node.routePath!]?.component
|
|
272
|
+
|
|
273
|
+
return [
|
|
274
|
+
`const ${node.variableName}Route = ${node.variableName}Import.update({
|
|
275
|
+
${[
|
|
276
|
+
node.isNonPath
|
|
277
|
+
? `id: '${node.path}'`
|
|
278
|
+
: `path: '${node.cleanedPath}'`,
|
|
279
|
+
`getParentRoute: () => ${node.parent?.variableName ?? 'root'}Route`,
|
|
280
|
+
]
|
|
281
|
+
.filter(Boolean)
|
|
282
|
+
.join(',')}
|
|
283
|
+
} as any)`,
|
|
284
|
+
loaderNode
|
|
285
|
+
? `.updateLoader({ loader: lazyFn(() => import('./${sanitize(
|
|
286
|
+
removeExt(
|
|
287
|
+
path.relative(
|
|
288
|
+
path.dirname(config.generatedRouteTree),
|
|
289
|
+
path.resolve(config.routesDirectory, loaderNode.filePath),
|
|
290
|
+
),
|
|
291
|
+
),
|
|
292
|
+
)}'), 'loader') })`
|
|
293
|
+
: '',
|
|
294
|
+
componentNode
|
|
295
|
+
? `.update({ component: lazyRouteComponent(() => import('./${sanitize(
|
|
296
|
+
removeExt(
|
|
297
|
+
path.relative(
|
|
298
|
+
path.dirname(config.generatedRouteTree),
|
|
299
|
+
path.resolve(
|
|
300
|
+
config.routesDirectory,
|
|
301
|
+
componentNode.filePath,
|
|
302
|
+
),
|
|
303
|
+
),
|
|
304
|
+
),
|
|
305
|
+
)}'), 'component') })`
|
|
306
|
+
: '',
|
|
307
|
+
].join('')
|
|
308
|
+
})
|
|
309
|
+
.join('\n\n'),
|
|
235
310
|
].join('\n')
|
|
236
311
|
|
|
237
312
|
const routeTypes = `declare module '@tanstack/react-router' {
|
|
@@ -239,6 +314,7 @@ export async function generator(config: Config) {
|
|
|
239
314
|
${routeNodes
|
|
240
315
|
.map((routeNode) => {
|
|
241
316
|
return `'${routeNode.routePath}': {
|
|
317
|
+
preLoaderRoute: typeof ${routeNode.variableName}Import
|
|
242
318
|
parentRoute: typeof ${routeNode.parent?.variableName ?? 'root'}Route
|
|
243
319
|
}`
|
|
244
320
|
})
|
|
@@ -246,40 +322,10 @@ export async function generator(config: Config) {
|
|
|
246
322
|
}
|
|
247
323
|
}`
|
|
248
324
|
|
|
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
325
|
const routeConfig = `export const routeTree = rootRoute.addChildren([${routeConfigChildrenText}])`
|
|
280
326
|
|
|
281
327
|
const routeConfigFileContent = await prettier.format(
|
|
282
|
-
[routeImports, routeTypes,
|
|
328
|
+
[routeImports, routeTypes, routeConfig].join('\n\n'),
|
|
283
329
|
{
|
|
284
330
|
semi: false,
|
|
285
331
|
parser: 'typescript',
|
|
@@ -381,9 +427,9 @@ function replaceBackslash(s?: string) {
|
|
|
381
427
|
|
|
382
428
|
export function hasParentRoute(
|
|
383
429
|
routes: RouteNode[],
|
|
384
|
-
|
|
430
|
+
routePathToCheck: string | undefined,
|
|
385
431
|
): RouteNode | null {
|
|
386
|
-
if (!
|
|
432
|
+
if (!routePathToCheck || routePathToCheck === '/') {
|
|
387
433
|
return null
|
|
388
434
|
}
|
|
389
435
|
|
|
@@ -396,13 +442,13 @@ export function hasParentRoute(
|
|
|
396
442
|
if (route.routePath === '/') continue
|
|
397
443
|
|
|
398
444
|
if (
|
|
399
|
-
|
|
400
|
-
route.routePath !==
|
|
445
|
+
routePathToCheck.startsWith(`${route.routePath}/`) &&
|
|
446
|
+
route.routePath !== routePathToCheck
|
|
401
447
|
) {
|
|
402
448
|
return route
|
|
403
449
|
}
|
|
404
450
|
}
|
|
405
|
-
const segments =
|
|
451
|
+
const segments = routePathToCheck.split('/')
|
|
406
452
|
segments.pop() // Remove the last segment
|
|
407
453
|
const parentRoute = segments.join('/')
|
|
408
454
|
|