@tanstack/router-generator 1.121.0-alpha.26 → 1.121.0-alpha.28

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 (75) hide show
  1. package/dist/cjs/config.cjs +5 -5
  2. package/dist/cjs/config.cjs.map +1 -1
  3. package/dist/cjs/config.d.cts +3 -3
  4. package/dist/cjs/filesystem/physical/getRouteNodes.cjs +18 -4
  5. package/dist/cjs/filesystem/physical/getRouteNodes.cjs.map +1 -1
  6. package/dist/cjs/filesystem/physical/getRouteNodes.d.cts +1 -0
  7. package/dist/cjs/filesystem/virtual/config.cjs.map +1 -1
  8. package/dist/cjs/filesystem/virtual/getRouteNodes.cjs +18 -12
  9. package/dist/cjs/filesystem/virtual/getRouteNodes.cjs.map +1 -1
  10. package/dist/cjs/filesystem/virtual/getRouteNodes.d.cts +4 -1
  11. package/dist/cjs/filesystem/virtual/loadConfigFile.cjs.map +1 -1
  12. package/dist/cjs/generator.cjs +147 -98
  13. package/dist/cjs/generator.cjs.map +1 -1
  14. package/dist/cjs/generator.d.cts +11 -9
  15. package/dist/cjs/index.d.cts +1 -1
  16. package/dist/cjs/logger.cjs.map +1 -1
  17. package/dist/cjs/plugin/default-generator-plugin.cjs +16 -10
  18. package/dist/cjs/plugin/default-generator-plugin.cjs.map +1 -1
  19. package/dist/cjs/template.cjs.map +1 -1
  20. package/dist/cjs/transform/default-transform-plugin.cjs +6 -4
  21. package/dist/cjs/transform/default-transform-plugin.cjs.map +1 -1
  22. package/dist/cjs/transform/transform.cjs +48 -32
  23. package/dist/cjs/transform/transform.cjs.map +1 -1
  24. package/dist/cjs/transform/transform.d.cts +1 -1
  25. package/dist/cjs/transform/types.d.cts +1 -1
  26. package/dist/cjs/transform/utils.cjs.map +1 -1
  27. package/dist/cjs/transform/utils.d.cts +1 -1
  28. package/dist/cjs/types.d.cts +5 -0
  29. package/dist/cjs/utils.cjs +43 -24
  30. package/dist/cjs/utils.cjs.map +1 -1
  31. package/dist/cjs/utils.d.cts +6 -0
  32. package/dist/esm/config.d.ts +3 -3
  33. package/dist/esm/config.js +6 -6
  34. package/dist/esm/config.js.map +1 -1
  35. package/dist/esm/filesystem/physical/getRouteNodes.d.ts +1 -0
  36. package/dist/esm/filesystem/physical/getRouteNodes.js +19 -5
  37. package/dist/esm/filesystem/physical/getRouteNodes.js.map +1 -1
  38. package/dist/esm/filesystem/virtual/config.js.map +1 -1
  39. package/dist/esm/filesystem/virtual/getRouteNodes.d.ts +4 -1
  40. package/dist/esm/filesystem/virtual/getRouteNodes.js +19 -13
  41. package/dist/esm/filesystem/virtual/getRouteNodes.js.map +1 -1
  42. package/dist/esm/filesystem/virtual/loadConfigFile.js.map +1 -1
  43. package/dist/esm/generator.d.ts +11 -9
  44. package/dist/esm/generator.js +150 -101
  45. package/dist/esm/generator.js.map +1 -1
  46. package/dist/esm/index.d.ts +1 -1
  47. package/dist/esm/logger.js.map +1 -1
  48. package/dist/esm/plugin/default-generator-plugin.js +16 -10
  49. package/dist/esm/plugin/default-generator-plugin.js.map +1 -1
  50. package/dist/esm/template.js.map +1 -1
  51. package/dist/esm/transform/default-transform-plugin.js +6 -4
  52. package/dist/esm/transform/default-transform-plugin.js.map +1 -1
  53. package/dist/esm/transform/transform.d.ts +1 -1
  54. package/dist/esm/transform/transform.js +48 -32
  55. package/dist/esm/transform/transform.js.map +1 -1
  56. package/dist/esm/transform/types.d.ts +1 -1
  57. package/dist/esm/transform/utils.d.ts +1 -1
  58. package/dist/esm/transform/utils.js.map +1 -1
  59. package/dist/esm/types.d.ts +5 -0
  60. package/dist/esm/utils.d.ts +6 -0
  61. package/dist/esm/utils.js +43 -24
  62. package/dist/esm/utils.js.map +1 -1
  63. package/package.json +5 -5
  64. package/src/config.ts +6 -5
  65. package/src/filesystem/physical/getRouteNodes.ts +31 -11
  66. package/src/filesystem/virtual/getRouteNodes.ts +32 -23
  67. package/src/generator.ts +196 -72
  68. package/src/index.ts +2 -0
  69. package/src/plugin/default-generator-plugin.ts +16 -3
  70. package/src/transform/default-transform-plugin.ts +5 -2
  71. package/src/transform/transform.ts +68 -43
  72. package/src/transform/types.ts +1 -1
  73. package/src/transform/utils.ts +1 -1
  74. package/src/types.ts +7 -0
  75. package/src/utils.ts +79 -31
