Add activated workspace reflection and Studio definition watches
Expose bounded snapshot-bound definition reads and latest-only watches from the serving checked bundle. Add checked reflection dependency ports, generated SDK bindings and selector-scoped invocation authority. Move Studio factory, contract and query discovery to public reflection inventories. Share an active-definition watch across canvas and standalone routes and invalidate/reload on epoch changes instead of polling GetWorkspace. Document the API and deferred scope; cover compiler/codegen, SDK injection, transport authorization, activation publication, pagination and reconnect behavior. Keep all work local; no deployment or publication.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { create } from "@bufbuild/protobuf";
|
||||
import { InjectedDependencySchema } from "../dist/quixos/refs_pb.js";
|
||||
import { DefinitionPageSchema } from "../dist/quixos/orch_pb.js";
|
||||
import { createRuntimeContext, bindQxHandler } from "../dist/index.js";
|
||||
|
||||
test("checked reflection bindings preserve injected scope, selector authority and cancellation", async () => {
|
||||
const seen = [];
|
||||
const page = create(DefinitionPageSchema, { identity: { workspaceId: "ws", workspaceEpoch: "7" } });
|
||||
const signal = new AbortController().signal;
|
||||
const raw = createRuntimeContext(
|
||||
{},
|
||||
{
|
||||
readDefinitions: async (request) => {
|
||||
seen.push(request);
|
||||
return page;
|
||||
},
|
||||
async *watchDefinitions(request, options) {
|
||||
assert.equal(options.signal, signal);
|
||||
seen.push(request);
|
||||
yield page;
|
||||
},
|
||||
},
|
||||
{
|
||||
objectId: "",
|
||||
input: {},
|
||||
dependencies: [
|
||||
create(InjectedDependencySchema, {
|
||||
portId: "meta",
|
||||
binding: { case: "reflection", value: { workspaceId: "ws", workspaceEpoch: "7", selectors: ["atoms"] } },
|
||||
}),
|
||||
],
|
||||
},
|
||||
);
|
||||
const handler = bindQxHandler(
|
||||
{
|
||||
receiver: "none",
|
||||
inputType: { kind: "builtin", name: "unit" },
|
||||
outputType: { kind: "builtin", name: "unit" },
|
||||
ports: { meta: { kind: "reflection", id: "meta", selectors: ["atoms"] } },
|
||||
},
|
||||
async (context) => {
|
||||
await context.ports.meta.read({ selector: { kind: "atoms" }, workspaceId: "forged", workspaceEpoch: "9" });
|
||||
for await (const result of context.ports.meta.watch({ selector: { kind: "atoms" } }, signal))
|
||||
assert.equal(result, page);
|
||||
assert.throws(() => context.ports.meta.read({ selector: { kind: "queries" } }), /Undeclared reflection/);
|
||||
},
|
||||
{},
|
||||
);
|
||||
await handler(raw);
|
||||
assert.equal(seen.length, 2);
|
||||
for (const request of seen) {
|
||||
assert.equal(request.workspaceId, "ws");
|
||||
assert.equal(request.workspaceEpoch, "7");
|
||||
}
|
||||
assert.throws(() => raw.reflection("missing"), /Missing/);
|
||||
});
|
||||
Reference in New Issue
Block a user