-
-
Notifications
You must be signed in to change notification settings - Fork 10.6k
/
Copy pathindex.ts
95 lines (78 loc) · 2.48 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import fs from "node:fs";
import * as Path from "pathe";
import pc from "picocolors";
import type vite from "vite";
import { createConfigLoader } from "../config/config";
import type { RouteManifestEntry } from "../config/routes";
import { generate } from "./generate";
import type { Context } from "./context";
import { getTypesDir, getTypesPath } from "./paths";
export async function run(rootDirectory: string) {
const ctx = await createContext({ rootDirectory, watch: false });
await writeAll(ctx);
}
export type Watcher = {
close: () => Promise<void>;
};
export async function watch(
rootDirectory: string,
{ logger }: { logger?: vite.Logger } = {}
): Promise<Watcher> {
const ctx = await createContext({ rootDirectory, watch: true });
await writeAll(ctx);
logger?.info(pc.green("generated types"), { timestamp: true, clear: true });
ctx.configLoader.onChange(async ({ result, routeConfigChanged }) => {
if (!result.ok) {
logger?.error(pc.red(result.error), { timestamp: true, clear: true });
return;
}
ctx.config = result.value;
if (routeConfigChanged) {
await writeAll(ctx);
logger?.info(pc.green("regenerated types"), {
timestamp: true,
clear: true,
});
}
});
return {
close: async () => await ctx.configLoader.close(),
};
}
async function createContext({
rootDirectory,
watch,
}: {
rootDirectory: string;
watch: boolean;
}): Promise<Context> {
const configLoader = await createConfigLoader({ rootDirectory, watch });
const configResult = await configLoader.getConfig();
if (!configResult.ok) {
throw new Error(configResult.error);
}
const config = configResult.value;
return {
configLoader,
rootDirectory,
config,
};
}
function isRouteInAppDirectory(ctx: Context, route: RouteManifestEntry) {
const absoluteRoutePath = Path.resolve(ctx.config.appDirectory, route.file);
return absoluteRoutePath.startsWith(ctx.config.appDirectory);
}
async function writeAll(ctx: Context): Promise<void> {
const typegenDir = getTypesDir(ctx);
fs.rmSync(typegenDir, { recursive: true, force: true });
Object.values(ctx.config.routes).forEach((route) => {
// We only generate types for routes in the app directory
if (!isRouteInAppDirectory(ctx, route)) {
return;
}
const typesPath = getTypesPath(ctx, route);
const content = generate(ctx, route);
fs.mkdirSync(Path.dirname(typesPath), { recursive: true });
fs.writeFileSync(typesPath, content);
});
}