@@ -56,35 +56,69 @@ export async function transform({
56
56
  registeredExports.set(exportName, plugin)
57
57
  }
58
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)
76
+ }
77
+
59
78
  const program: types.namedTypes.Program = ast.program
60
79
  // first pass: find registered exports
61
80
  for (const n of program.body) {
62
- if (
63
- registeredExports.size > 0 &&
64
- n.type === 'ExportNamedDeclaration' &&
65
- n.declaration?.type === 'VariableDeclaration'
66
- ) {
67
- const decl = n.declaration.declarations[0]
68
- if (
69
- decl &&
70
- decl.type === 'VariableDeclarator' &&
71
- decl.id.type === 'Identifier'
72
- ) {
73
- const plugin = registeredExports.get(decl.id.name)
74
- if (plugin) {
75
- const pluginAppliedChanges = plugin.onExportFound({
76
- decl,
77
- ctx: { ...ctx, preferredQuote },
78
- })
79
-
80
- if (pluginAppliedChanges) {
81
- appliedChanges = true
81
+ if (registeredExports.size > 0 && n.type === 'ExportNamedDeclaration') {
82
+ // direct export of a variable declaration, e.g. `export const Route = createFileRoute('/path')`
83
+ if (n.declaration?.type === 'VariableDeclaration') {
84
+ const decl = n.declaration.declarations[0]
85
+ if (
86
+ decl &&
87
+ decl.type === 'VariableDeclarator' &&
88
+ decl.id.type === 'Identifier'
89
+ ) {
90
+ const plugin = registeredExports.get(decl.id.name)
91
+ if (plugin) {
92
+ onExportFound(decl, decl.id.name, plugin)
93
+ }
94
+ }
95
+ }
96
+ // this is an export without a declaration, e.g. `export { Route }`
97
+ else if (n.declaration === null && n.specifiers) {
98
+ for (const spec of n.specifiers) {
99
+ if (typeof spec.exported.name === 'string') {
100
+ const plugin = registeredExports.get(spec.exported.name)
101
+ if (plugin) {
102
+ const variableName = spec.local?.name || spec.exported.name
103
+ // find the matching variable declaration by iterating over the top-level declarations
104
+ for (const decl of program.body) {
105
+ if (
106
+ decl.type === 'VariableDeclaration' &&
107
+ decl.declarations[0]
108
+ ) {
109
+ const variable = decl.declarations[0]
110
+ if (
111
+ variable.type === 'VariableDeclarator' &&
112
+ variable.id.type === 'Identifier' &&
113
+ variable.id.name === variableName
114
+ ) {
115
+ onExportFound(variable, spec.exported.name, plugin)
116
+ break
117
+ }
118
+ }
119
+ }
120
+ }
82
121
  }
83
-
84
- // export is handled, remove it from the registered exports
85
- registeredExports.delete(decl.id.name)
86
- // store the export so we can later return it once the file is transformed
87
- foundExports.push(decl.id.name)
88
122
  }
89
123
  }
90
124
  }
@@ -290,7 +324,7 @@ async function fixTransformedOutputText({
290
324
  originalCode: string
291
325
  transformedCode: string
292
326
  sourceMap: RawSourceMap
293
- preferredQuote: '"' | "'" | '`'
327
+ preferredQuote: '"' | "'"
294
328
  }) {
295
329
  const originalLines = originalCode.split('\n')
296
330
  const transformedLines = transformedCode.split('\n')
@@ -302,11 +336,10 @@ async function fixTransformedOutputText({
302
336
  const fixedLines = transformedLines.map((line, i) => {
303
337
  const transformedLineNum = i + 1
304
338
 
305
- let mapped = null
306
- let origLineText = null
339
+ let origLineText: string | undefined = undefined
307
340
 
308
341
  for (let col = 0; col < line.length; col++) {
309
- mapped = consumer.originalPositionFor({
342
+ const mapped = consumer.originalPositionFor({
310
343
  line: transformedLineNum,
311
344
  column: col,
312
345
  })
@@ -316,7 +349,7 @@ async function fixTransformedOutputText({
316
349
  }
317
350
  }
318
351
 
319
- if (origLineText != null) {
352
+ if (origLineText !== undefined) {
320
353
  if (origLineText === line) {
321
354
  return origLineText
322
355
  }
@@ -409,10 +442,9 @@ function detectSemicolonUsage(code: string) {
409
442
  return withSemis > total / 2
410
443
  }
411
444
 
412
- export function detectPreferredQuoteStyle(ast: types.ASTNode): "'" | '"' | '`' {
445
+ export function detectPreferredQuoteStyle(ast: types.ASTNode): "'" | '"' {
413
446
  let single = 0
414
447
  let double = 0
415
- let backtick = 0
416
448
 
417
449
  visit(ast, {
418
450
  visitStringLiteral(path) {
@@ -423,17 +455,10 @@ export function detectPreferredQuoteStyle(ast: types.ASTNode): "'" | '"' | '`' {
423
455
  }
424
456
  return false
425
457
  },
426
- visitTemplateLiteral(path) {
427
- if (path.parent.type !== 'JSXAttribute') {
428
- backtick++
429
- }
430
- return false
431
- },
432
458
  })
433
459
 
434
- return single >= double && single >= backtick
435
- ? "'"
436
- : double >= single && double >= backtick
437
- ? '"'
438
- : '`'
460
+ if (single >= double) {
461
+ return "'"
462
+ }
463
+ return '"'
439
464
  }
@@ -46,5 +46,5 @@ export interface TransformContext {
46
46
  routeId: string
47
47
  lazy: boolean
48
48
  verboseFileRoutes: boolean
49
- preferredQuote?: '"' | "'" | '`'
49
+ preferredQuote?: '"' | "'"
50
50
  }
@@ -5,7 +5,7 @@ const b = types.builders
5
5
  export function ensureStringArgument(
6
6
  callExpression: types.namedTypes.CallExpression,
7
7
  value: string,
8
- preferredQuote?: "'" | '"' | '`',
8
+ preferredQuote?: "'" | '"',
9
9
  ) {
10
10
  const argument = callExpression.arguments[0]
11
11
  if (!argument) {
package/src/types.ts CHANGED
@@ -18,6 +18,7 @@ export type RouteNode = {
18
18
  export interface GetRouteNodesResult {
19
19
  rootRouteNode?: RouteNode
20
20
  routeNodes: Array<RouteNode>
21
+ physicalDirectories: Array<string>
21
22
  }
22
23
 
23
24
  export type FsRouteType =
@@ -54,3 +55,9 @@ export type HandleNodeAccumulator = {
54
55
  routePiecesByPath: Record<string, RouteSubNode>
55
56
  routeNodes: Array<RouteNode>
56
57
  }
58
+
59
+ export type GetRoutesByFileMapResultValue = { routePath: string }
60
+ export type GetRoutesByFileMapResult = Map<
61
+ string,
62
+ GetRoutesByFileMapResultValue
63
+ >
package/src/utils.ts CHANGED
@@ -466,47 +466,61 @@ export function buildRouteTreeConfig(
466
466
  disableTypes: boolean,
467
467
  depth = 1,
468
468
  ): Array<string> {
469
- const children = nodes.map((node) => {
470
- if (node._fsRouteType === '__root') {
471
- return
472
- }
469
+ const children = nodes
470
+ .filter((n) => n.exports?.includes(exportName))
471
+ .map((node) => {
472
+ if (node._fsRouteType === '__root') {
473
+ return
474
+ }
473
475
 
474
- if (node._fsRouteType === 'pathless_layout' && !node.children?.length) {
475
- return
476
- }
476
+ if (node._fsRouteType === 'pathless_layout' && !node.children?.length) {
477
+ return
478
+ }
477
479
 
478
- const route = `${node.variableName}`
480
+ const route = `${node.variableName}`
479
481
 
480
- if (node.children?.length) {
481
- const childConfigs = buildRouteTreeConfig(
482
- node.children,
483
- exportName,
484
- disableTypes,
485
- depth + 1,
486
- )
482
+ if (node.children?.length) {
483
+ const childConfigs = buildRouteTreeConfig(
484
+ node.children,
485
+ exportName,
486
+ disableTypes,
487
+ depth + 1,
488
+ )
487
489
 
488
- const childrenDeclaration = disableTypes
489
- ? ''
490
- : `interface ${route}${exportName}Children {
491
- ${node.children.map((child) => `${child.variableName}${exportName}: typeof ${getResolvedRouteNodeVariableName(child, exportName)}`).join(',')}
490
+ const childrenDeclaration = disableTypes
491
+ ? ''
492
+ : `interface ${route}${exportName}Children {
493
+ ${node.children
494
+ .filter((n) => n.exports?.includes(exportName))
495
+ .map(
496
+ (child) =>
497
+ `${child.variableName}${exportName}: typeof ${getResolvedRouteNodeVariableName(child, exportName)}`,
498
+ )
499
+ .join(',')}
492
500
  }`
493
501
 
494
- const children = `const ${route}${exportName}Children${disableTypes ? '' : `: ${route}${exportName}Children`} = {
495
- ${node.children.map((child) => `${child.variableName}${exportName}: ${getResolvedRouteNodeVariableName(child, exportName)}`).join(',')}
502
+ const children = `const ${route}${exportName}Children${disableTypes ? '' : `: ${route}${exportName}Children`} = {
503
+ ${node.children
504
+ .filter((n) => n.exports?.includes(exportName))
505
+ .map(
506
+ (child) =>
507
+ `${child.variableName}${exportName}: ${getResolvedRouteNodeVariableName(child, exportName)}`,
508
+ )
509
+ .join(',')}
496
510
  }`
497
511
 
498
- const routeWithChildren = `const ${route}${exportName}WithChildren = ${route}${exportName}._addFileChildren(${route}${exportName}Children)`
512
+ const routeWithChildren = `const ${route}${exportName}WithChildren = ${route}${exportName}._addFileChildren(${route}${exportName}Children)`
499
513
 
500
- return [
501
- childConfigs.join('\n'),
502
- childrenDeclaration,
503
- children,
504
- routeWithChildren,
505
- ].join('\n\n')
506
- }
514
+ return [
515
+ childConfigs.join('\n'),
516
+ childrenDeclaration,
517
+ children,
518
+ routeWithChildren,
519
+ ].join('\n\n')
520
+ }
507
521
 
508
- return undefined
509
- })
522
+ return undefined
523
+ })
510
524
 
511
525
  return children.filter((x) => x !== undefined)
512
526
  }
@@ -583,3 +597,37 @@ export const findParent = (
583
597
  }
584
598
  return findParent(node.parent, exportName)
585
599
  }
600
+
601
+ export function buildFileRoutesByPathInterface(opts: {
602
+ routeNodes: Array<RouteNode>
603
+ module: string
604
+ interfaceName: string
605
+ exportName: string
606
+ }): string {
607
+ return `declare module '${opts.module}' {
608
+ interface ${opts.interfaceName} {
609
+ ${opts.routeNodes
610
+ .map((routeNode) => {
611
+ const filePathId = routeNode.routePath
612
+ let preloaderRoute = ''
613
+
614
+ if (routeNode.exports?.includes(opts.exportName)) {
615
+ preloaderRoute = `typeof ${routeNode.variableName}${opts.exportName}Import`
616
+ } else {
617
+ preloaderRoute = 'unknown'
618
+ }
619
+
620
+ const parent = findParent(routeNode, opts.exportName)
621
+
622
+ return `'${filePathId}': {
623
+ id: '${filePathId}'
624
+ path: '${inferPath(routeNode)}'
625
+ fullPath: '${inferFullPath(routeNode)}'
626
+ preLoaderRoute: ${preloaderRoute}
627
+ parentRoute: typeof ${parent}
628
+ }`
629
+ })
630
+ .join('\n')}
631
+ }
632
+ }`
633
+ }