@tanstack/router-generator 1.56.0 → 1.56.1
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/dist/cjs/generator.cjs +95 -7
- package/dist/cjs/generator.cjs.map +1 -1
- package/dist/cjs/generator.d.cts +24 -0
- package/dist/esm/generator.d.ts +24 -0
- package/dist/esm/generator.js +95 -7
- package/dist/esm/generator.js.map +1 -1
- package/package.json +4 -1
- package/src/generator.ts +129 -4
package/dist/cjs/generator.cjs
CHANGED
|
@@ -295,11 +295,23 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
295
295
|
const route = `${node.variableName}Route`;
|
|
296
296
|
if ((_b = node.children) == null ? void 0 : _b.length) {
|
|
297
297
|
const childConfigs = buildRouteTreeConfig(node.children, depth + 1);
|
|
298
|
-
|
|
298
|
+
const childrenDeclaration = `interface ${route}Children {
|
|
299
|
+
${node.children.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
300
|
+
}`;
|
|
301
|
+
const children2 = `const ${route}Children: ${route}Children = {
|
|
302
|
+
${node.children.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
303
|
+
}`;
|
|
304
|
+
const routeWithChildren = `const ${route}WithChildren = ${route}._addFileChildren(${route}Children)`;
|
|
305
|
+
return [
|
|
306
|
+
childConfigs,
|
|
307
|
+
childrenDeclaration,
|
|
308
|
+
children2,
|
|
309
|
+
routeWithChildren
|
|
310
|
+
].join("\n\n");
|
|
299
311
|
}
|
|
300
|
-
return
|
|
312
|
+
return void 0;
|
|
301
313
|
});
|
|
302
|
-
return children.filter(Boolean).join(
|
|
314
|
+
return children.filter(Boolean).join("\n\n");
|
|
303
315
|
}
|
|
304
316
|
const routeConfigChildrenText = buildRouteTreeConfig(routeTree);
|
|
305
317
|
const sortedRouteNodes = utils.multiSortBy(routeNodes, [
|
|
@@ -438,7 +450,43 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
438
450
|
}`
|
|
439
451
|
],
|
|
440
452
|
"// Create and export the route tree",
|
|
441
|
-
|
|
453
|
+
routeConfigChildrenText,
|
|
454
|
+
`interface FileRoutesByFullPath {
|
|
455
|
+
${[...createRouteNodesByFullPath(routeNodes).entries()].map(
|
|
456
|
+
([fullPath, routeNode]) => {
|
|
457
|
+
return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
|
|
458
|
+
}
|
|
459
|
+
)}
|
|
460
|
+
}`,
|
|
461
|
+
`interface FileRoutesByTo {
|
|
462
|
+
${[...createRouteNodesByTo(routeNodes).entries()].map(
|
|
463
|
+
([to, routeNode]) => {
|
|
464
|
+
return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
|
|
465
|
+
}
|
|
466
|
+
)}
|
|
467
|
+
}`,
|
|
468
|
+
`interface FileRoutesById {
|
|
469
|
+
${[...createRouteNodesById(routeNodes).entries()].map(
|
|
470
|
+
([id, routeNode]) => {
|
|
471
|
+
return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
|
|
472
|
+
}
|
|
473
|
+
)}
|
|
474
|
+
}`,
|
|
475
|
+
`interface FileRouteTypes {
|
|
476
|
+
fileRoutesByFullPath: FileRoutesByFullPath
|
|
477
|
+
fullPaths: ${[...createRouteNodesByFullPath(routeNodes).keys()].map((fullPath) => `'${fullPath}'`).join("|")}
|
|
478
|
+
fileRoutesByTo: FileRoutesByTo
|
|
479
|
+
to: ${[...createRouteNodesByTo(routeNodes).keys()].map((to) => `'${to}'`).join("|")}
|
|
480
|
+
id: ${[...createRouteNodesById(routeNodes).keys()].map((id) => `'${id}'`).join("|")}
|
|
481
|
+
fileRoutesById: FileRoutesById
|
|
482
|
+
}`,
|
|
483
|
+
`interface RootRouteChildren {
|
|
484
|
+
${routeTree.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
485
|
+
}`,
|
|
486
|
+
`const rootRouteChildren: RootRouteChildren = {
|
|
487
|
+
${routeTree.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
488
|
+
}`,
|
|
489
|
+
`export const routeTree = rootRoute._addFileChildren(rootRouteChildren)._addFileTypes<FileRouteTypes>()`,
|
|
442
490
|
...config.routeTreeFileFooter
|
|
443
491
|
].filter(Boolean).join("\n\n");
|
|
444
492
|
const createRouteManifest = () => {
|
|
@@ -507,9 +555,6 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
507
555
|
`✅ Processed ${routeNodes.length === 1 ? "route" : "routes"} in ${Date.now() - start}ms`
|
|
508
556
|
);
|
|
509
557
|
}
|
|
510
|
-
function spaces(d) {
|
|
511
|
-
return Array.from({ length: d }).map(() => " ").join("");
|
|
512
|
-
}
|
|
513
558
|
function removeTrailingUnderscores(s) {
|
|
514
559
|
return s == null ? void 0 : s.replaceAll(/(_$)/gi, "").replaceAll(/(_\/)/gi, "/");
|
|
515
560
|
}
|
|
@@ -549,6 +594,31 @@ function hasParentRoute(routes, node, routePathToCheck) {
|
|
|
549
594
|
const parentRoutePath = segments.join("/");
|
|
550
595
|
return hasParentRoute(routes, node, parentRoutePath);
|
|
551
596
|
}
|
|
597
|
+
const getResolvedRouteNodeVariableName = (routeNode) => {
|
|
598
|
+
var _a;
|
|
599
|
+
return ((_a = routeNode.children) == null ? void 0 : _a.length) ? `${routeNode.variableName}RouteWithChildren` : `${routeNode.variableName}Route`;
|
|
600
|
+
};
|
|
601
|
+
const createRouteNodesByFullPath = (routeNodes) => {
|
|
602
|
+
return new Map(
|
|
603
|
+
routeNodes.map((routeNode) => [inferFullPath(routeNode), routeNode])
|
|
604
|
+
);
|
|
605
|
+
};
|
|
606
|
+
const createRouteNodesByTo = (routeNodes) => {
|
|
607
|
+
return new Map(
|
|
608
|
+
dedupeBranchesAndIndexRoutes(routeNodes).map((routeNode) => [
|
|
609
|
+
inferTo(routeNode),
|
|
610
|
+
routeNode
|
|
611
|
+
])
|
|
612
|
+
);
|
|
613
|
+
};
|
|
614
|
+
const createRouteNodesById = (routeNodes) => {
|
|
615
|
+
return new Map(
|
|
616
|
+
routeNodes.map((routeNode) => {
|
|
617
|
+
const [_, id] = getFilePathIdAndRouteIdFromPath(routeNode.routePath);
|
|
618
|
+
return [id, routeNode];
|
|
619
|
+
})
|
|
620
|
+
);
|
|
621
|
+
};
|
|
552
622
|
const inferFullPath = (routeNode) => {
|
|
553
623
|
const fullPath = removeGroups(
|
|
554
624
|
utils.removeUnderscores(removeLayoutSegments(routeNode.routePath)) ?? ""
|
|
@@ -559,6 +629,18 @@ const inferPath = (routeNode) => {
|
|
|
559
629
|
var _a;
|
|
560
630
|
return routeNode.cleanedPath === "/" ? routeNode.cleanedPath : ((_a = routeNode.cleanedPath) == null ? void 0 : _a.replace(/\/$/, "")) ?? "";
|
|
561
631
|
};
|
|
632
|
+
const inferTo = (routeNode) => {
|
|
633
|
+
const fullPath = inferFullPath(routeNode);
|
|
634
|
+
if (fullPath === "/") return fullPath;
|
|
635
|
+
return fullPath.replace(/\/$/, "");
|
|
636
|
+
};
|
|
637
|
+
const dedupeBranchesAndIndexRoutes = (routes) => {
|
|
638
|
+
return routes.filter((route) => {
|
|
639
|
+
var _a;
|
|
640
|
+
if ((_a = route.children) == null ? void 0 : _a.find((child) => child.cleanedPath === "/")) return false;
|
|
641
|
+
return true;
|
|
642
|
+
});
|
|
643
|
+
};
|
|
562
644
|
function getFilePathIdAndRouteIdFromPath(pathname) {
|
|
563
645
|
const filePathId = removeTrailingUnderscores(pathname);
|
|
564
646
|
const id = removeGroups(filePathId ?? "");
|
|
@@ -603,10 +685,16 @@ function startAPIRouteSegmentsFromTSRFilePath(src, config) {
|
|
|
603
685
|
});
|
|
604
686
|
return segments;
|
|
605
687
|
}
|
|
688
|
+
exports.createRouteNodesByFullPath = createRouteNodesByFullPath;
|
|
689
|
+
exports.createRouteNodesById = createRouteNodesById;
|
|
690
|
+
exports.createRouteNodesByTo = createRouteNodesByTo;
|
|
691
|
+
exports.dedupeBranchesAndIndexRoutes = dedupeBranchesAndIndexRoutes;
|
|
606
692
|
exports.generator = generator;
|
|
693
|
+
exports.getResolvedRouteNodeVariableName = getResolvedRouteNodeVariableName;
|
|
607
694
|
exports.hasParentRoute = hasParentRoute;
|
|
608
695
|
exports.inferFullPath = inferFullPath;
|
|
609
696
|
exports.inferPath = inferPath;
|
|
697
|
+
exports.inferTo = inferTo;
|
|
610
698
|
exports.removeLastSegmentFromPath = removeLastSegmentFromPath;
|
|
611
699
|
exports.startAPIRouteSegmentsFromTSRFilePath = startAPIRouteSegmentsFromTSRFilePath;
|
|
612
700
|
//# sourceMappingURL=generator.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.cjs","sources":["../../src/generator.ts"],"sourcesContent":["import path from 'node:path'\nimport * as fs from 'node:fs'\nimport * as fsp from 'node:fs/promises'\nimport * as prettier from 'prettier'\nimport {\n determineInitialRoutePath,\n logging,\n multiSortBy,\n removeExt,\n removeTrailingSlash,\n removeUnderscores,\n replaceBackslash,\n routePathToVariable,\n trimPathLeft,\n} from './utils'\nimport { getRouteNodes as physicalGetRouteNodes } from './filesystem/physical/getRouteNodes'\nimport { getRouteNodes as virtualGetRouteNodes } from './filesystem/virtual/getRouteNodes'\nimport { rootPathId } from './filesystem/physical/rootPathId'\nimport type { GetRouteNodesResult, RouteNode } from './types'\nimport type { Config } from './config'\n\nlet latestTask = 0\nconst routeGroupPatternRegex = /\\(.+\\)/g\nconst possiblyNestedRouteGroupPatternRegex = /\\([^/]+\\)\\/?/g\n\nlet isFirst = false\nlet skipMessage = false\n\ntype RouteSubNode = {\n component?: RouteNode\n errorComponent?: RouteNode\n pendingComponent?: RouteNode\n loader?: RouteNode\n lazy?: RouteNode\n}\n\nexport async function generator(config: Config) {\n const logger = logging({ disabled: config.disableLogging })\n logger.log('')\n\n if (!isFirst) {\n logger.log('♻️ Generating routes...')\n isFirst = true\n } else if (skipMessage) {\n skipMessage = false\n } else {\n logger.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\n const prettierOptions: prettier.Options = {\n semi: config.semicolons,\n singleQuote: config.quoteStyle === 'single',\n parser: 'typescript',\n }\n\n let getRouteNodesResult: GetRouteNodesResult\n\n if (config.virtualRouteConfig) {\n getRouteNodesResult = await virtualGetRouteNodes(config)\n } else {\n getRouteNodesResult = await physicalGetRouteNodes(config)\n }\n\n const { rootRouteNode, routeNodes: beforeRouteNodes } = getRouteNodesResult\n if (rootRouteNode === undefined) {\n throw new Error(`rootRouteNode must not be undefined`)\n }\n const preRouteNodes = multiSortBy(beforeRouteNodes, [\n (d) => (d.routePath === '/' ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) =>\n d.filePath.match(new RegExp(`[./]${config.indexToken}[.]`)) ? 1 : -1,\n (d) =>\n d.filePath.match(\n /[./](component|errorComponent|pendingComponent|loader|lazy)[.]/,\n )\n ? 1\n : -1,\n (d) =>\n d.filePath.match(new RegExp(`[./]${config.routeToken}[.]`)) ? -1 : 1,\n (d) => (d.routePath?.endsWith('/') ? -1 : 1),\n (d) => d.routePath,\n ]).filter((d) => ![`/${rootPathId}`].includes(d.routePath || ''))\n\n const routeTree: Array<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 const routeNodes: Array<RouteNode> = []\n\n // the handleRootNode function is not being collapsed into the handleNode function\n // because it requires only a subset of the logic that the handleNode function requires\n // and it's easier to read and maintain this way\n const handleRootNode = async (node?: RouteNode) => {\n if (!node) {\n // currently this is not being handled, but it could be in the future\n // for example to handle a virtual root route\n return\n }\n\n // from here on, we are only handling the root node that's present in the file system\n const routeCode = fs.readFileSync(node.fullPath, 'utf-8')\n\n if (!routeCode) {\n const replaced = `import * as React from 'react';\nimport { Outlet, createRootRoute } from '@tanstack/react-router';\n\nexport const Route = createRootRoute({\n component: () => (\n <React.Fragment>\n <div>Hello \"${rootPathId}\"!</div>\n <Outlet />\n </React.Fragment>\n ),\n})\n\n`\n\n logger.log(`🟡 Creating ${node.fullPath}`)\n fs.writeFileSync(\n node.fullPath,\n await prettier.format(replaced, prettierOptions),\n )\n }\n }\n\n await handleRootNode(rootRouteNode)\n\n const handleNode = async (node: RouteNode) => {\n let parentRoute = hasParentRoute(routeNodes, node, node.routePath)\n\n // if the parent route is a virtual parent route, we need to find the real parent route\n if (parentRoute?.isVirtualParentRoute && parentRoute.children?.length) {\n // only if this sub-parent route returns a valid parent route, we use it, if not leave it as it\n const possibleParentRoute = hasParentRoute(\n parentRoute.children,\n node,\n node.routePath,\n )\n if (possibleParentRoute) {\n parentRoute = possibleParentRoute\n }\n }\n\n if (parentRoute) node.parent = parentRoute\n\n node.path = determineNodePath(node)\n\n const trimmedPath = trimPathLeft(node.path ?? '')\n\n const split = trimmedPath.split('/')\n const lastRouteSegment = split[split.length - 1] ?? trimmedPath\n\n node.isNonPath =\n lastRouteSegment.startsWith('_') ||\n routeGroupPatternRegex.test(lastRouteSegment)\n\n node.cleanedPath = removeGroups(\n removeUnderscores(removeLayoutSegments(node.path)) ?? '',\n )\n\n // Ensure the boilerplate for the route exists, which can be skipped for virtual parent routes and virtual routes\n if (!node.isVirtualParentRoute && !node.isVirtual) {\n const routeCode = fs.readFileSync(node.fullPath, 'utf-8')\n\n const escapedRoutePath = removeTrailingUnderscores(\n node.routePath?.replaceAll('$', '$$') ?? '',\n )\n\n let replaced = routeCode\n\n if (!routeCode) {\n if (node.isLazy) {\n replaced = [\n `import { createLazyFileRoute } from '@tanstack/react-router'`,\n `export const Route = createLazyFileRoute('${escapedRoutePath}')({\n component: () => <div>Hello ${escapedRoutePath}!</div>\n})`,\n ].join('\\n\\n')\n } else if (\n node.isRoute ||\n (!node.isComponent &&\n !node.isErrorComponent &&\n !node.isPendingComponent &&\n !node.isLoader)\n ) {\n replaced = [\n `import { createFileRoute } from '@tanstack/react-router'`,\n `export const Route = createFileRoute('${escapedRoutePath}')({\n component: () => <div>Hello ${escapedRoutePath}!</div>\n})`,\n ].join('\\n\\n')\n }\n } else {\n replaced = routeCode\n .replace(\n /(FileRoute\\(\\s*['\"])([^\\s]*)(['\"],?\\s*\\))/g,\n (match, p1, p2, p3) => `${p1}${escapedRoutePath}${p3}`,\n )\n .replace(\n /(import\\s*\\{.*)(create(Lazy)?FileRoute)(.*\\}\\s*from\\s*['\"]@tanstack\\/react-router['\"])/gs,\n (match, p1, p2, p3, p4) =>\n `${p1}${node.isLazy ? 'createLazyFileRoute' : 'createFileRoute'}${p4}`,\n )\n .replace(\n /create(Lazy)?FileRoute(\\(\\s*['\"])([^\\s]*)(['\"],?\\s*\\))/g,\n (match, p1, p2, p3, p4) =>\n `${node.isLazy ? 'createLazyFileRoute' : 'createFileRoute'}${p2}${escapedRoutePath}${p4}`,\n )\n }\n\n if (replaced !== routeCode) {\n logger.log(`🟡 Updating ${node.fullPath}`)\n await fsp.writeFile(node.fullPath, replaced)\n }\n }\n\n if (\n !node.isVirtual &&\n (node.isLoader ||\n node.isComponent ||\n node.isErrorComponent ||\n node.isPendingComponent ||\n node.isLazy)\n ) {\n routePiecesByPath[node.routePath!] =\n routePiecesByPath[node.routePath!] || {}\n\n routePiecesByPath[node.routePath!]![\n node.isLazy\n ? 'lazy'\n : node.isLoader\n ? 'loader'\n : node.isErrorComponent\n ? 'errorComponent'\n : node.isPendingComponent\n ? 'pendingComponent'\n : 'component'\n ] = node\n\n const anchorRoute = routeNodes.find((d) => d.routePath === node.routePath)\n\n if (!anchorRoute) {\n await handleNode({\n ...node,\n isVirtual: true,\n isLazy: false,\n isLoader: false,\n isComponent: false,\n isErrorComponent: false,\n isPendingComponent: false,\n })\n }\n return\n }\n\n const cleanedPathIsEmpty = (node.cleanedPath || '').length === 0\n const nonPathRoute = node.isRoute && node.isNonPath\n node.isVirtualParentRequired =\n node.isLayout || nonPathRoute ? !cleanedPathIsEmpty : false\n if (!node.isVirtual && node.isVirtualParentRequired) {\n const parentRoutePath = removeLastSegmentFromPath(node.routePath) || '/'\n const parentVariableName = routePathToVariable(parentRoutePath)\n\n const anchorRoute = routeNodes.find(\n (d) => d.routePath === parentRoutePath,\n )\n\n if (!anchorRoute) {\n const parentNode = {\n ...node,\n path: removeLastSegmentFromPath(node.path) || '/',\n filePath: removeLastSegmentFromPath(node.filePath) || '/',\n fullPath: removeLastSegmentFromPath(node.fullPath) || '/',\n routePath: parentRoutePath,\n variableName: parentVariableName,\n isVirtual: true,\n isLayout: false,\n isVirtualParentRoute: true,\n isVirtualParentRequired: false,\n }\n\n parentNode.children = parentNode.children ?? []\n parentNode.children.push(node)\n\n node.parent = parentNode\n\n if (node.isLayout) {\n // since `node.path` is used as the `id` on the route definition, we need to update it\n node.path = determineNodePath(node)\n }\n\n await handleNode(parentNode)\n } else {\n anchorRoute.children = anchorRoute.children ?? []\n anchorRoute.children.push(node)\n\n node.parent = anchorRoute\n }\n }\n\n if (node.parent) {\n if (!node.isVirtualParentRequired) {\n node.parent.children = node.parent.children ?? []\n node.parent.children.push(node)\n }\n } else {\n routeTree.push(node)\n }\n\n routeNodes.push(node)\n }\n\n for (const node of preRouteNodes.filter((d) => !d.isAPIRoute)) {\n await handleNode(node)\n }\n\n const startAPIRouteNodes: Array<RouteNode> = checkStartAPIRoutes(\n preRouteNodes.filter((d) => d.isAPIRoute),\n )\n\n const handleAPINode = async (node: RouteNode) => {\n const routeCode = fs.readFileSync(node.fullPath, 'utf-8')\n\n const escapedRoutePath = removeTrailingUnderscores(\n node.routePath?.replaceAll('$', '$$') ?? '',\n )\n\n if (!routeCode) {\n const replaced = `import { json } from '@tanstack/start'\nimport { createAPIFileRoute } from '@tanstack/start/api'\n\nexport const Route = createAPIFileRoute('${escapedRoutePath}')({\n GET: ({ request, params }) => {\n return json({ message: 'Hello ${escapedRoutePath}' })\n },\n})\n\n`\n\n logger.log(`🟡 Creating ${node.fullPath}`)\n fs.writeFileSync(\n node.fullPath,\n await prettier.format(replaced, prettierOptions),\n )\n } else {\n const copied = routeCode.replace(\n /(createAPIFileRoute\\(\\s*['\"])([^\\s]*)(['\"],?\\s*\\))/g,\n (_, p1, __, p3) => `${p1}${escapedRoutePath}${p3}`,\n )\n\n if (copied !== routeCode) {\n logger.log(`🟡 Updating ${node.fullPath}`)\n await fsp.writeFile(\n node.fullPath,\n await prettier.format(copied, prettierOptions),\n )\n }\n }\n }\n\n for (const node of startAPIRouteNodes) {\n await handleAPINode(node)\n }\n\n function buildRouteTreeConfig(nodes: Array<RouteNode>, depth = 1): string {\n const children = nodes.map((node) => {\n if (node.isRoot) {\n return\n }\n\n if (node.isLayout && !node.children?.length) {\n return\n }\n\n const route = `${node.variableName}Route`\n\n if (node.children?.length) {\n const childConfigs = buildRouteTreeConfig(node.children, depth + 1)\n return `${route}: ${route}.addChildren({${spaces(depth * 4)}${childConfigs}})`\n }\n\n return route\n })\n\n return children.filter(Boolean).join(`,`)\n }\n\n const routeConfigChildrenText = buildRouteTreeConfig(routeTree)\n\n const sortedRouteNodes = multiSortBy(routeNodes, [\n (d) => (d.routePath?.includes(`/${rootPathId}`) ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => (d.routePath?.endsWith(config.indexToken) ? -1 : 1),\n (d) => d,\n ])\n\n const imports = Object.entries({\n createFileRoute: sortedRouteNodes.some((d) => d.isVirtual),\n lazyFn: sortedRouteNodes.some(\n (node) => routePiecesByPath[node.routePath!]?.loader,\n ),\n lazyRouteComponent: sortedRouteNodes.some(\n (node) =>\n routePiecesByPath[node.routePath!]?.component ||\n routePiecesByPath[node.routePath!]?.errorComponent ||\n routePiecesByPath[node.routePath!]?.pendingComponent,\n ),\n })\n .filter((d) => d[1])\n .map((d) => d[0])\n\n const virtualRouteNodes = sortedRouteNodes.filter((d) => d.isVirtual)\n\n function getImportPath(node: RouteNode) {\n return replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, node.filePath),\n ),\n config.addExtensions,\n ),\n )\n }\n const routeImports = [\n ...config.routeTreeFileHeader,\n '// This file is auto-generated by TanStack Router',\n imports.length\n ? `import { ${imports.join(', ')} } from '@tanstack/react-router'\\n`\n : '',\n '// Import Routes',\n [\n `import { Route as rootRoute } from './${getImportPath(rootRouteNode)}'`,\n ...sortedRouteNodes\n .filter((d) => !d.isVirtual)\n .map((node) => {\n return `import { Route as ${\n node.variableName\n }Import } from './${getImportPath(node)}'`\n }),\n ].join('\\n'),\n virtualRouteNodes.length ? '// Create Virtual Routes' : '',\n virtualRouteNodes\n .map((node) => {\n return `const ${\n node.variableName\n }Import = createFileRoute('${removeTrailingUnderscores(\n node.routePath,\n )}')()`\n })\n .join('\\n'),\n '// Create/Update Routes',\n sortedRouteNodes\n .map((node) => {\n const loaderNode = routePiecesByPath[node.routePath!]?.loader\n const componentNode = routePiecesByPath[node.routePath!]?.component\n const errorComponentNode =\n routePiecesByPath[node.routePath!]?.errorComponent\n const pendingComponentNode =\n routePiecesByPath[node.routePath!]?.pendingComponent\n const lazyComponentNode = routePiecesByPath[node.routePath!]?.lazy\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 }${config.disableTypes ? '' : 'as any'})`,\n loaderNode\n ? `.updateLoader({ loader: lazyFn(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, loaderNode.filePath),\n ),\n config.addExtensions,\n ),\n )}'), 'loader') })`\n : '',\n componentNode || errorComponentNode || pendingComponentNode\n ? `.update({\n ${(\n [\n ['component', componentNode],\n ['errorComponent', errorComponentNode],\n ['pendingComponent', pendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n return `${\n d[0]\n }: lazyRouteComponent(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, d[1]!.filePath),\n ),\n config.addExtensions,\n ),\n )}'), '${d[0]}')`\n })\n .join('\\n,')}\n })`\n : '',\n lazyComponentNode\n ? `.lazy(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )}').then((d) => d.Route))`\n : '',\n ].join('')\n })\n .join('\\n\\n'),\n ...(config.disableTypes\n ? []\n : [\n '// Populate the FileRoutesByPath interface',\n `declare module '@tanstack/react-router' {\n interface FileRoutesByPath {\n ${routeNodes\n .map((routeNode) => {\n const [filePathId, routeId] = getFilePathIdAndRouteIdFromPath(\n routeNode.routePath,\n )\n\n return `'${filePathId}': {\n id: '${routeId}'\n path: '${inferPath(routeNode)}'\n fullPath: '${inferFullPath(routeNode)}'\n preLoaderRoute: typeof ${routeNode.variableName}Import\n parentRoute: typeof ${\n routeNode.isVirtualParentRequired\n ? `${routeNode.parent?.variableName}Route`\n : routeNode.parent?.variableName\n ? `${routeNode.parent.variableName}Import`\n : 'rootRoute'\n }\n }`\n })\n .join('\\n')}\n }\n}`,\n ]),\n '// Create and export the route tree',\n `export const routeTree = rootRoute.addChildren({${routeConfigChildrenText}})`,\n ...config.routeTreeFileFooter,\n ]\n .filter(Boolean)\n .join('\\n\\n')\n\n const createRouteManifest = () => {\n const routesManifest = {\n __root__: {\n filePath: rootRouteNode.filePath,\n children: routeTree.map(\n (d) => getFilePathIdAndRouteIdFromPath(d.routePath)[1],\n ),\n },\n ...Object.fromEntries(\n routeNodes.map((d) => {\n const [_, routeId] = getFilePathIdAndRouteIdFromPath(d.routePath)\n\n return [\n routeId,\n {\n filePath: d.filePath,\n parent: d.parent?.routePath\n ? getFilePathIdAndRouteIdFromPath(d.parent.routePath)[1]\n : undefined,\n children: d.children?.map(\n (childRoute) =>\n getFilePathIdAndRouteIdFromPath(childRoute.routePath)[1],\n ),\n },\n ]\n }),\n ),\n }\n\n return JSON.stringify(\n {\n routes: routesManifest,\n },\n null,\n 2,\n )\n }\n\n const routeConfigFileContent = await prettier.format(\n config.disableManifestGeneration\n ? routeImports\n : [\n routeImports,\n '\\n',\n '/* ROUTE_MANIFEST_START',\n createRouteManifest(),\n 'ROUTE_MANIFEST_END */',\n ].join('\\n'),\n prettierOptions,\n )\n\n if (!checkLatest()) return\n\n const existingRouteTreeContent = await fsp\n .readFile(path.resolve(config.generatedRouteTree), 'utf-8')\n .catch((err) => {\n if (err.code === 'ENOENT') {\n return ''\n }\n\n throw err\n })\n\n if (!checkLatest()) return\n\n // Ensure the directory exists\n await fsp.mkdir(path.dirname(path.resolve(config.generatedRouteTree)), {\n recursive: true,\n })\n\n if (!checkLatest()) return\n\n // Write the route tree file, if it has changed\n if (existingRouteTreeContent !== routeConfigFileContent) {\n await fsp.writeFile(\n path.resolve(config.generatedRouteTree),\n routeConfigFileContent,\n )\n if (!checkLatest()) return\n }\n\n logger.log(\n `✅ Processed ${routeNodes.length === 1 ? 'route' : 'routes'} in ${\n Date.now() - start\n }ms`,\n )\n}\n\nfunction spaces(d: number): string {\n return Array.from({ length: d })\n .map(() => ' ')\n .join('')\n}\n\nfunction removeTrailingUnderscores(s?: string) {\n return s?.replaceAll(/(_$)/gi, '').replaceAll(/(_\\/)/gi, '/')\n}\n\nfunction removeGroups(s: string) {\n return s.replace(possiblyNestedRouteGroupPatternRegex, '')\n}\n\n/**\n * The `node.path` is used as the `id` in the route definition.\n * This function checks if the given node has a parent and if so, it determines the correct path for the given node.\n * @param node - The node to determine the path for.\n * @returns The correct path for the given node.\n */\nfunction determineNodePath(node: RouteNode) {\n return (node.path = node.parent\n ? node.routePath?.replace(node.parent.routePath ?? '', '') || '/'\n : node.routePath)\n}\n\n/**\n * Removes the last segment from a given path. Segments are considered to be separated by a '/'.\n *\n * @param {string} routePath - The path from which to remove the last segment. Defaults to '/'.\n * @returns {string} The path with the last segment removed.\n * @example\n * removeLastSegmentFromPath('/workspace/_auth/foo') // '/workspace/_auth'\n */\nexport function removeLastSegmentFromPath(routePath: string = '/'): string {\n const segments = routePath.split('/')\n segments.pop() // Remove the last segment\n return segments.join('/')\n}\n\n/**\n * Removes all segments from a given path that start with an underscore ('_').\n *\n * @param {string} routePath - The path from which to remove segments. Defaults to '/'.\n * @returns {string} The path with all underscore-prefixed segments removed.\n * @example\n * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'\n */\nfunction removeLayoutSegments(routePath: string = '/'): string {\n const segments = routePath.split('/')\n const newSegments = segments.filter((segment) => !segment.startsWith('_'))\n return newSegments.join('/')\n}\n\nexport function hasParentRoute(\n routes: Array<RouteNode>,\n node: RouteNode,\n routePathToCheck: string | undefined,\n): RouteNode | null {\n if (!routePathToCheck || routePathToCheck === '/') {\n return null\n }\n\n const sortedNodes = multiSortBy(routes, [\n (d) => d.routePath!.length * -1,\n (d) => d.variableName,\n ]).filter((d) => d.routePath !== `/${rootPathId}`)\n\n for (const route of sortedNodes) {\n if (route.routePath === '/') continue\n\n if (\n routePathToCheck.startsWith(`${route.routePath}/`) &&\n route.routePath !== routePathToCheck\n ) {\n return route\n }\n }\n\n const segments = routePathToCheck.split('/')\n segments.pop() // Remove the last segment\n const parentRoutePath = segments.join('/')\n\n return hasParentRoute(routes, node, parentRoutePath)\n}\n\n/**\n * Infers the full path for use by TS\n */\nexport const inferFullPath = (routeNode: RouteNode): string => {\n const fullPath = removeGroups(\n removeUnderscores(removeLayoutSegments(routeNode.routePath)) ?? '',\n )\n\n return routeNode.cleanedPath === '/' ? fullPath : fullPath.replace(/\\/$/, '')\n}\n\n/**\n * Infers the path for use by TS\n */\nexport const inferPath = (routeNode: RouteNode): string => {\n return routeNode.cleanedPath === '/'\n ? routeNode.cleanedPath\n : (routeNode.cleanedPath?.replace(/\\/$/, '') ?? '')\n}\n\nfunction getFilePathIdAndRouteIdFromPath(pathname?: string) {\n const filePathId = removeTrailingUnderscores(pathname)\n const id = removeGroups(filePathId ?? '')\n\n return [filePathId, id] as const\n}\n\nfunction checkStartAPIRoutes(_routes: Array<RouteNode>) {\n if (_routes.length === 0) {\n return []\n }\n\n // Make sure these are valid URLs\n // Route Groups and Layout Routes aren't being removed since\n // you may want to have an API route that starts with an underscore\n // or be wrapped in parentheses\n const routes = _routes.map((d) => {\n const routePath = removeTrailingSlash(d.routePath ?? '')\n return { ...d, routePath }\n })\n\n // Check no two API routes have the same routePath\n // if they do, throw an error with the conflicting filePaths\n const routePaths = routes.map((d) => d.routePath)\n const uniqueRoutePaths = new Set(routePaths)\n if (routePaths.length !== uniqueRoutePaths.size) {\n const duplicateRoutePaths = routePaths.filter(\n (d, i) => routePaths.indexOf(d) !== i,\n )\n const conflictingFiles = routes\n .filter((d) => duplicateRoutePaths.includes(d.routePath))\n .map((d) => `${d.fullPath}`)\n const errorMessage = `Conflicting configuration paths was for found for the following API route${duplicateRoutePaths.length > 1 ? 's' : ''}: ${duplicateRoutePaths\n .map((p) => `\"${p}\"`)\n .join(', ')}.\nPlease ensure each API route has a unique route path.\nConflicting files: \\n ${conflictingFiles.join('\\n ')}\\n`\n throw new Error(errorMessage)\n }\n\n return routes\n}\n\nexport type StartAPIRoutePathSegment = {\n value: string\n type: 'path' | 'param' | 'splat'\n}\n\n/**\n * This function takes in a path in the format accepted by TanStack Router\n * and returns an array of path segments that can be used to generate\n * the pathname of the TanStack Start API route.\n *\n * @param src\n * @returns\n */\nexport function startAPIRouteSegmentsFromTSRFilePath(\n src: string,\n config: Config,\n): Array<StartAPIRoutePathSegment> {\n const routePath = determineInitialRoutePath(src)\n\n const parts = routePath\n .replaceAll('.', '/')\n .split('/')\n .filter((p) => !!p && p !== config.indexToken)\n const segments: Array<StartAPIRoutePathSegment> = parts.map((part) => {\n if (part.startsWith('$')) {\n if (part === '$') {\n return { value: part, type: 'splat' }\n }\n\n part.replaceAll('$', '')\n return { value: part, type: 'param' }\n }\n\n return { value: part, type: 'path' }\n })\n\n return segments\n}\n"],"names":["logging","virtualGetRouteNodes","physicalGetRouteNodes","multiSortBy","rootPathId","fs","prettier","trimPathLeft","removeUnderscores","fsp","routePathToVariable","replaceBackslash","removeExt","removeTrailingSlash","determineInitialRoutePath"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generator.cjs","sources":["../../src/generator.ts"],"sourcesContent":["import path from 'node:path'\nimport * as fs from 'node:fs'\nimport * as fsp from 'node:fs/promises'\nimport * as prettier from 'prettier'\nimport {\n determineInitialRoutePath,\n logging,\n multiSortBy,\n removeExt,\n removeTrailingSlash,\n removeUnderscores,\n replaceBackslash,\n routePathToVariable,\n trimPathLeft,\n} from './utils'\nimport { getRouteNodes as physicalGetRouteNodes } from './filesystem/physical/getRouteNodes'\nimport { getRouteNodes as virtualGetRouteNodes } from './filesystem/virtual/getRouteNodes'\nimport { rootPathId } from './filesystem/physical/rootPathId'\nimport type { GetRouteNodesResult, RouteNode } from './types'\nimport type { Config } from './config'\n\nlet latestTask = 0\nconst routeGroupPatternRegex = /\\(.+\\)/g\nconst possiblyNestedRouteGroupPatternRegex = /\\([^/]+\\)\\/?/g\n\nlet isFirst = false\nlet skipMessage = false\n\ntype RouteSubNode = {\n component?: RouteNode\n errorComponent?: RouteNode\n pendingComponent?: RouteNode\n loader?: RouteNode\n lazy?: RouteNode\n}\n\nexport async function generator(config: Config) {\n const logger = logging({ disabled: config.disableLogging })\n logger.log('')\n\n if (!isFirst) {\n logger.log('♻️ Generating routes...')\n isFirst = true\n } else if (skipMessage) {\n skipMessage = false\n } else {\n logger.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\n const prettierOptions: prettier.Options = {\n semi: config.semicolons,\n singleQuote: config.quoteStyle === 'single',\n parser: 'typescript',\n }\n\n let getRouteNodesResult: GetRouteNodesResult\n\n if (config.virtualRouteConfig) {\n getRouteNodesResult = await virtualGetRouteNodes(config)\n } else {\n getRouteNodesResult = await physicalGetRouteNodes(config)\n }\n\n const { rootRouteNode, routeNodes: beforeRouteNodes } = getRouteNodesResult\n if (rootRouteNode === undefined) {\n throw new Error(`rootRouteNode must not be undefined`)\n }\n const preRouteNodes = multiSortBy(beforeRouteNodes, [\n (d) => (d.routePath === '/' ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) =>\n d.filePath.match(new RegExp(`[./]${config.indexToken}[.]`)) ? 1 : -1,\n (d) =>\n d.filePath.match(\n /[./](component|errorComponent|pendingComponent|loader|lazy)[.]/,\n )\n ? 1\n : -1,\n (d) =>\n d.filePath.match(new RegExp(`[./]${config.routeToken}[.]`)) ? -1 : 1,\n (d) => (d.routePath?.endsWith('/') ? -1 : 1),\n (d) => d.routePath,\n ]).filter((d) => ![`/${rootPathId}`].includes(d.routePath || ''))\n\n const routeTree: Array<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 const routeNodes: Array<RouteNode> = []\n\n // the handleRootNode function is not being collapsed into the handleNode function\n // because it requires only a subset of the logic that the handleNode function requires\n // and it's easier to read and maintain this way\n const handleRootNode = async (node?: RouteNode) => {\n if (!node) {\n // currently this is not being handled, but it could be in the future\n // for example to handle a virtual root route\n return\n }\n\n // from here on, we are only handling the root node that's present in the file system\n const routeCode = fs.readFileSync(node.fullPath, 'utf-8')\n\n if (!routeCode) {\n const replaced = `import * as React from 'react';\nimport { Outlet, createRootRoute } from '@tanstack/react-router';\n\nexport const Route = createRootRoute({\n component: () => (\n <React.Fragment>\n <div>Hello \"${rootPathId}\"!</div>\n <Outlet />\n </React.Fragment>\n ),\n})\n\n`\n\n logger.log(`🟡 Creating ${node.fullPath}`)\n fs.writeFileSync(\n node.fullPath,\n await prettier.format(replaced, prettierOptions),\n )\n }\n }\n\n await handleRootNode(rootRouteNode)\n\n const handleNode = async (node: RouteNode) => {\n let parentRoute = hasParentRoute(routeNodes, node, node.routePath)\n\n // if the parent route is a virtual parent route, we need to find the real parent route\n if (parentRoute?.isVirtualParentRoute && parentRoute.children?.length) {\n // only if this sub-parent route returns a valid parent route, we use it, if not leave it as it\n const possibleParentRoute = hasParentRoute(\n parentRoute.children,\n node,\n node.routePath,\n )\n if (possibleParentRoute) {\n parentRoute = possibleParentRoute\n }\n }\n\n if (parentRoute) node.parent = parentRoute\n\n node.path = determineNodePath(node)\n\n const trimmedPath = trimPathLeft(node.path ?? '')\n\n const split = trimmedPath.split('/')\n const lastRouteSegment = split[split.length - 1] ?? trimmedPath\n\n node.isNonPath =\n lastRouteSegment.startsWith('_') ||\n routeGroupPatternRegex.test(lastRouteSegment)\n\n node.cleanedPath = removeGroups(\n removeUnderscores(removeLayoutSegments(node.path)) ?? '',\n )\n\n // Ensure the boilerplate for the route exists, which can be skipped for virtual parent routes and virtual routes\n if (!node.isVirtualParentRoute && !node.isVirtual) {\n const routeCode = fs.readFileSync(node.fullPath, 'utf-8')\n\n const escapedRoutePath = removeTrailingUnderscores(\n node.routePath?.replaceAll('$', '$$') ?? '',\n )\n\n let replaced = routeCode\n\n if (!routeCode) {\n if (node.isLazy) {\n replaced = [\n `import { createLazyFileRoute } from '@tanstack/react-router'`,\n `export const Route = createLazyFileRoute('${escapedRoutePath}')({\n component: () => <div>Hello ${escapedRoutePath}!</div>\n})`,\n ].join('\\n\\n')\n } else if (\n node.isRoute ||\n (!node.isComponent &&\n !node.isErrorComponent &&\n !node.isPendingComponent &&\n !node.isLoader)\n ) {\n replaced = [\n `import { createFileRoute } from '@tanstack/react-router'`,\n `export const Route = createFileRoute('${escapedRoutePath}')({\n component: () => <div>Hello ${escapedRoutePath}!</div>\n})`,\n ].join('\\n\\n')\n }\n } else {\n replaced = routeCode\n .replace(\n /(FileRoute\\(\\s*['\"])([^\\s]*)(['\"],?\\s*\\))/g,\n (match, p1, p2, p3) => `${p1}${escapedRoutePath}${p3}`,\n )\n .replace(\n /(import\\s*\\{.*)(create(Lazy)?FileRoute)(.*\\}\\s*from\\s*['\"]@tanstack\\/react-router['\"])/gs,\n (match, p1, p2, p3, p4) =>\n `${p1}${node.isLazy ? 'createLazyFileRoute' : 'createFileRoute'}${p4}`,\n )\n .replace(\n /create(Lazy)?FileRoute(\\(\\s*['\"])([^\\s]*)(['\"],?\\s*\\))/g,\n (match, p1, p2, p3, p4) =>\n `${node.isLazy ? 'createLazyFileRoute' : 'createFileRoute'}${p2}${escapedRoutePath}${p4}`,\n )\n }\n\n if (replaced !== routeCode) {\n logger.log(`🟡 Updating ${node.fullPath}`)\n await fsp.writeFile(node.fullPath, replaced)\n }\n }\n\n if (\n !node.isVirtual &&\n (node.isLoader ||\n node.isComponent ||\n node.isErrorComponent ||\n node.isPendingComponent ||\n node.isLazy)\n ) {\n routePiecesByPath[node.routePath!] =\n routePiecesByPath[node.routePath!] || {}\n\n routePiecesByPath[node.routePath!]![\n node.isLazy\n ? 'lazy'\n : node.isLoader\n ? 'loader'\n : node.isErrorComponent\n ? 'errorComponent'\n : node.isPendingComponent\n ? 'pendingComponent'\n : 'component'\n ] = node\n\n const anchorRoute = routeNodes.find((d) => d.routePath === node.routePath)\n\n if (!anchorRoute) {\n await handleNode({\n ...node,\n isVirtual: true,\n isLazy: false,\n isLoader: false,\n isComponent: false,\n isErrorComponent: false,\n isPendingComponent: false,\n })\n }\n return\n }\n\n const cleanedPathIsEmpty = (node.cleanedPath || '').length === 0\n const nonPathRoute = node.isRoute && node.isNonPath\n node.isVirtualParentRequired =\n node.isLayout || nonPathRoute ? !cleanedPathIsEmpty : false\n if (!node.isVirtual && node.isVirtualParentRequired) {\n const parentRoutePath = removeLastSegmentFromPath(node.routePath) || '/'\n const parentVariableName = routePathToVariable(parentRoutePath)\n\n const anchorRoute = routeNodes.find(\n (d) => d.routePath === parentRoutePath,\n )\n\n if (!anchorRoute) {\n const parentNode = {\n ...node,\n path: removeLastSegmentFromPath(node.path) || '/',\n filePath: removeLastSegmentFromPath(node.filePath) || '/',\n fullPath: removeLastSegmentFromPath(node.fullPath) || '/',\n routePath: parentRoutePath,\n variableName: parentVariableName,\n isVirtual: true,\n isLayout: false,\n isVirtualParentRoute: true,\n isVirtualParentRequired: false,\n }\n\n parentNode.children = parentNode.children ?? []\n parentNode.children.push(node)\n\n node.parent = parentNode\n\n if (node.isLayout) {\n // since `node.path` is used as the `id` on the route definition, we need to update it\n node.path = determineNodePath(node)\n }\n\n await handleNode(parentNode)\n } else {\n anchorRoute.children = anchorRoute.children ?? []\n anchorRoute.children.push(node)\n\n node.parent = anchorRoute\n }\n }\n\n if (node.parent) {\n if (!node.isVirtualParentRequired) {\n node.parent.children = node.parent.children ?? []\n node.parent.children.push(node)\n }\n } else {\n routeTree.push(node)\n }\n\n routeNodes.push(node)\n }\n\n for (const node of preRouteNodes.filter((d) => !d.isAPIRoute)) {\n await handleNode(node)\n }\n\n const startAPIRouteNodes: Array<RouteNode> = checkStartAPIRoutes(\n preRouteNodes.filter((d) => d.isAPIRoute),\n )\n\n const handleAPINode = async (node: RouteNode) => {\n const routeCode = fs.readFileSync(node.fullPath, 'utf-8')\n\n const escapedRoutePath = removeTrailingUnderscores(\n node.routePath?.replaceAll('$', '$$') ?? '',\n )\n\n if (!routeCode) {\n const replaced = `import { json } from '@tanstack/start'\nimport { createAPIFileRoute } from '@tanstack/start/api'\n\nexport const Route = createAPIFileRoute('${escapedRoutePath}')({\n GET: ({ request, params }) => {\n return json({ message: 'Hello ${escapedRoutePath}' })\n },\n})\n\n`\n\n logger.log(`🟡 Creating ${node.fullPath}`)\n fs.writeFileSync(\n node.fullPath,\n await prettier.format(replaced, prettierOptions),\n )\n } else {\n const copied = routeCode.replace(\n /(createAPIFileRoute\\(\\s*['\"])([^\\s]*)(['\"],?\\s*\\))/g,\n (_, p1, __, p3) => `${p1}${escapedRoutePath}${p3}`,\n )\n\n if (copied !== routeCode) {\n logger.log(`🟡 Updating ${node.fullPath}`)\n await fsp.writeFile(\n node.fullPath,\n await prettier.format(copied, prettierOptions),\n )\n }\n }\n }\n\n for (const node of startAPIRouteNodes) {\n await handleAPINode(node)\n }\n\n function buildRouteTreeConfig(nodes: Array<RouteNode>, depth = 1): string {\n const children = nodes.map((node) => {\n if (node.isRoot) {\n return\n }\n\n if (node.isLayout && !node.children?.length) {\n return\n }\n\n const route = `${node.variableName}Route`\n\n if (node.children?.length) {\n const childConfigs = buildRouteTreeConfig(node.children, depth + 1)\n\n const childrenDeclaration = `interface ${route}Children {\n ${node.children.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}\n }`\n\n const children = `const ${route}Children: ${route}Children = {\n ${node.children.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(',')}\n }`\n\n const routeWithChildren = `const ${route}WithChildren = ${route}._addFileChildren(${route}Children)`\n\n return [\n childConfigs,\n childrenDeclaration,\n children,\n routeWithChildren,\n ].join('\\n\\n')\n }\n\n return undefined\n })\n\n return children.filter(Boolean).join('\\n\\n')\n }\n\n const routeConfigChildrenText = buildRouteTreeConfig(routeTree)\n\n const sortedRouteNodes = multiSortBy(routeNodes, [\n (d) => (d.routePath?.includes(`/${rootPathId}`) ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => (d.routePath?.endsWith(config.indexToken) ? -1 : 1),\n (d) => d,\n ])\n\n const imports = Object.entries({\n createFileRoute: sortedRouteNodes.some((d) => d.isVirtual),\n lazyFn: sortedRouteNodes.some(\n (node) => routePiecesByPath[node.routePath!]?.loader,\n ),\n lazyRouteComponent: sortedRouteNodes.some(\n (node) =>\n routePiecesByPath[node.routePath!]?.component ||\n routePiecesByPath[node.routePath!]?.errorComponent ||\n routePiecesByPath[node.routePath!]?.pendingComponent,\n ),\n })\n .filter((d) => d[1])\n .map((d) => d[0])\n\n const virtualRouteNodes = sortedRouteNodes.filter((d) => d.isVirtual)\n\n function getImportPath(node: RouteNode) {\n return replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, node.filePath),\n ),\n config.addExtensions,\n ),\n )\n }\n const routeImports = [\n ...config.routeTreeFileHeader,\n '// This file is auto-generated by TanStack Router',\n imports.length\n ? `import { ${imports.join(', ')} } from '@tanstack/react-router'\\n`\n : '',\n '// Import Routes',\n [\n `import { Route as rootRoute } from './${getImportPath(rootRouteNode)}'`,\n ...sortedRouteNodes\n .filter((d) => !d.isVirtual)\n .map((node) => {\n return `import { Route as ${\n node.variableName\n }Import } from './${getImportPath(node)}'`\n }),\n ].join('\\n'),\n virtualRouteNodes.length ? '// Create Virtual Routes' : '',\n virtualRouteNodes\n .map((node) => {\n return `const ${\n node.variableName\n }Import = createFileRoute('${removeTrailingUnderscores(\n node.routePath,\n )}')()`\n })\n .join('\\n'),\n '// Create/Update Routes',\n sortedRouteNodes\n .map((node) => {\n const loaderNode = routePiecesByPath[node.routePath!]?.loader\n const componentNode = routePiecesByPath[node.routePath!]?.component\n const errorComponentNode =\n routePiecesByPath[node.routePath!]?.errorComponent\n const pendingComponentNode =\n routePiecesByPath[node.routePath!]?.pendingComponent\n const lazyComponentNode = routePiecesByPath[node.routePath!]?.lazy\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 }${config.disableTypes ? '' : 'as any'})`,\n loaderNode\n ? `.updateLoader({ loader: lazyFn(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, loaderNode.filePath),\n ),\n config.addExtensions,\n ),\n )}'), 'loader') })`\n : '',\n componentNode || errorComponentNode || pendingComponentNode\n ? `.update({\n ${(\n [\n ['component', componentNode],\n ['errorComponent', errorComponentNode],\n ['pendingComponent', pendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n return `${\n d[0]\n }: lazyRouteComponent(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, d[1]!.filePath),\n ),\n config.addExtensions,\n ),\n )}'), '${d[0]}')`\n })\n .join('\\n,')}\n })`\n : '',\n lazyComponentNode\n ? `.lazy(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )}').then((d) => d.Route))`\n : '',\n ].join('')\n })\n .join('\\n\\n'),\n ...(config.disableTypes\n ? []\n : [\n '// Populate the FileRoutesByPath interface',\n `declare module '@tanstack/react-router' {\n interface FileRoutesByPath {\n ${routeNodes\n .map((routeNode) => {\n const [filePathId, routeId] = getFilePathIdAndRouteIdFromPath(\n routeNode.routePath,\n )\n\n return `'${filePathId}': {\n id: '${routeId}'\n path: '${inferPath(routeNode)}'\n fullPath: '${inferFullPath(routeNode)}'\n preLoaderRoute: typeof ${routeNode.variableName}Import\n parentRoute: typeof ${\n routeNode.isVirtualParentRequired\n ? `${routeNode.parent?.variableName}Route`\n : routeNode.parent?.variableName\n ? `${routeNode.parent.variableName}Import`\n : 'rootRoute'\n }\n }`\n })\n .join('\\n')}\n }\n}`,\n ]),\n '// Create and export the route tree',\n routeConfigChildrenText,\n `interface FileRoutesByFullPath {\n ${[...createRouteNodesByFullPath(routeNodes).entries()].map(\n ([fullPath, routeNode]) => {\n return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n },\n )}\n }`,\n `interface FileRoutesByTo {\n ${[...createRouteNodesByTo(routeNodes).entries()].map(\n ([to, routeNode]) => {\n return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n },\n )}\n }`,\n `interface FileRoutesById {\n ${[...createRouteNodesById(routeNodes).entries()].map(\n ([id, routeNode]) => {\n return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n },\n )}\n }`,\n `interface FileRouteTypes {\n fileRoutesByFullPath: FileRoutesByFullPath\n fullPaths: ${[...createRouteNodesByFullPath(routeNodes).keys()].map((fullPath) => `'${fullPath}'`).join('|')}\n fileRoutesByTo: FileRoutesByTo\n to: ${[...createRouteNodesByTo(routeNodes).keys()].map((to) => `'${to}'`).join('|')}\n id: ${[...createRouteNodesById(routeNodes).keys()].map((id) => `'${id}'`).join('|')}\n fileRoutesById: FileRoutesById\n }`,\n `interface RootRouteChildren {\n ${routeTree.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}\n }`,\n `const rootRouteChildren: RootRouteChildren = {\n ${routeTree.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(',')}\n }`,\n `export const routeTree = rootRoute._addFileChildren(rootRouteChildren)._addFileTypes<FileRouteTypes>()`,\n ...config.routeTreeFileFooter,\n ]\n .filter(Boolean)\n .join('\\n\\n')\n\n const createRouteManifest = () => {\n const routesManifest = {\n __root__: {\n filePath: rootRouteNode.filePath,\n children: routeTree.map(\n (d) => getFilePathIdAndRouteIdFromPath(d.routePath)[1],\n ),\n },\n ...Object.fromEntries(\n routeNodes.map((d) => {\n const [_, routeId] = getFilePathIdAndRouteIdFromPath(d.routePath)\n\n return [\n routeId,\n {\n filePath: d.filePath,\n parent: d.parent?.routePath\n ? getFilePathIdAndRouteIdFromPath(d.parent.routePath)[1]\n : undefined,\n children: d.children?.map(\n (childRoute) =>\n getFilePathIdAndRouteIdFromPath(childRoute.routePath)[1],\n ),\n },\n ]\n }),\n ),\n }\n\n return JSON.stringify(\n {\n routes: routesManifest,\n },\n null,\n 2,\n )\n }\n\n const routeConfigFileContent = await prettier.format(\n config.disableManifestGeneration\n ? routeImports\n : [\n routeImports,\n '\\n',\n '/* ROUTE_MANIFEST_START',\n createRouteManifest(),\n 'ROUTE_MANIFEST_END */',\n ].join('\\n'),\n prettierOptions,\n )\n\n if (!checkLatest()) return\n\n const existingRouteTreeContent = await fsp\n .readFile(path.resolve(config.generatedRouteTree), 'utf-8')\n .catch((err) => {\n if (err.code === 'ENOENT') {\n return ''\n }\n\n throw err\n })\n\n if (!checkLatest()) return\n\n // Ensure the directory exists\n await fsp.mkdir(path.dirname(path.resolve(config.generatedRouteTree)), {\n recursive: true,\n })\n\n if (!checkLatest()) return\n\n // Write the route tree file, if it has changed\n if (existingRouteTreeContent !== routeConfigFileContent) {\n await fsp.writeFile(\n path.resolve(config.generatedRouteTree),\n routeConfigFileContent,\n )\n if (!checkLatest()) return\n }\n\n logger.log(\n `✅ Processed ${routeNodes.length === 1 ? 'route' : 'routes'} in ${\n Date.now() - start\n }ms`,\n )\n}\n\nfunction spaces(d: number): string {\n return Array.from({ length: d })\n .map(() => ' ')\n .join('')\n}\n\nfunction removeTrailingUnderscores(s?: string) {\n return s?.replaceAll(/(_$)/gi, '').replaceAll(/(_\\/)/gi, '/')\n}\n\nfunction removeGroups(s: string) {\n return s.replace(possiblyNestedRouteGroupPatternRegex, '')\n}\n\n/**\n * The `node.path` is used as the `id` in the route definition.\n * This function checks if the given node has a parent and if so, it determines the correct path for the given node.\n * @param node - The node to determine the path for.\n * @returns The correct path for the given node.\n */\nfunction determineNodePath(node: RouteNode) {\n return (node.path = node.parent\n ? node.routePath?.replace(node.parent.routePath ?? '', '') || '/'\n : node.routePath)\n}\n\n/**\n * Removes the last segment from a given path. Segments are considered to be separated by a '/'.\n *\n * @param {string} routePath - The path from which to remove the last segment. Defaults to '/'.\n * @returns {string} The path with the last segment removed.\n * @example\n * removeLastSegmentFromPath('/workspace/_auth/foo') // '/workspace/_auth'\n */\nexport function removeLastSegmentFromPath(routePath: string = '/'): string {\n const segments = routePath.split('/')\n segments.pop() // Remove the last segment\n return segments.join('/')\n}\n\n/**\n * Removes all segments from a given path that start with an underscore ('_').\n *\n * @param {string} routePath - The path from which to remove segments. Defaults to '/'.\n * @returns {string} The path with all underscore-prefixed segments removed.\n * @example\n * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'\n */\nfunction removeLayoutSegments(routePath: string = '/'): string {\n const segments = routePath.split('/')\n const newSegments = segments.filter((segment) => !segment.startsWith('_'))\n return newSegments.join('/')\n}\n\nexport function hasParentRoute(\n routes: Array<RouteNode>,\n node: RouteNode,\n routePathToCheck: string | undefined,\n): RouteNode | null {\n if (!routePathToCheck || routePathToCheck === '/') {\n return null\n }\n\n const sortedNodes = multiSortBy(routes, [\n (d) => d.routePath!.length * -1,\n (d) => d.variableName,\n ]).filter((d) => d.routePath !== `/${rootPathId}`)\n\n for (const route of sortedNodes) {\n if (route.routePath === '/') continue\n\n if (\n routePathToCheck.startsWith(`${route.routePath}/`) &&\n route.routePath !== routePathToCheck\n ) {\n return route\n }\n }\n\n const segments = routePathToCheck.split('/')\n segments.pop() // Remove the last segment\n const parentRoutePath = segments.join('/')\n\n return hasParentRoute(routes, node, parentRoutePath)\n}\n\n/**\n * Gets the final variable name for a route\n */\nexport const getResolvedRouteNodeVariableName = (\n routeNode: RouteNode,\n): string => {\n return routeNode.children?.length\n ? `${routeNode.variableName}RouteWithChildren`\n : `${routeNode.variableName}Route`\n}\n\n/**\n * Creates a map from fullPath to routeNode\n */\nexport const createRouteNodesByFullPath = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n routeNodes.map((routeNode) => [inferFullPath(routeNode), routeNode]),\n )\n}\n\n/**\n * Create a map from 'to' to a routeNode\n */\nexport const createRouteNodesByTo = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n dedupeBranchesAndIndexRoutes(routeNodes).map((routeNode) => [\n inferTo(routeNode),\n routeNode,\n ]),\n )\n}\n\n/**\n * Create a map from 'id' to a routeNode\n */\nexport const createRouteNodesById = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n routeNodes.map((routeNode) => {\n const [_, id] = getFilePathIdAndRouteIdFromPath(routeNode.routePath)\n return [id, routeNode]\n }),\n )\n}\n\n/**\n * Infers the full path for use by TS\n */\nexport const inferFullPath = (routeNode: RouteNode): string => {\n const fullPath = removeGroups(\n removeUnderscores(removeLayoutSegments(routeNode.routePath)) ?? '',\n )\n\n return routeNode.cleanedPath === '/' ? fullPath : fullPath.replace(/\\/$/, '')\n}\n\n/**\n * Infers the path for use by TS\n */\nexport const inferPath = (routeNode: RouteNode): string => {\n return routeNode.cleanedPath === '/'\n ? routeNode.cleanedPath\n : (routeNode.cleanedPath?.replace(/\\/$/, '') ?? '')\n}\n\n/**\n * Infers to path\n */\nexport const inferTo = (routeNode: RouteNode): string => {\n const fullPath = inferFullPath(routeNode)\n\n if (fullPath === '/') return fullPath\n\n return fullPath.replace(/\\/$/, '')\n}\n\n/**\n * Dedupes branches and index routes\n */\nexport const dedupeBranchesAndIndexRoutes = (\n routes: Array<RouteNode>,\n): Array<RouteNode> => {\n return routes.filter((route) => {\n if (route.children?.find((child) => child.cleanedPath === '/')) return false\n return true\n })\n}\n\nfunction getFilePathIdAndRouteIdFromPath(pathname?: string) {\n const filePathId = removeTrailingUnderscores(pathname)\n const id = removeGroups(filePathId ?? '')\n\n return [filePathId, id] as const\n}\n\nfunction checkStartAPIRoutes(_routes: Array<RouteNode>) {\n if (_routes.length === 0) {\n return []\n }\n\n // Make sure these are valid URLs\n // Route Groups and Layout Routes aren't being removed since\n // you may want to have an API route that starts with an underscore\n // or be wrapped in parentheses\n const routes = _routes.map((d) => {\n const routePath = removeTrailingSlash(d.routePath ?? '')\n return { ...d, routePath }\n })\n\n // Check no two API routes have the same routePath\n // if they do, throw an error with the conflicting filePaths\n const routePaths = routes.map((d) => d.routePath)\n const uniqueRoutePaths = new Set(routePaths)\n if (routePaths.length !== uniqueRoutePaths.size) {\n const duplicateRoutePaths = routePaths.filter(\n (d, i) => routePaths.indexOf(d) !== i,\n )\n const conflictingFiles = routes\n .filter((d) => duplicateRoutePaths.includes(d.routePath))\n .map((d) => `${d.fullPath}`)\n const errorMessage = `Conflicting configuration paths was for found for the following API route${duplicateRoutePaths.length > 1 ? 's' : ''}: ${duplicateRoutePaths\n .map((p) => `\"${p}\"`)\n .join(', ')}.\nPlease ensure each API route has a unique route path.\nConflicting files: \\n ${conflictingFiles.join('\\n ')}\\n`\n throw new Error(errorMessage)\n }\n\n return routes\n}\n\nexport type StartAPIRoutePathSegment = {\n value: string\n type: 'path' | 'param' | 'splat'\n}\n\n/**\n * This function takes in a path in the format accepted by TanStack Router\n * and returns an array of path segments that can be used to generate\n * the pathname of the TanStack Start API route.\n *\n * @param src\n * @returns\n */\nexport function startAPIRouteSegmentsFromTSRFilePath(\n src: string,\n config: Config,\n): Array<StartAPIRoutePathSegment> {\n const routePath = determineInitialRoutePath(src)\n\n const parts = routePath\n .replaceAll('.', '/')\n .split('/')\n .filter((p) => !!p && p !== config.indexToken)\n const segments: Array<StartAPIRoutePathSegment> = parts.map((part) => {\n if (part.startsWith('$')) {\n if (part === '$') {\n return { value: part, type: 'splat' }\n }\n\n part.replaceAll('$', '')\n return { value: part, type: 'param' }\n }\n\n return { value: part, type: 'path' }\n })\n\n return segments\n}\n"],"names":["logging","virtualGetRouteNodes","physicalGetRouteNodes","multiSortBy","rootPathId","fs","prettier","trimPathLeft","removeUnderscores","fsp","routePathToVariable","children","replaceBackslash","removeExt","removeTrailingSlash","determineInitialRoutePath"],"mappings":"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"}
|
package/dist/cjs/generator.d.cts
CHANGED
|
@@ -11,6 +11,22 @@ export declare function generator(config: Config): Promise<void>;
|
|
|
11
11
|
*/
|
|
12
12
|
export declare function removeLastSegmentFromPath(routePath?: string): string;
|
|
13
13
|
export declare function hasParentRoute(routes: Array<RouteNode>, node: RouteNode, routePathToCheck: string | undefined): RouteNode | null;
|
|
14
|
+
/**
|
|
15
|
+
* Gets the final variable name for a route
|
|
16
|
+
*/
|
|
17
|
+
export declare const getResolvedRouteNodeVariableName: (routeNode: RouteNode) => string;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a map from fullPath to routeNode
|
|
20
|
+
*/
|
|
21
|
+
export declare const createRouteNodesByFullPath: (routeNodes: Array<RouteNode>) => Map<string, RouteNode>;
|
|
22
|
+
/**
|
|
23
|
+
* Create a map from 'to' to a routeNode
|
|
24
|
+
*/
|
|
25
|
+
export declare const createRouteNodesByTo: (routeNodes: Array<RouteNode>) => Map<string, RouteNode>;
|
|
26
|
+
/**
|
|
27
|
+
* Create a map from 'id' to a routeNode
|
|
28
|
+
*/
|
|
29
|
+
export declare const createRouteNodesById: (routeNodes: Array<RouteNode>) => Map<string, RouteNode>;
|
|
14
30
|
/**
|
|
15
31
|
* Infers the full path for use by TS
|
|
16
32
|
*/
|
|
@@ -19,6 +35,14 @@ export declare const inferFullPath: (routeNode: RouteNode) => string;
|
|
|
19
35
|
* Infers the path for use by TS
|
|
20
36
|
*/
|
|
21
37
|
export declare const inferPath: (routeNode: RouteNode) => string;
|
|
38
|
+
/**
|
|
39
|
+
* Infers to path
|
|
40
|
+
*/
|
|
41
|
+
export declare const inferTo: (routeNode: RouteNode) => string;
|
|
42
|
+
/**
|
|
43
|
+
* Dedupes branches and index routes
|
|
44
|
+
*/
|
|
45
|
+
export declare const dedupeBranchesAndIndexRoutes: (routes: Array<RouteNode>) => Array<RouteNode>;
|
|
22
46
|
export type StartAPIRoutePathSegment = {
|
|
23
47
|
value: string;
|
|
24
48
|
type: 'path' | 'param' | 'splat';
|
package/dist/esm/generator.d.ts
CHANGED
|
@@ -11,6 +11,22 @@ export declare function generator(config: Config): Promise<void>;
|
|
|
11
11
|
*/
|
|
12
12
|
export declare function removeLastSegmentFromPath(routePath?: string): string;
|
|
13
13
|
export declare function hasParentRoute(routes: Array<RouteNode>, node: RouteNode, routePathToCheck: string | undefined): RouteNode | null;
|
|
14
|
+
/**
|
|
15
|
+
* Gets the final variable name for a route
|
|
16
|
+
*/
|
|
17
|
+
export declare const getResolvedRouteNodeVariableName: (routeNode: RouteNode) => string;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a map from fullPath to routeNode
|
|
20
|
+
*/
|
|
21
|
+
export declare const createRouteNodesByFullPath: (routeNodes: Array<RouteNode>) => Map<string, RouteNode>;
|
|
22
|
+
/**
|
|
23
|
+
* Create a map from 'to' to a routeNode
|
|
24
|
+
*/
|
|
25
|
+
export declare const createRouteNodesByTo: (routeNodes: Array<RouteNode>) => Map<string, RouteNode>;
|
|
26
|
+
/**
|
|
27
|
+
* Create a map from 'id' to a routeNode
|
|
28
|
+
*/
|
|
29
|
+
export declare const createRouteNodesById: (routeNodes: Array<RouteNode>) => Map<string, RouteNode>;
|
|
14
30
|
/**
|
|
15
31
|
* Infers the full path for use by TS
|
|
16
32
|
*/
|
|
@@ -19,6 +35,14 @@ export declare const inferFullPath: (routeNode: RouteNode) => string;
|
|
|
19
35
|
* Infers the path for use by TS
|
|
20
36
|
*/
|
|
21
37
|
export declare const inferPath: (routeNode: RouteNode) => string;
|
|
38
|
+
/**
|
|
39
|
+
* Infers to path
|
|
40
|
+
*/
|
|
41
|
+
export declare const inferTo: (routeNode: RouteNode) => string;
|
|
42
|
+
/**
|
|
43
|
+
* Dedupes branches and index routes
|
|
44
|
+
*/
|
|
45
|
+
export declare const dedupeBranchesAndIndexRoutes: (routes: Array<RouteNode>) => Array<RouteNode>;
|
|
22
46
|
export type StartAPIRoutePathSegment = {
|
|
23
47
|
value: string;
|
|
24
48
|
type: 'path' | 'param' | 'splat';
|
package/dist/esm/generator.js
CHANGED
|
@@ -274,11 +274,23 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
274
274
|
const route = `${node.variableName}Route`;
|
|
275
275
|
if ((_b = node.children) == null ? void 0 : _b.length) {
|
|
276
276
|
const childConfigs = buildRouteTreeConfig(node.children, depth + 1);
|
|
277
|
-
|
|
277
|
+
const childrenDeclaration = `interface ${route}Children {
|
|
278
|
+
${node.children.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
279
|
+
}`;
|
|
280
|
+
const children2 = `const ${route}Children: ${route}Children = {
|
|
281
|
+
${node.children.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
282
|
+
}`;
|
|
283
|
+
const routeWithChildren = `const ${route}WithChildren = ${route}._addFileChildren(${route}Children)`;
|
|
284
|
+
return [
|
|
285
|
+
childConfigs,
|
|
286
|
+
childrenDeclaration,
|
|
287
|
+
children2,
|
|
288
|
+
routeWithChildren
|
|
289
|
+
].join("\n\n");
|
|
278
290
|
}
|
|
279
|
-
return
|
|
291
|
+
return void 0;
|
|
280
292
|
});
|
|
281
|
-
return children.filter(Boolean).join(
|
|
293
|
+
return children.filter(Boolean).join("\n\n");
|
|
282
294
|
}
|
|
283
295
|
const routeConfigChildrenText = buildRouteTreeConfig(routeTree);
|
|
284
296
|
const sortedRouteNodes = multiSortBy(routeNodes, [
|
|
@@ -417,7 +429,43 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
417
429
|
}`
|
|
418
430
|
],
|
|
419
431
|
"// Create and export the route tree",
|
|
420
|
-
|
|
432
|
+
routeConfigChildrenText,
|
|
433
|
+
`interface FileRoutesByFullPath {
|
|
434
|
+
${[...createRouteNodesByFullPath(routeNodes).entries()].map(
|
|
435
|
+
([fullPath, routeNode]) => {
|
|
436
|
+
return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
|
|
437
|
+
}
|
|
438
|
+
)}
|
|
439
|
+
}`,
|
|
440
|
+
`interface FileRoutesByTo {
|
|
441
|
+
${[...createRouteNodesByTo(routeNodes).entries()].map(
|
|
442
|
+
([to, routeNode]) => {
|
|
443
|
+
return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
|
|
444
|
+
}
|
|
445
|
+
)}
|
|
446
|
+
}`,
|
|
447
|
+
`interface FileRoutesById {
|
|
448
|
+
${[...createRouteNodesById(routeNodes).entries()].map(
|
|
449
|
+
([id, routeNode]) => {
|
|
450
|
+
return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`;
|
|
451
|
+
}
|
|
452
|
+
)}
|
|
453
|
+
}`,
|
|
454
|
+
`interface FileRouteTypes {
|
|
455
|
+
fileRoutesByFullPath: FileRoutesByFullPath
|
|
456
|
+
fullPaths: ${[...createRouteNodesByFullPath(routeNodes).keys()].map((fullPath) => `'${fullPath}'`).join("|")}
|
|
457
|
+
fileRoutesByTo: FileRoutesByTo
|
|
458
|
+
to: ${[...createRouteNodesByTo(routeNodes).keys()].map((to) => `'${to}'`).join("|")}
|
|
459
|
+
id: ${[...createRouteNodesById(routeNodes).keys()].map((id) => `'${id}'`).join("|")}
|
|
460
|
+
fileRoutesById: FileRoutesById
|
|
461
|
+
}`,
|
|
462
|
+
`interface RootRouteChildren {
|
|
463
|
+
${routeTree.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
464
|
+
}`,
|
|
465
|
+
`const rootRouteChildren: RootRouteChildren = {
|
|
466
|
+
${routeTree.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(",")}
|
|
467
|
+
}`,
|
|
468
|
+
`export const routeTree = rootRoute._addFileChildren(rootRouteChildren)._addFileTypes<FileRouteTypes>()`,
|
|
421
469
|
...config.routeTreeFileFooter
|
|
422
470
|
].filter(Boolean).join("\n\n");
|
|
423
471
|
const createRouteManifest = () => {
|
|
@@ -486,9 +534,6 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
486
534
|
`✅ Processed ${routeNodes.length === 1 ? "route" : "routes"} in ${Date.now() - start}ms`
|
|
487
535
|
);
|
|
488
536
|
}
|
|
489
|
-
function spaces(d) {
|
|
490
|
-
return Array.from({ length: d }).map(() => " ").join("");
|
|
491
|
-
}
|
|
492
537
|
function removeTrailingUnderscores(s) {
|
|
493
538
|
return s == null ? void 0 : s.replaceAll(/(_$)/gi, "").replaceAll(/(_\/)/gi, "/");
|
|
494
539
|
}
|
|
@@ -528,6 +573,31 @@ function hasParentRoute(routes, node, routePathToCheck) {
|
|
|
528
573
|
const parentRoutePath = segments.join("/");
|
|
529
574
|
return hasParentRoute(routes, node, parentRoutePath);
|
|
530
575
|
}
|
|
576
|
+
const getResolvedRouteNodeVariableName = (routeNode) => {
|
|
577
|
+
var _a;
|
|
578
|
+
return ((_a = routeNode.children) == null ? void 0 : _a.length) ? `${routeNode.variableName}RouteWithChildren` : `${routeNode.variableName}Route`;
|
|
579
|
+
};
|
|
580
|
+
const createRouteNodesByFullPath = (routeNodes) => {
|
|
581
|
+
return new Map(
|
|
582
|
+
routeNodes.map((routeNode) => [inferFullPath(routeNode), routeNode])
|
|
583
|
+
);
|
|
584
|
+
};
|
|
585
|
+
const createRouteNodesByTo = (routeNodes) => {
|
|
586
|
+
return new Map(
|
|
587
|
+
dedupeBranchesAndIndexRoutes(routeNodes).map((routeNode) => [
|
|
588
|
+
inferTo(routeNode),
|
|
589
|
+
routeNode
|
|
590
|
+
])
|
|
591
|
+
);
|
|
592
|
+
};
|
|
593
|
+
const createRouteNodesById = (routeNodes) => {
|
|
594
|
+
return new Map(
|
|
595
|
+
routeNodes.map((routeNode) => {
|
|
596
|
+
const [_, id] = getFilePathIdAndRouteIdFromPath(routeNode.routePath);
|
|
597
|
+
return [id, routeNode];
|
|
598
|
+
})
|
|
599
|
+
);
|
|
600
|
+
};
|
|
531
601
|
const inferFullPath = (routeNode) => {
|
|
532
602
|
const fullPath = removeGroups(
|
|
533
603
|
removeUnderscores(removeLayoutSegments(routeNode.routePath)) ?? ""
|
|
@@ -538,6 +608,18 @@ const inferPath = (routeNode) => {
|
|
|
538
608
|
var _a;
|
|
539
609
|
return routeNode.cleanedPath === "/" ? routeNode.cleanedPath : ((_a = routeNode.cleanedPath) == null ? void 0 : _a.replace(/\/$/, "")) ?? "";
|
|
540
610
|
};
|
|
611
|
+
const inferTo = (routeNode) => {
|
|
612
|
+
const fullPath = inferFullPath(routeNode);
|
|
613
|
+
if (fullPath === "/") return fullPath;
|
|
614
|
+
return fullPath.replace(/\/$/, "");
|
|
615
|
+
};
|
|
616
|
+
const dedupeBranchesAndIndexRoutes = (routes) => {
|
|
617
|
+
return routes.filter((route) => {
|
|
618
|
+
var _a;
|
|
619
|
+
if ((_a = route.children) == null ? void 0 : _a.find((child) => child.cleanedPath === "/")) return false;
|
|
620
|
+
return true;
|
|
621
|
+
});
|
|
622
|
+
};
|
|
541
623
|
function getFilePathIdAndRouteIdFromPath(pathname) {
|
|
542
624
|
const filePathId = removeTrailingUnderscores(pathname);
|
|
543
625
|
const id = removeGroups(filePathId ?? "");
|
|
@@ -583,10 +665,16 @@ function startAPIRouteSegmentsFromTSRFilePath(src, config) {
|
|
|
583
665
|
return segments;
|
|
584
666
|
}
|
|
585
667
|
export {
|
|
668
|
+
createRouteNodesByFullPath,
|
|
669
|
+
createRouteNodesById,
|
|
670
|
+
createRouteNodesByTo,
|
|
671
|
+
dedupeBranchesAndIndexRoutes,
|
|
586
672
|
generator,
|
|
673
|
+
getResolvedRouteNodeVariableName,
|
|
587
674
|
hasParentRoute,
|
|
588
675
|
inferFullPath,
|
|
589
676
|
inferPath,
|
|
677
|
+
inferTo,
|
|
590
678
|
removeLastSegmentFromPath,
|
|
591
679
|
startAPIRouteSegmentsFromTSRFilePath
|
|
592
680
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.js","sources":["../../src/generator.ts"],"sourcesContent":["import path from 'node:path'\nimport * as fs from 'node:fs'\nimport * as fsp from 'node:fs/promises'\nimport * as prettier from 'prettier'\nimport {\n determineInitialRoutePath,\n logging,\n multiSortBy,\n removeExt,\n removeTrailingSlash,\n removeUnderscores,\n replaceBackslash,\n routePathToVariable,\n trimPathLeft,\n} from './utils'\nimport { getRouteNodes as physicalGetRouteNodes } from './filesystem/physical/getRouteNodes'\nimport { getRouteNodes as virtualGetRouteNodes } from './filesystem/virtual/getRouteNodes'\nimport { rootPathId } from './filesystem/physical/rootPathId'\nimport type { GetRouteNodesResult, RouteNode } from './types'\nimport type { Config } from './config'\n\nlet latestTask = 0\nconst routeGroupPatternRegex = /\\(.+\\)/g\nconst possiblyNestedRouteGroupPatternRegex = /\\([^/]+\\)\\/?/g\n\nlet isFirst = false\nlet skipMessage = false\n\ntype RouteSubNode = {\n component?: RouteNode\n errorComponent?: RouteNode\n pendingComponent?: RouteNode\n loader?: RouteNode\n lazy?: RouteNode\n}\n\nexport async function generator(config: Config) {\n const logger = logging({ disabled: config.disableLogging })\n logger.log('')\n\n if (!isFirst) {\n logger.log('♻️ Generating routes...')\n isFirst = true\n } else if (skipMessage) {\n skipMessage = false\n } else {\n logger.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\n const prettierOptions: prettier.Options = {\n semi: config.semicolons,\n singleQuote: config.quoteStyle === 'single',\n parser: 'typescript',\n }\n\n let getRouteNodesResult: GetRouteNodesResult\n\n if (config.virtualRouteConfig) {\n getRouteNodesResult = await virtualGetRouteNodes(config)\n } else {\n getRouteNodesResult = await physicalGetRouteNodes(config)\n }\n\n const { rootRouteNode, routeNodes: beforeRouteNodes } = getRouteNodesResult\n if (rootRouteNode === undefined) {\n throw new Error(`rootRouteNode must not be undefined`)\n }\n const preRouteNodes = multiSortBy(beforeRouteNodes, [\n (d) => (d.routePath === '/' ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) =>\n d.filePath.match(new RegExp(`[./]${config.indexToken}[.]`)) ? 1 : -1,\n (d) =>\n d.filePath.match(\n /[./](component|errorComponent|pendingComponent|loader|lazy)[.]/,\n )\n ? 1\n : -1,\n (d) =>\n d.filePath.match(new RegExp(`[./]${config.routeToken}[.]`)) ? -1 : 1,\n (d) => (d.routePath?.endsWith('/') ? -1 : 1),\n (d) => d.routePath,\n ]).filter((d) => ![`/${rootPathId}`].includes(d.routePath || ''))\n\n const routeTree: Array<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 const routeNodes: Array<RouteNode> = []\n\n // the handleRootNode function is not being collapsed into the handleNode function\n // because it requires only a subset of the logic that the handleNode function requires\n // and it's easier to read and maintain this way\n const handleRootNode = async (node?: RouteNode) => {\n if (!node) {\n // currently this is not being handled, but it could be in the future\n // for example to handle a virtual root route\n return\n }\n\n // from here on, we are only handling the root node that's present in the file system\n const routeCode = fs.readFileSync(node.fullPath, 'utf-8')\n\n if (!routeCode) {\n const replaced = `import * as React from 'react';\nimport { Outlet, createRootRoute } from '@tanstack/react-router';\n\nexport const Route = createRootRoute({\n component: () => (\n <React.Fragment>\n <div>Hello \"${rootPathId}\"!</div>\n <Outlet />\n </React.Fragment>\n ),\n})\n\n`\n\n logger.log(`🟡 Creating ${node.fullPath}`)\n fs.writeFileSync(\n node.fullPath,\n await prettier.format(replaced, prettierOptions),\n )\n }\n }\n\n await handleRootNode(rootRouteNode)\n\n const handleNode = async (node: RouteNode) => {\n let parentRoute = hasParentRoute(routeNodes, node, node.routePath)\n\n // if the parent route is a virtual parent route, we need to find the real parent route\n if (parentRoute?.isVirtualParentRoute && parentRoute.children?.length) {\n // only if this sub-parent route returns a valid parent route, we use it, if not leave it as it\n const possibleParentRoute = hasParentRoute(\n parentRoute.children,\n node,\n node.routePath,\n )\n if (possibleParentRoute) {\n parentRoute = possibleParentRoute\n }\n }\n\n if (parentRoute) node.parent = parentRoute\n\n node.path = determineNodePath(node)\n\n const trimmedPath = trimPathLeft(node.path ?? '')\n\n const split = trimmedPath.split('/')\n const lastRouteSegment = split[split.length - 1] ?? trimmedPath\n\n node.isNonPath =\n lastRouteSegment.startsWith('_') ||\n routeGroupPatternRegex.test(lastRouteSegment)\n\n node.cleanedPath = removeGroups(\n removeUnderscores(removeLayoutSegments(node.path)) ?? '',\n )\n\n // Ensure the boilerplate for the route exists, which can be skipped for virtual parent routes and virtual routes\n if (!node.isVirtualParentRoute && !node.isVirtual) {\n const routeCode = fs.readFileSync(node.fullPath, 'utf-8')\n\n const escapedRoutePath = removeTrailingUnderscores(\n node.routePath?.replaceAll('$', '$$') ?? '',\n )\n\n let replaced = routeCode\n\n if (!routeCode) {\n if (node.isLazy) {\n replaced = [\n `import { createLazyFileRoute } from '@tanstack/react-router'`,\n `export const Route = createLazyFileRoute('${escapedRoutePath}')({\n component: () => <div>Hello ${escapedRoutePath}!</div>\n})`,\n ].join('\\n\\n')\n } else if (\n node.isRoute ||\n (!node.isComponent &&\n !node.isErrorComponent &&\n !node.isPendingComponent &&\n !node.isLoader)\n ) {\n replaced = [\n `import { createFileRoute } from '@tanstack/react-router'`,\n `export const Route = createFileRoute('${escapedRoutePath}')({\n component: () => <div>Hello ${escapedRoutePath}!</div>\n})`,\n ].join('\\n\\n')\n }\n } else {\n replaced = routeCode\n .replace(\n /(FileRoute\\(\\s*['\"])([^\\s]*)(['\"],?\\s*\\))/g,\n (match, p1, p2, p3) => `${p1}${escapedRoutePath}${p3}`,\n )\n .replace(\n /(import\\s*\\{.*)(create(Lazy)?FileRoute)(.*\\}\\s*from\\s*['\"]@tanstack\\/react-router['\"])/gs,\n (match, p1, p2, p3, p4) =>\n `${p1}${node.isLazy ? 'createLazyFileRoute' : 'createFileRoute'}${p4}`,\n )\n .replace(\n /create(Lazy)?FileRoute(\\(\\s*['\"])([^\\s]*)(['\"],?\\s*\\))/g,\n (match, p1, p2, p3, p4) =>\n `${node.isLazy ? 'createLazyFileRoute' : 'createFileRoute'}${p2}${escapedRoutePath}${p4}`,\n )\n }\n\n if (replaced !== routeCode) {\n logger.log(`🟡 Updating ${node.fullPath}`)\n await fsp.writeFile(node.fullPath, replaced)\n }\n }\n\n if (\n !node.isVirtual &&\n (node.isLoader ||\n node.isComponent ||\n node.isErrorComponent ||\n node.isPendingComponent ||\n node.isLazy)\n ) {\n routePiecesByPath[node.routePath!] =\n routePiecesByPath[node.routePath!] || {}\n\n routePiecesByPath[node.routePath!]![\n node.isLazy\n ? 'lazy'\n : node.isLoader\n ? 'loader'\n : node.isErrorComponent\n ? 'errorComponent'\n : node.isPendingComponent\n ? 'pendingComponent'\n : 'component'\n ] = node\n\n const anchorRoute = routeNodes.find((d) => d.routePath === node.routePath)\n\n if (!anchorRoute) {\n await handleNode({\n ...node,\n isVirtual: true,\n isLazy: false,\n isLoader: false,\n isComponent: false,\n isErrorComponent: false,\n isPendingComponent: false,\n })\n }\n return\n }\n\n const cleanedPathIsEmpty = (node.cleanedPath || '').length === 0\n const nonPathRoute = node.isRoute && node.isNonPath\n node.isVirtualParentRequired =\n node.isLayout || nonPathRoute ? !cleanedPathIsEmpty : false\n if (!node.isVirtual && node.isVirtualParentRequired) {\n const parentRoutePath = removeLastSegmentFromPath(node.routePath) || '/'\n const parentVariableName = routePathToVariable(parentRoutePath)\n\n const anchorRoute = routeNodes.find(\n (d) => d.routePath === parentRoutePath,\n )\n\n if (!anchorRoute) {\n const parentNode = {\n ...node,\n path: removeLastSegmentFromPath(node.path) || '/',\n filePath: removeLastSegmentFromPath(node.filePath) || '/',\n fullPath: removeLastSegmentFromPath(node.fullPath) || '/',\n routePath: parentRoutePath,\n variableName: parentVariableName,\n isVirtual: true,\n isLayout: false,\n isVirtualParentRoute: true,\n isVirtualParentRequired: false,\n }\n\n parentNode.children = parentNode.children ?? []\n parentNode.children.push(node)\n\n node.parent = parentNode\n\n if (node.isLayout) {\n // since `node.path` is used as the `id` on the route definition, we need to update it\n node.path = determineNodePath(node)\n }\n\n await handleNode(parentNode)\n } else {\n anchorRoute.children = anchorRoute.children ?? []\n anchorRoute.children.push(node)\n\n node.parent = anchorRoute\n }\n }\n\n if (node.parent) {\n if (!node.isVirtualParentRequired) {\n node.parent.children = node.parent.children ?? []\n node.parent.children.push(node)\n }\n } else {\n routeTree.push(node)\n }\n\n routeNodes.push(node)\n }\n\n for (const node of preRouteNodes.filter((d) => !d.isAPIRoute)) {\n await handleNode(node)\n }\n\n const startAPIRouteNodes: Array<RouteNode> = checkStartAPIRoutes(\n preRouteNodes.filter((d) => d.isAPIRoute),\n )\n\n const handleAPINode = async (node: RouteNode) => {\n const routeCode = fs.readFileSync(node.fullPath, 'utf-8')\n\n const escapedRoutePath = removeTrailingUnderscores(\n node.routePath?.replaceAll('$', '$$') ?? '',\n )\n\n if (!routeCode) {\n const replaced = `import { json } from '@tanstack/start'\nimport { createAPIFileRoute } from '@tanstack/start/api'\n\nexport const Route = createAPIFileRoute('${escapedRoutePath}')({\n GET: ({ request, params }) => {\n return json({ message: 'Hello ${escapedRoutePath}' })\n },\n})\n\n`\n\n logger.log(`🟡 Creating ${node.fullPath}`)\n fs.writeFileSync(\n node.fullPath,\n await prettier.format(replaced, prettierOptions),\n )\n } else {\n const copied = routeCode.replace(\n /(createAPIFileRoute\\(\\s*['\"])([^\\s]*)(['\"],?\\s*\\))/g,\n (_, p1, __, p3) => `${p1}${escapedRoutePath}${p3}`,\n )\n\n if (copied !== routeCode) {\n logger.log(`🟡 Updating ${node.fullPath}`)\n await fsp.writeFile(\n node.fullPath,\n await prettier.format(copied, prettierOptions),\n )\n }\n }\n }\n\n for (const node of startAPIRouteNodes) {\n await handleAPINode(node)\n }\n\n function buildRouteTreeConfig(nodes: Array<RouteNode>, depth = 1): string {\n const children = nodes.map((node) => {\n if (node.isRoot) {\n return\n }\n\n if (node.isLayout && !node.children?.length) {\n return\n }\n\n const route = `${node.variableName}Route`\n\n if (node.children?.length) {\n const childConfigs = buildRouteTreeConfig(node.children, depth + 1)\n return `${route}: ${route}.addChildren({${spaces(depth * 4)}${childConfigs}})`\n }\n\n return route\n })\n\n return children.filter(Boolean).join(`,`)\n }\n\n const routeConfigChildrenText = buildRouteTreeConfig(routeTree)\n\n const sortedRouteNodes = multiSortBy(routeNodes, [\n (d) => (d.routePath?.includes(`/${rootPathId}`) ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => (d.routePath?.endsWith(config.indexToken) ? -1 : 1),\n (d) => d,\n ])\n\n const imports = Object.entries({\n createFileRoute: sortedRouteNodes.some((d) => d.isVirtual),\n lazyFn: sortedRouteNodes.some(\n (node) => routePiecesByPath[node.routePath!]?.loader,\n ),\n lazyRouteComponent: sortedRouteNodes.some(\n (node) =>\n routePiecesByPath[node.routePath!]?.component ||\n routePiecesByPath[node.routePath!]?.errorComponent ||\n routePiecesByPath[node.routePath!]?.pendingComponent,\n ),\n })\n .filter((d) => d[1])\n .map((d) => d[0])\n\n const virtualRouteNodes = sortedRouteNodes.filter((d) => d.isVirtual)\n\n function getImportPath(node: RouteNode) {\n return replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, node.filePath),\n ),\n config.addExtensions,\n ),\n )\n }\n const routeImports = [\n ...config.routeTreeFileHeader,\n '// This file is auto-generated by TanStack Router',\n imports.length\n ? `import { ${imports.join(', ')} } from '@tanstack/react-router'\\n`\n : '',\n '// Import Routes',\n [\n `import { Route as rootRoute } from './${getImportPath(rootRouteNode)}'`,\n ...sortedRouteNodes\n .filter((d) => !d.isVirtual)\n .map((node) => {\n return `import { Route as ${\n node.variableName\n }Import } from './${getImportPath(node)}'`\n }),\n ].join('\\n'),\n virtualRouteNodes.length ? '// Create Virtual Routes' : '',\n virtualRouteNodes\n .map((node) => {\n return `const ${\n node.variableName\n }Import = createFileRoute('${removeTrailingUnderscores(\n node.routePath,\n )}')()`\n })\n .join('\\n'),\n '// Create/Update Routes',\n sortedRouteNodes\n .map((node) => {\n const loaderNode = routePiecesByPath[node.routePath!]?.loader\n const componentNode = routePiecesByPath[node.routePath!]?.component\n const errorComponentNode =\n routePiecesByPath[node.routePath!]?.errorComponent\n const pendingComponentNode =\n routePiecesByPath[node.routePath!]?.pendingComponent\n const lazyComponentNode = routePiecesByPath[node.routePath!]?.lazy\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 }${config.disableTypes ? '' : 'as any'})`,\n loaderNode\n ? `.updateLoader({ loader: lazyFn(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, loaderNode.filePath),\n ),\n config.addExtensions,\n ),\n )}'), 'loader') })`\n : '',\n componentNode || errorComponentNode || pendingComponentNode\n ? `.update({\n ${(\n [\n ['component', componentNode],\n ['errorComponent', errorComponentNode],\n ['pendingComponent', pendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n return `${\n d[0]\n }: lazyRouteComponent(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, d[1]!.filePath),\n ),\n config.addExtensions,\n ),\n )}'), '${d[0]}')`\n })\n .join('\\n,')}\n })`\n : '',\n lazyComponentNode\n ? `.lazy(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )}').then((d) => d.Route))`\n : '',\n ].join('')\n })\n .join('\\n\\n'),\n ...(config.disableTypes\n ? []\n : [\n '// Populate the FileRoutesByPath interface',\n `declare module '@tanstack/react-router' {\n interface FileRoutesByPath {\n ${routeNodes\n .map((routeNode) => {\n const [filePathId, routeId] = getFilePathIdAndRouteIdFromPath(\n routeNode.routePath,\n )\n\n return `'${filePathId}': {\n id: '${routeId}'\n path: '${inferPath(routeNode)}'\n fullPath: '${inferFullPath(routeNode)}'\n preLoaderRoute: typeof ${routeNode.variableName}Import\n parentRoute: typeof ${\n routeNode.isVirtualParentRequired\n ? `${routeNode.parent?.variableName}Route`\n : routeNode.parent?.variableName\n ? `${routeNode.parent.variableName}Import`\n : 'rootRoute'\n }\n }`\n })\n .join('\\n')}\n }\n}`,\n ]),\n '// Create and export the route tree',\n `export const routeTree = rootRoute.addChildren({${routeConfigChildrenText}})`,\n ...config.routeTreeFileFooter,\n ]\n .filter(Boolean)\n .join('\\n\\n')\n\n const createRouteManifest = () => {\n const routesManifest = {\n __root__: {\n filePath: rootRouteNode.filePath,\n children: routeTree.map(\n (d) => getFilePathIdAndRouteIdFromPath(d.routePath)[1],\n ),\n },\n ...Object.fromEntries(\n routeNodes.map((d) => {\n const [_, routeId] = getFilePathIdAndRouteIdFromPath(d.routePath)\n\n return [\n routeId,\n {\n filePath: d.filePath,\n parent: d.parent?.routePath\n ? getFilePathIdAndRouteIdFromPath(d.parent.routePath)[1]\n : undefined,\n children: d.children?.map(\n (childRoute) =>\n getFilePathIdAndRouteIdFromPath(childRoute.routePath)[1],\n ),\n },\n ]\n }),\n ),\n }\n\n return JSON.stringify(\n {\n routes: routesManifest,\n },\n null,\n 2,\n )\n }\n\n const routeConfigFileContent = await prettier.format(\n config.disableManifestGeneration\n ? routeImports\n : [\n routeImports,\n '\\n',\n '/* ROUTE_MANIFEST_START',\n createRouteManifest(),\n 'ROUTE_MANIFEST_END */',\n ].join('\\n'),\n prettierOptions,\n )\n\n if (!checkLatest()) return\n\n const existingRouteTreeContent = await fsp\n .readFile(path.resolve(config.generatedRouteTree), 'utf-8')\n .catch((err) => {\n if (err.code === 'ENOENT') {\n return ''\n }\n\n throw err\n })\n\n if (!checkLatest()) return\n\n // Ensure the directory exists\n await fsp.mkdir(path.dirname(path.resolve(config.generatedRouteTree)), {\n recursive: true,\n })\n\n if (!checkLatest()) return\n\n // Write the route tree file, if it has changed\n if (existingRouteTreeContent !== routeConfigFileContent) {\n await fsp.writeFile(\n path.resolve(config.generatedRouteTree),\n routeConfigFileContent,\n )\n if (!checkLatest()) return\n }\n\n logger.log(\n `✅ Processed ${routeNodes.length === 1 ? 'route' : 'routes'} in ${\n Date.now() - start\n }ms`,\n )\n}\n\nfunction spaces(d: number): string {\n return Array.from({ length: d })\n .map(() => ' ')\n .join('')\n}\n\nfunction removeTrailingUnderscores(s?: string) {\n return s?.replaceAll(/(_$)/gi, '').replaceAll(/(_\\/)/gi, '/')\n}\n\nfunction removeGroups(s: string) {\n return s.replace(possiblyNestedRouteGroupPatternRegex, '')\n}\n\n/**\n * The `node.path` is used as the `id` in the route definition.\n * This function checks if the given node has a parent and if so, it determines the correct path for the given node.\n * @param node - The node to determine the path for.\n * @returns The correct path for the given node.\n */\nfunction determineNodePath(node: RouteNode) {\n return (node.path = node.parent\n ? node.routePath?.replace(node.parent.routePath ?? '', '') || '/'\n : node.routePath)\n}\n\n/**\n * Removes the last segment from a given path. Segments are considered to be separated by a '/'.\n *\n * @param {string} routePath - The path from which to remove the last segment. Defaults to '/'.\n * @returns {string} The path with the last segment removed.\n * @example\n * removeLastSegmentFromPath('/workspace/_auth/foo') // '/workspace/_auth'\n */\nexport function removeLastSegmentFromPath(routePath: string = '/'): string {\n const segments = routePath.split('/')\n segments.pop() // Remove the last segment\n return segments.join('/')\n}\n\n/**\n * Removes all segments from a given path that start with an underscore ('_').\n *\n * @param {string} routePath - The path from which to remove segments. Defaults to '/'.\n * @returns {string} The path with all underscore-prefixed segments removed.\n * @example\n * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'\n */\nfunction removeLayoutSegments(routePath: string = '/'): string {\n const segments = routePath.split('/')\n const newSegments = segments.filter((segment) => !segment.startsWith('_'))\n return newSegments.join('/')\n}\n\nexport function hasParentRoute(\n routes: Array<RouteNode>,\n node: RouteNode,\n routePathToCheck: string | undefined,\n): RouteNode | null {\n if (!routePathToCheck || routePathToCheck === '/') {\n return null\n }\n\n const sortedNodes = multiSortBy(routes, [\n (d) => d.routePath!.length * -1,\n (d) => d.variableName,\n ]).filter((d) => d.routePath !== `/${rootPathId}`)\n\n for (const route of sortedNodes) {\n if (route.routePath === '/') continue\n\n if (\n routePathToCheck.startsWith(`${route.routePath}/`) &&\n route.routePath !== routePathToCheck\n ) {\n return route\n }\n }\n\n const segments = routePathToCheck.split('/')\n segments.pop() // Remove the last segment\n const parentRoutePath = segments.join('/')\n\n return hasParentRoute(routes, node, parentRoutePath)\n}\n\n/**\n * Infers the full path for use by TS\n */\nexport const inferFullPath = (routeNode: RouteNode): string => {\n const fullPath = removeGroups(\n removeUnderscores(removeLayoutSegments(routeNode.routePath)) ?? '',\n )\n\n return routeNode.cleanedPath === '/' ? fullPath : fullPath.replace(/\\/$/, '')\n}\n\n/**\n * Infers the path for use by TS\n */\nexport const inferPath = (routeNode: RouteNode): string => {\n return routeNode.cleanedPath === '/'\n ? routeNode.cleanedPath\n : (routeNode.cleanedPath?.replace(/\\/$/, '') ?? '')\n}\n\nfunction getFilePathIdAndRouteIdFromPath(pathname?: string) {\n const filePathId = removeTrailingUnderscores(pathname)\n const id = removeGroups(filePathId ?? '')\n\n return [filePathId, id] as const\n}\n\nfunction checkStartAPIRoutes(_routes: Array<RouteNode>) {\n if (_routes.length === 0) {\n return []\n }\n\n // Make sure these are valid URLs\n // Route Groups and Layout Routes aren't being removed since\n // you may want to have an API route that starts with an underscore\n // or be wrapped in parentheses\n const routes = _routes.map((d) => {\n const routePath = removeTrailingSlash(d.routePath ?? '')\n return { ...d, routePath }\n })\n\n // Check no two API routes have the same routePath\n // if they do, throw an error with the conflicting filePaths\n const routePaths = routes.map((d) => d.routePath)\n const uniqueRoutePaths = new Set(routePaths)\n if (routePaths.length !== uniqueRoutePaths.size) {\n const duplicateRoutePaths = routePaths.filter(\n (d, i) => routePaths.indexOf(d) !== i,\n )\n const conflictingFiles = routes\n .filter((d) => duplicateRoutePaths.includes(d.routePath))\n .map((d) => `${d.fullPath}`)\n const errorMessage = `Conflicting configuration paths was for found for the following API route${duplicateRoutePaths.length > 1 ? 's' : ''}: ${duplicateRoutePaths\n .map((p) => `\"${p}\"`)\n .join(', ')}.\nPlease ensure each API route has a unique route path.\nConflicting files: \\n ${conflictingFiles.join('\\n ')}\\n`\n throw new Error(errorMessage)\n }\n\n return routes\n}\n\nexport type StartAPIRoutePathSegment = {\n value: string\n type: 'path' | 'param' | 'splat'\n}\n\n/**\n * This function takes in a path in the format accepted by TanStack Router\n * and returns an array of path segments that can be used to generate\n * the pathname of the TanStack Start API route.\n *\n * @param src\n * @returns\n */\nexport function startAPIRouteSegmentsFromTSRFilePath(\n src: string,\n config: Config,\n): Array<StartAPIRoutePathSegment> {\n const routePath = determineInitialRoutePath(src)\n\n const parts = routePath\n .replaceAll('.', '/')\n .split('/')\n .filter((p) => !!p && p !== config.indexToken)\n const segments: Array<StartAPIRoutePathSegment> = parts.map((part) => {\n if (part.startsWith('$')) {\n if (part === '$') {\n return { value: part, type: 'splat' }\n }\n\n part.replaceAll('$', '')\n return { value: part, type: 'param' }\n }\n\n return { value: part, type: 'path' }\n })\n\n return segments\n}\n"],"names":["virtualGetRouteNodes","physicalGetRouteNodes"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generator.js","sources":["../../src/generator.ts"],"sourcesContent":["import path from 'node:path'\nimport * as fs from 'node:fs'\nimport * as fsp from 'node:fs/promises'\nimport * as prettier from 'prettier'\nimport {\n determineInitialRoutePath,\n logging,\n multiSortBy,\n removeExt,\n removeTrailingSlash,\n removeUnderscores,\n replaceBackslash,\n routePathToVariable,\n trimPathLeft,\n} from './utils'\nimport { getRouteNodes as physicalGetRouteNodes } from './filesystem/physical/getRouteNodes'\nimport { getRouteNodes as virtualGetRouteNodes } from './filesystem/virtual/getRouteNodes'\nimport { rootPathId } from './filesystem/physical/rootPathId'\nimport type { GetRouteNodesResult, RouteNode } from './types'\nimport type { Config } from './config'\n\nlet latestTask = 0\nconst routeGroupPatternRegex = /\\(.+\\)/g\nconst possiblyNestedRouteGroupPatternRegex = /\\([^/]+\\)\\/?/g\n\nlet isFirst = false\nlet skipMessage = false\n\ntype RouteSubNode = {\n component?: RouteNode\n errorComponent?: RouteNode\n pendingComponent?: RouteNode\n loader?: RouteNode\n lazy?: RouteNode\n}\n\nexport async function generator(config: Config) {\n const logger = logging({ disabled: config.disableLogging })\n logger.log('')\n\n if (!isFirst) {\n logger.log('♻️ Generating routes...')\n isFirst = true\n } else if (skipMessage) {\n skipMessage = false\n } else {\n logger.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\n const prettierOptions: prettier.Options = {\n semi: config.semicolons,\n singleQuote: config.quoteStyle === 'single',\n parser: 'typescript',\n }\n\n let getRouteNodesResult: GetRouteNodesResult\n\n if (config.virtualRouteConfig) {\n getRouteNodesResult = await virtualGetRouteNodes(config)\n } else {\n getRouteNodesResult = await physicalGetRouteNodes(config)\n }\n\n const { rootRouteNode, routeNodes: beforeRouteNodes } = getRouteNodesResult\n if (rootRouteNode === undefined) {\n throw new Error(`rootRouteNode must not be undefined`)\n }\n const preRouteNodes = multiSortBy(beforeRouteNodes, [\n (d) => (d.routePath === '/' ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) =>\n d.filePath.match(new RegExp(`[./]${config.indexToken}[.]`)) ? 1 : -1,\n (d) =>\n d.filePath.match(\n /[./](component|errorComponent|pendingComponent|loader|lazy)[.]/,\n )\n ? 1\n : -1,\n (d) =>\n d.filePath.match(new RegExp(`[./]${config.routeToken}[.]`)) ? -1 : 1,\n (d) => (d.routePath?.endsWith('/') ? -1 : 1),\n (d) => d.routePath,\n ]).filter((d) => ![`/${rootPathId}`].includes(d.routePath || ''))\n\n const routeTree: Array<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 const routeNodes: Array<RouteNode> = []\n\n // the handleRootNode function is not being collapsed into the handleNode function\n // because it requires only a subset of the logic that the handleNode function requires\n // and it's easier to read and maintain this way\n const handleRootNode = async (node?: RouteNode) => {\n if (!node) {\n // currently this is not being handled, but it could be in the future\n // for example to handle a virtual root route\n return\n }\n\n // from here on, we are only handling the root node that's present in the file system\n const routeCode = fs.readFileSync(node.fullPath, 'utf-8')\n\n if (!routeCode) {\n const replaced = `import * as React from 'react';\nimport { Outlet, createRootRoute } from '@tanstack/react-router';\n\nexport const Route = createRootRoute({\n component: () => (\n <React.Fragment>\n <div>Hello \"${rootPathId}\"!</div>\n <Outlet />\n </React.Fragment>\n ),\n})\n\n`\n\n logger.log(`🟡 Creating ${node.fullPath}`)\n fs.writeFileSync(\n node.fullPath,\n await prettier.format(replaced, prettierOptions),\n )\n }\n }\n\n await handleRootNode(rootRouteNode)\n\n const handleNode = async (node: RouteNode) => {\n let parentRoute = hasParentRoute(routeNodes, node, node.routePath)\n\n // if the parent route is a virtual parent route, we need to find the real parent route\n if (parentRoute?.isVirtualParentRoute && parentRoute.children?.length) {\n // only if this sub-parent route returns a valid parent route, we use it, if not leave it as it\n const possibleParentRoute = hasParentRoute(\n parentRoute.children,\n node,\n node.routePath,\n )\n if (possibleParentRoute) {\n parentRoute = possibleParentRoute\n }\n }\n\n if (parentRoute) node.parent = parentRoute\n\n node.path = determineNodePath(node)\n\n const trimmedPath = trimPathLeft(node.path ?? '')\n\n const split = trimmedPath.split('/')\n const lastRouteSegment = split[split.length - 1] ?? trimmedPath\n\n node.isNonPath =\n lastRouteSegment.startsWith('_') ||\n routeGroupPatternRegex.test(lastRouteSegment)\n\n node.cleanedPath = removeGroups(\n removeUnderscores(removeLayoutSegments(node.path)) ?? '',\n )\n\n // Ensure the boilerplate for the route exists, which can be skipped for virtual parent routes and virtual routes\n if (!node.isVirtualParentRoute && !node.isVirtual) {\n const routeCode = fs.readFileSync(node.fullPath, 'utf-8')\n\n const escapedRoutePath = removeTrailingUnderscores(\n node.routePath?.replaceAll('$', '$$') ?? '',\n )\n\n let replaced = routeCode\n\n if (!routeCode) {\n if (node.isLazy) {\n replaced = [\n `import { createLazyFileRoute } from '@tanstack/react-router'`,\n `export const Route = createLazyFileRoute('${escapedRoutePath}')({\n component: () => <div>Hello ${escapedRoutePath}!</div>\n})`,\n ].join('\\n\\n')\n } else if (\n node.isRoute ||\n (!node.isComponent &&\n !node.isErrorComponent &&\n !node.isPendingComponent &&\n !node.isLoader)\n ) {\n replaced = [\n `import { createFileRoute } from '@tanstack/react-router'`,\n `export const Route = createFileRoute('${escapedRoutePath}')({\n component: () => <div>Hello ${escapedRoutePath}!</div>\n})`,\n ].join('\\n\\n')\n }\n } else {\n replaced = routeCode\n .replace(\n /(FileRoute\\(\\s*['\"])([^\\s]*)(['\"],?\\s*\\))/g,\n (match, p1, p2, p3) => `${p1}${escapedRoutePath}${p3}`,\n )\n .replace(\n /(import\\s*\\{.*)(create(Lazy)?FileRoute)(.*\\}\\s*from\\s*['\"]@tanstack\\/react-router['\"])/gs,\n (match, p1, p2, p3, p4) =>\n `${p1}${node.isLazy ? 'createLazyFileRoute' : 'createFileRoute'}${p4}`,\n )\n .replace(\n /create(Lazy)?FileRoute(\\(\\s*['\"])([^\\s]*)(['\"],?\\s*\\))/g,\n (match, p1, p2, p3, p4) =>\n `${node.isLazy ? 'createLazyFileRoute' : 'createFileRoute'}${p2}${escapedRoutePath}${p4}`,\n )\n }\n\n if (replaced !== routeCode) {\n logger.log(`🟡 Updating ${node.fullPath}`)\n await fsp.writeFile(node.fullPath, replaced)\n }\n }\n\n if (\n !node.isVirtual &&\n (node.isLoader ||\n node.isComponent ||\n node.isErrorComponent ||\n node.isPendingComponent ||\n node.isLazy)\n ) {\n routePiecesByPath[node.routePath!] =\n routePiecesByPath[node.routePath!] || {}\n\n routePiecesByPath[node.routePath!]![\n node.isLazy\n ? 'lazy'\n : node.isLoader\n ? 'loader'\n : node.isErrorComponent\n ? 'errorComponent'\n : node.isPendingComponent\n ? 'pendingComponent'\n : 'component'\n ] = node\n\n const anchorRoute = routeNodes.find((d) => d.routePath === node.routePath)\n\n if (!anchorRoute) {\n await handleNode({\n ...node,\n isVirtual: true,\n isLazy: false,\n isLoader: false,\n isComponent: false,\n isErrorComponent: false,\n isPendingComponent: false,\n })\n }\n return\n }\n\n const cleanedPathIsEmpty = (node.cleanedPath || '').length === 0\n const nonPathRoute = node.isRoute && node.isNonPath\n node.isVirtualParentRequired =\n node.isLayout || nonPathRoute ? !cleanedPathIsEmpty : false\n if (!node.isVirtual && node.isVirtualParentRequired) {\n const parentRoutePath = removeLastSegmentFromPath(node.routePath) || '/'\n const parentVariableName = routePathToVariable(parentRoutePath)\n\n const anchorRoute = routeNodes.find(\n (d) => d.routePath === parentRoutePath,\n )\n\n if (!anchorRoute) {\n const parentNode = {\n ...node,\n path: removeLastSegmentFromPath(node.path) || '/',\n filePath: removeLastSegmentFromPath(node.filePath) || '/',\n fullPath: removeLastSegmentFromPath(node.fullPath) || '/',\n routePath: parentRoutePath,\n variableName: parentVariableName,\n isVirtual: true,\n isLayout: false,\n isVirtualParentRoute: true,\n isVirtualParentRequired: false,\n }\n\n parentNode.children = parentNode.children ?? []\n parentNode.children.push(node)\n\n node.parent = parentNode\n\n if (node.isLayout) {\n // since `node.path` is used as the `id` on the route definition, we need to update it\n node.path = determineNodePath(node)\n }\n\n await handleNode(parentNode)\n } else {\n anchorRoute.children = anchorRoute.children ?? []\n anchorRoute.children.push(node)\n\n node.parent = anchorRoute\n }\n }\n\n if (node.parent) {\n if (!node.isVirtualParentRequired) {\n node.parent.children = node.parent.children ?? []\n node.parent.children.push(node)\n }\n } else {\n routeTree.push(node)\n }\n\n routeNodes.push(node)\n }\n\n for (const node of preRouteNodes.filter((d) => !d.isAPIRoute)) {\n await handleNode(node)\n }\n\n const startAPIRouteNodes: Array<RouteNode> = checkStartAPIRoutes(\n preRouteNodes.filter((d) => d.isAPIRoute),\n )\n\n const handleAPINode = async (node: RouteNode) => {\n const routeCode = fs.readFileSync(node.fullPath, 'utf-8')\n\n const escapedRoutePath = removeTrailingUnderscores(\n node.routePath?.replaceAll('$', '$$') ?? '',\n )\n\n if (!routeCode) {\n const replaced = `import { json } from '@tanstack/start'\nimport { createAPIFileRoute } from '@tanstack/start/api'\n\nexport const Route = createAPIFileRoute('${escapedRoutePath}')({\n GET: ({ request, params }) => {\n return json({ message: 'Hello ${escapedRoutePath}' })\n },\n})\n\n`\n\n logger.log(`🟡 Creating ${node.fullPath}`)\n fs.writeFileSync(\n node.fullPath,\n await prettier.format(replaced, prettierOptions),\n )\n } else {\n const copied = routeCode.replace(\n /(createAPIFileRoute\\(\\s*['\"])([^\\s]*)(['\"],?\\s*\\))/g,\n (_, p1, __, p3) => `${p1}${escapedRoutePath}${p3}`,\n )\n\n if (copied !== routeCode) {\n logger.log(`🟡 Updating ${node.fullPath}`)\n await fsp.writeFile(\n node.fullPath,\n await prettier.format(copied, prettierOptions),\n )\n }\n }\n }\n\n for (const node of startAPIRouteNodes) {\n await handleAPINode(node)\n }\n\n function buildRouteTreeConfig(nodes: Array<RouteNode>, depth = 1): string {\n const children = nodes.map((node) => {\n if (node.isRoot) {\n return\n }\n\n if (node.isLayout && !node.children?.length) {\n return\n }\n\n const route = `${node.variableName}Route`\n\n if (node.children?.length) {\n const childConfigs = buildRouteTreeConfig(node.children, depth + 1)\n\n const childrenDeclaration = `interface ${route}Children {\n ${node.children.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}\n }`\n\n const children = `const ${route}Children: ${route}Children = {\n ${node.children.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(',')}\n }`\n\n const routeWithChildren = `const ${route}WithChildren = ${route}._addFileChildren(${route}Children)`\n\n return [\n childConfigs,\n childrenDeclaration,\n children,\n routeWithChildren,\n ].join('\\n\\n')\n }\n\n return undefined\n })\n\n return children.filter(Boolean).join('\\n\\n')\n }\n\n const routeConfigChildrenText = buildRouteTreeConfig(routeTree)\n\n const sortedRouteNodes = multiSortBy(routeNodes, [\n (d) => (d.routePath?.includes(`/${rootPathId}`) ? -1 : 1),\n (d) => d.routePath?.split('/').length,\n (d) => (d.routePath?.endsWith(config.indexToken) ? -1 : 1),\n (d) => d,\n ])\n\n const imports = Object.entries({\n createFileRoute: sortedRouteNodes.some((d) => d.isVirtual),\n lazyFn: sortedRouteNodes.some(\n (node) => routePiecesByPath[node.routePath!]?.loader,\n ),\n lazyRouteComponent: sortedRouteNodes.some(\n (node) =>\n routePiecesByPath[node.routePath!]?.component ||\n routePiecesByPath[node.routePath!]?.errorComponent ||\n routePiecesByPath[node.routePath!]?.pendingComponent,\n ),\n })\n .filter((d) => d[1])\n .map((d) => d[0])\n\n const virtualRouteNodes = sortedRouteNodes.filter((d) => d.isVirtual)\n\n function getImportPath(node: RouteNode) {\n return replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, node.filePath),\n ),\n config.addExtensions,\n ),\n )\n }\n const routeImports = [\n ...config.routeTreeFileHeader,\n '// This file is auto-generated by TanStack Router',\n imports.length\n ? `import { ${imports.join(', ')} } from '@tanstack/react-router'\\n`\n : '',\n '// Import Routes',\n [\n `import { Route as rootRoute } from './${getImportPath(rootRouteNode)}'`,\n ...sortedRouteNodes\n .filter((d) => !d.isVirtual)\n .map((node) => {\n return `import { Route as ${\n node.variableName\n }Import } from './${getImportPath(node)}'`\n }),\n ].join('\\n'),\n virtualRouteNodes.length ? '// Create Virtual Routes' : '',\n virtualRouteNodes\n .map((node) => {\n return `const ${\n node.variableName\n }Import = createFileRoute('${removeTrailingUnderscores(\n node.routePath,\n )}')()`\n })\n .join('\\n'),\n '// Create/Update Routes',\n sortedRouteNodes\n .map((node) => {\n const loaderNode = routePiecesByPath[node.routePath!]?.loader\n const componentNode = routePiecesByPath[node.routePath!]?.component\n const errorComponentNode =\n routePiecesByPath[node.routePath!]?.errorComponent\n const pendingComponentNode =\n routePiecesByPath[node.routePath!]?.pendingComponent\n const lazyComponentNode = routePiecesByPath[node.routePath!]?.lazy\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 }${config.disableTypes ? '' : 'as any'})`,\n loaderNode\n ? `.updateLoader({ loader: lazyFn(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, loaderNode.filePath),\n ),\n config.addExtensions,\n ),\n )}'), 'loader') })`\n : '',\n componentNode || errorComponentNode || pendingComponentNode\n ? `.update({\n ${(\n [\n ['component', componentNode],\n ['errorComponent', errorComponentNode],\n ['pendingComponent', pendingComponentNode],\n ] as const\n )\n .filter((d) => d[1])\n .map((d) => {\n return `${\n d[0]\n }: lazyRouteComponent(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(config.routesDirectory, d[1]!.filePath),\n ),\n config.addExtensions,\n ),\n )}'), '${d[0]}')`\n })\n .join('\\n,')}\n })`\n : '',\n lazyComponentNode\n ? `.lazy(() => import('./${replaceBackslash(\n removeExt(\n path.relative(\n path.dirname(config.generatedRouteTree),\n path.resolve(\n config.routesDirectory,\n lazyComponentNode.filePath,\n ),\n ),\n config.addExtensions,\n ),\n )}').then((d) => d.Route))`\n : '',\n ].join('')\n })\n .join('\\n\\n'),\n ...(config.disableTypes\n ? []\n : [\n '// Populate the FileRoutesByPath interface',\n `declare module '@tanstack/react-router' {\n interface FileRoutesByPath {\n ${routeNodes\n .map((routeNode) => {\n const [filePathId, routeId] = getFilePathIdAndRouteIdFromPath(\n routeNode.routePath,\n )\n\n return `'${filePathId}': {\n id: '${routeId}'\n path: '${inferPath(routeNode)}'\n fullPath: '${inferFullPath(routeNode)}'\n preLoaderRoute: typeof ${routeNode.variableName}Import\n parentRoute: typeof ${\n routeNode.isVirtualParentRequired\n ? `${routeNode.parent?.variableName}Route`\n : routeNode.parent?.variableName\n ? `${routeNode.parent.variableName}Import`\n : 'rootRoute'\n }\n }`\n })\n .join('\\n')}\n }\n}`,\n ]),\n '// Create and export the route tree',\n routeConfigChildrenText,\n `interface FileRoutesByFullPath {\n ${[...createRouteNodesByFullPath(routeNodes).entries()].map(\n ([fullPath, routeNode]) => {\n return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n },\n )}\n }`,\n `interface FileRoutesByTo {\n ${[...createRouteNodesByTo(routeNodes).entries()].map(\n ([to, routeNode]) => {\n return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n },\n )}\n }`,\n `interface FileRoutesById {\n ${[...createRouteNodesById(routeNodes).entries()].map(\n ([id, routeNode]) => {\n return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`\n },\n )}\n }`,\n `interface FileRouteTypes {\n fileRoutesByFullPath: FileRoutesByFullPath\n fullPaths: ${[...createRouteNodesByFullPath(routeNodes).keys()].map((fullPath) => `'${fullPath}'`).join('|')}\n fileRoutesByTo: FileRoutesByTo\n to: ${[...createRouteNodesByTo(routeNodes).keys()].map((to) => `'${to}'`).join('|')}\n id: ${[...createRouteNodesById(routeNodes).keys()].map((id) => `'${id}'`).join('|')}\n fileRoutesById: FileRoutesById\n }`,\n `interface RootRouteChildren {\n ${routeTree.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}\n }`,\n `const rootRouteChildren: RootRouteChildren = {\n ${routeTree.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(',')}\n }`,\n `export const routeTree = rootRoute._addFileChildren(rootRouteChildren)._addFileTypes<FileRouteTypes>()`,\n ...config.routeTreeFileFooter,\n ]\n .filter(Boolean)\n .join('\\n\\n')\n\n const createRouteManifest = () => {\n const routesManifest = {\n __root__: {\n filePath: rootRouteNode.filePath,\n children: routeTree.map(\n (d) => getFilePathIdAndRouteIdFromPath(d.routePath)[1],\n ),\n },\n ...Object.fromEntries(\n routeNodes.map((d) => {\n const [_, routeId] = getFilePathIdAndRouteIdFromPath(d.routePath)\n\n return [\n routeId,\n {\n filePath: d.filePath,\n parent: d.parent?.routePath\n ? getFilePathIdAndRouteIdFromPath(d.parent.routePath)[1]\n : undefined,\n children: d.children?.map(\n (childRoute) =>\n getFilePathIdAndRouteIdFromPath(childRoute.routePath)[1],\n ),\n },\n ]\n }),\n ),\n }\n\n return JSON.stringify(\n {\n routes: routesManifest,\n },\n null,\n 2,\n )\n }\n\n const routeConfigFileContent = await prettier.format(\n config.disableManifestGeneration\n ? routeImports\n : [\n routeImports,\n '\\n',\n '/* ROUTE_MANIFEST_START',\n createRouteManifest(),\n 'ROUTE_MANIFEST_END */',\n ].join('\\n'),\n prettierOptions,\n )\n\n if (!checkLatest()) return\n\n const existingRouteTreeContent = await fsp\n .readFile(path.resolve(config.generatedRouteTree), 'utf-8')\n .catch((err) => {\n if (err.code === 'ENOENT') {\n return ''\n }\n\n throw err\n })\n\n if (!checkLatest()) return\n\n // Ensure the directory exists\n await fsp.mkdir(path.dirname(path.resolve(config.generatedRouteTree)), {\n recursive: true,\n })\n\n if (!checkLatest()) return\n\n // Write the route tree file, if it has changed\n if (existingRouteTreeContent !== routeConfigFileContent) {\n await fsp.writeFile(\n path.resolve(config.generatedRouteTree),\n routeConfigFileContent,\n )\n if (!checkLatest()) return\n }\n\n logger.log(\n `✅ Processed ${routeNodes.length === 1 ? 'route' : 'routes'} in ${\n Date.now() - start\n }ms`,\n )\n}\n\nfunction spaces(d: number): string {\n return Array.from({ length: d })\n .map(() => ' ')\n .join('')\n}\n\nfunction removeTrailingUnderscores(s?: string) {\n return s?.replaceAll(/(_$)/gi, '').replaceAll(/(_\\/)/gi, '/')\n}\n\nfunction removeGroups(s: string) {\n return s.replace(possiblyNestedRouteGroupPatternRegex, '')\n}\n\n/**\n * The `node.path` is used as the `id` in the route definition.\n * This function checks if the given node has a parent and if so, it determines the correct path for the given node.\n * @param node - The node to determine the path for.\n * @returns The correct path for the given node.\n */\nfunction determineNodePath(node: RouteNode) {\n return (node.path = node.parent\n ? node.routePath?.replace(node.parent.routePath ?? '', '') || '/'\n : node.routePath)\n}\n\n/**\n * Removes the last segment from a given path. Segments are considered to be separated by a '/'.\n *\n * @param {string} routePath - The path from which to remove the last segment. Defaults to '/'.\n * @returns {string} The path with the last segment removed.\n * @example\n * removeLastSegmentFromPath('/workspace/_auth/foo') // '/workspace/_auth'\n */\nexport function removeLastSegmentFromPath(routePath: string = '/'): string {\n const segments = routePath.split('/')\n segments.pop() // Remove the last segment\n return segments.join('/')\n}\n\n/**\n * Removes all segments from a given path that start with an underscore ('_').\n *\n * @param {string} routePath - The path from which to remove segments. Defaults to '/'.\n * @returns {string} The path with all underscore-prefixed segments removed.\n * @example\n * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo'\n */\nfunction removeLayoutSegments(routePath: string = '/'): string {\n const segments = routePath.split('/')\n const newSegments = segments.filter((segment) => !segment.startsWith('_'))\n return newSegments.join('/')\n}\n\nexport function hasParentRoute(\n routes: Array<RouteNode>,\n node: RouteNode,\n routePathToCheck: string | undefined,\n): RouteNode | null {\n if (!routePathToCheck || routePathToCheck === '/') {\n return null\n }\n\n const sortedNodes = multiSortBy(routes, [\n (d) => d.routePath!.length * -1,\n (d) => d.variableName,\n ]).filter((d) => d.routePath !== `/${rootPathId}`)\n\n for (const route of sortedNodes) {\n if (route.routePath === '/') continue\n\n if (\n routePathToCheck.startsWith(`${route.routePath}/`) &&\n route.routePath !== routePathToCheck\n ) {\n return route\n }\n }\n\n const segments = routePathToCheck.split('/')\n segments.pop() // Remove the last segment\n const parentRoutePath = segments.join('/')\n\n return hasParentRoute(routes, node, parentRoutePath)\n}\n\n/**\n * Gets the final variable name for a route\n */\nexport const getResolvedRouteNodeVariableName = (\n routeNode: RouteNode,\n): string => {\n return routeNode.children?.length\n ? `${routeNode.variableName}RouteWithChildren`\n : `${routeNode.variableName}Route`\n}\n\n/**\n * Creates a map from fullPath to routeNode\n */\nexport const createRouteNodesByFullPath = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n routeNodes.map((routeNode) => [inferFullPath(routeNode), routeNode]),\n )\n}\n\n/**\n * Create a map from 'to' to a routeNode\n */\nexport const createRouteNodesByTo = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n dedupeBranchesAndIndexRoutes(routeNodes).map((routeNode) => [\n inferTo(routeNode),\n routeNode,\n ]),\n )\n}\n\n/**\n * Create a map from 'id' to a routeNode\n */\nexport const createRouteNodesById = (\n routeNodes: Array<RouteNode>,\n): Map<string, RouteNode> => {\n return new Map(\n routeNodes.map((routeNode) => {\n const [_, id] = getFilePathIdAndRouteIdFromPath(routeNode.routePath)\n return [id, routeNode]\n }),\n )\n}\n\n/**\n * Infers the full path for use by TS\n */\nexport const inferFullPath = (routeNode: RouteNode): string => {\n const fullPath = removeGroups(\n removeUnderscores(removeLayoutSegments(routeNode.routePath)) ?? '',\n )\n\n return routeNode.cleanedPath === '/' ? fullPath : fullPath.replace(/\\/$/, '')\n}\n\n/**\n * Infers the path for use by TS\n */\nexport const inferPath = (routeNode: RouteNode): string => {\n return routeNode.cleanedPath === '/'\n ? routeNode.cleanedPath\n : (routeNode.cleanedPath?.replace(/\\/$/, '') ?? '')\n}\n\n/**\n * Infers to path\n */\nexport const inferTo = (routeNode: RouteNode): string => {\n const fullPath = inferFullPath(routeNode)\n\n if (fullPath === '/') return fullPath\n\n return fullPath.replace(/\\/$/, '')\n}\n\n/**\n * Dedupes branches and index routes\n */\nexport const dedupeBranchesAndIndexRoutes = (\n routes: Array<RouteNode>,\n): Array<RouteNode> => {\n return routes.filter((route) => {\n if (route.children?.find((child) => child.cleanedPath === '/')) return false\n return true\n })\n}\n\nfunction getFilePathIdAndRouteIdFromPath(pathname?: string) {\n const filePathId = removeTrailingUnderscores(pathname)\n const id = removeGroups(filePathId ?? '')\n\n return [filePathId, id] as const\n}\n\nfunction checkStartAPIRoutes(_routes: Array<RouteNode>) {\n if (_routes.length === 0) {\n return []\n }\n\n // Make sure these are valid URLs\n // Route Groups and Layout Routes aren't being removed since\n // you may want to have an API route that starts with an underscore\n // or be wrapped in parentheses\n const routes = _routes.map((d) => {\n const routePath = removeTrailingSlash(d.routePath ?? '')\n return { ...d, routePath }\n })\n\n // Check no two API routes have the same routePath\n // if they do, throw an error with the conflicting filePaths\n const routePaths = routes.map((d) => d.routePath)\n const uniqueRoutePaths = new Set(routePaths)\n if (routePaths.length !== uniqueRoutePaths.size) {\n const duplicateRoutePaths = routePaths.filter(\n (d, i) => routePaths.indexOf(d) !== i,\n )\n const conflictingFiles = routes\n .filter((d) => duplicateRoutePaths.includes(d.routePath))\n .map((d) => `${d.fullPath}`)\n const errorMessage = `Conflicting configuration paths was for found for the following API route${duplicateRoutePaths.length > 1 ? 's' : ''}: ${duplicateRoutePaths\n .map((p) => `\"${p}\"`)\n .join(', ')}.\nPlease ensure each API route has a unique route path.\nConflicting files: \\n ${conflictingFiles.join('\\n ')}\\n`\n throw new Error(errorMessage)\n }\n\n return routes\n}\n\nexport type StartAPIRoutePathSegment = {\n value: string\n type: 'path' | 'param' | 'splat'\n}\n\n/**\n * This function takes in a path in the format accepted by TanStack Router\n * and returns an array of path segments that can be used to generate\n * the pathname of the TanStack Start API route.\n *\n * @param src\n * @returns\n */\nexport function startAPIRouteSegmentsFromTSRFilePath(\n src: string,\n config: Config,\n): Array<StartAPIRoutePathSegment> {\n const routePath = determineInitialRoutePath(src)\n\n const parts = routePath\n .replaceAll('.', '/')\n .split('/')\n .filter((p) => !!p && p !== config.indexToken)\n const segments: Array<StartAPIRoutePathSegment> = parts.map((part) => {\n if (part.startsWith('$')) {\n if (part === '$') {\n return { value: part, type: 'splat' }\n }\n\n part.replaceAll('$', '')\n return { value: part, type: 'param' }\n }\n\n return { value: part, type: 'path' }\n })\n\n return segments\n}\n"],"names":["virtualGetRouteNodes","physicalGetRouteNodes","children"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/router-generator",
|
|
3
|
-
"version": "1.56.
|
|
3
|
+
"version": "1.56.1",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,5 +54,8 @@
|
|
|
54
54
|
"zod": "^3.23.8",
|
|
55
55
|
"@tanstack/virtual-file-routes": "^1.56.0"
|
|
56
56
|
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@tanstack/react-router": "^1.53.1"
|
|
59
|
+
},
|
|
57
60
|
"scripts": {}
|
|
58
61
|
}
|
package/src/generator.ts
CHANGED
|
@@ -392,13 +392,29 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
392
392
|
|
|
393
393
|
if (node.children?.length) {
|
|
394
394
|
const childConfigs = buildRouteTreeConfig(node.children, depth + 1)
|
|
395
|
-
|
|
395
|
+
|
|
396
|
+
const childrenDeclaration = `interface ${route}Children {
|
|
397
|
+
${node.children.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}
|
|
398
|
+
}`
|
|
399
|
+
|
|
400
|
+
const children = `const ${route}Children: ${route}Children = {
|
|
401
|
+
${node.children.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(',')}
|
|
402
|
+
}`
|
|
403
|
+
|
|
404
|
+
const routeWithChildren = `const ${route}WithChildren = ${route}._addFileChildren(${route}Children)`
|
|
405
|
+
|
|
406
|
+
return [
|
|
407
|
+
childConfigs,
|
|
408
|
+
childrenDeclaration,
|
|
409
|
+
children,
|
|
410
|
+
routeWithChildren,
|
|
411
|
+
].join('\n\n')
|
|
396
412
|
}
|
|
397
413
|
|
|
398
|
-
return
|
|
414
|
+
return undefined
|
|
399
415
|
})
|
|
400
416
|
|
|
401
|
-
return children.filter(Boolean).join(
|
|
417
|
+
return children.filter(Boolean).join('\n\n')
|
|
402
418
|
}
|
|
403
419
|
|
|
404
420
|
const routeConfigChildrenText = buildRouteTreeConfig(routeTree)
|
|
@@ -572,7 +588,43 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
572
588
|
}`,
|
|
573
589
|
]),
|
|
574
590
|
'// Create and export the route tree',
|
|
575
|
-
|
|
591
|
+
routeConfigChildrenText,
|
|
592
|
+
`interface FileRoutesByFullPath {
|
|
593
|
+
${[...createRouteNodesByFullPath(routeNodes).entries()].map(
|
|
594
|
+
([fullPath, routeNode]) => {
|
|
595
|
+
return `'${fullPath}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`
|
|
596
|
+
},
|
|
597
|
+
)}
|
|
598
|
+
}`,
|
|
599
|
+
`interface FileRoutesByTo {
|
|
600
|
+
${[...createRouteNodesByTo(routeNodes).entries()].map(
|
|
601
|
+
([to, routeNode]) => {
|
|
602
|
+
return `'${to}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`
|
|
603
|
+
},
|
|
604
|
+
)}
|
|
605
|
+
}`,
|
|
606
|
+
`interface FileRoutesById {
|
|
607
|
+
${[...createRouteNodesById(routeNodes).entries()].map(
|
|
608
|
+
([id, routeNode]) => {
|
|
609
|
+
return `'${id}': typeof ${getResolvedRouteNodeVariableName(routeNode)}`
|
|
610
|
+
},
|
|
611
|
+
)}
|
|
612
|
+
}`,
|
|
613
|
+
`interface FileRouteTypes {
|
|
614
|
+
fileRoutesByFullPath: FileRoutesByFullPath
|
|
615
|
+
fullPaths: ${[...createRouteNodesByFullPath(routeNodes).keys()].map((fullPath) => `'${fullPath}'`).join('|')}
|
|
616
|
+
fileRoutesByTo: FileRoutesByTo
|
|
617
|
+
to: ${[...createRouteNodesByTo(routeNodes).keys()].map((to) => `'${to}'`).join('|')}
|
|
618
|
+
id: ${[...createRouteNodesById(routeNodes).keys()].map((id) => `'${id}'`).join('|')}
|
|
619
|
+
fileRoutesById: FileRoutesById
|
|
620
|
+
}`,
|
|
621
|
+
`interface RootRouteChildren {
|
|
622
|
+
${routeTree.map((child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`).join(',')}
|
|
623
|
+
}`,
|
|
624
|
+
`const rootRouteChildren: RootRouteChildren = {
|
|
625
|
+
${routeTree.map((child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`).join(',')}
|
|
626
|
+
}`,
|
|
627
|
+
`export const routeTree = rootRoute._addFileChildren(rootRouteChildren)._addFileTypes<FileRouteTypes>()`,
|
|
576
628
|
...config.routeTreeFileFooter,
|
|
577
629
|
]
|
|
578
630
|
.filter(Boolean)
|
|
@@ -752,6 +804,56 @@ export function hasParentRoute(
|
|
|
752
804
|
return hasParentRoute(routes, node, parentRoutePath)
|
|
753
805
|
}
|
|
754
806
|
|
|
807
|
+
/**
|
|
808
|
+
* Gets the final variable name for a route
|
|
809
|
+
*/
|
|
810
|
+
export const getResolvedRouteNodeVariableName = (
|
|
811
|
+
routeNode: RouteNode,
|
|
812
|
+
): string => {
|
|
813
|
+
return routeNode.children?.length
|
|
814
|
+
? `${routeNode.variableName}RouteWithChildren`
|
|
815
|
+
: `${routeNode.variableName}Route`
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* Creates a map from fullPath to routeNode
|
|
820
|
+
*/
|
|
821
|
+
export const createRouteNodesByFullPath = (
|
|
822
|
+
routeNodes: Array<RouteNode>,
|
|
823
|
+
): Map<string, RouteNode> => {
|
|
824
|
+
return new Map(
|
|
825
|
+
routeNodes.map((routeNode) => [inferFullPath(routeNode), routeNode]),
|
|
826
|
+
)
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
/**
|
|
830
|
+
* Create a map from 'to' to a routeNode
|
|
831
|
+
*/
|
|
832
|
+
export const createRouteNodesByTo = (
|
|
833
|
+
routeNodes: Array<RouteNode>,
|
|
834
|
+
): Map<string, RouteNode> => {
|
|
835
|
+
return new Map(
|
|
836
|
+
dedupeBranchesAndIndexRoutes(routeNodes).map((routeNode) => [
|
|
837
|
+
inferTo(routeNode),
|
|
838
|
+
routeNode,
|
|
839
|
+
]),
|
|
840
|
+
)
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Create a map from 'id' to a routeNode
|
|
845
|
+
*/
|
|
846
|
+
export const createRouteNodesById = (
|
|
847
|
+
routeNodes: Array<RouteNode>,
|
|
848
|
+
): Map<string, RouteNode> => {
|
|
849
|
+
return new Map(
|
|
850
|
+
routeNodes.map((routeNode) => {
|
|
851
|
+
const [_, id] = getFilePathIdAndRouteIdFromPath(routeNode.routePath)
|
|
852
|
+
return [id, routeNode]
|
|
853
|
+
}),
|
|
854
|
+
)
|
|
855
|
+
}
|
|
856
|
+
|
|
755
857
|
/**
|
|
756
858
|
* Infers the full path for use by TS
|
|
757
859
|
*/
|
|
@@ -772,6 +874,29 @@ export const inferPath = (routeNode: RouteNode): string => {
|
|
|
772
874
|
: (routeNode.cleanedPath?.replace(/\/$/, '') ?? '')
|
|
773
875
|
}
|
|
774
876
|
|
|
877
|
+
/**
|
|
878
|
+
* Infers to path
|
|
879
|
+
*/
|
|
880
|
+
export const inferTo = (routeNode: RouteNode): string => {
|
|
881
|
+
const fullPath = inferFullPath(routeNode)
|
|
882
|
+
|
|
883
|
+
if (fullPath === '/') return fullPath
|
|
884
|
+
|
|
885
|
+
return fullPath.replace(/\/$/, '')
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
/**
|
|
889
|
+
* Dedupes branches and index routes
|
|
890
|
+
*/
|
|
891
|
+
export const dedupeBranchesAndIndexRoutes = (
|
|
892
|
+
routes: Array<RouteNode>,
|
|
893
|
+
): Array<RouteNode> => {
|
|
894
|
+
return routes.filter((route) => {
|
|
895
|
+
if (route.children?.find((child) => child.cleanedPath === '/')) return false
|
|
896
|
+
return true
|
|
897
|
+
})
|
|
898
|
+
}
|
|
899
|
+
|
|
775
900
|
function getFilePathIdAndRouteIdFromPath(pathname?: string) {
|
|
776
901
|
const filePathId = removeTrailingUnderscores(pathname)
|
|
777
902
|
const id = removeGroups(filePathId ?? '')
|