Introduce persisted Web Studio component capabilities

This commit is contained in:
2026-09-04 21:03:09 -07:00
parent f4987093f6
commit fd039f095b
17 changed files with 2459 additions and 1609 deletions
+55
View File
@@ -1,4 +1,6 @@
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { test } from "node:test";
import { compileCapabilitySource } from "../src/capability-language/index.js";
import {
@@ -146,3 +148,56 @@ test("well-formed but invalid programs report semantic paths", () => {
assert.equal(diagnostic.phase, "validation");
assert.ok(diagnostic.path?.includes("operationBindings"));
});
test("Web Studio sidecars declare lazy materialization and checked cross-object ports", () => {
const source = readFileSync(
resolve(process.cwd(), "test/fixtures/web-studio.capabilities.qx"),
"utf8",
);
const result = compileCapabilitySource(source, "web-studio.capabilities.qx");
assert.equal(result.ok, true);
if (!result.ok) return;
const host = result.workspace.conformances.find((entry) =>
entry.atomId === "atom:project" &&
entry.interfaceRevisionId === "interface:org.quixos.web-studio.has-react-component@1"
);
assert.deepEqual(host?.relationshipMaterializations, [{
memberId: "member:org.quixos.web-studio.has-react-component:component",
constructorAtomId: "atom:project-component",
edgeTypeId: "edge:project:component",
constructedProjectionId: "projection:component:subject",
}]);
const component = result.workspace.conformances.find((entry) =>
entry.atomId === "atom:project-component"
);
const binding = component?.operationBindings[0]?.binding;
assert.equal(binding?.kind, "package");
if (binding?.kind !== "package") return;
assert.deepEqual(binding.dependencies[1]?.binding, {
kind: "state",
slotId: "slot:project:name",
via: {
edgeTypeId: "edge:project:component",
projectionId: "projection:component:subject",
},
});
});
test("relationship materializers require a constructor from the host atom", () => {
const source = readFileSync(
resolve(process.cwd(), "test/fixtures/web-studio.capabilities.qx"),
"utf8",
).replace(
"constructs ProjectComponent : atom-ref<Project>;",
"constructs ProjectComponent : unit;",
);
const result = compileCapabilitySource(source, "invalid-materializer.qx");
assert.equal(result.ok, false);
if (result.ok) return;
assert.ok(result.diagnostics.some((entry) =>
entry.code === "invalid-relationship-materialization" &&
entry.message.includes("must accept")
));
});