-
Notifications
You must be signed in to change notification settings - Fork 0
/
generate-remix-routes.ts
109 lines (94 loc) · 2.98 KB
/
generate-remix-routes.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { readConfig } from '@remix-run/dev/dist/config.js'
import type { ConfigRoute, RouteManifest } from '@remix-run/dev/dist/config/routes.js'
import { writeFileSync } from 'fs'
import { format, resolveConfig } from 'prettier'
const outputPath = `routes.ts`
function buildPath(routes: RouteManifest, route: ConfigRoute): string {
const result = []
if (route.parentId) {
result.push(buildPath(routes, routes[route.parentId]))
}
if (route.path) {
result.push(route.path)
}
return result.join('/')
}
function buildParams(path: string, input: boolean = false) {
return path
.replace(/'/g, '')
.split('/')
.filter((part) => part.startsWith(':'))
.map((part) => part.replace(':', ''))
.map(
(param) =>
`${param}: string${input ? ' | number' : ''}${param.endsWith('?') ? ' | undefined' : ''}`,
)
.join(',')
}
;(async () => {
const { routes } = await readConfig()
const paths = [
...new Set(
Object.keys(routes).map((key) => {
let path = buildPath(routes, routes[key])
if (path === '') {
path = '/'
}
return `'${path}'`
}),
),
]
const content = `
export const routerPaths = {${paths
.map((path) => {
if (!path.includes('/:')) {
return `${path}: ${path}`
}
return `${path}(params: {${buildParams(path, true)}}) {
return buildPath(${path}, params)
}`
})
.join(',')}} as const
export const unsafeRouterPaths = {${paths
.map((path) => {
return `${path}(params: Record<string, unknown>) {
return unsafeBuildPath(${path}, params)
}`
})
.join(',')}} as const
export type RouterPath = keyof typeof routerPaths
export type RouterParams = {${paths.map((path) => `${path}: {${buildParams(path)}}`).join(',')}}
type InputParams = {${paths.map((path) => `${path}: {${buildParams(path, true)}}`).join(',')}}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function buildPath<TRouterPath extends RouterPath>(route: TRouterPath, params: InputParams[TRouterPath]) {
return route
.replace(/'/g, '')
.split('/')
.map((part) =>
part.startsWith(':') ? params[part.replace(':', '').replace('?', '') as keyof InputParams[TRouterPath]] : part,
)
.filter((part) => part !== undefined)
.join('/')
}
function unsafeBuildPath<TRouterPath extends RouterPath>(
route: TRouterPath,
params: Record<string, unknown>,
) {
return route
.replace(/'/g, '')
.split('/')
.map((part) => (part.startsWith(':') ? params[part.replace(':', '').replace('?', '')] : part))
.filter((part) => part !== undefined)
.join('/')
}
`
try {
const formatted = await format(content, {
...(await resolveConfig(process.cwd())),
parser: 'typescript',
})
writeFileSync(outputPath, formatted)
} catch (err) {
console.log(content)
}
})()