Skip to content

Commit 79ffc2f

Browse files
committed
autotype working
1 parent 25dd952 commit 79ffc2f

File tree

5 files changed

+27
-54
lines changed

5 files changed

+27
-54
lines changed

packages/react-router-dev/typescript/autotype/language-service.ts

Lines changed: 4 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ function autotypeRoute(ctx: Context, filepath: string, code: string) {
167167
...annotateDefaultExportExpression(ctx, stmt, typesSource),
168168
...annotateNamedExportFunctionDeclaration(ctx, stmt, typesSource),
169169
...annotateNamedExportVariableStatement(ctx, stmt, typesSource),
170-
...annotateExportDeclaration(ctx, stmt, typesSource),
171170
]),
172171
];
173172
return new AutotypedRoute(code, splices);
@@ -295,62 +294,23 @@ function annotateFunction(
295294

296295
const annotateReturnType = Route.exports[name]?.annotateReturnType;
297296

297+
name = name === "default" ? "Default" : name;
298298
return [
299299
param && param.type === undefined
300300
? {
301301
index: param.getEnd(),
302-
content: `: Parameters<import("${typesSource}").Route["${name}"]>[0]`,
302+
content: `: import("${typesSource}").${name}["args"]`,
303303
remapDiagnostics,
304304
}
305305
: null,
306306
returnTypeIndex && annotateReturnType && fn.type === undefined
307307
? {
308308
index: returnTypeIndex,
309-
content: `: ReturnType<import("${typesSource}").Route["${name}"]> `,
309+
content: `: import("${typesSource}").${name}["return"]`,
310310
remapDiagnostics,
311311
}
312312
: null,
313-
].filter((x) => x !== null);
314-
}
315-
316-
function annotateExportDeclaration(
317-
ctx: Context,
318-
stmt: ts.Statement,
319-
typesSource: string
320-
): Splice[] {
321-
if (!ctx.ts.isExportDeclaration(stmt)) return [];
322-
323-
const source = stmt.moduleSpecifier;
324-
if (source && !ctx.ts.isStringLiteral(source)) return [];
325-
326-
const exports = stmt.exportClause;
327-
if (!exports) return [];
328-
if (!ctx.ts.isNamedExports(exports)) return [];
329-
330-
return exports.elements
331-
.map((specifier) => {
332-
const name = specifier.name.text;
333-
const routeExport = Route.exports[name];
334-
if (!routeExport) return undefined;
335-
336-
const localName = specifier.propertyName?.text ?? name;
337-
const unique = AST.generateUniqueIdentifier();
338-
const satisfiesType = `import("${typesSource}").Route["${name}"]`;
339-
340-
const splice: Splice = {
341-
index: stmt.getStart(),
342-
content: source
343-
? `import { ${localName} as ${unique} } from "${source.text}"\n` +
344-
`${unique} satisfies ${satisfiesType}\n`
345-
: `${localName} satisfies ${satisfiesType}\n`,
346-
remapDiagnostics: {
347-
start: specifier.name.getStart(),
348-
length: specifier.name.getWidth(),
349-
},
350-
};
351-
return splice;
352-
})
353-
.filter((x) => x !== undefined);
313+
].filter((x) => x !== null) as Splice[];
354314
}
355315

356316
export class AutotypedRoute {

packages/react-router-dev/typescript/decorate.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export function decorateLanguageService(ctx: Context) {
7777
replacementSpan: { start: lineStart, length: position - lineStart },
7878
};
7979
})
80-
.filter((x) => x !== null);
80+
.filter((x) => x !== null) as ts.CompletionEntry[];
8181

8282
if (!completions) {
8383
return routeExportCompletions.length > 0
@@ -176,7 +176,7 @@ export function decorateLanguageService(ctx: Context) {
176176
return diagnostic;
177177
}
178178
})
179-
.filter((x) => x !== undefined);
179+
.filter((x) => x !== undefined) as ts.Diagnostic[];
180180

181181
const hmrNamedFunctionsDiagnostics: ts.Diagnostic[] = sourceFile.statements
182182
// eslint-disable-next-line array-callback-return
@@ -212,7 +212,7 @@ export function decorateLanguageService(ctx: Context) {
212212
};
213213
}
214214
})
215-
.filter((x) => x !== undefined);
215+
.filter((x) => x !== undefined) as ts.Diagnostic[];
216216

217217
return [
218218
...hmrNamedFunctionsDiagnostics,

packages/react-router-dev/typescript/plugin.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as Path from "pathe";
88

99
import * as Typegen from "./typegen";
1010
import type { Context } from "./context";
11+
import { decorateLanguageService } from "./decorate";
1112

1213
export default function init(modules: { typescript: typeof ts }) {
1314
function create(info: ts.server.PluginCreateInfo) {
@@ -29,6 +30,7 @@ export default function init(modules: { typescript: typeof ts }) {
2930
};
3031
Typegen.watch(ctx);
3132

33+
decorateLanguageService(ctx);
3234
return info.languageService;
3335
}
3436
return { create };

packages/react-router-dev/typescript/routes.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
11
import Path from "pathe";
2+
import Pathe from "pathe/utils";
23

34
import type ts from "typescript/lib/tsserverlibrary";
45

56
import type { Context } from "./context";
67
import type { RouteManifestEntry } from "../config/routes";
78

9+
function noext(path: string) {
10+
return Path.join(Path.dirname(path), Pathe.filename(path));
11+
}
12+
813
export function get(
914
ctx: Context,
1015
fileName: string
1116
): RouteManifestEntry | undefined {
12-
return ctx.routes[Path.relative(ctx.config.appDirectory, fileName)];
17+
const routeId = noext(Path.relative(ctx.config.appDirectory, fileName));
18+
ctx.logger?.info(
19+
`Route.get filename:${fileName} routeId:${routeId} routes:${JSON.stringify(
20+
ctx.routes
21+
)}`
22+
);
23+
return ctx.routes[routeId];
1324
}
1425

1526
type RouteExportInfo = {
@@ -25,7 +36,7 @@ export const exports: Record<string, RouteExportInfo> = {
2536
link: `https://remix.run/docs/en/main/route/links`,
2637
}),
2738
},
28-
serverLoader: {
39+
loader: {
2940
annotateReturnType: false,
3041
documentation: createDocumentation({
3142
name: "serverLoader",
@@ -47,7 +58,7 @@ export const exports: Record<string, RouteExportInfo> = {
4758
link: `https://remix.run/docs/en/main/route/hydrate-fallback`,
4859
}),
4960
},
50-
serverAction: {
61+
action: {
5162
annotateReturnType: false,
5263
documentation: createDocumentation({
5364
name: "serverAction",

packages/react-router-dev/typescript/typegen.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ function getModule(ctx: Context, route: RouteManifestEntry): string {
9090
export type LoaderData = T.LoaderData<Route>
9191
export type ActionData = T.ActionData<Route>
9292
93-
export type ServerLoader = T.ServerLoader<Params>
94-
export type ClientLoader = T.ClientLoader<Params, Route>
95-
export type ServerAction = T.ServerAction<Params>
96-
export type ClientAction = T.ClientAction<Params, Route>
93+
export type serverLoader = T.ServerLoader<Params>
94+
export type clientLoader = T.ClientLoader<Params, Route>
95+
export type serverAction = T.ServerAction<Params>
96+
export type clientAction = T.ClientAction<Params, Route>
9797
9898
export type HydrateFallback = T.HydrateFallback<Params>
9999
export type Default = T.Default<Params, LoaderData, ActionData>

0 commit comments

Comments
 (0)