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
97 lines
2.5 KiB
JavaScript
97 lines
2.5 KiB
JavaScript
import { readdir, stat } from "node:fs/promises";
|
|
import { dirname, join, relative, sep } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { spawn } from "node:child_process";
|
|
|
|
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
const protocolSrcDir = join(packageRoot, "src");
|
|
const pollIntervalMs = 1000;
|
|
|
|
let currentFingerprint = "";
|
|
let generateInFlight = false;
|
|
let generateAgain = false;
|
|
|
|
async function collectSourceFiles(dir) {
|
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
const files = [];
|
|
|
|
for (const entry of entries) {
|
|
const path = join(dir, entry.name);
|
|
const relativePath = relative(protocolSrcDir, path);
|
|
const parts = relativePath.split(sep);
|
|
|
|
if (parts[0] === "generated") {
|
|
continue;
|
|
}
|
|
|
|
if (entry.isDirectory()) {
|
|
files.push(...(await collectSourceFiles(path)));
|
|
continue;
|
|
}
|
|
|
|
if (entry.isFile() && entry.name.endsWith(".ts")) {
|
|
files.push(path);
|
|
}
|
|
}
|
|
|
|
return files;
|
|
}
|
|
|
|
async function fingerprintSources() {
|
|
const files = await collectSourceFiles(protocolSrcDir);
|
|
const stats = await Promise.all(
|
|
files.sort().map(async (file) => {
|
|
const fileStat = await stat(file);
|
|
return `${relative(packageRoot, file)}:${fileStat.mtimeMs}:${fileStat.size}`;
|
|
}),
|
|
);
|
|
|
|
return stats.join("\n");
|
|
}
|
|
|
|
function runGenerate() {
|
|
if (generateInFlight) {
|
|
generateAgain = true;
|
|
return;
|
|
}
|
|
|
|
generateInFlight = true;
|
|
const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
const child = spawn(npmCommand, ["run", "generate:validators"], {
|
|
cwd: packageRoot,
|
|
stdio: "inherit",
|
|
});
|
|
|
|
child.on("exit", (code, signal) => {
|
|
generateInFlight = false;
|
|
if (code !== 0) {
|
|
console.error(
|
|
signal
|
|
? `validation AOT generation stopped by ${signal}`
|
|
: `validation AOT generation failed with exit code ${code}`,
|
|
);
|
|
}
|
|
|
|
if (generateAgain) {
|
|
generateAgain = false;
|
|
runGenerate();
|
|
}
|
|
});
|
|
}
|
|
|
|
async function poll() {
|
|
try {
|
|
const nextFingerprint = await fingerprintSources();
|
|
if (currentFingerprint && nextFingerprint !== currentFingerprint) {
|
|
runGenerate();
|
|
}
|
|
currentFingerprint = nextFingerprint;
|
|
} catch (error) {
|
|
console.error("validation AOT watcher failed to scan protocol sources", error);
|
|
}
|
|
}
|
|
|
|
currentFingerprint = await fingerprintSources();
|
|
console.log("Watching protocol schema sources for validation AOT changes...");
|
|
setInterval(poll, pollIntervalMs);
|