@benjavicente/router-generator 1.166.24

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 (108) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
  3. package/dist/cjs/config.cjs +134 -0
  4. package/dist/cjs/config.cjs.map +1 -0
  5. package/dist/cjs/config.d.cts +254 -0
  6. package/dist/cjs/filesystem/physical/getRouteNodes.cjs +234 -0
  7. package/dist/cjs/filesystem/physical/getRouteNodes.cjs.map +1 -0
  8. package/dist/cjs/filesystem/physical/getRouteNodes.d.cts +25 -0
  9. package/dist/cjs/filesystem/physical/rootPathId.cjs +6 -0
  10. package/dist/cjs/filesystem/physical/rootPathId.cjs.map +1 -0
  11. package/dist/cjs/filesystem/physical/rootPathId.d.cts +1 -0
  12. package/dist/cjs/filesystem/virtual/config.cjs +39 -0
  13. package/dist/cjs/filesystem/virtual/config.cjs.map +1 -0
  14. package/dist/cjs/filesystem/virtual/config.d.cts +3 -0
  15. package/dist/cjs/filesystem/virtual/getRouteNodes.cjs +175 -0
  16. package/dist/cjs/filesystem/virtual/getRouteNodes.cjs.map +1 -0
  17. package/dist/cjs/filesystem/virtual/getRouteNodes.d.cts +9 -0
  18. package/dist/cjs/filesystem/virtual/loadConfigFile.cjs +12 -0
  19. package/dist/cjs/filesystem/virtual/loadConfigFile.cjs.map +1 -0
  20. package/dist/cjs/filesystem/virtual/loadConfigFile.d.cts +1 -0
  21. package/dist/cjs/generator.cjs +805 -0
  22. package/dist/cjs/generator.cjs.map +1 -0
  23. package/dist/cjs/generator.d.cts +116 -0
  24. package/dist/cjs/index.cjs +33 -0
  25. package/dist/cjs/index.d.cts +12 -0
  26. package/dist/cjs/logger.cjs +31 -0
  27. package/dist/cjs/logger.cjs.map +1 -0
  28. package/dist/cjs/logger.d.cts +10 -0
  29. package/dist/cjs/plugin/types.d.cts +18 -0
  30. package/dist/cjs/template.cjs +203 -0
  31. package/dist/cjs/template.cjs.map +1 -0
  32. package/dist/cjs/template.d.cts +34 -0
  33. package/dist/cjs/transform/transform.cjs +302 -0
  34. package/dist/cjs/transform/transform.cjs.map +1 -0
  35. package/dist/cjs/transform/transform.d.cts +4 -0
  36. package/dist/cjs/transform/types.d.cts +31 -0
  37. package/dist/cjs/transform/utils.cjs +34 -0
  38. package/dist/cjs/transform/utils.cjs.map +1 -0
  39. package/dist/cjs/transform/utils.d.cts +2 -0
  40. package/dist/cjs/types.d.cts +57 -0
  41. package/dist/cjs/utils.cjs +653 -0
  42. package/dist/cjs/utils.cjs.map +1 -0
  43. package/dist/cjs/utils.d.cts +212 -0
  44. package/dist/cjs/validate-route-params.cjs +73 -0
  45. package/dist/cjs/validate-route-params.cjs.map +1 -0
  46. package/dist/cjs/validate-route-params.d.cts +9 -0
  47. package/dist/esm/config.d.ts +254 -0
  48. package/dist/esm/config.js +129 -0
  49. package/dist/esm/config.js.map +1 -0
  50. package/dist/esm/filesystem/physical/getRouteNodes.d.ts +25 -0
  51. package/dist/esm/filesystem/physical/getRouteNodes.js +230 -0
  52. package/dist/esm/filesystem/physical/getRouteNodes.js.map +1 -0
  53. package/dist/esm/filesystem/physical/rootPathId.d.ts +1 -0
  54. package/dist/esm/filesystem/physical/rootPathId.js +6 -0
  55. package/dist/esm/filesystem/physical/rootPathId.js.map +1 -0
  56. package/dist/esm/filesystem/virtual/config.d.ts +3 -0
  57. package/dist/esm/filesystem/virtual/config.js +38 -0
  58. package/dist/esm/filesystem/virtual/config.js.map +1 -0
  59. package/dist/esm/filesystem/virtual/getRouteNodes.d.ts +9 -0
  60. package/dist/esm/filesystem/virtual/getRouteNodes.js +173 -0
  61. package/dist/esm/filesystem/virtual/getRouteNodes.js.map +1 -0
  62. package/dist/esm/filesystem/virtual/loadConfigFile.d.ts +1 -0
  63. package/dist/esm/filesystem/virtual/loadConfigFile.js +11 -0
  64. package/dist/esm/filesystem/virtual/loadConfigFile.js.map +1 -0
  65. package/dist/esm/generator.d.ts +116 -0
  66. package/dist/esm/generator.js +801 -0
  67. package/dist/esm/generator.js.map +1 -0
  68. package/dist/esm/index.d.ts +12 -0
  69. package/dist/esm/index.js +8 -0
  70. package/dist/esm/logger.d.ts +10 -0
  71. package/dist/esm/logger.js +31 -0
  72. package/dist/esm/logger.js.map +1 -0
  73. package/dist/esm/plugin/types.d.ts +18 -0
  74. package/dist/esm/template.d.ts +34 -0
  75. package/dist/esm/template.js +202 -0
  76. package/dist/esm/template.js.map +1 -0
  77. package/dist/esm/transform/transform.d.ts +4 -0
  78. package/dist/esm/transform/transform.js +301 -0
  79. package/dist/esm/transform/transform.js.map +1 -0
  80. package/dist/esm/transform/types.d.ts +31 -0
  81. package/dist/esm/transform/utils.d.ts +2 -0
  82. package/dist/esm/transform/utils.js +34 -0
  83. package/dist/esm/transform/utils.js.map +1 -0
  84. package/dist/esm/types.d.ts +57 -0
  85. package/dist/esm/utils.d.ts +212 -0
  86. package/dist/esm/utils.js +609 -0
  87. package/dist/esm/utils.js.map +1 -0
  88. package/dist/esm/validate-route-params.d.ts +9 -0
  89. package/dist/esm/validate-route-params.js +73 -0
  90. package/dist/esm/validate-route-params.js.map +1 -0
  91. package/package.json +82 -0
  92. package/src/config.ts +247 -0
  93. package/src/filesystem/physical/getRouteNodes.ts +541 -0
  94. package/src/filesystem/physical/rootPathId.ts +1 -0
  95. package/src/filesystem/virtual/config.ts +45 -0
  96. package/src/filesystem/virtual/getRouteNodes.ts +307 -0
  97. package/src/filesystem/virtual/loadConfigFile.ts +8 -0
  98. package/src/generator.ts +1686 -0
  99. package/src/index.ts +54 -0
  100. package/src/logger.ts +43 -0
  101. package/src/plugin/types.ts +18 -0
  102. package/src/template.ts +313 -0
  103. package/src/transform/transform.ts +534 -0
  104. package/src/transform/types.ts +39 -0
  105. package/src/transform/utils.ts +42 -0
  106. package/src/types.ts +74 -0
  107. package/src/utils.ts +1067 -0
  108. package/src/validate-route-params.ts +118 -0
