Skip to content

Commit 983d144

Browse files
committed
feat: Save routeManifest with KnownRoutes type during yarn link-routes
1 parent 620a871 commit 983d144

File tree

3 files changed

+50
-6
lines changed

3 files changed

+50
-6
lines changed

packages/@aetherspace/navigation/AetherLink/AetherLink.types.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { ComponentProps } from 'react'
22
import { Text } from 'react-native'
33
// Schemas
44
import { TAetherStyleProps } from '../../schemas/ats'
5+
// Types
6+
import type { KnownRoutes } from 'registries/routeManifest'
57

68
/* --- Types ----------------------------------------------------------------------------------- */
79

@@ -16,17 +18,17 @@ export type AetherLinkBaseType = Partial<ComponentProps<typeof Text>> &
1618
}
1719

1820
export type AetherLinkToType = AetherLinkBaseType & {
19-
to: string
21+
to: KnownRoutes
2022
href?: never
2123
routeName?: never
2224
}
2325
export type AetherLinkHrefType = AetherLinkBaseType & {
24-
href: string
26+
href: KnownRoutes
2527
to?: never
2628
routeName?: never
2729
}
2830
export type AetherLinkRouteType = AetherLinkBaseType & {
29-
routeName: string
31+
routeName: KnownRoutes
3032
to?: never
3133
href?: never
3234
}

packages/@aetherspace/scripts/link-routes.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,21 @@ import { excludeDirs, parseWorkspaces } from './helpers/scriptUtils'
77

88
const genMsg = `// -i- Automatically generated by 'yarn link-routes', do not modify manually`
99

10+
const manifestTemplate = `${genMsg}
11+
export const routeManifest = {
12+
{{routeManifestLines}}
13+
} as const
14+
15+
export type KnownRoutes = keyof typeof routeManifest | (string & {})
16+
`
17+
1018
/* --- link-routes ----------------------------------------------------------------------------- */
1119

