Files
nana-story/scripts/verify-contracts.mjs
T

72 lines
2.5 KiB
JavaScript

import { createHash } from "node:crypto";
import { readFile, readdir } from "node:fs/promises";
import { resolve } from "node:path";
const root = resolve(import.meta.dirname, "..");
const sourcePath = resolve(root, "crates/nana-domain/src/lib.rs");
const hashPath = resolve(root, "contracts/.source.sha256");
const schemaDirectory = resolve(root, "contracts/schema");
const source = await readFile(sourcePath);
const expectedHash = (await readFile(hashPath, "utf8")).trim();
const normalizedSource = source.toString("utf8").replaceAll("\r\n", "\n");
const actualHash = createHash("sha256").update(normalizedSource).digest("hex");
if (actualHash !== expectedHash) {
throw new Error(
"Generated contracts are stale. Install Rust and run `pnpm contracts:generate`."
);
}
const schemaFiles = (await readdir(schemaDirectory))
.filter((name) => name.endsWith(".schema.json"))
.sort();
const required = [
"app-info.schema.json",
"branch-list.schema.json",
"character-card.schema.json",
"demo-pack-summary.schema.json",
"fork-branch-request.schema.json",
"fork-branch-result.schema.json",
"item-spec.schema.json",
"lapp-connection-test-result.schema.json",
"lapp-settings.schema.json",
"persona.schema.json",
"player-view.schema.json",
"plot-module.schema.json",
"presentation-snapshot.schema.json",
"rename-branch-request.schema.json",
"resource-bundle.schema.json",
"resource-header.schema.json",
"runtime-state.schema.json",
"story-node.schema.json",
"switch-branch-request.schema.json",
"switch-branch-result.schema.json",
"turn-failure.schema.json",
"turn-request.schema.json",
"turn-result.schema.json",
"update-lapp-settings-request.schema.json",
"world-book.schema.json"
];
if (JSON.stringify(schemaFiles) !== JSON.stringify(required)) {
throw new Error(
`Generated schema manifest mismatch.\nExpected: ${required.join(", ")}\nActual: ${schemaFiles.join(", ")}`
);
}
for (const name of schemaFiles) {
const value = JSON.parse(await readFile(resolve(schemaDirectory, name), "utf8"));
if (typeof value !== "object" || value === null || value.$schema === undefined) {
throw new Error(`Invalid generated schema: contracts/schema/${name}`);
}
}
const typeScript = await readFile(resolve(root, "contracts/ts/index.ts"), "utf8");
if (!typeScript.startsWith("// @generated by crates/nana-contracts")) {
throw new Error("contracts/ts/index.ts is not marked as generated");
}
console.log(`Verified ${schemaFiles.length} schemas and TypeScript DTO source hash.`);