Format authored monorepo code with pinned language formatters

This commit is contained in:
Timothy J. Aveni
2026-09-15 15:23:24 -07:00
parent bee4452852
commit 0d3c013c07
12 changed files with 1223 additions and 674 deletions
+151 -64
View File
@@ -1,108 +1,192 @@
import assert from "node:assert/strict";
import test from "node:test";
import { referenceFromWire } from "../dist/references.js";
import { bindQxHandler, decodeQxValue, encodeQxValue, jsToProtoValue, liveValue, protoValueToJs, opaqueReactPropsBinding } from "../dist/index.js";
import {
bindQxHandler,
decodeQxValue,
encodeQxValue,
jsToProtoValue,
liveValue,
protoValueToJs,
opaqueReactPropsBinding,
} from "../dist/index.js";
const scalar = (name) => ({ kind: "scalar", name });
const unit = { kind: "builtin", name: "unit" };
test("opaque React props retain managed references while ordinary messages remain closed", () => {
const descriptorId = "org.quixos.web-studio.ReactProps";
const reference = referenceFromWire("obj:task");
const type = {kind: "message", descriptorId};
const messages = {[descriptorId]: opaqueReactPropsBinding};
const decoded = decodeQxValue(type, encodeQxValue(type, {subject: reference, title: "Task"}, messages), messages);
const type = { kind: "message", descriptorId };
const messages = { [descriptorId]: opaqueReactPropsBinding };
const decoded = decodeQxValue(type, encodeQxValue(type, { subject: reference, title: "Task" }, messages), messages);
assert.ok(decoded.subject.equals(reference));
assert.equal(decoded.title, "Task");
assert.throws(() => opaqueReactPropsBinding.encode(null), /object/);
assert.throws(() => opaqueReactPropsBinding.encode([]), /object/);
assert.throws(() => encodeQxValue({kind: "message", descriptorId: "Ordinary"}, {subject: reference},
{Ordinary: opaqueReactPropsBinding}), /Managed references/);
assert.throws(
() =>
encodeQxValue(
{ kind: "message", descriptorId: "Ordinary" },
{ subject: reference },
{ Ordinary: opaqueReactPropsBinding },
),
/Managed references/,
);
});
test("declared record inputs preserve opaque references without opening message codecs", async () => {
const target = referenceFromWire("obj:board");
const type = {kind: "record", fields: {
target: {kind: "object-ref", expectation: {kind: "atom", atomId: "board"}},
x: scalar("double"), note: {kind: "optional", value: scalar("string")},
}};
const encoded = encodeQxValue(type, {target, x: 12}, {});
const type = {
kind: "record",
fields: {
target: { kind: "object-ref", expectation: { kind: "atom", atomId: "board" } },
x: scalar("double"),
note: { kind: "optional", value: scalar("string") },
},
};
const encoded = encodeQxValue(type, { target, x: 12 }, {});
const decoded = decodeQxValue(type, encoded, {});
assert.ok(decoded.target.equals(target));
assert.equal(decoded.x, 12);
assert.equal(decoded.note, null);
assert.throws(() => JSON.stringify(decoded), /cannot be serialized/);
assert.throws(() => encodeQxValue(type, {target, x: 12, hidden: target}, {}), /Unexpected/);
assert.throws(() => encodeQxValue(type, {x: 12}, {}), /Missing/);
assert.throws(() => encodeQxValue(type, {target: "obj:board", x: 12}, {}), /opaque object reference/);
const handler = bindQxHandler({inputType: type, outputType: unit, ports: {}}, async (context) => {
assert.ok(context.input.target.equals(target));
assert.equal(context.input.x, 12);
}, {});
await handler({objectId: target, inputProto: encoded.kind.value.fields});
assert.throws(() => encodeQxValue(type, { target, x: 12, hidden: target }, {}), /Unexpected/);
assert.throws(() => encodeQxValue(type, { x: 12 }, {}), /Missing/);
assert.throws(() => encodeQxValue(type, { target: "obj:board", x: 12 }, {}), /opaque object reference/);
const handler = bindQxHandler(
{ inputType: type, outputType: unit, ports: {} },
async (context) => {
assert.ok(context.input.target.equals(target));
assert.equal(context.input.x, 12);
},
{},
);
await handler({ objectId: target, inputProto: encoded.kind.value.fields });
});
test("typed sessions rebind ports and cancellation to each acquired invocation", async () => {
const first = new AbortController(), second = new AbortController();
const first = new AbortController(),
second = new AbortController();
let closed = false;
const context = (value, signal) => ({objectId: referenceFromWire("obj:owner"), inputProto: {}, signal,
state: () => ({live: async () => liveValue(jsToProtoValue(value))})});
const raw = {...context(1n, first.signal), openSession: async () => ({id: "session:test",
run: (work) => work(context(2n, second.signal)), close: async () => {closed = true;}})};
const handler = bindQxHandler({inputType: unit, outputType: unit, ports: {counter: {kind: "state", id: "counter", valueType: scalar("int64"), primitives: ["read"]}}}, async (bound) => {
assert.equal(bound.signal, first.signal);
const session = await bound.openSession();
await session.run(async (next) => {
assert.equal(next.signal, second.signal);
assert.equal(await next.ports.counter.get(), 2n);
assert.equal(next.openSession, undefined);
});
await session.close();
}, {});
const context = (value, signal) => ({
objectId: referenceFromWire("obj:owner"),
inputProto: {},
signal,
state: () => ({ live: async () => liveValue(jsToProtoValue(value)) }),
});
const raw = {
...context(1n, first.signal),
openSession: async () => ({
id: "session:test",
run: (work) => work(context(2n, second.signal)),
close: async () => {
closed = true;
},
}),
};
const handler = bindQxHandler(
{
inputType: unit,
outputType: unit,
ports: { counter: { kind: "state", id: "counter", valueType: scalar("int64"), primitives: ["read"] } },
},
async (bound) => {
assert.equal(bound.signal, first.signal);
const session = await bound.openSession();
await session.run(async (next) => {
assert.equal(next.signal, second.signal);
assert.equal(await next.ports.counter.get(), 2n);
assert.equal(next.openSession, undefined);
});
await session.close();
},
{},
);
await handler(raw);
assert.equal(closed, true);
});
test("binding codecs round trip nested bytes, 64-bit integers, nulls, and references", () => {
const values = [[scalar("int64"), -(2n ** 63n)], [scalar("uint64"), 2n ** 64n - 1n],
const values = [
[scalar("int64"), -(2n ** 63n)],
[scalar("uint64"), 2n ** 64n - 1n],
[scalar("bytes"), new Uint8Array([0, 255])],
[{ kind: "list", value: { kind: "optional", value: scalar("int64") } }, [null, 2n ** 60n]],
[{ kind: "object-ref", expectation: { kind: "atom", atomId: "thing" } }, referenceFromWire("obj:thing")]];
[{ kind: "object-ref", expectation: { kind: "atom", atomId: "thing" } }, referenceFromWire("obj:thing")],
];
for (const [type, value] of values) assert.deepEqual(decodeQxValue(type, encodeQxValue(type, value, {}), {}), value);
});
test("opaque references pass declared RPC boundaries but cannot enter ordinary data", () => {
const reference = referenceFromWire("obj:thing");
const type = {kind: "object-ref", expectation: {kind: "atom", atomId: "thing"}};
const type = { kind: "object-ref", expectation: { kind: "atom", atomId: "thing" } };
const roundtrip = decodeQxValue(type, encodeQxValue(type, reference, {}), {});
assert.equal(reference.equals(roundtrip), true);
assert.equal(reference.equals(referenceFromWire("obj:other")), false);
assert.throws(() => JSON.stringify({nested: [reference]}), /cannot be serialized/);
assert.throws(() => JSON.stringify({ nested: [reference] }), /cannot be serialized/);
assert.throws(() => String(reference), /cannot be coerced/);
assert.throws(() => encodeQxValue(type, "obj:thing", {}), /opaque/);
assert.throws(() => encodeQxValue(scalar("string"), reference, {}), /Managed references/);
const message = {kind: "message", descriptorId: "Payload"};
assert.throws(() => encodeQxValue(message, {nested: reference}, {Payload: {encode: jsToProtoValue}}), /Managed references/);
assert.throws(() => encodeQxValue(message, {}, {Payload: {encode: () => jsToProtoValue(reference)}}), /Managed references/);
assert.throws(() => decodeQxValue(message, jsToProtoValue(reference), {Payload: {decode: () => ({})}}), /Managed references/);
const message = { kind: "message", descriptorId: "Payload" };
assert.throws(
() => encodeQxValue(message, { nested: reference }, { Payload: { encode: jsToProtoValue } }),
/Managed references/,
);
assert.throws(
() => encodeQxValue(message, {}, { Payload: { encode: () => jsToProtoValue(reference) } }),
/Managed references/,
);
assert.throws(
() => decodeQxValue(message, jsToProtoValue(reference), { Payload: { decode: () => ({}) } }),
/Managed references/,
);
});
test("typed state and interface ports preserve declared values and exact operation IDs", async () => {
const spec = { inputType: scalar("int64"), outputType: scalar("bytes"), ports: {
data: { kind: "state", id: "state-id", valueType: scalar("int64"), primitives: ["read", "write"] },
reader: { kind: "interface", id: "interface-id", operations: { "payload.get": { id: "get-id", inputType: unit, outputType: scalar("bytes") } } },
} };
const spec = {
inputType: scalar("int64"),
outputType: scalar("bytes"),
ports: {
data: { kind: "state", id: "state-id", valueType: scalar("int64"), primitives: ["read", "write"] },
reader: {
kind: "interface",
id: "interface-id",
operations: { "payload.get": { id: "get-id", inputType: unit, outputType: scalar("bytes") } },
},
},
};
let written;
const handler = bindQxHandler(spec, async ({ input, ports }) => {
assert.equal(input, 2n ** 60n);
assert.equal(await ports.data.get(), 9n);
assert.deepEqual((await ports.data.live()).$quixosValue, jsToProtoValue(9n));
assert.ok(ports.reader.objectId.equals(referenceFromWire("obj:reader")));
assert.deepEqual((await ports.reader.live["payload.get"]()).$quixosValue, jsToProtoValue(new Uint8Array([7])));
await ports.data.set(input);
return ports.reader["payload.get"]();
}, {});
const result = await handler({ inputProto: { value: jsToProtoValue(2n ** 60n) }, objectId: "obj",
state: (id) => { assert.equal(id, "state-id"); return {
live: async () => liveValue(jsToProtoValue(9n)), set: async (value) => { written = value; },
}; },
interface: (id) => { assert.equal(id, "interface-id"); return { objectId: referenceFromWire("obj:reader"), live: async (operation, input) => {
assert.equal(operation, "get-id"); assert.deepEqual(input, {}); return liveValue(jsToProtoValue(new Uint8Array([7])));
} }; },
const handler = bindQxHandler(
spec,
async ({ input, ports }) => {
assert.equal(input, 2n ** 60n);
assert.equal(await ports.data.get(), 9n);
assert.deepEqual((await ports.data.live()).$quixosValue, jsToProtoValue(9n));
assert.ok(ports.reader.objectId.equals(referenceFromWire("obj:reader")));
assert.deepEqual((await ports.reader.live["payload.get"]()).$quixosValue, jsToProtoValue(new Uint8Array([7])));
await ports.data.set(input);
return ports.reader["payload.get"]();
},
{},
);
const result = await handler({
inputProto: { value: jsToProtoValue(2n ** 60n) },
objectId: "obj",
state: (id) => {
assert.equal(id, "state-id");
return {
live: async () => liveValue(jsToProtoValue(9n)),
set: async (value) => {
written = value;
},
};
},
interface: (id) => {
assert.equal(id, "interface-id");
return {
objectId: referenceFromWire("obj:reader"),
live: async (operation, input) => {
assert.equal(operation, "get-id");
assert.deepEqual(input, {});
return liveValue(jsToProtoValue(new Uint8Array([7])));
},
};
},
});
assert.equal(written.$quixosValue.kind.value, String(2n ** 60n));
assert.deepEqual(result.$quixosValue.kind.value, new Uint8Array([7]));
@@ -110,8 +194,11 @@ test("typed state and interface ports preserve declared values and exact operati
test("external message bindings and derived event types are used at the boundary", async () => {
const message = { kind: "message", descriptorId: "Payload" };
const messages = { Payload: { encode: jsToProtoValue, decode: protoValueToJs } };
const handler = bindQxHandler({ inputType: message, outputType: { kind: "builtin", name: "watch-handle" }, eventType: message, ports: {} },
{ kind: "derived", get: ({ input }) => ({ value: input.title }) }, messages);
const handler = bindQxHandler(
{ inputType: message, outputType: { kind: "builtin", name: "watch-handle" }, eventType: message, ports: {} },
{ kind: "derived", get: ({ input }) => ({ value: input.title }) },
messages,
);
assert.equal(handler.kind, "derived");
const result = await handler.get({ objectId: "obj", inputProto: { title: jsToProtoValue("hello") } });
assert.deepEqual(protoValueToJs(result.$quixosValue), { value: "hello" });
+38 -21
View File
@@ -1,30 +1,47 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import crypto from 'node:crypto';
import {spawnSync} from 'node:child_process';
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import crypto from "node:crypto";
import { spawnSync } from "node:child_process";
test('supervised SDK reads a credential file and proves instance identity without an environment token', async t => {
const directory = await fs.mkdtemp(path.join(os.tmpdir(), 'qx-sdk-credential-'));
t.after(() => fs.rm(directory, {recursive:true, force:true}));
const token = crypto.randomBytes(32).toString('hex');
const filename = path.join(directory, 'process-token');
await fs.writeFile(filename, token, {mode:0o600});
const env = {...process.env, CAMINO_RUNTIME_AUTH_TOKEN_FILE: filename,
CAMINO_RUNTIME_AUTH_REQUIRED:'1', QUIXOS_RUNTIME_INSTANCE_ID:'instance:test'};
test("supervised SDK reads a credential file and proves instance identity without an environment token", async (t) => {
const directory = await fs.mkdtemp(path.join(os.tmpdir(), "qx-sdk-credential-"));
t.after(() => fs.rm(directory, { recursive: true, force: true }));
const token = crypto.randomBytes(32).toString("hex");
const filename = path.join(directory, "process-token");
await fs.writeFile(filename, token, { mode: 0o600 });
const env = {
...process.env,
CAMINO_RUNTIME_AUTH_TOKEN_FILE: filename,
CAMINO_RUNTIME_AUTH_REQUIRED: "1",
QUIXOS_RUNTIME_INSTANCE_ID: "instance:test",
};
delete env.CAMINO_RUNTIME_AUTH_TOKEN;
const result = spawnSync(process.execPath, ['--input-type=module', '-e', `
import {createPackageRuntimeRoutes} from ${JSON.stringify(new URL('../dist/index.js', import.meta.url).href)};
const result = spawnSync(
process.execPath,
[
"--input-type=module",
"-e",
`
import {createPackageRuntimeRoutes} from ${JSON.stringify(new URL("../dist/index.js", import.meta.url).href)};
createPackageRuntimeRoutes({packageRevisionId:'package:test',exports:{}})({
service(_type, implementation) { console.log(JSON.stringify(implementation.handshake({nonce:'challenge'}))); }
});
`], {env, encoding:'utf8'});
`,
],
{ env, encoding: "utf8" },
);
assert.equal(result.status, 0, result.stderr);
const handshake = JSON.parse(result.stdout);
assert.equal(handshake.authenticationProof, crypto.createHmac('sha256', token)
.update(JSON.stringify(['challenge','instance:test','package:test'])).digest('hex'));
assert.ok(handshake.capabilities.includes('epoch-grants-v1'));
assert.equal(
handshake.authenticationProof,
crypto
.createHmac("sha256", token)
.update(JSON.stringify(["challenge", "instance:test", "package:test"]))
.digest("hex"),
);
assert.ok(handshake.capabilities.includes("epoch-grants-v1"));
assert.ok(!result.stdout.includes(token));
});
+20 -8
View File
@@ -1,13 +1,25 @@
import test from "node:test";
import assert from "node:assert/strict";
import {createMigrationContext, migrationObjectId} from "../dist/migration.js";
import { createMigrationContext, migrationObjectId } from "../dist/migration.js";
test("migration context offers restricted ports and deterministic helper identities", () => {
const input = {schemaVersion: 1, executionId: "operation:transition", exportId: "migrate", ports: [
{name: "old", binding: "slot:name", view: "old", access: ["read"], states: [{objectId: "obj:one", value: "Alice"}]},
{name: "new", binding: "slot:name", view: "new", access: ["write"]}, {name: "newRead", binding: "slot:name", view: "new", access: ["read"]},
{name: "helpers", binding: "atom:helper", view: "new", access: ["create"]},
]};
const {context, result} = createMigrationContext(input);
const input = {
schemaVersion: 1,
executionId: "operation:transition",
exportId: "migrate",
ports: [
{
name: "old",
binding: "slot:name",
view: "old",
access: ["read"],
states: [{ objectId: "obj:one", value: "Alice" }],
},
{ name: "new", binding: "slot:name", view: "new", access: ["write"] },
{ name: "newRead", binding: "slot:name", view: "new", access: ["read"] },
{ name: "helpers", binding: "atom:helper", view: "new", access: ["create"] },
],
};
const { context, result } = createMigrationContext(input);
assert.equal(context.read("old", "obj:one"), "Alice");
assert.throws(() => context.write("old", "obj:one", "Bob"), /does not grant/);
assert.throws(() => context.read("new", "obj:one"), /does not grant/);
@@ -20,5 +32,5 @@ test("migration context offers restricted ports and deterministic helper identit
assert.equal(helper, migrationObjectId(input.executionId, "helpers", "one"));
assert.equal(context.create("helpers", "one"), helper);
assert.equal(result().creates.length, 1);
assert.deepEqual(input.ports[0].states, [{objectId: "obj:one", value: "Alice"}]);
assert.deepEqual(input.ports[0].states, [{ objectId: "obj:one", value: "Alice" }]);
});
+14 -7
View File
@@ -1,16 +1,23 @@
import test from "node:test";
import assert from "node:assert/strict";
import {relationshipMap, relationshipList, relationshipSet} from "../dist/index.js";
import {referenceFromWire} from "../dist/references.js";
import { relationshipMap, relationshipList, relationshipSet } from "../dist/index.js";
import { referenceFromWire } from "../dist/references.js";
test("relationship helpers preserve handles and require explicit collection revisions", async () => {
let current = {revision: 0n, entries: []}, serial = 0;
const port = {collection: async () => ({revision: current.revision, entries: current.entries.map((entry) => ({...entry}))}),
let current = { revision: 0n, entries: [] },
serial = 0;
const port = {
collection: async () => ({ revision: current.revision, entries: current.entries.map((entry) => ({ ...entry })) }),
replace: async (entries, revision) => {
assert.equal(revision, current.revision);
current = {revision: revision + 1n, entries: entries.map((entry) => ({...entry, edgeId: entry.edgeId ?? `edge:${++serial}`}))};
current = {
revision: revision + 1n,
entries: entries.map((entry) => ({ ...entry, edgeId: entry.edgeId ?? `edge:${++serial}` })),
};
return port.collection();
}};
const a = referenceFromWire("obj:a"), b = referenceFromWire("obj:b");
},
};
const a = referenceFromWire("obj:a"),
b = referenceFromWire("obj:b");
const map = relationshipMap(port);
await map.set("a1", a, 0n);
assert.equal((await map.get("a1")).value.equals(a), true);
+231 -182
View File
@@ -21,11 +21,7 @@ import {
ValueSchema,
ValueSourceSchema,
} from "../dist/camino/api_pb.js";
import {
EdgeDependencySchema,
InjectedDependencySchema,
PackageExportRefSchema,
} from "../dist/quixos/refs_pb.js";
import { EdgeDependencySchema, InjectedDependencySchema, PackageExportRefSchema } from "../dist/quixos/refs_pb.js";
import { InvokeCapabilityResponseSchema, OrchestratorRuntime } from "../dist/quixos/orch_pb.js";
import { DerivedDependencySchema, PackageRuntime } from "../dist/quixos/runtime_pb.js";
@@ -93,26 +89,30 @@ test("runtime context exposes only explicitly injected ports", async () => {
resolveEdge: async () => ({ edges: [] }),
connectEdge: async () => ({}),
};
const context = createRuntimeContext(camino, {}, {
objectId: "obj:task",
input: {},
dependencies: [
create(InjectedDependencySchema, {
portId: "port:title",
binding: { case: "stateSlotId", value: "slot:task:title" },
}),
create(InjectedDependencySchema, {
portId: "port:children",
binding: {
case: "edge",
value: create(EdgeDependencySchema, {
edgeTypeId: "edge:task:children",
projectionId: "projection:task:children",
}),
},
}),
],
});
const context = createRuntimeContext(
camino,
{},
{
objectId: "obj:task",
input: {},
dependencies: [
create(InjectedDependencySchema, {
portId: "port:title",
binding: { case: "stateSlotId", value: "slot:task:title" },
}),
create(InjectedDependencySchema, {
portId: "port:children",
binding: {
case: "edge",
value: create(EdgeDependencySchema, {
edgeTypeId: "edge:task:children",
projectionId: "projection:task:children",
}),
},
}),
],
},
);
assert.equal(await context.state("port:title").get(), "obj:task/slot:task:title");
await context.state("port:title").set("Changed");
@@ -126,23 +126,30 @@ test("runtime context exposes only explicitly injected ports", async () => {
test("injected ports preserve an explicitly traversed object through PackageRuntime RPC", async () => {
const reads = [];
const caminoServer = await listen((router) => router.service(CaminoService, {
readState: (request) => {
reads.push(request);
return { value: jsToProtoValue("Project name") };
},
}));
const runtimeServer = await listen(createPackageRuntimeRoutes({
packageRevisionId: "package:test@1",
caminoUrl: caminoServer.url,
exports: {
"export:test:value": (context) => context.state("port:value").get(),
},
}));
const client = createClient(PackageRuntime, createConnectTransport({
baseUrl: runtimeServer.url,
httpVersion: "1.1",
}));
const caminoServer = await listen((router) =>
router.service(CaminoService, {
readState: (request) => {
reads.push(request);
return { value: jsToProtoValue("Project name") };
},
}),
);
const runtimeServer = await listen(
createPackageRuntimeRoutes({
packageRevisionId: "package:test@1",
caminoUrl: caminoServer.url,
exports: {
"export:test:value": (context) => context.state("port:value").get(),
},
}),
);
const client = createClient(
PackageRuntime,
createConnectTransport({
baseUrl: runtimeServer.url,
httpVersion: "1.1",
}),
);
try {
const response = await client.invoke({
export: create(PackageExportRefSchema, {
@@ -150,11 +157,13 @@ test("injected ports preserve an explicitly traversed object through PackageRunt
exportId: "export:test:value",
}),
objectId: "obj:component",
dependencies: [create(InjectedDependencySchema, {
portId: "port:value",
objectId: "obj:project",
binding: { case: "stateSlotId", value: "slot:project:name" },
})],
dependencies: [
create(InjectedDependencySchema, {
portId: "port:value",
objectId: "obj:project",
binding: { case: "stateSlotId", value: "slot:project:name" },
}),
],
});
assert.equal(response.ok, true);
assert.equal(protoValueToJs(response.result), "Project name");
@@ -178,32 +187,40 @@ test("interface views invoke a related object and propagate transitive live depe
}),
}),
});
const orchServer = await listen((router) => router.service(OrchestratorRuntime, {
invokeCapability: (request) => {
invocations.push(request);
return create(InvokeCapabilityResponseSchema, {
ok: true,
result: sourceValue,
dependencies: [create(DerivedDependencySchema, {
kind: "state",
objectId: "obj:project",
attachmentId: "slot:project:name",
})],
});
},
}));
const runtimeServer = await listen(createPackageRuntimeRoutes({
packageRevisionId: "package:test@1",
orchUrl: orchServer.url,
exports: {
"export:test:value": derived((context) =>
context.interface("port:named").live("operation:named:name:get")),
},
}));
const client = createClient(PackageRuntime, createConnectTransport({
baseUrl: runtimeServer.url,
httpVersion: "1.1",
}));
const orchServer = await listen((router) =>
router.service(OrchestratorRuntime, {
invokeCapability: (request) => {
invocations.push(request);
return create(InvokeCapabilityResponseSchema, {
ok: true,
result: sourceValue,
dependencies: [
create(DerivedDependencySchema, {
kind: "state",
objectId: "obj:project",
attachmentId: "slot:project:name",
}),
],
});
},
}),
);
const runtimeServer = await listen(
createPackageRuntimeRoutes({
packageRevisionId: "package:test@1",
orchUrl: orchServer.url,
exports: {
"export:test:value": derived((context) => context.interface("port:named").live("operation:named:name:get")),
},
}),
);
const client = createClient(
PackageRuntime,
createConnectTransport({
baseUrl: runtimeServer.url,
httpVersion: "1.1",
}),
);
try {
const response = await client.invoke({
export: create(PackageExportRefSchema, {
@@ -211,11 +228,13 @@ test("interface views invoke a related object and propagate transitive live depe
exportId: "export:test:value",
}),
objectId: "obj:component",
dependencies: [create(InjectedDependencySchema, {
portId: "port:named",
objectId: "obj:project",
binding: { case: "interfaceRevisionId", value: "interface:named@1" },
})],
dependencies: [
create(InjectedDependencySchema, {
portId: "port:named",
objectId: "obj:project",
binding: { case: "interfaceRevisionId", value: "interface:named@1" },
}),
],
});
assert.equal(response.ok, true);
assert.equal(invocations[0]?.objectId, "obj:project");
@@ -232,64 +251,80 @@ test("interface views invoke a related object and propagate transitive live depe
test("derived interface views reread after their transitive subscriptions become live", async () => {
let current = "before subscription";
let invocationCount = 0;
const caminoServer = await listen((router) => router.service(CaminoService, {
watchObject: async function* (request, context) {
// Model a write racing the first nested capability read. Camino makes
// the subscription live before yielding this snapshot.
current = "after subscription";
yield {
objectId: request.objectId,
snapshot: create(CaminoObjectSchema, {
id: request.objectId,
atomId: "atom:project",
workspaceRevisionId: "workspace:test@1",
}),
};
await new Promise((resolve) =>
context.signal.addEventListener("abort", resolve, { once: true }));
},
}));
const orchServer = await listen((router) => router.service(OrchestratorRuntime, {
invokeCapability: () => {
invocationCount += 1;
return create(InvokeCapabilityResponseSchema, {
ok: true,
result: jsToProtoValue(current),
dependencies: [create(DerivedDependencySchema, {
kind: "state",
objectId: "obj:project",
attachmentId: "slot:project:name",
})],
});
},
}));
const runtimeServer = await listen(createPackageRuntimeRoutes({
packageRevisionId: "package:test@1",
caminoUrl: caminoServer.url,
orchUrl: orchServer.url,
exports: {
"export:test:value": derived((context) =>
context.interface("port:named").invoke("operation:named:name:get")),
},
}));
const client = createClient(PackageRuntime, createConnectTransport({
baseUrl: runtimeServer.url,
httpVersion: "1.1",
}));
const caminoServer = await listen((router) =>
router.service(CaminoService, {
watchObject: async function* (request, context) {
// Model a write racing the first nested capability read. Camino makes
// the subscription live before yielding this snapshot.
current = "after subscription";
yield {
objectId: request.objectId,
snapshot: create(CaminoObjectSchema, {
id: request.objectId,
atomId: "atom:project",
workspaceRevisionId: "workspace:test@1",
}),
};
await new Promise((resolve) => context.signal.addEventListener("abort", resolve, { once: true }));
},
}),
);
const orchServer = await listen((router) =>
router.service(OrchestratorRuntime, {
invokeCapability: () => {
invocationCount += 1;
return create(InvokeCapabilityResponseSchema, {
ok: true,
result: jsToProtoValue(current),
dependencies: [
create(DerivedDependencySchema, {
kind: "state",
objectId: "obj:project",
attachmentId: "slot:project:name",
}),
],
});
},
}),
);
const runtimeServer = await listen(
createPackageRuntimeRoutes({
packageRevisionId: "package:test@1",
caminoUrl: caminoServer.url,
orchUrl: orchServer.url,
exports: {
"export:test:value": derived((context) => context.interface("port:named").invoke("operation:named:name:get")),
},
}),
);
const client = createClient(
PackageRuntime,
createConnectTransport({
baseUrl: runtimeServer.url,
httpVersion: "1.1",
}),
);
const controller = new AbortController();
try {
const stream = client.watch({
export: create(PackageExportRefSchema, {
packageRevisionId: "package:test@1",
exportId: "export:test:value",
}),
objectId: "obj:component",
dependencies: [create(InjectedDependencySchema, {
portId: "port:named",
objectId: "obj:project",
binding: { case: "interfaceRevisionId", value: "interface:named@1" },
})],
}, { signal: controller.signal })[Symbol.asyncIterator]();
const stream = client
.watch(
{
export: create(PackageExportRefSchema, {
packageRevisionId: "package:test@1",
exportId: "export:test:value",
}),
objectId: "obj:component",
dependencies: [
create(InjectedDependencySchema, {
portId: "port:named",
objectId: "obj:project",
binding: { case: "interfaceRevisionId", value: "interface:named@1" },
}),
],
},
{ signal: controller.signal },
)
[Symbol.asyncIterator]();
const initial = await stream.next();
assert.equal(protoValueToJs(initial.value?.value), "after subscription");
assert.equal(invocationCount, 2);
@@ -305,56 +340,70 @@ test("derived watches subscribe before reading and emit only real changes", asyn
let current = "before";
let subscribed = false;
const changes = [];
const caminoServer = await listen((router) => router.service(CaminoService, {
readState: () => {
assert.equal(subscribed, true, "the dependency stream must be live before the state read");
return { value: jsToProtoValue(current) };
},
watchObject: async function* (request, context) {
subscribed = true;
yield {
objectId: request.objectId,
snapshot: create(CaminoObjectSchema, {
id: request.objectId,
atomId: "atom:test",
workspaceRevisionId: "workspace:test@1",
}),
};
while (!context.signal.aborted) {
const changed = await new Promise((resolve) => {
const finish = () => resolve(true);
changes.push(finish);
context.signal.addEventListener("abort", () => resolve(false), { once: true });
});
if (!changed) return;
yield { objectId: request.objectId };
}
},
}));
const runtimeServer = await listen(createPackageRuntimeRoutes({
packageRevisionId: "package:test@1",
caminoUrl: caminoServer.url,
exports: {
"export:test:value": derived((context) => context.state("port:value").get()),
},
}));
const client = createClient(PackageRuntime, createConnectTransport({
baseUrl: runtimeServer.url,
httpVersion: "1.1",
}));
const caminoServer = await listen((router) =>
router.service(CaminoService, {
readState: () => {
assert.equal(subscribed, true, "the dependency stream must be live before the state read");
return { value: jsToProtoValue(current) };
},
watchObject: async function* (request, context) {
subscribed = true;
yield {
objectId: request.objectId,
snapshot: create(CaminoObjectSchema, {
id: request.objectId,
atomId: "atom:test",
workspaceRevisionId: "workspace:test@1",
}),
};
while (!context.signal.aborted) {
const changed = await new Promise((resolve) => {
const finish = () => resolve(true);
changes.push(finish);
context.signal.addEventListener("abort", () => resolve(false), { once: true });
});
if (!changed) return;
yield { objectId: request.objectId };
}
},
}),
);
const runtimeServer = await listen(
createPackageRuntimeRoutes({
packageRevisionId: "package:test@1",
caminoUrl: caminoServer.url,
exports: {
"export:test:value": derived((context) => context.state("port:value").get()),
},
}),
);
const client = createClient(
PackageRuntime,
createConnectTransport({
baseUrl: runtimeServer.url,
httpVersion: "1.1",
}),
);
const controller = new AbortController();
try {
const stream = client.watch({
export: create(PackageExportRefSchema, {
packageRevisionId: "package:test@1",
exportId: "export:test:value",
}),
objectId: "obj:test",
dependencies: [create(InjectedDependencySchema, {
portId: "port:value",
binding: { case: "stateSlotId", value: "slot:test:value" },
})],
}, { signal: controller.signal })[Symbol.asyncIterator]();
const stream = client
.watch(
{
export: create(PackageExportRefSchema, {
packageRevisionId: "package:test@1",
exportId: "export:test:value",
}),
objectId: "obj:test",
dependencies: [
create(InjectedDependencySchema, {
portId: "port:value",
binding: { case: "stateSlotId", value: "slot:test:value" },
}),
],
},
{ signal: controller.signal },
)
[Symbol.asyncIterator]();
const initial = await stream.next();
assert.equal(protoValueToJs(initial.value?.value), "before");
assert.equal(initial.value?.initial, true);