mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
* perf(protocol): generate inbound ws validators * perf(client): use generated ws validation * docs(protocol): document generated validation * fix(protocol): make validator generation source-only * test(protocol): cover explicit provider model normalization * fix(protocol): preserve inbound compat defaults * fix(protocol): make validator import rewrite portable * fix(protocol): harden validation safety checks * fix(protocol): guard generated validator boundaries * fix(protocol): normalize legacy inbound defaults * fix(protocol): simplify generated validation safety net * fix(protocol): keep cold typecheck source-only * fix(protocol): encapsulate validator codegen * fix(protocol): bootstrap source-alias typechecks * fix(app): keep source aliases out of bundler config * fix(protocol): harden validator codegen packaging * fix(protocol): own zod-aot patches in generator * fix(protocol): trim validator safety net * fix(client): normalize provider updates before dispatch * fix(protocol): keep validator generation out of install
107 lines
4.3 KiB
JavaScript
107 lines
4.3 KiB
JavaScript
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
import { createRequire } from "node:module";
|
|
import { dirname, relative, resolve, sep } from "node:path";
|
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
|
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
const source = resolve(packageRoot, "codegen/ws-outbound.compile.ts");
|
|
const runtimeSchemaMetadata = resolve(packageRoot, "src/validation/ws-outbound-schema-metadata.ts");
|
|
const output = resolve(packageRoot, "src/generated/validation/ws-outbound.aot.ts");
|
|
|
|
const require = createRequire(import.meta.url);
|
|
const zodAotEntry = require.resolve("zod-aot");
|
|
const zodAotRoot = resolve(dirname(zodAotEntry), "..");
|
|
const emitterPath = resolve(zodAotRoot, "dist/cli/emitter.js");
|
|
const discriminatedUnionPath = resolve(
|
|
zodAotRoot,
|
|
"dist/core/codegen/schemas/discriminated-union.js",
|
|
);
|
|
|
|
async function ensureZodAotRuntimeImportExtensionPatch() {
|
|
const emitter = await readFile(emitterPath, "utf8");
|
|
if (emitter.includes('sourceRelPath.endsWith(".js")')) {
|
|
return;
|
|
}
|
|
|
|
const before = 'let importPath = sourceRelPath.replace(/\\.[cm]?[jt]sx?$/, "");';
|
|
const after =
|
|
'let importPath = sourceRelPath.endsWith(".js")\n ? sourceRelPath\n : sourceRelPath.replace(/\\.[cm]?[jt]sx?$/, "");';
|
|
if (!emitter.includes(before)) {
|
|
throw new Error("zod-aot emitter shape changed; update the runtime import extension patch");
|
|
}
|
|
await writeFile(emitterPath, emitter.replace(before, after));
|
|
}
|
|
|
|
async function ensureZodAotDiscriminatedUnionOutputPatch() {
|
|
let discriminatedUnionEmitter = await readFile(discriminatedUnionPath, "utf8");
|
|
if (
|
|
discriminatedUnionEmitter.includes(
|
|
"const needsOutputPropagation = ir.options.some(hasMutation);",
|
|
)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
const importBefore = 'import { escapeString } from "../context.js";';
|
|
const importAfter = 'import { escapeString, hasMutation } from "../context.js";';
|
|
const outputFlagBefore = "const discKey = escapeString(ir.discriminator);\n let code = emit `";
|
|
const outputFlagAfter =
|
|
"const discKey = escapeString(ir.discriminator);\n const needsOutputPropagation = ir.options.some(hasMutation);\n let code = emit `";
|
|
const propagationBefore =
|
|
" ${g.visit(option, { input: objVar, output: objVar })}\n break;`;";
|
|
const propagationAfter =
|
|
' ${g.visit(option, { input: objVar, output: objVar })}\n ${needsOutputPropagation ? `${g.output}=${objVar};` : ""}\n break;`;';
|
|
|
|
if (
|
|
!discriminatedUnionEmitter.includes(importBefore) ||
|
|
!discriminatedUnionEmitter.includes(outputFlagBefore) ||
|
|
!discriminatedUnionEmitter.includes(propagationBefore)
|
|
) {
|
|
throw new Error("zod-aot discriminated-union emitter shape changed; update the output patch");
|
|
}
|
|
|
|
discriminatedUnionEmitter = discriminatedUnionEmitter
|
|
.replace(importBefore, importAfter)
|
|
.replace(outputFlagBefore, outputFlagAfter)
|
|
.replace(propagationBefore, propagationAfter);
|
|
await writeFile(discriminatedUnionPath, discriminatedUnionEmitter);
|
|
}
|
|
|
|
await Promise.all([
|
|
ensureZodAotRuntimeImportExtensionPatch(),
|
|
ensureZodAotDiscriminatedUnionOutputPatch(),
|
|
]);
|
|
|
|
const [{ discoverSchemas }, { compileSchemas }, { generateCompiledFileContent }] =
|
|
await Promise.all([
|
|
import(pathToFileURL(resolve(zodAotRoot, "dist/discovery.js")).href),
|
|
import(pathToFileURL(resolve(zodAotRoot, "dist/core/pipeline.js")).href),
|
|
import(pathToFileURL(resolve(zodAotRoot, "dist/cli/emitter.js")).href),
|
|
]);
|
|
|
|
const schemas = await discoverSchemas(source, { cacheBust: true });
|
|
if (schemas.length === 0) {
|
|
throw new Error(`No zod-aot compile() exports found in ${relative(packageRoot, source)}`);
|
|
}
|
|
|
|
const compiled = compileSchemas(schemas, { mode: "inline" });
|
|
const runtimeImportPath = relative(dirname(output), runtimeSchemaMetadata)
|
|
.replace(/\.[cm]?[jt]sx?$/, ".js")
|
|
.split(sep)
|
|
.join("/");
|
|
const content = generateCompiledFileContent(compiled, runtimeImportPath, {
|
|
zodCompat: false,
|
|
}).replace(
|
|
"// AUTO-GENERATED by zod-aot — DO NOT EDIT",
|
|
"// @ts-nocheck\n// AUTO-GENERATED by zod-aot — DO NOT EDIT",
|
|
);
|
|
|
|
await mkdir(dirname(output), { recursive: true });
|
|
await writeFile(output, content);
|
|
|
|
console.info(
|
|
`generated ${relative(packageRoot, output)} from ${relative(packageRoot, source)} (${schemas
|
|
.map((schema) => schema.exportName)
|
|
.join(", ")})`,
|
|
);
|