Skip to content

Commit 3071cfa

Browse files
authored
typegen: refactor (#12242)
1 parent 25a35de commit 3071cfa

File tree

4 files changed

+246
-241
lines changed

4 files changed

+246
-241
lines changed

packages/react-router-dev/cli/commands.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,15 +204,9 @@ export async function typegen(
204204
root ??= process.cwd();
205205

206206
if (flags.watch) {
207-
await Typegen.watch(root, { configFile: flags.config });
207+
await Typegen.watch(root, flags.config);
208208
await new Promise(() => {}); // keep alive
209209
return;
210210
}
211-
212-
let ctx = await loadPluginContext({ root, configFile: flags.config });
213-
await Typegen.writeAll({
214-
rootDirectory: root,
215-
appDirectory: ctx.reactRouterConfig.appDirectory,
216-
routes: ctx.reactRouterConfig.routes,
217-
});
211+
await Typegen.run(root, flags.config);
218212
}

packages/react-router-dev/typegen.ts

Lines changed: 0 additions & 233 deletions
This file was deleted.
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import dedent from "dedent";
2+
import * as Pathe from "pathe/utils";
3+
4+
import { type RouteManifest, type RouteManifestEntry } from "../config/routes";
5+
6+
export function generate(
7+
routes: RouteManifest,
8+
route: RouteManifestEntry
9+
): string {
10+
return dedent`
11+
// React Router generated types for route:
12+
// ${route.file}
13+
14+
import * as T from "react-router/types"
15+
16+
export type Params = {${formatParamProperties(routes, route)}}
17+
18+
type RouteModule = typeof import("./${Pathe.filename(route.file)}")
19+
20+
export namespace Route {
21+
export type LoaderData = T.CreateLoaderData<RouteModule>
22+
export type ActionData = T.CreateActionData<RouteModule>
23+
24+
export type LoaderArgs = T.CreateServerLoaderArgs<Params>
25+
export type ClientLoaderArgs = T.CreateClientLoaderArgs<Params, RouteModule>
26+
export type ActionArgs = T.CreateServerActionArgs<Params>
27+
export type ClientActionArgs = T.CreateClientActionArgs<Params, RouteModule>
28+
29+
export type HydrateFallbackProps = T.CreateHydrateFallbackProps<Params>
30+
export type ComponentProps = T.CreateComponentProps<Params, LoaderData, ActionData>
31+
export type ErrorBoundaryProps = T.CreateErrorBoundaryProps<Params, LoaderData, ActionData>
32+
}
33+
`;
34+
}
35+
36+
function formatParamProperties(
37+
routes: RouteManifest,
38+
route: RouteManifestEntry
39+
) {
40+
const urlpath = getRouteLineage(routes, route)
41+
.map((route) => route.path)
42+
.join("/");
43+
const params = parseParams(urlpath);
44+
const indent = " ".repeat(3);
45+
const properties = Object.entries(params).map(([name, values]) => {
46+
if (values.length === 1) {
47+
const isOptional = values[0];
48+
return indent + (isOptional ? `"${name}"?: string` : `"${name}": string`);
49+
}
50+
const items = values.map((isOptional) =>
51+
isOptional ? "string | undefined" : "string"
52+
);
53+
return indent + `"${name}": [${items.join(", ")}]`;
54+
});
55+
56+
// prettier-ignore
57+
const body =
58+
properties.length === 0 ? "" :
59+
"\n" + properties.join("\n") + "\n";
60+
61+
return body;
62+
}
63+
64+
function getRouteLineage(routes: RouteManifest, route: RouteManifestEntry) {
65+
const result: RouteManifestEntry[] = [];
66+
while (route) {
67+
result.push(route);
68+
if (!route.parentId) break;
69+
route = routes[route.parentId];
70+
}
71+
result.reverse();
72+
return result;
73+
}
74+
75+
function parseParams(urlpath: string) {
76+
const result: Record<string, boolean[]> = {};
77+
78+
let segments = urlpath.split("/");
79+
segments
80+
.filter((s) => s.startsWith(":"))
81+
.forEach((param) => {
82+
param = param.slice(1); // omit leading `:`
83+
let isOptional = param.endsWith("?");
84+
if (isOptional) {
85+
param = param.slice(0, -1); // omit trailing `?`
86+
}
87+
88+
result[param] ??= [];
89+
result[param].push(isOptional);
90+
return;
91+
});
92+
93+
const hasSplat = segments.at(-1) === "*";
94+
if (hasSplat) result["*"] = [false];
95+
return result;
96+
}

0 commit comments

Comments
 (0)