@tanstack/router-generator 1.139.14 → 1.140.1
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.
- package/dist/cjs/config.cjs +1 -1
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/config.d.cts +6 -6
- package/dist/cjs/filesystem/physical/getRouteNodes.cjs +32 -17
- package/dist/cjs/filesystem/physical/getRouteNodes.cjs.map +1 -1
- package/dist/cjs/filesystem/physical/getRouteNodes.d.cts +1 -1
- package/dist/cjs/generator.cjs +141 -42
- package/dist/cjs/generator.cjs.map +1 -1
- package/dist/cjs/template.cjs +47 -0
- package/dist/cjs/template.cjs.map +1 -1
- package/dist/cjs/types.d.cts +2 -1
- package/dist/esm/config.d.ts +6 -6
- package/dist/esm/config.js +1 -1
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/filesystem/physical/getRouteNodes.d.ts +1 -1
- package/dist/esm/filesystem/physical/getRouteNodes.js +32 -17
- package/dist/esm/filesystem/physical/getRouteNodes.js.map +1 -1
- package/dist/esm/generator.js +141 -42
- package/dist/esm/generator.js.map +1 -1
- package/dist/esm/template.js +47 -0
- package/dist/esm/template.js.map +1 -1
- package/dist/esm/types.d.ts +2 -1
- package/package.json +6 -6
- package/src/config.ts +1 -1
- package/src/filesystem/physical/getRouteNodes.ts +42 -19
- package/src/generator.ts +208 -54
- package/src/template.ts +65 -0
- package/src/types.ts +2 -0
|
@@ -17,7 +17,7 @@ import type {
|
|
|
17
17
|
import type { FsRouteType, GetRouteNodesResult, RouteNode } from '../../types'
|
|
18
18
|
import type { Config } from '../../config'
|
|
19
19
|
|
|
20
|
-
const disallowedRouteGroupConfiguration = /\(([^)]+)\).(ts|js|tsx|jsx)/
|
|
20
|
+
const disallowedRouteGroupConfiguration = /\(([^)]+)\).(ts|js|tsx|jsx|vue)/
|
|
21
21
|
|
|
22
22
|
const virtualConfigFileRegExp = /__virtual\.[mc]?[jt]s$/
|
|
23
23
|
export function isVirtualConfigFile(fileName: string): boolean {
|
|
@@ -129,7 +129,7 @@ export async function getRouteNodes(
|
|
|
129
129
|
|
|
130
130
|
if (dirent.isDirectory()) {
|
|
131
131
|
await recurse(relativePath)
|
|
132
|
-
} else if (fullPath.match(/\.(tsx|ts|jsx|js)$/)) {
|
|
132
|
+
} else if (fullPath.match(/\.(tsx|ts|jsx|js|vue)$/)) {
|
|
133
133
|
const filePath = replaceBackslash(path.join(dir, dirent.name))
|
|
134
134
|
const filePathNoExt = removeExt(filePath)
|
|
135
135
|
const {
|
|
@@ -170,31 +170,37 @@ export async function getRouteNodes(
|
|
|
170
170
|
routeType = 'pathless_layout'
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
[
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
173
|
+
// Only show deprecation warning for .tsx/.ts files, not .vue files
|
|
174
|
+
// Vue files using .component.vue is the Vue-native way
|
|
175
|
+
const isVueFile = filePath.endsWith('.vue')
|
|
176
|
+
if (!isVueFile) {
|
|
177
|
+
;(
|
|
178
|
+
[
|
|
179
|
+
['component', 'component'],
|
|
180
|
+
['errorComponent', 'errorComponent'],
|
|
181
|
+
['notFoundComponent', 'notFoundComponent'],
|
|
182
|
+
['pendingComponent', 'pendingComponent'],
|
|
183
|
+
['loader', 'loader'],
|
|
184
|
+
] satisfies Array<[FsRouteType, string]>
|
|
185
|
+
).forEach(([matcher, type]) => {
|
|
186
|
+
if (routeType === matcher) {
|
|
187
|
+
logger.warn(
|
|
188
|
+
`WARNING: The \`.${type}.tsx\` suffix used for the ${filePath} file is deprecated. Use the new \`.lazy.tsx\` suffix instead.`,
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
})
|
|
192
|
+
}
|
|
187
193
|
|
|
188
194
|
routePath = routePath.replace(
|
|
189
195
|
new RegExp(
|
|
190
|
-
`/(component|errorComponent|pendingComponent|loader|${config.routeToken}|lazy)$`,
|
|
196
|
+
`/(component|errorComponent|notFoundComponent|pendingComponent|loader|${config.routeToken}|lazy)$`,
|
|
191
197
|
),
|
|
192
198
|
'',
|
|
193
199
|
)
|
|
194
200
|
|
|
195
201
|
originalRoutePath = originalRoutePath.replace(
|
|
196
202
|
new RegExp(
|
|
197
|
-
`/(component|errorComponent|pendingComponent|loader|${config.routeToken}|lazy)$`,
|
|
203
|
+
`/(component|errorComponent|notFoundComponent|pendingComponent|loader|${config.routeToken}|lazy)$`,
|
|
198
204
|
),
|
|
199
205
|
'',
|
|
200
206
|
)
|
|
@@ -234,7 +240,20 @@ export async function getRouteNodes(
|
|
|
234
240
|
|
|
235
241
|
await recurse('./')
|
|
236
242
|
|
|
237
|
-
|
|
243
|
+
// Find the root route node - prefer the actual route file over component/loader files
|
|
244
|
+
const rootRouteNode =
|
|
245
|
+
routeNodes.find(
|
|
246
|
+
(d) =>
|
|
247
|
+
d.routePath === `/${rootPathId}` &&
|
|
248
|
+
![
|
|
249
|
+
'component',
|
|
250
|
+
'errorComponent',
|
|
251
|
+
'notFoundComponent',
|
|
252
|
+
'pendingComponent',
|
|
253
|
+
'loader',
|
|
254
|
+
'lazy',
|
|
255
|
+
].includes(d._fsRouteType),
|
|
256
|
+
) ?? routeNodes.find((d) => d.routePath === `/${rootPathId}`)
|
|
238
257
|
if (rootRouteNode) {
|
|
239
258
|
rootRouteNode._fsRouteType = '__root'
|
|
240
259
|
rootRouteNode.variableName = 'root'
|
|
@@ -270,6 +289,7 @@ export function getRouteMeta(
|
|
|
270
289
|
| 'component'
|
|
271
290
|
| 'pendingComponent'
|
|
272
291
|
| 'errorComponent'
|
|
292
|
+
| 'notFoundComponent'
|
|
273
293
|
>
|
|
274
294
|
variableName: string
|
|
275
295
|
} {
|
|
@@ -293,6 +313,9 @@ export function getRouteMeta(
|
|
|
293
313
|
} else if (routePath.endsWith('/errorComponent')) {
|
|
294
314
|
// error component routes, i.e. `/foo.errorComponent.tsx`
|
|
295
315
|
fsRouteType = 'errorComponent'
|
|
316
|
+
} else if (routePath.endsWith('/notFoundComponent')) {
|
|
317
|
+
// not found component routes, i.e. `/foo.notFoundComponent.tsx`
|
|
318
|
+
fsRouteType = 'notFoundComponent'
|
|
296
319
|
}
|
|
297
320
|
|
|
298
321
|
const variableName = routePathToVariable(routePath)
|
package/src/generator.ts
CHANGED
|
@@ -353,7 +353,7 @@ export class Generator {
|
|
|
353
353
|
: -1,
|
|
354
354
|
(d) =>
|
|
355
355
|
d.filePath.match(
|
|
356
|
-
/[./](component|errorComponent|pendingComponent|loader|lazy)[.]/,
|
|
356
|
+
/[./](component|errorComponent|notFoundComponent|pendingComponent|loader|lazy)[.]/,
|
|
357
357
|
)
|
|
358
358
|
? 1
|
|
359
359
|
: -1,
|
|
@@ -363,7 +363,20 @@ export class Generator {
|
|
|
363
363
|
: 1,
|
|
364
364
|
(d) => (d.routePath?.endsWith('/') ? -1 : 1),
|
|
365
365
|
(d) => d.routePath,
|
|
366
|
-
]).filter((d) =>
|
|
366
|
+
]).filter((d) => {
|
|
367
|
+
// Exclude the root route itself, but keep component/loader pieces for the root
|
|
368
|
+
if (d.routePath === `/${rootPathId}`) {
|
|
369
|
+
return [
|
|
370
|
+
'component',
|
|
371
|
+
'errorComponent',
|
|
372
|
+
'notFoundComponent',
|
|
373
|
+
'pendingComponent',
|
|
374
|
+
'loader',
|
|
375
|
+
'lazy',
|
|
376
|
+
].includes(d._fsRouteType)
|
|
377
|
+
}
|
|
378
|
+
return true
|
|
379
|
+
})
|
|
367
380
|
|
|
368
381
|
const routeFileAllResult = await Promise.allSettled(
|
|
369
382
|
preRouteNodes
|
|
@@ -562,6 +575,31 @@ export class Generator {
|
|
|
562
575
|
source: this.targetTemplate.fullPkg,
|
|
563
576
|
})
|
|
564
577
|
}
|
|
578
|
+
// Add lazyRouteComponent import if there are component pieces
|
|
579
|
+
const hasComponentPieces = sortedRouteNodes.some(
|
|
580
|
+
(node) =>
|
|
581
|
+
acc.routePiecesByPath[node.routePath!]?.component ||
|
|
582
|
+
acc.routePiecesByPath[node.routePath!]?.errorComponent ||
|
|
583
|
+
acc.routePiecesByPath[node.routePath!]?.notFoundComponent ||
|
|
584
|
+
acc.routePiecesByPath[node.routePath!]?.pendingComponent,
|
|
585
|
+
)
|
|
586
|
+
// Add lazyFn import if there are loader pieces
|
|
587
|
+
const hasLoaderPieces = sortedRouteNodes.some(
|
|
588
|
+
(node) => acc.routePiecesByPath[node.routePath!]?.loader,
|
|
589
|
+
)
|
|
590
|
+
if (hasComponentPieces || hasLoaderPieces) {
|
|
591
|
+
const runtimeImport: ImportDeclaration = {
|
|
592
|
+
specifiers: [],
|
|
593
|
+
source: this.targetTemplate.fullPkg,
|
|
594
|
+
}
|
|
595
|
+
if (hasComponentPieces) {
|
|
596
|
+
runtimeImport.specifiers.push({ imported: 'lazyRouteComponent' })
|
|
597
|
+
}
|
|
598
|
+
if (hasLoaderPieces) {
|
|
599
|
+
runtimeImport.specifiers.push({ imported: 'lazyFn' })
|
|
600
|
+
}
|
|
601
|
+
imports.push(runtimeImport)
|
|
602
|
+
}
|
|
565
603
|
if (config.verboseFileRoutes === false) {
|
|
566
604
|
const typeImport: ImportDeclaration = {
|
|
567
605
|
specifiers: [],
|
|
@@ -602,6 +640,8 @@ export class Generator {
|
|
|
602
640
|
const componentNode = acc.routePiecesByPath[node.routePath!]?.component
|
|
603
641
|
const errorComponentNode =
|
|
604
642
|
acc.routePiecesByPath[node.routePath!]?.errorComponent
|
|
643
|
+
const notFoundComponentNode =
|
|
644
|
+
acc.routePiecesByPath[node.routePath!]?.notFoundComponent
|
|
605
645
|
const pendingComponentNode =
|
|
606
646
|
acc.routePiecesByPath[node.routePath!]?.pendingComponent
|
|
607
647
|
const lazyComponentNode = acc.routePiecesByPath[node.routePath!]?.lazy
|
|
@@ -628,50 +668,147 @@ export class Generator {
|
|
|
628
668
|
),
|
|
629
669
|
)}'), 'loader') })`
|
|
630
670
|
: '',
|
|
631
|
-
componentNode ||
|
|
671
|
+
componentNode ||
|
|
672
|
+
errorComponentNode ||
|
|
673
|
+
notFoundComponentNode ||
|
|
674
|
+
pendingComponentNode
|
|
632
675
|
? `.update({
|
|
633
676
|
${(
|
|
634
677
|
[
|
|
635
678
|
['component', componentNode],
|
|
636
679
|
['errorComponent', errorComponentNode],
|
|
680
|
+
['notFoundComponent', notFoundComponentNode],
|
|
637
681
|
['pendingComponent', pendingComponentNode],
|
|
638
682
|
] as const
|
|
639
683
|
)
|
|
640
684
|
.filter((d) => d[1])
|
|
641
685
|
.map((d) => {
|
|
686
|
+
// For .vue files, use 'default' as the export name since Vue SFCs export default
|
|
687
|
+
const isVueFile = d[1]!.filePath.endsWith('.vue')
|
|
688
|
+
const exportName = isVueFile ? 'default' : d[0]
|
|
689
|
+
// Keep .vue extension for Vue files since Vite requires it
|
|
690
|
+
const importPath = replaceBackslash(
|
|
691
|
+
isVueFile
|
|
692
|
+
? path.relative(
|
|
693
|
+
path.dirname(config.generatedRouteTree),
|
|
694
|
+
path.resolve(
|
|
695
|
+
config.routesDirectory,
|
|
696
|
+
d[1]!.filePath,
|
|
697
|
+
),
|
|
698
|
+
)
|
|
699
|
+
: removeExt(
|
|
700
|
+
path.relative(
|
|
701
|
+
path.dirname(config.generatedRouteTree),
|
|
702
|
+
path.resolve(
|
|
703
|
+
config.routesDirectory,
|
|
704
|
+
d[1]!.filePath,
|
|
705
|
+
),
|
|
706
|
+
),
|
|
707
|
+
config.addExtensions,
|
|
708
|
+
),
|
|
709
|
+
)
|
|
642
710
|
return `${
|
|
643
711
|
d[0]
|
|
644
|
-
}: lazyRouteComponent(() => import('./${
|
|
645
|
-
removeExt(
|
|
646
|
-
path.relative(
|
|
647
|
-
path.dirname(config.generatedRouteTree),
|
|
648
|
-
path.resolve(config.routesDirectory, d[1]!.filePath),
|
|
649
|
-
),
|
|
650
|
-
config.addExtensions,
|
|
651
|
-
),
|
|
652
|
-
)}'), '${d[0]}')`
|
|
712
|
+
}: lazyRouteComponent(() => import('./${importPath}'), '${exportName}')`
|
|
653
713
|
})
|
|
654
714
|
.join('\n,')}
|
|
655
715
|
})`
|
|
656
716
|
: '',
|
|
657
717
|
lazyComponentNode
|
|
658
|
-
?
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
718
|
+
? (() => {
|
|
719
|
+
// For .vue files, use 'default' export since Vue SFCs export default
|
|
720
|
+
const isVueFile = lazyComponentNode.filePath.endsWith('.vue')
|
|
721
|
+
const exportAccessor = isVueFile ? 'd.default' : 'd.Route'
|
|
722
|
+
// Keep .vue extension for Vue files since Vite requires it
|
|
723
|
+
const importPath = replaceBackslash(
|
|
724
|
+
isVueFile
|
|
725
|
+
? path.relative(
|
|
726
|
+
path.dirname(config.generatedRouteTree),
|
|
727
|
+
path.resolve(
|
|
728
|
+
config.routesDirectory,
|
|
729
|
+
lazyComponentNode.filePath,
|
|
730
|
+
),
|
|
731
|
+
)
|
|
732
|
+
: removeExt(
|
|
733
|
+
path.relative(
|
|
734
|
+
path.dirname(config.generatedRouteTree),
|
|
735
|
+
path.resolve(
|
|
736
|
+
config.routesDirectory,
|
|
737
|
+
lazyComponentNode.filePath,
|
|
738
|
+
),
|
|
739
|
+
),
|
|
740
|
+
config.addExtensions,
|
|
741
|
+
),
|
|
742
|
+
)
|
|
743
|
+
return `.lazy(() => import('./${importPath}').then((d) => ${exportAccessor}))`
|
|
744
|
+
})()
|
|
670
745
|
: '',
|
|
671
746
|
].join(''),
|
|
672
747
|
].join('\n\n')
|
|
673
748
|
})
|
|
674
749
|
|
|
750
|
+
// Generate update for root route if it has component pieces
|
|
751
|
+
const rootRoutePath = `/${rootPathId}`
|
|
752
|
+
const rootComponentNode = acc.routePiecesByPath[rootRoutePath]?.component
|
|
753
|
+
const rootErrorComponentNode =
|
|
754
|
+
acc.routePiecesByPath[rootRoutePath]?.errorComponent
|
|
755
|
+
const rootNotFoundComponentNode =
|
|
756
|
+
acc.routePiecesByPath[rootRoutePath]?.notFoundComponent
|
|
757
|
+
const rootPendingComponentNode =
|
|
758
|
+
acc.routePiecesByPath[rootRoutePath]?.pendingComponent
|
|
759
|
+
|
|
760
|
+
let rootRouteUpdate = ''
|
|
761
|
+
if (
|
|
762
|
+
rootComponentNode ||
|
|
763
|
+
rootErrorComponentNode ||
|
|
764
|
+
rootNotFoundComponentNode ||
|
|
765
|
+
rootPendingComponentNode
|
|
766
|
+
) {
|
|
767
|
+
rootRouteUpdate = `const rootRouteWithChildren = rootRouteImport${
|
|
768
|
+
rootComponentNode ||
|
|
769
|
+
rootErrorComponentNode ||
|
|
770
|
+
rootNotFoundComponentNode ||
|
|
771
|
+
rootPendingComponentNode
|
|
772
|
+
? `.update({
|
|
773
|
+
${(
|
|
774
|
+
[
|
|
775
|
+
['component', rootComponentNode],
|
|
776
|
+
['errorComponent', rootErrorComponentNode],
|
|
777
|
+
['notFoundComponent', rootNotFoundComponentNode],
|
|
778
|
+
['pendingComponent', rootPendingComponentNode],
|
|
779
|
+
] as const
|
|
780
|
+
)
|
|
781
|
+
.filter((d) => d[1])
|
|
782
|
+
.map((d) => {
|
|
783
|
+
// For .vue files, use 'default' as the export name since Vue SFCs export default
|
|
784
|
+
const isVueFile = d[1]!.filePath.endsWith('.vue')
|
|
785
|
+
const exportName = isVueFile ? 'default' : d[0]
|
|
786
|
+
// Keep .vue extension for Vue files since Vite requires it
|
|
787
|
+
const importPath = replaceBackslash(
|
|
788
|
+
isVueFile
|
|
789
|
+
? path.relative(
|
|
790
|
+
path.dirname(config.generatedRouteTree),
|
|
791
|
+
path.resolve(config.routesDirectory, d[1]!.filePath),
|
|
792
|
+
)
|
|
793
|
+
: removeExt(
|
|
794
|
+
path.relative(
|
|
795
|
+
path.dirname(config.generatedRouteTree),
|
|
796
|
+
path.resolve(
|
|
797
|
+
config.routesDirectory,
|
|
798
|
+
d[1]!.filePath,
|
|
799
|
+
),
|
|
800
|
+
),
|
|
801
|
+
config.addExtensions,
|
|
802
|
+
),
|
|
803
|
+
)
|
|
804
|
+
return `${d[0]}: lazyRouteComponent(() => import('./${importPath}'), '${exportName}')`
|
|
805
|
+
})
|
|
806
|
+
.join('\n,')}
|
|
807
|
+
})`
|
|
808
|
+
: ''
|
|
809
|
+
}._addFileChildren(rootRouteChildren)${config.disableTypes ? '' : `._addFileTypes<FileRouteTypes>()`}`
|
|
810
|
+
}
|
|
811
|
+
|
|
675
812
|
let fileRoutesByPathInterface = ''
|
|
676
813
|
let fileRoutesByFullPath = ''
|
|
677
814
|
|
|
@@ -741,7 +878,12 @@ ${acc.routeTree.map((child) => `${child.variableName}Route: typeof ${getResolved
|
|
|
741
878
|
)
|
|
742
879
|
.join(',')}
|
|
743
880
|
}`,
|
|
744
|
-
|
|
881
|
+
rootRouteUpdate
|
|
882
|
+
? rootRouteUpdate.replace(
|
|
883
|
+
'const rootRouteWithChildren = ',
|
|
884
|
+
'export const routeTree = ',
|
|
885
|
+
)
|
|
886
|
+
: `export const routeTree = rootRouteImport._addFileChildren(rootRouteChildren)${config.disableTypes ? '' : `._addFileTypes<FileRouteTypes>()`}`,
|
|
745
887
|
].join('\n')
|
|
746
888
|
|
|
747
889
|
checkRouteFullPathUniqueness(
|
|
@@ -894,6 +1036,7 @@ ${acc.routeTree.map((child) => `${child.variableName}Route: typeof ${getResolved
|
|
|
894
1036
|
'component',
|
|
895
1037
|
'pendingComponent',
|
|
896
1038
|
'errorComponent',
|
|
1039
|
+
'notFoundComponent',
|
|
897
1040
|
'loader',
|
|
898
1041
|
] satisfies Array<FsRouteType>
|
|
899
1042
|
).every((d) => d !== node._fsRouteType)
|
|
@@ -915,32 +1058,39 @@ ${acc.routeTree.map((child) => `${child.variableName}Route: typeof ${getResolved
|
|
|
915
1058
|
return null
|
|
916
1059
|
}
|
|
917
1060
|
}
|
|
918
|
-
// transform the file
|
|
919
|
-
const transformResult = await transform({
|
|
920
|
-
source: updatedCacheEntry.fileContent,
|
|
921
|
-
ctx: {
|
|
922
|
-
target: this.config.target,
|
|
923
|
-
routeId: escapedRoutePath,
|
|
924
|
-
lazy: node._fsRouteType === 'lazy',
|
|
925
|
-
verboseFileRoutes: !(this.config.verboseFileRoutes === false),
|
|
926
|
-
},
|
|
927
|
-
node,
|
|
928
|
-
})
|
|
929
1061
|
|
|
930
|
-
if
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1062
|
+
// Check if this is a Vue component file
|
|
1063
|
+
// Vue SFC files (.vue) don't need transformation as they can't have a Route export
|
|
1064
|
+
const isVueFile = node.filePath.endsWith('.vue')
|
|
1065
|
+
|
|
1066
|
+
if (!isVueFile) {
|
|
1067
|
+
// transform the file
|
|
1068
|
+
const transformResult = await transform({
|
|
1069
|
+
source: updatedCacheEntry.fileContent,
|
|
1070
|
+
ctx: {
|
|
1071
|
+
target: this.config.target,
|
|
1072
|
+
routeId: escapedRoutePath,
|
|
1073
|
+
lazy: node._fsRouteType === 'lazy',
|
|
1074
|
+
verboseFileRoutes: !(this.config.verboseFileRoutes === false),
|
|
1075
|
+
},
|
|
1076
|
+
node,
|
|
1077
|
+
})
|
|
1078
|
+
|
|
1079
|
+
if (transformResult.result === 'no-route-export') {
|
|
1080
|
+
this.logger.warn(
|
|
1081
|
+
`Route file "${node.fullPath}" does not contain any route piece. This is likely a mistake.`,
|
|
1082
|
+
)
|
|
1083
|
+
return null
|
|
1084
|
+
}
|
|
1085
|
+
if (transformResult.result === 'error') {
|
|
1086
|
+
throw new Error(
|
|
1087
|
+
`Error transforming route file ${node.fullPath}: ${transformResult.error}`,
|
|
1088
|
+
)
|
|
1089
|
+
}
|
|
1090
|
+
if (transformResult.result === 'modified') {
|
|
1091
|
+
updatedCacheEntry.fileContent = transformResult.output
|
|
1092
|
+
shouldWriteRouteFile = true
|
|
1093
|
+
}
|
|
944
1094
|
}
|
|
945
1095
|
|
|
946
1096
|
for (const plugin of this.plugins) {
|
|
@@ -1262,6 +1412,7 @@ ${acc.routeTree.map((child) => `${child.variableName}Route: typeof ${getResolved
|
|
|
1262
1412
|
'component',
|
|
1263
1413
|
'pendingComponent',
|
|
1264
1414
|
'errorComponent',
|
|
1415
|
+
'notFoundComponent',
|
|
1265
1416
|
] satisfies Array<FsRouteType>
|
|
1266
1417
|
).some((d) => d === node._fsRouteType)
|
|
1267
1418
|
) {
|
|
@@ -1275,16 +1426,19 @@ ${acc.routeTree.map((child) => `${child.variableName}Route: typeof ${getResolved
|
|
|
1275
1426
|
? 'loader'
|
|
1276
1427
|
: node._fsRouteType === 'errorComponent'
|
|
1277
1428
|
? 'errorComponent'
|
|
1278
|
-
: node._fsRouteType === '
|
|
1279
|
-
? '
|
|
1280
|
-
: '
|
|
1429
|
+
: node._fsRouteType === 'notFoundComponent'
|
|
1430
|
+
? 'notFoundComponent'
|
|
1431
|
+
: node._fsRouteType === 'pendingComponent'
|
|
1432
|
+
? 'pendingComponent'
|
|
1433
|
+
: 'component'
|
|
1281
1434
|
] = node
|
|
1282
1435
|
|
|
1283
1436
|
const anchorRoute = acc.routeNodes.find(
|
|
1284
1437
|
(d) => d.routePath === node.routePath,
|
|
1285
1438
|
)
|
|
1286
1439
|
|
|
1287
|
-
|
|
1440
|
+
// Don't create virtual routes for root route component pieces - the root route is handled separately
|
|
1441
|
+
if (!anchorRoute && node.routePath !== `/${rootPathId}`) {
|
|
1288
1442
|
this.handleNode(
|
|
1289
1443
|
{
|
|
1290
1444
|
...node,
|
package/src/template.ts
CHANGED
|
@@ -167,6 +167,71 @@ export function getTargetTemplate(config: Config): TargetTemplate {
|
|
|
167
167
|
? 'export const Route = createLazyFileRoute('
|
|
168
168
|
: `export const Route = createLazyFileRoute('${routePath}')(`,
|
|
169
169
|
|
|
170
|
+
tsrExportEnd: () => ');',
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
}
|
|
174
|
+
case 'vue':
|
|
175
|
+
return {
|
|
176
|
+
fullPkg: '@tanstack/vue-router',
|
|
177
|
+
subPkg: 'vue-router',
|
|
178
|
+
rootRoute: {
|
|
179
|
+
template: () =>
|
|
180
|
+
[
|
|
181
|
+
'import { h } from "vue"\n',
|
|
182
|
+
'%%tsrImports%%',
|
|
183
|
+
'\n\n',
|
|
184
|
+
'%%tsrExportStart%%{\n component: RootComponent\n }%%tsrExportEnd%%\n\n',
|
|
185
|
+
'function RootComponent() { return h("div", {}, ["Hello \\"%%tsrPath%%\\"!", h(Outlet)]) };\n',
|
|
186
|
+
].join(''),
|
|
187
|
+
imports: {
|
|
188
|
+
tsrImports: () =>
|
|
189
|
+
"import { Outlet, createRootRoute } from '@tanstack/vue-router';",
|
|
190
|
+
tsrExportStart: () => 'export const Route = createRootRoute(',
|
|
191
|
+
tsrExportEnd: () => ');',
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
route: {
|
|
195
|
+
template: () =>
|
|
196
|
+
[
|
|
197
|
+
'import { h } from "vue"\n',
|
|
198
|
+
'%%tsrImports%%',
|
|
199
|
+
'\n\n',
|
|
200
|
+
'%%tsrExportStart%%{\n component: RouteComponent\n }%%tsrExportEnd%%\n\n',
|
|
201
|
+
'function RouteComponent() { return h("div", {}, "Hello \\"%%tsrPath%%\\"!") };\n',
|
|
202
|
+
].join(''),
|
|
203
|
+
imports: {
|
|
204
|
+
tsrImports: () =>
|
|
205
|
+
config.verboseFileRoutes === false
|
|
206
|
+
? ''
|
|
207
|
+
: "import { createFileRoute } from '@tanstack/vue-router';",
|
|
208
|
+
tsrExportStart: (routePath) =>
|
|
209
|
+
config.verboseFileRoutes === false
|
|
210
|
+
? 'export const Route = createFileRoute('
|
|
211
|
+
: `export const Route = createFileRoute('${routePath}')(`,
|
|
212
|
+
tsrExportEnd: () => ');',
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
lazyRoute: {
|
|
216
|
+
template: () =>
|
|
217
|
+
[
|
|
218
|
+
'import { h } from "vue"\n',
|
|
219
|
+
'%%tsrImports%%',
|
|
220
|
+
'\n\n',
|
|
221
|
+
'%%tsrExportStart%%{\n component: RouteComponent\n }%%tsrExportEnd%%\n\n',
|
|
222
|
+
'function RouteComponent() { return h("div", {}, "Hello \\"%%tsrPath%%\\"!") };\n',
|
|
223
|
+
].join(''),
|
|
224
|
+
imports: {
|
|
225
|
+
tsrImports: () =>
|
|
226
|
+
config.verboseFileRoutes === false
|
|
227
|
+
? ''
|
|
228
|
+
: "import { createLazyFileRoute } from '@tanstack/vue-router';",
|
|
229
|
+
|
|
230
|
+
tsrExportStart: (routePath) =>
|
|
231
|
+
config.verboseFileRoutes === false
|
|
232
|
+
? 'export const Route = createLazyFileRoute('
|
|
233
|
+
: `export const Route = createLazyFileRoute('${routePath}')(`,
|
|
234
|
+
|
|
170
235
|
tsrExportEnd: () => ');',
|
|
171
236
|
},
|
|
172
237
|
},
|
package/src/types.ts
CHANGED
|
@@ -33,10 +33,12 @@ export type FsRouteType =
|
|
|
33
33
|
| 'component' // @deprecated
|
|
34
34
|
| 'pendingComponent' // @deprecated
|
|
35
35
|
| 'errorComponent' // @deprecated
|
|
36
|
+
| 'notFoundComponent' // @deprecated
|
|
36
37
|
|
|
37
38
|
export type RouteSubNode = {
|
|
38
39
|
component?: RouteNode
|
|
39
40
|
errorComponent?: RouteNode
|
|
41
|
+
notFoundComponent?: RouteNode
|
|
40
42
|
pendingComponent?: RouteNode
|
|
41
43
|
loader?: RouteNode
|
|
42
44
|
lazy?: RouteNode
|