@tanstack/router-generator 1.55.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/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
- return `${route}: ${route}.addChildren({${spaces(depth * 4)}${childConfigs}})`
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 route
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
- `export const routeTree = rootRoute.addChildren({${routeConfigChildrenText}})`,
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 ?? '')