67 lines
3.3 KiB
TypeScript
67 lines
3.3 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { test } from "node:test";
|
|
import { compileCapabilityResourceSource, compileCapabilitySource } from "../src/capability-language/parser.js";
|
|
import { formatQx } from "../src/capability-language/source.js";
|
|
import { compileExecutionPlan, compileKernelProgram } from "../src/execution-world/index.js";
|
|
const contract = `interface Item id "item" revision "item@1" {
|
|
operation remove id "remove" : unit -> unit {
|
|
call id "remove:call" execution transaction targets [server];
|
|
}
|
|
}`;
|
|
const workspace = `workspace Lifecycle id "workspace:lifecycle" revision "workspace:lifecycle@1" commit "${"a".repeat(40)}" {
|
|
import interface Item;
|
|
atom Node id "node";
|
|
conform Node as Item id "node:item" {
|
|
private edge Links id "links" {
|
|
atom Node projection children id "children" many on-delete "cascade-other";
|
|
atom Node projection parent id "parent" optional-one on-delete "detach";
|
|
}
|
|
bind remove.call to lifecycle.delete;
|
|
}
|
|
}`;
|
|
function compile(ifaceSource = contract, workspaceSource = workspace) {
|
|
const iface = compileCapabilityResourceSource(ifaceSource, {
|
|
source: { repository: "https://example.test/lifecycle.git", commit: "a".repeat(40) },
|
|
});
|
|
assert.ok(iface.ok && iface.resource.kind === "interface", JSON.stringify(iface.diagnostics));
|
|
return compileCapabilitySource(workspaceSource, "workspace.qx", {
|
|
interfaces: new Map([["Item", iface.resource.revision]]),
|
|
});
|
|
}
|
|
test("lifecycle binding and endpoint policies survive formatting and kernel compilation", () => {
|
|
const result = compile();
|
|
assert.ok(result.ok, JSON.stringify(result.diagnostics));
|
|
const formatted = compile(formatQx(contract), formatQx(workspace));
|
|
assert.ok(formatted.ok, JSON.stringify(formatted.diagnostics));
|
|
const plan = compileExecutionPlan(result.workspace);
|
|
assert.equal(compileExecutionPlan(formatted.workspace).digest, plan.digest);
|
|
const kernel = compileKernelProgram(plan) as {
|
|
operations: { binding: unknown }[];
|
|
model: { edges: { a: { onDelete: string }; b: { onDelete: string } }[] };
|
|
};
|
|
assert.deepEqual(kernel.operations[0]!.binding, { kind: "lifecycle", primitive: "delete" });
|
|
assert.equal(kernel.model.edges[0]!.a.onDelete, "cascade-other");
|
|
assert.equal(kernel.model.edges[0]!.b.onDelete, "detach");
|
|
});
|
|
test("deletion rejects browser, snapshot, remote, class, payload and unknown primitive promises", () => {
|
|
for (const [iface, ws] of [
|
|
[contract.replace("targets [server]", "targets [browser, server]"), workspace],
|
|
[contract.replace("transaction targets", "snapshot targets"), workspace],
|
|
[contract.replace("execution transaction targets [server]", "execution remote"), workspace],
|
|
[contract.replace("execution transaction targets [server]", ""), workspace],
|
|
[contract.replace("operation remove", "static operation remove"), workspace],
|
|
[contract.replace("unit -> unit", "string -> unit"), workspace],
|
|
[contract.replace("unit -> unit", "unit -> string"), workspace],
|
|
[contract, workspace.replace("lifecycle.delete", "lifecycle.resurrect")],
|
|
]) {
|
|
const result = compile(iface, ws);
|
|
assert.equal(result.ok, false, iface + ws);
|
|
assert.ok(
|
|
result.diagnostics.some((d) =>
|
|
["invalid-execution-contract", "invalid-lifecycle-binding", "invalid-package-binding"].includes(d.code),
|
|
),
|
|
JSON.stringify(result.diagnostics),
|
|
);
|
|
}
|
|
});
|