winterspec
Version:
Write Winter-CG compatible routes with filesystem routing and tons of features
61 lines (57 loc) • 2.7 kB
JavaScript
import { Option } from "clipanion";
import fs from "node:fs/promises";
import { BaseCommand } from "../../../cli/base-command.js";
import { extractRouteSpecsFromAST } from "../../../lib/codegen/extract-route-specs-from-ast.js";
import Debug from "debug";
const debug = Debug("winterspec:CodeGenRouteTypes");
export class CodeGenRouteTypes extends BaseCommand {
constructor() {
super(...arguments);
this.outputPath = Option.String("--output,-o", {
description: "Path to the output file",
required: true,
});
}
async run(config) {
debug("Running with config", config);
const { project, routes, renderType } = await extractRouteSpecsFromAST({
tsConfigFilePath: config.tsconfigPath,
routesDirectory: config.routesDirectory,
});
project.createSourceFile("manifest.ts", `
import {z} from "zod"
export type Routes = {
${routes
.map(({ route, httpMethods, jsonResponseZodOutputType, jsonBodyZodInputType, commonParamsZodInputType, queryParamsZodInputType, urlEncodedFormDataZodInputType, }) => {
return ` "${route}": {
route: "${route}"
method: ${httpMethods.map((m) => `"${m}"`).join(" | ")}
${jsonResponseZodOutputType
? `jsonResponse: ${renderType(jsonResponseZodOutputType)}`
: ""}
${jsonBodyZodInputType
? `jsonBody: ${renderType(jsonBodyZodInputType)}`
: ""}
${commonParamsZodInputType
? `commonParams: ${renderType(commonParamsZodInputType)}`
: ""}
${queryParamsZodInputType
? `queryParams: ${renderType(queryParamsZodInputType)}`
: ""}
${urlEncodedFormDataZodInputType
? `urlEncodedFormData: ${renderType(urlEncodedFormDataZodInputType)}`
: ""}
}`;
})
.join("\n")}
}
type ExtractOrUnknown<T, Key extends string> = Key extends keyof T ? T[Key] : unknown;
export type RouteResponse<Path extends keyof Routes> = ExtractOrUnknown<Routes[Path], "jsonResponse">
export type RouteRequestBody<Path extends keyof Routes> = ExtractOrUnknown<Routes[Path], "jsonBody"> & ExtractOrUnknown<Routes[Path], "commonParams">
export type RouteRequestParams<Path extends keyof Routes> = ExtractOrUnknown<Routes[Path], "queryParams"> & ExtractOrUnknown<Routes[Path], "commonParams">
`);
const result = project.emitToMemory({ emitOnlyDtsFiles: true });
await fs.writeFile(this.outputPath, result.getFiles().find((f) => f.filePath.includes("/manifest.d.ts")).text);
}
}
CodeGenRouteTypes.paths = [[`codegen`, `route-types`]];