fix(api): align frontend with REST contracts
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import { execFile } from "node:child_process";
|
||||
import { createHash } from "node:crypto";
|
||||
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { basename, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { promisify } from "node:util";
|
||||
|
||||
const manifest = JSON.parse(
|
||||
await readFile(new URL("../contracts/manifest.json", import.meta.url), "utf8"),
|
||||
);
|
||||
const run = promisify(execFile);
|
||||
const projectRoot = fileURLToPath(new URL("../", import.meta.url));
|
||||
const generator = join(
|
||||
projectRoot,
|
||||
"node_modules",
|
||||
"openapi-typescript",
|
||||
"bin",
|
||||
"cli.js",
|
||||
);
|
||||
const temporaryDirectory = await mkdtemp(
|
||||
join(tmpdir(), "tjwater-api-contracts-"),
|
||||
);
|
||||
|
||||
try {
|
||||
for (const [name, contract] of Object.entries(manifest.contracts)) {
|
||||
const contractPath = fileURLToPath(
|
||||
new URL(`../contracts/${contract.file}`, import.meta.url),
|
||||
);
|
||||
const payload = await readFile(contractPath);
|
||||
const actual = createHash("sha256").update(payload).digest("hex");
|
||||
if (actual !== contract.sha256) {
|
||||
throw new Error(
|
||||
`${name} contract hash mismatch: expected ${contract.sha256}, got ${actual}`,
|
||||
);
|
||||
}
|
||||
|
||||
const generatedName = `${name}Api.ts`;
|
||||
const temporaryOutput = join(temporaryDirectory, generatedName);
|
||||
await run(process.execPath, [generator, contractPath, "-o", temporaryOutput]);
|
||||
const expectedOutput = await readFile(
|
||||
new URL(`../src/generated/${generatedName}`, import.meta.url),
|
||||
);
|
||||
const generatedOutput = await readFile(temporaryOutput);
|
||||
if (!expectedOutput.equals(generatedOutput)) {
|
||||
throw new Error(
|
||||
`${basename(contract.file)} generated type is stale: run \`npm run api:generate\``,
|
||||
);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
await rm(temporaryDirectory, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
console.log(
|
||||
`validated API contract mirrors and generated types for ${manifest.contract_version}`,
|
||||
);
|
||||
Reference in New Issue
Block a user