1// @effect-diagnostics nodeBuiltinImport:off - standalone catalog generation uses synchronous Node I/O.
2// @effect-diagnostics globalConsole:off - standalone maintenance command output.
3import * as NodeFS from "node:fs";
4import * as NodeModule from "node:module";
5import * as NodePath from "node:path";
6
7import { catalog } from "@handy-computer/models";
8import * as Schema from "effect/Schema";
9
10import manifest from "../package.json" with { type: "json" };
11import { renderSpeechCatalog } from "./speech-catalog.ts";
12
13const require = NodeModule.createRequire(import.meta.url);
14const source = require.resolve("@handy-computer/models/catalog.json");
15const sourceManifest = Schema.decodeSync(
16 Schema.fromJsonString(Schema.Struct({ version: Schema.String })),
17)(NodeFS.readFileSync(NodePath.join(NodePath.dirname(source), "package.json"), "utf8"));
18if (sourceManifest.version !== manifest.devDependencies["@handy-computer/models"]) {
19 throw new Error("Install the exact pinned @handy-computer/models version before generating.");
20}
21const target = new URL("../src/speech/catalog.json", import.meta.url);
22const expected = await renderSpeechCatalog(
23 catalog.data,
24 sourceManifest.version,
25 manifest.dependencies["transcribe-cpp"],
26);
27if (process.argv.includes("--check")) {
28 if (NodeFS.readFileSync(target, "utf8") !== expected) {
29 throw new Error("Speech catalog differs; run vp run speech:catalog:sync in apps/server.");
30 }
31 console.log("Bundled speech catalog matches the pinned source.");
32} else {
33 NodeFS.writeFileSync(target, expected);
34 console.log(`Generated speech catalog from @handy-computer/models@${sourceManifest.version}.`);
35}