1220
const linkRoutes = () => {
1321
try {
22+
// Keep track of routes to save manifest
23+
const routeManifest = {}
24+
1425
// Get all route paths in the features & package folders
1526
const packageRoutePaths = glob.sync('../../packages/**/routes/**/*.{ts,tsx}').filter(excludeDirs) // prettier-ignore
1627
const featureRoutePaths = glob.sync('../../features/**/routes/**/*.{ts,tsx}').filter(excludeDirs) // prettier-ignore
@@ -34,6 +45,7 @@ const linkRoutes = () => {
3445

3546
// Parse & match each route path to a workspace import
3647
const parsePath = (pth, autoDefault = true) => {
48+
let screenComponentName = ''
3749
// Figure out the workspace import
3850
const [packageParts, routeParts] = pth.split('/routes') as [string, string]
3951
const workspaceMatcher = packageParts.replace('../../', '')
@@ -43,6 +55,13 @@ const linkRoutes = () => {
4355
const expoExports = autoDefault ? ['default'] : ([] as string[])
4456
if ([...indexRoutes, ...paramRoutes, ...apiRoutes].includes(pth)) {
4557
const routeFile = fs.readFileSync(pth, 'utf8')
58+
// Keep track of which Screen component is used?
59+
if (routeFile.includes('screen={'))
60+
screenComponentName = routeFile.split('screen={')[1].split('}')[0]
61+
if (routeFile.includes('ScreenComponent'))
62+
screenComponentName = routeFile.split('ScreenComponent')[1].split('=')[1].split('\n')[0].trim() // prettier-ignore
63+
if (screenComponentName.includes('.'))
64+
screenComponentName = screenComponentName.split('.').pop() as string
4665
// Always check if there's a default export when autoDefault is false
4766
if (!autoDefault && routeFile.includes('default')) nextExports.push('next')
4867
// Next.js Route Segment Config Exports
@@ -68,7 +87,7 @@ const linkRoutes = () => {
6887
if (routeFile.includes('size')) nextExports.push('size')
6988
}
7089
// Return everything
71-
return { workspacePackageName, routeParts, nextExports, expoExports }
90+
return { workspacePackageName, routeParts, nextExports, expoExports, screenComponentName }
7291
}
7392
// Clear previous generated route files
7493
fs.mkdirSync('../../apps/expo/app/(generated)', { recursive: true }) // create empty folder if it doesn't exist
@@ -81,8 +100,9 @@ const linkRoutes = () => {
81100

82101
// Reexport fs based index routing in next & expo app dirs
83102
indexRoutes.forEach((pth) => {
84-
const { workspacePackageName, routeParts, nextExports, expoExports } = parsePath(pth)
103+
const { workspacePackageName, routeParts, nextExports, expoExports, screenComponentName } = parsePath(pth) // prettier-ignore
85104
const routeSegments = routeParts.split('index.ts')[0]
105+
if (screenComponentName) routeManifest[routeSegments] = screenComponentName
86106
const importPath = `${workspacePackageName}/routes${routeSegments}index`
87107
const expoExportLine = `${genMsg}\nexport { ${expoExports.join(', ')} } from '${importPath}'\n` // prettier-ignore
88108
const nextExportLine = `'use client'\nexport { ${nextExports.join(', ')} } from '${importPath}'\n` // prettier-ignore
@@ -96,10 +116,11 @@ const linkRoutes = () => {
96116
})
97117
// Reexport fs based slug routing in next & expo app dirs
98118
paramRoutes.forEach((pth) => {
99-
const { workspacePackageName, routeParts, nextExports, expoExports } = parsePath(pth)
119+
const { workspacePackageName, routeParts, nextExports, expoExports, screenComponentName } = parsePath(pth) // prettier-ignore
100120
const fileName = routeParts.split('/').pop() as string // e.g. "[slug].tsx"
101121
const routeParam = fileName.split('.ts')[0] // e.g. "[slug]"
102122
const routeSegments = routeParts.split(fileName)[0]
123+
if (screenComponentName) routeManifest[routeSegments] = screenComponentName
103124
const importPath = `${workspacePackageName}/routes${routeSegments}${routeParam}`
104125
const expoExportLine = `export { ${expoExports.join(', ')} } from '${importPath}'\n`
105126
const nextExportLine = `'use client'\n${genMsg}\nexport { ${nextExports.join(', ')} } from '${importPath}'\n` // prettier-ignore
@@ -233,6 +254,15 @@ const linkRoutes = () => {
233254
console.log(` ✅ ${routeSegments} -- API Route from "${pth}"`)
234255
console.log(` └── /apps/next/app/(generated)${routeSegments}route.ts`)
235256
})
257+
258+
// Save route manifest
259+
const routeManifestPath = '../../packages/@registries/routeManifest.ts'
260+
const routeManifestLines = Object.entries(routeManifest).map(([route, compName]) => {
261+
const routePath = route === '/' ? '/' : route.substring(0, route.length - 1) // prettier-ignore
262+
return ` ['${routePath}']: '${compName}',`
263+
}).join('\n') // prettier-ignore
264+
const routeManifestFile = manifestTemplate.replace('{{routeManifestLines}}', routeManifestLines) // prettier-ignore
265+
fs.writeFileSync(routeManifestPath, routeManifestFile)
236266
} catch (err) {
237267
console.log(err)
238268
console.error(err)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// -i- Automatically generated by 'yarn link-routes', do not modify manually
2+
export const routeManifest = {
3+
['/bio']: 'BioScreen',
4+
['/cv']: 'ResumeScreen',
5+
['/']: 'BioScreen',
6+
['/links']: 'BioScreen',
7+
['/resume']: 'ResumeScreen',
8+
['/cv/[slug]']: 'ResumeScreen',
9+
['/resume/[slug]']: 'ResumeScreen',
10+
} as const
11+
12+
export type KnownRoutes = keyof typeof routeManifest | (string & {})

0 commit comments

Comments
 (0)