Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 79fbee2b32 | |||
| 8480674212 |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"sourceRepo": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos",
|
"sourceRepo": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos",
|
||||||
"sourceCommit": "351b7d74d316380481d8fcf212e03d6ec777a2f3",
|
"sourceCommit": "61cb9aa5a580c2846d426464228c7d1082b7021a",
|
||||||
"sourcePath": "quixos-instance/packages/camino-package-runtime",
|
"sourcePath": "quixos-instance/packages/camino-package-runtime",
|
||||||
"exportName": "camino-package-runtime",
|
"exportName": "camino-package-runtime",
|
||||||
"mirrorRemote": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git"
|
"mirrorRemote": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git"
|
||||||
|
|||||||
Vendored
+3
@@ -35,6 +35,9 @@ export type QxValueType = {
|
|||||||
} | {
|
} | {
|
||||||
kind: "message";
|
kind: "message";
|
||||||
descriptorId: string;
|
descriptorId: string;
|
||||||
|
} | {
|
||||||
|
kind: "record";
|
||||||
|
fields: Record<string, QxValueType>;
|
||||||
} | {
|
} | {
|
||||||
kind: "object-ref";
|
kind: "object-ref";
|
||||||
expectation: unknown;
|
expectation: unknown;
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"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"}
|
||||||
Vendored
+24
-2
@@ -7,8 +7,18 @@ export const qxDerived = (get) => ({ kind: "derived", get });
|
|||||||
export const decodeQxValue = (type, value, messages) => {
|
export const decodeQxValue = (type, value, messages) => {
|
||||||
if (type.kind === "builtin" && type.name === "unit")
|
if (type.kind === "builtin" && type.name === "unit")
|
||||||
return null;
|
return null;
|
||||||
|
if (type.kind === "optional" && !value)
|
||||||
|
return null;
|
||||||
if (!value)
|
if (!value)
|
||||||
throw new Error("Missing QX wire value");
|
throw new Error("Missing QX wire value");
|
||||||
|
if (type.kind === "record") {
|
||||||
|
if (value.kind.case !== "objectValue")
|
||||||
|
throw new Error("Expected QX record");
|
||||||
|
const fields = value.kind.value.fields;
|
||||||
|
if (Object.keys(fields).some((name) => !Object.hasOwn(type.fields, name)))
|
||||||
|
throw new Error("Unexpected QX record field");
|
||||||
|
return Object.fromEntries(Object.entries(type.fields).map(([name, field]) => [name, decodeQxValue(field, fields[name], messages)]));
|
||||||
|
}
|
||||||
if (type.kind === "optional")
|
if (type.kind === "optional")
|
||||||
return value.kind.case === "nullValue" ? null : decodeQxValue(type.value, value, messages);
|
return value.kind.case === "nullValue" ? null : decodeQxValue(type.value, value, messages);
|
||||||
if (type.kind === "list") {
|
if (type.kind === "list") {
|
||||||
@@ -52,6 +62,18 @@ const requireMessage = (messages, id) => {
|
|||||||
export const encodeQxValue = (type, value, messages) => {
|
export const encodeQxValue = (type, value, messages) => {
|
||||||
if (type.kind === "builtin" && type.name === "unit")
|
if (type.kind === "builtin" && type.name === "unit")
|
||||||
return jsToProtoValue(null);
|
return jsToProtoValue(null);
|
||||||
|
if (type.kind === "record") {
|
||||||
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
||||||
|
throw new Error("Expected QX record");
|
||||||
|
if (Object.keys(value).some((name) => !Object.hasOwn(type.fields, name)))
|
||||||
|
throw new Error("Unexpected QX record field");
|
||||||
|
const fields = Object.fromEntries(Object.entries(type.fields).map(([name, field]) => {
|
||||||
|
if (!Object.hasOwn(value, name) && field.kind !== "optional")
|
||||||
|
throw new Error(`Missing QX record field ${name}`);
|
||||||
|
return [name, encodeQxValue(field, value[name] ?? (field.kind === "optional" ? null : value[name]), messages)];
|
||||||
|
}));
|
||||||
|
return create(ValueSchema, { kind: { case: "objectValue", value: create(ObjectValueSchema, { fields }) } });
|
||||||
|
}
|
||||||
if (type.kind === "optional")
|
if (type.kind === "optional")
|
||||||
return value === null ? jsToProtoValue(null) : encodeQxValue(type.value, value, messages);
|
return value === null ? jsToProtoValue(null) : encodeQxValue(type.value, value, messages);
|
||||||
if (type.kind === "list")
|
if (type.kind === "list")
|
||||||
@@ -69,7 +91,7 @@ export const encodeQxValue = (type, value, messages) => {
|
|||||||
return jsToProtoValue(value);
|
return jsToProtoValue(value);
|
||||||
};
|
};
|
||||||
const inputValue = (context, type) => {
|
const inputValue = (context, type) => {
|
||||||
if (type.kind === "message")
|
if (type.kind === "message" || type.kind === "record")
|
||||||
return create(ValueSchema, { kind: { case: "objectValue",
|
return create(ValueSchema, { kind: { case: "objectValue",
|
||||||
value: create(ObjectValueSchema, { fields: context.inputProto }) } });
|
value: create(ObjectValueSchema, { fields: context.inputProto }) } });
|
||||||
return context.inputProto.value;
|
return context.inputProto.value;
|
||||||
@@ -78,7 +100,7 @@ const inputFields = (type, value, messages) => {
|
|||||||
if (type.kind === "builtin" && type.name === "unit")
|
if (type.kind === "builtin" && type.name === "unit")
|
||||||
return {};
|
return {};
|
||||||
const encoded = encodeQxValue(type, value, messages);
|
const encoded = encodeQxValue(type, value, messages);
|
||||||
if (type.kind === "message") {
|
if (type.kind === "message" || type.kind === "record") {
|
||||||
if (encoded.kind.case !== "objectValue")
|
if (encoded.kind.case !== "objectValue")
|
||||||
throw new Error("Message inputs must encode an object value");
|
throw new Error("Message inputs must encode an object value");
|
||||||
return Object.fromEntries(Object.entries(encoded.kind.value.fields).map(([key, entry]) => [key, liveValue(entry)]));
|
return Object.fromEntries(Object.entries(encoded.kind.value.fields).map(([key, entry]) => [key, liveValue(entry)]));
|
||||||
|
|||||||
+19
-2
@@ -20,6 +20,7 @@ export type QxValueType =
|
|||||||
| { kind: "builtin"; name: "unit" | "watch-handle" }
|
| { kind: "builtin"; name: "unit" | "watch-handle" }
|
||||||
| { kind: "scalar"; name: string }
|
| { kind: "scalar"; name: string }
|
||||||
| { kind: "message"; descriptorId: string }
|
| { kind: "message"; descriptorId: string }
|
||||||
|
| { kind: "record"; fields: Record<string, QxValueType> }
|
||||||
| { kind: "object-ref"; expectation: unknown }
|
| { kind: "object-ref"; expectation: unknown }
|
||||||
| { kind: "optional" | "list"; value: QxValueType };
|
| { kind: "optional" | "list"; value: QxValueType };
|
||||||
export type QxOperationSpec = { id: string; inputType: QxValueType; outputType: QxValueType };
|
export type QxOperationSpec = { id: string; inputType: QxValueType; outputType: QxValueType };
|
||||||
@@ -37,7 +38,14 @@ export type QxMessages = Record<string, MessageBinding<any>>;
|
|||||||
// Conversion belongs at the binding boundary. It does not add orchestrator validation.
|
// Conversion belongs at the binding boundary. It does not add orchestrator validation.
|
||||||
export const decodeQxValue = (type: QxValueType, value: Value | undefined, messages: QxMessages): any => {
|
export const decodeQxValue = (type: QxValueType, value: Value | undefined, messages: QxMessages): any => {
|
||||||
if (type.kind === "builtin" && type.name === "unit") return null;
|
if (type.kind === "builtin" && type.name === "unit") return null;
|
||||||
|
if (type.kind === "optional" && !value) return null;
|
||||||
if (!value) throw new Error("Missing QX wire value");
|
if (!value) throw new Error("Missing QX wire value");
|
||||||
|
if (type.kind === "record") {
|
||||||
|
if (value.kind.case !== "objectValue") throw new Error("Expected QX record");
|
||||||
|
const fields = value.kind.value.fields;
|
||||||
|
if (Object.keys(fields).some((name) => !Object.hasOwn(type.fields, name))) throw new Error("Unexpected QX record field");
|
||||||
|
return Object.fromEntries(Object.entries(type.fields).map(([name, field]) => [name, decodeQxValue(field, fields[name], messages)]));
|
||||||
|
}
|
||||||
if (type.kind === "optional") return value.kind.case === "nullValue" ? null : decodeQxValue(type.value, value, messages);
|
if (type.kind === "optional") return value.kind.case === "nullValue" ? null : decodeQxValue(type.value, value, messages);
|
||||||
if (type.kind === "list") {
|
if (type.kind === "list") {
|
||||||
if (value.kind.case !== "listValue") throw new Error("Expected QX list");
|
if (value.kind.case !== "listValue") throw new Error("Expected QX list");
|
||||||
@@ -74,6 +82,15 @@ const requireMessage = (messages: QxMessages, id: string) => {
|
|||||||
};
|
};
|
||||||
export const encodeQxValue = (type: QxValueType, value: any, messages: QxMessages): Value => {
|
export const encodeQxValue = (type: QxValueType, value: any, messages: QxMessages): Value => {
|
||||||
if (type.kind === "builtin" && type.name === "unit") return jsToProtoValue(null);
|
if (type.kind === "builtin" && type.name === "unit") return jsToProtoValue(null);
|
||||||
|
if (type.kind === "record") {
|
||||||
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Expected QX record");
|
||||||
|
if (Object.keys(value).some((name) => !Object.hasOwn(type.fields, name))) throw new Error("Unexpected QX record field");
|
||||||
|
const fields = Object.fromEntries(Object.entries(type.fields).map(([name, field]) => {
|
||||||
|
if (!Object.hasOwn(value, name) && field.kind !== "optional") throw new Error(`Missing QX record field ${name}`);
|
||||||
|
return [name, encodeQxValue(field, value[name] ?? (field.kind === "optional" ? null : value[name]), messages)];
|
||||||
|
}));
|
||||||
|
return create(ValueSchema, {kind: {case: "objectValue", value: create(ObjectValueSchema, {fields})}});
|
||||||
|
}
|
||||||
if (type.kind === "optional") return value === null ? jsToProtoValue(null) : encodeQxValue(type.value, value, messages);
|
if (type.kind === "optional") return value === null ? jsToProtoValue(null) : encodeQxValue(type.value, value, messages);
|
||||||
if (type.kind === "list") return jsToProtoValue(value.map((entry: unknown) => liveValue(encodeQxValue(type.value, entry, messages))));
|
if (type.kind === "list") return jsToProtoValue(value.map((entry: unknown) => liveValue(encodeQxValue(type.value, entry, messages))));
|
||||||
if (type.kind === "object-ref") { referenceToWire(value); return jsToProtoValue(value); }
|
if (type.kind === "object-ref") { referenceToWire(value); return jsToProtoValue(value); }
|
||||||
@@ -87,14 +104,14 @@ export const encodeQxValue = (type: QxValueType, value: any, messages: QxMessage
|
|||||||
};
|
};
|
||||||
|
|
||||||
const inputValue = (context: RuntimeContext, type: QxValueType) => {
|
const inputValue = (context: RuntimeContext, type: QxValueType) => {
|
||||||
if (type.kind === "message") return create(ValueSchema, { kind: { case: "objectValue",
|
if (type.kind === "message" || type.kind === "record") return create(ValueSchema, { kind: { case: "objectValue",
|
||||||
value: create(ObjectValueSchema, { fields: context.inputProto }) } });
|
value: create(ObjectValueSchema, { fields: context.inputProto }) } });
|
||||||
return context.inputProto.value;
|
return context.inputProto.value;
|
||||||
};
|
};
|
||||||
const inputFields = (type: QxValueType, value: unknown, messages: QxMessages): Record<string, unknown> => {
|
const inputFields = (type: QxValueType, value: unknown, messages: QxMessages): Record<string, unknown> => {
|
||||||
if (type.kind === "builtin" && type.name === "unit") return {};
|
if (type.kind === "builtin" && type.name === "unit") return {};
|
||||||
const encoded = encodeQxValue(type, value, messages);
|
const encoded = encodeQxValue(type, value, messages);
|
||||||
if (type.kind === "message") {
|
if (type.kind === "message" || type.kind === "record") {
|
||||||
if (encoded.kind.case !== "objectValue") throw new Error("Message inputs must encode an object value");
|
if (encoded.kind.case !== "objectValue") throw new Error("Message inputs must encode an object value");
|
||||||
return Object.fromEntries(Object.entries(encoded.kind.value.fields).map(([key, entry]) => [key, liveValue(entry)]));
|
return Object.fromEntries(Object.entries(encoded.kind.value.fields).map(([key, entry]) => [key, liveValue(entry)]));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,27 @@ import { referenceFromWire } from "../dist/references.js";
|
|||||||
import { bindQxHandler, decodeQxValue, encodeQxValue, jsToProtoValue, liveValue, protoValueToJs } from "../dist/index.js";
|
import { bindQxHandler, decodeQxValue, encodeQxValue, jsToProtoValue, liveValue, protoValueToJs } from "../dist/index.js";
|
||||||
const scalar = (name) => ({ kind: "scalar", name });
|
const scalar = (name) => ({ kind: "scalar", name });
|
||||||
const unit = { kind: "builtin", name: "unit" };
|
const unit = { kind: "builtin", name: "unit" };
|
||||||
|
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 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});
|
||||||
|
});
|
||||||
test("typed sessions rebind ports and cancellation to each acquired invocation", async () => {
|
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;
|
let closed = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user