@tanstack/router-generator 1.52.0 → 1.54.0
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 +21 -19
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/config.d.cts +3 -0
- package/dist/cjs/filesystem/physical/getRouteNodes.cjs +125 -0
- package/dist/cjs/filesystem/physical/getRouteNodes.cjs.map +1 -0
- package/dist/cjs/filesystem/physical/getRouteNodes.d.cts +3 -0
- package/dist/cjs/filesystem/physical/rootPathId.cjs +5 -0
- package/dist/cjs/filesystem/physical/rootPathId.cjs.map +1 -0
- package/dist/cjs/filesystem/physical/rootPathId.d.cts +1 -0
- package/dist/cjs/filesystem/virtual/config.cjs +37 -0
- package/dist/cjs/filesystem/virtual/config.cjs.map +1 -0
- package/dist/cjs/filesystem/virtual/config.d.cts +3 -0
- package/dist/cjs/filesystem/virtual/getRouteNodes.cjs +119 -0
- package/dist/cjs/filesystem/virtual/getRouteNodes.cjs.map +1 -0
- package/dist/cjs/filesystem/virtual/getRouteNodes.d.cts +5 -0
- package/dist/cjs/generator.cjs +43 -168
- package/dist/cjs/generator.cjs.map +1 -1
- package/dist/cjs/generator.d.cts +1 -26
- package/dist/cjs/types.d.cts +27 -0
- package/dist/cjs/utils.cjs +34 -0
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +8 -0
- package/dist/esm/config.d.ts +3 -0
- package/dist/esm/config.js +2 -0
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/filesystem/physical/getRouteNodes.d.ts +3 -0
- package/dist/esm/filesystem/physical/getRouteNodes.js +108 -0
- package/dist/esm/filesystem/physical/getRouteNodes.js.map +1 -0
- package/dist/esm/filesystem/physical/rootPathId.d.ts +1 -0
- package/dist/esm/filesystem/physical/rootPathId.js +5 -0
- package/dist/esm/filesystem/physical/rootPathId.js.map +1 -0
- package/dist/esm/filesystem/virtual/config.d.ts +3 -0
- package/dist/esm/filesystem/virtual/config.js +37 -0
- package/dist/esm/filesystem/virtual/config.js.map +1 -0
- package/dist/esm/filesystem/virtual/getRouteNodes.d.ts +5 -0
- package/dist/esm/filesystem/virtual/getRouteNodes.js +119 -0
- package/dist/esm/filesystem/virtual/getRouteNodes.js.map +1 -0
- package/dist/esm/generator.d.ts +1 -26
- package/dist/esm/generator.js +29 -154
- package/dist/esm/generator.js.map +1 -1
- package/dist/esm/types.d.ts +27 -0
- package/dist/esm/utils.d.ts +8 -0
- package/dist/esm/utils.js +34 -0
- package/dist/esm/utils.js.map +1 -1
- package/package.json +3 -2
- package/src/config.ts +2 -0
- package/src/filesystem/physical/getRouteNodes.ts +151 -0
- package/src/filesystem/physical/rootPathId.ts +1 -0
- package/src/filesystem/virtual/config.ts +45 -0
- package/src/filesystem/virtual/getRouteNodes.ts +141 -0
- package/src/generator.ts +45 -239
- package/src/types.ts +28 -0
- package/src/utils.ts +43 -0
package/src/generator.ts
CHANGED
|
@@ -2,175 +2,25 @@ import path from 'node:path'
|
|
|
2
2
|
import * as fs from 'node:fs'
|
|
3
3
|
import * as fsp from 'node:fs/promises'
|
|
4
4
|
import * as prettier from 'prettier'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
determineInitialRoutePath,
|
|
7
|
+
logging,
|
|
8
|
+
removeExt,
|
|
9
|
+
removeTrailingSlash,
|
|
10
|
+
removeUnderscores,
|
|
11
|
+
replaceBackslash,
|
|
12
|
+
routePathToVariable,
|
|
13
|
+
trimPathLeft,
|
|
14
|
+
} from './utils'
|
|
15
|
+
import { getRouteNodes as physicalGetRouteNodes } from './filesystem/physical/getRouteNodes'
|
|
16
|
+
import { getRouteNodes as virtualGetRouteNodes } from './filesystem/virtual/getRouteNodes'
|
|
17
|
+
import { rootPathId } from './filesystem/physical/rootPathId'
|
|
18
|
+
import type { GetRouteNodesResult, RouteNode } from './types'
|
|
6
19
|
import type { Config } from './config'
|
|
7
20
|
|
|
8
21
|
let latestTask = 0
|
|
9
|
-
export const rootPathId = '__root'
|
|
10
22
|
const routeGroupPatternRegex = /\(.+\)/g
|
|
11
23
|
const possiblyNestedRouteGroupPatternRegex = /\([^/]+\)\/?/g
|
|
12
|
-
const disallowedRouteGroupConfiguration = /\(([^)]+)\).(ts|js|tsx|jsx)/
|
|
13
|
-
|
|
14
|
-
export type RouteNode = {
|
|
15
|
-
filePath: string
|
|
16
|
-
fullPath: string
|
|
17
|
-
variableName: string
|
|
18
|
-
routePath?: string
|
|
19
|
-
cleanedPath?: string
|
|
20
|
-
path?: string
|
|
21
|
-
isNonPath?: boolean
|
|
22
|
-
isNonLayout?: boolean
|
|
23
|
-
isLayout?: boolean
|
|
24
|
-
isVirtualParentRequired?: boolean
|
|
25
|
-
isVirtualParentRoute?: boolean
|
|
26
|
-
isRoute?: boolean
|
|
27
|
-
isAPIRoute?: boolean
|
|
28
|
-
isLoader?: boolean
|
|
29
|
-
isComponent?: boolean
|
|
30
|
-
isErrorComponent?: boolean
|
|
31
|
-
isPendingComponent?: boolean
|
|
32
|
-
isVirtual?: boolean
|
|
33
|
-
isLazy?: boolean
|
|
34
|
-
isRoot?: boolean
|
|
35
|
-
children?: Array<RouteNode>
|
|
36
|
-
parent?: RouteNode
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async function getRouteNodes(config: Config) {
|
|
40
|
-
const { routeFilePrefix, routeFileIgnorePrefix, routeFileIgnorePattern } =
|
|
41
|
-
config
|
|
42
|
-
const logger = logging({ disabled: config.disableLogging })
|
|
43
|
-
const routeFileIgnoreRegExp = new RegExp(routeFileIgnorePattern ?? '', 'g')
|
|
44
|
-
|
|
45
|
-
const routeNodes: Array<RouteNode> = []
|
|
46
|
-
|
|
47
|
-
async function recurse(dir: string) {
|
|
48
|
-
const fullDir = path.resolve(config.routesDirectory, dir)
|
|
49
|
-
let dirList = await fsp.readdir(fullDir, { withFileTypes: true })
|
|
50
|
-
|
|
51
|
-
dirList = dirList.filter((d) => {
|
|
52
|
-
if (
|
|
53
|
-
d.name.startsWith('.') ||
|
|
54
|
-
(routeFileIgnorePrefix && d.name.startsWith(routeFileIgnorePrefix))
|
|
55
|
-
) {
|
|
56
|
-
return false
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (routeFilePrefix) {
|
|
60
|
-
return d.name.startsWith(routeFilePrefix)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (routeFileIgnorePattern) {
|
|
64
|
-
return !d.name.match(routeFileIgnoreRegExp)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return true
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
await Promise.all(
|
|
71
|
-
dirList.map(async (dirent) => {
|
|
72
|
-
const fullPath = path.join(fullDir, dirent.name)
|
|
73
|
-
const relativePath = path.join(dir, dirent.name)
|
|
74
|
-
|
|
75
|
-
if (dirent.isDirectory()) {
|
|
76
|
-
await recurse(relativePath)
|
|
77
|
-
} else if (fullPath.match(/\.(tsx|ts|jsx|js)$/)) {
|
|
78
|
-
const filePath = replaceBackslash(path.join(dir, dirent.name))
|
|
79
|
-
const filePathNoExt = removeExt(filePath)
|
|
80
|
-
let routePath = determineInitialRoutePath(filePathNoExt)
|
|
81
|
-
|
|
82
|
-
if (routeFilePrefix) {
|
|
83
|
-
routePath = routePath.replaceAll(routeFilePrefix, '')
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (disallowedRouteGroupConfiguration.test(dirent.name)) {
|
|
87
|
-
const errorMessage = `A route configuration for a route group was found at \`${filePath}\`. This is not supported. Did you mean to use a layout/pathless route instead?`
|
|
88
|
-
logger.error(`ERROR: ${errorMessage}`)
|
|
89
|
-
throw new Error(errorMessage)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const variableName = routePathToVariable(routePath)
|
|
93
|
-
|
|
94
|
-
// Remove the index from the route path and
|
|
95
|
-
// if the route path is empty, use `/'
|
|
96
|
-
|
|
97
|
-
const isLazy = routePath.endsWith('/lazy')
|
|
98
|
-
|
|
99
|
-
if (isLazy) {
|
|
100
|
-
routePath = routePath.replace(/\/lazy$/, '')
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const isRoute = routePath.endsWith(`/${config.routeToken}`)
|
|
104
|
-
const isComponent = routePath.endsWith('/component')
|
|
105
|
-
const isErrorComponent = routePath.endsWith('/errorComponent')
|
|
106
|
-
const isPendingComponent = routePath.endsWith('/pendingComponent')
|
|
107
|
-
const isLoader = routePath.endsWith('/loader')
|
|
108
|
-
const isAPIRoute = routePath.startsWith(
|
|
109
|
-
`${removeTrailingSlash(config.apiBase)}/`,
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
const segments = routePath.split('/')
|
|
113
|
-
const lastRouteSegment = segments[segments.length - 1]
|
|
114
|
-
const isLayout =
|
|
115
|
-
(lastRouteSegment !== config.indexToken &&
|
|
116
|
-
lastRouteSegment !== config.routeToken &&
|
|
117
|
-
lastRouteSegment?.startsWith('_')) ||
|
|
118
|
-
false
|
|
119
|
-
|
|
120
|
-
;(
|
|
121
|
-
[
|
|
122
|
-
[isComponent, 'component'],
|
|
123
|
-
[isErrorComponent, 'errorComponent'],
|
|
124
|
-
[isPendingComponent, 'pendingComponent'],
|
|
125
|
-
[isLoader, 'loader'],
|
|
126
|
-
] as const
|
|
127
|
-
).forEach(([isType, type]) => {
|
|
128
|
-
if (isType) {
|
|
129
|
-
logger.warn(
|
|
130
|
-
`WARNING: The \`.${type}.tsx\` suffix used for the ${filePath} file is deprecated. Use the new \`.lazy.tsx\` suffix instead.`,
|
|
131
|
-
)
|
|
132
|
-
}
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
routePath = routePath.replace(
|
|
136
|
-
new RegExp(
|
|
137
|
-
`/(component|errorComponent|pendingComponent|loader|${config.routeToken}|lazy)$`,
|
|
138
|
-
),
|
|
139
|
-
'',
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
if (routePath === config.indexToken) {
|
|
143
|
-
routePath = '/'
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
routePath =
|
|
147
|
-
routePath.replace(new RegExp(`/${config.indexToken}$`), '/') || '/'
|
|
148
|
-
|
|
149
|
-
routeNodes.push({
|
|
150
|
-
filePath,
|
|
151
|
-
fullPath,
|
|
152
|
-
routePath,
|
|
153
|
-
variableName,
|
|
154
|
-
isRoute,
|
|
155
|
-
isComponent,
|
|
156
|
-
isErrorComponent,
|
|
157
|
-
isPendingComponent,
|
|
158
|
-
isLoader,
|
|
159
|
-
isLazy,
|
|
160
|
-
isLayout,
|
|
161
|
-
isAPIRoute,
|
|
162
|
-
})
|
|
163
|
-
}
|
|
164
|
-
}),
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
return routeNodes
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
await recurse('./')
|
|
171
|
-
|
|
172
|
-
return routeNodes
|
|
173
|
-
}
|
|
174
24
|
|
|
175
25
|
let isFirst = false
|
|
176
26
|
let skipMessage = false
|
|
@@ -216,12 +66,18 @@ export async function generator(config: Config) {
|
|
|
216
66
|
parser: 'typescript',
|
|
217
67
|
}
|
|
218
68
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
69
|
+
let getRouteNodesResult: GetRouteNodesResult
|
|
70
|
+
|
|
71
|
+
if (config.virtualRouteConfig) {
|
|
72
|
+
getRouteNodesResult = await virtualGetRouteNodes(config)
|
|
73
|
+
} else {
|
|
74
|
+
getRouteNodesResult = await physicalGetRouteNodes(config)
|
|
75
|
+
}
|
|
224
76
|
|
|
77
|
+
const { rootRouteNode, routeNodes: beforeRouteNodes } = getRouteNodesResult
|
|
78
|
+
if (rootRouteNode === undefined) {
|
|
79
|
+
throw new Error(`rootRouteNode must not be undefined`)
|
|
80
|
+
}
|
|
225
81
|
const preRouteNodes = multiSortBy(beforeRouteNodes, [
|
|
226
82
|
(d) => (d.routePath === '/' ? -1 : 1),
|
|
227
83
|
(d) => d.routePath?.split('/').length,
|
|
@@ -307,13 +163,11 @@ export const Route = createRootRoute({
|
|
|
307
163
|
const trimmedPath = trimPathLeft(node.path ?? '')
|
|
308
164
|
|
|
309
165
|
const split = trimmedPath.split('/')
|
|
310
|
-
const first = split[0] ?? trimmedPath
|
|
311
166
|
const lastRouteSegment = split[split.length - 1] ?? trimmedPath
|
|
312
167
|
|
|
313
168
|
node.isNonPath =
|
|
314
169
|
lastRouteSegment.startsWith('_') ||
|
|
315
170
|
routeGroupPatternRegex.test(lastRouteSegment)
|
|
316
|
-
node.isNonLayout = first.endsWith('_')
|
|
317
171
|
|
|
318
172
|
node.cleanedPath = removeGroups(
|
|
319
173
|
removeUnderscores(removeLayoutSegments(node.path)) ?? '',
|
|
@@ -571,11 +425,18 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
571
425
|
.map((d) => d[0])
|
|
572
426
|
|
|
573
427
|
const virtualRouteNodes = sortedRouteNodes.filter((d) => d.isVirtual)
|
|
574
|
-
const rootPathIdExtension =
|
|
575
|
-
config.addExtensions && rootRouteNode
|
|
576
|
-
? path.extname(rootRouteNode.filePath)
|
|
577
|
-
: ''
|
|
578
428
|
|
|
429
|
+
function getImportPath(node: RouteNode) {
|
|
430
|
+
return replaceBackslash(
|
|
431
|
+
removeExt(
|
|
432
|
+
path.relative(
|
|
433
|
+
path.dirname(config.generatedRouteTree),
|
|
434
|
+
path.resolve(config.routesDirectory, node.filePath),
|
|
435
|
+
),
|
|
436
|
+
config.addExtensions,
|
|
437
|
+
),
|
|
438
|
+
)
|
|
439
|
+
}
|
|
579
440
|
const routeImports = [
|
|
580
441
|
...config.routeTreeFileHeader,
|
|
581
442
|
'// This file is auto-generated by TanStack Router',
|
|
@@ -584,29 +445,13 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
584
445
|
: '',
|
|
585
446
|
'// Import Routes',
|
|
586
447
|
[
|
|
587
|
-
`import { Route as rootRoute } from './${
|
|
588
|
-
path.relative(
|
|
589
|
-
path.dirname(config.generatedRouteTree),
|
|
590
|
-
path.resolve(
|
|
591
|
-
config.routesDirectory,
|
|
592
|
-
`${routePathIdPrefix}${rootPathId}${rootPathIdExtension}`,
|
|
593
|
-
),
|
|
594
|
-
),
|
|
595
|
-
)}'`,
|
|
448
|
+
`import { Route as rootRoute } from './${getImportPath(rootRouteNode)}'`,
|
|
596
449
|
...sortedRouteNodes
|
|
597
450
|
.filter((d) => !d.isVirtual)
|
|
598
451
|
.map((node) => {
|
|
599
452
|
return `import { Route as ${
|
|
600
453
|
node.variableName
|
|
601
|
-
}Import } from './${
|
|
602
|
-
removeExt(
|
|
603
|
-
path.relative(
|
|
604
|
-
path.dirname(config.generatedRouteTree),
|
|
605
|
-
path.resolve(config.routesDirectory, node.filePath),
|
|
606
|
-
),
|
|
607
|
-
config.addExtensions,
|
|
608
|
-
),
|
|
609
|
-
)}'`
|
|
454
|
+
}Import } from './${getImportPath(node)}'`
|
|
610
455
|
}),
|
|
611
456
|
].join('\n'),
|
|
612
457
|
virtualRouteNodes.length ? '// Create Virtual Routes' : '',
|
|
@@ -704,7 +549,7 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
704
549
|
${routeNodes
|
|
705
550
|
.map((routeNode) => {
|
|
706
551
|
const [filePathId, routeId] = getFilePathIdAndRouteIdFromPath(
|
|
707
|
-
routeNode.routePath
|
|
552
|
+
routeNode.routePath,
|
|
708
553
|
)
|
|
709
554
|
|
|
710
555
|
return `'${filePathId}': {
|
|
@@ -735,14 +580,14 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
735
580
|
const createRouteManifest = () => {
|
|
736
581
|
const routesManifest = {
|
|
737
582
|
__root__: {
|
|
738
|
-
filePath: rootRouteNode
|
|
583
|
+
filePath: rootRouteNode.filePath,
|
|
739
584
|
children: routeTree.map(
|
|
740
|
-
(d) => getFilePathIdAndRouteIdFromPath(d.routePath
|
|
585
|
+
(d) => getFilePathIdAndRouteIdFromPath(d.routePath)[1],
|
|
741
586
|
),
|
|
742
587
|
},
|
|
743
588
|
...Object.fromEntries(
|
|
744
589
|
routeNodes.map((d) => {
|
|
745
|
-
const [_, routeId] = getFilePathIdAndRouteIdFromPath(d.routePath
|
|
590
|
+
const [_, routeId] = getFilePathIdAndRouteIdFromPath(d.routePath)
|
|
746
591
|
|
|
747
592
|
return [
|
|
748
593
|
routeId,
|
|
@@ -753,7 +598,7 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
753
598
|
: undefined,
|
|
754
599
|
children: d.children?.map(
|
|
755
600
|
(childRoute) =>
|
|
756
|
-
getFilePathIdAndRouteIdFromPath(childRoute.routePath
|
|
601
|
+
getFilePathIdAndRouteIdFromPath(childRoute.routePath)[1],
|
|
757
602
|
),
|
|
758
603
|
},
|
|
759
604
|
]
|
|
@@ -820,24 +665,6 @@ export const Route = createAPIFileRoute('${escapedRoutePath}')({
|
|
|
820
665
|
)
|
|
821
666
|
}
|
|
822
667
|
|
|
823
|
-
function routePathToVariable(routePath: string): string {
|
|
824
|
-
return (
|
|
825
|
-
removeUnderscores(routePath)
|
|
826
|
-
?.replace(/\/\$\//g, '/splat/')
|
|
827
|
-
.replace(/\$$/g, 'splat')
|
|
828
|
-
.replace(/\$/g, '')
|
|
829
|
-
.split(/[/-]/g)
|
|
830
|
-
.map((d, i) => (i > 0 ? capitalize(d) : d))
|
|
831
|
-
.join('')
|
|
832
|
-
.replace(/([^a-zA-Z0-9]|[.])/gm, '')
|
|
833
|
-
.replace(/^(\d)/g, 'R$1') ?? ''
|
|
834
|
-
)
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
export function removeExt(d: string, keepExtension: boolean = false) {
|
|
838
|
-
return keepExtension ? d : d.substring(0, d.lastIndexOf('.')) || d
|
|
839
|
-
}
|
|
840
|
-
|
|
841
668
|
function spaces(d: number): string {
|
|
842
669
|
return Array.from({ length: d })
|
|
843
670
|
.map(() => ' ')
|
|
@@ -874,35 +701,14 @@ export function multiSortBy<T>(
|
|
|
874
701
|
.map(([d]) => d)
|
|
875
702
|
}
|
|
876
703
|
|
|
877
|
-
function capitalize(s: string) {
|
|
878
|
-
if (typeof s !== 'string') return ''
|
|
879
|
-
return s.charAt(0).toUpperCase() + s.slice(1)
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
function removeUnderscores(s?: string) {
|
|
883
|
-
return s?.replaceAll(/(^_|_$)/gi, '').replaceAll(/(\/_|_\/)/gi, '/')
|
|
884
|
-
}
|
|
885
|
-
|
|
886
704
|
function removeTrailingUnderscores(s?: string) {
|
|
887
705
|
return s?.replaceAll(/(_$)/gi, '').replaceAll(/(_\/)/gi, '/')
|
|
888
706
|
}
|
|
889
707
|
|
|
890
|
-
function replaceBackslash(s: string) {
|
|
891
|
-
return s.replaceAll(/\\/gi, '/')
|
|
892
|
-
}
|
|
893
|
-
|
|
894
708
|
function removeGroups(s: string) {
|
|
895
709
|
return s.replace(possiblyNestedRouteGroupPatternRegex, '')
|
|
896
710
|
}
|
|
897
711
|
|
|
898
|
-
function removeTrailingSlash(s: string) {
|
|
899
|
-
return s.replace(/\/$/, '')
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
function determineInitialRoutePath(routePath: string) {
|
|
903
|
-
return cleanPath(`/${routePath.split('.').join('/')}`) || ''
|
|
904
|
-
}
|
|
905
|
-
|
|
906
712
|
/**
|
|
907
713
|
* The `node.path` is used as the `id` in the route definition.
|
|
908
714
|
* This function checks if the given node has a parent and if so, it determines the correct path for the given node.
|
|
@@ -911,7 +717,7 @@ function determineInitialRoutePath(routePath: string) {
|
|
|
911
717
|
*/
|
|
912
718
|
function determineNodePath(node: RouteNode) {
|
|
913
719
|
return (node.path = node.parent
|
|
914
|
-
? node.routePath?.replace(node.parent.routePath
|
|
720
|
+
? node.routePath?.replace(node.parent.routePath ?? '', '') || '/'
|
|
915
721
|
: node.routePath)
|
|
916
722
|
}
|
|
917
723
|
|
|
@@ -995,7 +801,7 @@ export const inferPath = (routeNode: RouteNode): string => {
|
|
|
995
801
|
: (routeNode.cleanedPath?.replace(/\/$/, '') ?? '')
|
|
996
802
|
}
|
|
997
803
|
|
|
998
|
-
function getFilePathIdAndRouteIdFromPath(pathname
|
|
804
|
+
function getFilePathIdAndRouteIdFromPath(pathname?: string) {
|
|
999
805
|
const filePathId = removeTrailingUnderscores(pathname)
|
|
1000
806
|
const id = removeGroups(filePathId ?? '')
|
|
1001
807
|
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type RouteNode = {
|
|
2
|
+
filePath: string
|
|
3
|
+
fullPath: string
|
|
4
|
+
variableName: string
|
|
5
|
+
routePath?: string
|
|
6
|
+
cleanedPath?: string
|
|
7
|
+
path?: string
|
|
8
|
+
isNonPath?: boolean
|
|
9
|
+
isLayout?: boolean
|
|
10
|
+
isVirtualParentRequired?: boolean
|
|
11
|
+
isVirtualParentRoute?: boolean
|
|
12
|
+
isRoute?: boolean
|
|
13
|
+
isAPIRoute?: boolean
|
|
14
|
+
isLoader?: boolean
|
|
15
|
+
isComponent?: boolean
|
|
16
|
+
isErrorComponent?: boolean
|
|
17
|
+
isPendingComponent?: boolean
|
|
18
|
+
isVirtual?: boolean
|
|
19
|
+
isLazy?: boolean
|
|
20
|
+
isRoot?: boolean
|
|
21
|
+
children?: Array<RouteNode>
|
|
22
|
+
parent?: RouteNode
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface GetRouteNodesResult {
|
|
26
|
+
rootRouteNode?: RouteNode
|
|
27
|
+
routeNodes: Array<RouteNode>
|
|
28
|
+
}
|
package/src/utils.ts
CHANGED
|
@@ -26,3 +26,46 @@ export function logging(config: { disabled: boolean }) {
|
|
|
26
26
|
},
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
|
|
30
|
+
export function removeLeadingSlash(path: string): string {
|
|
31
|
+
return path.replace(/^\//, '')
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function removeTrailingSlash(s: string) {
|
|
35
|
+
return s.replace(/\/$/, '')
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function determineInitialRoutePath(routePath: string) {
|
|
39
|
+
return cleanPath(`/${routePath.split('.').join('/')}`) || ''
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function replaceBackslash(s: string) {
|
|
43
|
+
return s.replaceAll(/\\/gi, '/')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function routePathToVariable(routePath: string): string {
|
|
47
|
+
return (
|
|
48
|
+
removeUnderscores(routePath)
|
|
49
|
+
?.replace(/\/\$\//g, '/splat/')
|
|
50
|
+
.replace(/\$$/g, 'splat')
|
|
51
|
+
.replace(/\$/g, '')
|
|
52
|
+
.split(/[/-]/g)
|
|
53
|
+
.map((d, i) => (i > 0 ? capitalize(d) : d))
|
|
54
|
+
.join('')
|
|
55
|
+
.replace(/([^a-zA-Z0-9]|[.])/gm, '')
|
|
56
|
+
.replace(/^(\d)/g, 'R$1') ?? ''
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function removeUnderscores(s?: string) {
|
|
61
|
+
return s?.replaceAll(/(^_|_$)/gi, '').replaceAll(/(\/_|_\/)/gi, '/')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function capitalize(s: string) {
|
|
65
|
+
if (typeof s !== 'string') return ''
|
|
66
|
+
return s.charAt(0).toUpperCase() + s.slice(1)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function removeExt(d: string, keepExtension: boolean = false) {
|
|
70
|
+
return keepExtension ? d : d.substring(0, d.lastIndexOf('.')) || d
|
|
71
|
+
}
|