@buzola/vite-plugin 0.0.11 → 0.0.13

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 (76) hide show
  1. package/dist/__tests__/plugin.test.d.ts +2 -0
  2. package/dist/__tests__/plugin.test.d.ts.map +1 -0
  3. package/dist/__tests__/plugin.test.js +110 -0
  4. package/dist/__tests__/plugin.test.js.map +1 -0
  5. package/dist/index.d.ts +0 -14
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +0 -7
  8. package/dist/index.js.map +1 -1
  9. package/dist/plugin.d.ts +2 -20
  10. package/dist/plugin.d.ts.map +1 -1
  11. package/dist/plugin.js +12 -31
  12. package/dist/plugin.js.map +1 -1
  13. package/package.json +3 -5
  14. package/src/__tests__/plugin.test.ts +129 -0
  15. package/src/index.ts +0 -21
  16. package/src/plugin.ts +22 -56
  17. package/dist/__tests__/codegen.test.d.ts +0 -2
  18. package/dist/__tests__/codegen.test.d.ts.map +0 -1
  19. package/dist/__tests__/codegen.test.js +0 -208
  20. package/dist/__tests__/codegen.test.js.map +0 -1
  21. package/dist/__tests__/conventions.test.d.ts +0 -2
  22. package/dist/__tests__/conventions.test.d.ts.map +0 -1
  23. package/dist/__tests__/conventions.test.js +0 -80
  24. package/dist/__tests__/conventions.test.js.map +0 -1
  25. package/dist/__tests__/page-extractor.test.d.ts +0 -2
  26. package/dist/__tests__/page-extractor.test.d.ts.map +0 -1
  27. package/dist/__tests__/page-extractor.test.js +0 -82
  28. package/dist/__tests__/page-extractor.test.js.map +0 -1
  29. package/dist/__tests__/tree-builder.test.d.ts +0 -2
  30. package/dist/__tests__/tree-builder.test.d.ts.map +0 -1
  31. package/dist/__tests__/tree-builder.test.js +0 -474
  32. package/dist/__tests__/tree-builder.test.js.map +0 -1
  33. package/dist/cli.d.ts +0 -3
  34. package/dist/cli.d.ts.map +0 -1
  35. package/dist/cli.js +0 -39
  36. package/dist/cli.js.map +0 -1
  37. package/dist/config.d.ts +0 -20
  38. package/dist/config.d.ts.map +0 -1
  39. package/dist/config.js +0 -20
  40. package/dist/config.js.map +0 -1
  41. package/dist/conventions.d.ts +0 -53
  42. package/dist/conventions.d.ts.map +0 -1
  43. package/dist/conventions.js +0 -82
  44. package/dist/conventions.js.map +0 -1
  45. package/dist/generate.d.ts +0 -26
  46. package/dist/generate.d.ts.map +0 -1
  47. package/dist/generate.js +0 -44
  48. package/dist/generate.js.map +0 -1
  49. package/dist/generator/codegen.d.ts +0 -19
  50. package/dist/generator/codegen.d.ts.map +0 -1
  51. package/dist/generator/codegen.js +0 -170
  52. package/dist/generator/codegen.js.map +0 -1
  53. package/dist/generator/page-extractor.d.ts +0 -21
  54. package/dist/generator/page-extractor.d.ts.map +0 -1
  55. package/dist/generator/page-extractor.js +0 -23
  56. package/dist/generator/page-extractor.js.map +0 -1
  57. package/dist/generator/scanner.d.ts +0 -11
  58. package/dist/generator/scanner.d.ts.map +0 -1
  59. package/dist/generator/scanner.js +0 -34
  60. package/dist/generator/scanner.js.map +0 -1
  61. package/dist/generator/tree-builder.d.ts +0 -54
  62. package/dist/generator/tree-builder.d.ts.map +0 -1
  63. package/dist/generator/tree-builder.js +0 -364
  64. package/dist/generator/tree-builder.js.map +0 -1
  65. package/src/__tests__/codegen.test.ts +0 -229
  66. package/src/__tests__/conventions.test.ts +0 -93
  67. package/src/__tests__/page-extractor.test.ts +0 -95
  68. package/src/__tests__/tree-builder.test.ts +0 -554
  69. package/src/cli.ts +0 -43
  70. package/src/config.ts +0 -35
  71. package/src/conventions.ts +0 -116
  72. package/src/generate.ts +0 -64
  73. package/src/generator/codegen.ts +0 -221
  74. package/src/generator/page-extractor.ts +0 -48
  75. package/src/generator/scanner.ts +0 -45
  76. package/src/generator/tree-builder.ts +0 -454
