@tanstack/router-generator 1.132.0-alpha.9 → 1.132.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/cjs/config.cjs +6 -2
  2. package/dist/cjs/config.cjs.map +1 -1
  3. package/dist/cjs/config.d.cts +12 -9
  4. package/dist/cjs/generator.cjs +264 -316
  5. package/dist/cjs/generator.cjs.map +1 -1
  6. package/dist/cjs/generator.d.cts +20 -7
  7. package/dist/cjs/index.cjs +0 -1
  8. package/dist/cjs/index.cjs.map +1 -1
  9. package/dist/cjs/index.d.cts +4 -4
  10. package/dist/cjs/plugin/types.d.cts +10 -38
  11. package/dist/cjs/transform/transform.cjs +108 -40
  12. package/dist/cjs/transform/transform.cjs.map +1 -1
  13. package/dist/cjs/transform/transform.d.cts +1 -1
  14. package/dist/cjs/transform/types.d.cts +4 -18
  15. package/dist/cjs/types.d.cts +1 -1
  16. package/dist/cjs/utils.cjs +55 -39
  17. package/dist/cjs/utils.cjs.map +1 -1
  18. package/dist/cjs/utils.d.cts +5 -5
  19. package/dist/esm/config.d.ts +12 -9
  20. package/dist/esm/config.js +6 -2
  21. package/dist/esm/config.js.map +1 -1
  22. package/dist/esm/generator.d.ts +20 -7
  23. package/dist/esm/generator.js +266 -318
  24. package/dist/esm/generator.js.map +1 -1
  25. package/dist/esm/index.d.ts +4 -4
  26. package/dist/esm/index.js +1 -2
  27. package/dist/esm/plugin/types.d.ts +10 -38
  28. package/dist/esm/transform/transform.d.ts +1 -1
  29. package/dist/esm/transform/transform.js +106 -38
  30. package/dist/esm/transform/transform.js.map +1 -1
  31. package/dist/esm/transform/types.d.ts +4 -18
  32. package/dist/esm/types.d.ts +1 -1
  33. package/dist/esm/utils.d.ts +5 -5
  34. package/dist/esm/utils.js +55 -39
  35. package/dist/esm/utils.js.map +1 -1
  36. package/package.json +5 -5
  37. package/src/config.ts +7 -1
  38. package/src/generator.ts +306 -366
  39. package/src/index.ts +2 -7
  40. package/src/plugin/types.ts +11 -44
  41. package/src/transform/transform.ts +118 -53
  42. package/src/transform/types.ts +5 -18
  43. package/src/types.ts +1 -1
  44. package/src/utils.ts +85 -70
  45. package/dist/cjs/plugin/default-generator-plugin.cjs +0 -94
  46. package/dist/cjs/plugin/default-generator-plugin.cjs.map +0 -1
  47. package/dist/cjs/plugin/default-generator-plugin.d.cts +0 -2
  48. package/dist/cjs/transform/default-transform-plugin.cjs +0 -97
  49. package/dist/cjs/transform/default-transform-plugin.cjs.map +0 -1
  50. package/dist/cjs/transform/default-transform-plugin.d.cts +0 -2
  51. package/dist/esm/plugin/default-generator-plugin.d.ts +0 -2
  52. package/dist/esm/plugin/default-generator-plugin.js +0 -94
  53. package/dist/esm/plugin/default-generator-plugin.js.map +0 -1
  54. package/dist/esm/transform/default-transform-plugin.d.ts +0 -2
  55. package/dist/esm/transform/default-transform-plugin.js +0 -97
  56. package/dist/esm/transform/default-transform-plugin.js.map +0 -1
  57. package/src/plugin/default-generator-plugin.ts +0 -109
  58. package/src/transform/default-transform-plugin.ts +0 -106
package/src/index.ts CHANGED
@@ -9,11 +9,7 @@ export type { Config, BaseConfig } from './config'
9
9
  export { Generator } from './generator'
