import type { GitSource } from "../resource-lock/index.js"; import type { StructuralRequest } from "./structural-plan.js"; import { executionScaffold, isExecutionScaffold } from "./execution-scaffold.js"; import { scaffoldController } from "./controller-scaffold.js"; import { scaffoldComponent } from "./component-scaffold.js"; import { scaffoldQuery } from "./query-scaffold.js"; type Source = { repository: string; commit: string }; export type ScaffoldRecipe = { template?: "typescript-execution" | "typescript-component"; source: Source; directory?: string; name?: string; id?: string; revision?: string; declaration?: string; queryDocument?: string; initialFiles?: Record; controller?: { registry?: string; subject: string; snapshot: string; remote: string; input: "unit" | "value" }; tools?: { quixos: Source; protocol: Source; helpers: Source; sdk?: Source }; }; const source = (value: Source): GitSource => { if (!value || typeof value.repository !== "string" || typeof value.commit !== "string") throw Error("Scaffold requires an exact source identity; use a registered repository"); const url = new URL(value.repository); if ( url.protocol !== "https:" || url.username || url.password || url.search || url.hash || !/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/.test(value.commit) ) throw Error("Scaffolds require credential-free HTTPS sources and full exact commits"); return { resolver: "git", ...value }; }; const nixSource = (value: Source) => `git+${source(value).repository}?ref=refs/tags/quixos-reachability/${value.commit}&rev=${value.commit}`; /** One-shot edits; structural planning retains interrupted work and authored files. */ export async function scaffoldRecipe( root: string, command: "package" | "function" | "component" | "controller" | "query" | "migration" | "refresh", spec: ScaffoldRecipe, ): Promise { if (command === "refresh") throw Error( "Scaffold refresh is removed. Edit authored code and run check; add entries with scaffold function/component/query.", ); if (command === "migration") throw Error( "Old-workspace migration scaffolding is retired. Current disposable workspaces do not require migration code.", ); source(spec.source); if (spec.directory && !/^[A-Za-z0-9_-][A-Za-z0-9_.-]*(?:\/[A-Za-z0-9_-][A-Za-z0-9_.-]*)*$/.test(spec.directory)) throw Error("Scaffold directory must be contained"); if (spec.template && !["typescript-execution", "typescript-component"].includes(spec.template)) throw Error("Use typescript-execution or typescript-component; old server/source-string presets are retired"); const prefix = spec.directory ? spec.directory + "/" : ""; if (command !== "package" && !(await isExecutionScaffold(root, prefix))) throw Error("Scaffolding requires a checked execution package"); if (spec.tools) Object.values(spec.tools).forEach(source); if (command === "controller") return scaffoldController(root, prefix, spec); if (command === "component") return scaffoldComponent(root, prefix, spec); if (command === "query") return scaffoldQuery(root, prefix, spec); return executionScaffold(root, command, spec, prefix, nixSource); }