@@ -1,364 +0,0 @@
1
- import * as path from 'node:path';
2
- import { parseDirName, parseFileName } from '../conventions.js';
3
- import { extractPages } from './page-extractor.js';
4
- // ─── Public API ─────────────────────────────────────────────────────────────
5
- /**
6
- * Build a route tree from scanned files.
7
- * Loads each module via moduleLoader to extract createPage() metadata.
8
- *
9
- * Two-phase approach:
10
- * 1. Extract flat route entries from all files.
11
- * 2. Build the tree using route-pattern prefix matching (not file hierarchy).
12
- */
13
- export async function buildFileRouteTree(files, moduleLoader) {
14
- const entries = await extractEntries(files, moduleLoader);
15
- return buildTreeFromEntries(entries);
16
- }
17
- // ─── Phase 1: Extract flat route entries ────────────────────────────────────
18
- async function extractEntries(files, moduleLoader) {
19
- const entries = [];
20
- for (const file of files) {
21
- const ext = path.extname(file.relativePath);
22
- const withoutExt = file.relativePath.slice(0, -ext.length);
23
- const parts = withoutExt.split(path.sep);
24
- const fileName = parts.pop();
25
- const dirs = parts;
26
- const fileInfo = parseFileName(fileName);
27
- // Compute fileScope (URL path from directory structure, skipping pathless groups)
28
- // and pathlessGroups chain
29
- let fileScope = '';
30
- const pathlessGroups = [];
31
- let groupPath = '';
32
- for (const dir of dirs) {
33
- groupPath = groupPath ? `${groupPath}/${dir}` : dir;
34
- const dirInfo = parseDirName(dir);
35
- if (dirInfo.isPathlessGroup) {
36
- pathlessGroups.push(groupPath);
37
- }
38
- else {
39
- fileScope = joinPath(fileScope, dirInfo.segment);
40
- }
41
- }
42
- if (!fileScope)
43
- fileScope = '/';
44
- if (fileInfo.isLayout) {
45
- // Detect pathless group layout: immediate parent dir is a pathless group
46
- const lastDir = dirs.length > 0 ? dirs[dirs.length - 1] : null;
47
- const isPathlessGroupLayout = lastDir != null && parseDirName(lastDir).isPathlessGroup;
48
- entries.push({
49
- routePattern: fileScope,
50
- treePosition: fileScope,
51
- filePath: file.absolutePath,
52
- exportName: 'default',
53
- kind: 'layout',
54
- params: [],
55
- fileScope,
56
- pathlessGroups,
57
- pathlessGroupId: isPathlessGroupLayout ? groupPath : undefined,
58
- });
59
- }
60
- else if (fileInfo.isNotFound) {
61
- const catchAllPattern = fileScope === '/' ? '/:__notFound+' : `${fileScope}/:__notFound+`;
62
- const pageId = dirs.length === 0 ? '404' : `${dirs.join('/')}/404`;
63
- entries.push({
64
- routePattern: catchAllPattern,
65
- treePosition: catchAllPattern,
66
- filePath: file.absolutePath,
67
- exportName: 'default',
68
- kind: 'notFound',
69
- pageId,
70
- params: [{ name: '__notFound', optional: false, array: false }],
71
- fileScope,
72
- pathlessGroups,
73
- });
74
- }
75
- else {
76
- const isIndex = fileInfo.isIndex;
77
- const basePath = isIndex ? fileScope : joinPath(fileScope, fileName);
78
- const pages = await safeExtractPages(file, moduleLoader);
79
- if (pages.length === 0) {
80
- // No createPage() — plain component
81
- entries.push({
82
- routePattern: basePath,
83
- treePosition: basePath,
84
- filePath: file.absolutePath,
85
- exportName: 'default',
86
- kind: 'page',
87
- params: [],
88
- fileScope,
89
- pathlessGroups,
90
- });
91
- }
92
- else {
93
- for (const page of pages) {
94
- const pageId = derivePageId(dirs, fileName, isIndex, page.exportName);
95
- const defaultPattern = page.isDefault ? basePath : joinPath(basePath, page.exportName);
96
- const routePattern = page.route ?? defaultPattern;
97
- entries.push({
98
- routePattern,
99
- treePosition: defaultPattern,
100
- filePath: file.absolutePath,
101
- exportName: page.exportName,
102
- kind: 'page',
103
- pageId,
104
- params: page.params,
105
- fileScope,
106
- pathlessGroups,
107
- });
108
- }
109
- }
110
- }
111
- }
112
- return entries;
113
- }
114
- function buildTreeFromEntries(entries) {
115
- const root = {
116
- segment: '',
117
- fullPath: '/',
118
- isLayout: false,
119
- isIndex: false,
120
- isNotFound: false,
121
- isPathlessGroup: false,
122
- children: [],
123
- };
124
- const layouts = entries.filter(e => e.kind === 'layout');
125
- const pages = entries.filter(e => e.kind !== 'layout');
126
- // Sort layouts: shorter routePattern first, non-pathless before pathless
127
- layouts.sort((a, b) => {
128
- if (a.routePattern.length !== b.routePattern.length)
129
- return a.routePattern.length - b.routePattern.length;
130
- if (a.pathlessGroupId && !b.pathlessGroupId)
131
- return 1;
132
- if (!a.pathlessGroupId && b.pathlessGroupId)
133
- return -1;
134
- return 0;
135
- });
136
- // Insert layouts into tree
137
- // Track all layout nodes for page assignment
138
- const layoutRefs = [{ node: root }];
139
- for (const layout of layouts) {
140
- if (layout.pathlessGroupId) {
141
- // Pathless group layout — find parent by walking layoutRefs, respecting pathless group chain
142
- const parent = findParentForPathlessGroupLayout(layoutRefs, layout);
143
- const node = {
144
- segment: '',
145
- fullPath: layout.treePosition,
146
- filePath: layout.filePath,
147
- isLayout: true,
148
- isIndex: false,
149
- isNotFound: false,
150
- isPathlessGroup: true,
151
- children: [],
152
- };
153
- parent.node.children.push(node);
154
- layoutRefs.push({ node, pathlessGroupId: layout.pathlessGroupId });
155
- }
156
- else if (layout.treePosition === '/' && !root.filePath) {
157
- // Root layout
158
- root.isLayout = true;
159
- root.filePath = layout.filePath;
160
- }
161
- else if (layout.treePosition === '/') {
162
- // Additional layout at root (shouldn't happen normally, but handle)
163
- root.isLayout = true;
164
- root.filePath = layout.filePath;
165
- }
166
- else {
167
- // Regular layout — find parent by prefix matching
168
- const parent = findDeepestLayoutParent(layoutRefs, layout.treePosition, layout.pathlessGroups);
169
- const segment = computeSegmentFromParent(parent.node.fullPath, layout.treePosition);
170
- const node = {
171
- segment,
172
- fullPath: layout.treePosition,
173
- filePath: layout.filePath,
174
- isLayout: true,
175
- isIndex: false,
176
- isNotFound: false,
177
- isPathlessGroup: false,
178
- children: [],
179
- };
180
- parent.node.children.push(node);
181
- layoutRefs.push({ node });
182
- }
183
- }
184
- // Insert pages into tree (using file-hierarchy position, not route pattern)
185
- for (const entry of pages) {
186
- const parent = findDeepestLayoutParent(layoutRefs, entry.treePosition, entry.pathlessGroups);
187
- const isIndex = entry.treePosition === parent.node.fullPath;
188
- const segment = isIndex ? '' : computeSegmentFromParent(parent.node.fullPath, entry.treePosition);
189
- const pageExports = entry.pageId
190
- ? [{
191
- pageId: entry.pageId,
192
- exportName: entry.exportName,
193
- routePattern: entry.routePattern,
194
- params: entry.params,
195
- }]
196
- : undefined;
197
- // For named exports from the same file as an existing node, check collision
198
- if (!isIndex) {
199
- checkCollision(parent.node.children, segment, entry.filePath, entry.exportName);
200
- }
201
- // Try to reuse an existing container node (e.g., from a directory that has no _layout.tsx)
202
- const existing = !isIndex
203
- ? parent.node.children.find(c => c.segment === segment && !c.filePath && !c.isLayout && !c.isPathlessGroup)
204
- : undefined;
205
- if (existing) {
206
- existing.filePath = entry.filePath;
207
- existing.exportName = entry.exportName;
208
- existing.pageExports = pageExports;
209
- }
210
- else {
211
- parent.node.children.push({
212
- segment,
213
- fullPath: entry.treePosition,
214
- filePath: entry.filePath,
215
- exportName: entry.exportName,
216
- isLayout: false,
217
- isIndex,
218
- isNotFound: entry.kind === 'notFound',
219
- isPathlessGroup: false,
220
- pageExports,
221
- children: [],
222
- });
223
- }
224
- }
225
- // Sort children recursively
226
- sortChildren(root);
227
- if (root.isLayout && root.filePath) {
228
- return [root];
229
- }
230
- return root.children;
231
- }
232
- /**
233
- * Find the parent layout for a pathless group layout.
234
- * The parent is the deepest layout at the same routePattern level,
235
- * considering the pathless group nesting chain.
236
- */
237
- function findParentForPathlessGroupLayout(layoutRefs, entry) {
238
- // The parent is the layout whose pathlessGroupId is the previous entry in the chain,
239
- // or the deepest non-pathless layout at the same routePattern if this is the first group.
240
- const groupChain = entry.pathlessGroups;
241
- const thisGroupIndex = groupChain.indexOf(entry.pathlessGroupId);
242
- if (thisGroupIndex > 0) {
243
- // Has a parent pathless group — find it
244
- const parentGroupId = groupChain[thisGroupIndex - 1];
245
- const parentRef = layoutRefs.find(r => r.pathlessGroupId === parentGroupId);
246
- if (parentRef)
247
- return parentRef;
248
- }
249
- // First pathless group in chain (or parent not found) — find the deepest regular layout at prefix
250
- let best = layoutRefs[0]; // root
251
- for (const ref of layoutRefs) {
252
- if (ref.pathlessGroupId)
253
- continue; // skip other pathless groups
254
- if (isPathPrefixOrEqual(ref.node.fullPath, entry.routePattern) && ref.node.fullPath.length >= best.node.fullPath.length) {
255
- best = ref;
256
- }
257
- }
258
- return best;
259
- }
260
- /**
261
- * Find the deepest layout whose routePattern is a prefix of the given pattern.
262
- * Respects pathless group membership.
263
- */
264
- function findDeepestLayoutParent(layoutRefs, routePattern, pathlessGroups) {
265
- let best = layoutRefs[0]; // root
266
- for (const ref of layoutRefs) {
267
- if (!isPathPrefixOrEqual(ref.node.fullPath, routePattern))
268
- continue;
269
- // For pathless groups, only match if the entry belongs to this group
270
- if (ref.pathlessGroupId && !pathlessGroups.includes(ref.pathlessGroupId))
271
- continue;
272
- // Prefer deeper matches. For ties (pathless groups at same depth), prefer pathless group
273
- // that the entry belongs to over non-pathless.
274
- if (ref.node.fullPath.length > best.node.fullPath.length) {
275
- best = ref;
276
- }
277
- else if (ref.node.fullPath.length === best.node.fullPath.length && ref.pathlessGroupId && pathlessGroups.includes(ref.pathlessGroupId)) {
278
- best = ref;
279
- }
280
- }
281
- return best;
282
- }
283
- function isPathPrefixOrEqual(prefix, path) {
284
- if (prefix === '/')
285
- return true;
286
- return path === prefix || path.startsWith(prefix + '/');
287
- }
288
- function computeSegmentFromParent(parentFullPath, childFullPath) {
289
- if (parentFullPath === '/')
290
- return childFullPath.slice(1);
291
- return childFullPath.slice(parentFullPath.length + 1);
292
- }
293
- // ─── Helpers ────────────────────────────────────────────────────────────────
294
- /**
295
- * Derive page ID from file path and export name.
296
- */
297
- function derivePageId(dirs, fileName, isIndex, exportName) {
298
- const segments = [...dirs];
299
- if (isIndex) {
300
- if (segments.length === 0) {
301
- return exportName === 'default' ? 'index' : `index/${exportName}`;
302
- }
303
- const base = segments.join('/');
304
- return exportName === 'default' ? base : `${base}/${exportName}`;
305
- }
306
- segments.push(fileName);
307
- const base = segments.join('/');
308
- return exportName === 'default' ? base : `${base}/${exportName}`;
309
- }
310
- async function safeExtractPages(file, moduleLoader) {
311
- try {
312
- return await extractPages(file.absolutePath, moduleLoader);
313
- }
314
- catch (error) {
315
- const message = error instanceof Error ? error.message : String(error);
316
- const stack = error instanceof Error && error.stack ? `\n${error.stack}` : '';
317
- console.warn(`[buzola] Failed to extract page metadata from "${file.relativePath}". `
318
- + `The file will be treated as a plain component (no typed params, no loader, no custom route). `
319
- + `Cause: ${message}${stack}`);
320
- return [];
321
- }
322
- }
323
- function checkCollision(siblings, segment, filePath, exportName) {
324
- const existing = siblings.find(c => c.segment === segment && !c.isLayout && !c.isPathlessGroup);
325
- if (!existing || !existing.filePath)
326
- return;
327
- const existingDesc = existing.exportName && existing.exportName !== 'default'
328
- ? `named export '${existing.exportName}' in '${existing.filePath}'`
329
- : `'${existing.filePath}'`;
330
- const newDesc = exportName !== 'default'
331
- ? `named export '${exportName}' in '${filePath}'`
332
- : `'${filePath}'`;
333
- throw new Error(`Route collision: ${newDesc} conflicts with ${existingDesc} — both resolve to segment '${segment}'`);
334
- }
335
- function sortChildren(node) {
336
- for (const child of node.children) {
337
- sortChildren(child);
338
- }
339
- node.children.sort((a, b) => sortWeight(a) - sortWeight(b));
340
- }
341
- const SORT_INDEX = 0;
342
- const SORT_STATIC = 1;
343
- const SORT_DYNAMIC = 2;
344
- const SORT_CATCHALL = 3;
345
- const SORT_NOT_FOUND = 4;
346
- function sortWeight(node) {
347
- if (node.isIndex)
348
- return SORT_INDEX;
349
- if (node.isNotFound)
350
- return SORT_NOT_FOUND;
351
- if (node.segment.includes(':') && node.segment.includes('+'))
352
- return SORT_CATCHALL;
353
- if (node.segment.includes(':'))
354
- return SORT_DYNAMIC;
355
- return SORT_STATIC;
356
- }
357
- function joinPath(parent, child) {
358
- if (!child)
359
- return parent || '/';
360
- if (!parent || parent === '/')
361
- return `/${child}`;
362
- return `${parent}/${child}`;
363
- }
364
- //# sourceMappingURL=tree-builder.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tree-builder.js","sourceRoot":"","sources":["../../src/generator/tree-builder.ts"],"names":[],"mappings":"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"}
@@ -1,229 +0,0 @@
1
- import { describe, expect, it } from 'bun:test'
2
- import { generateRouteModule } from '../generator/codegen.js'
3
-
4
- describe('generateRouteModule', () => {
5
- it('emits BuzolaPersistentParams when persistentParams is provided', () => {
6
- const output = generateRouteModule({
7
- tree: [],
8
- routesDir: '/tmp/routes',
9
- outputPath: '/tmp/buzola.gen.ts',
10
- persistentParams: ['lang'],
11
- })
12
-
13
- expect(output).toContain('interface BuzolaPersistentParams')
14
- expect(output).toContain('lang: true;')
15
- })
16
-
17
- it('quotes hyphenated persistentParams keys', () => {
18
- const output = generateRouteModule({
19
- tree: [],
20
- routesDir: '/tmp/routes',
21
- outputPath: '/tmp/buzola.gen.ts',
22
- persistentParams: ['create-new-project', 'source', 'utm-medium'],
23
- })
24
-
25
- expect(output).toContain("'create-new-project': true;")
26
- expect(output).toContain('source: true;')
27
- expect(output).toContain("'utm-medium': true;")
28
- })
29
-
30
- it('quotes hyphenated page param keys in BuzolaPageMap', () => {
31
- const output = generateRouteModule({
32
- tree: [{
33
- segment: 'users',
34
- fullPath: '/users',
35
- filePath: '/tmp/routes/users.tsx',
36
- exportName: 'default',
37
- isLayout: false,
38
- isIndex: false,
39
- isNotFound: false,
40
- isPathlessGroup: false,
41
- pageExports: [{
42
- pageId: 'users',
43
- exportName: 'default',
44
- routePattern: '/users',
45
- params: [
46
- { name: 'create-new-project', optional: true, array: false },
47
- { name: 'source', optional: false, array: false },
48
- ],
49
- }],
50
- children: [],
51
- }],
52
- routesDir: '/tmp/routes',
53
- outputPath: '/tmp/buzola.gen.ts',
54
- })
55
-
56
- expect(output).toContain("'create-new-project'?: string")
57
- expect(output).toContain('source: string')
58
- })
59
-
60
- it('does not emit BuzolaPersistentParams without persistentParams', () => {
61
- const output = generateRouteModule({
62
- tree: [],
63
- routesDir: '/tmp/routes',
64
- outputPath: '/tmp/buzola.gen.ts',
65
- })
66
-
67
- expect(output).not.toContain('BuzolaPersistentParams')
68
- })
69
-
70
- it('emits BuzolaPageMap interface', () => {
71
- const output = generateRouteModule({
72
- tree: [],
73
- routesDir: '/tmp/routes',
74
- outputPath: '/tmp/buzola.gen.ts',
75
- })
76
-
77
- expect(output).toContain('interface BuzolaPageMap')
78
- })
79
-
80
- it('emits pageRegistry export', () => {
81
- const output = generateRouteModule({
82
- tree: [],
83
- routesDir: '/tmp/routes',
84
- outputPath: '/tmp/buzola.gen.ts',
85
- })
86
-
87
- expect(output).toContain('export const pageRegistry')
88
- })
89
-
90
- it('generates correct lazy import for default export', () => {
91
- const output = generateRouteModule({
92
- tree: [{
93
- segment: 'users',
94
- fullPath: '/users',
95
- filePath: '/tmp/routes/users.tsx',
96
- exportName: 'default',
97
- isLayout: false,
98
- isIndex: false,
99
- isNotFound: false,
100
- isPathlessGroup: false,
101
- pageExports: [{ pageId: 'users', exportName: 'default', routePattern: '/users', params: [] }],
102
- children: [],
103
- }],
104
- routesDir: '/tmp/routes',
105
- outputPath: '/tmp/buzola.gen.ts',
106
- })
107
-
108
- expect(output).toContain('.then(m => ({ default: m.default.component }))')
109
- })
110
-
111
- it('generates correct lazy import for named export', () => {
112
- const output = generateRouteModule({
113
- tree: [{
114
- segment: 'users',
115
- fullPath: '/users',
116
- isLayout: false,
117
- isIndex: false,
118
- isNotFound: false,
119
- isPathlessGroup: false,
120
- children: [{
121
- segment: 'detail',
122
- fullPath: '/users/detail',
123
- filePath: '/tmp/routes/users.tsx',
124
- exportName: 'detail',
125
- isLayout: false,
126
- isIndex: false,
127
- isNotFound: false,
128
- isPathlessGroup: false,
129
- pageExports: [{ pageId: 'users/detail', exportName: 'detail', routePattern: '/users/detail', params: [] }],
130
- children: [],
131
- }],
132
- }],
133
- routesDir: '/tmp/routes',
134
- outputPath: '/tmp/buzola.gen.ts',
135
- })
136
-
137
- expect(output).toContain('.then(m => ({ default: m.detail.component }))')
138
- expect(output).toContain("'users/detail': '/users/detail'")
139
- })
140
-
141
- it('generates matchPath when routePattern differs from file position', () => {
142
- const output = generateRouteModule({
143
- tree: [{
144
- segment: 'login',
145
- fullPath: '/login',
146
- filePath: '/tmp/routes/login/_layout.tsx',
147
- isLayout: true,
148
- isIndex: false,
149
- isNotFound: false,
150
- isPathlessGroup: false,
151
- children: [{
152
- segment: '',
153
- fullPath: '/login',
154
- filePath: '/tmp/routes/login/index.tsx',
155
- exportName: 'default',
156
- isLayout: false,
157
- isIndex: true,
158
- isNotFound: false,
159
- isPathlessGroup: false,
160
- pageExports: [{ pageId: 'login', exportName: 'default', routePattern: '/', params: [] }],
161
- children: [],
162
- }],
163
- }],
164
- routesDir: '/tmp/routes',
165
- outputPath: '/tmp/buzola.gen.ts',
166
- })
167
-
168
- expect(output).toContain("matchPath: '/'")
169
- expect(output).toContain('isIndex: true')
170
- })
171
-
172
- it('does not generate matchPath when routePattern matches file position', () => {
173
- const output = generateRouteModule({
174
- tree: [{
175
- segment: 'users',
176
- fullPath: '/users',
177
- filePath: '/tmp/routes/users.tsx',
178
- exportName: 'default',
179
- isLayout: false,
180
- isIndex: false,
181
- isNotFound: false,
182
- isPathlessGroup: false,
183
- pageExports: [{ pageId: 'users', exportName: 'default', routePattern: '/users', params: [] }],
184
- children: [],
185
- }],
186
- routesDir: '/tmp/routes',
187
- outputPath: '/tmp/buzola.gen.ts',
188
- })
189
-
190
- expect(output).not.toContain('matchPath')
191
- })
192
-
193
- it('generates separate imports for default and named exports from same file', () => {
194
- const output = generateRouteModule({
195
- tree: [{
196
- segment: 'users',
197
- fullPath: '/users',
198
- filePath: '/tmp/routes/users.tsx',
199
- exportName: 'default',
200
- isLayout: false,
201
- isIndex: false,
202
- isNotFound: false,
203
- isPathlessGroup: false,
204
- pageExports: [{ pageId: 'users', exportName: 'default', routePattern: '/users', params: [] }],
205
- children: [{
206
- segment: 'detail',
207
- fullPath: '/users/detail',
208
- filePath: '/tmp/routes/users.tsx',
209
- exportName: 'detail',
210
- isLayout: false,
211
- isIndex: false,
212
- isNotFound: false,
213
- isPathlessGroup: false,
214
- pageExports: [{ pageId: 'users/detail', exportName: 'detail', routePattern: '/users/detail', params: [] }],
215
- children: [],
216
- }],
217
- }],
218
- routesDir: '/tmp/routes',
219
- outputPath: '/tmp/buzola.gen.ts',
220
- })
221
-
222
- // Two separate import lines for the same file
223
- expect(output).toContain('m.default.component')
224
- expect(output).toContain('m.detail.component')
225
- // Both in page registry
226
- expect(output).toContain("'users': '/users'")
227
- expect(output).toContain("'users/detail': '/users/detail'")
228
- })
229
- })