Files
quixos-protocol/src/capability-language/controller-scaffold.ts
T

43 lines
1.6 KiB
TypeScript
Raw Normal View History

import fs from "node:fs/promises";
import path from "node:path";
import type { ScaffoldRecipe } from "./scaffold-recipes.js";
import type { StructuralRequest } from "./structural-plan.js";
export async function scaffoldController(
root: string,
prefix: string,
spec: ScaffoldRecipe,
): Promise<StructuralRequest> {
const entry = { id: spec.id, ...spec.controller };
const fields = ["id", "subject", "snapshot", "remote", "input"];
if (
Object.keys(entry).length !== fields.length ||
fields.some((key) => typeof (entry as Record<string, unknown>)[key] !== "string") ||
!["unit", "value"].includes(entry.input ?? "")
)
throw Error("Controller requires id, subject, snapshot, remote and input (unit/value)");
const file = prefix + "quixos.controllers.json";
let before: string | undefined;
try {
before = await fs.readFile(path.join(root, file), "utf8");
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
}
const catalog = before ? JSON.parse(before) : { schemaVersion: 1, controllers: [] };
if (
catalog.schemaVersion !== 1 ||
!Array.isArray(catalog.controllers) ||
catalog.controllers.length >= 1000 ||
catalog.controllers.some((c: { id: string }) => c.id === entry.id)
)
throw Error("Invalid catalog or duplicate controller ID");
catalog.controllers.push(entry);
const content = JSON.stringify(catalog, null, 2) + "\n";
return {
kind: "package",
source: spec.source,
resourceRoot: spec.directory,
validation: "syntax",
files: [before === undefined ? { file, create: content } : { file, expected: before, replace: content }],
};
}