Files
clean-architecture-frontend…/scripts/generate-contract-set.ts
T
2026-08-01 19:39:59 +09:00

65 lines
2.1 KiB
TypeScript

import { createHash } from "node:crypto";
import { mkdir, writeFile } from "node:fs/promises";
import { dirname } from "node:path";
import {
CONTRACT_SET_ALGORITHM,
computeContractSetDigestWith,
type ContractSetPackage,
} from "../src/contracts/contract-set-canonical.ts";
import { EXPECTED_CONTRACT_SET_PACKAGES } from "../src/features/installed-contract-contributions.ts";
/**
* §5.4 / §17.2.2 step 2. Derives the build-time expected contract set from the
* installed contributions and emits it as generated source for the manifest
* writer. `TEMPLATE_FIXTURE` provenance never reaches this list, so a fixture
* cannot influence the release digest.
*/
const OUTPUT = ".generated/frontend-runtime/contract-set.ts";
function sha256(bytes: Uint8Array): Uint8Array {
return new Uint8Array(createHash("sha256").update(bytes).digest());
}
export function buildContractSet(
packages: readonly ContractSetPackage[] = EXPECTED_CONTRACT_SET_PACKAGES as readonly ContractSetPackage[],
) {
return Object.freeze({
setAlgorithm: CONTRACT_SET_ALGORITHM,
setDigest: computeContractSetDigestWith(packages, sha256),
packages: Object.freeze(
[...packages]
.map((entry) => Object.freeze({ ...entry }))
.sort((left, right) => (left.packageId < right.packageId ? -1 : 1)),
),
});
}
async function main(): Promise<void> {
const contractSet = buildContractSet();
const source = [
"// Generated by scripts/generate-contract-set.ts. Do not edit.",
"// Regenerated from scratch on every build; never committed.",
"",
"import type { ContractSet } from \"../../src/contracts/contract-set.ts\";",
"",
`export const BUILD_CONTRACT_SET: ContractSet = ${JSON.stringify(
contractSet,
null,
2,
)} as const;`,
"",
].join("\n");
await mkdir(dirname(OUTPUT), { recursive: true });
await writeFile(OUTPUT, source, "utf8");
process.stdout.write(
`contract set: ${contractSet.packages.length} package(s) ${contractSet.setDigest}\n`,
);
}
if (process.argv[1]?.endsWith("generate-contract-set.ts")) {
await main();
}