Simplify workspace authoring and isolate managed component styles
Use imperative scaffolds without a registry/refresh lifecycle; preserve authored runtime wiring and generate checked descriptors. Consolidate binding options, embed checked TSX/CSS source, queue mutable convergence while allowing parallel immutable checks, and preload real CLI observations. Add Shadow DOM boundaries with scoped overlays and composed-event handling. Update template/toolchain pins and document VM-free authoring, browser, and stateful acceptance; no deployment or default-template selection.
This commit is contained in:
@@ -17,7 +17,7 @@ export type StructuralRequest = {
|
||||
source?: {repository: string; commit: string};
|
||||
resourceRoot?: string;
|
||||
validation?: "syntax" | "resource-graph";
|
||||
files: ({file: string; edits: StructuralEdit[]} | {file: string; create: string} | {file: string; generated: string})[];
|
||||
files: ({file: string; edits: StructuralEdit[]} | {file: string; create: string} | {file: string; generated: string} | {file: string; expected: string; replace: string})[];
|
||||
};
|
||||
type Change = {file: string; before: string | null; after: string; mode: number};
|
||||
type Journal = {schemaVersion: 1; id: string; root: string; phase: "prepared" | "complete"; changes: Change[]};
|
||||
@@ -70,6 +70,9 @@ export const planStructure = async (rootPath: string, request: StructuralRequest
|
||||
if ("create" in input) {
|
||||
if (before !== null || typeof input.create !== "string") throw new Error("Scaffold creation cannot replace an existing file");
|
||||
after = input.create;
|
||||
} else if ("replace" in input) {
|
||||
if (before !== input.expected || typeof input.replace !== "string") throw new Error(`Stale imperative edit: ${input.file}`);
|
||||
after = input.replace;
|
||||
} else if ("generated" in input) {
|
||||
const generated = (text: string) => text.startsWith("// Generated by qx-scaffold-v1\n") || text.startsWith("# Generated by qx-scaffold-v1\n") || (() => {try {return JSON.parse(text).generatedBy === "qx-scaffold-v1";} catch {return false;}})();
|
||||
if (typeof input.generated !== "string" || !generated(input.generated) || (before !== null && !generated(before))) throw new Error("Only scaffold-owned generated files may be regenerated");
|
||||
@@ -79,17 +82,6 @@ export const planStructure = async (rootPath: string, request: StructuralRequest
|
||||
after = input.edits.reduce(editStructure, before);
|
||||
}
|
||||
if (Buffer.byteLength(after) > 1024 * 1024) throw new Error("Scaffold file exceeds 1 MiB");
|
||||
if (input.file.endsWith("package.qx")) {
|
||||
let registry;
|
||||
try { registry = JSON.parse(await fs.readFile(path.join(root, path.dirname(input.file), "quixos.scaffold.json"), "utf8")); }
|
||||
catch (error) { if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error; }
|
||||
if (registry?.generatedBy === "qx-scaffold-v1") {
|
||||
const declaration = parseQx(after).root.children.find(node => node.kind === "packageResourceDecl");
|
||||
const literal = declaration?.children.find(node => node.kind === "stringLiteral");
|
||||
if (literal && JSON.parse(after.slice(literal.start, literal.end)) !== registry.id)
|
||||
throw new Error("Cannot change a scaffold-owned package identity independently of its registry; create a new managed package instead");
|
||||
}
|
||||
}
|
||||
const mode = before === null ? 0o644 : (await fs.stat(path.join(root, input.file))).mode & 0o777;
|
||||
changes.push({file: input.file, before, after, mode});
|
||||
await containedParent(snapshot.directory, input.file);
|
||||
@@ -109,9 +101,7 @@ export const planStructure = async (rootPath: string, request: StructuralRequest
|
||||
if (request.kind === "workspace") await compileWorkspaceRepository({rootDirectory: resourceRoot, resolveResource});
|
||||
else if (["package", "interface"].includes(request.kind) && request.source) {
|
||||
const compiled = await compileCapabilityResourceRepository({rootDirectory: resourceRoot, kind: request.kind as "package" | "interface", source: {resolver: "git", ...request.source}, resolveResource});
|
||||
let scaffoldOwned = false;
|
||||
try { scaffoldOwned = JSON.parse(await fs.readFile(path.join(resourceRoot, "quixos.scaffold.json"), "utf8")).generatedBy === "qx-scaffold-v1"; } catch { /* ordinary resource, no generated package scaffolding */ }
|
||||
if (scaffoldOwned && compiled.resource.kind === "package") {
|
||||
if (compiled.resource.kind === "package") {
|
||||
const configuration = JSON.parse(await fs.readFile(path.join(resourceRoot, "quixos.check.json"), "utf8"));
|
||||
const artifacts = [
|
||||
{file: configuration.bindingOutput as string, after: generateTypeScriptBindings(bindingSchema(compiled), compiled.resource.revision.revisionId, configuration.options)},
|
||||
|
||||
Reference in New Issue
Block a user