@@ -0,0 +1,301 @@
1
+ import { mergeImportDeclarations } from "../utils.js";
2
+ import { ensureStringArgument } from "./utils.js";
3
+ import { parseAst } from "@benjavicente/router-utils";
4
+ import { parse, print, types, visit } from "recast";
5
+ import { SourceMapConsumer } from "source-map";
6
+ //#region src/transform/transform.ts
7
+ var b = types.builders;
8
+ async function transform({ ctx, source, node }) {
9
+ let appliedChanges = false;
10
+ let ast;
11
+ try {
12
+ ast = parse(source, {
13
+ sourceFileName: "output.ts",
14
+ parser: { parse(code) {
15
+ return parseAst({
16
+ code,
17
+ tokens: true
18
+ });
19
+ } }
20
+ });
21
+ } catch (e) {
22
+ console.error("Error parsing code", ctx.routeId, source, e);
23
+ return {
24
+ result: "error",
25
+ error: e
26
+ };
27
+ }
28
+ const preferredQuote = detectPreferredQuoteStyle(ast);
29
+ let routeExportHandled = false;
30
+ function onExportFound(decl) {
31
+ if (decl.init?.type === "CallExpression") {
32
+ const callExpression = decl.init;
33
+ const firstArgument = callExpression.arguments[0];
34
+ if (firstArgument) {
35
+ if (firstArgument.type === "ObjectExpression") {
36
+ const staticProperties = firstArgument.properties.flatMap((p) => {
37
+ if (p.type === "ObjectProperty" && p.key.type === "Identifier") return p.key.name;
38
+ return [];
39
+ });
40
+ node.createFileRouteProps = new Set(staticProperties);
41
+ }
42
+ }
43
+ let identifier;
44
+ if (callExpression.callee.type === "Identifier") {
45
+ identifier = callExpression.callee;
46
+ if (ctx.verboseFileRoutes) {
47
+ callExpression.callee = b.callExpression(identifier, [b.stringLiteral(ctx.routeId)]);
48
+ appliedChanges = true;
49
+ }
50
+ } else if (callExpression.callee.type === "CallExpression" && callExpression.callee.callee.type === "Identifier") {
51
+ identifier = callExpression.callee.callee;
52
+ if (!ctx.verboseFileRoutes) {
53
+ callExpression.callee = identifier;
54
+ appliedChanges = true;
55
+ } else appliedChanges = ensureStringArgument(callExpression.callee, ctx.routeId, ctx.preferredQuote);
56
+ }
57
+ if (identifier === void 0) throw new Error(`expected identifier to be present in ${ctx.routeId} for export "Route"`);
58
+ if (identifier.name === "createFileRoute" && ctx.lazy) {
59
+ identifier.name = "createLazyFileRoute";
60
+ appliedChanges = true;
61
+ } else if (identifier.name === "createLazyFileRoute" && !ctx.lazy) {
62
+ identifier.name = "createFileRoute";
63
+ appliedChanges = true;
64
+ }
65
+ } else throw new Error(`expected "Route" export to be initialized by a CallExpression`);
66
+ routeExportHandled = true;
67
+ }
68
+ const program = ast.program;
69
+ for (const n of program.body) {
70
+ if (n.type === "ExportNamedDeclaration") {
71
+ if (n.declaration?.type === "VariableDeclaration") {
72
+ const decl = n.declaration.declarations[0];
73
+ if (decl && decl.type === "VariableDeclarator" && decl.id.type === "Identifier") {
74
+ if (decl.id.name === "Route") onExportFound(decl);
75
+ }
76
+ } else if (n.declaration === null && n.specifiers) {
77
+ for (const spec of n.specifiers) if (typeof spec.exported.name === "string") {
78
+ if (spec.exported.name === "Route") {
79
+ const variableName = spec.local?.name || spec.exported.name;
80
+ for (const decl of program.body) if (decl.type === "VariableDeclaration" && decl.declarations[0]) {
81
+ const variable = decl.declarations[0];
82
+ if (variable.type === "VariableDeclarator" && variable.id.type === "Identifier" && variable.id.name === variableName) {
83
+ onExportFound(variable);
84
+ break;
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ if (routeExportHandled) break;
92
+ }
93
+ if (!routeExportHandled) return { result: "no-route-export" };
94
+ const imports = {
95
+ required: [],
96
+ banned: []
97
+ };
98
+ const targetModule = ctx.target === "angular" ? ctx.angularRouterPackage ?? "@benjavicente/angular-router-experimental" : `@benjavicente/${ctx.target}-router`;
99
+ if (ctx.verboseFileRoutes === false) imports.banned = [{
100
+ source: targetModule,
101
+ specifiers: [{ imported: "createLazyFileRoute" }, { imported: "createFileRoute" }]
102
+ }];
103
+ else if (ctx.lazy) {
104
+ imports.required = [{
105
+ source: targetModule,
106
+ specifiers: [{ imported: "createLazyFileRoute" }]
107
+ }];
108
+ imports.banned = [{
109
+ source: targetModule,
110
+ specifiers: [{ imported: "createFileRoute" }]
111
+ }];
112
+ } else {
113
+ imports.required = [{
114
+ source: targetModule,
115
+ specifiers: [{ imported: "createFileRoute" }]
116
+ }];
117
+ imports.banned = [{
118
+ source: targetModule,
119
+ specifiers: [{ imported: "createLazyFileRoute" }]
120
+ }];
121
+ }
122
+ imports.required = mergeImportDeclarations(imports.required);
123
+ imports.banned = mergeImportDeclarations(imports.banned);
124
+ const importStatementCandidates = [];
125
+ const importDeclarationsToRemove = [];
126
+ for (const n of program.body) {
127
+ const findImport = (opts) => (i) => {
128
+ if (i.source === opts.source) {
129
+ const importKind = i.importKind || "value";
130
+ return (opts.importKind || "value") === importKind;
131
+ }
132
+ return false;
133
+ };
134
+ if (n.type === "ImportDeclaration" && typeof n.source.value === "string") {
135
+ const filterImport = findImport({
136
+ source: n.source.value,
137
+ importKind: n.importKind
138
+ });
139
+ let requiredImports = imports.required.filter(filterImport)[0];
140
+ const bannedImports = imports.banned.filter(filterImport)[0];
141
+ if (!requiredImports && !bannedImports) continue;
142
+ const importSpecifiersToRemove = [];
143
+ if (n.specifiers) {
144
+ for (const spec of n.specifiers) {
145
+ if (!requiredImports && !bannedImports) break;
146
+ if (spec.type === "ImportSpecifier" && typeof spec.imported.name === "string") {
147
+ if (requiredImports) {
148
+ const requiredImportIndex = requiredImports.specifiers.findIndex((imp) => imp.imported === spec.imported.name);
149
+ if (requiredImportIndex !== -1) {
150
+ requiredImports.specifiers.splice(requiredImportIndex, 1);
151
+ if (requiredImports.specifiers.length === 0) {
152
+ const reqIdx = imports.required.indexOf(requiredImports);
153
+ if (reqIdx !== -1) imports.required.splice(reqIdx, 1);
154
+ requiredImports = void 0;
155
+ }
156
+ } else if (requiredImports.specifiers.length > 0) importStatementCandidates.push(n);
157
+ }
158
+ if (bannedImports) {
159
+ if (bannedImports.specifiers.findIndex((imp) => imp.imported === spec.imported.name) !== -1) importSpecifiersToRemove.push(spec);
160
+ }
161
+ }
162
+ }
163
+ if (importSpecifiersToRemove.length > 0) {
164
+ appliedChanges = true;
165
+ n.specifiers = n.specifiers.filter((spec) => !importSpecifiersToRemove.includes(spec));
166
+ if (n.specifiers.length === 0) importDeclarationsToRemove.push(n);
167
+ }
168
+ }
169
+ }
170
+ }
171
+ imports.required.forEach((requiredImport) => {
172
+ if (requiredImport.specifiers.length > 0) {
173
+ appliedChanges = true;
174
+ if (importStatementCandidates.length > 0) {
175
+ const importStatement = importStatementCandidates.find((importStatement) => {
176
+ if (importStatement.source.value === requiredImport.source) return (importStatement.importKind || "value") === (requiredImport.importKind || "value");
177
+ return false;
178
+ });
179
+ if (importStatement) {
180
+ if (importStatement.specifiers === void 0) importStatement.specifiers = [];
181
+ const importSpecifiersToAdd = requiredImport.specifiers.map((spec) => b.importSpecifier(b.identifier(spec.imported), b.identifier(spec.imported)));
182
+ importStatement.specifiers = [...importStatement.specifiers, ...importSpecifiersToAdd];
183
+ return;
184
+ }
185
+ }
186
+ const importStatement = b.importDeclaration(requiredImport.specifiers.map((spec) => b.importSpecifier(b.identifier(spec.imported), spec.local ? b.identifier(spec.local) : null)), b.stringLiteral(requiredImport.source));
187
+ program.body.unshift(importStatement);
188
+ }
189
+ });
190
+ if (importDeclarationsToRemove.length > 0) {
191
+ appliedChanges = true;
192
+ for (const importDeclaration of importDeclarationsToRemove) if (importDeclaration.specifiers?.length === 0) {
193
+ const index = program.body.indexOf(importDeclaration);
194
+ if (index !== -1) program.body.splice(index, 1);
195
+ }
196
+ }
197
+ if (!appliedChanges) return { result: "not-modified" };
198
+ const printResult = print(ast, {
199
+ reuseWhitespace: true,
200
+ sourceMapName: "output.map"
201
+ });
202
+ let transformedCode = printResult.code;
203
+ if (printResult.map) transformedCode = await fixTransformedOutputText({
204
+ originalCode: source,
205
+ transformedCode,
206
+ sourceMap: printResult.map,
207
+ preferredQuote
208
+ });
209
+ return {
210
+ result: "modified",
211
+ output: transformedCode
212
+ };
213
+ }
214
+ async function fixTransformedOutputText({ originalCode, transformedCode, sourceMap, preferredQuote }) {
215
+ const originalLines = originalCode.split("\n");
216
+ const transformedLines = transformedCode.split("\n");
217
+ const defaultUsesSemicolons = detectSemicolonUsage(originalCode);
218
+ const consumer = await new SourceMapConsumer(sourceMap);
219
+ return transformedLines.map((line, i) => {
220
+ const transformedLineNum = i + 1;
221
+ let origLineText = void 0;
222
+ for (let col = 0; col < line.length; col++) {
223
+ const mapped = consumer.originalPositionFor({
224
+ line: transformedLineNum,
225
+ column: col
226
+ });
227
+ if (mapped.line != null && mapped.line > 0) {
228
+ origLineText = originalLines[mapped.line - 1];
229
+ break;
230
+ }
231
+ }
232
+ if (origLineText !== void 0) {
233
+ if (origLineText === line) return origLineText;
234
+ return fixLine(line, {
235
+ originalLine: origLineText,
236
+ useOriginalSemicolon: true,
237
+ useOriginalQuotes: true,
238
+ fallbackQuote: preferredQuote
239
+ });
240
+ } else return fixLine(line, {
241
+ originalLine: null,
242
+ useOriginalSemicolon: false,
243
+ useOriginalQuotes: false,
244
+ fallbackQuote: preferredQuote,
245
+ fallbackSemicolon: defaultUsesSemicolons
246
+ });
247
+ }).join("\n");
248
+ }
249
+ function fixLine(line, { originalLine, useOriginalSemicolon, useOriginalQuotes, fallbackQuote, fallbackSemicolon = true }) {
250
+ let result = line;
251
+ if (useOriginalQuotes && originalLine) result = fixQuotes(result, originalLine, fallbackQuote);
252
+ else if (!useOriginalQuotes && fallbackQuote) result = fixQuotesToPreferred(result, fallbackQuote);
253
+ if (useOriginalSemicolon && originalLine) {
254
+ const hadSemicolon = originalLine.trimEnd().endsWith(";");
255
+ const hasSemicolon = result.trimEnd().endsWith(";");
256
+ if (hadSemicolon && !hasSemicolon) result += ";";
257
+ if (!hadSemicolon && hasSemicolon) result = result.replace(/;\s*$/, "");
258
+ } else if (!useOriginalSemicolon) {
259
+ const hasSemicolon = result.trimEnd().endsWith(";");
260
+ if (!fallbackSemicolon && hasSemicolon) result = result.replace(/;\s*$/, "");
261
+ if (fallbackSemicolon && !hasSemicolon && result.trim()) result += ";";
262
+ }
263
+ return result;
264
+ }
265
+ function fixQuotes(line, originalLine, fallbackQuote) {
266
+ let originalQuote = detectQuoteFromLine(originalLine);
267
+ if (!originalQuote) originalQuote = fallbackQuote;
268
+ return fixQuotesToPreferred(line, originalQuote);
269
+ }
270
+ function fixQuotesToPreferred(line, quote) {
271
+ return line.replace(/(['"`])([^'"`\\]*(?:\\.[^'"`\\]*)*)\1/g, (_, q, content) => {
272
+ return `${quote}${content.replaceAll(quote, `\\${quote}`)}${quote}`;
273
+ });
274
+ }
275
+ function detectQuoteFromLine(line) {
276
+ const match = line.match(/(['"`])(?:\\.|[^\\])*?\1/);
277
+ return match ? match[1] : null;
278
+ }
279
+ function detectSemicolonUsage(code) {
280
+ const lines = code.split("\n").map((l) => l.trim());
281
+ const total = lines.length;
282
+ return lines.filter((l) => l.endsWith(";")).length > total / 2;
283
+ }
284
+ function detectPreferredQuoteStyle(ast) {
285
+ let single = 0;
286
+ let double = 0;
287
+ visit(ast, { visitStringLiteral(path) {
288
+ if (path.parent.node.type !== "JSXAttribute") {
289
+ const raw = path.node.extra?.raw;
290
+ if (raw?.startsWith("'")) single++;
291
+ else if (raw?.startsWith("\"")) double++;
292
+ }
293
+ return false;
294
+ } });
295
+ if (single >= double) return "'";
296
+ return "\"";
297
+ }
298
+ //#endregion
299
+ export { transform };
300
+
301
+ //# sourceMappingURL=transform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform.js","names":[],"sources":["../../../src/transform/transform.ts"],"sourcesContent":["import { parseAst } from '@benjavicente/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 =\n ctx.target === 'angular'\n ? (ctx.angularRouterPackage ??\n '@benjavicente/angular-router-experimental')\n : `@benjavicente/${ctx.target}-router`\n\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 const reqIdx = imports.required.indexOf(requiredImports)\n if (reqIdx !== -1) {\n imports.required.splice(reqIdx, 1)\n }\n requiredImports = undefined\n }\n } else if (requiredImports.specifiers.length > 0) {\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"],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { ImportDeclaration, RouteNode } from '../types.js';
2
+ import { Config } from '../config.js';
3
+ export interface TransformOptions {
4
+ source: string;
5
+ ctx: TransformContext;
6
+ node: RouteNode;
7
+ }
8
+ export type TransformResult = {
9
+ result: 'no-route-export';
10
+ } | {
11
+ result: 'not-modified';
12
+ } | {
13
+ result: 'modified';
14
+ output: string;
15
+ } | {
16
+ result: 'error';
17
+ error?: any;
18
+ };
19
+ export interface TransformImportsConfig {
20
+ banned?: Array<ImportDeclaration>;
21
+ required?: Array<ImportDeclaration>;
22
+ }
23
+ export interface TransformContext {
24
+ target: Config['target'];
25
+ routeId: string;
26
+ lazy: boolean;
27
+ verboseFileRoutes: boolean;
28
+ preferredQuote?: '"' | "'";
29
+ /** Set when `target` is `angular`; drives `createFileRoute` import source. */
30
+ angularRouterPackage?: string;
31
+ }
@@ -0,0 +1,2 @@
1
+ import { types } from 'recast';
2
+ export declare function ensureStringArgument(callExpression: types.namedTypes.CallExpression, value: string, preferredQuote?: "'" | '"'): boolean;
@@ -0,0 +1,34 @@
1
+ import { types } from "recast";
2
+ //#region src/transform/utils.ts
3
+ var b = types.builders;
4
+ function ensureStringArgument(callExpression, value, preferredQuote) {
5
+ const argument = callExpression.arguments[0];
6
+ if (!argument) {
7
+ let stringLiteral;
8
+ if (!preferredQuote) stringLiteral = b.stringLiteral.from({ value });
9
+ else stringLiteral = b.stringLiteral.from({
10
+ value,
11
+ extra: {
12
+ rawValue: value,
13
+ raw: `${preferredQuote}${value}${preferredQuote}`
14
+ }
15
+ });
16
+ callExpression.arguments.push(stringLiteral);
17
+ return true;
18
+ } else if (argument.type === "StringLiteral") {
19
+ if (argument.value !== value) {
20
+ argument.value = value;
21
+ return true;
22
+ }
23
+ } else if (argument.type === "TemplateLiteral") {
24
+ if (argument.quasis.length === 1 && argument.quasis[0] && argument.quasis[0].value.raw !== value) {
25
+ argument.quasis[0].value.raw = value;
26
+ return true;
27
+ }
28
+ }
29
+ return false;
30
+ }
31
+ //#endregion
32
+ export { ensureStringArgument };
33
+
34
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","names":[],"sources":["../../../src/transform/utils.ts"],"sourcesContent":["import { types } from 'recast'\n\nconst b = types.builders\n\nexport function ensureStringArgument(\n callExpression: types.namedTypes.CallExpression,\n value: string,\n preferredQuote?: \"'\" | '\"',\n) {\n const argument = callExpression.arguments[0]\n if (!argument) {\n let stringLiteral: types.namedTypes.StringLiteral\n if (!preferredQuote) {\n stringLiteral = b.stringLiteral.from({ value })\n } else {\n stringLiteral = b.stringLiteral.from({\n value,\n extra: {\n rawValue: value,\n raw: `${preferredQuote}${value}${preferredQuote}`,\n },\n })\n }\n callExpression.arguments.push(stringLiteral)\n return true\n } else if (argument.type === 'StringLiteral') {\n if (argument.value !== value) {\n argument.value = value\n return true\n }\n } else if (argument.type === 'TemplateLiteral') {\n if (\n argument.quasis.length === 1 &&\n argument.quasis[0] &&\n argument.quasis[0].value.raw !== value\n ) {\n argument.quasis[0].value.raw = value\n return true\n }\n }\n return false\n}\n"],"mappings":";;AAEA,IAAM,IAAI,MAAM;AAEhB,SAAgB,qBACd,gBACA,OACA,gBACA;CACA,MAAM,WAAW,eAAe,UAAU;AAC1C,KAAI,CAAC,UAAU;EACb,IAAI;AACJ,MAAI,CAAC,eACH,iBAAgB,EAAE,cAAc,KAAK,EAAE,OAAO,CAAC;MAE/C,iBAAgB,EAAE,cAAc,KAAK;GACnC;GACA,OAAO;IACL,UAAU;IACV,KAAK,GAAG,iBAAiB,QAAQ;IAClC;GACF,CAAC;AAEJ,iBAAe,UAAU,KAAK,cAAc;AAC5C,SAAO;YACE,SAAS,SAAS;MACvB,SAAS,UAAU,OAAO;AAC5B,YAAS,QAAQ;AACjB,UAAO;;YAEA,SAAS,SAAS;MAEzB,SAAS,OAAO,WAAW,KAC3B,SAAS,OAAO,MAChB,SAAS,OAAO,GAAG,MAAM,QAAQ,OACjC;AACA,YAAS,OAAO,GAAG,MAAM,MAAM;AAC/B,UAAO;;;AAGX,QAAO"}
@@ -0,0 +1,57 @@
1
+ export type RouteNode = {
2
+ filePath: string;
3
+ fullPath: string;
4
+ variableName: string;
5
+ _fsRouteType: FsRouteType;
6
+ routePath?: string;
7
+ originalRoutePath?: string;
8
+ cleanedPath?: string;
9
+ path?: string;
10
+ isNonPath?: boolean;
11
+ isVirtualParentRoute?: boolean;
12
+ isVirtual?: boolean;
13
+ children?: Array<RouteNode>;
14
+ parent?: RouteNode;
15
+ createFileRouteProps?: Set<string>;
16
+ /**
17
+ * For virtual routes: the routePath of the explicit parent from virtual config.
18
+ * Used to prevent auto-nesting siblings based on path prefix matching (#5822, #5431).
19
+ * Falls back to path-based inference if the explicit parent is not found
20
+ * (e.g., when the parent is a virtual file-less route that gets filtered out).
21
+ */
22
+ _virtualParentRoutePath?: string;
23
+ };
24
+ export interface GetRouteNodesResult {
25
+ rootRouteNode?: RouteNode;
26
+ routeNodes: Array<RouteNode>;
27
+ physicalDirectories: Array<string>;
28
+ }
29
+ export type FsRouteType = '__root' | 'static' | 'layout' | 'pathless_layout' | 'lazy' | 'loader' | 'component' | 'pendingComponent' | 'errorComponent' | 'notFoundComponent';
30
+ export type RouteSubNode = {
31
+ component?: RouteNode;
32
+ errorComponent?: RouteNode;
33
+ notFoundComponent?: RouteNode;
34
+ pendingComponent?: RouteNode;
35
+ loader?: RouteNode;
36
+ lazy?: RouteNode;
37
+ };
38
+ export type ImportSpecifier = {
39
+ imported: string;
40
+ local?: string;
41
+ };
42
+ export type ImportDeclaration = {
43
+ source: string;
44
+ specifiers: Array<ImportSpecifier>;
45
+ importKind?: 'type' | 'value';
46
+ };
47
+ export type HandleNodeAccumulator = {
48
+ routeTree: Array<RouteNode>;
49
+ routePiecesByPath: Record<string, RouteSubNode>;
50
+ routeNodes: Array<RouteNode>;
51
+ /** O(1) lookup by routePath - avoids O(n) .find() on every node */
52
+ routeNodesByPath: Map<string, RouteNode>;
53
+ };
54
+ export type GetRoutesByFileMapResultValue = {
55
+ routePath: string;
56
+ };
57
+ export type GetRoutesByFileMapResult = Map<string, GetRoutesByFileMapResultValue>;