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

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
@@ -3,16 +3,16 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const routerUtils = require("@tanstack/router-utils");
4
4
  const recast = require("recast");
5
5
  const sourceMap = require("source-map");
6
- const utils = require("../utils.cjs");
6
+ const utils$1 = require("../utils.cjs");
7
+ const utils = require("./utils.cjs");
7
8
  const b = recast.types.builders;
8
9
  async function transform({
9
10
  ctx,
10
11
  source,
11
- plugins
12
+ node
12
13
  }) {
13
14
  let appliedChanges = false;
14
15
  let ast;
15
- const foundExports = [];
16
16
  try {
17
17
  ast = recast.parse(source, {
18
18
  sourceFileName: "output.ts",
@@ -35,49 +35,83 @@ async function transform({
35
35
  };
36
36
  }
37
37
  const preferredQuote = detectPreferredQuoteStyle(ast);
38
- const registeredExports = /* @__PURE__ */ new Map();
39
- for (const plugin of plugins ?? []) {
40
- const exportName = plugin.exportName;
41
- if (registeredExports.has(exportName)) {
38
+ let routeExportHandled = false;
39
+ function onExportFound(decl) {
40
+ if (decl.init?.type === "CallExpression") {
41
+ const callExpression = decl.init;
42
+ const firstArgument = callExpression.arguments[0];
43
+ if (firstArgument) {
44
+ if (firstArgument.type === "ObjectExpression") {
45
+ const staticProperties = firstArgument.properties.flatMap((p) => {
46
+ if (p.type === "ObjectProperty" && p.key.type === "Identifier") {
47
+ return p.key.name;
48
+ }
49
+ return [];
50
+ });
51
+ node.createFileRouteProps = new Set(staticProperties);
52
+ }
53
+ }
54
+ let identifier;
55
+ if (callExpression.callee.type === "Identifier") {
56
+ identifier = callExpression.callee;
57
+ if (ctx.verboseFileRoutes) {
58
+ callExpression.callee = b.callExpression(identifier, [
59
+ b.stringLiteral(ctx.routeId)
60
+ ]);
61
+ appliedChanges = true;
62
+ }
63
+ } else if (callExpression.callee.type === "CallExpression" && callExpression.callee.callee.type === "Identifier") {
64
+ identifier = callExpression.callee.callee;
65
+ if (!ctx.verboseFileRoutes) {
66
+ callExpression.callee = identifier;
67
+ appliedChanges = true;
68
+ } else {
69
+ appliedChanges = utils.ensureStringArgument(
70
+ callExpression.callee,
71
+ ctx.routeId,
72
+ ctx.preferredQuote
73
+ );
74
+ }
75
+ }
76
+ if (identifier === void 0) {
77
+ throw new Error(
78
+ `expected identifier to be present in ${ctx.routeId} for export "Route"`
79
+ );
80
+ }
81
+ if (identifier.name === "createFileRoute" && ctx.lazy) {
82
+ identifier.name = "createLazyFileRoute";
83
+ appliedChanges = true;
84
+ } else if (identifier.name === "createLazyFileRoute" && !ctx.lazy) {
85
+ identifier.name = "createFileRoute";
86
+ appliedChanges = true;
87
+ }
88
+ } else {
42
89
  throw new Error(
43
- `Export ${exportName} is already registered by plugin ${registeredExports.get(exportName)?.name}`
90
+ `expected "Route" export to be initialized by a CallExpression`
44
91
  );
45
92
  }
46
- registeredExports.set(exportName, plugin);
47
- }
48
- function onExportFound(decl, exportName, plugin) {
49
- const pluginAppliedChanges = plugin.onExportFound({
50
- decl,
51
- ctx: { ...ctx, preferredQuote }
52
- });
53
- if (pluginAppliedChanges) {
54
- appliedChanges = true;
55
- }
56
- registeredExports.delete(exportName);
57
- foundExports.push(exportName);
93
+ routeExportHandled = true;
58
94
  }
59
95
  const program = ast.program;
60
96
  for (const n of program.body) {
61
- if (registeredExports.size > 0 && n.type === "ExportNamedDeclaration") {
97
+ if (n.type === "ExportNamedDeclaration") {
62
98
  if (n.declaration?.type === "VariableDeclaration") {
63
99
  const decl = n.declaration.declarations[0];
64
100
  if (decl && decl.type === "VariableDeclarator" && decl.id.type === "Identifier") {
65
- const plugin = registeredExports.get(decl.id.name);
66
- if (plugin) {
67
- onExportFound(decl, decl.id.name, plugin);
101
+ if (decl.id.name === "Route") {
102
+ onExportFound(decl);
68
103
  }
69
104
  }
70
105
  } else if (n.declaration === null && n.specifiers) {
71
106
  for (const spec of n.specifiers) {
72
107
  if (typeof spec.exported.name === "string") {
73
- const plugin = registeredExports.get(spec.exported.name);
74
- if (plugin) {
108
+ if (spec.exported.name === "Route") {
75
109
  const variableName = spec.local?.name || spec.exported.name;
76
110
  for (const decl of program.body) {
77
111
  if (decl.type === "VariableDeclaration" && decl.declarations[0]) {
78
112
  const variable = decl.declarations[0];
79
113
  if (variable.type === "VariableDeclarator" && variable.id.type === "Identifier" && variable.id.name === variableName) {
80
- onExportFound(variable, spec.exported.name, plugin);
114
+ onExportFound(variable);
81
115
  break;
82
116
  }
83
117
  }
@@ -87,25 +121,61 @@ async function transform({
87
121
  }
88
122
  }
89
123
  }
124
+ if (routeExportHandled) {
125
+ break;
126
+ }
127
+ }
128
+ if (!routeExportHandled) {
129
+ return {
130
+ result: "no-route-export"
131
+ };
90
132
  }
91
133
  const imports = {
92
134
  required: [],
93
135
  banned: []
94
136
  };
95
- for (const plugin of plugins ?? []) {
96
- const exportName = plugin.exportName;
97
- if (foundExports.includes(exportName)) {
98
- const pluginImports = plugin.imports(ctx);
99
- if (pluginImports.required) {
100
- imports.required.push(...pluginImports.required);
101
- }
102
- if (pluginImports.banned) {
103
- imports.banned.push(...pluginImports.banned);
137
+ const targetModule = `@tanstack/${ctx.target}-router`;
138
+ if (ctx.verboseFileRoutes === false) {
139
+ imports.banned = [
140
+ {
141
+ source: targetModule,
142
+ specifiers: [
143
+ { imported: "createLazyFileRoute" },
144
+ { imported: "createFileRoute" }
145
+ ]
104
146
  }
147
+ ];
148
+ } else {
149
+ if (ctx.lazy) {
150
+ imports.required = [
151
+ {
152
+ source: targetModule,
153
+ specifiers: [{ imported: "createLazyFileRoute" }]
154
+ }
155
+ ];
156
+ imports.banned = [
157
+ {
158
+ source: targetModule,
159
+ specifiers: [{ imported: "createFileRoute" }]
160
+ }
161
+ ];
162
+ } else {
163
+ imports.required = [
164
+ {
165
+ source: targetModule,
166
+ specifiers: [{ imported: "createFileRoute" }]
167
+ }
168
+ ];
169
+ imports.banned = [
170
+ {
171
+ source: targetModule,
172
+ specifiers: [{ imported: "createLazyFileRoute" }]
173
+ }
174
+ ];
105
175
  }
106
176
  }
107
- imports.required = utils.mergeImportDeclarations(imports.required);
108
- imports.banned = utils.mergeImportDeclarations(imports.banned);
177
+ imports.required = utils$1.mergeImportDeclarations(imports.required);
178
+ imports.banned = utils$1.mergeImportDeclarations(imports.banned);
109
179
  const importStatementCandidates = [];
110
180
  const importDeclarationsToRemove = [];
111
181
  for (const n of program.body) {
@@ -229,7 +299,6 @@ async function transform({
229
299
  }
230
300
  if (!appliedChanges) {
231
301
  return {
232
- exports: foundExports,
233
302
  result: "not-modified"
234
303
  };
235
304
  }
@@ -249,7 +318,6 @@ async function transform({
249
318
  }
250
319
  return {
251
320
  result: "modified",
252
- exports: foundExports,
253
321
  output: transformedCode
254
322
  };
255
323
  }
@@ -1 +1 @@
1
- {"version":3,"file":"transform.cjs","sources":["../../../src/transform/transform.ts"],"sourcesContent":["import { parseAst } from '@tanstack/router-utils'\nimport { parse, print, types, visit } from 'recast'\nimport { SourceMapConsumer } from 'source-map'\nimport { mergeImportDeclarations } from '../utils'\nimport type { ImportDeclaration } from '../types'\nimport type { RawSourceMap } from 'source-map'\nimport type {\n TransformOptions,\n TransformPlugin,\n TransformResult,\n} from './types'\n\nconst b = types.builders\n\nexport async function transform({\n ctx,\n source,\n plugins,\n}: TransformOptions): Promise<TransformResult> {\n let appliedChanges = false as boolean\n let ast: types.namedTypes.File\n const foundExports: Array<string> = []\n try {\n ast = parse(source, {\n sourceFileName: 'output.ts',\n parser: {\n parse(code: string) {\n return parseAst({\n code,\n // we need to instruct babel to produce tokens,\n // otherwise recast will try to generate the tokens via its own parser and will fail\n tokens: true,\n })\n },\n },\n })\n } catch (e) {\n console.error('Error parsing code', ctx.routeId, source, e)\n return {\n result: 'error',\n error: e,\n }\n }\n\n const preferredQuote = detectPreferredQuoteStyle(ast)\n\n const registeredExports = new Map</* export name */ string, TransformPlugin>()\n\n for (const plugin of plugins ?? []) {\n const exportName = plugin.exportName\n if (registeredExports.has(exportName)) {\n throw new Error(\n `Export ${exportName} is already registered by plugin ${registeredExports.get(exportName)?.name}`,\n )\n }\n registeredExports.set(exportName, plugin)\n }\n\n function onExportFound(\n decl: types.namedTypes.VariableDeclarator,\n exportName: string,\n plugin: TransformPlugin,\n ) {\n const pluginAppliedChanges = plugin.onExportFound({\n decl,\n ctx: { ...ctx, preferredQuote },\n })\n if (pluginAppliedChanges) {\n appliedChanges = true\n }\n\n // export is handled, remove it from the registered exports\n registeredExports.delete(exportName)\n // store the export so we can later return it once the file is transformed\n foundExports.push(exportName)\n }\n\n const program: types.namedTypes.Program = ast.program\n // first pass: find registered exports\n for (const n of program.body) {\n if (registeredExports.size > 0 && n.type === 'ExportNamedDeclaration') {\n // direct export of a variable declaration, e.g. `export const Route = createFileRoute('/path')`\n if (n.declaration?.type === 'VariableDeclaration') {\n const decl = n.declaration.declarations[0]\n if (\n decl &&\n decl.type === 'VariableDeclarator' &&\n decl.id.type === 'Identifier'\n ) {\n const plugin = registeredExports.get(decl.id.name)\n if (plugin) {\n onExportFound(decl, decl.id.name, plugin)\n }\n }\n }\n // this is an export without a declaration, e.g. `export { Route }`\n else if (n.declaration === null && n.specifiers) {\n for (const spec of n.specifiers) {\n if (typeof spec.exported.name === 'string') {\n const plugin = registeredExports.get(spec.exported.name)\n if (plugin) {\n const variableName = spec.local?.name || spec.exported.name\n // find the matching variable declaration by iterating over the top-level declarations\n for (const decl of program.body) {\n if (\n decl.type === 'VariableDeclaration' &&\n decl.declarations[0]\n ) {\n const variable = decl.declarations[0]\n if (\n variable.type === 'VariableDeclarator' &&\n variable.id.type === 'Identifier' &&\n variable.id.name === variableName\n ) {\n onExportFound(variable, spec.exported.name, plugin)\n break\n }\n }\n }\n }\n }\n }\n }\n }\n }\n\n const imports: {\n required: Array<ImportDeclaration>\n banned: Array<ImportDeclaration>\n } = {\n required: [],\n banned: [],\n }\n\n for (const plugin of plugins ?? []) {\n const exportName = plugin.exportName\n if (foundExports.includes(exportName)) {\n const pluginImports = plugin.imports(ctx)\n if (pluginImports.required) {\n imports.required.push(...pluginImports.required)\n }\n if (pluginImports.banned) {\n imports.banned.push(...pluginImports.banned)\n }\n }\n }\n\n imports.required = mergeImportDeclarations(imports.required)\n imports.banned = mergeImportDeclarations(imports.banned)\n\n const importStatementCandidates: Array<types.namedTypes.ImportDeclaration> =\n []\n const importDeclarationsToRemove: Array<types.namedTypes.ImportDeclaration> =\n []\n\n // second pass: apply import rules, but only if a matching export for the plugin was found\n for (const n of program.body) {\n const findImport =\n (opts: { source: string; importKind?: 'type' | 'value' | 'typeof' }) =>\n (i: ImportDeclaration) => {\n if (i.source === opts.source) {\n const importKind = i.importKind || 'value'\n const expectedImportKind = opts.importKind || 'value'\n return expectedImportKind === importKind\n }\n return false\n }\n if (n.type === 'ImportDeclaration' && typeof n.source.value === 'string') {\n const filterImport = findImport({\n source: n.source.value,\n importKind: n.importKind,\n })\n let requiredImports = imports.required.filter(filterImport)[0]\n\n const bannedImports = imports.banned.filter(filterImport)[0]\n if (!requiredImports && !bannedImports) {\n continue\n }\n const importSpecifiersToRemove: types.namedTypes.ImportDeclaration['specifiers'] =\n []\n if (n.specifiers) {\n for (const spec of n.specifiers) {\n if (!requiredImports && !bannedImports) {\n break\n }\n if (\n spec.type === 'ImportSpecifier' &&\n typeof spec.imported.name === 'string'\n ) {\n if (requiredImports) {\n const requiredImportIndex = requiredImports.specifiers.findIndex(\n (imp) => imp.imported === spec.imported.name,\n )\n if (requiredImportIndex !== -1) {\n // import is already present, remove it from requiredImports\n requiredImports.specifiers.splice(requiredImportIndex, 1)\n if (requiredImports.specifiers.length === 0) {\n imports.required = imports.required.splice(\n imports.required.indexOf(requiredImports),\n 1,\n )\n requiredImports = undefined\n }\n } else {\n // add the import statement to the candidates\n importStatementCandidates.push(n)\n }\n }\n if (bannedImports) {\n const bannedImportIndex = bannedImports.specifiers.findIndex(\n (imp) => imp.imported === spec.imported.name,\n )\n if (bannedImportIndex !== -1) {\n importSpecifiersToRemove.push(spec)\n }\n }\n }\n }\n if (importSpecifiersToRemove.length > 0) {\n appliedChanges = true\n n.specifiers = n.specifiers.filter(\n (spec) => !importSpecifiersToRemove.includes(spec),\n )\n\n // mark the import statement as to be deleted if it is now empty\n if (n.specifiers.length === 0) {\n importDeclarationsToRemove.push(n)\n }\n }\n }\n }\n }\n imports.required.forEach((requiredImport) => {\n if (requiredImport.specifiers.length > 0) {\n appliedChanges = true\n if (importStatementCandidates.length > 0) {\n // find the first import statement that matches both the module and the import kind\n const importStatement = importStatementCandidates.find(\n (importStatement) => {\n if (importStatement.source.value === requiredImport.source) {\n const importKind = importStatement.importKind || 'value'\n const requiredImportKind = requiredImport.importKind || 'value'\n return importKind === requiredImportKind\n }\n return false\n },\n )\n if (importStatement) {\n if (importStatement.specifiers === undefined) {\n importStatement.specifiers = []\n }\n const importSpecifiersToAdd = requiredImport.specifiers.map((spec) =>\n b.importSpecifier(\n b.identifier(spec.imported),\n b.identifier(spec.imported),\n ),\n )\n importStatement.specifiers = [\n ...importStatement.specifiers,\n ...importSpecifiersToAdd,\n ]\n return\n }\n }\n const importStatement = b.importDeclaration(\n requiredImport.specifiers.map((spec) =>\n b.importSpecifier(\n b.identifier(spec.imported),\n spec.local ? b.identifier(spec.local) : null,\n ),\n ),\n b.stringLiteral(requiredImport.source),\n )\n program.body.unshift(importStatement)\n }\n })\n if (importDeclarationsToRemove.length > 0) {\n appliedChanges = true\n for (const importDeclaration of importDeclarationsToRemove) {\n // check if the import declaration is still empty\n if (importDeclaration.specifiers?.length === 0) {\n const index = program.body.indexOf(importDeclaration)\n if (index !== -1) {\n program.body.splice(index, 1)\n }\n }\n }\n }\n\n if (!appliedChanges) {\n return {\n exports: foundExports,\n result: 'not-modified',\n }\n }\n\n const printResult = print(ast, {\n reuseWhitespace: true,\n sourceMapName: 'output.map',\n })\n let transformedCode = printResult.code\n if (printResult.map) {\n const fixedOutput = await fixTransformedOutputText({\n originalCode: source,\n transformedCode,\n sourceMap: printResult.map as RawSourceMap,\n preferredQuote,\n })\n transformedCode = fixedOutput\n }\n return {\n result: 'modified',\n exports: foundExports,\n output: transformedCode,\n }\n}\n\nasync function fixTransformedOutputText({\n originalCode,\n transformedCode,\n sourceMap,\n preferredQuote,\n}: {\n originalCode: string\n transformedCode: string\n sourceMap: RawSourceMap\n preferredQuote: '\"' | \"'\"\n}) {\n const originalLines = originalCode.split('\\n')\n const transformedLines = transformedCode.split('\\n')\n\n const defaultUsesSemicolons = detectSemicolonUsage(originalCode)\n\n const consumer = await new SourceMapConsumer(sourceMap)\n\n const fixedLines = transformedLines.map((line, i) => {\n const transformedLineNum = i + 1\n\n let origLineText: string | undefined = undefined\n\n for (let col = 0; col < line.length; col++) {\n const mapped = consumer.originalPositionFor({\n line: transformedLineNum,\n column: col,\n })\n if (mapped.line != null && mapped.line > 0) {\n origLineText = originalLines[mapped.line - 1]\n break\n }\n }\n\n if (origLineText !== undefined) {\n if (origLineText === line) {\n return origLineText\n }\n return fixLine(line, {\n originalLine: origLineText,\n useOriginalSemicolon: true,\n useOriginalQuotes: true,\n fallbackQuote: preferredQuote,\n })\n } else {\n return fixLine(line, {\n originalLine: null,\n useOriginalSemicolon: false,\n useOriginalQuotes: false,\n fallbackQuote: preferredQuote,\n fallbackSemicolon: defaultUsesSemicolons,\n })\n }\n })\n\n return fixedLines.join('\\n')\n}\n\nfunction fixLine(\n line: string,\n {\n originalLine,\n useOriginalSemicolon,\n useOriginalQuotes,\n fallbackQuote,\n fallbackSemicolon = true,\n }: {\n originalLine: string | null\n useOriginalSemicolon: boolean\n useOriginalQuotes: boolean\n fallbackQuote: string\n fallbackSemicolon?: boolean\n },\n) {\n let result = line\n\n if (useOriginalQuotes && originalLine) {\n result = fixQuotes(result, originalLine, fallbackQuote)\n } else if (!useOriginalQuotes && fallbackQuote) {\n result = fixQuotesToPreferred(result, fallbackQuote)\n }\n\n if (useOriginalSemicolon && originalLine) {\n const hadSemicolon = originalLine.trimEnd().endsWith(';')\n const hasSemicolon = result.trimEnd().endsWith(';')\n if (hadSemicolon && !hasSemicolon) result += ';'\n if (!hadSemicolon && hasSemicolon) result = result.replace(/;\\s*$/, '')\n } else if (!useOriginalSemicolon) {\n const hasSemicolon = result.trimEnd().endsWith(';')\n if (!fallbackSemicolon && hasSemicolon) result = result.replace(/;\\s*$/, '')\n if (fallbackSemicolon && !hasSemicolon && result.trim()) result += ';'\n }\n\n return result\n}\n\nfunction fixQuotes(line: string, originalLine: string, fallbackQuote: string) {\n let originalQuote = detectQuoteFromLine(originalLine)\n if (!originalQuote) {\n originalQuote = fallbackQuote\n }\n return fixQuotesToPreferred(line, originalQuote)\n}\n\nfunction fixQuotesToPreferred(line: string, quote: string) {\n // Replace existing quotes with preferred quote\n return line.replace(\n /(['\"`])([^'\"`\\\\]*(?:\\\\.[^'\"`\\\\]*)*)\\1/g,\n (_, q, content) => {\n const escaped = content.replaceAll(quote, `\\\\${quote}`)\n return `${quote}${escaped}${quote}`\n },\n )\n}\n\nfunction detectQuoteFromLine(line: string) {\n const match = line.match(/(['\"`])(?:\\\\.|[^\\\\])*?\\1/)\n return match ? match[1] : null\n}\n\nfunction detectSemicolonUsage(code: string) {\n const lines = code.split('\\n').map((l) => l.trim())\n const total = lines.length\n const withSemis = lines.filter((l) => l.endsWith(';')).length\n return withSemis > total / 2\n}\n\nexport function detectPreferredQuoteStyle(ast: types.ASTNode): \"'\" | '\"' {\n let single = 0\n let double = 0\n\n visit(ast, {\n visitStringLiteral(path) {\n if (path.parent.node.type !== 'JSXAttribute') {\n const raw = path.node.extra?.raw\n if (raw?.startsWith(\"'\")) single++\n else if (raw?.startsWith('\"')) double++\n }\n return false\n },\n })\n\n if (single >= double) {\n return \"'\"\n }\n return '\"'\n}\n"],"names":["types","parse","parseAst","mergeImportDeclarations","importStatement","print","sourceMap","SourceMapConsumer","visit"],"mappings":"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"}
1
+ {"version":3,"file":"transform.cjs","sources":["../../../src/transform/transform.ts"],"sourcesContent":["import { parseAst } from '@tanstack/router-utils'\nimport { parse, print, types, visit } from 'recast'\nimport { SourceMapConsumer } from 'source-map'\nimport { mergeImportDeclarations } from '../utils'\nimport { ensureStringArgument } from './utils'\nimport type { ImportDeclaration } from '../types'\nimport type { RawSourceMap } from 'source-map'\nimport type { TransformOptions, TransformResult } from './types'\n\nconst b = types.builders\n\nexport async function transform({\n ctx,\n source,\n node,\n}: TransformOptions): Promise<TransformResult> {\n let appliedChanges = false as boolean\n let ast: types.namedTypes.File\n try {\n ast = parse(source, {\n sourceFileName: 'output.ts',\n parser: {\n parse(code: string) {\n return parseAst({\n code,\n // we need to instruct babel to produce tokens,\n // otherwise recast will try to generate the tokens via its own parser and will fail\n tokens: true,\n })\n },\n },\n })\n } catch (e) {\n console.error('Error parsing code', ctx.routeId, source, e)\n return {\n result: 'error',\n error: e,\n }\n }\n\n const preferredQuote = detectPreferredQuoteStyle(ast)\n\n let routeExportHandled = false as boolean\n function onExportFound(decl: types.namedTypes.VariableDeclarator) {\n if (decl.init?.type === 'CallExpression') {\n const callExpression = decl.init\n const firstArgument = callExpression.arguments[0]\n if (firstArgument) {\n if (firstArgument.type === 'ObjectExpression') {\n const staticProperties = firstArgument.properties.flatMap((p) => {\n if (p.type === 'ObjectProperty' && p.key.type === 'Identifier') {\n return p.key.name\n }\n return []\n })\n node.createFileRouteProps = new Set(staticProperties)\n }\n }\n let identifier: types.namedTypes.Identifier | undefined\n // `const Route = createFileRoute({ ... })`\n if (callExpression.callee.type === 'Identifier') {\n identifier = callExpression.callee\n if (ctx.verboseFileRoutes) {\n // we need to add the string literal via another CallExpression\n callExpression.callee = b.callExpression(identifier, [\n b.stringLiteral(ctx.routeId),\n ])\n appliedChanges = true\n }\n }\n // `const Route = createFileRoute('/path')({ ... })`\n else if (\n callExpression.callee.type === 'CallExpression' &&\n callExpression.callee.callee.type === 'Identifier'\n ) {\n identifier = callExpression.callee.callee\n if (!ctx.verboseFileRoutes) {\n // we need to remove the route id\n callExpression.callee = identifier\n appliedChanges = true\n } else {\n // check if the route id is correct\n appliedChanges = ensureStringArgument(\n callExpression.callee,\n ctx.routeId,\n ctx.preferredQuote,\n )\n }\n }\n if (identifier === undefined) {\n throw new Error(\n `expected identifier to be present in ${ctx.routeId} for export \"Route\"`,\n )\n }\n if (identifier.name === 'createFileRoute' && ctx.lazy) {\n identifier.name = 'createLazyFileRoute'\n appliedChanges = true\n } else if (identifier.name === 'createLazyFileRoute' && !ctx.lazy) {\n identifier.name = 'createFileRoute'\n appliedChanges = true\n }\n } else {\n throw new Error(\n `expected \"Route\" export to be initialized by a CallExpression`,\n )\n }\n routeExportHandled = true\n }\n\n const program: types.namedTypes.Program = ast.program\n // first pass: find Route export\n for (const n of program.body) {\n if (n.type === 'ExportNamedDeclaration') {\n // direct export of a variable declaration, e.g. `export const Route = createFileRoute('/path')`\n if (n.declaration?.type === 'VariableDeclaration') {\n const decl = n.declaration.declarations[0]\n if (\n decl &&\n decl.type === 'VariableDeclarator' &&\n decl.id.type === 'Identifier'\n ) {\n if (decl.id.name === 'Route') {\n onExportFound(decl)\n }\n }\n }\n // this is an export without a declaration, e.g. `export { Route }`\n else if (n.declaration === null && n.specifiers) {\n for (const spec of n.specifiers) {\n if (typeof spec.exported.name === 'string') {\n if (spec.exported.name === 'Route') {\n const variableName = spec.local?.name || spec.exported.name\n // find the matching variable declaration by iterating over the top-level declarations\n for (const decl of program.body) {\n if (\n decl.type === 'VariableDeclaration' &&\n decl.declarations[0]\n ) {\n const variable = decl.declarations[0]\n if (\n variable.type === 'VariableDeclarator' &&\n variable.id.type === 'Identifier' &&\n variable.id.name === variableName\n ) {\n onExportFound(variable)\n break\n }\n }\n }\n }\n }\n }\n }\n }\n if (routeExportHandled) {\n break\n }\n }\n\n if (!routeExportHandled) {\n return {\n result: 'no-route-export',\n }\n }\n\n const imports: {\n required: Array<ImportDeclaration>\n banned: Array<ImportDeclaration>\n } = {\n required: [],\n banned: [],\n }\n\n const targetModule = `@tanstack/${ctx.target}-router`\n if (ctx.verboseFileRoutes === false) {\n imports.banned = [\n {\n source: targetModule,\n specifiers: [\n { imported: 'createLazyFileRoute' },\n { imported: 'createFileRoute' },\n ],\n },\n ]\n } else {\n if (ctx.lazy) {\n imports.required = [\n {\n source: targetModule,\n specifiers: [{ imported: 'createLazyFileRoute' }],\n },\n ]\n imports.banned = [\n {\n source: targetModule,\n specifiers: [{ imported: 'createFileRoute' }],\n },\n ]\n } else {\n imports.required = [\n {\n source: targetModule,\n specifiers: [{ imported: 'createFileRoute' }],\n },\n ]\n imports.banned = [\n {\n source: targetModule,\n specifiers: [{ imported: 'createLazyFileRoute' }],\n },\n ]\n }\n }\n\n imports.required = mergeImportDeclarations(imports.required)\n imports.banned = mergeImportDeclarations(imports.banned)\n\n const importStatementCandidates: Array<types.namedTypes.ImportDeclaration> =\n []\n const importDeclarationsToRemove: Array<types.namedTypes.ImportDeclaration> =\n []\n\n // second pass: apply import rules, but only if a matching export for the plugin was found\n for (const n of program.body) {\n const findImport =\n (opts: { source: string; importKind?: 'type' | 'value' | 'typeof' }) =>\n (i: ImportDeclaration) => {\n if (i.source === opts.source) {\n const importKind = i.importKind || 'value'\n const expectedImportKind = opts.importKind || 'value'\n return expectedImportKind === importKind\n }\n return false\n }\n if (n.type === 'ImportDeclaration' && typeof n.source.value === 'string') {\n const filterImport = findImport({\n source: n.source.value,\n importKind: n.importKind,\n })\n let requiredImports = imports.required.filter(filterImport)[0]\n\n const bannedImports = imports.banned.filter(filterImport)[0]\n if (!requiredImports && !bannedImports) {\n continue\n }\n const importSpecifiersToRemove: types.namedTypes.ImportDeclaration['specifiers'] =\n []\n if (n.specifiers) {\n for (const spec of n.specifiers) {\n if (!requiredImports && !bannedImports) {\n break\n }\n if (\n spec.type === 'ImportSpecifier' &&\n typeof spec.imported.name === 'string'\n ) {\n if (requiredImports) {\n const requiredImportIndex = requiredImports.specifiers.findIndex(\n (imp) => imp.imported === spec.imported.name,\n )\n if (requiredImportIndex !== -1) {\n // import is already present, remove it from requiredImports\n requiredImports.specifiers.splice(requiredImportIndex, 1)\n if (requiredImports.specifiers.length === 0) {\n imports.required = imports.required.splice(\n imports.required.indexOf(requiredImports),\n 1,\n )\n requiredImports = undefined\n }\n } else {\n // add the import statement to the candidates\n importStatementCandidates.push(n)\n }\n }\n if (bannedImports) {\n const bannedImportIndex = bannedImports.specifiers.findIndex(\n (imp) => imp.imported === spec.imported.name,\n )\n if (bannedImportIndex !== -1) {\n importSpecifiersToRemove.push(spec)\n }\n }\n }\n }\n if (importSpecifiersToRemove.length > 0) {\n appliedChanges = true\n n.specifiers = n.specifiers.filter(\n (spec) => !importSpecifiersToRemove.includes(spec),\n )\n\n // mark the import statement as to be deleted if it is now empty\n if (n.specifiers.length === 0) {\n importDeclarationsToRemove.push(n)\n }\n }\n }\n }\n }\n imports.required.forEach((requiredImport) => {\n if (requiredImport.specifiers.length > 0) {\n appliedChanges = true\n if (importStatementCandidates.length > 0) {\n // find the first import statement that matches both the module and the import kind\n const importStatement = importStatementCandidates.find(\n (importStatement) => {\n if (importStatement.source.value === requiredImport.source) {\n const importKind = importStatement.importKind || 'value'\n const requiredImportKind = requiredImport.importKind || 'value'\n return importKind === requiredImportKind\n }\n return false\n },\n )\n if (importStatement) {\n if (importStatement.specifiers === undefined) {\n importStatement.specifiers = []\n }\n const importSpecifiersToAdd = requiredImport.specifiers.map((spec) =>\n b.importSpecifier(\n b.identifier(spec.imported),\n b.identifier(spec.imported),\n ),\n )\n importStatement.specifiers = [\n ...importStatement.specifiers,\n ...importSpecifiersToAdd,\n ]\n return\n }\n }\n const importStatement = b.importDeclaration(\n requiredImport.specifiers.map((spec) =>\n b.importSpecifier(\n b.identifier(spec.imported),\n spec.local ? b.identifier(spec.local) : null,\n ),\n ),\n b.stringLiteral(requiredImport.source),\n )\n program.body.unshift(importStatement)\n }\n })\n if (importDeclarationsToRemove.length > 0) {\n appliedChanges = true\n for (const importDeclaration of importDeclarationsToRemove) {\n // check if the import declaration is still empty\n if (importDeclaration.specifiers?.length === 0) {\n const index = program.body.indexOf(importDeclaration)\n if (index !== -1) {\n program.body.splice(index, 1)\n }\n }\n }\n }\n\n if (!appliedChanges) {\n return {\n result: 'not-modified',\n }\n }\n\n const printResult = print(ast, {\n reuseWhitespace: true,\n sourceMapName: 'output.map',\n })\n let transformedCode = printResult.code\n if (printResult.map) {\n const fixedOutput = await fixTransformedOutputText({\n originalCode: source,\n transformedCode,\n sourceMap: printResult.map as RawSourceMap,\n preferredQuote,\n })\n transformedCode = fixedOutput\n }\n return {\n result: 'modified',\n output: transformedCode,\n }\n}\n\nasync function fixTransformedOutputText({\n originalCode,\n transformedCode,\n sourceMap,\n preferredQuote,\n}: {\n originalCode: string\n transformedCode: string\n sourceMap: RawSourceMap\n preferredQuote: '\"' | \"'\"\n}) {\n const originalLines = originalCode.split('\\n')\n const transformedLines = transformedCode.split('\\n')\n\n const defaultUsesSemicolons = detectSemicolonUsage(originalCode)\n\n const consumer = await new SourceMapConsumer(sourceMap)\n\n const fixedLines = transformedLines.map((line, i) => {\n const transformedLineNum = i + 1\n\n let origLineText: string | undefined = undefined\n\n for (let col = 0; col < line.length; col++) {\n const mapped = consumer.originalPositionFor({\n line: transformedLineNum,\n column: col,\n })\n if (mapped.line != null && mapped.line > 0) {\n origLineText = originalLines[mapped.line - 1]\n break\n }\n }\n\n if (origLineText !== undefined) {\n if (origLineText === line) {\n return origLineText\n }\n return fixLine(line, {\n originalLine: origLineText,\n useOriginalSemicolon: true,\n useOriginalQuotes: true,\n fallbackQuote: preferredQuote,\n })\n } else {\n return fixLine(line, {\n originalLine: null,\n useOriginalSemicolon: false,\n useOriginalQuotes: false,\n fallbackQuote: preferredQuote,\n fallbackSemicolon: defaultUsesSemicolons,\n })\n }\n })\n\n return fixedLines.join('\\n')\n}\n\nfunction fixLine(\n line: string,\n {\n originalLine,\n useOriginalSemicolon,\n useOriginalQuotes,\n fallbackQuote,\n fallbackSemicolon = true,\n }: {\n originalLine: string | null\n useOriginalSemicolon: boolean\n useOriginalQuotes: boolean\n fallbackQuote: string\n fallbackSemicolon?: boolean\n },\n) {\n let result = line\n\n if (useOriginalQuotes && originalLine) {\n result = fixQuotes(result, originalLine, fallbackQuote)\n } else if (!useOriginalQuotes && fallbackQuote) {\n result = fixQuotesToPreferred(result, fallbackQuote)\n }\n\n if (useOriginalSemicolon && originalLine) {\n const hadSemicolon = originalLine.trimEnd().endsWith(';')\n const hasSemicolon = result.trimEnd().endsWith(';')\n if (hadSemicolon && !hasSemicolon) result += ';'\n if (!hadSemicolon && hasSemicolon) result = result.replace(/;\\s*$/, '')\n } else if (!useOriginalSemicolon) {\n const hasSemicolon = result.trimEnd().endsWith(';')\n if (!fallbackSemicolon && hasSemicolon) result = result.replace(/;\\s*$/, '')\n if (fallbackSemicolon && !hasSemicolon && result.trim()) result += ';'\n }\n\n return result\n}\n\nfunction fixQuotes(line: string, originalLine: string, fallbackQuote: string) {\n let originalQuote = detectQuoteFromLine(originalLine)\n if (!originalQuote) {\n originalQuote = fallbackQuote\n }\n return fixQuotesToPreferred(line, originalQuote)\n}\n\nfunction fixQuotesToPreferred(line: string, quote: string) {\n // Replace existing quotes with preferred quote\n return line.replace(\n /(['\"`])([^'\"`\\\\]*(?:\\\\.[^'\"`\\\\]*)*)\\1/g,\n (_, q, content) => {\n const escaped = content.replaceAll(quote, `\\\\${quote}`)\n return `${quote}${escaped}${quote}`\n },\n )\n}\n\nfunction detectQuoteFromLine(line: string) {\n const match = line.match(/(['\"`])(?:\\\\.|[^\\\\])*?\\1/)\n return match ? match[1] : null\n}\n\nfunction detectSemicolonUsage(code: string) {\n const lines = code.split('\\n').map((l) => l.trim())\n const total = lines.length\n const withSemis = lines.filter((l) => l.endsWith(';')).length\n return withSemis > total / 2\n}\n\nexport function detectPreferredQuoteStyle(ast: types.ASTNode): \"'\" | '\"' {\n let single = 0\n let double = 0\n\n visit(ast, {\n visitStringLiteral(path) {\n if (path.parent.node.type !== 'JSXAttribute') {\n const raw = path.node.extra?.raw\n if (raw?.startsWith(\"'\")) single++\n else if (raw?.startsWith('\"')) double++\n }\n return false\n },\n })\n\n if (single >= double) {\n return \"'\"\n }\n return '\"'\n}\n"],"names":["types","parse","parseAst","ensureStringArgument","mergeImportDeclarations","importStatement","print","sourceMap","SourceMapConsumer","visit"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import { types } from 'recast';
2
2
  import { TransformOptions, TransformResult } from './types.cjs';
3
- export declare function transform({ ctx, source, plugins, }: TransformOptions): Promise<TransformResult>;
3
+ export declare function transform({ ctx, source, node, }: TransformOptions): Promise<TransformResult>;
4
4
  export declare function detectPreferredQuoteStyle(ast: types.ASTNode): "'" | '"';
@@ -1,18 +1,17 @@
1
- import { ImportDeclaration } from '../types.cjs';
2
- import { types } from 'recast';
1
+ import { ImportDeclaration, RouteNode } from '../types.cjs';
3
2
  import { Config } from '../config.cjs';
4
3
  export interface TransformOptions {
5
4
  source: string;
6
5
  ctx: TransformContext;
7
- plugins?: Array<TransformPlugin>;
6
+ node: RouteNode;
8
7
  }
9
8
  export type TransformResult = {
9
+ result: 'no-route-export';
10
+ } | {
10
11
  result: 'not-modified';
11
- exports: Array<string>;
12
12
  } | {
13
13
  result: 'modified';
14
14
  output: string;
15
- exports: Array<string>;
16
15
  } | {
17
16
  result: 'error';
18
17
  error?: any;
@@ -21,19 +20,6 @@ export interface TransformImportsConfig {
21
20
  banned?: Array<ImportDeclaration>;
22
21
  required?: Array<ImportDeclaration>;
23
22
  }
24
- export interface TransformPlugin {
25
- name: string;
26
- exportName: string;
27
- imports: (ctx: TransformContext) => TransformImportsConfig;
28
- /**
29
- * Called after the export is found in the AST.
30
- * @returns true if the plugin modified the AST, false otherwise
31
- */
32
- onExportFound: (opts: {
33
- decl: types.namedTypes.VariableDeclarator;
34
- ctx: TransformContext;
35
- }) => boolean;
36
- }
37
23
  export interface TransformContext {
38
24
  target: Config['target'];
39
25
  routeId: string;
@@ -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
  export interface GetRouteNodesResult {
18
18
  rootRouteNode?: RouteNode;
@@ -196,8 +196,8 @@ function hasParentRoute(routes, node, routePathToCheck) {
196
196
  const parentRoutePath = segments.join("/");
197
197
  return hasParentRoute(routes, node, parentRoutePath);
198
198
  }
199
- const getResolvedRouteNodeVariableName = (routeNode, variableNameSuffix) => {
200
- return routeNode.children?.length ? `${routeNode.variableName}${variableNameSuffix}WithChildren` : `${routeNode.variableName}${variableNameSuffix}`;
199
+ const getResolvedRouteNodeVariableName = (routeNode) => {
200
+ return routeNode.children?.length ? `${routeNode.variableName}RouteWithChildren` : `${routeNode.variableName}Route`;
201
201
  };
202
202
  function isRouteNodeValidForAugmentation(routeNode) {
203
203
  if (!routeNode || routeNode.isVirtual) {
@@ -273,8 +273,8 @@ Conflicting files:
273
273
  throw new Error(errorMessage);
274
274
  }
275
275
  }
276
- function buildRouteTreeConfig(nodes, exportName, disableTypes, depth = 1) {
277
- const children = nodes.filter((n) => n.exports?.includes(exportName)).map((node) => {
276
+ function buildRouteTreeConfig(nodes, disableTypes, depth = 1) {
277
+ const children = nodes.map((node) => {
278
278
  if (node._fsRouteType === "__root") {
279
279
  return;
280
280
  }
@@ -285,21 +285,20 @@ function buildRouteTreeConfig(nodes, exportName, disableTypes, depth = 1) {
285
285
  if (node.children?.length) {
286
286
  const childConfigs = buildRouteTreeConfig(
287
287
  node.children,
288
- exportName,
289
288
  disableTypes,
290
289
  depth + 1
291
290
  );
292
- const childrenDeclaration = disableTypes ? "" : `interface ${route}${exportName}Children {
293
- ${node.children.filter((n) => n.exports?.includes(exportName)).map(
294
- (child) => `${child.variableName}${exportName}: typeof ${getResolvedRouteNodeVariableName(child, exportName)}`
291
+ const childrenDeclaration = disableTypes ? "" : `interface ${route}RouteChildren {
292
+ ${node.children.map(
293
+ (child) => `${child.variableName}Route: typeof ${getResolvedRouteNodeVariableName(child)}`
295
294
  ).join(",")}
296
295
  }`;
297
- const children2 = `const ${route}${exportName}Children${disableTypes ? "" : `: ${route}${exportName}Children`} = {
298
- ${node.children.filter((n) => n.exports?.includes(exportName)).map(
299
- (child) => `${child.variableName}${exportName}: ${getResolvedRouteNodeVariableName(child, exportName)}`
296
+ const children2 = `const ${route}RouteChildren${disableTypes ? "" : `: ${route}RouteChildren`} = {
297
+ ${node.children.map(
298
+ (child) => `${child.variableName}Route: ${getResolvedRouteNodeVariableName(child)}`
300
299
  ).join(",")}
301
300
  }`;
302
- const routeWithChildren = `const ${route}${exportName}WithChildren = ${route}${exportName}._addFileChildren(${route}${exportName}Children)`;
301
+ const routeWithChildren = `const ${route}RouteWithChildren = ${route}Route._addFileChildren(${route}RouteChildren)`;
303
302
  return [
304
303
  childConfigs.join("\n"),
305
304
  childrenDeclaration,
@@ -315,12 +314,6 @@ function buildImportString(importDeclaration) {
315
314
  const { source, specifiers, importKind } = importDeclaration;
316
315
  return specifiers.length ? `import ${importKind === "type" ? "type " : ""}{ ${specifiers.map((s) => s.local ? `${s.imported} as ${s.local}` : s.imported).join(", ")} } from '${source}'` : "";
317
316
  }
318
- function lowerCaseFirstChar(value) {
319
- if (!value[0]) {
320
- return value;
321
- }
322
- return value[0].toLowerCase() + value.slice(1);
323
- }
324
317
  function mergeImportDeclarations(imports) {
325
318
  const merged = {};
326
319
  for (const imp of imports) {
@@ -338,36 +331,26 @@ function mergeImportDeclarations(imports) {
338
331
  }
339
332
  return Object.values(merged);
340
333
  }
341
- function hasChildWithExport(node, exportName) {
342
- return node.children?.some((child) => hasChildWithExport(child)) ?? false;
343
- }
344
- const findParent = (node, exportName) => {
334
+ const findParent = (node) => {
345
335
  if (!node) {
346
- return `root${exportName}Import`;
336
+ return `rootRouteImport`;
347
337
  }
348
338
  if (node.parent) {
349
- if (node.parent.exports?.includes(exportName)) {
350
- if (node.isVirtualParentRequired) {
351
- return `${node.parent.variableName}${exportName}`;
352
- } else {
353
- return `${node.parent.variableName}${exportName}`;
354
- }
339
+ if (node.isVirtualParentRequired) {
340
+ return `${node.parent.variableName}Route`;
341
+ } else {
342
+ return `${node.parent.variableName}Route`;
355
343
  }
356
344
  }
357
- return findParent(node.parent, exportName);
345
+ return findParent(node.parent);
358
346
  };
359
347
  function buildFileRoutesByPathInterface(opts) {
360
348
  return `declare module '${opts.module}' {
361
349
  interface ${opts.interfaceName} {
362
350
  ${opts.routeNodes.map((routeNode) => {
363
351
  const filePathId = routeNode.routePath;
364
- let preloaderRoute = "";
365
- if (routeNode.exports?.includes(opts.exportName)) {
366
- preloaderRoute = `typeof ${routeNode.variableName}${opts.exportName}Import`;
367
- } else {
368
- preloaderRoute = "unknown";
369
- }
370
- const parent = findParent(routeNode, opts.exportName);
352
+ const preloaderRoute = `typeof ${routeNode.variableName}RouteImport`;
353
+ const parent = findParent(routeNode);
371
354
  return `'${filePathId}': {
372
355
  id: '${filePathId}'
373
356
  path: '${inferPath(routeNode)}'
@@ -379,6 +362,39 @@ function buildFileRoutesByPathInterface(opts) {
379
362
  }
380
363
  }`;
381
364
  }
365
+ function getImportPath(node, config, generatedRouteTreePath) {
366
+ return replaceBackslash(
367
+ removeExt(
368
+ path.relative(
369
+ path.dirname(generatedRouteTreePath),
370
+ path.resolve(config.routesDirectory, node.filePath)
371
+ ),
372
+ config.addExtensions
373
+ )
374
+ );
375
+ }
376
+ function getImportForRouteNode(node, config, generatedRouteTreePath, root) {
377
+ let source = "";
378
+ if (config.importRoutesUsingAbsolutePaths) {
379
+ source = replaceBackslash(
380
+ removeExt(
381
+ path.resolve(root, config.routesDirectory, node.filePath),
382
+ config.addExtensions
383
+ )
384
+ );
385
+ } else {
386
+ source = `./${getImportPath(node, config, generatedRouteTreePath)}`;
387
+ }
388
+ return {
389
+ source,
390
+ specifiers: [
391
+ {
392
+ imported: "Route",
393
+ local: `${node.variableName}RouteImport`
394
+ }
395
+ ]
396
+ };
397
+ }
382
398
  exports.buildFileRoutesByPathInterface = buildFileRoutesByPathInterface;
383
399
  exports.buildImportString = buildImportString;
384
400
  exports.buildRouteTreeConfig = buildRouteTreeConfig;
@@ -394,14 +410,14 @@ exports.determineInitialRoutePath = determineInitialRoutePath;
394
410
  exports.determineNodePath = determineNodePath;
395
411
  exports.findParent = findParent;
396
412
  exports.format = format;
413
+ exports.getImportForRouteNode = getImportForRouteNode;
414
+ exports.getImportPath = getImportPath;
397
415
  exports.getResolvedRouteNodeVariableName = getResolvedRouteNodeVariableName;
398
- exports.hasChildWithExport = hasChildWithExport;
399
416
  exports.hasParentRoute = hasParentRoute;
400
417
  exports.inferFullPath = inferFullPath;
401
418
  exports.inferPath = inferPath;
402
419
  exports.inferTo = inferTo;
403
420
  exports.isRouteNodeValidForAugmentation = isRouteNodeValidForAugmentation;
404
- exports.lowerCaseFirstChar = lowerCaseFirstChar;
405
421
  exports.mergeImportDeclarations = mergeImportDeclarations;
406
422
  exports.multiSortBy = multiSortBy;
407
423
  exports.removeExt = removeExt;