Skip to content

Commit

Permalink
fix: route ids were merged incorrectly
Browse files Browse the repository at this point in the history
  • Loading branch information
yesmeck committed Dec 11, 2024
1 parent c40ca54 commit 9cfe0da
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 42 deletions.
19 changes: 9 additions & 10 deletions src/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ interface Options {
}

type RoutesInfo = Record<string, {
id: string;
fileName: string;
params: string[];
}>

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

async function buildHelpers(config: RequiredReactRouterConfig): Promise<RoutesInfo> {
async function buildHelpers(config: RequiredReactRouterConfig): Promise<[RoutesInfo, string[]]> {
const routesInfo: RoutesInfo = {};
const routeIds: string[] = [];
const handleRoutesRecursive = (
parentId?: string,
parentPath: RouteManifestEntry[] = [],
Expand All @@ -29,9 +29,9 @@ async function buildHelpers(config: RequiredReactRouterConfig): Promise<RoutesIn
);
routes.forEach((route) => {
let currentPath = parentPath;
routeIds.push(route.id);
if (route.id === 'root') {
routesInfo['/'] = {
id: route.id,
fileName: route.file,
params: [],
};
Expand All @@ -46,7 +46,6 @@ async function buildHelpers(config: RequiredReactRouterConfig): Promise<RoutesIn
// account optional segments that aren't params/dynamic.
for (const pathVariant of expandOptionalStaticSegments(fullPath)) {
routesInfo[pathVariant] = {
id: route.id,
fileName: route.file,
params: paramsNames
};
Expand All @@ -56,7 +55,7 @@ async function buildHelpers(config: RequiredReactRouterConfig): Promise<RoutesIn
});
};
handleRoutesRecursive();
return routesInfo;
return [routesInfo, routeIds];
}

function expandOptionalStaticSegments(path: string) {
Expand All @@ -80,11 +79,11 @@ function expandOptionalStaticSegments(path: string) {
}

export async function build(root: string, config: RequiredReactRouterConfig, options: Options) {
const routesInfo = await buildHelpers(config);
generate(root, config, routesInfo, options);
const [routesInfo, routeIds] = await buildHelpers(config);
generate(root, config, routesInfo, routeIds, options);
}

function generate(root: string, config: RequiredReactRouterConfig, routesInfo: RoutesInfo, options: Options) {
function generate(root: string, config: RequiredReactRouterConfig, routesInfo: RoutesInfo, routeIds: string[], options: Options) {
const outputPath = path.join(
root,
options.outputDirPath,
Expand All @@ -93,8 +92,8 @@ function generate(root: string, config: RequiredReactRouterConfig, routesInfo: R
const tsCode = template({
strict: options.strict,
relativeAppDirPath,
routes: Object.entries(routesInfo).map(([route, { id, fileName, params }]) => ({
id,
routeIds,
routes: Object.entries(routesInfo).map(([route, { fileName, params }]) => ({
route,
params,
fileName: slash(fileName.replace(/\.tsx?$/, '')),
Expand Down
12 changes: 8 additions & 4 deletions src/template.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
interface Context {
strict?: boolean;
relativeAppDirPath: string;
routeIds: string[];
routes: Array<{
id: string,
route: string;
params: string[];
fileName: string;
Expand All @@ -21,9 +21,8 @@ function exportedQuery(ctx: Context) {
}

function routes(ctx: Context) {
const routes = ctx.routes.map(({ id, route, params, fileName }) =>
const routes = ctx.routes.map(({ route, params, fileName }) =>
`"${route}": {
id: '${id}',
params: ${params.length > 0 ? `{${params.map(param => `${param}: string | number`).join('; ')}}` : 'never'},
query: ExportedQuery<import('${ctx.relativeAppDirPath}/${fileName}').SearchParams>,
}`
Expand All @@ -34,6 +33,11 @@ function routes(ctx: Context) {
}`
}

function routeIds(ctx: Context) {
return `export type RouteId =
| ${ctx.routeIds.map(routeId => `'${routeId}'`).join(`\n${indent(6)}| `)};`;
}

export function template(ctx: Context) {
return `declare module "safe-routes" {
type URLSearchParamsInit = string | string[][] | Record<string, string> | URLSearchParams;
Expand All @@ -51,7 +55,7 @@ export function template(ctx: Context) {
}[keyof Routes]
>;
export type RouteId = Routes[keyof Routes]['id'];
${routeIds(ctx)}
export function $path<
Route extends keyof Routes,
Expand Down
64 changes: 36 additions & 28 deletions tests/__snapshots__/build.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -10,137 +10,114 @@ exports[`gen route types 1`] = `
export interface Routes {
"/": {
id: 'root',
params: never,
query: ExportedQuery<import('../app/root').SearchParams>,
},
"/:lang?/about": {
id: 'routes/($lang).about',
params: {lang?: string | number},
query: ExportedQuery<import('../app/routes/($lang).about').SearchParams>,
},
"/admin": {
id: 'routes/admin._index',
params: never,
query: ExportedQuery<import('../app/routes/admin._index').SearchParams>,
},
"/admin/episodes": {
id: 'routes/admin.episodes._index',
params: never,
query: ExportedQuery<import('../app/routes/admin.episodes._index').SearchParams>,
},
"/admin/episodes/:id": {
id: 'routes/admin.episodes.$id._index',
params: {id: string | number},
query: ExportedQuery<import('../app/routes/admin.episodes.$id._index').SearchParams>,
},
"/admin/episodes/:id/comments": {
id: 'routes/admin.episodes.$id.comments',
params: {id: string | number},
query: ExportedQuery<import('../app/routes/admin.episodes.$id.comments').SearchParams>,
},
"/admin/episodes/new": {
id: 'routes/admin.episodes.new',
params: never,
query: ExportedQuery<import('../app/routes/admin.episodes.new').SearchParams>,
},
"/api/:id.json": {
id: 'routes/api.$id[.]json',
params: {id: string | number},
query: ExportedQuery<import('../app/routes/api.$id[.]json').SearchParams>,
},
"/auth": {
id: 'routes/auth._auth',
params: never,
query: ExportedQuery<import('../app/routes/auth._auth').SearchParams>,
},
"/auth/login": {
id: 'routes/auth._auth.login',
params: never,
query: ExportedQuery<import('../app/routes/auth._auth.login').SearchParams>,
},
"/blog": {
params: never,
query: ExportedQuery<import('../app/routes/blog._index').SearchParams>,
},
"/blog/rss.xml": {
id: 'routes/blog.rss[.]xml',
params: never,
query: ExportedQuery<import('../app/routes/blog.rss[.]xml').SearchParams>,
},
"/chats/:season/:episode": {
id: 'routes/chats_.$season.$episode',
params: {season: string | number; episode: string | number},
query: ExportedQuery<import('../app/routes/chats_.$season.$episode').SearchParams>,
},
"/chats/:season/:episode/:slug": {
id: 'routes/chats_.$season.$episode.$slug',
params: {season: string | number; episode: string | number; slug: string | number},
query: ExportedQuery<import('../app/routes/chats_.$season.$episode.$slug').SearchParams>,
},
"/credits": {
id: 'routes/credits',
params: never,
query: ExportedQuery<import('../app/routes/credits').SearchParams>,
},
"/home": {
id: 'routes/(static).home',
params: never,
query: ExportedQuery<import('../app/routes/(static).home').SearchParams>,
},
"/jokes": {
id: 'routes/jokes._index',
params: never,
query: ExportedQuery<import('../app/routes/jokes._index').SearchParams>,
},
"/jokes/:jokeId": {
id: 'routes/jokes.$jokeId',
params: {jokeId: string | number},
query: ExportedQuery<import('../app/routes/jokes.$jokeId').SearchParams>,
},
"/people/:personId": {
id: 'routes/people.$personId',
params: {personId: string | number},
query: ExportedQuery<import('../app/routes/people.$personId').SearchParams>,
},
"/people/:personId/:planId/remove-plan": {
id: 'routes/people.$personId.$planId.remove-plan',
params: {personId: string | number; planId: string | number},
query: ExportedQuery<import('../app/routes/people.$personId.$planId.remove-plan').SearchParams>,
},
"/posts": {
id: 'routes/posts._index',
params: never,
query: ExportedQuery<import('../app/routes/posts._index').SearchParams>,
},
"/posts/:id": {
id: 'routes/posts.$id',
params: {id: string | number},
query: ExportedQuery<import('../app/routes/posts.$id').SearchParams>,
},
"/posts/*": {
id: 'routes/posts.$',
params: {"*": string | number},
query: ExportedQuery<import('../app/routes/posts.$').SearchParams>,
},
"/posts/delete": {
id: 'routes/posts.delete',
params: never,
query: ExportedQuery<import('../app/routes/posts.delete').SearchParams>,
},
"/s/:query": {
id: 'routes/s.$query',
params: {query: string | number},
query: ExportedQuery<import('../app/routes/s.$query').SearchParams>,
},
"/sign-in/*": {
id: 'routes/sign-in.$',
params: {"*": string | number},
query: ExportedQuery<import('../app/routes/sign-in.$').SearchParams>,
},
"/somewhere/cool/*": {
id: 'catchall',
params: {"*": string | number},
query: ExportedQuery<import('../app/catchall').SearchParams>,
},
"/static/home": {
id: 'routes/(static).home',
params: never,
query: ExportedQuery<import('../app/routes/(static).home').SearchParams>,
}
Expand All @@ -153,7 +130,38 @@ exports[`gen route types 1`] = `
}[keyof Routes]
>;
export type RouteId = Routes[keyof Routes]['id'];
export type RouteId =
| 'root'
| 'routes/chats_.$season.$episode'
| 'routes/chats_.$season.$episode.$slug'
| 'routes/people.$personId'
| 'routes/people.$personId.$planId.remove-plan'
| 'routes/api.$id[.]json'
| 'routes/blog.rss[.]xml'
| 'routes/($lang).about'
| 'routes/(static).home'
| 'routes/posts._index'
| 'routes/posts.delete'
| 'routes/auth._auth'
| 'routes/auth._auth.login'
| 'routes/posts.$id'
| 'routes/sign-in.$'
| 'routes/s.$query'
| 'routes/credits'
| 'routes/posts.$'
| 'routes/admin'
| 'routes/admin.episodes._index'
| 'routes/admin.episodes.$id'
| 'routes/admin.episodes.$id.comments'
| 'routes/admin.episodes.$id._index'
| 'routes/admin.episodes.new'
| 'routes/admin._index'
| 'routes/jokes'
| 'routes/jokes.$jokeId'
| 'routes/jokes._index'
| 'routes/blog'
| 'routes/blog._index'
| 'catchall';
export function $path<
Route extends keyof Routes,
Expand Down
12 changes: 12 additions & 0 deletions tests/fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,18 @@ export const testRoutes =
path: "jokes",
parentId: "root",
},
"routes/blog": {
file: "routes/blog.tsx",
id: "routes/blog",
path: "blog",
parentId: "root",
},
"routes/blog._index": {
file: "routes/blog._index.tsx",
id: "routes/blog._index",
path: undefined,
parentId: "routes/blog",
},
catchall: {
path: "/somewhere/cool/*",
index: undefined,
Expand Down

0 comments on commit 9cfe0da

Please sign in to comment.