10
10
  export type { FileEventType, FileEvent, GeneratorEvent } from './generator'
11
11
 
12
- export type {
13
- GeneratorPluginBase,
14
- GeneratorPlugin,
15
- GeneratorPluginWithTransform,
16
- } from './plugin/types'
12
+ export type { GeneratorPlugin } from './plugin/types'
17
13
 
18
14
  export {
19
15
  capitalize,
@@ -31,7 +27,6 @@ export {
31
27
  format,
32
28
  removeExt,
33
29
  checkRouteFullPathUniqueness,
34
- hasChildWithExport,
35
30
  } from './utils'
36
31
 
37
32
  export type {
@@ -41,6 +36,7 @@ export type {
41
36
  GetRoutesByFileMapResultValue,
42
37
  ImportDeclaration,
43
38
  ImportSpecifier,
39
+ HandleNodeAccumulator,
44
40
  } from './types'
45
41
 
46
42
  export { getRouteNodes as physicalGetRouteNodes } from './filesystem/physical/getRouteNodes'
@@ -54,5 +50,4 @@ export type {
54
50
  TransformImportsConfig,
55
51
  TransformContext,
56
52
  TransformOptions,
57
- TransformPlugin,
58
53
  } from './transform/types'
@@ -1,51 +1,18 @@
1
- import type { TransformPlugin } from '../transform/types'
2
- import type {
3
- HandleNodeAccumulator,
4
- ImportDeclaration,
5
- RouteNode,
6
- } from '../types'
7
-
1
+ import type { HandleNodeAccumulator, RouteNode } from '../types'
8
2
  import type { Generator } from '../generator'
9
3
 
10
- export type GeneratorPlugin = GeneratorPluginBase | GeneratorPluginWithTransform
11
-
12
- export interface GeneratorPluginBase {
4
+ export interface GeneratorPlugin {
13
5
  name: string
14
- onRouteTreesChanged?: (opts: {
15
- routeTrees: Array<{
16
- sortedRouteNodes: Array<RouteNode>
17
- acc: HandleNodeAccumulator
18
- exportName: string
19
- }>
6
+ init?: (opts: { generator: Generator }) => void
7
+ onRouteTreeChanged?: (opts: {
8
+ routeTree: Array<RouteNode>
9
+ routeNodes: Array<RouteNode>
20
10
  rootRouteNode: RouteNode
21
- generator: Generator
11
+ acc: HandleNodeAccumulator
22
12
  }) => void
23
- }
24
13
 
25
- export interface GeneratorPluginWithTransform extends GeneratorPluginBase {
26
- transformPlugin: TransformPlugin
27
- moduleAugmentation: (opts: { generator: Generator }) => {
28
- module: string
29
- interfaceName: string
30
- }
31
- imports: (opts: {
32
- rootRouteNode: RouteNode
33
- sortedRouteNodes: Array<RouteNode>
34
- acc: HandleNodeAccumulator
35
- generator: Generator
36
- }) => Array<ImportDeclaration>
37
- routeModuleAugmentation: (opts: {
38
- routeNode: RouteNode
39
- }) => string | undefined
40
- createRootRouteCode: () => string
41
- createVirtualRouteCode: (opts: { node: RouteNode }) => string
42
- config: (opts: {
43
- generator: Generator
44
- rootRouteNode: RouteNode
45
- sortedRouteNodes: Array<RouteNode>
46
- }) => {
47
- virtualRootRoute?: boolean
48
- }
14
+ afterTransform?: (opts: {
15
+ node: RouteNode
16
+ prevNode: RouteNode | undefined
17
+ }) => void
49
18
  }
50
-
51
- export {}
@@ -2,24 +2,20 @@ import { parseAst } from '@tanstack/router-utils'
2
2
  import { parse, print, types, visit } from 'recast'
3
3
  import { SourceMapConsumer } from 'source-map'
4
4
  import { mergeImportDeclarations } from '../utils'
5
+ import { ensureStringArgument } from './utils'
5
6
  import type { ImportDeclaration } from '../types'
6
7
  import type { RawSourceMap } from 'source-map'
7
- import type {
8
- TransformOptions,
9
- TransformPlugin,
10
- TransformResult,
11
- } from './types'
8
+ import type { TransformOptions, TransformResult } from './types'
12
9
 
13
10
  const b = types.builders
14
11
 
15
12
  export async function transform({
16
13
  ctx,
17
14
  source,
18
- plugins,
15
+ node,
19
16
  }: TransformOptions): Promise<TransformResult> {
20
17
  let appliedChanges = false as boolean
21
18
  let ast: types.namedTypes.File
22
- const foundExports: Array<string> = []
23
19
  try {
24
20
  ast = parse(source, {
25
21
  sourceFileName: 'output.ts',
@@ -44,41 +40,77 @@ export async function transform({
44
40
 
45
41
  const preferredQuote = detectPreferredQuoteStyle(ast)
46
42
 
47
- const registeredExports = new Map</* export name */ string, TransformPlugin>()
48
-
49
- for (const plugin of plugins ?? []) {
50
- const exportName = plugin.exportName
51
- if (registeredExports.has(exportName)) {
43
+ let routeExportHandled = false as boolean
44
+ function onExportFound(decl: types.namedTypes.VariableDeclarator) {
45
+ if (decl.init?.type === 'CallExpression') {
46
+ const callExpression = decl.init
47
+ const firstArgument = callExpression.arguments[0]
48
+ if (firstArgument) {
49
+ if (firstArgument.type === 'ObjectExpression') {
50
+ const staticProperties = firstArgument.properties.flatMap((p) => {
51
+ if (p.type === 'ObjectProperty' && p.key.type === 'Identifier') {
52
+ return p.key.name
53
+ }
54
+ return []
55
+ })
56
+ node.createFileRouteProps = new Set(staticProperties)
57
+ }
58
+ }
59
+ let identifier: types.namedTypes.Identifier | undefined
60
+ // `const Route = createFileRoute({ ... })`
61
+ if (callExpression.callee.type === 'Identifier') {
62
+ identifier = callExpression.callee
63
+ if (ctx.verboseFileRoutes) {
64
+ // we need to add the string literal via another CallExpression
65
+ callExpression.callee = b.callExpression(identifier, [
66
+ b.stringLiteral(ctx.routeId),
67
+ ])
68
+ appliedChanges = true
69
+ }
70
+ }
71
+ // `const Route = createFileRoute('/path')({ ... })`
72
+ else if (
73
+ callExpression.callee.type === 'CallExpression' &&
74
+ callExpression.callee.callee.type === 'Identifier'
75
+ ) {
76
+ identifier = callExpression.callee.callee
77
+ if (!ctx.verboseFileRoutes) {
78
+ // we need to remove the route id
79
+ callExpression.callee = identifier
80
+ appliedChanges = true
81
+ } else {
82
+ // check if the route id is correct
83
+ appliedChanges = ensureStringArgument(
84
+ callExpression.callee,
85
+ ctx.routeId,
86
+ ctx.preferredQuote,
87
+ )
88
+ }
89
+ }
90
+ if (identifier === undefined) {
91
+ throw new Error(
92
+ `expected identifier to be present in ${ctx.routeId} for export "Route"`,
93
+ )
94
+ }
95
+ if (identifier.name === 'createFileRoute' && ctx.lazy) {
96
+ identifier.name = 'createLazyFileRoute'
97
+ appliedChanges = true
98
+ } else if (identifier.name === 'createLazyFileRoute' && !ctx.lazy) {
99
+ identifier.name = 'createFileRoute'
100
+ appliedChanges = true
101
+ }
102
+ } else {
52
103
  throw new Error(
53
- `Export ${exportName} is already registered by plugin ${registeredExports.get(exportName)?.name}`,
104
+ `expected "Route" export to be initialized by a CallExpression`,
54
105
  )
55
106
  }
56
- registeredExports.set(exportName, plugin)
57
- }
58
-
59
- function onExportFound(
60
- decl: types.namedTypes.VariableDeclarator,
61
- exportName: string,
62
- plugin: TransformPlugin,
63
- ) {
64
- const pluginAppliedChanges = plugin.onExportFound({
65
- decl,
66
- ctx: { ...ctx, preferredQuote },
67
- })
68
- if (pluginAppliedChanges) {
69
- appliedChanges = true
70
- }
71
-
72
- // export is handled, remove it from the registered exports
73
- registeredExports.delete(exportName)
74
- // store the export so we can later return it once the file is transformed
75
- foundExports.push(exportName)
107
+ routeExportHandled = true
76
108
  }
77
109
 
78
110
  const program: types.namedTypes.Program = ast.program
79
- // first pass: find registered exports
111
+ // first pass: find Route export
80
112
  for (const n of program.body) {
81
- if (registeredExports.size > 0 && n.type === 'ExportNamedDeclaration') {
113
+ if (n.type === 'ExportNamedDeclaration') {
82
114
  // direct export of a variable declaration, e.g. `export const Route = createFileRoute('/path')`
83
115
  if (n.declaration?.type === 'VariableDeclaration') {
84
116
  const decl = n.declaration.declarations[0]
@@ -87,9 +119,8 @@ export async function transform({
87
119
  decl.type === 'VariableDeclarator' &&
88
120
  decl.id.type === 'Identifier'
89
121
  ) {
90
- const plugin = registeredExports.get(decl.id.name)
91
- if (plugin) {
92
- onExportFound(decl, decl.id.name, plugin)
122
+ if (decl.id.name === 'Route') {
123
+ onExportFound(decl)
93
124
  }
94
125
  }
95
126
  }
@@ -97,8 +128,7 @@ export async function transform({
97
128
  else if (n.declaration === null && n.specifiers) {
98
129
  for (const spec of n.specifiers) {
99
130
  if (typeof spec.exported.name === 'string') {
100
- const plugin = registeredExports.get(spec.exported.name)
101
- if (plugin) {
131
+ if (spec.exported.name === 'Route') {
102
132
  const variableName = spec.local?.name || spec.exported.name
103
133
  // find the matching variable declaration by iterating over the top-level declarations
104
134
  for (const decl of program.body) {
@@ -112,7 +142,7 @@ export async function transform({
112
142
  variable.id.type === 'Identifier' &&
113
143
  variable.id.name === variableName
114
144
  ) {
115
- onExportFound(variable, spec.exported.name, plugin)
145
+ onExportFound(variable)
116
146
  break
117
147
  }
118
148
  }
@@ -122,6 +152,15 @@ export async function transform({
122
152
  }
123
153
  }
124
154
  }
155
+ if (routeExportHandled) {
156
+ break
157
+ }
158
+ }
159
+
160
+ if (!routeExportHandled) {
161
+ return {
162
+ result: 'no-route-export',
163
+ }
125
164
  }
126
165
 
127
166
  const imports: {
@@ -132,16 +171,44 @@ export async function transform({
132
171
  banned: [],
133
172
  }
134
173
 
135
- for (const plugin of plugins ?? []) {
136
- const exportName = plugin.exportName
137
- if (foundExports.includes(exportName)) {
138
- const pluginImports = plugin.imports(ctx)
139
- if (pluginImports.required) {
140
- imports.required.push(...pluginImports.required)
141
- }
142
- if (pluginImports.banned) {
143
- imports.banned.push(...pluginImports.banned)
144
- }
174
+ const targetModule = `@tanstack/${ctx.target}-router`
175
+ if (ctx.verboseFileRoutes === false) {
176
+ imports.banned = [
177
+ {
178
+ source: targetModule,
179
+ specifiers: [
180
+ { imported: 'createLazyFileRoute' },
181
+ { imported: 'createFileRoute' },
182
+ ],
183
+ },
184
+ ]
185
+ } else {
186
+ if (ctx.lazy) {
187
+ imports.required = [
188
+ {
189
+ source: targetModule,
190
+ specifiers: [{ imported: 'createLazyFileRoute' }],
191
+ },
192
+ ]
193
+ imports.banned = [
194
+ {
195
+ source: targetModule,
196
+ specifiers: [{ imported: 'createFileRoute' }],
197
+ },
198
+ ]
199
+ } else {
200
+ imports.required = [
201
+ {
202
+ source: targetModule,
203
+ specifiers: [{ imported: 'createFileRoute' }],
204
+ },
205
+ ]
206
+ imports.banned = [
207
+ {
208
+ source: targetModule,
209
+ specifiers: [{ imported: 'createLazyFileRoute' }],
210
+ },
211
+ ]
145
212
  }
146
213
  }
147
214
 
@@ -289,7 +356,6 @@ export async function transform({
289
356
 
290
357
  if (!appliedChanges) {
291
358
  return {
292
- exports: foundExports,
293
359
  result: 'not-modified',
294
360
  }
295
361
  }
@@ -310,7 +376,6 @@ export async function transform({
310
376
  }
311
377
  return {
312
378
  result: 'modified',
313
- exports: foundExports,
314
379
  output: transformedCode,
315
380
  }
316
381
  }
@@ -1,22 +1,22 @@
1
- import type { ImportDeclaration } from '../types'
2
- import type { types } from 'recast'
1
+ import type { ImportDeclaration, RouteNode } from '../types'
3
2
  import type { Config } from '../config'
4
3
 
5
4
  export interface TransformOptions {
6
5
  source: string
7
6
  ctx: TransformContext
8
- plugins?: Array<TransformPlugin>
7
+ node: RouteNode
9
8
  }
10
9
 
11
10
  export type TransformResult =
11
+ | {
12
+ result: 'no-route-export'
13
+ }
12
14
  | {
13
15
  result: 'not-modified'
14
- exports: Array<string>
15
16
  }
16
17
  | {
17
18
  result: 'modified'
18
19
  output: string
19
- exports: Array<string>
20
20
  }
21
21
  | {
22
22
  result: 'error'
@@ -27,19 +27,6 @@ export interface TransformImportsConfig {
27
27
  banned?: Array<ImportDeclaration>
28
28
  required?: Array<ImportDeclaration>
29
29
  }
30
- export interface TransformPlugin {
31
- name: string
32
- exportName: string
33
- imports: (ctx: TransformContext) => TransformImportsConfig
34
- /**
35
- * Called after the export is found in the AST.
36
- * @returns true if the plugin modified the AST, false otherwise
37
- */
38
- onExportFound: (opts: {
39
- decl: types.namedTypes.VariableDeclarator
40
- ctx: TransformContext
41
- }) => boolean
42
- }
43
30
 
44
31
  export interface TransformContext {
45
32
  target: Config['target']
package/src/types.ts CHANGED
@@ -12,7 +12,7 @@ export type RouteNode = {
12
12
  isVirtual?: boolean
13
13
  children?: Array<RouteNode>
14
14
  parent?: RouteNode
15
- exports?: Array<string>
15
+ createFileRouteProps?: Set<string>
16
16
  }
17
17
 
18
18
  export interface GetRouteNodesResult {
package/src/utils.ts CHANGED
@@ -320,11 +320,10 @@ export function hasParentRoute(
320
320
  */
321
321
  export const getResolvedRouteNodeVariableName = (
322
322
  routeNode: RouteNode,
323
- variableNameSuffix: string,
324
323
  ): string => {
325
324
  return routeNode.children?.length
326
- ? `${routeNode.variableName}${variableNameSuffix}WithChildren`
327
- : `${routeNode.variableName}${variableNameSuffix}`
325
+ ? `${routeNode.variableName}RouteWithChildren`
326
+ : `${routeNode.variableName}Route`
328
327
  }
329
328
 
330
329
  /**
@@ -463,65 +462,59 @@ Conflicting files: \n ${conflictingFiles.map((d) => path.resolve(config.routesDi
463
462
 
464
463
  export function buildRouteTreeConfig(
465
464
  nodes: Array<RouteNode>,
466
- exportName: string,
467
465
  disableTypes: boolean,
468
466
  depth = 1,
469
467
  ): Array<string> {
470
- const children = nodes
471
- .filter((n) => n.exports?.includes(exportName))
472
- .map((node) => {
473
- if (node._fsRouteType === '__root') {
474
- return
475
- }
468
+ const children = nodes.map((node) => {
469
+ if (node._fsRouteType === '__root') {
470
+ return
471
+ }
476
472
 
477
- if (node._fsRouteType === 'pathless_layout' && !node.children?.length) {
478
- return
479
- }
473
+ if (node._fsRouteType === 'pathless_layout' && !node.children?.length) {
474
+ return
475
+ }
480
476
 
481
- const route = `${node.variableName}`
477
+ const route = `${node.variableName}`
482
478
 
483
- if (node.children?.length) {
484
- const childConfigs = buildRouteTreeConfig(
485
- node.children,
486
- exportName,
487
- disableTypes,
488
- depth + 1,
489
- )
479
+ if (node.children?.length) {
480
+ const childConfigs = buildRouteTreeConfig(
481
+ node.children,
482
+ disableTypes,
483
+ depth + 1,
484
+ )
490
485
 
491
- const childrenDeclaration = disableTypes
492
- ? ''
493
- : `interface ${route}${exportName}Children {
486
+ const childrenDeclaration = disableTypes
487
+ ? ''
488
+ : `interface ${route}RouteChildren {
494
489
  ${node.children
495
- .filter((n) => n.exports?.includes(exportName))
496
490
  .map(
497
491
  (child) =>
498
- `${child.variableName}${exportName}: typeof ${getResolvedRouteNodeVariableName(child, exportName)}`,
492
+ `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`,
499
493
  )
500
494
  .join(',')}
501
495
  }`
502
496
 
503
- const children = `const ${route}${exportName}Children${disableTypes ? '' : `: ${route}${exportName}Children`} = {
497
+ const children = `const ${route}RouteChildren${disableTypes ? '' : `: ${route}RouteChildren`} = {
504
498
  ${node.children
505
- .filter((n) => n.exports?.includes(exportName))
506
499
  .map(
507
500
  (child) =>
508
- `${child.variableName}${exportName}: ${getResolvedRouteNodeVariableName(child, exportName)}`,
501
+ `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`,
509
502
  )
510
503
  .join(',')}
511
504
  }`
512
505
 
513
- const routeWithChildren = `const ${route}${exportName}WithChildren = ${route}${exportName}._addFileChildren(${route}${exportName}Children)`
506
+ const routeWithChildren = `const ${route}RouteWithChildren = ${route}Route._addFileChildren(${route}RouteChildren)`
514
507
 
515
- return [
516
- childConfigs.join('\n'),
517
- childrenDeclaration,
518
- children,
519
- routeWithChildren,
520
- ].join('\n\n')
521
- }
508
+ return [
509
+ childConfigs.join('\n'),
510
+ childrenDeclaration,
511
+ children,
512
+ routeWithChildren,
513
+ ].join('\n\n')
514
+ }
522
515
 
523
- return undefined
524
- })
516
+ return undefined
517
+ })
525
518
 
526
519
  return children.filter((x) => x !== undefined)
527
520
  }
@@ -570,55 +563,33 @@ export function mergeImportDeclarations(
570
563
  return Object.values(merged)
571
564
  }
572
565
 
573
- export function hasChildWithExport(
574
- node: RouteNode,
575
- exportName: string,
576
- ): boolean {
577
- return (
578
- node.children?.some((child) => hasChildWithExport(child, exportName)) ??
579
- false
580
- )
581
- }
582
-
583
- export const findParent = (
584
- node: RouteNode | undefined,
585
- exportName: string,
586
- ): string => {
566
+ export const findParent = (node: RouteNode | undefined): string => {
587
567
  if (!node) {
588
- return `root${exportName}Import`
568
+ return `rootRouteImport`
589
569
  }
590
570
  if (node.parent) {
591
- if (node.parent.exports?.includes(exportName)) {
592
- if (node.isVirtualParentRequired) {
593
- return `${node.parent.variableName}${exportName}`
594
- } else {
595
- return `${node.parent.variableName}${exportName}`
596
- }
571
+ if (node.isVirtualParentRequired) {
572
+ return `${node.parent.variableName}Route`
573
+ } else {
574
+ return `${node.parent.variableName}Route`
597
575
  }
598
576
  }
599
- return findParent(node.parent, exportName)
577
+ return findParent(node.parent)
600
578
  }
601
579
 
602
580
  export function buildFileRoutesByPathInterface(opts: {
603
581
  routeNodes: Array<RouteNode>
604
582
  module: string
605
583
  interfaceName: string
606
- exportName: string
607
584
  }): string {
608
585
  return `declare module '${opts.module}' {
609
586
  interface ${opts.interfaceName} {
610
587
  ${opts.routeNodes
611
588
  .map((routeNode) => {
612
589
  const filePathId = routeNode.routePath
613
- let preloaderRoute = ''
614
-
615
- if (routeNode.exports?.includes(opts.exportName)) {
616
- preloaderRoute = `typeof ${routeNode.variableName}${opts.exportName}Import`
617
- } else {
618
- preloaderRoute = 'unknown'
619
- }
590
+ const preloaderRoute = `typeof ${routeNode.variableName}RouteImport`
620
591
 
621
- const parent = findParent(routeNode, opts.exportName)
592
+ const parent = findParent(routeNode)
622
593
 
623
594
  return `'${filePathId}': {
624
595
  id: '${filePathId}'
@@ -632,3 +603,47 @@ export function buildFileRoutesByPathInterface(opts: {
632
603
  }
633
604
  }`
634
605
  }
606
+
607
+ export function getImportPath(
608
+ node: RouteNode,
609
+ config: Config,
610
+ generatedRouteTreePath: string,
611
+ ): string {
612
+ return replaceBackslash(
613
+ removeExt(
614
+ path.relative(
615
+ path.dirname(generatedRouteTreePath),
616
+ path.resolve(config.routesDirectory, node.filePath),
617
+ ),
618
+ config.addExtensions,
619
+ ),
620
+ )
621
+ }
622
+
623
+ export function getImportForRouteNode(
624
+ node: RouteNode,
625
+ config: Config,
626
+ generatedRouteTreePath: string,
627
+ root: string,
628
+ ): ImportDeclaration {
629
+ let source = ''
630
+ if (config.importRoutesUsingAbsolutePaths) {
631
+ source = replaceBackslash(
632
+ removeExt(
633
+ path.resolve(root, config.routesDirectory, node.filePath),
634
+ config.addExtensions,
635
+ ),
636
+ )
637
+ } else {
638
+ source = `./${getImportPath(node, config, generatedRouteTreePath)}`
639
+ }
640
+ return {
641
+ source,
642
+ specifiers: [
643
+ {
644
+ imported: 'Route',
645
+ local: `${node.variableName}RouteImport`,
646
+ },
647
+ ],
648
+ } satisfies ImportDeclaration
649
+ }