Skip to content

Commit ab16639

Browse files
authored
fix: route ids were merged incorrectly (#125)
1 parent c40ca54 commit ab16639

File tree

4 files changed

+65
-42
lines changed

4 files changed

+65
-42
lines changed

src/build.ts

+9-10
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ interface Options {
1111
}
1212

1313
type RoutesInfo = Record<string, {
14-
id: string;
1514
fileName: string;
1615
params: string[];
1716
}>
1817

1918
export const DEFAULT_OUTPUT_DIR_PATH = './.react-router/types'
2019

21-
async function buildHelpers(config: RequiredReactRouterConfig): Promise<RoutesInfo> {
20+
async function buildHelpers(config: RequiredReactRouterConfig): Promise<[RoutesInfo, string[]]> {
2221
const routesInfo: RoutesInfo = {};
22+
const routeIds: string[] = [];
2323
const handleRoutesRecursive = (
2424
parentId?: string,
2525
parentPath: RouteManifestEntry[] = [],
@@ -29,9 +29,9 @@ async function buildHelpers(config: RequiredReactRouterConfig): Promise<RoutesIn
2929
);
3030
routes.forEach((route) => {
3131
let currentPath = parentPath;
32+
routeIds.push(route.id);
3233
if (route.id === 'root') {
3334
routesInfo['/'] = {
34-
id: route.id,
3535
fileName: route.file,
3636
params: [],
3737
};
@@ -46,7 +46,6 @@ async function buildHelpers(config: RequiredReactRouterConfig): Promise<RoutesIn
4646
// account optional segments that aren't params/dynamic.
4747
for (const pathVariant of expandOptionalStaticSegments(fullPath)) {
4848
routesInfo[pathVariant] = {
49-
id: route.id,
5049
fileName: route.file,
5150
params: paramsNames
5251
};
@@ -56,7 +55,7 @@ async function buildHelpers(config: RequiredReactRouterConfig): Promise<RoutesIn
5655
});
5756
};
5857
handleRoutesRecursive();
59-
return routesInfo;
58+
return [routesInfo, routeIds];
6059
}
6160

6261
function expandOptionalStaticSegments(path: string) {
@@ -80,11 +79,11 @@ function expandOptionalStaticSegments(path: string) {
8079
}
8180

8281
export async function build(root: string, config: RequiredReactRouterConfig, options: Options) {
83-
const routesInfo = await buildHelpers(config);
84-
generate(root, config, routesInfo, options);
82+
const [routesInfo, routeIds] = await buildHelpers(config);
83+
generate(root, config, routesInfo, routeIds, options);
8584
}
8685

87-
function generate(root: string, config: RequiredReactRouterConfig, routesInfo: RoutesInfo, options: Options) {
86+
function generate(root: string, config: RequiredReactRouterConfig, routesInfo: RoutesInfo, routeIds: string[], options: Options) {
8887
const outputPath = path.join(
8988
root,
9089
options.outputDirPath,
@@ -93,8 +92,8 @@ function generate(root: string, config: RequiredReactRouterConfig, routesInfo: R
9392
const tsCode = template({
9493
strict: options.strict,
9594
relativeAppDirPath,
96-
routes: Object.entries(routesInfo).map(([route, { id, fileName, params }]) => ({
97-
id,
95+
routeIds,
96+
routes: Object.entries(routesInfo).map(([route, { fileName, params }]) => ({
9897
route,
9998
params,
10099
fileName: slash(fileName.replace(/\.tsx?$/, '')),

src/template.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
interface Context {
22
strict?: boolean;
33
relativeAppDirPath: string;
4+
routeIds: string[];
45
routes: Array<{
5-
id: string,
66
route: string;
77
params: string[];
88
fileName: string;
@@ -21,9 +21,8 @@ function exportedQuery(ctx: Context) {
2121
}
2222

2323
function routes(ctx: Context) {
24-
const routes = ctx.routes.map(({ id, route, params, fileName }) =>
24+
const routes = ctx.routes.map(({ route, params, fileName }) =>
2525
`"${route}": {
26-
id: '${id}',
2726
params: ${params.length > 0 ? `{${params.map(param => `${param}: string | number`).join('; ')}}` : 'never'},
2827
query: ExportedQuery<import('${ctx.relativeAppDirPath}/${fileName}').SearchParams>,
2928
}`
@@ -34,6 +33,11 @@ function routes(ctx: Context) {
3433
}`
3534
}
3635

36+
function routeIds(ctx: Context) {
37+
return `export type RouteId =
38+
| ${ctx.routeIds.map(routeId => `'${routeId}'`).join(`\n${indent(6)}| `)};`;
39+
}
40+
3741
export function template(ctx: Context) {
3842
return `declare module "safe-routes" {
3943
type URLSearchParamsInit = string | string[][] | Record<string, string> | URLSearchParams;
@@ -51,7 +55,7 @@ export function template(ctx: Context) {
5155
}[keyof Routes]
5256
>;
5357
54-
export type RouteId = Routes[keyof Routes]['id'];
58+
${routeIds(ctx)}
5559
5660
export function $path<
5761
Route extends keyof Routes,

tests/__snapshots__/build.test.ts.snap

+36-28
Original file line numberDiff line numberDiff line change
@@ -10,137 +10,114 @@ exports[`gen route types 1`] = `
1010
1111
export interface Routes {
1212
"/": {
13-
id: 'root',
1413
params: never,
1514
query: ExportedQuery<import('../app/root').SearchParams>,
1615
},
1716
"/:lang?/about": {
18-
id: 'routes/($lang).about',
1917
params: {lang?: string | number},
2018
query: ExportedQuery<import('../app/routes/($lang).about').SearchParams>,
2119
},
2220
"/admin": {
23-
id: 'routes/admin._index',
2421
params: never,
2522
query: ExportedQuery<import('../app/routes/admin._index').SearchParams>,
2623
},
2724
"/admin/episodes": {
28-
id: 'routes/admin.episodes._index',
2925
params: never,
3026
query: ExportedQuery<import('../app/routes/admin.episodes._index').SearchParams>,
3127
},
3228
"/admin/episodes/:id": {
33-
id: 'routes/admin.episodes.$id._index',
3429
params: {id: string | number},
3530
query: ExportedQuery<import('../app/routes/admin.episodes.$id._index').SearchParams>,
3631
},
3732
"/admin/episodes/:id/comments": {
38-
id: 'routes/admin.episodes.$id.comments',
3933
params: {id: string | number},
4034
query: ExportedQuery<import('../app/routes/admin.episodes.$id.comments').SearchParams>,
4135
},
4236
"/admin/episodes/new": {
43-
id: 'routes/admin.episodes.new',
4437
params: never,
4538
query: ExportedQuery<import('../app/routes/admin.episodes.new').SearchParams>,
4639
},
4740
"/api/:id.json": {
48-
id: 'routes/api.$id[.]json',
4941
params: {id: string | number},
5042
query: ExportedQuery<import('../app/routes/api.$id[.]json').SearchParams>,
5143
},
5244
"/auth": {
53-
id: 'routes/auth._auth',
5445
params: never,
5546
query: ExportedQuery<import('../app/routes/auth._auth').SearchParams>,
5647
},
5748
"/auth/login": {
58-
id: 'routes/auth._auth.login',
5949
params: never,
6050
query: ExportedQuery<import('../app/routes/auth._auth.login').SearchParams>,
6151
},
52+
"/blog": {
53+
params: never,
54+
query: ExportedQuery<import('../app/routes/blog._index').SearchParams>,
55+
},
6256
"/blog/rss.xml": {
63-
id: 'routes/blog.rss[.]xml',
6457
params: never,
6558
query: ExportedQuery<import('../app/routes/blog.rss[.]xml').SearchParams>,
6659
},
6760
"/chats/:season/:episode": {
68-
id: 'routes/chats_.$season.$episode',
6961
params: {season: string | number; episode: string | number},
7062
query: ExportedQuery<import('../app/routes/chats_.$season.$episode').SearchParams>,
7163
},
7264
"/chats/:season/:episode/:slug": {
73-
id: 'routes/chats_.$season.$episode.$slug',
7465
params: {season: string | number; episode: string | number; slug: string | number},
7566
query: ExportedQuery<import('../app/routes/chats_.$season.$episode.$slug').SearchParams>,
7667
},
7768
"/credits": {
78-
id: 'routes/credits',
7969
params: never,
8070
query: ExportedQuery<import('../app/routes/credits').SearchParams>,
8171
},
8272
"/home": {
83-
id: 'routes/(static).home',
8473
params: never,
8574
query: ExportedQuery<import('../app/routes/(static).home').SearchParams>,
8675
},
8776
"/jokes": {
88-
id: 'routes/jokes._index',
8977
params: never,
9078
query: ExportedQuery<import('../app/routes/jokes._index').SearchParams>,
9179
},
9280
"/jokes/:jokeId": {
93-
id: 'routes/jokes.$jokeId',
9481
params: {jokeId: string | number},
9582
query: ExportedQuery<import('../app/routes/jokes.$jokeId').SearchParams>,
9683
},
9784
"/people/:personId": {
98-
id: 'routes/people.$personId',
9985
params: {personId: string | number},
10086
query: ExportedQuery<import('../app/routes/people.$personId').SearchParams>,
10187
},
10288
"/people/:personId/:planId/remove-plan": {
103-
id: 'routes/people.$personId.$planId.remove-plan',
10489
params: {personId: string | number; planId: string | number},
10590
query: ExportedQuery<import('../app/routes/people.$personId.$planId.remove-plan').SearchParams>,
10691
},
10792
"/posts": {
108-
id: 'routes/posts._index',
10993
params: never,
11094
query: ExportedQuery<import('../app/routes/posts._index').SearchParams>,
11195
},
11296
"/posts/:id": {
113-
id: 'routes/posts.$id',
11497
params: {id: string | number},
11598
query: ExportedQuery<import('../app/routes/posts.$id').SearchParams>,
11699
},
117100
"/posts/*": {
118-
id: 'routes/posts.$',
119101
params: {"*": string | number},
120102
query: ExportedQuery<import('../app/routes/posts.$').SearchParams>,
121103
},
122104
"/posts/delete": {
123-
id: 'routes/posts.delete',
124105
params: never,
125106
query: ExportedQuery<import('../app/routes/posts.delete').SearchParams>,
126107
},
127108
"/s/:query": {
128-
id: 'routes/s.$query',
129109
params: {query: string | number},
130110
query: ExportedQuery<import('../app/routes/s.$query').SearchParams>,
131111
},
132112
"/sign-in/*": {
133-
id: 'routes/sign-in.$',
134113
params: {"*": string | number},
135114
query: ExportedQuery<import('../app/routes/sign-in.$').SearchParams>,
136115
},
137116
"/somewhere/cool/*": {
138-
id: 'catchall',
139117
params: {"*": string | number},
140118
query: ExportedQuery<import('../app/catchall').SearchParams>,
141119
},
142120
"/static/home": {
143-
id: 'routes/(static).home',
144121
params: never,
145122
query: ExportedQuery<import('../app/routes/(static).home').SearchParams>,
146123
}
@@ -153,7 +130,38 @@ exports[`gen route types 1`] = `
153130
}[keyof Routes]
154131
>;
155132
156-
export type RouteId = Routes[keyof Routes]['id'];
133+
export type RouteId =
134+
| 'root'
135+
| 'routes/chats_.$season.$episode'
136+
| 'routes/chats_.$season.$episode.$slug'
137+
| 'routes/people.$personId'
138+
| 'routes/people.$personId.$planId.remove-plan'
139+
| 'routes/api.$id[.]json'
140+
| 'routes/blog.rss[.]xml'
141+
| 'routes/($lang).about'
142+
| 'routes/(static).home'
143+
| 'routes/posts._index'
144+
| 'routes/posts.delete'
145+
| 'routes/auth._auth'
146+
| 'routes/auth._auth.login'
147+
| 'routes/posts.$id'
148+
| 'routes/sign-in.$'
149+
| 'routes/s.$query'
150+
| 'routes/credits'
151+
| 'routes/posts.$'
152+
| 'routes/admin'
153+
| 'routes/admin.episodes._index'
154+
| 'routes/admin.episodes.$id'
155+
| 'routes/admin.episodes.$id.comments'
156+
| 'routes/admin.episodes.$id._index'
157+
| 'routes/admin.episodes.new'
158+
| 'routes/admin._index'
159+
| 'routes/jokes'
160+
| 'routes/jokes.$jokeId'
161+
| 'routes/jokes._index'
162+
| 'routes/blog'
163+
| 'routes/blog._index'
164+
| 'catchall';
157165
158166
export function $path<
159167
Route extends keyof Routes,

tests/fixture.ts

+12
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,18 @@ export const testRoutes =
172172
path: "jokes",
173173
parentId: "root",
174174
},
175+
"routes/blog": {
176+
file: "routes/blog.tsx",
177+
id: "routes/blog",
178+
path: "blog",
179+
parentId: "root",
180+
},
181+
"routes/blog._index": {
182+
file: "routes/blog._index.tsx",
183+
id: "routes/blog._index",
184+
path: undefined,
185+
parentId: "routes/blog",
186+
},
175187
catchall: {
176188
path: "/somewhere/cool/*",
177189
index: undefined,

0 commit comments

Comments
 (0)