65 lines
2.1 KiB
TypeScript
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();
|
|
}
|