Implement main-thread Camino sessions and synchronous CRDT editing

This commit is contained in:
Timothy J. Aveni
2026-09-27 23:57:29 -07:00
parent ad72185a6c
commit 696023b4ba
24 changed files with 3784 additions and 3218 deletions
+17
View File
@@ -154,3 +154,20 @@ await writeFile("dist/portable-reader/compound-crdt/kernel.json", JSON.stringify
const { emitExecutionScaffold } = await import("./execution-scaffold-fixture.js");
const executionScaffold = await emitExecutionScaffold("dist/portable-reader/execution-scaffold/source");
await writeFile("dist/portable-reader/execution-scaffold/plan.json", JSON.stringify(executionScaffold));
// Native variant fixture shared by generated-type and browser editing qualification.
const { readFile } = await import("node:fs/promises");
const { compileCapabilityResourceSource } = await import("../src/capability-language/index.js");
const { portableValueSchema, tsType } = await import("../src/bindings/portable.js");
const variantSource = compileCapabilityResourceSource(await readFile("test/fixtures/canvas-content.qx", "utf8"), {
source: { repository: "https://example.test/canvas-content.git", commit: "a".repeat(40) },
});
if (!variantSource.ok || variantSource.resource.kind !== "interface") throw Error("Invalid variant fixture");
const entries = variantSource.resource.revision.members[0];
if (entries.kind !== "value") throw Error("Expected entries value");
await mkdir("dist/portable-reader/variants", { recursive: true });
await writeFile("dist/portable-reader/variants/schema.json", JSON.stringify(portableValueSchema(entries.valueType)));
await writeFile(
"dist/portable-reader/variants/entries.ts",
"export type Entries = " + tsType(entries.valueType) + ";\n",
);
+12
View File
@@ -0,0 +1,12 @@
type Point = record { x:double; y:double; };
type Entry = variant id "canvas:entry@1" {
paragraph id "canvas:paragraph" : record { text:string; };
stroke id "canvas:stroke" : record { points:list<Point>; };
image id "canvas:image" : record { asset:string; };
};
interface CanvasContent id "canvas" revision "canvas@1" {
queryable value entries id "entries" : list<Entry> {
get id "entries:get" execution snapshot targets [browser,server];
edit id "entries:edit" execution transaction targets [browser,server];
}
}
+82
View File
@@ -0,0 +1,82 @@
import { readFileSync } from "node:fs";
import assert from "node:assert/strict";
import { test } from "node:test";
import { compileCapabilityResourceSource } from "../src/capability-language/index.js";
import { compileQuery } from "../src/query/compile.js";
import { defaultQueryBudgets } from "../src/query/types.js";
import { portableValueSchema, tsType } from "../src/bindings/portable.js";
import { isStorableType, TypeSubstitution } from "../src/capability-model/index.js";
const source = { repository: "https://example.test/variants.git", commit: "a".repeat(40) };
const declaration = readFileSync("test/fixtures/canvas-content.qx", "utf8");
const result = compileCapabilityResourceSource(declaration, { source });
assert.ok(result.ok, JSON.stringify(result.diagnostics));
if (result.resource.kind !== "interface") throw Error("Expected interface");
const iface = result.resource.revision;
const entries = iface.members[0];
if (entries.kind !== "value") throw Error("Expected value");
test("native variant aliases lower into nominal cases with typed payloads", () => {
assert.equal(entries.valueType.kind, "list");
assert.ok(isStorableType(entries.valueType));
const schema = portableValueSchema(entries.valueType) as any;
assert.equal(schema.value.id, "canvas:entry@1");
assert.equal(schema.value.cases.stroke.id, "canvas:stroke");
assert.match(tsType(entries.valueType), /kind: "stroke"/);
assert.match(tsType(entries.valueType), /ReadonlyArray<.*"x": number/);
const substitution = new TypeSubstitution({
arguments: new Map([["T", { kind: "value", type: { kind: "scalar", name: "string" } }]]),
applyInterface: () => {
throw Error("unused");
},
implementsInterface: () => false,
});
assert.deepEqual(
substitution.value({
kind: "variant",
id: "box",
cases: { some: { id: "box:some", value: { kind: "parameter", parameterId: "T" } } },
}),
{ kind: "variant", id: "box", cases: { some: { id: "box:some", value: { kind: "scalar", name: "string" } } } },
);
});
test("variant query scalars keep their checked payload type and reject branch selection", async () => {
const query = {
id: "canvas-query",
displayName: "Canvas",
root: { kind: "object" as const, interface: iface.revisionId },
document: "canvas.graphql",
operation: "Canvas",
fragments: [],
views: [],
allowances: [],
budgets: { ...defaultQueryBudgets },
watch: true,
};
const checked = await compileQuery(query, [iface], async () => `query Canvas { root { entries } }`);
assert.equal(checked.output.kind, "record");
if (checked.output.kind !== "record") return;
const root = checked.output.fields.root;
assert.equal(root.kind, "record");
if (root.kind !== "record") return;
assert.deepEqual(root.fields.entries, entries.valueType);
await assert.rejects(compileQuery(query, [iface], async () => `query Canvas { root { entries { kind value } } }`));
});
test("unknown and duplicate cases fail; reference payloads remain nonstorable", () => {
const duplicate = compileCapabilityResourceSource(declaration.replace('"canvas:image"', '"canvas:stroke"'), {
source,
});
assert.equal(duplicate.ok, false);
assert.ok(
!isStorableType({
kind: "variant",
id: "transport",
cases: {
ref: {
id: "ref",
value: { kind: "object-ref", expectation: { kind: "interface", interfaceRevisionId: iface.revisionId } },
},
},
}),
);
});