Compare commits
93 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 446fd4e36e | |||
| dac9c48856 | |||
| d0dca13ff9 | |||
| f42d70a4fe | |||
| 424ebec92e | |||
| b86dbe2dfa | |||
| 1982c6fff1 | |||
| 13d2d0b1ee | |||
| c1330ae8e3 | |||
| 7e69e675ba | |||
| 99101ad206 | |||
| 169c0cdc37 | |||
| 47efd9659d | |||
| cd2b04dc8c | |||
| fc838413c5 | |||
| 5bb8ee876d | |||
| 0e183516c0 | |||
| 2319b1f637 | |||
| 0854822923 | |||
| 0d3c013c07 | |||
| bee4452852 | |||
| d3d050d9cb | |||
| e8a175504a | |||
| 3dd4e9a1ad | |||
| 62ae43ee40 | |||
| 110e41b268 | |||
| 2b7035fe81 | |||
| 8480674212 | |||
| 79fbee2b32 | |||
| a2fe7e4f5e | |||
| 652ac8e53e | |||
| 0907f97803 | |||
| ce6ae8f662 | |||
| 549c4539d5 | |||
| fa9e77e75c | |||
| a998690446 | |||
| 46c8950a75 | |||
| 2de080c09f | |||
| c15a8a51fa | |||
| d83f82c90f | |||
| b7b4a63155 | |||
| 04614be2c9 | |||
| 16b344c0ad | |||
| 385a5bd595 | |||
| 9771b0803e | |||
| 2dfba87179 | |||
| ab46f4f136 | |||
| 673575fc54 | |||
| dcdbd525fb | |||
| 5d3bd68a63 | |||
| 5c6f9b9de5 | |||
| 69441e9465 | |||
| 6c3542d2ea | |||
| 833518c3ea | |||
| e564cfeb32 | |||
| 013d4cf3c8 | |||
| aec3a348b1 | |||
| 8fc1060b65 | |||
| a83c43f9d9 | |||
| b1d0667045 | |||
| cad6057316 | |||
| 9674ffa108 | |||
| 1df06f4be7 | |||
| 02e2313aa9 | |||
| bd684cd07d | |||
| df4946e016 | |||
| 765c321f8a | |||
| d2e3172a62 | |||
| fa6939d40c | |||
| 415eb6b411 | |||
| 0f2e0f6d89 | |||
| 85e0dafbeb | |||
| 5ab1ec5428 | |||
| b4ab4c49c9 | |||
| 9c7614cac1 | |||
| 955350b487 | |||
| 0fb0da6b18 | |||
| 740bbc7aff | |||
| 337036e996 | |||
| b7cf9eaa07 | |||
| 4c042e571c | |||
| 7134b30ba3 | |||
| 19b101f348 | |||
| 79e602278c | |||
| 88f11767b1 | |||
| 2a67a2c3f5 | |||
| dd5e70514c | |||
| d7cc562bf6 | |||
| 79bc6abca5 | |||
| 2bf0e44646 | |||
| 97e91221d7 | |||
| 65eb332d88 | |||
| 056b3eaa8e |
@@ -0,0 +1 @@
|
||||
.yarn/install-state.gz
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 1,
|
||||
"sourceRepo": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos.git",
|
||||
"sourceCommit": "9472ad0a8e16927025594c294abc44cdfb30596b",
|
||||
"sourceRepo": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos",
|
||||
"sourceCommit": "8e42108f9ac903cca5f613fefbff3c147c775b81",
|
||||
"sourcePath": "quixos-instance/packages/camino-package-runtime",
|
||||
"exportName": "camino-package-runtime",
|
||||
"mirrorRemote": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git"
|
||||
|
||||
Binary file not shown.
+15
-1
@@ -1,5 +1,5 @@
|
||||
approvedGitRepositories:
|
||||
- https://gitea-external.egads.tutti.syntaxblitz.net/quixos/*
|
||||
- "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/*"
|
||||
|
||||
enableScripts: true
|
||||
|
||||
@@ -9,6 +9,20 @@ individualNixPackaging: true
|
||||
|
||||
nodeLinker: node-modules
|
||||
|
||||
supportedArchitectures:
|
||||
os:
|
||||
- current
|
||||
- linux
|
||||
cpu:
|
||||
- current
|
||||
- x64
|
||||
- arm64
|
||||
libc:
|
||||
- current
|
||||
- glibc
|
||||
|
||||
npmMinimalAgeGate: 0
|
||||
|
||||
plugins:
|
||||
- checksum: 271de9a785321a37c564b8e2a6b5cd689850b20572d5fee8ec0a6b8e7a5d4cfb59e533524af2b4a537e00da12828abd062eaec6978556e3dd9149a020db2591b
|
||||
path: .yarn/plugins/yarn-plugin-nixify.cjs
|
||||
|
||||
Vendored
+103
@@ -0,0 +1,103 @@
|
||||
import { type Value } from "./camino/api_pb.js";
|
||||
import { liveValue, type RuntimeHandler, type DerivedHandler } from "./index.js";
|
||||
export type { QxObjectRef } from "./references.js";
|
||||
declare const watchBrand: unique symbol;
|
||||
export type QxWatchHandle = string & {
|
||||
readonly [watchBrand]: true;
|
||||
};
|
||||
export type MessageBinding<T> = {
|
||||
encode(value: T): Value;
|
||||
decode(value: Value): T;
|
||||
};
|
||||
export type QxLiveValue = ReturnType<typeof liveValue>;
|
||||
export type BindingValue<B> = B extends MessageBinding<infer T> ? T : never;
|
||||
export type QxHandler<C, O> = (context: C) => O | Promise<O>;
|
||||
export type QxDerived<C, O> = {
|
||||
kind: "derived";
|
||||
get: QxHandler<C, O>;
|
||||
};
|
||||
export type QxSession<C> = {
|
||||
id: string;
|
||||
run<T>(work: (context: C) => Promise<T>): Promise<T>;
|
||||
close(): Promise<void>;
|
||||
};
|
||||
export type QxContextLifecycle<C> = {
|
||||
signal?: AbortSignal;
|
||||
openSession?: () => Promise<QxSession<C>>;
|
||||
};
|
||||
declare const contractView: unique symbol;
|
||||
/** Generated exact closed contract. A descriptor is type evidence, never authority. */
|
||||
export type QxInterfaceContract<View> = {
|
||||
readonly interfaceRevisionId: string;
|
||||
readonly operations: Record<string, QxOperationSpec>;
|
||||
readonly [contractView]: (value: View) => View;
|
||||
};
|
||||
export declare const defineQxInterfaceContract: <View>(interfaceRevisionId: string, operations: Record<string, QxOperationSpec>) => QxInterfaceContract<View>;
|
||||
export type QxConformer = {
|
||||
tryConform<View>(object: import("./references.js").QxObjectRef, contract: QxInterfaceContract<View>): Promise<View | undefined>;
|
||||
};
|
||||
export declare const qxDerived: <C, O>(get: QxHandler<C, O>) => QxDerived<C, O>;
|
||||
/** Versioned binding ABI. This mirrors the language-neutral value IR. */
|
||||
export type QxValueType = {
|
||||
kind: "builtin";
|
||||
name: "unit" | "watch-handle";
|
||||
} | {
|
||||
kind: "scalar";
|
||||
name: string;
|
||||
} | {
|
||||
kind: "message";
|
||||
descriptorId: string;
|
||||
} | {
|
||||
kind: "record";
|
||||
fields: Record<string, QxValueType>;
|
||||
} | {
|
||||
kind: "object-ref";
|
||||
expectation: unknown;
|
||||
} | {
|
||||
kind: "optional" | "list";
|
||||
value: QxValueType;
|
||||
};
|
||||
export type QxOperationSpec = {
|
||||
id: string;
|
||||
inputType: QxValueType;
|
||||
outputType: QxValueType;
|
||||
};
|
||||
export type QxPortSpec = {
|
||||
kind: "query";
|
||||
id: string;
|
||||
definitionDigest: string;
|
||||
variables: QxValueType;
|
||||
output: QxValueType;
|
||||
watch: boolean;
|
||||
} | {
|
||||
kind: "state";
|
||||
id: string;
|
||||
valueType: QxValueType;
|
||||
primitives: string[];
|
||||
} | {
|
||||
kind: "edge";
|
||||
id: string;
|
||||
primitives: string[];
|
||||
} | {
|
||||
kind: "interface";
|
||||
id: string;
|
||||
interfaceRevisionId: string;
|
||||
operations: Record<string, QxOperationSpec>;
|
||||
} | {
|
||||
kind: "constructor";
|
||||
id: string;
|
||||
inputType: QxValueType;
|
||||
};
|
||||
export type QxHandlerSpec = {
|
||||
receiver?: "none";
|
||||
inputType: QxValueType;
|
||||
outputType: QxValueType;
|
||||
eventType?: QxValueType;
|
||||
ports: Record<string, QxPortSpec>;
|
||||
};
|
||||
export type QxMessages = Record<string, MessageBinding<any>>;
|
||||
export declare const decodeQxValue: (type: QxValueType, value: Value | undefined, messages: QxMessages) => any;
|
||||
export declare const encodeQxValue: (type: QxValueType, value: any, messages: QxMessages) => Value;
|
||||
/** The sole unchecked cast connects generated contracts to the dynamic RPC runtime. */
|
||||
export declare const bindQxHandler: <C, O>(spec: QxHandlerSpec, handler: QxHandler<C, O> | QxDerived<C, O>, messages: QxMessages) => RuntimeHandler | DerivedHandler;
|
||||
//# sourceMappingURL=bindings.d.ts.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"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"}
|
||||
Vendored
+247
@@ -0,0 +1,247 @@
|
||||
import { create } from "@bufbuild/protobuf";
|
||||
import { ValueSchema, ObjectValueSchema } from "./camino/api_pb.js";
|
||||
import { derived, jsToProtoValue, liveValue, protoValueToJs, } from "./index.js";
|
||||
import { assertReferenceFree, referenceToWire } from "./references.js";
|
||||
import { decodeQuerySnapshot } from "./queries.js";
|
||||
export const defineQxInterfaceContract = (interfaceRevisionId, operations) => Object.freeze({ interfaceRevisionId, operations });
|
||||
export const qxDerived = (get) => ({ kind: "derived", get });
|
||||
const bindInterfaceView = (target, contract, messages) => ({
|
||||
objectId: target.objectId,
|
||||
contract,
|
||||
live: Object.fromEntries(Object.entries(contract.operations).map(([name, operation]) => [
|
||||
name,
|
||||
(input) => target.live(operation.id, inputFields(operation.inputType, input, messages)),
|
||||
])),
|
||||
...Object.fromEntries(Object.entries(contract.operations).map(([name, operation]) => [
|
||||
name,
|
||||
async (input) => decodeQxValue(operation.outputType, (await target.live(operation.id, inputFields(operation.inputType, input, messages))).$quixosValue, messages),
|
||||
])),
|
||||
});
|
||||
// Conversion belongs at the binding boundary. It does not add orchestrator validation.
|
||||
export const decodeQxValue = (type, value, messages) => {
|
||||
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 (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 === "list") {
|
||||
if (value.kind.case !== "listValue")
|
||||
throw new Error("Expected QX list");
|
||||
return value.kind.value.values.map((entry) => decodeQxValue(type.value, entry, messages));
|
||||
}
|
||||
if (type.kind === "message") {
|
||||
assertReferenceFree(protoValueToJs(value));
|
||||
const decoded = requireMessage(messages, type.descriptorId).decode(value);
|
||||
assertReferenceFree(decoded);
|
||||
return decoded;
|
||||
}
|
||||
if (type.kind === "object-ref") {
|
||||
if (value.kind.case !== "refValue")
|
||||
throw new Error("Expected a declared RPC object reference");
|
||||
return protoValueToJs(value);
|
||||
}
|
||||
if (value.kind.case === "refValue")
|
||||
throw new Error("Reference supplied to a non-reference value");
|
||||
if (type.kind === "scalar") {
|
||||
if (type.name === "int64" || type.name === "uint64") {
|
||||
if (value.kind.case !== "integerValue")
|
||||
throw new Error("Expected QX integer");
|
||||
return BigInt(value.kind.value);
|
||||
}
|
||||
if (type.name === "bytes") {
|
||||
if (value.kind.case !== "bytesValue")
|
||||
throw new Error("Expected QX bytes");
|
||||
return value.kind.value;
|
||||
}
|
||||
}
|
||||
return protoValueToJs(value);
|
||||
};
|
||||
const requireMessage = (messages, id) => {
|
||||
const binding = messages[id];
|
||||
if (!binding)
|
||||
throw new Error(`Missing message binding ${id}`);
|
||||
return binding;
|
||||
};
|
||||
export const encodeQxValue = (type, value, messages) => {
|
||||
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 === "list")
|
||||
return jsToProtoValue(value.map((entry) => liveValue(encodeQxValue(type.value, entry, messages))));
|
||||
if (type.kind === "object-ref") {
|
||||
referenceToWire(value);
|
||||
return jsToProtoValue(value);
|
||||
}
|
||||
assertReferenceFree(value);
|
||||
if (type.kind === "message") {
|
||||
const encoded = requireMessage(messages, type.descriptorId).encode(value);
|
||||
assertReferenceFree(protoValueToJs(encoded));
|
||||
return encoded;
|
||||
}
|
||||
return jsToProtoValue(value);
|
||||
};
|
||||
const inputValue = (context, type) => {
|
||||
if (type.kind === "message" || type.kind === "record")
|
||||
return create(ValueSchema, {
|
||||
kind: { case: "objectValue", value: create(ObjectValueSchema, { fields: context.inputProto }) },
|
||||
});
|
||||
return context.inputProto.value;
|
||||
};
|
||||
const inputFields = (type, value, messages) => {
|
||||
if (type.kind === "builtin" && type.name === "unit")
|
||||
return {};
|
||||
const encoded = encodeQxValue(type, value, messages);
|
||||
if (type.kind === "message" || type.kind === "record") {
|
||||
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 { value: liveValue(encoded) };
|
||||
};
|
||||
/** The sole unchecked cast connects generated contracts to the dynamic RPC runtime. */
|
||||
export const bindQxHandler = (spec, handler, messages) => {
|
||||
const bindContext = (raw) => {
|
||||
const ports = Object.fromEntries(Object.entries(spec.ports).map(([name, port]) => {
|
||||
switch (port.kind) {
|
||||
case "state": {
|
||||
const state = raw.state(port.id);
|
||||
return [
|
||||
name,
|
||||
{
|
||||
...(port.primitives.includes("read")
|
||||
? {
|
||||
get: async () => decodeQxValue(port.valueType, (await state.live()).$quixosValue, messages),
|
||||
live: () => state.live(),
|
||||
}
|
||||
: {}),
|
||||
...(port.primitives.includes("write")
|
||||
? {
|
||||
set: async (value) => state.set(liveValue(encodeQxValue(port.valueType, value, messages))),
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
];
|
||||
}
|
||||
case "edge": {
|
||||
const edge = raw.edge(port.id);
|
||||
return [
|
||||
name,
|
||||
{
|
||||
...Object.fromEntries(port.primitives.map((primitive) => [
|
||||
primitive,
|
||||
edge[primitive],
|
||||
])),
|
||||
...(port.primitives.includes("resolve") ? { collection: edge.collection } : {}),
|
||||
...(port.primitives.includes("resolve") &&
|
||||
port.primitives.includes("connect") &&
|
||||
port.primitives.includes("disconnect")
|
||||
? { replace: edge.replace }
|
||||
: {}),
|
||||
},
|
||||
];
|
||||
}
|
||||
case "interface": {
|
||||
const target = raw.interface(port.id);
|
||||
return [
|
||||
name,
|
||||
bindInterfaceView(target, defineQxInterfaceContract(port.interfaceRevisionId, port.operations), messages),
|
||||
];
|
||||
}
|
||||
case "query": {
|
||||
const query = raw.query(port.id);
|
||||
const variablesToWire = (variables) => {
|
||||
const value = encodeQxValue(port.variables, variables, messages);
|
||||
if (value.kind.case !== "objectValue")
|
||||
throw new Error("QUERY_VARIABLE_INVALID");
|
||||
return value.kind.value.fields;
|
||||
};
|
||||
return [
|
||||
name,
|
||||
{
|
||||
async execute(variables) {
|
||||
const response = await query.execute(variablesToWire(variables), port.definitionDigest);
|
||||
if (response.pending.length || response.errors.length)
|
||||
throw new Error("QUERY_INCOMPLETE");
|
||||
return decodeQxValue(port.output, response.value, messages);
|
||||
},
|
||||
...(port.watch
|
||||
? {
|
||||
async *watch(variables, signal) {
|
||||
for await (const event of query.watch(variablesToWire(variables), signal, port.definitionDigest)) {
|
||||
if (!event.snapshot)
|
||||
throw new Error("QUERY_SNAPSHOT_MISSING");
|
||||
yield decodeQuerySnapshot(event.snapshot, port.output, event.runId, event.sequence);
|
||||
}
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
];
|
||||
}
|
||||
case "constructor":
|
||||
return [
|
||||
name,
|
||||
{
|
||||
construct: (input) => raw.constructor(port.id).construct(inputFields(port.inputType, input, messages)),
|
||||
},
|
||||
];
|
||||
}
|
||||
}));
|
||||
return {
|
||||
conform: {
|
||||
async tryConform(object, contract) {
|
||||
const target = await raw.tryConform(object, contract.interfaceRevisionId);
|
||||
return target
|
||||
? bindInterfaceView(target, contract, messages)
|
||||
: undefined;
|
||||
},
|
||||
},
|
||||
...(spec.receiver === "none" ? {} : { objectId: raw.objectId }),
|
||||
signal: raw.signal,
|
||||
...(spec.receiver !== "none" && raw.openSession
|
||||
? {
|
||||
openSession: async () => {
|
||||
const session = await raw.openSession();
|
||||
return {
|
||||
id: session.id,
|
||||
close: () => session.close(),
|
||||
run: (work) => session.run((next) => work(bindContext(next))),
|
||||
};
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
input: decodeQxValue(spec.inputType, inputValue(raw, spec.inputType), messages),
|
||||
ports,
|
||||
};
|
||||
};
|
||||
const execute = async (raw) => {
|
||||
const context = bindContext(raw);
|
||||
const value = await (typeof handler === "function" ? handler(context) : handler.get(context));
|
||||
return liveValue(encodeQxValue(spec.eventType ?? spec.outputType, value, messages));
|
||||
};
|
||||
return typeof handler === "function" ? execute : derived(execute);
|
||||
};
|
||||
Vendored
+1449
File diff suppressed because it is too large
Load Diff
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+278
File diff suppressed because one or more lines are too long
Vendored
+1306
File diff suppressed because it is too large
Load Diff
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+333
File diff suppressed because one or more lines are too long
Vendored
+118
@@ -0,0 +1,118 @@
|
||||
import http from "node:http";
|
||||
import { type QxObjectRef } from "./references.js";
|
||||
export * from "./bindings.js";
|
||||
export * from "./queries.js";
|
||||
export { relationshipMap, relationshipList, relationshipSet } from "./relationships.js";
|
||||
export { createMigrationContext, migrationObjectId, serveMigration, type MigrationContext, type MigrationInput, type MigrationOutput, type MigrationEdge, } from "./migration.js";
|
||||
import { type Client, type ConnectRouter } from "@connectrpc/connect";
|
||||
import { CaminoService, type Value, type QueryResponse } from "./camino/api_pb.js";
|
||||
import { OrchestratorRuntime } from "./quixos/orch_pb.js";
|
||||
export type CaminoClient = Client<typeof CaminoService>;
|
||||
export type OrchClient = Client<typeof OrchestratorRuntime>;
|
||||
export type RuntimeDependency = {
|
||||
kind: "state";
|
||||
objectId: string;
|
||||
attachmentId: string;
|
||||
} | {
|
||||
kind: "edge";
|
||||
objectId: string;
|
||||
attachmentId: string;
|
||||
projectionId: string;
|
||||
};
|
||||
export declare const objectRef: (reference: QxObjectRef) => QxObjectRef<string>;
|
||||
export declare const liveValue: (value: Value) => {
|
||||
$quixosValue: Value;
|
||||
};
|
||||
export declare const jsToProtoValue: (value: unknown) => Value;
|
||||
export declare const protoValueToJs: (value: Value | undefined) => unknown;
|
||||
export declare const protoFieldsToJs: (fields: Record<string, Value>) => {
|
||||
[k: string]: unknown;
|
||||
};
|
||||
export type StatePort<T = unknown> = {
|
||||
slotId: string;
|
||||
get(): Promise<T>;
|
||||
live(): Promise<ReturnType<typeof liveValue>>;
|
||||
set(value: T): Promise<void>;
|
||||
};
|
||||
export type EdgePort = {
|
||||
edgeTypeId: string;
|
||||
projectionId: string;
|
||||
resolve(): Promise<QxObjectRef[]>;
|
||||
connect(target: QxObjectRef): Promise<void>;
|
||||
disconnect(target: QxObjectRef): Promise<void>;
|
||||
collection(): Promise<RelationshipCollection>;
|
||||
replace(entries: RelationshipEntry[], expectedRevision: bigint): Promise<RelationshipCollection>;
|
||||
};
|
||||
export type RelationshipEntry<T extends QxObjectRef = QxObjectRef> = {
|
||||
edgeId?: string;
|
||||
target: T;
|
||||
key?: string | boolean | bigint;
|
||||
};
|
||||
export type RelationshipCollection<T extends QxObjectRef = QxObjectRef> = {
|
||||
revision: bigint;
|
||||
entries: RelationshipEntry<T>[];
|
||||
};
|
||||
export type InterfacePort = {
|
||||
objectId: QxObjectRef;
|
||||
interfaceRevisionId: string;
|
||||
invoke(operationId: string, input?: Record<string, unknown>): Promise<unknown>;
|
||||
live(operationId: string, input?: Record<string, unknown>): Promise<ReturnType<typeof liveValue>>;
|
||||
};
|
||||
export type ConstructorPort = {
|
||||
atomId: string;
|
||||
construct(input?: Record<string, unknown>): Promise<QxObjectRef>;
|
||||
};
|
||||
export type QueryPort = {
|
||||
queryId: string;
|
||||
execute(variables: Record<string, Value>, expectedDefinitionDigest?: string): Promise<QueryResponse>;
|
||||
watch(variables: Record<string, Value>, signal: AbortSignal, expectedDefinitionDigest?: string): AsyncIterable<import("./quixos/orch_pb.js").QueryEvent>;
|
||||
};
|
||||
export type RuntimePort = StatePort | EdgePort | InterfacePort | ConstructorPort | QueryPort;
|
||||
export type RuntimeContext = {
|
||||
tryConform(object: QxObjectRef, interfaceRevisionId: string): Promise<InterfacePort | undefined>;
|
||||
/** Cooperative cancellation. Completion is acknowledged only after the handler returns. */
|
||||
signal?: AbortSignal;
|
||||
openSession?: () => Promise<RuntimeSession>;
|
||||
objectId: QxObjectRef;
|
||||
input: Record<string, unknown>;
|
||||
inputProto: Record<string, Value>;
|
||||
ports: ReadonlyMap<string, RuntimePort>;
|
||||
state<T = unknown>(portId: string): StatePort<T>;
|
||||
edge(portId: string): EdgePort;
|
||||
interface(portId: string): InterfacePort;
|
||||
constructor(portId: string): ConstructorPort;
|
||||
query(portId: string): QueryPort;
|
||||
};
|
||||
export type RuntimeSession = {
|
||||
id: string;
|
||||
run<T>(work: (context: RuntimeContext) => Promise<T>): Promise<T>;
|
||||
/** Close the external resource first, then close its host retention/session. */
|
||||
close(): Promise<void>;
|
||||
};
|
||||
export declare class RuntimeAuthorityError extends Error {
|
||||
readonly retryable: boolean;
|
||||
constructor(message: string);
|
||||
}
|
||||
export declare const createRuntimeContext: (camino: CaminoClient, orch: OrchClient, request: RuntimeRequest) => RuntimeContext;
|
||||
export type RuntimeHandler = (context: RuntimeContext) => unknown | Promise<unknown>;
|
||||
export type DerivedHandler = {
|
||||
kind: "derived";
|
||||
get: RuntimeHandler;
|
||||
};
|
||||
export declare const derived: (get: RuntimeHandler) => DerivedHandler;
|
||||
export declare const createPackageRuntimeRoutes: (config: {
|
||||
packageRevisionId: string;
|
||||
exports: Record<string, RuntimeHandler | DerivedHandler>;
|
||||
caminoUrl?: string;
|
||||
orchUrl?: string;
|
||||
}) => (router: ConnectRouter) => ConnectRouter;
|
||||
export declare const servePackageRuntime: (config: {
|
||||
packageRevisionId: string;
|
||||
exports: Record<string, RuntimeHandler | DerivedHandler>;
|
||||
}) => http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
|
||||
type RuntimeRequest = {
|
||||
objectId: string;
|
||||
input: Record<string, Value>;
|
||||
dependencies: import("./quixos/refs_pb.js").InjectedDependency[];
|
||||
};
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
||||
Vendored
+661
@@ -0,0 +1,661 @@
|
||||
import http from "node:http";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { createInvocationRegistry } from "./invocations.js";
|
||||
import { isObjectReference, referenceFromWire, referenceToWire, assertReferenceFree, } from "./references.js";
|
||||
export * from "./bindings.js";
|
||||
export * from "./queries.js";
|
||||
export { relationshipMap, relationshipList, relationshipSet } from "./relationships.js";
|
||||
import { AsyncLocalStorage } from "node:async_hooks";
|
||||
import { createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
||||
export { createMigrationContext, migrationObjectId, serveMigration, } from "./migration.js";
|
||||
import { create, equals } from "@bufbuild/protobuf";
|
||||
import { Code, ConnectError, createClient } from "@connectrpc/connect";
|
||||
import { connectNodeAdapter, createConnectTransport } from "@connectrpc/connect-node";
|
||||
import { CaminoService, CrdtValueSchema, ListValueSchema, NullValueSchema, ObjectValueSchema, RefValueSchema, ValueSchema, } from "./camino/api_pb.js";
|
||||
import { OrchestratorRuntime } from "./quixos/orch_pb.js";
|
||||
import { DerivedDependencySchema, HandshakeResponseSchema, InvokeResponseSchema, PackageRuntime, WatchEventSchema, } from "./quixos/runtime_pb.js";
|
||||
import { CapabilityRefSchema } from "./quixos/refs_pb.js";
|
||||
const dependencyKey = (dependency) => `${dependency.kind}:${dependency.objectId}:${dependency.attachmentId}:${dependency.kind === "edge" ? dependency.projectionId : ""}`;
|
||||
const dependencyScope = new AsyncLocalStorage();
|
||||
const recordDependency = async (dependency) => {
|
||||
const scope = dependencyScope.getStore();
|
||||
if (!scope)
|
||||
return;
|
||||
const key = `${dependency.kind}:${dependency.objectId}:${dependency.attachmentId}:${dependency.kind === "edge" ? dependency.projectionId : ""}`;
|
||||
scope.dependencies.set(key, dependency);
|
||||
await scope.observe?.(dependency);
|
||||
};
|
||||
const bytesToBase64 = (value) => Buffer.from(value).toString("base64");
|
||||
const base64ToBytes = (value) => Buffer.from(value, "base64");
|
||||
const isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
||||
const isWrappedValue = (value) => isRecord(value) &&
|
||||
"$quixosValue" in value &&
|
||||
isRecord(value.$quixosValue) &&
|
||||
value.$quixosValue.$typeName === "camino.Value";
|
||||
export const objectRef = (reference) => {
|
||||
referenceToWire(reference);
|
||||
return reference;
|
||||
};
|
||||
export const liveValue = (value) => ({ $quixosValue: value });
|
||||
export const jsToProtoValue = (value) => {
|
||||
if (isObjectReference(value))
|
||||
return create(ValueSchema, {
|
||||
kind: { case: "refValue", value: create(RefValueSchema, { objectId: referenceToWire(value) }) },
|
||||
});
|
||||
if (isWrappedValue(value))
|
||||
return value.$quixosValue;
|
||||
if (value === null || value === undefined) {
|
||||
return create(ValueSchema, { kind: { case: "nullValue", value: create(NullValueSchema, {}) } });
|
||||
}
|
||||
if (typeof value === "boolean")
|
||||
return create(ValueSchema, { kind: { case: "boolValue", value } });
|
||||
if (typeof value === "number")
|
||||
return create(ValueSchema, { kind: { case: "numberValue", value } });
|
||||
if (typeof value === "bigint")
|
||||
return create(ValueSchema, { kind: { case: "integerValue", value: String(value) } });
|
||||
if (typeof value === "string")
|
||||
return create(ValueSchema, { kind: { case: "stringValue", value } });
|
||||
if (value instanceof Uint8Array)
|
||||
return create(ValueSchema, { kind: { case: "bytesValue", value } });
|
||||
if (Array.isArray(value)) {
|
||||
return create(ValueSchema, {
|
||||
kind: { case: "listValue", value: create(ListValueSchema, { values: value.map(jsToProtoValue) }) },
|
||||
});
|
||||
}
|
||||
if (isRecord(value) && "$quixosRef" in value)
|
||||
throw new Error("Raw ID wrappers are not object references");
|
||||
if (isRecord(value) && typeof value.$quixosCrdtType === "string" && typeof value.$quixosCrdtPayload === "string") {
|
||||
return create(ValueSchema, {
|
||||
kind: {
|
||||
case: "crdtValue",
|
||||
value: create(CrdtValueSchema, {
|
||||
type: value.$quixosCrdtType,
|
||||
encoding: typeof value.$quixosCrdtEncoding === "string" ? value.$quixosCrdtEncoding : "base64",
|
||||
payload: base64ToBytes(value.$quixosCrdtPayload),
|
||||
}),
|
||||
},
|
||||
});
|
||||
}
|
||||
if (!isRecord(value))
|
||||
throw new Error(`Unsupported runtime value ${typeof value}`);
|
||||
return create(ValueSchema, {
|
||||
kind: {
|
||||
case: "objectValue",
|
||||
value: create(ObjectValueSchema, {
|
||||
fields: Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, jsToProtoValue(entry)])),
|
||||
}),
|
||||
},
|
||||
});
|
||||
};
|
||||
export const protoValueToJs = (value) => {
|
||||
switch (value?.kind.case) {
|
||||
case "nullValue":
|
||||
case undefined:
|
||||
return null;
|
||||
case "boolValue":
|
||||
case "numberValue":
|
||||
case "stringValue":
|
||||
case "integerValue":
|
||||
return value.kind.value;
|
||||
case "bytesValue":
|
||||
return bytesToBase64(value.kind.value);
|
||||
case "refValue":
|
||||
return referenceFromWire(value.kind.value.objectId);
|
||||
case "listValue":
|
||||
return value.kind.value.values.map(protoValueToJs);
|
||||
case "objectValue":
|
||||
return Object.fromEntries(Object.entries(value.kind.value.fields).map(([key, entry]) => [key, protoValueToJs(entry)]));
|
||||
case "crdtValue":
|
||||
return {
|
||||
$quixosCrdtType: value.kind.value.type,
|
||||
$quixosCrdtEncoding: value.kind.value.encoding,
|
||||
$quixosCrdtPayload: bytesToBase64(value.kind.value.payload),
|
||||
};
|
||||
}
|
||||
};
|
||||
export const protoFieldsToJs = (fields) => Object.fromEntries(Object.entries(fields).map(([key, value]) => [key, protoValueToJs(value)]));
|
||||
export class RuntimeAuthorityError extends Error {
|
||||
retryable;
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "RuntimeAuthorityError";
|
||||
this.retryable = /WORKSPACE_FENCED|STALE_EPOCH/.test(message);
|
||||
}
|
||||
}
|
||||
const targetForEdge = (edge, projectionId) => (edge.firstProjectionId === projectionId ? edge.secondObjectId : edge.firstObjectId);
|
||||
export const createRuntimeContext = (camino, orch, request) => {
|
||||
const acquiredPort = (objectId, interfaceRevisionId, conformance) => {
|
||||
const invoke = async (operationId, input = {}) => {
|
||||
const response = await orch.invokeCapability({
|
||||
objectId,
|
||||
capability: create(CapabilityRefSchema, { interfaceRevisionId, operationId, conformance }),
|
||||
input: Object.fromEntries(Object.entries(input).map(([key, value]) => [key, jsToProtoValue(value)])),
|
||||
});
|
||||
if (!response.ok)
|
||||
throw new Error(response.error || "Capability invocation failed");
|
||||
for (const dependency of response.dependencies) {
|
||||
if (dependency.kind === "state" || dependency.kind === "edge")
|
||||
await recordDependency({
|
||||
kind: dependency.kind,
|
||||
objectId: dependency.objectId,
|
||||
attachmentId: dependency.attachmentId,
|
||||
...(dependency.kind === "edge" ? { projectionId: dependency.projectionId } : {}),
|
||||
});
|
||||
}
|
||||
if (!response.result)
|
||||
throw new Error("Capability returned no value");
|
||||
return response.result;
|
||||
};
|
||||
return {
|
||||
objectId: referenceFromWire(objectId),
|
||||
interfaceRevisionId,
|
||||
invoke: async (operation, input) => protoValueToJs(await invoke(operation, input)),
|
||||
live: async (operation, input) => liveValue(await invoke(operation, input)),
|
||||
};
|
||||
};
|
||||
const ports = new Map();
|
||||
for (const dependency of request.dependencies) {
|
||||
switch (dependency.binding.case) {
|
||||
case "queryId": {
|
||||
const queryId = dependency.binding.value, objectId = dependency.objectId || request.objectId;
|
||||
ports.set(dependency.portId, {
|
||||
queryId,
|
||||
execute: (variables, expectedDefinitionDigest) => orch.executeQuery({ queryId, objectId, variables, expectedDefinitionDigest }),
|
||||
watch: (variables, signal, expectedDefinitionDigest) => orch.watchQuery({ queryId, objectId, variables, expectedDefinitionDigest }, { signal }),
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "stateSlotId": {
|
||||
const slotId = dependency.binding.value;
|
||||
const dependencyObjectId = dependency.objectId || request.objectId;
|
||||
const state = {
|
||||
slotId,
|
||||
async get() {
|
||||
await recordDependency({ kind: "state", objectId: dependencyObjectId, attachmentId: slotId });
|
||||
return protoValueToJs((await camino.readState({ objectId: dependencyObjectId, slotId })).value);
|
||||
},
|
||||
async live() {
|
||||
await recordDependency({ kind: "state", objectId: dependencyObjectId, attachmentId: slotId });
|
||||
const value = await camino.readState({ objectId: dependencyObjectId, slotId });
|
||||
if (!value.value)
|
||||
throw new Error(`State ${slotId} returned no value`);
|
||||
return liveValue(value.value);
|
||||
},
|
||||
async set(value) {
|
||||
assertReferenceFree(isWrappedValue(value) ? protoValueToJs(value.$quixosValue) : value);
|
||||
await camino.writeState({ objectId: dependencyObjectId, slotId, value: jsToProtoValue(value) });
|
||||
},
|
||||
};
|
||||
ports.set(dependency.portId, state);
|
||||
break;
|
||||
}
|
||||
case "edge": {
|
||||
const { edgeTypeId, projectionId } = dependency.binding.value;
|
||||
const dependencyObjectId = dependency.objectId || request.objectId;
|
||||
const collectionResult = (response) => ({
|
||||
revision: response.revision,
|
||||
entries: response.entries.map((entry) => ({
|
||||
edgeId: entry.edgeId,
|
||||
target: referenceFromWire(entry.targetObjectId),
|
||||
...(entry.key
|
||||
? {
|
||||
key: entry.key.kind.case === "integerValue"
|
||||
? BigInt(entry.key.kind.value)
|
||||
: protoValueToJs(entry.key),
|
||||
}
|
||||
: {}),
|
||||
})),
|
||||
});
|
||||
const edge = {
|
||||
edgeTypeId,
|
||||
projectionId,
|
||||
async collection() {
|
||||
await recordDependency({
|
||||
kind: "edge",
|
||||
objectId: dependencyObjectId,
|
||||
attachmentId: edgeTypeId,
|
||||
projectionId,
|
||||
});
|
||||
return collectionResult(await camino.readCollection({ objectId: dependencyObjectId, edgeTypeId, projectionId }));
|
||||
},
|
||||
async replace(entries, expectedRevision) {
|
||||
return collectionResult(await camino.replaceCollection({
|
||||
objectId: dependencyObjectId,
|
||||
edgeTypeId,
|
||||
projectionId,
|
||||
expectedRevision,
|
||||
entries: entries.map((entry) => {
|
||||
assertReferenceFree(entry.key);
|
||||
return {
|
||||
edgeId: entry.edgeId ?? "",
|
||||
targetObjectId: referenceToWire(entry.target),
|
||||
key: entry.key === undefined ? undefined : jsToProtoValue(entry.key),
|
||||
};
|
||||
}),
|
||||
}));
|
||||
},
|
||||
async resolve() {
|
||||
await recordDependency({
|
||||
kind: "edge",
|
||||
objectId: dependencyObjectId,
|
||||
attachmentId: edgeTypeId,
|
||||
projectionId,
|
||||
});
|
||||
const result = await camino.resolveEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId });
|
||||
return result.edges.map((entry) => referenceFromWire(targetForEdge(entry, projectionId)));
|
||||
},
|
||||
async connect(target) {
|
||||
const targetObjectId = referenceToWire(target);
|
||||
await camino.connectEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId, targetObjectId });
|
||||
},
|
||||
async disconnect(target) {
|
||||
const targetObjectId = referenceToWire(target);
|
||||
const result = await camino.resolveEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId });
|
||||
for (const entry of result.edges) {
|
||||
if (targetForEdge(entry, projectionId) === targetObjectId)
|
||||
await camino.disconnectEdge({ edgeId: entry.id });
|
||||
}
|
||||
},
|
||||
};
|
||||
ports.set(dependency.portId, edge);
|
||||
break;
|
||||
}
|
||||
case "interfaceRevisionId": {
|
||||
const interfaceRevisionId = dependency.binding.value;
|
||||
const dependencyObjectId = dependency.objectId || request.objectId;
|
||||
ports.set(dependency.portId, acquiredPort(dependencyObjectId, interfaceRevisionId));
|
||||
break;
|
||||
}
|
||||
case "constructorAtomId": {
|
||||
const atomId = dependency.binding.value;
|
||||
const constructor = {
|
||||
atomId,
|
||||
async construct(input = {}) {
|
||||
const response = await orch.constructObject({
|
||||
atomId,
|
||||
input: Object.fromEntries(Object.entries(input).map(([key, value]) => [key, jsToProtoValue(value)])),
|
||||
});
|
||||
if (!response.object)
|
||||
throw new Error(`Constructor ${atomId} returned no object`);
|
||||
return referenceFromWire(response.object.id);
|
||||
},
|
||||
};
|
||||
ports.set(dependency.portId, constructor);
|
||||
}
|
||||
}
|
||||
}
|
||||
const requirePort = (portId, kind) => {
|
||||
const port = ports.get(portId);
|
||||
if (!port || !(kind in port))
|
||||
throw new Error(`Missing ${kind} dependency port ${portId}`);
|
||||
return port;
|
||||
};
|
||||
return {
|
||||
async tryConform(object, interfaceRevisionId) {
|
||||
const objectId = referenceToWire(object);
|
||||
const { conformance } = await orch.tryConform({ objectId, interfaceRevisionId });
|
||||
if (conformance && (conformance.objectId !== objectId || conformance.interfaceRevisionId !== interfaceRevisionId))
|
||||
throw new Error("Conformance response does not match the requested view");
|
||||
return conformance ? acquiredPort(objectId, interfaceRevisionId, conformance) : undefined;
|
||||
},
|
||||
get objectId() {
|
||||
return referenceFromWire(request.objectId);
|
||||
},
|
||||
input: protoFieldsToJs(request.input),
|
||||
inputProto: request.input,
|
||||
ports,
|
||||
state: (portId) => requirePort(portId, "slotId"),
|
||||
edge: (portId) => requirePort(portId, "edgeTypeId"),
|
||||
interface: (portId) => requirePort(portId, "interfaceRevisionId"),
|
||||
constructor: (portId) => requirePort(portId, "atomId"),
|
||||
query: (portId) => requirePort(portId, "queryId"),
|
||||
};
|
||||
};
|
||||
export const derived = (get) => ({ kind: "derived", get });
|
||||
const isDerived = (handler) => typeof handler === "object" && handler.kind === "derived";
|
||||
const evaluate = async (handler, context, observe) => {
|
||||
const dependencies = new Map();
|
||||
const result = await dependencyScope.run({ dependencies, observe }, () => isDerived(handler) ? handler.get(context) : handler(context));
|
||||
return { value: jsToProtoValue(result), dependencies: [...dependencies.values()] };
|
||||
};
|
||||
const protoDependencies = (dependencies) => dependencies.map((entry) => create(DerivedDependencySchema, {
|
||||
kind: entry.kind,
|
||||
objectId: entry.objectId,
|
||||
attachmentId: entry.attachmentId,
|
||||
projectionId: entry.kind === "edge" ? entry.projectionId : "",
|
||||
}));
|
||||
export const createPackageRuntimeRoutes = (config) => {
|
||||
const invocations = createInvocationRegistry();
|
||||
const headers = {};
|
||||
const processToken = process.env.CAMINO_RUNTIME_AUTH_TOKEN ??
|
||||
(process.env.CAMINO_RUNTIME_AUTH_TOKEN_FILE
|
||||
? readFileSync(process.env.CAMINO_RUNTIME_AUTH_TOKEN_FILE, "utf8").trim()
|
||||
: "");
|
||||
if (processToken) {
|
||||
headers["x-camino-runtime-token"] = processToken;
|
||||
}
|
||||
else if (process.env.CAMINO_RUNTIME_AUTH_REQUIRED === "1") {
|
||||
throw new Error("CAMINO_RUNTIME_AUTH_TOKEN is required");
|
||||
}
|
||||
const camino = createClient(CaminoService, createConnectTransport({
|
||||
baseUrl: config.caminoUrl ?? process.env.CAMINO_URL ?? "http://127.0.0.1:7310",
|
||||
httpVersion: "1.1",
|
||||
interceptors: headers["x-camino-runtime-token"]
|
||||
? [
|
||||
(next) => async (request) => {
|
||||
request.header.set("x-camino-runtime-token", headers["x-camino-runtime-token"]);
|
||||
return await next(request);
|
||||
},
|
||||
]
|
||||
: [],
|
||||
}));
|
||||
const orch = createClient(OrchestratorRuntime, createConnectTransport({
|
||||
baseUrl: config.orchUrl ?? process.env.QUIXOS_ORCH_URL ?? "http://127.0.0.1:7311",
|
||||
httpVersion: "1.1",
|
||||
}));
|
||||
const authenticateInstance = (header) => {
|
||||
if (!process.env.QUIXOS_RUNTIME_INSTANCE_ID)
|
||||
return; // standalone development ABI
|
||||
const supplied = Buffer.from(header.get("x-quixos-instance-token") ?? "");
|
||||
const expected = Buffer.from(processToken);
|
||||
if (!expected.length || supplied.length !== expected.length || !timingSafeEqual(supplied, expected)) {
|
||||
throw new ConnectError("Invalid runtime instance credential", Code.Unauthenticated);
|
||||
}
|
||||
};
|
||||
const clientsFor = (request) => {
|
||||
const context = request.context;
|
||||
if (process.env.QUIXOS_RUNTIME_INSTANCE_ID &&
|
||||
(!context?.grant || context.instanceId !== process.env.QUIXOS_RUNTIME_INSTANCE_ID || !context.workspaceEpoch)) {
|
||||
throw new ConnectError("Managed invocation requires an exact instance and epoch grant", Code.Unauthenticated);
|
||||
}
|
||||
if (!context?.grant)
|
||||
return { camino, orch };
|
||||
const transport = (url) => createConnectTransport({
|
||||
baseUrl: url,
|
||||
httpVersion: "1.1",
|
||||
interceptors: [
|
||||
(next) => async (call) => {
|
||||
call.header.set("x-quixos-invocation-grant", context.grant);
|
||||
call.header.set("x-camino-runtime-token", processToken);
|
||||
return next(call);
|
||||
},
|
||||
],
|
||||
});
|
||||
return {
|
||||
camino: createClient(CaminoService, transport(config.caminoUrl ?? process.env.CAMINO_URL ?? "http://127.0.0.1:7310")),
|
||||
orch: createClient(OrchestratorRuntime, transport(config.orchUrl ?? process.env.QUIXOS_ORCH_URL ?? "http://127.0.0.1:7311")),
|
||||
};
|
||||
};
|
||||
const runtimeControl = async (operation, input) => {
|
||||
const response = await fetch(`${config.caminoUrl ?? process.env.CAMINO_URL ?? "http://127.0.0.1:7310"}/__runtime/${operation}`, {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json", "x-camino-runtime-token": processToken },
|
||||
body: JSON.stringify(input),
|
||||
signal: AbortSignal.timeout(10_000),
|
||||
});
|
||||
const value = (await response.json());
|
||||
if (!response.ok)
|
||||
throw new RuntimeAuthorityError(value.error ?? "Runtime authority request failed");
|
||||
return value;
|
||||
};
|
||||
const attachSessions = (runtimeContext, request) => {
|
||||
if (!request.context?.grant || !request.context.ownerConformanceId)
|
||||
return;
|
||||
runtimeContext.openSession = async () => {
|
||||
const ownerId = request.context.ownerConformanceId;
|
||||
const registration = {
|
||||
grant: request.context.grant,
|
||||
objectId: request.objectId,
|
||||
ownerId,
|
||||
sessionId: `session:${randomBytes(16).toString("hex")}`,
|
||||
token: randomBytes(32).toString("base64url"),
|
||||
};
|
||||
const register = () => runtimeControl("register-session", registration);
|
||||
const registered = await register().catch((error) => {
|
||||
// Retry a transport/lost-response failure with exactly the same identity.
|
||||
// Admission/authority errors are definitive and must not be retried here.
|
||||
if (error instanceof RuntimeAuthorityError)
|
||||
throw error;
|
||||
return register();
|
||||
});
|
||||
let closed = false;
|
||||
return {
|
||||
id: registered.sessionId,
|
||||
async run(work) {
|
||||
if (closed)
|
||||
throw new RuntimeAuthorityError("SESSION_CLOSED");
|
||||
// Acquisition happens before user code. A fence failure can be retried
|
||||
// by the caller without replaying a side-effecting callback.
|
||||
const grant = await runtimeControl("acquire-session", registered);
|
||||
const execution = invocations.begin(grant.invocationId);
|
||||
const sessionRequest = {
|
||||
...request,
|
||||
context: { grant: grant.grant, instanceId: grant.instanceId, workspaceEpoch: grant.epoch },
|
||||
};
|
||||
const clients = clientsFor(sessionRequest);
|
||||
const context = createRuntimeContext(clients.camino, clients.orch, sessionRequest);
|
||||
context.signal = execution.signal;
|
||||
try {
|
||||
return await work(context);
|
||||
}
|
||||
finally {
|
||||
execution.finish();
|
||||
await runtimeControl("complete-invocation", { invocationId: grant.invocationId }).catch((error) => console.error("Session completion will be reconciled by the host", error));
|
||||
}
|
||||
},
|
||||
async close() {
|
||||
await runtimeControl("close-session", registered);
|
||||
closed = true;
|
||||
},
|
||||
};
|
||||
};
|
||||
};
|
||||
return (router) => router.service(PackageRuntime, {
|
||||
handshake: (request) => create(HandshakeResponseSchema, {
|
||||
packageRevisionId: config.packageRevisionId,
|
||||
runtimeProtocolVersion: "quixos-capabilities-v1",
|
||||
exportIds: Object.keys(config.exports),
|
||||
capabilities: ["invocation-completion-v1", "instance-authentication-v1", "epoch-grants-v1"],
|
||||
instanceId: process.env.QUIXOS_RUNTIME_INSTANCE_ID ?? "",
|
||||
authenticationProof: request.nonce && processToken
|
||||
? createHmac("sha256", processToken)
|
||||
.update(JSON.stringify([
|
||||
request.nonce,
|
||||
process.env.QUIXOS_RUNTIME_INSTANCE_ID ?? "",
|
||||
config.packageRevisionId,
|
||||
]))
|
||||
.digest("hex")
|
||||
: "",
|
||||
}),
|
||||
getInvocationStatus: (request, context) => {
|
||||
authenticateInstance(context.requestHeader);
|
||||
return invocations.status(request.invocationId);
|
||||
},
|
||||
cancelInvocation: (request, context) => {
|
||||
authenticateInstance(context.requestHeader);
|
||||
return invocations.cancel(request.invocationId);
|
||||
},
|
||||
invoke: async (request, context) => {
|
||||
authenticateInstance(context.requestHeader);
|
||||
const { camino, orch } = clientsFor(request);
|
||||
const exportId = request.export?.exportId;
|
||||
const handler = exportId ? config.exports[exportId] : undefined;
|
||||
if (!handler)
|
||||
throw new ConnectError(`Unknown export ${exportId ?? ""}`, Code.NotFound);
|
||||
const execution = invocations.begin(request.invocationId || (process.env.QUIXOS_RUNTIME_INSTANCE_ID ? "" : randomUUID()));
|
||||
try {
|
||||
const runtimeContext = createRuntimeContext(camino, orch, request);
|
||||
attachSessions(runtimeContext, request);
|
||||
runtimeContext.signal = AbortSignal.any([context.signal, execution.signal]);
|
||||
const result = await evaluate(handler, runtimeContext);
|
||||
execution.finish();
|
||||
return create(InvokeResponseSchema, {
|
||||
ok: true,
|
||||
result: result.value,
|
||||
dependencies: protoDependencies(result.dependencies),
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
execution.finish(true);
|
||||
return create(InvokeResponseSchema, {
|
||||
ok: false,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: async function* (request, context) {
|
||||
authenticateInstance(context.requestHeader);
|
||||
const { camino, orch } = clientsFor(request);
|
||||
const exportId = request.export?.exportId;
|
||||
const handler = exportId ? config.exports[exportId] : undefined;
|
||||
if (!handler || !isDerived(handler)) {
|
||||
throw new ConnectError(`Export ${exportId ?? ""} is not derived`, Code.FailedPrecondition);
|
||||
}
|
||||
const execution = invocations.begin(request.invocationId || (process.env.QUIXOS_RUNTIME_INSTANCE_ID ? "" : randomUUID()));
|
||||
const signal = AbortSignal.any([context.signal, execution.signal]);
|
||||
try {
|
||||
const watchId = `watch:${randomUUID()}`;
|
||||
const runtimeContext = createRuntimeContext(camino, orch, request);
|
||||
attachSessions(runtimeContext, request);
|
||||
runtimeContext.signal = signal;
|
||||
const subscriptions = new Map();
|
||||
const establishing = new Map();
|
||||
let subscriptionEpoch = 0;
|
||||
const ensureSubscription = async (dependency) => {
|
||||
const key = dependencyKey(dependency);
|
||||
if (subscriptions.has(key))
|
||||
return;
|
||||
const pending = establishing.get(key);
|
||||
if (pending)
|
||||
return await pending;
|
||||
const establish = (async () => {
|
||||
const controller = new AbortController();
|
||||
const stream = camino
|
||||
.watchObject({
|
||||
objectId: dependency.objectId,
|
||||
includeSnapshot: true,
|
||||
attachmentIds: request.context?.grant ? [dependency.attachmentId] : [],
|
||||
}, { signal: controller.signal })[Symbol.asyncIterator]();
|
||||
try {
|
||||
// Camino subscribes before producing the snapshot, so once this
|
||||
// resolves the following state/edge read cannot race the stream.
|
||||
const snapshot = await stream.next();
|
||||
if (snapshot.done)
|
||||
throw new Error(`Dependency stream ${key} ended during setup`);
|
||||
const waitNext = () => stream.next().then((result) => ({ key, done: Boolean(result.done) }), (error) => ({ key, done: true, error }));
|
||||
const subscription = {
|
||||
dependency,
|
||||
controller,
|
||||
waitNext,
|
||||
next: Promise.resolve({ key, done: false }),
|
||||
};
|
||||
subscription.next = waitNext();
|
||||
subscriptions.set(key, subscription);
|
||||
subscriptionEpoch += 1;
|
||||
}
|
||||
catch (error) {
|
||||
controller.abort();
|
||||
throw error;
|
||||
}
|
||||
})();
|
||||
establishing.set(key, establish);
|
||||
try {
|
||||
await establish;
|
||||
}
|
||||
finally {
|
||||
establishing.delete(key);
|
||||
}
|
||||
};
|
||||
const abortAll = () => {
|
||||
for (const subscription of subscriptions.values()) {
|
||||
subscription.controller.abort();
|
||||
}
|
||||
};
|
||||
signal.addEventListener("abort", abortAll, { once: true });
|
||||
const evaluateWithStableSubscriptions = async () => {
|
||||
// A direct state/edge port records its dependency before reading it,
|
||||
// but a nested interface invocation can only report its transitive
|
||||
// dependencies after that invocation returns. Once a new dependency
|
||||
// stream is established, evaluate again so every read contributing to
|
||||
// the emitted value happened after its stream became live.
|
||||
for (let pass = 0; pass < 32; pass += 1) {
|
||||
const before = subscriptionEpoch;
|
||||
const result = await evaluate(handler, runtimeContext, ensureSubscription);
|
||||
if (subscriptionEpoch === before)
|
||||
return result;
|
||||
}
|
||||
throw new Error("Derived dependency discovery did not stabilize after 32 passes");
|
||||
};
|
||||
try {
|
||||
let current = await evaluateWithStableSubscriptions();
|
||||
yield create(WatchEventSchema, {
|
||||
watchId,
|
||||
value: current.value,
|
||||
dependencies: protoDependencies(current.dependencies),
|
||||
initial: true,
|
||||
});
|
||||
const abort = new Promise((resolve) => {
|
||||
if (signal.aborted)
|
||||
resolve("abort");
|
||||
else
|
||||
signal.addEventListener("abort", () => resolve("abort"), { once: true });
|
||||
});
|
||||
while (!signal.aborted) {
|
||||
if (subscriptions.size === 0) {
|
||||
await abort;
|
||||
break;
|
||||
}
|
||||
const outcome = await Promise.race([...[...subscriptions.values()].map((entry) => entry.next), abort]);
|
||||
if (outcome === "abort")
|
||||
break;
|
||||
const subscription = subscriptions.get(outcome.key);
|
||||
if (!subscription)
|
||||
continue;
|
||||
if (outcome.error)
|
||||
throw outcome.error;
|
||||
if (outcome.done)
|
||||
throw new Error(`Dependency stream ${outcome.key} ended unexpectedly`);
|
||||
subscription.next = subscription.waitNext();
|
||||
const updated = await evaluateWithStableSubscriptions();
|
||||
const active = new Set(updated.dependencies.map(dependencyKey));
|
||||
for (const [key, entry] of subscriptions) {
|
||||
if (!active.has(key)) {
|
||||
entry.controller.abort();
|
||||
subscriptions.delete(key);
|
||||
}
|
||||
}
|
||||
if (!equals(ValueSchema, current.value, updated.value)) {
|
||||
yield create(WatchEventSchema, {
|
||||
watchId,
|
||||
value: updated.value,
|
||||
dependencies: protoDependencies(updated.dependencies),
|
||||
});
|
||||
}
|
||||
current = updated;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
signal.removeEventListener("abort", abortAll);
|
||||
abortAll();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
execution.finish();
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
export const servePackageRuntime = (config) => {
|
||||
const host = process.env.QUIXOS_RUNTIME_HOST ?? "127.0.0.1";
|
||||
const port = Number(process.env.QUIXOS_RUNTIME_PORT ?? "0");
|
||||
const handler = connectNodeAdapter({ routes: createPackageRuntimeRoutes(config) });
|
||||
const server = http.createServer((request, response) => void handler(request, response));
|
||||
server.listen(port, host, () => console.log(`${config.packageRevisionId} listening on ${host}:${port}`));
|
||||
const shutdown = () => {
|
||||
server.close(() => process.exit(0));
|
||||
server.closeAllConnections();
|
||||
};
|
||||
process.on("SIGTERM", shutdown);
|
||||
process.on("SIGINT", shutdown);
|
||||
return server;
|
||||
};
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
/** Execution completion, not HTTP disconnection, is the drain boundary. */
|
||||
export declare const createInvocationRegistry: () => {
|
||||
begin(id: string): {
|
||||
signal: AbortSignal;
|
||||
finish(failed?: boolean): void;
|
||||
};
|
||||
status(id: string): {
|
||||
invocationId: string;
|
||||
state: string;
|
||||
};
|
||||
cancel(id: string): {
|
||||
invocationId: string;
|
||||
state: string;
|
||||
};
|
||||
};
|
||||
//# sourceMappingURL=invocations.d.ts.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"invocations.d.ts","sourceRoot":"","sources":["../src/invocations.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,eAAO,MAAM,wBAAwB;IAGjC,KAAK,KAAK,MAAM;QASZ,MAAM;QACN,MAAM;;IAKV,MAAM,KAAK,MAAM;QACN,YAAY;QAAM,KAAK;;IAElC,MAAM,KAAK,MAAM;;;;CASpB,CAAC"}
|
||||
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
/** Execution completion, not HTTP disconnection, is the drain boundary. */
|
||||
export const createInvocationRegistry = () => {
|
||||
const entries = new Map();
|
||||
return {
|
||||
begin(id) {
|
||||
if (!id || entries.has(id))
|
||||
throw new Error("Invocation ID is missing or already used; invocations are never replayed implicitly");
|
||||
// Completed identities remain until process retirement. A bounded process
|
||||
// may reject new work; it must not evict and accidentally replay a call.
|
||||
if (entries.size >= 100_000)
|
||||
throw new Error("Invocation registry full; explicit runtime retirement required");
|
||||
const entry = { state: "running", controller: new AbortController() };
|
||||
entries.set(id, entry);
|
||||
return {
|
||||
signal: entry.controller.signal,
|
||||
finish(failed = false) {
|
||||
entry.state = failed ? "failed" : "completed";
|
||||
},
|
||||
};
|
||||
},
|
||||
status(id) {
|
||||
return { invocationId: id, state: entries.get(id)?.state ?? "unknown" };
|
||||
},
|
||||
cancel(id) {
|
||||
const entry = entries.get(id);
|
||||
if (entry && ["running", "cancellation-requested"].includes(entry.state)) {
|
||||
entry.state = "cancellation-requested";
|
||||
entry.controller.abort();
|
||||
}
|
||||
return this.status(id);
|
||||
},
|
||||
};
|
||||
};
|
||||
Vendored
+72
@@ -0,0 +1,72 @@
|
||||
export type MigrationInput = {
|
||||
schemaVersion: 1;
|
||||
executionId: string;
|
||||
exportId: string;
|
||||
ports: {
|
||||
name: string;
|
||||
binding: string;
|
||||
view: "old" | "new";
|
||||
access: ("read" | "write" | "create" | "edge")[];
|
||||
atomId?: string;
|
||||
attachedAtomId?: string;
|
||||
defaultValue?: unknown;
|
||||
states?: {
|
||||
objectId: string;
|
||||
value: unknown;
|
||||
}[];
|
||||
edges?: MigrationEdge[];
|
||||
}[];
|
||||
};
|
||||
export type MigrationEdge = {
|
||||
id: string;
|
||||
edgeTypeId: string;
|
||||
firstObjectId: string;
|
||||
secondObjectId: string;
|
||||
firstProjectionId: string;
|
||||
secondProjectionId: string;
|
||||
firstOrdinal?: number;
|
||||
secondOrdinal?: number;
|
||||
firstKeyJson?: string;
|
||||
secondKeyJson?: string;
|
||||
};
|
||||
export type MigrationOutput = {
|
||||
schemaVersion: 1;
|
||||
executionId: string;
|
||||
writes: {
|
||||
port: string;
|
||||
objectId: string;
|
||||
value: unknown;
|
||||
}[];
|
||||
creates: {
|
||||
port: string;
|
||||
logicalKey: string;
|
||||
objectId: string;
|
||||
}[];
|
||||
edgeReplacements: {
|
||||
port: string;
|
||||
edges: MigrationEdge[];
|
||||
}[];
|
||||
};
|
||||
export type MigrationContext = {
|
||||
enumerate(port: string): {
|
||||
objectId: string;
|
||||
value: unknown;
|
||||
}[];
|
||||
read(port: string, objectId: string): unknown;
|
||||
write(port: string, objectId: string, value: unknown): void;
|
||||
create(port: string, logicalKey: string): string;
|
||||
edges(port: string): MigrationEdge[];
|
||||
replaceEdges(port: string, edges: MigrationEdge[]): void;
|
||||
};
|
||||
export declare const migrationObjectId: (executionId: string, port: string, logicalKey: string) => string;
|
||||
/** No ordinary RuntimeContext or network/database clients are supplied here.
|
||||
* Process isolation belongs to the host, not this convenience API. */
|
||||
export declare const createMigrationContext: (input: MigrationInput) => {
|
||||
context: MigrationContext;
|
||||
result: () => MigrationOutput;
|
||||
};
|
||||
/** Entrypoint for an immutable package's dedicated bin/migrate executable.
|
||||
* stdout is protocol-only; send diagnostics to stderr. The host independently
|
||||
* validates every write, helper identity, contract, and completion receipt. */
|
||||
export declare const serveMigration: (exports: Record<string, (context: MigrationContext) => void | Promise<void>>) => Promise<void>;
|
||||
//# sourceMappingURL=migration.d.ts.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../src/migration.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,EAAE,CAAC,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;QACpB,MAAM,EAAE,CAAC,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC;QACjD,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,MAAM,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,OAAO,CAAA;SAAE,EAAE,CAAC;QAChD,KAAK,CAAC,EAAE,aAAa,EAAE,CAAC;KACzB,EAAE,CAAC;CACL,CAAC;AACF,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AACF,MAAM,MAAM,eAAe,GAAG;IAC5B,aAAa,EAAE,CAAC,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC7D,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAClE,gBAAgB,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,aAAa,EAAE,CAAA;KAAE,EAAE,CAAC;CAC9D,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAChE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IACjD,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAAC;IACrC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;CAC1D,CAAC;AACF,eAAO,MAAM,iBAAiB,gBAAiB,MAAM,QAAQ,MAAM,cAAc,MAAM,WAGnE,CAAC;AAErB;sEACsE;AACtE,eAAO,MAAM,sBAAsB,UAAW,cAAc;;;CAgF3D,CAAC;AAEF;;+EAE+E;AAC/E,eAAO,MAAM,cAAc,YAAmB,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,kBAgBhH,CAAC"}
|
||||
Vendored
+108
@@ -0,0 +1,108 @@
|
||||
import { createHash } from "node:crypto";
|
||||
export const migrationObjectId = (executionId, port, logicalKey) => `obj:migration:${createHash("sha256")
|
||||
.update(JSON.stringify([executionId, port, logicalKey]))
|
||||
.digest("hex")}`;
|
||||
/** No ordinary RuntimeContext or network/database clients are supplied here.
|
||||
* Process isolation belongs to the host, not this convenience API. */
|
||||
export const createMigrationContext = (input) => {
|
||||
if (input.schemaVersion !== 1 ||
|
||||
!input.executionId ||
|
||||
new Set(input.ports.map((entry) => entry.name)).size !== input.ports.length)
|
||||
throw new Error("Invalid migration input");
|
||||
const output = {
|
||||
schemaVersion: 1,
|
||||
executionId: input.executionId,
|
||||
writes: [],
|
||||
creates: [],
|
||||
edgeReplacements: [],
|
||||
};
|
||||
const port = (name, access) => {
|
||||
const selected = input.ports.find((entry) => entry.name === name);
|
||||
if (!selected?.access.includes(access) || (selected.view === "old" && access !== "read"))
|
||||
throw new Error(`Migration port ${name} does not grant ${access}`);
|
||||
return selected;
|
||||
};
|
||||
const context = {
|
||||
enumerate(name) {
|
||||
const selected = port(name, "read"), states = structuredClone(selected.states ?? []);
|
||||
if (selected.view === "new" && Object.hasOwn(selected, "defaultValue"))
|
||||
for (const helper of output.creates) {
|
||||
if (input.ports.find((entry) => entry.name === helper.port)?.atomId === selected.attachedAtomId &&
|
||||
!states.some((entry) => entry.objectId === helper.objectId))
|
||||
states.push({ objectId: helper.objectId, value: structuredClone(selected.defaultValue) });
|
||||
}
|
||||
if (selected.view === "new")
|
||||
for (const write of output.writes) {
|
||||
if (input.ports.find((entry) => entry.name === write.port)?.binding !== selected.binding)
|
||||
continue;
|
||||
const existing = states.findIndex((entry) => entry.objectId === write.objectId), entry = { objectId: write.objectId, value: structuredClone(write.value) };
|
||||
if (existing < 0)
|
||||
states.push(entry);
|
||||
else
|
||||
states[existing] = entry;
|
||||
}
|
||||
return states.sort((a, b) => (a.objectId < b.objectId ? -1 : a.objectId > b.objectId ? 1 : 0));
|
||||
},
|
||||
read(name, objectId) {
|
||||
return context.enumerate(name).find((entry) => entry.objectId === objectId)?.value;
|
||||
},
|
||||
write(name, objectId, value) {
|
||||
port(name, "write");
|
||||
const previous = output.writes.findIndex((entry) => entry.port === name && entry.objectId === objectId);
|
||||
const entry = { port: name, objectId, value: structuredClone(value) };
|
||||
if (previous < 0)
|
||||
output.writes.push(entry);
|
||||
else
|
||||
output.writes[previous] = entry;
|
||||
},
|
||||
create(name, logicalKey) {
|
||||
port(name, "create");
|
||||
if (!logicalKey || logicalKey.length > 1024)
|
||||
throw new Error("Migration creation requires a bounded stable logical key");
|
||||
const objectId = migrationObjectId(input.executionId, name, logicalKey);
|
||||
if (!output.creates.some((entry) => entry.objectId === objectId))
|
||||
output.creates.push({ port: name, logicalKey, objectId });
|
||||
return objectId;
|
||||
},
|
||||
edges(name) {
|
||||
const selected = port(name, "read");
|
||||
const replacement = selected.view === "new"
|
||||
? output.edgeReplacements.find((entry) => input.ports.find((candidate) => candidate.name === entry.port)?.binding === selected.binding)
|
||||
: undefined;
|
||||
return structuredClone(replacement?.edges ?? selected.edges ?? []);
|
||||
},
|
||||
replaceEdges(name, edges) {
|
||||
port(name, "edge");
|
||||
const previous = output.edgeReplacements.findIndex((entry) => entry.port === name);
|
||||
const entry = { port: name, edges: structuredClone(edges) };
|
||||
if (previous < 0)
|
||||
output.edgeReplacements.push(entry);
|
||||
else
|
||||
output.edgeReplacements[previous] = entry;
|
||||
},
|
||||
};
|
||||
return { context, result: () => structuredClone(output) };
|
||||
};
|
||||
/** Entrypoint for an immutable package's dedicated bin/migrate executable.
|
||||
* stdout is protocol-only; send diagnostics to stderr. The host independently
|
||||
* validates every write, helper identity, contract, and completion receipt. */
|
||||
export const serveMigration = async (exports) => {
|
||||
const chunks = [];
|
||||
let bytes = 0;
|
||||
for await (const chunk of process.stdin) {
|
||||
bytes += chunk.length;
|
||||
if (bytes > 16 * 1024 * 1024)
|
||||
throw new Error("Migration input exceeds 16 MiB");
|
||||
chunks.push(Buffer.from(chunk));
|
||||
}
|
||||
const input = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
||||
const implementation = Object.hasOwn(exports, input.exportId) ? exports[input.exportId] : undefined;
|
||||
if (!implementation)
|
||||
throw new Error("Unknown migration export");
|
||||
const execution = createMigrationContext(input);
|
||||
await implementation(execution.context);
|
||||
const result = JSON.stringify(execution.result());
|
||||
if (Buffer.byteLength(result) > 16 * 1024 * 1024)
|
||||
throw new Error("Migration output exceeds 16 MiB");
|
||||
process.stdout.write(`${result}\n`);
|
||||
};
|
||||
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
import { type QxValueType } from "./bindings.js";
|
||||
import type { QueryResponse } from "./camino/api_pb.js";
|
||||
import type { QxObjectRef } from "./references.js";
|
||||
export type QxQueryPartial<T> = T extends QxObjectRef ? T : T extends readonly (infer Item)[] ? QxQueryPartial<Item>[] : T extends object ? {
|
||||
[Key in keyof T]?: QxQueryPartial<T[Key]>;
|
||||
} : T;
|
||||
export type QxQuerySnapshot<T> = {
|
||||
runId: string;
|
||||
sequence: bigint;
|
||||
dataVersion: string;
|
||||
bindingDigest: string;
|
||||
consistency: string;
|
||||
fields: {
|
||||
path: readonly (string | number)[];
|
||||
status: "pending" | "error";
|
||||
error?: string;
|
||||
}[];
|
||||
} & ({
|
||||
status: "ready";
|
||||
data: T;
|
||||
} | {
|
||||
status: "partial";
|
||||
data: QxQueryPartial<T>;
|
||||
});
|
||||
declare const queryTypes: unique symbol;
|
||||
/** Generated shape evidence, not permission to run a query. */
|
||||
export interface QxQueryDescriptor<Variables, Result, Root extends string = string> {
|
||||
readonly id: string;
|
||||
readonly definitionDigest: string;
|
||||
readonly rootInterfaceRevisionId: Root;
|
||||
readonly variables: QxValueType;
|
||||
readonly output: QxValueType;
|
||||
readonly watch: boolean;
|
||||
readonly [queryTypes]?: (variables: Variables, result: Result) => [Variables, Result];
|
||||
}
|
||||
export declare function decodeQuerySnapshot<T>(response: QueryResponse, output: QxValueType, runId: string, sequence: bigint): QxQuerySnapshot<T>;
|
||||
export {};
|
||||
//# sourceMappingURL=queries.d.ts.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,SAAS,WAAW,GACjD,CAAC,GACD,CAAC,SAAS,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,GAC/B,cAAc,CAAC,IAAI,CAAC,EAAE,GACtB,CAAC,SAAS,MAAM,GACd;KAAG,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;CAAE,GAC7C,CAAC,CAAC;AACV,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;QAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/F,GAAG,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,CAAA;CAAE,CAAC,CAAC;AACpF,OAAO,CAAC,MAAM,UAAU,EAAE,OAAO,MAAM,CAAC;AACxC,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,SAAS,MAAM,GAAG,MAAM;IAChF,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,uBAAuB,EAAE,IAAI,CAAC;IACvC,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;CACvF;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,eAAe,CAAC,CAAC,CAAC,CA6CpB"}
|
||||
Vendored
+57
@@ -0,0 +1,57 @@
|
||||
import { decodeQxValue } from "./bindings.js";
|
||||
export function decodeQuerySnapshot(response, output, runId, sequence) {
|
||||
if (response.preparationToken || response.residualWindows.length || response.relationalCaptures.length)
|
||||
throw new Error("QUERY_RESULT_UNFINISHED: private preparation is not a query result");
|
||||
const fields = [
|
||||
...response.pending.map((field) => ({ path: field.path, status: "pending" })),
|
||||
...response.errors.map((field) => ({ path: field.path, status: "error", error: field.error })),
|
||||
].map((field) => ({
|
||||
...field,
|
||||
path: field.path.map((part) => {
|
||||
if (part.part.case !== "field" && part.part.case !== "index")
|
||||
throw new Error("QUERY_PATCH_INVALID");
|
||||
return part.part.value;
|
||||
}),
|
||||
}));
|
||||
// Pending/error values are absent, not successful nulls of a scalar type.
|
||||
const shape = structuredClone(output);
|
||||
for (const field of fields) {
|
||||
let cursor = shape;
|
||||
for (const [index, part] of field.path.entries()) {
|
||||
while (cursor.kind === "optional")
|
||||
cursor = cursor.value;
|
||||
const last = index === field.path.length - 1;
|
||||
if (typeof part === "string" && cursor.kind === "record" && cursor.fields[part]) {
|
||||
if (last)
|
||||
cursor.fields[part] = { kind: "optional", value: cursor.fields[part] };
|
||||
else
|
||||
cursor = cursor.fields[part];
|
||||
}
|
||||
else if (typeof part === "number" && cursor.kind === "list")
|
||||
cursor = cursor.value;
|
||||
else
|
||||
throw new Error("QUERY_PATCH_INVALID");
|
||||
}
|
||||
}
|
||||
const data = decodeQxValue(shape, response.value, {});
|
||||
for (const field of fields) {
|
||||
let cursor = data;
|
||||
for (const [index, part] of field.path.entries()) {
|
||||
if (!cursor || typeof cursor !== "object")
|
||||
throw new Error("QUERY_PATCH_INVALID");
|
||||
if (index === field.path.length - 1)
|
||||
delete cursor[part];
|
||||
else
|
||||
cursor = cursor[part];
|
||||
}
|
||||
}
|
||||
return {
|
||||
runId,
|
||||
sequence,
|
||||
dataVersion: response.dataVersion,
|
||||
bindingDigest: response.bindingDigest,
|
||||
consistency: response.consistency,
|
||||
fields,
|
||||
...(fields.length ? { status: "partial", data } : { status: "ready", data }),
|
||||
};
|
||||
}
|
||||
Vendored
+904
@@ -0,0 +1,904 @@
|
||||
import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2";
|
||||
import type { CaminoObject, CrdtValue, QueryPathPart, QueryRequestSchema, QueryResponse, QueryResponseSchema, Value } from "../camino/api_pb.js";
|
||||
import type { InstalledQuery } from "../camino/schema_pb.js";
|
||||
import type { PackageDescriptor } from "./package_pb.js";
|
||||
import type { CapabilityRef, ConformanceWitness, PackageExportRef } from "./refs_pb.js";
|
||||
import type { DerivedDependency } from "./runtime_pb.js";
|
||||
import type { Message } from "@bufbuild/protobuf";
|
||||
/**
|
||||
* Describes the file quixos/orch.proto.
|
||||
*/
|
||||
export declare const file_quixos_orch: GenFile;
|
||||
/**
|
||||
* @generated from message quixos.orch.QueryEvent
|
||||
*/
|
||||
export type QueryEvent = Message<"quixos.orch.QueryEvent"> & {
|
||||
/**
|
||||
* @generated from field: string run_id = 1;
|
||||
*/
|
||||
runId: string;
|
||||
/**
|
||||
* @generated from field: uint64 sequence = 2;
|
||||
*/
|
||||
sequence: bigint;
|
||||
/**
|
||||
* @generated from field: string kind = 3;
|
||||
*/
|
||||
kind: string;
|
||||
/**
|
||||
* @generated from field: camino.QueryResponse snapshot = 4;
|
||||
*/
|
||||
snapshot?: QueryResponse | undefined;
|
||||
/**
|
||||
* @generated from field: repeated camino.QueryPathPart path = 5;
|
||||
*/
|
||||
path: QueryPathPart[];
|
||||
/**
|
||||
* @generated from field: camino.Value value = 6;
|
||||
*/
|
||||
value?: Value | undefined;
|
||||
/**
|
||||
* @generated from field: string error = 7;
|
||||
*/
|
||||
error: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.QueryEvent.
|
||||
* Use `create(QueryEventSchema)` to create a new message.
|
||||
*/
|
||||
export declare const QueryEventSchema: GenMessage<QueryEvent>;
|
||||
/**
|
||||
* Exact closed interface lookup; no policy selection or competing conformances.
|
||||
*
|
||||
* @generated from message quixos.orch.TryConformRequest
|
||||
*/
|
||||
export type TryConformRequest = Message<"quixos.orch.TryConformRequest"> & {
|
||||
/**
|
||||
* @generated from field: string object_id = 1;
|
||||
*/
|
||||
objectId: string;
|
||||
/**
|
||||
* @generated from field: string interface_revision_id = 2;
|
||||
*/
|
||||
interfaceRevisionId: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.TryConformRequest.
|
||||
* Use `create(TryConformRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const TryConformRequestSchema: GenMessage<TryConformRequest>;
|
||||
/**
|
||||
* @generated from message quixos.orch.TryConformResponse
|
||||
*/
|
||||
export type TryConformResponse = Message<"quixos.orch.TryConformResponse"> & {
|
||||
/**
|
||||
* Absent only when this object lacks a known contract. Other failures are errors.
|
||||
*
|
||||
* @generated from field: quixos.ConformanceWitness conformance = 1;
|
||||
*/
|
||||
conformance?: ConformanceWitness | undefined;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.TryConformResponse.
|
||||
* Use `create(TryConformResponseSchema)` to create a new message.
|
||||
*/
|
||||
export declare const TryConformResponseSchema: GenMessage<TryConformResponse>;
|
||||
/**
|
||||
* @generated from message quixos.orch.ConstructObjectRequest
|
||||
*/
|
||||
export type ConstructObjectRequest = Message<"quixos.orch.ConstructObjectRequest"> & {
|
||||
/**
|
||||
* @generated from field: string atom_id = 1;
|
||||
*/
|
||||
atomId: string;
|
||||
/**
|
||||
* @generated from field: map<string, camino.Value> input = 2;
|
||||
*/
|
||||
input: {
|
||||
[key: string]: Value;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.ConstructObjectRequest.
|
||||
* Use `create(ConstructObjectRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const ConstructObjectRequestSchema: GenMessage<ConstructObjectRequest>;
|
||||
/**
|
||||
* @generated from message quixos.orch.ConstructObjectResponse
|
||||
*/
|
||||
export type ConstructObjectResponse = Message<"quixos.orch.ConstructObjectResponse"> & {
|
||||
/**
|
||||
* @generated from field: camino.CaminoObject object = 1;
|
||||
*/
|
||||
object?: CaminoObject | undefined;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.ConstructObjectResponse.
|
||||
* Use `create(ConstructObjectResponseSchema)` to create a new message.
|
||||
*/
|
||||
export declare const ConstructObjectResponseSchema: GenMessage<ConstructObjectResponse>;
|
||||
/**
|
||||
* @generated from message quixos.orch.ResolveOrConstructRelatedObjectRequest
|
||||
*/
|
||||
export type ResolveOrConstructRelatedObjectRequest = Message<"quixos.orch.ResolveOrConstructRelatedObjectRequest"> & {
|
||||
/**
|
||||
* @generated from field: string object_id = 1;
|
||||
*/
|
||||
objectId: string;
|
||||
/**
|
||||
* @generated from field: string interface_revision_id = 2;
|
||||
*/
|
||||
interfaceRevisionId: string;
|
||||
/**
|
||||
* @generated from field: string member_id = 3;
|
||||
*/
|
||||
memberId: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.ResolveOrConstructRelatedObjectRequest.
|
||||
* Use `create(ResolveOrConstructRelatedObjectRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const ResolveOrConstructRelatedObjectRequestSchema: GenMessage<ResolveOrConstructRelatedObjectRequest>;
|
||||
/**
|
||||
* @generated from message quixos.orch.ResolveOrConstructRelatedObjectResponse
|
||||
*/
|
||||
export type ResolveOrConstructRelatedObjectResponse = Message<"quixos.orch.ResolveOrConstructRelatedObjectResponse"> & {
|
||||
/**
|
||||
* @generated from field: camino.CaminoObject object = 1;
|
||||
*/
|
||||
object?: CaminoObject | undefined;
|
||||
/**
|
||||
* @generated from field: bool constructed = 2;
|
||||
*/
|
||||
constructed: boolean;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.ResolveOrConstructRelatedObjectResponse.
|
||||
* Use `create(ResolveOrConstructRelatedObjectResponseSchema)` to create a new message.
|
||||
*/
|
||||
export declare const ResolveOrConstructRelatedObjectResponseSchema: GenMessage<ResolveOrConstructRelatedObjectResponse>;
|
||||
/**
|
||||
* @generated from message quixos.orch.InvokeCapabilityRequest
|
||||
*/
|
||||
export type InvokeCapabilityRequest = Message<"quixos.orch.InvokeCapabilityRequest"> & {
|
||||
/**
|
||||
* @generated from field: quixos.CapabilityRef capability = 1;
|
||||
*/
|
||||
capability?: CapabilityRef | undefined;
|
||||
/**
|
||||
* @generated from field: string object_id = 2;
|
||||
*/
|
||||
objectId: string;
|
||||
/**
|
||||
* @generated from field: map<string, camino.Value> input = 3;
|
||||
*/
|
||||
input: {
|
||||
[key: string]: Value;
|
||||
};
|
||||
/**
|
||||
* Identifies one logical client mutation across the capability and Camino
|
||||
* layers so a live-value controller can recognize its own confirmation.
|
||||
*
|
||||
* @generated from field: string client_mutation_id = 4;
|
||||
*/
|
||||
clientMutationId: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.InvokeCapabilityRequest.
|
||||
* Use `create(InvokeCapabilityRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const InvokeCapabilityRequestSchema: GenMessage<InvokeCapabilityRequest>;
|
||||
/**
|
||||
* @generated from message quixos.orch.InvokeClassCapabilityRequest
|
||||
*/
|
||||
export type InvokeClassCapabilityRequest = Message<"quixos.orch.InvokeClassCapabilityRequest"> & {
|
||||
/**
|
||||
* @generated from field: string conformance_id = 1;
|
||||
*/
|
||||
conformanceId: string;
|
||||
/**
|
||||
* @generated from field: string operation_id = 2;
|
||||
*/
|
||||
operationId: string;
|
||||
/**
|
||||
* @generated from field: map<string, camino.Value> input = 3;
|
||||
*/
|
||||
input: {
|
||||
[key: string]: Value;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.InvokeClassCapabilityRequest.
|
||||
* Use `create(InvokeClassCapabilityRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const InvokeClassCapabilityRequestSchema: GenMessage<InvokeClassCapabilityRequest>;
|
||||
/**
|
||||
* @generated from message quixos.orch.InvokeCapabilityResponse
|
||||
*/
|
||||
export type InvokeCapabilityResponse = Message<"quixos.orch.InvokeCapabilityResponse"> & {
|
||||
/**
|
||||
* @generated from field: string invocation_id = 1;
|
||||
*/
|
||||
invocationId: string;
|
||||
/**
|
||||
* @generated from field: quixos.orch.Activation activation = 2;
|
||||
*/
|
||||
activation?: Activation | undefined;
|
||||
/**
|
||||
* @generated from field: bool ok = 3;
|
||||
*/
|
||||
ok: boolean;
|
||||
/**
|
||||
* @generated from field: camino.Value result = 4;
|
||||
*/
|
||||
result?: Value | undefined;
|
||||
/**
|
||||
* @generated from field: string error = 5;
|
||||
*/
|
||||
error: string;
|
||||
/**
|
||||
* @generated from field: repeated quixos.runtime.DerivedDependency dependencies = 6;
|
||||
*/
|
||||
dependencies: DerivedDependency[];
|
||||
/**
|
||||
* @generated from field: quixos.orch.FieldEditing field_editing = 7;
|
||||
*/
|
||||
fieldEditing?: FieldEditing | undefined;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.InvokeCapabilityResponse.
|
||||
* Use `create(InvokeCapabilityResponseSchema)` to create a new message.
|
||||
*/
|
||||
export declare const InvokeCapabilityResponseSchema: GenMessage<InvokeCapabilityResponse>;
|
||||
/**
|
||||
* Resolved from the checked native getter/setter binding, not Value.source.
|
||||
*
|
||||
* @generated from message quixos.orch.FieldEditing
|
||||
*/
|
||||
export type FieldEditing = Message<"quixos.orch.FieldEditing"> & {
|
||||
/**
|
||||
* @generated from field: string getter_operation_id = 1;
|
||||
*/
|
||||
getterOperationId: string;
|
||||
/**
|
||||
* @generated from field: string setter_operation_id = 2;
|
||||
*/
|
||||
setterOperationId: string;
|
||||
/**
|
||||
* @generated from field: string document_type = 3;
|
||||
*/
|
||||
documentType: string;
|
||||
/**
|
||||
* @generated from field: string binding_digest = 4;
|
||||
*/
|
||||
bindingDigest: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.FieldEditing.
|
||||
* Use `create(FieldEditingSchema)` to create a new message.
|
||||
*/
|
||||
export declare const FieldEditingSchema: GenMessage<FieldEditing>;
|
||||
/**
|
||||
* @generated from message quixos.orch.EditCapabilityFieldRequest
|
||||
*/
|
||||
export type EditCapabilityFieldRequest = Message<"quixos.orch.EditCapabilityFieldRequest"> & {
|
||||
/**
|
||||
* The public getter; setter must belong to the same value member.
|
||||
*
|
||||
* @generated from field: quixos.CapabilityRef capability = 1;
|
||||
*/
|
||||
capability?: CapabilityRef | undefined;
|
||||
/**
|
||||
* @generated from field: string object_id = 2;
|
||||
*/
|
||||
objectId: string;
|
||||
/**
|
||||
* @generated from field: string setter_operation_id = 3;
|
||||
*/
|
||||
setterOperationId: string;
|
||||
/**
|
||||
* @generated from field: string binding_digest = 4;
|
||||
*/
|
||||
bindingDigest: string;
|
||||
/**
|
||||
* @generated from field: camino.CrdtValue update = 5;
|
||||
*/
|
||||
update?: CrdtValue | undefined;
|
||||
/**
|
||||
* @generated from field: string client_mutation_id = 6;
|
||||
*/
|
||||
clientMutationId: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.EditCapabilityFieldRequest.
|
||||
* Use `create(EditCapabilityFieldRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const EditCapabilityFieldRequestSchema: GenMessage<EditCapabilityFieldRequest>;
|
||||
/**
|
||||
* @generated from message quixos.orch.WatchCapabilityRequest
|
||||
*/
|
||||
export type WatchCapabilityRequest = Message<"quixos.orch.WatchCapabilityRequest"> & {
|
||||
/**
|
||||
* @generated from field: quixos.CapabilityRef capability = 1;
|
||||
*/
|
||||
capability?: CapabilityRef | undefined;
|
||||
/**
|
||||
* @generated from field: string object_id = 2;
|
||||
*/
|
||||
objectId: string;
|
||||
/**
|
||||
* @generated from field: map<string, camino.Value> input = 3;
|
||||
*/
|
||||
input: {
|
||||
[key: string]: Value;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.WatchCapabilityRequest.
|
||||
* Use `create(WatchCapabilityRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const WatchCapabilityRequestSchema: GenMessage<WatchCapabilityRequest>;
|
||||
/**
|
||||
* @generated from message quixos.orch.WatchCapabilityEvent
|
||||
*/
|
||||
export type WatchCapabilityEvent = Message<"quixos.orch.WatchCapabilityEvent"> & {
|
||||
/**
|
||||
* @generated from field: string invocation_id = 1;
|
||||
*/
|
||||
invocationId: string;
|
||||
/**
|
||||
* @generated from field: quixos.orch.Activation activation = 2;
|
||||
*/
|
||||
activation?: Activation | undefined;
|
||||
/**
|
||||
* @generated from field: string watch_id = 3;
|
||||
*/
|
||||
watchId: string;
|
||||
/**
|
||||
* @generated from field: camino.Value value = 4;
|
||||
*/
|
||||
value?: Value | undefined;
|
||||
/**
|
||||
* @generated from field: repeated quixos.runtime.DerivedDependency dependencies = 5;
|
||||
*/
|
||||
dependencies: DerivedDependency[];
|
||||
/**
|
||||
* @generated from field: string error = 6;
|
||||
*/
|
||||
error: string;
|
||||
/**
|
||||
* @generated from field: bool initial = 7;
|
||||
*/
|
||||
initial: boolean;
|
||||
/**
|
||||
* @generated from field: quixos.orch.FieldEditing field_editing = 8;
|
||||
*/
|
||||
fieldEditing?: FieldEditing | undefined;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.WatchCapabilityEvent.
|
||||
* Use `create(WatchCapabilityEventSchema)` to create a new message.
|
||||
*/
|
||||
export declare const WatchCapabilityEventSchema: GenMessage<WatchCapabilityEvent>;
|
||||
/**
|
||||
* @generated from message quixos.orch.GetWorkspaceRequest
|
||||
*/
|
||||
export type GetWorkspaceRequest = Message<"quixos.orch.GetWorkspaceRequest"> & {
|
||||
/**
|
||||
* Revision polling must not download the entire interface graph.
|
||||
*
|
||||
* @generated from field: bool include_interface_contracts = 1;
|
||||
*/
|
||||
includeInterfaceContracts: boolean;
|
||||
/**
|
||||
* @generated from field: bool include_query_contracts = 2;
|
||||
*/
|
||||
includeQueryContracts: boolean;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.GetWorkspaceRequest.
|
||||
* Use `create(GetWorkspaceRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const GetWorkspaceRequestSchema: GenMessage<GetWorkspaceRequest>;
|
||||
/**
|
||||
* @generated from message quixos.orch.GetWorkspaceResponse
|
||||
*/
|
||||
export type GetWorkspaceResponse = Message<"quixos.orch.GetWorkspaceResponse"> & {
|
||||
/**
|
||||
* @generated from field: string workspace_id = 1;
|
||||
*/
|
||||
workspaceId: string;
|
||||
/**
|
||||
* @generated from field: string workspace_revision_id = 2;
|
||||
*/
|
||||
workspaceRevisionId: string;
|
||||
/**
|
||||
* @generated from field: string source_root_commit = 3;
|
||||
*/
|
||||
sourceRootCommit: string;
|
||||
/**
|
||||
* Checked constructors whose wire input can be empty. The create panel uses
|
||||
* class factory conformances instead of this constructor inventory.
|
||||
*
|
||||
* @generated from field: repeated string empty_input_constructible_atom_ids = 4;
|
||||
*/
|
||||
emptyInputConstructibleAtomIds: string[];
|
||||
/**
|
||||
* @generated from field: repeated quixos.orch.CapabilityInputContract capability_inputs = 5;
|
||||
*/
|
||||
capabilityInputs: CapabilityInputContract[];
|
||||
/**
|
||||
* @generated from field: repeated quixos.orch.ConstructorInputContract constructor_inputs = 6;
|
||||
*/
|
||||
constructorInputs: ConstructorInputContract[];
|
||||
/**
|
||||
* Exact closed interface contracts used by checked presentation consumers.
|
||||
*
|
||||
* @generated from field: string interfaces_json = 7;
|
||||
*/
|
||||
interfacesJson: string;
|
||||
/**
|
||||
* @generated from field: repeated quixos.orch.ClassCapability class_capabilities = 8;
|
||||
*/
|
||||
classCapabilities: ClassCapability[];
|
||||
/**
|
||||
* @generated from field: repeated quixos.orch.QueryDescription queries = 9;
|
||||
*/
|
||||
queries: QueryDescription[];
|
||||
/**
|
||||
* @generated from field: uint32 active_query_executions = 10;
|
||||
*/
|
||||
activeQueryExecutions: number;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.GetWorkspaceResponse.
|
||||
* Use `create(GetWorkspaceResponseSchema)` to create a new message.
|
||||
*/
|
||||
export declare const GetWorkspaceResponseSchema: GenMessage<GetWorkspaceResponse>;
|
||||
/**
|
||||
* @generated from message quixos.orch.QueryDescription
|
||||
*/
|
||||
export type QueryDescription = Message<"quixos.orch.QueryDescription"> & {
|
||||
/**
|
||||
* @generated from field: string id = 1;
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* @generated from field: string name = 2;
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* @generated from field: string package_revision_id = 3;
|
||||
*/
|
||||
packageRevisionId: string;
|
||||
/**
|
||||
* @generated from field: string document = 4;
|
||||
*/
|
||||
document: string;
|
||||
/**
|
||||
* @generated from field: string schema = 5;
|
||||
*/
|
||||
schema: string;
|
||||
/**
|
||||
* @generated from field: repeated string source_files = 6;
|
||||
*/
|
||||
sourceFiles: string[];
|
||||
/**
|
||||
* @generated from field: string effects_json = 7;
|
||||
*/
|
||||
effectsJson: string;
|
||||
/**
|
||||
* @generated from field: camino.InstalledQuery plan = 8;
|
||||
*/
|
||||
plan?: InstalledQuery | undefined;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.QueryDescription.
|
||||
* Use `create(QueryDescriptionSchema)` to create a new message.
|
||||
*/
|
||||
export declare const QueryDescriptionSchema: GenMessage<QueryDescription>;
|
||||
/**
|
||||
* @generated from message quixos.orch.ClassCapability
|
||||
*/
|
||||
export type ClassCapability = Message<"quixos.orch.ClassCapability"> & {
|
||||
/**
|
||||
* @generated from field: string conformance_id = 1;
|
||||
*/
|
||||
conformanceId: string;
|
||||
/**
|
||||
* @generated from field: string atom_id = 2;
|
||||
*/
|
||||
atomId: string;
|
||||
/**
|
||||
* @generated from field: string interface_revision_id = 3;
|
||||
*/
|
||||
interfaceRevisionId: string;
|
||||
/**
|
||||
* @generated from field: string definition_id = 4;
|
||||
*/
|
||||
definitionId: string;
|
||||
/**
|
||||
* @generated from field: string operation_id = 5;
|
||||
*/
|
||||
operationId: string;
|
||||
/**
|
||||
* @generated from field: string input_type_json = 6;
|
||||
*/
|
||||
inputTypeJson: string;
|
||||
/**
|
||||
* @generated from field: string output_type_json = 7;
|
||||
*/
|
||||
outputTypeJson: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.ClassCapability.
|
||||
* Use `create(ClassCapabilitySchema)` to create a new message.
|
||||
*/
|
||||
export declare const ClassCapabilitySchema: GenMessage<ClassCapability>;
|
||||
/**
|
||||
* @generated from message quixos.orch.CapabilityInputContract
|
||||
*/
|
||||
export type CapabilityInputContract = Message<"quixos.orch.CapabilityInputContract"> & {
|
||||
/**
|
||||
* @generated from field: string interface_revision_id = 1;
|
||||
*/
|
||||
interfaceRevisionId: string;
|
||||
/**
|
||||
* @generated from field: string operation_id = 2;
|
||||
*/
|
||||
operationId: string;
|
||||
/**
|
||||
* @generated from field: string type_json = 3;
|
||||
*/
|
||||
typeJson: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.CapabilityInputContract.
|
||||
* Use `create(CapabilityInputContractSchema)` to create a new message.
|
||||
*/
|
||||
export declare const CapabilityInputContractSchema: GenMessage<CapabilityInputContract>;
|
||||
/**
|
||||
* @generated from message quixos.orch.ConstructorInputContract
|
||||
*/
|
||||
export type ConstructorInputContract = Message<"quixos.orch.ConstructorInputContract"> & {
|
||||
/**
|
||||
* @generated from field: string atom_id = 1;
|
||||
*/
|
||||
atomId: string;
|
||||
/**
|
||||
* @generated from field: string type_json = 2;
|
||||
*/
|
||||
typeJson: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.ConstructorInputContract.
|
||||
* Use `create(ConstructorInputContractSchema)` to create a new message.
|
||||
*/
|
||||
export declare const ConstructorInputContractSchema: GenMessage<ConstructorInputContract>;
|
||||
/**
|
||||
* @generated from message quixos.orch.ListActivationsRequest
|
||||
*/
|
||||
export type ListActivationsRequest = Message<"quixos.orch.ListActivationsRequest"> & {};
|
||||
/**
|
||||
* Describes the message quixos.orch.ListActivationsRequest.
|
||||
* Use `create(ListActivationsRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const ListActivationsRequestSchema: GenMessage<ListActivationsRequest>;
|
||||
/**
|
||||
* @generated from message quixos.orch.ListPackageDescriptorsRequest
|
||||
*/
|
||||
export type ListPackageDescriptorsRequest = Message<"quixos.orch.ListPackageDescriptorsRequest"> & {};
|
||||
/**
|
||||
* Describes the message quixos.orch.ListPackageDescriptorsRequest.
|
||||
* Use `create(ListPackageDescriptorsRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const ListPackageDescriptorsRequestSchema: GenMessage<ListPackageDescriptorsRequest>;
|
||||
/**
|
||||
* @generated from message quixos.orch.ListPackageDescriptorsResponse
|
||||
*/
|
||||
export type ListPackageDescriptorsResponse = Message<"quixos.orch.ListPackageDescriptorsResponse"> & {
|
||||
/**
|
||||
* @generated from field: repeated quixos.PackageDescriptor descriptors = 1;
|
||||
*/
|
||||
descriptors: PackageDescriptor[];
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.ListPackageDescriptorsResponse.
|
||||
* Use `create(ListPackageDescriptorsResponseSchema)` to create a new message.
|
||||
*/
|
||||
export declare const ListPackageDescriptorsResponseSchema: GenMessage<ListPackageDescriptorsResponse>;
|
||||
/**
|
||||
* @generated from message quixos.orch.ListPackageRuntimesRequest
|
||||
*/
|
||||
export type ListPackageRuntimesRequest = Message<"quixos.orch.ListPackageRuntimesRequest"> & {};
|
||||
/**
|
||||
* Describes the message quixos.orch.ListPackageRuntimesRequest.
|
||||
* Use `create(ListPackageRuntimesRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const ListPackageRuntimesRequestSchema: GenMessage<ListPackageRuntimesRequest>;
|
||||
/**
|
||||
* @generated from message quixos.orch.ListPackageRuntimesResponse
|
||||
*/
|
||||
export type ListPackageRuntimesResponse = Message<"quixos.orch.ListPackageRuntimesResponse"> & {
|
||||
/**
|
||||
* @generated from field: repeated quixos.orch.PackageRuntimeStatus runtimes = 1;
|
||||
*/
|
||||
runtimes: PackageRuntimeStatus[];
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.ListPackageRuntimesResponse.
|
||||
* Use `create(ListPackageRuntimesResponseSchema)` to create a new message.
|
||||
*/
|
||||
export declare const ListPackageRuntimesResponseSchema: GenMessage<ListPackageRuntimesResponse>;
|
||||
/**
|
||||
* @generated from message quixos.orch.ListActivationsResponse
|
||||
*/
|
||||
export type ListActivationsResponse = Message<"quixos.orch.ListActivationsResponse"> & {
|
||||
/**
|
||||
* @generated from field: repeated quixos.orch.Activation activations = 1;
|
||||
*/
|
||||
activations: Activation[];
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.ListActivationsResponse.
|
||||
* Use `create(ListActivationsResponseSchema)` to create a new message.
|
||||
*/
|
||||
export declare const ListActivationsResponseSchema: GenMessage<ListActivationsResponse>;
|
||||
/**
|
||||
* @generated from message quixos.orch.CloseActivationRequest
|
||||
*/
|
||||
export type CloseActivationRequest = Message<"quixos.orch.CloseActivationRequest"> & {
|
||||
/**
|
||||
* @generated from field: string activation_id = 1;
|
||||
*/
|
||||
activationId: string;
|
||||
/**
|
||||
* @generated from field: string reason = 2;
|
||||
*/
|
||||
reason: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.CloseActivationRequest.
|
||||
* Use `create(CloseActivationRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const CloseActivationRequestSchema: GenMessage<CloseActivationRequest>;
|
||||
/**
|
||||
* @generated from message quixos.orch.CloseActivationResponse
|
||||
*/
|
||||
export type CloseActivationResponse = Message<"quixos.orch.CloseActivationResponse"> & {
|
||||
/**
|
||||
* @generated from field: quixos.orch.Activation activation = 1;
|
||||
*/
|
||||
activation?: Activation | undefined;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.CloseActivationResponse.
|
||||
* Use `create(CloseActivationResponseSchema)` to create a new message.
|
||||
*/
|
||||
export declare const CloseActivationResponseSchema: GenMessage<CloseActivationResponse>;
|
||||
/**
|
||||
* @generated from message quixos.orch.Activation
|
||||
*/
|
||||
export type Activation = Message<"quixos.orch.Activation"> & {
|
||||
/**
|
||||
* @generated from field: string activation_id = 1;
|
||||
*/
|
||||
activationId: string;
|
||||
/**
|
||||
* @generated from field: quixos.PackageExportRef export = 2;
|
||||
*/
|
||||
export?: PackageExportRef | undefined;
|
||||
/**
|
||||
* @generated from field: string object_id = 3;
|
||||
*/
|
||||
objectId: string;
|
||||
/**
|
||||
* @generated from field: string state = 4;
|
||||
*/
|
||||
state: string;
|
||||
/**
|
||||
* @generated from field: uint32 demand = 5;
|
||||
*/
|
||||
demand: number;
|
||||
/**
|
||||
* @generated from field: string opened_at = 6;
|
||||
*/
|
||||
openedAt: string;
|
||||
/**
|
||||
* @generated from field: string last_used_at = 7;
|
||||
*/
|
||||
lastUsedAt: string;
|
||||
/**
|
||||
* @generated from field: string idle_deadline_at = 8;
|
||||
*/
|
||||
idleDeadlineAt: string;
|
||||
/**
|
||||
* @generated from field: string closed_at = 9;
|
||||
*/
|
||||
closedAt: string;
|
||||
/**
|
||||
* @generated from field: string close_reason = 10;
|
||||
*/
|
||||
closeReason: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.Activation.
|
||||
* Use `create(ActivationSchema)` to create a new message.
|
||||
*/
|
||||
export declare const ActivationSchema: GenMessage<Activation>;
|
||||
/**
|
||||
* @generated from message quixos.orch.PackageRuntimeStatus
|
||||
*/
|
||||
export type PackageRuntimeStatus = Message<"quixos.orch.PackageRuntimeStatus"> & {
|
||||
/**
|
||||
* @generated from field: string runtime_key = 1;
|
||||
*/
|
||||
runtimeKey: string;
|
||||
/**
|
||||
* @generated from field: string package_revision_id = 2;
|
||||
*/
|
||||
packageRevisionId: string;
|
||||
/**
|
||||
* @generated from field: string source_repository = 3;
|
||||
*/
|
||||
sourceRepository: string;
|
||||
/**
|
||||
* @generated from field: string source_commit = 4;
|
||||
*/
|
||||
sourceCommit: string;
|
||||
/**
|
||||
* @generated from field: string build_target = 5;
|
||||
*/
|
||||
buildTarget: string;
|
||||
/**
|
||||
* @generated from field: string server_path = 6;
|
||||
*/
|
||||
serverPath: string;
|
||||
/**
|
||||
* @generated from field: uint32 pid = 7;
|
||||
*/
|
||||
pid: number;
|
||||
/**
|
||||
* @generated from field: string state = 8;
|
||||
*/
|
||||
state: string;
|
||||
/**
|
||||
* @generated from field: string started_at = 9;
|
||||
*/
|
||||
startedAt: string;
|
||||
/**
|
||||
* @generated from field: string last_handshake_at = 10;
|
||||
*/
|
||||
lastHandshakeAt: string;
|
||||
/**
|
||||
* @generated from field: string runtime_protocol_version = 11;
|
||||
*/
|
||||
runtimeProtocolVersion: string;
|
||||
/**
|
||||
* @generated from field: uint32 advertised_export_count = 12;
|
||||
*/
|
||||
advertisedExportCount: number;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.orch.PackageRuntimeStatus.
|
||||
* Use `create(PackageRuntimeStatusSchema)` to create a new message.
|
||||
*/
|
||||
export declare const PackageRuntimeStatusSchema: GenMessage<PackageRuntimeStatus>;
|
||||
/**
|
||||
* @generated from service quixos.orch.OrchestratorRuntime
|
||||
*/
|
||||
export declare const OrchestratorRuntime: GenService<{
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.ExecuteQuery
|
||||
*/
|
||||
executeQuery: {
|
||||
methodKind: "unary";
|
||||
input: typeof QueryRequestSchema;
|
||||
output: typeof QueryResponseSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.WatchQuery
|
||||
*/
|
||||
watchQuery: {
|
||||
methodKind: "server_streaming";
|
||||
input: typeof QueryRequestSchema;
|
||||
output: typeof QueryEventSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.TryConform
|
||||
*/
|
||||
tryConform: {
|
||||
methodKind: "unary";
|
||||
input: typeof TryConformRequestSchema;
|
||||
output: typeof TryConformResponseSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.InvokeCapability
|
||||
*/
|
||||
invokeCapability: {
|
||||
methodKind: "unary";
|
||||
input: typeof InvokeCapabilityRequestSchema;
|
||||
output: typeof InvokeCapabilityResponseSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.EditCapabilityField
|
||||
*/
|
||||
editCapabilityField: {
|
||||
methodKind: "unary";
|
||||
input: typeof EditCapabilityFieldRequestSchema;
|
||||
output: typeof InvokeCapabilityResponseSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.InvokeClassCapability
|
||||
*/
|
||||
invokeClassCapability: {
|
||||
methodKind: "unary";
|
||||
input: typeof InvokeClassCapabilityRequestSchema;
|
||||
output: typeof InvokeCapabilityResponseSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.WatchCapability
|
||||
*/
|
||||
watchCapability: {
|
||||
methodKind: "server_streaming";
|
||||
input: typeof WatchCapabilityRequestSchema;
|
||||
output: typeof WatchCapabilityEventSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.ConstructObject
|
||||
*/
|
||||
constructObject: {
|
||||
methodKind: "unary";
|
||||
input: typeof ConstructObjectRequestSchema;
|
||||
output: typeof ConstructObjectResponseSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.ResolveOrConstructRelatedObject
|
||||
*/
|
||||
resolveOrConstructRelatedObject: {
|
||||
methodKind: "unary";
|
||||
input: typeof ResolveOrConstructRelatedObjectRequestSchema;
|
||||
output: typeof ResolveOrConstructRelatedObjectResponseSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.GetWorkspace
|
||||
*/
|
||||
getWorkspace: {
|
||||
methodKind: "unary";
|
||||
input: typeof GetWorkspaceRequestSchema;
|
||||
output: typeof GetWorkspaceResponseSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.ListPackageDescriptors
|
||||
*/
|
||||
listPackageDescriptors: {
|
||||
methodKind: "unary";
|
||||
input: typeof ListPackageDescriptorsRequestSchema;
|
||||
output: typeof ListPackageDescriptorsResponseSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.ListPackageRuntimes
|
||||
*/
|
||||
listPackageRuntimes: {
|
||||
methodKind: "unary";
|
||||
input: typeof ListPackageRuntimesRequestSchema;
|
||||
output: typeof ListPackageRuntimesResponseSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.ListActivations
|
||||
*/
|
||||
listActivations: {
|
||||
methodKind: "unary";
|
||||
input: typeof ListActivationsRequestSchema;
|
||||
output: typeof ListActivationsResponseSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.orch.OrchestratorRuntime.CloseActivation
|
||||
*/
|
||||
closeActivation: {
|
||||
methodKind: "unary";
|
||||
input: typeof CloseActivationRequestSchema;
|
||||
output: typeof CloseActivationResponseSchema;
|
||||
};
|
||||
}>;
|
||||
//# sourceMappingURL=orch_pb.d.ts.map
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+167
File diff suppressed because one or more lines are too long
Vendored
+51
@@ -0,0 +1,51 @@
|
||||
import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2";
|
||||
import type { Message } from "@bufbuild/protobuf";
|
||||
/**
|
||||
* Describes the file quixos/package.proto.
|
||||
*/
|
||||
export declare const file_quixos_package: GenFile;
|
||||
/**
|
||||
* @generated from message quixos.PackageDescriptor
|
||||
*/
|
||||
export type PackageDescriptor = Message<"quixos.PackageDescriptor"> & {
|
||||
/**
|
||||
* @generated from field: string package_id = 1;
|
||||
*/
|
||||
packageId: string;
|
||||
/**
|
||||
* @generated from field: string package_revision_id = 2;
|
||||
*/
|
||||
packageRevisionId: string;
|
||||
/**
|
||||
* @generated from field: string runtime_protocol_version = 3;
|
||||
*/
|
||||
runtimeProtocolVersion: string;
|
||||
/**
|
||||
* @generated from field: repeated quixos.RuntimeExport exports = 4;
|
||||
*/
|
||||
exports: RuntimeExport[];
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.PackageDescriptor.
|
||||
* Use `create(PackageDescriptorSchema)` to create a new message.
|
||||
*/
|
||||
export declare const PackageDescriptorSchema: GenMessage<PackageDescriptor>;
|
||||
/**
|
||||
* @generated from message quixos.RuntimeExport
|
||||
*/
|
||||
export type RuntimeExport = Message<"quixos.RuntimeExport"> & {
|
||||
/**
|
||||
* @generated from field: string export_id = 1;
|
||||
*/
|
||||
exportId: string;
|
||||
/**
|
||||
* @generated from field: string runtime_symbol = 2;
|
||||
*/
|
||||
runtimeSymbol: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.RuntimeExport.
|
||||
* Use `create(RuntimeExportSchema)` to create a new message.
|
||||
*/
|
||||
export declare const RuntimeExportSchema: GenMessage<RuntimeExport>;
|
||||
//# sourceMappingURL=package_pb.d.ts.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"package_pb.d.ts","sourceRoot":"","sources":["../../src/quixos/package_pb.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAExE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,OACgT,CAAC;AAEnV;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,0BAA0B,CAAC,GAAG;IACpE;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,sBAAsB,EAAE,MAAM,CAAC;IAE/B;;OAEG;IACH,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,UAAU,CAAC,iBAAiB,CAC7B,CAAC;AAEtC;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,sBAAsB,CAAC,GAAG;IAC5D;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,UAAU,CAAC,aAAa,CACrB,CAAC"}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js"
|
||||
// @generated from file quixos/package.proto (package quixos, syntax proto3)
|
||||
/* eslint-disable */
|
||||
import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
|
||||
/**
|
||||
* Describes the file quixos/package.proto.
|
||||
*/
|
||||
export const file_quixos_package = /*@__PURE__*/ fileDesc("ChRxdWl4b3MvcGFja2FnZS5wcm90bxIGcXVpeG9zIo4BChFQYWNrYWdlRGVzY3JpcHRvchISCgpwYWNrYWdlX2lkGAEgASgJEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYAiABKAkSIAoYcnVudGltZV9wcm90b2NvbF92ZXJzaW9uGAMgASgJEiYKB2V4cG9ydHMYBCADKAsyFS5xdWl4b3MuUnVudGltZUV4cG9ydCI6Cg1SdW50aW1lRXhwb3J0EhEKCWV4cG9ydF9pZBgBIAEoCRIWCg5ydW50aW1lX3N5bWJvbBgCIAEoCWIGcHJvdG8z");
|
||||
/**
|
||||
* Describes the message quixos.PackageDescriptor.
|
||||
* Use `create(PackageDescriptorSchema)` to create a new message.
|
||||
*/
|
||||
export const PackageDescriptorSchema = /*@__PURE__*/ messageDesc(file_quixos_package, 0);
|
||||
/**
|
||||
* Describes the message quixos.RuntimeExport.
|
||||
* Use `create(RuntimeExportSchema)` to create a new message.
|
||||
*/
|
||||
export const RuntimeExportSchema = /*@__PURE__*/ messageDesc(file_quixos_package, 1);
|
||||
Vendored
+155
@@ -0,0 +1,155 @@
|
||||
import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2";
|
||||
import type { Message } from "@bufbuild/protobuf";
|
||||
/**
|
||||
* Describes the file quixos/refs.proto.
|
||||
*/
|
||||
export declare const file_quixos_refs: GenFile;
|
||||
/**
|
||||
* @generated from message quixos.CapabilityRef
|
||||
*/
|
||||
export type CapabilityRef = Message<"quixos.CapabilityRef"> & {
|
||||
/**
|
||||
* @generated from field: string interface_revision_id = 1;
|
||||
*/
|
||||
interfaceRevisionId: string;
|
||||
/**
|
||||
* @generated from field: string operation_id = 2;
|
||||
*/
|
||||
operationId: string;
|
||||
/**
|
||||
* Optional fence for a view acquired through TryConform. Not an authority grant.
|
||||
*
|
||||
* @generated from field: quixos.ConformanceWitness conformance = 3;
|
||||
*/
|
||||
conformance?: ConformanceWitness | undefined;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.CapabilityRef.
|
||||
* Use `create(CapabilityRefSchema)` to create a new message.
|
||||
*/
|
||||
export declare const CapabilityRefSchema: GenMessage<CapabilityRef>;
|
||||
/**
|
||||
* @generated from message quixos.ConformanceWitness
|
||||
*/
|
||||
export type ConformanceWitness = Message<"quixos.ConformanceWitness"> & {
|
||||
/**
|
||||
* @generated from field: string object_id = 1;
|
||||
*/
|
||||
objectId: string;
|
||||
/**
|
||||
* @generated from field: string interface_revision_id = 2;
|
||||
*/
|
||||
interfaceRevisionId: string;
|
||||
/**
|
||||
* @generated from field: string conformance_id = 3;
|
||||
*/
|
||||
conformanceId: string;
|
||||
/**
|
||||
* @generated from field: string workspace_revision_id = 4;
|
||||
*/
|
||||
workspaceRevisionId: string;
|
||||
/**
|
||||
* @generated from field: string workspace_epoch = 5;
|
||||
*/
|
||||
workspaceEpoch: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.ConformanceWitness.
|
||||
* Use `create(ConformanceWitnessSchema)` to create a new message.
|
||||
*/
|
||||
export declare const ConformanceWitnessSchema: GenMessage<ConformanceWitness>;
|
||||
/**
|
||||
* @generated from message quixos.PackageExportRef
|
||||
*/
|
||||
export type PackageExportRef = Message<"quixos.PackageExportRef"> & {
|
||||
/**
|
||||
* @generated from field: string package_revision_id = 1;
|
||||
*/
|
||||
packageRevisionId: string;
|
||||
/**
|
||||
* @generated from field: string export_id = 2;
|
||||
*/
|
||||
exportId: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.PackageExportRef.
|
||||
* Use `create(PackageExportRefSchema)` to create a new message.
|
||||
*/
|
||||
export declare const PackageExportRefSchema: GenMessage<PackageExportRef>;
|
||||
/**
|
||||
* @generated from message quixos.InjectedDependency
|
||||
*/
|
||||
export type InjectedDependency = Message<"quixos.InjectedDependency"> & {
|
||||
/**
|
||||
* @generated from field: string port_id = 1;
|
||||
*/
|
||||
portId: string;
|
||||
/**
|
||||
* @generated from oneof quixos.InjectedDependency.binding
|
||||
*/
|
||||
binding: {
|
||||
/**
|
||||
* @generated from field: string state_slot_id = 2;
|
||||
*/
|
||||
value: string;
|
||||
case: "stateSlotId";
|
||||
} | {
|
||||
/**
|
||||
* @generated from field: quixos.EdgeDependency edge = 3;
|
||||
*/
|
||||
value: EdgeDependency;
|
||||
case: "edge";
|
||||
} | {
|
||||
/**
|
||||
* @generated from field: string interface_revision_id = 4;
|
||||
*/
|
||||
value: string;
|
||||
case: "interfaceRevisionId";
|
||||
} | {
|
||||
/**
|
||||
* @generated from field: string constructor_atom_id = 5;
|
||||
*/
|
||||
value: string;
|
||||
case: "constructorAtomId";
|
||||
} | {
|
||||
/**
|
||||
* @generated from field: string query_id = 7;
|
||||
*/
|
||||
value: string;
|
||||
case: "queryId";
|
||||
} | {
|
||||
case: undefined;
|
||||
value?: undefined;
|
||||
};
|
||||
/**
|
||||
* Defaults to the invocation receiver. A checked dependency traversal can
|
||||
* select a related object explicitly before the package runtime starts.
|
||||
*
|
||||
* @generated from field: string object_id = 6;
|
||||
*/
|
||||
objectId: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.InjectedDependency.
|
||||
* Use `create(InjectedDependencySchema)` to create a new message.
|
||||
*/
|
||||
export declare const InjectedDependencySchema: GenMessage<InjectedDependency>;
|
||||
/**
|
||||
* @generated from message quixos.EdgeDependency
|
||||
*/
|
||||
export type EdgeDependency = Message<"quixos.EdgeDependency"> & {
|
||||
/**
|
||||
* @generated from field: string edge_type_id = 1;
|
||||
*/
|
||||
edgeTypeId: string;
|
||||
/**
|
||||
* @generated from field: string projection_id = 2;
|
||||
*/
|
||||
projectionId: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.EdgeDependency.
|
||||
* Use `create(EdgeDependencySchema)` to create a new message.
|
||||
*/
|
||||
export declare const EdgeDependencySchema: GenMessage<EdgeDependency>;
|
||||
//# sourceMappingURL=refs_pb.d.ts.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"refs_pb.d.ts","sourceRoot":"","sources":["../../src/quixos/refs_pb.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAExE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,OAC21B,CAAC;AAE33B;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,sBAAsB,CAAC,GAAG;IAC5D;;OAEG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;CAC9C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,UAAU,CAAC,aAAa,CACxB,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,2BAA2B,CAAC,GAAG;IACtE;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,UAAU,CAAC,kBAAkB,CAClC,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,yBAAyB,CAAC,GAAG;IAClE;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,UAAU,CAAC,gBAAgB,CAC9B,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,2BAA2B,CAAC,GAAG;IACtE;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,EAAE;QACP;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,aAAa,CAAC;KACrB,GAAG;QACF;;WAEG;QACH,KAAK,EAAE,cAAc,CAAC;QACtB,IAAI,EAAE,MAAM,CAAC;KACd,GAAG;QACF;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,qBAAqB,CAAC;KAC7B,GAAG;QACF;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,mBAAmB,CAAC;KAC3B,GAAG;QACF;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,SAAS,CAAC;KACjB,GAAG;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC;IAE3C;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,UAAU,CAAC,kBAAkB,CAClC,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,uBAAuB,CAAC,GAAG;IAC9D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,CAAC,cAAc,CAC1B,CAAC"}
|
||||
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js"
|
||||
// @generated from file quixos/refs.proto (package quixos, syntax proto3)
|
||||
/* eslint-disable */
|
||||
import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
|
||||
/**
|
||||
* Describes the file quixos/refs.proto.
|
||||
*/
|
||||
export const file_quixos_refs = /*@__PURE__*/ fileDesc("ChFxdWl4b3MvcmVmcy5wcm90bxIGcXVpeG9zInUKDUNhcGFiaWxpdHlSZWYSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAEgASgJEhQKDG9wZXJhdGlvbl9pZBgCIAEoCRIvCgtjb25mb3JtYW5jZRgDIAEoCzIaLnF1aXhvcy5Db25mb3JtYW5jZVdpdG5lc3MilgEKEkNvbmZvcm1hbmNlV2l0bmVzcxIRCglvYmplY3RfaWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJEhYKDmNvbmZvcm1hbmNlX2lkGAMgASgJEh0KFXdvcmtzcGFjZV9yZXZpc2lvbl9pZBgEIAEoCRIXCg93b3Jrc3BhY2VfZXBvY2gYBSABKAkiQgoQUGFja2FnZUV4cG9ydFJlZhIbChNwYWNrYWdlX3JldmlzaW9uX2lkGAEgASgJEhEKCWV4cG9ydF9pZBgCIAEoCSLYAQoSSW5qZWN0ZWREZXBlbmRlbmN5Eg8KB3BvcnRfaWQYASABKAkSFwoNc3RhdGVfc2xvdF9pZBgCIAEoCUgAEiYKBGVkZ2UYAyABKAsyFi5xdWl4b3MuRWRnZURlcGVuZGVuY3lIABIfChVpbnRlcmZhY2VfcmV2aXNpb25faWQYBCABKAlIABIdChNjb25zdHJ1Y3Rvcl9hdG9tX2lkGAUgASgJSAASEgoIcXVlcnlfaWQYByABKAlIABIRCglvYmplY3RfaWQYBiABKAlCCQoHYmluZGluZyI9Cg5FZGdlRGVwZW5kZW5jeRIUCgxlZGdlX3R5cGVfaWQYASABKAkSFQoNcHJvamVjdGlvbl9pZBgCIAEoCWIGcHJvdG8z");
|
||||
/**
|
||||
* Describes the message quixos.CapabilityRef.
|
||||
* Use `create(CapabilityRefSchema)` to create a new message.
|
||||
*/
|
||||
export const CapabilityRefSchema = /*@__PURE__*/ messageDesc(file_quixos_refs, 0);
|
||||
/**
|
||||
* Describes the message quixos.ConformanceWitness.
|
||||
* Use `create(ConformanceWitnessSchema)` to create a new message.
|
||||
*/
|
||||
export const ConformanceWitnessSchema = /*@__PURE__*/ messageDesc(file_quixos_refs, 1);
|
||||
/**
|
||||
* Describes the message quixos.PackageExportRef.
|
||||
* Use `create(PackageExportRefSchema)` to create a new message.
|
||||
*/
|
||||
export const PackageExportRefSchema = /*@__PURE__*/ messageDesc(file_quixos_refs, 2);
|
||||
/**
|
||||
* Describes the message quixos.InjectedDependency.
|
||||
* Use `create(InjectedDependencySchema)` to create a new message.
|
||||
*/
|
||||
export const InjectedDependencySchema = /*@__PURE__*/ messageDesc(file_quixos_refs, 3);
|
||||
/**
|
||||
* Describes the message quixos.EdgeDependency.
|
||||
* Use `create(EdgeDependencySchema)` to create a new message.
|
||||
*/
|
||||
export const EdgeDependencySchema = /*@__PURE__*/ messageDesc(file_quixos_refs, 4);
|
||||
Vendored
+330
@@ -0,0 +1,330 @@
|
||||
import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2";
|
||||
import type { Value } from "../camino/api_pb.js";
|
||||
import type { InjectedDependency, PackageExportRef } from "./refs_pb.js";
|
||||
import type { Message } from "@bufbuild/protobuf";
|
||||
/**
|
||||
* Describes the file quixos/runtime.proto.
|
||||
*/
|
||||
export declare const file_quixos_runtime: GenFile;
|
||||
/**
|
||||
* @generated from message quixos.runtime.HandshakeRequest
|
||||
*/
|
||||
export type HandshakeRequest = Message<"quixos.runtime.HandshakeRequest"> & {
|
||||
/**
|
||||
* @generated from field: string orch_protocol_version = 1;
|
||||
*/
|
||||
orchProtocolVersion: string;
|
||||
/**
|
||||
* @generated from field: string nonce = 2;
|
||||
*/
|
||||
nonce: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.runtime.HandshakeRequest.
|
||||
* Use `create(HandshakeRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const HandshakeRequestSchema: GenMessage<HandshakeRequest>;
|
||||
/**
|
||||
* @generated from message quixos.runtime.HandshakeResponse
|
||||
*/
|
||||
export type HandshakeResponse = Message<"quixos.runtime.HandshakeResponse"> & {
|
||||
/**
|
||||
* @generated from field: string package_revision_id = 1;
|
||||
*/
|
||||
packageRevisionId: string;
|
||||
/**
|
||||
* @generated from field: string runtime_protocol_version = 2;
|
||||
*/
|
||||
runtimeProtocolVersion: string;
|
||||
/**
|
||||
* @generated from field: repeated string export_ids = 3;
|
||||
*/
|
||||
exportIds: string[];
|
||||
/**
|
||||
* @generated from field: string instance_id = 4;
|
||||
*/
|
||||
instanceId: string;
|
||||
/**
|
||||
* @generated from field: string authentication_proof = 5;
|
||||
*/
|
||||
authenticationProof: string;
|
||||
/**
|
||||
* @generated from field: repeated string capabilities = 6;
|
||||
*/
|
||||
capabilities: string[];
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.runtime.HandshakeResponse.
|
||||
* Use `create(HandshakeResponseSchema)` to create a new message.
|
||||
*/
|
||||
export declare const HandshakeResponseSchema: GenMessage<HandshakeResponse>;
|
||||
/**
|
||||
* @generated from message quixos.runtime.InvocationContext
|
||||
*/
|
||||
export type InvocationContext = Message<"quixos.runtime.InvocationContext"> & {
|
||||
/**
|
||||
* @generated from field: string workspace_epoch = 1;
|
||||
*/
|
||||
workspaceEpoch: string;
|
||||
/**
|
||||
* @generated from field: string instance_id = 2;
|
||||
*/
|
||||
instanceId: string;
|
||||
/**
|
||||
* @generated from field: string binding_digest = 3;
|
||||
*/
|
||||
bindingDigest: string;
|
||||
/**
|
||||
* @generated from field: string grant = 4;
|
||||
*/
|
||||
grant: string;
|
||||
/**
|
||||
* @generated from field: string session_id = 5;
|
||||
*/
|
||||
sessionId: string;
|
||||
/**
|
||||
* Host-selected owner; packages must not invent workspace-local ownership.
|
||||
*
|
||||
* @generated from field: string owner_conformance_id = 6;
|
||||
*/
|
||||
ownerConformanceId: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.runtime.InvocationContext.
|
||||
* Use `create(InvocationContextSchema)` to create a new message.
|
||||
*/
|
||||
export declare const InvocationContextSchema: GenMessage<InvocationContext>;
|
||||
/**
|
||||
* @generated from message quixos.runtime.InvocationControlRequest
|
||||
*/
|
||||
export type InvocationControlRequest = Message<"quixos.runtime.InvocationControlRequest"> & {
|
||||
/**
|
||||
* @generated from field: string invocation_id = 1;
|
||||
*/
|
||||
invocationId: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.runtime.InvocationControlRequest.
|
||||
* Use `create(InvocationControlRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const InvocationControlRequestSchema: GenMessage<InvocationControlRequest>;
|
||||
/**
|
||||
* @generated from message quixos.runtime.InvocationStatus
|
||||
*/
|
||||
export type InvocationStatus = Message<"quixos.runtime.InvocationStatus"> & {
|
||||
/**
|
||||
* @generated from field: string invocation_id = 1;
|
||||
*/
|
||||
invocationId: string;
|
||||
/**
|
||||
* unknown, running, cancellation-requested, completed, failed
|
||||
*
|
||||
* @generated from field: string state = 2;
|
||||
*/
|
||||
state: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.runtime.InvocationStatus.
|
||||
* Use `create(InvocationStatusSchema)` to create a new message.
|
||||
*/
|
||||
export declare const InvocationStatusSchema: GenMessage<InvocationStatus>;
|
||||
/**
|
||||
* @generated from message quixos.runtime.InvokeRequest
|
||||
*/
|
||||
export type InvokeRequest = Message<"quixos.runtime.InvokeRequest"> & {
|
||||
/**
|
||||
* @generated from field: string invocation_id = 1;
|
||||
*/
|
||||
invocationId: string;
|
||||
/**
|
||||
* @generated from field: quixos.PackageExportRef export = 2;
|
||||
*/
|
||||
export?: PackageExportRef | undefined;
|
||||
/**
|
||||
* @generated from field: string object_id = 3;
|
||||
*/
|
||||
objectId: string;
|
||||
/**
|
||||
* @generated from field: map<string, camino.Value> input = 4;
|
||||
*/
|
||||
input: {
|
||||
[key: string]: Value;
|
||||
};
|
||||
/**
|
||||
* @generated from field: repeated quixos.InjectedDependency dependencies = 5;
|
||||
*/
|
||||
dependencies: InjectedDependency[];
|
||||
/**
|
||||
* @generated from field: quixos.runtime.InvocationContext context = 6;
|
||||
*/
|
||||
context?: InvocationContext | undefined;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.runtime.InvokeRequest.
|
||||
* Use `create(InvokeRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const InvokeRequestSchema: GenMessage<InvokeRequest>;
|
||||
/**
|
||||
* @generated from message quixos.runtime.InvokeResponse
|
||||
*/
|
||||
export type InvokeResponse = Message<"quixos.runtime.InvokeResponse"> & {
|
||||
/**
|
||||
* @generated from field: bool ok = 1;
|
||||
*/
|
||||
ok: boolean;
|
||||
/**
|
||||
* @generated from field: camino.Value result = 2;
|
||||
*/
|
||||
result?: Value | undefined;
|
||||
/**
|
||||
* @generated from field: string error = 3;
|
||||
*/
|
||||
error: string;
|
||||
/**
|
||||
* @generated from field: repeated quixos.runtime.DerivedDependency dependencies = 4;
|
||||
*/
|
||||
dependencies: DerivedDependency[];
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.runtime.InvokeResponse.
|
||||
* Use `create(InvokeResponseSchema)` to create a new message.
|
||||
*/
|
||||
export declare const InvokeResponseSchema: GenMessage<InvokeResponse>;
|
||||
/**
|
||||
* @generated from message quixos.runtime.WatchRequest
|
||||
*/
|
||||
export type WatchRequest = Message<"quixos.runtime.WatchRequest"> & {
|
||||
/**
|
||||
* @generated from field: string invocation_id = 1;
|
||||
*/
|
||||
invocationId: string;
|
||||
/**
|
||||
* @generated from field: quixos.PackageExportRef export = 2;
|
||||
*/
|
||||
export?: PackageExportRef | undefined;
|
||||
/**
|
||||
* @generated from field: string object_id = 3;
|
||||
*/
|
||||
objectId: string;
|
||||
/**
|
||||
* @generated from field: map<string, camino.Value> input = 4;
|
||||
*/
|
||||
input: {
|
||||
[key: string]: Value;
|
||||
};
|
||||
/**
|
||||
* @generated from field: repeated quixos.InjectedDependency dependencies = 5;
|
||||
*/
|
||||
dependencies: InjectedDependency[];
|
||||
/**
|
||||
* @generated from field: quixos.runtime.InvocationContext context = 6;
|
||||
*/
|
||||
context?: InvocationContext | undefined;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.runtime.WatchRequest.
|
||||
* Use `create(WatchRequestSchema)` to create a new message.
|
||||
*/
|
||||
export declare const WatchRequestSchema: GenMessage<WatchRequest>;
|
||||
/**
|
||||
* @generated from message quixos.runtime.DerivedDependency
|
||||
*/
|
||||
export type DerivedDependency = Message<"quixos.runtime.DerivedDependency"> & {
|
||||
/**
|
||||
* @generated from field: string kind = 1;
|
||||
*/
|
||||
kind: string;
|
||||
/**
|
||||
* @generated from field: string object_id = 2;
|
||||
*/
|
||||
objectId: string;
|
||||
/**
|
||||
* @generated from field: string attachment_id = 3;
|
||||
*/
|
||||
attachmentId: string;
|
||||
/**
|
||||
* @generated from field: string projection_id = 4;
|
||||
*/
|
||||
projectionId: string;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.runtime.DerivedDependency.
|
||||
* Use `create(DerivedDependencySchema)` to create a new message.
|
||||
*/
|
||||
export declare const DerivedDependencySchema: GenMessage<DerivedDependency>;
|
||||
/**
|
||||
* @generated from message quixos.runtime.WatchEvent
|
||||
*/
|
||||
export type WatchEvent = Message<"quixos.runtime.WatchEvent"> & {
|
||||
/**
|
||||
* @generated from field: string watch_id = 1;
|
||||
*/
|
||||
watchId: string;
|
||||
/**
|
||||
* @generated from field: camino.Value value = 2;
|
||||
*/
|
||||
value?: Value | undefined;
|
||||
/**
|
||||
* @generated from field: repeated quixos.runtime.DerivedDependency dependencies = 3;
|
||||
*/
|
||||
dependencies: DerivedDependency[];
|
||||
/**
|
||||
* @generated from field: string error = 4;
|
||||
*/
|
||||
error: string;
|
||||
/**
|
||||
* @generated from field: bool initial = 5;
|
||||
*/
|
||||
initial: boolean;
|
||||
};
|
||||
/**
|
||||
* Describes the message quixos.runtime.WatchEvent.
|
||||
* Use `create(WatchEventSchema)` to create a new message.
|
||||
*/
|
||||
export declare const WatchEventSchema: GenMessage<WatchEvent>;
|
||||
/**
|
||||
* @generated from service quixos.runtime.PackageRuntime
|
||||
*/
|
||||
export declare const PackageRuntime: GenService<{
|
||||
/**
|
||||
* @generated from rpc quixos.runtime.PackageRuntime.Handshake
|
||||
*/
|
||||
handshake: {
|
||||
methodKind: "unary";
|
||||
input: typeof HandshakeRequestSchema;
|
||||
output: typeof HandshakeResponseSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.runtime.PackageRuntime.Invoke
|
||||
*/
|
||||
invoke: {
|
||||
methodKind: "unary";
|
||||
input: typeof InvokeRequestSchema;
|
||||
output: typeof InvokeResponseSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.runtime.PackageRuntime.Watch
|
||||
*/
|
||||
watch: {
|
||||
methodKind: "server_streaming";
|
||||
input: typeof WatchRequestSchema;
|
||||
output: typeof WatchEventSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.runtime.PackageRuntime.GetInvocationStatus
|
||||
*/
|
||||
getInvocationStatus: {
|
||||
methodKind: "unary";
|
||||
input: typeof InvocationControlRequestSchema;
|
||||
output: typeof InvocationStatusSchema;
|
||||
};
|
||||
/**
|
||||
* @generated from rpc quixos.runtime.PackageRuntime.CancelInvocation
|
||||
*/
|
||||
cancelInvocation: {
|
||||
methodKind: "unary";
|
||||
input: typeof InvocationControlRequestSchema;
|
||||
output: typeof InvocationStatusSchema;
|
||||
};
|
||||
}>;
|
||||
//# sourceMappingURL=runtime_pb.d.ts.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"runtime_pb.d.ts","sourceRoot":"","sources":["../../src/quixos/runtime_pb.ts"],"names":[],"mappings":"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"}
|
||||
Vendored
+64
@@ -0,0 +1,64 @@
|
||||
// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js"
|
||||
// @generated from file quixos/runtime.proto (package quixos.runtime, syntax proto3)
|
||||
/* eslint-disable */
|
||||
import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2";
|
||||
import { file_camino_api } from "../camino/api_pb.js";
|
||||
import { file_quixos_refs } from "./refs_pb.js";
|
||||
/**
|
||||
* Describes the file quixos/runtime.proto.
|
||||
*/
|
||||
export const file_quixos_runtime = /*@__PURE__*/ fileDesc("ChRxdWl4b3MvcnVudGltZS5wcm90bxIOcXVpeG9zLnJ1bnRpbWUiQAoQSGFuZHNoYWtlUmVxdWVzdBIdChVvcmNoX3Byb3RvY29sX3ZlcnNpb24YASABKAkSDQoFbm9uY2UYAiABKAkirwEKEUhhbmRzaGFrZVJlc3BvbnNlEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYASABKAkSIAoYcnVudGltZV9wcm90b2NvbF92ZXJzaW9uGAIgASgJEhIKCmV4cG9ydF9pZHMYAyADKAkSEwoLaW5zdGFuY2VfaWQYBCABKAkSHAoUYXV0aGVudGljYXRpb25fcHJvb2YYBSABKAkSFAoMY2FwYWJpbGl0aWVzGAYgAygJIpoBChFJbnZvY2F0aW9uQ29udGV4dBIXCg93b3Jrc3BhY2VfZXBvY2gYASABKAkSEwoLaW5zdGFuY2VfaWQYAiABKAkSFgoOYmluZGluZ19kaWdlc3QYAyABKAkSDQoFZ3JhbnQYBCABKAkSEgoKc2Vzc2lvbl9pZBgFIAEoCRIcChRvd25lcl9jb25mb3JtYW5jZV9pZBgGIAEoCSIxChhJbnZvY2F0aW9uQ29udHJvbFJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCSI4ChBJbnZvY2F0aW9uU3RhdHVzEhUKDWludm9jYXRpb25faWQYASABKAkSDQoFc3RhdGUYAiABKAkivwIKDUludm9rZVJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCRIoCgZleHBvcnQYAiABKAsyGC5xdWl4b3MuUGFja2FnZUV4cG9ydFJlZhIRCglvYmplY3RfaWQYAyABKAkSNwoFaW5wdXQYBCADKAsyKC5xdWl4b3MucnVudGltZS5JbnZva2VSZXF1ZXN0LklucHV0RW50cnkSMAoMZGVwZW5kZW5jaWVzGAUgAygLMhoucXVpeG9zLkluamVjdGVkRGVwZW5kZW5jeRIyCgdjb250ZXh0GAYgASgLMiEucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRleHQaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIoMBCg5JbnZva2VSZXNwb25zZRIKCgJvaxgBIAEoCBIdCgZyZXN1bHQYAiABKAsyDS5jYW1pbm8uVmFsdWUSDQoFZXJyb3IYAyABKAkSNwoMZGVwZW5kZW5jaWVzGAQgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kivQIKDFdhdGNoUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI2CgVpbnB1dBgEIAMoCzInLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdC5JbnB1dEVudHJ5EjAKDGRlcGVuZGVuY2llcxgFIAMoCzIaLnF1aXhvcy5JbmplY3RlZERlcGVuZGVuY3kSMgoHY29udGV4dBgGIAEoCzIhLnF1aXhvcy5ydW50aW1lLkludm9jYXRpb25Db250ZXh0GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJiChFEZXJpdmVkRGVwZW5kZW5jeRIMCgRraW5kGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRIVCg1hdHRhY2htZW50X2lkGAMgASgJEhUKDXByb2plY3Rpb25faWQYBCABKAkilQEKCldhdGNoRXZlbnQSEAoId2F0Y2hfaWQYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWUSNwoMZGVwZW5kZW5jaWVzGAMgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kSDQoFZXJyb3IYBCABKAkSDwoHaW5pdGlhbBgFIAEoCDKzAwoOUGFja2FnZVJ1bnRpbWUSUAoJSGFuZHNoYWtlEiAucXVpeG9zLnJ1bnRpbWUuSGFuZHNoYWtlUmVxdWVzdBohLnF1aXhvcy5ydW50aW1lLkhhbmRzaGFrZVJlc3BvbnNlEkcKBkludm9rZRIdLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QaHi5xdWl4b3MucnVudGltZS5JbnZva2VSZXNwb25zZRJDCgVXYXRjaBIcLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdBoaLnF1aXhvcy5ydW50aW1lLldhdGNoRXZlbnQwARJhChNHZXRJbnZvY2F0aW9uU3RhdHVzEigucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRyb2xSZXF1ZXN0GiAucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvblN0YXR1cxJeChBDYW5jZWxJbnZvY2F0aW9uEigucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRyb2xSZXF1ZXN0GiAucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvblN0YXR1c2IGcHJvdG8z", [file_camino_api, file_quixos_refs]);
|
||||
/**
|
||||
* Describes the message quixos.runtime.HandshakeRequest.
|
||||
* Use `create(HandshakeRequestSchema)` to create a new message.
|
||||
*/
|
||||
export const HandshakeRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 0);
|
||||
/**
|
||||
* Describes the message quixos.runtime.HandshakeResponse.
|
||||
* Use `create(HandshakeResponseSchema)` to create a new message.
|
||||
*/
|
||||
export const HandshakeResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 1);
|
||||
/**
|
||||
* Describes the message quixos.runtime.InvocationContext.
|
||||
* Use `create(InvocationContextSchema)` to create a new message.
|
||||
*/
|
||||
export const InvocationContextSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 2);
|
||||
/**
|
||||
* Describes the message quixos.runtime.InvocationControlRequest.
|
||||
* Use `create(InvocationControlRequestSchema)` to create a new message.
|
||||
*/
|
||||
export const InvocationControlRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 3);
|
||||
/**
|
||||
* Describes the message quixos.runtime.InvocationStatus.
|
||||
* Use `create(InvocationStatusSchema)` to create a new message.
|
||||
*/
|
||||
export const InvocationStatusSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 4);
|
||||
/**
|
||||
* Describes the message quixos.runtime.InvokeRequest.
|
||||
* Use `create(InvokeRequestSchema)` to create a new message.
|
||||
*/
|
||||
export const InvokeRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 5);
|
||||
/**
|
||||
* Describes the message quixos.runtime.InvokeResponse.
|
||||
* Use `create(InvokeResponseSchema)` to create a new message.
|
||||
*/
|
||||
export const InvokeResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 6);
|
||||
/**
|
||||
* Describes the message quixos.runtime.WatchRequest.
|
||||
* Use `create(WatchRequestSchema)` to create a new message.
|
||||
*/
|
||||
export const WatchRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 7);
|
||||
/**
|
||||
* Describes the message quixos.runtime.DerivedDependency.
|
||||
* Use `create(DerivedDependencySchema)` to create a new message.
|
||||
*/
|
||||
export const DerivedDependencySchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 8);
|
||||
/**
|
||||
* Describes the message quixos.runtime.WatchEvent.
|
||||
* Use `create(WatchEventSchema)` to create a new message.
|
||||
*/
|
||||
export const WatchEventSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 9);
|
||||
/**
|
||||
* @generated from service quixos.runtime.PackageRuntime
|
||||
*/
|
||||
export const PackageRuntime = /*@__PURE__*/ serviceDesc(file_quixos_runtime, 0);
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
declare const referenceBrand: unique symbol;
|
||||
export interface QxObjectRef<Identity extends string = string> {
|
||||
readonly [referenceBrand]: {
|
||||
readonly [K in Identity]: true;
|
||||
};
|
||||
equals(other: QxObjectRef<string>): boolean;
|
||||
}
|
||||
export declare const isObjectReference: (value: unknown) => value is QxObjectRef;
|
||||
/** Internal transport boundary; intentionally not exported from the SDK entry. */
|
||||
export declare const referenceFromWire: (id: string) => QxObjectRef;
|
||||
export declare const referenceToWire: (value: unknown) => string;
|
||||
export declare const assertReferenceFree: (value: unknown, seen?: Set<object>) => void;
|
||||
export {};
|
||||
//# sourceMappingURL=references.d.ts.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"references.d.ts","sourceRoot":"","sources":["../src/references.ts"],"names":[],"mappings":"AAGA,OAAO,CAAC,MAAM,cAAc,EAAE,OAAO,MAAM,CAAC;AAC5C,MAAM,WAAW,WAAW,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM;IAC3D,QAAQ,CAAC,CAAC,cAAc,CAAC,EAAE;QAAE,QAAQ,EAAE,CAAC,IAAI,QAAQ,GAAG,IAAI;KAAE,CAAC;IAC9D,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;CAC7C;AAmBD,eAAO,MAAM,iBAAiB,UAAW,OAAO,KAAG,KAAK,IAAI,WACU,CAAC;AAEvE,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,OAAQ,MAAM,KAAG,WAG9C,CAAC;AACF,eAAO,MAAM,eAAe,UAAW,OAAO,KAAG,MAGhD,CAAC;AACF,eAAO,MAAM,mBAAmB,UAAW,OAAO,yBAA6B,IAU9E,CAAC"}
|
||||
Vendored
+46
@@ -0,0 +1,46 @@
|
||||
/** Opaque runtime identity. The wire codec, never ordinary package state, owns
|
||||
* the raw ID. These handles do not themselves confer authority or a lease. */
|
||||
const identities = new WeakMap();
|
||||
class Reference {
|
||||
constructor(id) {
|
||||
identities.set(this, id);
|
||||
Object.freeze(this);
|
||||
}
|
||||
equals(other) {
|
||||
return isObjectReference(other) && identities.get(this) === identities.get(other);
|
||||
}
|
||||
toJSON() {
|
||||
throw new Error("Object references cannot be serialized into ordinary data");
|
||||
}
|
||||
toString() {
|
||||
throw new Error("Object references cannot be coerced to strings");
|
||||
}
|
||||
[Symbol.toPrimitive]() {
|
||||
throw new Error("Object references cannot be coerced to scalar values");
|
||||
}
|
||||
}
|
||||
export const isObjectReference = (value) => typeof value === "object" && value !== null && identities.has(value);
|
||||
/** Internal transport boundary; intentionally not exported from the SDK entry. */
|
||||
export const referenceFromWire = (id) => {
|
||||
if (typeof id !== "string" || !id)
|
||||
throw new Error("Missing object reference identity");
|
||||
return new Reference(id);
|
||||
};
|
||||
export const referenceToWire = (value) => {
|
||||
if (!isObjectReference(value))
|
||||
throw new Error("Expected an opaque object reference, not a raw ID");
|
||||
return identities.get(value);
|
||||
};
|
||||
export const assertReferenceFree = (value, seen = new Set()) => {
|
||||
if (!value || typeof value !== "object")
|
||||
return;
|
||||
if (isObjectReference(value))
|
||||
throw new Error("Managed references belong in declared RPC references or graph relationships, not ordinary state/messages");
|
||||
if (seen.has(value))
|
||||
throw new Error("Cyclic ordinary data");
|
||||
seen.add(value);
|
||||
if (!(value instanceof Uint8Array))
|
||||
for (const child of Object.values(value))
|
||||
assertReferenceFree(child, seen);
|
||||
seen.delete(value);
|
||||
};
|
||||
Vendored
+30
@@ -0,0 +1,30 @@
|
||||
import type { QxObjectRef } from "./references.js";
|
||||
import type { RelationshipCollection, RelationshipEntry } from "./index.js";
|
||||
type Key = string | boolean | bigint;
|
||||
type Port<T extends QxObjectRef> = {
|
||||
collection(): Promise<RelationshipCollection<T>>;
|
||||
replace(entries: RelationshipEntry<T>[], expectedRevision: bigint): Promise<RelationshipCollection<T>>;
|
||||
};
|
||||
/** Helpers never retry a failed CAS or silently overwrite concurrent edits. */
|
||||
export declare const relationshipMap: <T extends QxObjectRef, K extends Key = Key>(port: Port<T>) => {
|
||||
read: () => Promise<RelationshipCollection<T>>;
|
||||
get(key: K): Promise<{
|
||||
revision: bigint;
|
||||
value: T | undefined;
|
||||
}>;
|
||||
set(key: K, target: T, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
|
||||
delete(key: K, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
|
||||
};
|
||||
export declare const relationshipList: <T extends QxObjectRef>(port: Port<T>) => {
|
||||
read: () => Promise<RelationshipCollection<T>>;
|
||||
insert(index: number, target: T, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
|
||||
move(edgeId: string, index: number, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
|
||||
delete(edgeId: string, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
|
||||
};
|
||||
export declare const relationshipSet: <T extends QxObjectRef>(port: Port<T>) => {
|
||||
read: () => Promise<RelationshipCollection<T>>;
|
||||
add(target: T, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
|
||||
delete(target: T, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
|
||||
};
|
||||
export {};
|
||||
//# sourceMappingURL=relationships.d.ts.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"relationships.d.ts","sourceRoot":"","sources":["../src/relationships.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC5E,KAAK,GAAG,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AACrC,KAAK,IAAI,CAAC,CAAC,SAAS,WAAW,IAAI;IACjC,UAAU,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,OAAO,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;CACxG,CAAC;AAMF,+EAA+E;AAC/E,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,WAAW,EAAE,CAAC,SAAS,GAAG,GAAG,GAAG,QAAQ,IAAI,CAAC,CAAC,CAAC;IACvF,IAAI;IACE,GAAG,MAAM,CAAC;;;;IAIV,GAAG,MAAM,CAAC,UAAU,CAAC,oBAAoB,MAAM;IAO/C,MAAM,MAAM,CAAC,oBAAoB,MAAM;CAO7C,CAAC;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,WAAW,QAAQ,IAAI,CAAC,CAAC,CAAC;IACnE,IAAI;IACE,MAAM,QAAQ,MAAM,UAAU,CAAC,oBAAoB,MAAM;IAOzD,IAAI,SAAS,MAAM,SAAS,MAAM,oBAAoB,MAAM;IAS5D,MAAM,SAAS,MAAM,oBAAoB,MAAM;CAQrD,CAAC;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,WAAW,QAAQ,IAAI,CAAC,CAAC,CAAC;IAClE,IAAI;IACE,GAAG,SAAS,CAAC,oBAAoB,MAAM;IAKvC,MAAM,SAAS,CAAC,oBAAoB,MAAM;CAOhD,CAAC"}
|
||||
Vendored
+63
@@ -0,0 +1,63 @@
|
||||
const checked = async (port, revision) => {
|
||||
const snapshot = await port.collection();
|
||||
if (snapshot.revision !== revision)
|
||||
throw new Error("STALE_COLLECTION_REVISION");
|
||||
return snapshot;
|
||||
};
|
||||
/** Helpers never retry a failed CAS or silently overwrite concurrent edits. */
|
||||
export const relationshipMap = (port) => ({
|
||||
read: () => port.collection(),
|
||||
async get(key) {
|
||||
const snapshot = await port.collection();
|
||||
return { revision: snapshot.revision, value: snapshot.entries.find((entry) => entry.key === key)?.target };
|
||||
},
|
||||
async set(key, target, expectedRevision) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
const entries = snapshot.entries.filter((entry) => entry.key !== key);
|
||||
const existing = snapshot.entries.find((entry) => entry.key === key && entry.target.equals(target));
|
||||
entries.push(existing ?? { key, target });
|
||||
return port.replace(entries, expectedRevision);
|
||||
},
|
||||
async delete(key, expectedRevision) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
return port.replace(snapshot.entries.filter((entry) => entry.key !== key), expectedRevision);
|
||||
},
|
||||
});
|
||||
export const relationshipList = (port) => ({
|
||||
read: () => port.collection(),
|
||||
async insert(index, target, expectedRevision) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
if (!Number.isSafeInteger(index) || index < 0 || index > snapshot.entries.length)
|
||||
throw new Error("List index out of bounds");
|
||||
snapshot.entries.splice(index, 0, { target });
|
||||
return port.replace(snapshot.entries, expectedRevision);
|
||||
},
|
||||
async move(edgeId, index, expectedRevision) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
const prior = snapshot.entries.findIndex((entry) => entry.edgeId === edgeId);
|
||||
if (prior < 0 || !Number.isSafeInteger(index) || index < 0 || index >= snapshot.entries.length)
|
||||
throw new Error("Unknown list entry or invalid index");
|
||||
const [entry] = snapshot.entries.splice(prior, 1);
|
||||
snapshot.entries.splice(index, 0, entry);
|
||||
return port.replace(snapshot.entries, expectedRevision);
|
||||
},
|
||||
async delete(edgeId, expectedRevision) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
if (!snapshot.entries.some((entry) => entry.edgeId === edgeId))
|
||||
throw new Error("Unknown list entry");
|
||||
return port.replace(snapshot.entries.filter((entry) => entry.edgeId !== edgeId), expectedRevision);
|
||||
},
|
||||
});
|
||||
export const relationshipSet = (port) => ({
|
||||
read: () => port.collection(),
|
||||
async add(target, expectedRevision) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
if (snapshot.entries.some((entry) => entry.target.equals(target)))
|
||||
return snapshot;
|
||||
return port.replace([...snapshot.entries, { target }], expectedRevision);
|
||||
},
|
||||
async delete(target, expectedRevision) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
return port.replace(snapshot.entries.filter((entry) => !entry.target.equals(target)), expectedRevision);
|
||||
},
|
||||
});
|
||||
Generated
+14
-14
@@ -74,17 +74,17 @@
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1783890039,
|
||||
"narHash": "sha256-5R7WV6KCSYwQ9SmjmIvRovPjG551icfYa7XHBz68sYA=",
|
||||
"ref": "refs/heads/exported",
|
||||
"rev": "a287ab31330222d7dcd517c640a5de89f48bc4d0",
|
||||
"revCount": 4,
|
||||
"lastModified": 1789699975,
|
||||
"narHash": "sha256-OG2ebD1FAzPPXjgFcH0Bd+DR/pS2YL3zlaIQ9XUCpJg=",
|
||||
"ref": "refs/tags/quixos-reachability/93c8cae1e651fa6a98ab5aa26e9ed2696c0bfd05",
|
||||
"rev": "93c8cae1e651fa6a98ab5aa26e9ed2696c0bfd05",
|
||||
"revCount": 88,
|
||||
"type": "git",
|
||||
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-protocol.git"
|
||||
},
|
||||
"original": {
|
||||
"ref": "refs/heads/exported",
|
||||
"rev": "a287ab31330222d7dcd517c640a5de89f48bc4d0",
|
||||
"ref": "refs/tags/quixos-reachability/93c8cae1e651fa6a98ab5aa26e9ed2696c0bfd05",
|
||||
"rev": "93c8cae1e651fa6a98ab5aa26e9ed2696c0bfd05",
|
||||
"type": "git",
|
||||
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-protocol.git"
|
||||
}
|
||||
@@ -92,17 +92,17 @@
|
||||
"quixosNixHelpers": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1783886666,
|
||||
"narHash": "sha256-y52TlYwH9RBzzyhpkY/eB21t85BE84idpsg8618MIHg=",
|
||||
"ref": "refs/heads/exported",
|
||||
"rev": "81e55657d9ce0ba092cffd69ee15179ea02aa598",
|
||||
"revCount": 2,
|
||||
"lastModified": 1788574090,
|
||||
"narHash": "sha256-bSgc0LS2Ub01fnE14VqazdZzFuVPl4sykmA2d1l4kDs=",
|
||||
"ref": "refs/tags/quixos-reachability/7177130c0365f2fa58ea4877366e1c5d17db4c01",
|
||||
"rev": "7177130c0365f2fa58ea4877366e1c5d17db4c01",
|
||||
"revCount": 4,
|
||||
"type": "git",
|
||||
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git"
|
||||
},
|
||||
"original": {
|
||||
"ref": "refs/heads/exported",
|
||||
"rev": "81e55657d9ce0ba092cffd69ee15179ea02aa598",
|
||||
"ref": "refs/tags/quixos-reachability/7177130c0365f2fa58ea4877366e1c5d17db4c01",
|
||||
"rev": "7177130c0365f2fa58ea4877366e1c5d17db4c01",
|
||||
"type": "git",
|
||||
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git"
|
||||
}
|
||||
|
||||
@@ -4,18 +4,23 @@
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
quixos-protocol.url = "git+https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-protocol.git?ref=refs/heads/exported&rev=a287ab31330222d7dcd517c640a5de89f48bc4d0";
|
||||
quixos-protocol.url = "git+https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-protocol.git?ref=refs/tags/quixos-reachability/93c8cae1e651fa6a98ab5aa26e9ed2696c0bfd05&rev=93c8cae1e651fa6a98ab5aa26e9ed2696c0bfd05";
|
||||
quixosNixHelpers = {
|
||||
url = "git+https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git?ref=refs/heads/exported&rev=81e55657d9ce0ba092cffd69ee15179ea02aa598";
|
||||
url = "git+https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git?ref=refs/tags/quixos-reachability/7177130c0365f2fa58ea4877366e1c5d17db4c01&rev=7177130c0365f2fa58ea4877366e1c5d17db4c01";
|
||||
flake = false;
|
||||
};
|
||||
};
|
||||
|
||||
outputs = inputs@{ nixpkgs, flake-utils, quixosNixHelpers, ... }:
|
||||
outputs =
|
||||
inputs@{
|
||||
nixpkgs,
|
||||
flake-utils,
|
||||
quixosNixHelpers,
|
||||
...
|
||||
}:
|
||||
let
|
||||
quixosHelpers = import "${quixosNixHelpers}/quixos-package-helpers.nix";
|
||||
in
|
||||
quixosHelpers.mkCaminoTsYarnNixifyFlake {
|
||||
packageOutputs = quixosHelpers.mkCaminoTsYarnNixifyFlake {
|
||||
inherit inputs nixpkgs flake-utils;
|
||||
packageRoot = ./.;
|
||||
sourceName = "quixos-camino-package-runtime-source";
|
||||
@@ -23,14 +28,48 @@
|
||||
nativeBuildInputs = { pkgs, ... }: [
|
||||
pkgs.protobuf
|
||||
];
|
||||
buildEnv = { inputs, pkgs, system }: {
|
||||
QUIXOS_PROTO_PATH = "${pkgs.protobuf}/include:${inputs.quixos-protocol.packages.${system}.default}/proto";
|
||||
buildEnv =
|
||||
{
|
||||
inputs,
|
||||
pkgs,
|
||||
system,
|
||||
}:
|
||||
{
|
||||
QUIXOS_PROTO_PATH = "${pkgs.protobuf}/include:${
|
||||
inputs.quixos-protocol.packages.${system}.default
|
||||
}/proto";
|
||||
};
|
||||
devShellPackages = { pkgs, ... }: [
|
||||
pkgs.protobuf
|
||||
];
|
||||
devShellHook = { inputs, pkgs, system, ... }: ''
|
||||
export QUIXOS_PROTO_PATH="${pkgs.protobuf}/include:${inputs.quixos-protocol.packages.${system}.default}/proto''${QUIXOS_PROTO_PATH:+:$QUIXOS_PROTO_PATH}"
|
||||
devShellHook =
|
||||
{
|
||||
inputs,
|
||||
pkgs,
|
||||
system,
|
||||
...
|
||||
}:
|
||||
''
|
||||
export QUIXOS_PROTO_PATH="${pkgs.protobuf}/include:${
|
||||
inputs.quixos-protocol.packages.${system}.default
|
||||
}/proto''${QUIXOS_PROTO_PATH:+:$QUIXOS_PROTO_PATH}"
|
||||
'';
|
||||
};
|
||||
in
|
||||
packageOutputs
|
||||
// flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
builtPackage = packageOutputs.packages.${system}.default;
|
||||
in
|
||||
{
|
||||
checks.dist-current = pkgs.runCommand "camino-package-runtime-dist-current" { } ''
|
||||
diff --recursive --unified \
|
||||
${./dist} \
|
||||
${builtPackage}/libexec/-quixos-camino-package-runtime/dist
|
||||
touch "$out"
|
||||
'';
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
+10
-7
@@ -2,18 +2,21 @@
|
||||
"name": "@quixos/camino-package-runtime",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"packageManager": "yarn@4.14.1",
|
||||
"packageManager": "yarn@4.18.0",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./src/index.ts",
|
||||
"default": "./src/index.ts"
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn generate && tsc -p tsconfig.json",
|
||||
"generate": "rm -rf src/camino src/quixos && protoc --es_out=src --es_opt=target=ts,import_extension=js --proto_path=$QUIXOS_PROTO_PATH quixos/refs.proto quixos/runtime.proto camino/schema.proto camino/api.proto",
|
||||
"typecheck": "yarn generate && tsc --noEmit"
|
||||
"build": "rm -rf dist && yarn generate && tsc -p tsconfig.json",
|
||||
"generate": "rm -rf src/camino src/quixos && protoc --experimental_allow_proto3_optional --es_out=src --es_opt=target=ts,import_extension=js --proto_path=$QUIXOS_PROTO_PATH quixos/refs.proto quixos/runtime.proto quixos/orch.proto quixos/package.proto camino/schema.proto camino/api.proto",
|
||||
"typecheck": "yarn generate && tsc --noEmit",
|
||||
"test": "yarn build && node --test test/*.test.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bufbuild/protobuf": "^2.12.1",
|
||||
@@ -23,6 +26,6 @@
|
||||
"devDependencies": {
|
||||
"@bufbuild/protoc-gen-es": "^2.12.1",
|
||||
"@types/node": "^24",
|
||||
"typescript": "^5.9.3"
|
||||
"typescript": "^7.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
+325
@@ -0,0 +1,325 @@
|
||||
import { create } from "@bufbuild/protobuf";
|
||||
import { ValueSchema, ObjectValueSchema, type Value } from "./camino/api_pb.js";
|
||||
import {
|
||||
derived,
|
||||
jsToProtoValue,
|
||||
liveValue,
|
||||
protoValueToJs,
|
||||
type RuntimeContext,
|
||||
type RuntimeHandler,
|
||||
type DerivedHandler,
|
||||
} from "./index.js";
|
||||
|
||||
export type { QxObjectRef } from "./references.js";
|
||||
import { assertReferenceFree, referenceToWire } from "./references.js";
|
||||
import { decodeQuerySnapshot } from "./queries.js";
|
||||
declare const watchBrand: unique symbol;
|
||||
export type QxWatchHandle = string & { readonly [watchBrand]: true };
|
||||
export type MessageBinding<T> = { encode(value: T): Value; decode(value: Value): T };
|
||||
export type QxLiveValue = ReturnType<typeof liveValue>;
|
||||
export type BindingValue<B> = B extends MessageBinding<infer T> ? T : never;
|
||||
export type QxHandler<C, O> = (context: C) => O | Promise<O>;
|
||||
export type QxDerived<C, O> = { kind: "derived"; get: QxHandler<C, O> };
|
||||
export type QxSession<C> = { id: string; run<T>(work: (context: C) => Promise<T>): Promise<T>; close(): Promise<void> };
|
||||
export type QxContextLifecycle<C> = { signal?: AbortSignal; openSession?: () => Promise<QxSession<C>> };
|
||||
declare const contractView: unique symbol;
|
||||
/** Generated exact closed contract. A descriptor is type evidence, never authority. */
|
||||
export type QxInterfaceContract<View> = {
|
||||
readonly interfaceRevisionId: string;
|
||||
readonly operations: Record<string, QxOperationSpec>;
|
||||
readonly [contractView]: (value: View) => View;
|
||||
};
|
||||
export const defineQxInterfaceContract = <View>(
|
||||
interfaceRevisionId: string,
|
||||
operations: Record<string, QxOperationSpec>,
|
||||
): QxInterfaceContract<View> => Object.freeze({ interfaceRevisionId, operations }) as QxInterfaceContract<View>;
|
||||
export type QxConformer = {
|
||||
tryConform<View>(
|
||||
object: import("./references.js").QxObjectRef,
|
||||
contract: QxInterfaceContract<View>,
|
||||
): Promise<View | undefined>;
|
||||
};
|
||||
export const qxDerived = <C, O>(get: QxHandler<C, O>): QxDerived<C, O> => ({ kind: "derived", get });
|
||||
|
||||
/** Versioned binding ABI. This mirrors the language-neutral value IR. */
|
||||
export type QxValueType =
|
||||
| { kind: "builtin"; name: "unit" | "watch-handle" }
|
||||
| { kind: "scalar"; name: string }
|
||||
| { kind: "message"; descriptorId: string }
|
||||
| { kind: "record"; fields: Record<string, QxValueType> }
|
||||
| { kind: "object-ref"; expectation: unknown }
|
||||
| { kind: "optional" | "list"; value: QxValueType };
|
||||
export type QxOperationSpec = { id: string; inputType: QxValueType; outputType: QxValueType };
|
||||
export type QxPortSpec =
|
||||
| { kind: "query"; id: string; definitionDigest: string; variables: QxValueType; output: QxValueType; watch: boolean }
|
||||
| { kind: "state"; id: string; valueType: QxValueType; primitives: string[] }
|
||||
| { kind: "edge"; id: string; primitives: string[] }
|
||||
| { kind: "interface"; id: string; interfaceRevisionId: string; operations: Record<string, QxOperationSpec> }
|
||||
| { kind: "constructor"; id: string; inputType: QxValueType };
|
||||
export type QxHandlerSpec = {
|
||||
receiver?: "none";
|
||||
inputType: QxValueType;
|
||||
outputType: QxValueType;
|
||||
eventType?: QxValueType;
|
||||
ports: Record<string, QxPortSpec>;
|
||||
};
|
||||
export type QxMessages = Record<string, MessageBinding<any>>;
|
||||
|
||||
const bindInterfaceView = (
|
||||
target: import("./index.js").InterfacePort,
|
||||
contract: QxInterfaceContract<unknown>,
|
||||
messages: QxMessages,
|
||||
) => ({
|
||||
objectId: target.objectId,
|
||||
contract,
|
||||
live: Object.fromEntries(
|
||||
Object.entries(contract.operations).map(([name, operation]) => [
|
||||
name,
|
||||
(input: unknown) => target.live(operation.id, inputFields(operation.inputType, input, messages)),
|
||||
]),
|
||||
),
|
||||
...Object.fromEntries(
|
||||
Object.entries(contract.operations).map(([name, operation]) => [
|
||||
name,
|
||||
async (input: unknown) =>
|
||||
decodeQxValue(
|
||||
operation.outputType,
|
||||
(await target.live(operation.id, inputFields(operation.inputType, input, messages))).$quixosValue,
|
||||
messages,
|
||||
),
|
||||
]),
|
||||
),
|
||||
});
|
||||
|
||||
// Conversion belongs at the binding boundary. It does not add orchestrator validation.
|
||||
export const decodeQxValue = (type: QxValueType, value: Value | undefined, messages: QxMessages): any => {
|
||||
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 (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 === "list") {
|
||||
if (value.kind.case !== "listValue") throw new Error("Expected QX list");
|
||||
return value.kind.value.values.map((entry) => decodeQxValue(type.value, entry, messages));
|
||||
}
|
||||
if (type.kind === "message") {
|
||||
assertReferenceFree(protoValueToJs(value));
|
||||
const decoded = requireMessage(messages, type.descriptorId).decode(value);
|
||||
assertReferenceFree(decoded);
|
||||
return decoded;
|
||||
}
|
||||
if (type.kind === "object-ref") {
|
||||
if (value.kind.case !== "refValue") throw new Error("Expected a declared RPC object reference");
|
||||
return protoValueToJs(value);
|
||||
}
|
||||
if (value.kind.case === "refValue") throw new Error("Reference supplied to a non-reference value");
|
||||
if (type.kind === "scalar") {
|
||||
if (type.name === "int64" || type.name === "uint64") {
|
||||
if (value.kind.case !== "integerValue") throw new Error("Expected QX integer");
|
||||
return BigInt(value.kind.value);
|
||||
}
|
||||
if (type.name === "bytes") {
|
||||
if (value.kind.case !== "bytesValue") throw new Error("Expected QX bytes");
|
||||
return value.kind.value;
|
||||
}
|
||||
}
|
||||
return protoValueToJs(value);
|
||||
};
|
||||
|
||||
const requireMessage = (messages: QxMessages, id: string) => {
|
||||
const binding = messages[id];
|
||||
if (!binding) throw new Error(`Missing message binding ${id}`);
|
||||
return binding;
|
||||
};
|
||||
export const encodeQxValue = (type: QxValueType, value: any, messages: QxMessages): Value => {
|
||||
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 === "list")
|
||||
return jsToProtoValue(value.map((entry: unknown) => liveValue(encodeQxValue(type.value, entry, messages))));
|
||||
if (type.kind === "object-ref") {
|
||||
referenceToWire(value);
|
||||
return jsToProtoValue(value);
|
||||
}
|
||||
assertReferenceFree(value);
|
||||
if (type.kind === "message") {
|
||||
const encoded = requireMessage(messages, type.descriptorId).encode(value);
|
||||
assertReferenceFree(protoValueToJs(encoded));
|
||||
return encoded;
|
||||
}
|
||||
return jsToProtoValue(value);
|
||||
};
|
||||
|
||||
const inputValue = (context: RuntimeContext, type: QxValueType) => {
|
||||
if (type.kind === "message" || type.kind === "record")
|
||||
return create(ValueSchema, {
|
||||
kind: { case: "objectValue", value: create(ObjectValueSchema, { fields: context.inputProto }) },
|
||||
});
|
||||
return context.inputProto.value;
|
||||
};
|
||||
const inputFields = (type: QxValueType, value: unknown, messages: QxMessages): Record<string, unknown> => {
|
||||
if (type.kind === "builtin" && type.name === "unit") return {};
|
||||
const encoded = encodeQxValue(type, value, messages);
|
||||
if (type.kind === "message" || type.kind === "record") {
|
||||
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 { value: liveValue(encoded) };
|
||||
};
|
||||
|
||||
/** The sole unchecked cast connects generated contracts to the dynamic RPC runtime. */
|
||||
export const bindQxHandler = <C, O>(
|
||||
spec: QxHandlerSpec,
|
||||
handler: QxHandler<C, O> | QxDerived<C, O>,
|
||||
messages: QxMessages,
|
||||
): RuntimeHandler | DerivedHandler => {
|
||||
const bindContext = (raw: RuntimeContext): C => {
|
||||
const ports = Object.fromEntries(
|
||||
Object.entries(spec.ports).map(([name, port]) => {
|
||||
switch (port.kind) {
|
||||
case "state": {
|
||||
const state = raw.state(port.id);
|
||||
return [
|
||||
name,
|
||||
{
|
||||
...(port.primitives.includes("read")
|
||||
? {
|
||||
get: async () => decodeQxValue(port.valueType, (await state.live()).$quixosValue, messages),
|
||||
live: () => state.live(),
|
||||
}
|
||||
: {}),
|
||||
...(port.primitives.includes("write")
|
||||
? {
|
||||
set: async (value: unknown) =>
|
||||
state.set(liveValue(encodeQxValue(port.valueType, value, messages))),
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
];
|
||||
}
|
||||
case "edge": {
|
||||
const edge = raw.edge(port.id);
|
||||
return [
|
||||
name,
|
||||
{
|
||||
...Object.fromEntries(
|
||||
port.primitives.map((primitive) => [
|
||||
primitive,
|
||||
edge[primitive as "resolve" | "connect" | "disconnect"],
|
||||
]),
|
||||
),
|
||||
...(port.primitives.includes("resolve") ? { collection: edge.collection } : {}),
|
||||
...(port.primitives.includes("resolve") &&
|
||||
port.primitives.includes("connect") &&
|
||||
port.primitives.includes("disconnect")
|
||||
? { replace: edge.replace }
|
||||
: {}),
|
||||
},
|
||||
];
|
||||
}
|
||||
case "interface": {
|
||||
const target = raw.interface(port.id);
|
||||
return [
|
||||
name,
|
||||
bindInterfaceView(target, defineQxInterfaceContract(port.interfaceRevisionId, port.operations), messages),
|
||||
];
|
||||
}
|
||||
case "query": {
|
||||
const query = raw.query(port.id);
|
||||
const variablesToWire = (variables: unknown) => {
|
||||
const value = encodeQxValue(port.variables, variables, messages);
|
||||
if (value.kind.case !== "objectValue") throw new Error("QUERY_VARIABLE_INVALID");
|
||||
return value.kind.value.fields;
|
||||
};
|
||||
return [
|
||||
name,
|
||||
{
|
||||
async execute(variables: unknown) {
|
||||
const response = await query.execute(variablesToWire(variables), port.definitionDigest);
|
||||
if (response.pending.length || response.errors.length) throw new Error("QUERY_INCOMPLETE");
|
||||
return decodeQxValue(port.output, response.value, messages);
|
||||
},
|
||||
...(port.watch
|
||||
? {
|
||||
async *watch(variables: unknown, signal: AbortSignal) {
|
||||
for await (const event of query.watch(
|
||||
variablesToWire(variables),
|
||||
signal,
|
||||
port.definitionDigest,
|
||||
)) {
|
||||
if (!event.snapshot) throw new Error("QUERY_SNAPSHOT_MISSING");
|
||||
yield decodeQuerySnapshot(event.snapshot, port.output, event.runId, event.sequence);
|
||||
}
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
];
|
||||
}
|
||||
case "constructor":
|
||||
return [
|
||||
name,
|
||||
{
|
||||
construct: (input: unknown) =>
|
||||
raw.constructor(port.id).construct(inputFields(port.inputType, input, messages)),
|
||||
},
|
||||
];
|
||||
}
|
||||
}),
|
||||
);
|
||||
return {
|
||||
conform: {
|
||||
async tryConform<View>(object: import("./references.js").QxObjectRef, contract: QxInterfaceContract<View>) {
|
||||
const target = await raw.tryConform(object, contract.interfaceRevisionId);
|
||||
return target
|
||||
? (bindInterfaceView(target, contract as QxInterfaceContract<unknown>, messages) as View)
|
||||
: undefined;
|
||||
},
|
||||
} satisfies QxConformer,
|
||||
...(spec.receiver === "none" ? {} : { objectId: raw.objectId }),
|
||||
signal: raw.signal,
|
||||
...(spec.receiver !== "none" && raw.openSession
|
||||
? {
|
||||
openSession: async () => {
|
||||
const session = await raw.openSession!();
|
||||
return {
|
||||
id: session.id,
|
||||
close: () => session.close(),
|
||||
run: <T>(work: (context: C) => Promise<T>) => session.run((next) => work(bindContext(next))),
|
||||
};
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
input: decodeQxValue(spec.inputType, inputValue(raw, spec.inputType), messages),
|
||||
ports,
|
||||
} as C;
|
||||
};
|
||||
const execute = async (raw: RuntimeContext) => {
|
||||
const context = bindContext(raw);
|
||||
const value = await (typeof handler === "function" ? handler(context) : handler.get(context));
|
||||
return liveValue(encodeQxValue(spec.eventType ?? spec.outputType, value, messages));
|
||||
};
|
||||
return typeof handler === "function" ? execute : derived(execute);
|
||||
};
|
||||
+1036
-259
File diff suppressed because one or more lines are too long
+1289
-611
File diff suppressed because one or more lines are too long
+729
-869
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,32 @@
|
||||
/** Execution completion, not HTTP disconnection, is the drain boundary. */
|
||||
export const createInvocationRegistry = () => {
|
||||
const entries = new Map<string, { state: string; controller: AbortController }>();
|
||||
return {
|
||||
begin(id: string) {
|
||||
if (!id || entries.has(id))
|
||||
throw new Error("Invocation ID is missing or already used; invocations are never replayed implicitly");
|
||||
// Completed identities remain until process retirement. A bounded process
|
||||
// may reject new work; it must not evict and accidentally replay a call.
|
||||
if (entries.size >= 100_000) throw new Error("Invocation registry full; explicit runtime retirement required");
|
||||
const entry = { state: "running", controller: new AbortController() };
|
||||
entries.set(id, entry);
|
||||
return {
|
||||
signal: entry.controller.signal,
|
||||
finish(failed = false) {
|
||||
entry.state = failed ? "failed" : "completed";
|
||||
},
|
||||
};
|
||||
},
|
||||
status(id: string) {
|
||||
return { invocationId: id, state: entries.get(id)?.state ?? "unknown" };
|
||||
},
|
||||
cancel(id: string) {
|
||||
const entry = entries.get(id);
|
||||
if (entry && ["running", "cancellation-requested"].includes(entry.state)) {
|
||||
entry.state = "cancellation-requested";
|
||||
entry.controller.abort();
|
||||
}
|
||||
return this.status(id);
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,154 @@
|
||||
import { createHash } from "node:crypto";
|
||||
|
||||
export type MigrationInput = {
|
||||
schemaVersion: 1;
|
||||
executionId: string;
|
||||
exportId: string;
|
||||
ports: {
|
||||
name: string;
|
||||
binding: string;
|
||||
view: "old" | "new";
|
||||
access: ("read" | "write" | "create" | "edge")[];
|
||||
atomId?: string;
|
||||
attachedAtomId?: string;
|
||||
defaultValue?: unknown;
|
||||
states?: { objectId: string; value: unknown }[];
|
||||
edges?: MigrationEdge[];
|
||||
}[];
|
||||
};
|
||||
export type MigrationEdge = {
|
||||
id: string;
|
||||
edgeTypeId: string;
|
||||
firstObjectId: string;
|
||||
secondObjectId: string;
|
||||
firstProjectionId: string;
|
||||
secondProjectionId: string;
|
||||
firstOrdinal?: number;
|
||||
secondOrdinal?: number;
|
||||
firstKeyJson?: string;
|
||||
secondKeyJson?: string;
|
||||
};
|
||||
export type MigrationOutput = {
|
||||
schemaVersion: 1;
|
||||
executionId: string;
|
||||
writes: { port: string; objectId: string; value: unknown }[];
|
||||
creates: { port: string; logicalKey: string; objectId: string }[];
|
||||
edgeReplacements: { port: string; edges: MigrationEdge[] }[];
|
||||
};
|
||||
export type MigrationContext = {
|
||||
enumerate(port: string): { objectId: string; value: unknown }[];
|
||||
read(port: string, objectId: string): unknown;
|
||||
write(port: string, objectId: string, value: unknown): void;
|
||||
create(port: string, logicalKey: string): string;
|
||||
edges(port: string): MigrationEdge[];
|
||||
replaceEdges(port: string, edges: MigrationEdge[]): void;
|
||||
};
|
||||
export const migrationObjectId = (executionId: string, port: string, logicalKey: string) =>
|
||||
`obj:migration:${createHash("sha256")
|
||||
.update(JSON.stringify([executionId, port, logicalKey]))
|
||||
.digest("hex")}`;
|
||||
|
||||
/** No ordinary RuntimeContext or network/database clients are supplied here.
|
||||
* Process isolation belongs to the host, not this convenience API. */
|
||||
export const createMigrationContext = (input: MigrationInput) => {
|
||||
if (
|
||||
input.schemaVersion !== 1 ||
|
||||
!input.executionId ||
|
||||
new Set(input.ports.map((entry) => entry.name)).size !== input.ports.length
|
||||
)
|
||||
throw new Error("Invalid migration input");
|
||||
const output: MigrationOutput = {
|
||||
schemaVersion: 1,
|
||||
executionId: input.executionId,
|
||||
writes: [],
|
||||
creates: [],
|
||||
edgeReplacements: [],
|
||||
};
|
||||
const port = (name: string, access: string) => {
|
||||
const selected = input.ports.find((entry) => entry.name === name);
|
||||
if (!selected?.access.includes(access as "read") || (selected.view === "old" && access !== "read"))
|
||||
throw new Error(`Migration port ${name} does not grant ${access}`);
|
||||
return selected;
|
||||
};
|
||||
const context: MigrationContext = {
|
||||
enumerate(name) {
|
||||
const selected = port(name, "read"),
|
||||
states = structuredClone(selected.states ?? []);
|
||||
if (selected.view === "new" && Object.hasOwn(selected, "defaultValue"))
|
||||
for (const helper of output.creates) {
|
||||
if (
|
||||
input.ports.find((entry) => entry.name === helper.port)?.atomId === selected.attachedAtomId &&
|
||||
!states.some((entry) => entry.objectId === helper.objectId)
|
||||
)
|
||||
states.push({ objectId: helper.objectId, value: structuredClone(selected.defaultValue) });
|
||||
}
|
||||
if (selected.view === "new")
|
||||
for (const write of output.writes) {
|
||||
if (input.ports.find((entry) => entry.name === write.port)?.binding !== selected.binding) continue;
|
||||
const existing = states.findIndex((entry) => entry.objectId === write.objectId),
|
||||
entry = { objectId: write.objectId, value: structuredClone(write.value) };
|
||||
if (existing < 0) states.push(entry);
|
||||
else states[existing] = entry;
|
||||
}
|
||||
return states.sort((a, b) => (a.objectId < b.objectId ? -1 : a.objectId > b.objectId ? 1 : 0));
|
||||
},
|
||||
read(name, objectId) {
|
||||
return context.enumerate(name).find((entry) => entry.objectId === objectId)?.value;
|
||||
},
|
||||
write(name, objectId, value) {
|
||||
port(name, "write");
|
||||
const previous = output.writes.findIndex((entry) => entry.port === name && entry.objectId === objectId);
|
||||
const entry = { port: name, objectId, value: structuredClone(value) };
|
||||
if (previous < 0) output.writes.push(entry);
|
||||
else output.writes[previous] = entry;
|
||||
},
|
||||
create(name, logicalKey) {
|
||||
port(name, "create");
|
||||
if (!logicalKey || logicalKey.length > 1024)
|
||||
throw new Error("Migration creation requires a bounded stable logical key");
|
||||
const objectId = migrationObjectId(input.executionId, name, logicalKey);
|
||||
if (!output.creates.some((entry) => entry.objectId === objectId))
|
||||
output.creates.push({ port: name, logicalKey, objectId });
|
||||
return objectId;
|
||||
},
|
||||
edges(name) {
|
||||
const selected = port(name, "read");
|
||||
const replacement =
|
||||
selected.view === "new"
|
||||
? output.edgeReplacements.find(
|
||||
(entry) => input.ports.find((candidate) => candidate.name === entry.port)?.binding === selected.binding,
|
||||
)
|
||||
: undefined;
|
||||
return structuredClone(replacement?.edges ?? selected.edges ?? []);
|
||||
},
|
||||
replaceEdges(name, edges) {
|
||||
port(name, "edge");
|
||||
const previous = output.edgeReplacements.findIndex((entry) => entry.port === name);
|
||||
const entry = { port: name, edges: structuredClone(edges) };
|
||||
if (previous < 0) output.edgeReplacements.push(entry);
|
||||
else output.edgeReplacements[previous] = entry;
|
||||
},
|
||||
};
|
||||
return { context, result: () => structuredClone(output) };
|
||||
};
|
||||
|
||||
/** Entrypoint for an immutable package's dedicated bin/migrate executable.
|
||||
* stdout is protocol-only; send diagnostics to stderr. The host independently
|
||||
* validates every write, helper identity, contract, and completion receipt. */
|
||||
export const serveMigration = async (exports: Record<string, (context: MigrationContext) => void | Promise<void>>) => {
|
||||
const chunks: Buffer[] = [];
|
||||
let bytes = 0;
|
||||
for await (const chunk of process.stdin) {
|
||||
bytes += chunk.length;
|
||||
if (bytes > 16 * 1024 * 1024) throw new Error("Migration input exceeds 16 MiB");
|
||||
chunks.push(Buffer.from(chunk));
|
||||
}
|
||||
const input = JSON.parse(Buffer.concat(chunks).toString("utf8")) as MigrationInput;
|
||||
const implementation = Object.hasOwn(exports, input.exportId) ? exports[input.exportId] : undefined;
|
||||
if (!implementation) throw new Error("Unknown migration export");
|
||||
const execution = createMigrationContext(input);
|
||||
await implementation(execution.context);
|
||||
const result = JSON.stringify(execution.result());
|
||||
if (Buffer.byteLength(result) > 16 * 1024 * 1024) throw new Error("Migration output exceeds 16 MiB");
|
||||
process.stdout.write(`${result}\n`);
|
||||
};
|
||||
@@ -0,0 +1,82 @@
|
||||
import { decodeQxValue, type QxValueType } from "./bindings.js";
|
||||
import type { QueryResponse } from "./camino/api_pb.js";
|
||||
import type { QxObjectRef } from "./references.js";
|
||||
|
||||
export type QxQueryPartial<T> = T extends QxObjectRef
|
||||
? T
|
||||
: T extends readonly (infer Item)[]
|
||||
? QxQueryPartial<Item>[]
|
||||
: T extends object
|
||||
? { [Key in keyof T]?: QxQueryPartial<T[Key]> }
|
||||
: T;
|
||||
export type QxQuerySnapshot<T> = {
|
||||
runId: string;
|
||||
sequence: bigint;
|
||||
dataVersion: string;
|
||||
bindingDigest: string;
|
||||
consistency: string;
|
||||
fields: { path: readonly (string | number)[]; status: "pending" | "error"; error?: string }[];
|
||||
} & ({ status: "ready"; data: T } | { status: "partial"; data: QxQueryPartial<T> });
|
||||
declare const queryTypes: unique symbol;
|
||||
/** Generated shape evidence, not permission to run a query. */
|
||||
export interface QxQueryDescriptor<Variables, Result, Root extends string = string> {
|
||||
readonly id: string;
|
||||
readonly definitionDigest: string;
|
||||
readonly rootInterfaceRevisionId: Root;
|
||||
readonly variables: QxValueType;
|
||||
readonly output: QxValueType;
|
||||
readonly watch: boolean;
|
||||
readonly [queryTypes]?: (variables: Variables, result: Result) => [Variables, Result];
|
||||
}
|
||||
|
||||
export function decodeQuerySnapshot<T>(
|
||||
response: QueryResponse,
|
||||
output: QxValueType,
|
||||
runId: string,
|
||||
sequence: bigint,
|
||||
): QxQuerySnapshot<T> {
|
||||
if (response.preparationToken || response.residualWindows.length || response.relationalCaptures.length)
|
||||
throw new Error("QUERY_RESULT_UNFINISHED: private preparation is not a query result");
|
||||
const fields = [
|
||||
...response.pending.map((field) => ({ path: field.path, status: "pending" as const })),
|
||||
...response.errors.map((field) => ({ path: field.path, status: "error" as const, error: field.error })),
|
||||
].map((field) => ({
|
||||
...field,
|
||||
path: field.path.map((part) => {
|
||||
if (part.part.case !== "field" && part.part.case !== "index") throw new Error("QUERY_PATCH_INVALID");
|
||||
return part.part.value;
|
||||
}),
|
||||
}));
|
||||
// Pending/error values are absent, not successful nulls of a scalar type.
|
||||
const shape = structuredClone(output);
|
||||
for (const field of fields) {
|
||||
let cursor = shape;
|
||||
for (const [index, part] of field.path.entries()) {
|
||||
while (cursor.kind === "optional") cursor = cursor.value;
|
||||
const last = index === field.path.length - 1;
|
||||
if (typeof part === "string" && cursor.kind === "record" && cursor.fields[part]) {
|
||||
if (last) cursor.fields[part] = { kind: "optional", value: cursor.fields[part]! };
|
||||
else cursor = cursor.fields[part]!;
|
||||
} else if (typeof part === "number" && cursor.kind === "list") cursor = cursor.value;
|
||||
else throw new Error("QUERY_PATCH_INVALID");
|
||||
}
|
||||
}
|
||||
const data = decodeQxValue(shape, response.value, {}) as Record<string, unknown>;
|
||||
for (const field of fields) {
|
||||
let cursor: unknown = data;
|
||||
for (const [index, part] of field.path.entries()) {
|
||||
if (!cursor || typeof cursor !== "object") throw new Error("QUERY_PATCH_INVALID");
|
||||
if (index === field.path.length - 1) delete (cursor as Record<string | number, unknown>)[part];
|
||||
else cursor = (cursor as Record<string | number, unknown>)[part];
|
||||
}
|
||||
}
|
||||
return {
|
||||
runId,
|
||||
sequence,
|
||||
dataVersion: response.dataVersion,
|
||||
bindingDigest: response.bindingDigest,
|
||||
consistency: response.consistency,
|
||||
fields,
|
||||
...(fields.length ? { status: "partial", data } : { status: "ready", data }),
|
||||
} as QxQuerySnapshot<T>;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,68 @@
|
||||
// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js"
|
||||
// @generated from file quixos/package.proto (package quixos, syntax proto3)
|
||||
/* eslint-disable */
|
||||
|
||||
import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2";
|
||||
import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
|
||||
import type { Message } from "@bufbuild/protobuf";
|
||||
|
||||
/**
|
||||
* Describes the file quixos/package.proto.
|
||||
*/
|
||||
export const file_quixos_package: GenFile = /*@__PURE__*/
|
||||
fileDesc("ChRxdWl4b3MvcGFja2FnZS5wcm90bxIGcXVpeG9zIo4BChFQYWNrYWdlRGVzY3JpcHRvchISCgpwYWNrYWdlX2lkGAEgASgJEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYAiABKAkSIAoYcnVudGltZV9wcm90b2NvbF92ZXJzaW9uGAMgASgJEiYKB2V4cG9ydHMYBCADKAsyFS5xdWl4b3MuUnVudGltZUV4cG9ydCI6Cg1SdW50aW1lRXhwb3J0EhEKCWV4cG9ydF9pZBgBIAEoCRIWCg5ydW50aW1lX3N5bWJvbBgCIAEoCWIGcHJvdG8z");
|
||||
|
||||
/**
|
||||
* @generated from message quixos.PackageDescriptor
|
||||
*/
|
||||
export type PackageDescriptor = Message<"quixos.PackageDescriptor"> & {
|
||||
/**
|
||||
* @generated from field: string package_id = 1;
|
||||
*/
|
||||
packageId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string package_revision_id = 2;
|
||||
*/
|
||||
packageRevisionId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string runtime_protocol_version = 3;
|
||||
*/
|
||||
runtimeProtocolVersion: string;
|
||||
|
||||
/**
|
||||
* @generated from field: repeated quixos.RuntimeExport exports = 4;
|
||||
*/
|
||||
exports: RuntimeExport[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message quixos.PackageDescriptor.
|
||||
* Use `create(PackageDescriptorSchema)` to create a new message.
|
||||
*/
|
||||
export const PackageDescriptorSchema: GenMessage<PackageDescriptor> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_package, 0);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.RuntimeExport
|
||||
*/
|
||||
export type RuntimeExport = Message<"quixos.RuntimeExport"> & {
|
||||
/**
|
||||
* @generated from field: string export_id = 1;
|
||||
*/
|
||||
exportId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string runtime_symbol = 2;
|
||||
*/
|
||||
runtimeSymbol: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message quixos.RuntimeExport.
|
||||
* Use `create(RuntimeExportSchema)` to create a new message.
|
||||
*/
|
||||
export const RuntimeExportSchema: GenMessage<RuntimeExport> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_package, 1);
|
||||
|
||||
+155
-22
@@ -10,42 +10,175 @@ import type { Message } from "@bufbuild/protobuf";
|
||||
* Describes the file quixos/refs.proto.
|
||||
*/
|
||||
export const file_quixos_refs: GenFile = /*@__PURE__*/
|
||||
fileDesc("ChFxdWl4b3MvcmVmcy5wcm90bxIGcXVpeG9zInYKC0Z1bmN0aW9uUmVmEhkKEXBhY2thZ2VfbmFtZXNwYWNlGAEgASgJEhQKDHBhY2thZ2VfbmFtZRgCIAEoCRIOCgZzeW1ib2wYAyABKAkSEwoLdmVyc2lvbl9yZWYYBCABKAkSEQoJb3BlcmF0aW9uGAUgASgJYgZwcm90bzM");
|
||||
fileDesc("ChFxdWl4b3MvcmVmcy5wcm90bxIGcXVpeG9zInUKDUNhcGFiaWxpdHlSZWYSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAEgASgJEhQKDG9wZXJhdGlvbl9pZBgCIAEoCRIvCgtjb25mb3JtYW5jZRgDIAEoCzIaLnF1aXhvcy5Db25mb3JtYW5jZVdpdG5lc3MilgEKEkNvbmZvcm1hbmNlV2l0bmVzcxIRCglvYmplY3RfaWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJEhYKDmNvbmZvcm1hbmNlX2lkGAMgASgJEh0KFXdvcmtzcGFjZV9yZXZpc2lvbl9pZBgEIAEoCRIXCg93b3Jrc3BhY2VfZXBvY2gYBSABKAkiQgoQUGFja2FnZUV4cG9ydFJlZhIbChNwYWNrYWdlX3JldmlzaW9uX2lkGAEgASgJEhEKCWV4cG9ydF9pZBgCIAEoCSLYAQoSSW5qZWN0ZWREZXBlbmRlbmN5Eg8KB3BvcnRfaWQYASABKAkSFwoNc3RhdGVfc2xvdF9pZBgCIAEoCUgAEiYKBGVkZ2UYAyABKAsyFi5xdWl4b3MuRWRnZURlcGVuZGVuY3lIABIfChVpbnRlcmZhY2VfcmV2aXNpb25faWQYBCABKAlIABIdChNjb25zdHJ1Y3Rvcl9hdG9tX2lkGAUgASgJSAASEgoIcXVlcnlfaWQYByABKAlIABIRCglvYmplY3RfaWQYBiABKAlCCQoHYmluZGluZyI9Cg5FZGdlRGVwZW5kZW5jeRIUCgxlZGdlX3R5cGVfaWQYASABKAkSFQoNcHJvamVjdGlvbl9pZBgCIAEoCWIGcHJvdG8z");
|
||||
|
||||
/**
|
||||
* @generated from message quixos.FunctionRef
|
||||
* @generated from message quixos.CapabilityRef
|
||||
*/
|
||||
export type FunctionRef = Message<"quixos.FunctionRef"> & {
|
||||
export type CapabilityRef = Message<"quixos.CapabilityRef"> & {
|
||||
/**
|
||||
* @generated from field: string package_namespace = 1;
|
||||
* @generated from field: string interface_revision_id = 1;
|
||||
*/
|
||||
packageNamespace: string;
|
||||
interfaceRevisionId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string package_name = 2;
|
||||
* @generated from field: string operation_id = 2;
|
||||
*/
|
||||
packageName: string;
|
||||
operationId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string symbol = 3;
|
||||
* Optional fence for a view acquired through TryConform. Not an authority grant.
|
||||
*
|
||||
* @generated from field: quixos.ConformanceWitness conformance = 3;
|
||||
*/
|
||||
symbol: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string version_ref = 4;
|
||||
*/
|
||||
versionRef: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string operation = 5;
|
||||
*/
|
||||
operation: string;
|
||||
conformance?: ConformanceWitness | undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message quixos.FunctionRef.
|
||||
* Use `create(FunctionRefSchema)` to create a new message.
|
||||
* Describes the message quixos.CapabilityRef.
|
||||
* Use `create(CapabilityRefSchema)` to create a new message.
|
||||
*/
|
||||
export const FunctionRefSchema: GenMessage<FunctionRef> = /*@__PURE__*/
|
||||
export const CapabilityRefSchema: GenMessage<CapabilityRef> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_refs, 0);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.ConformanceWitness
|
||||
*/
|
||||
export type ConformanceWitness = Message<"quixos.ConformanceWitness"> & {
|
||||
/**
|
||||
* @generated from field: string object_id = 1;
|
||||
*/
|
||||
objectId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string interface_revision_id = 2;
|
||||
*/
|
||||
interfaceRevisionId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string conformance_id = 3;
|
||||
*/
|
||||
conformanceId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string workspace_revision_id = 4;
|
||||
*/
|
||||
workspaceRevisionId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string workspace_epoch = 5;
|
||||
*/
|
||||
workspaceEpoch: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message quixos.ConformanceWitness.
|
||||
* Use `create(ConformanceWitnessSchema)` to create a new message.
|
||||
*/
|
||||
export const ConformanceWitnessSchema: GenMessage<ConformanceWitness> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_refs, 1);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.PackageExportRef
|
||||
*/
|
||||
export type PackageExportRef = Message<"quixos.PackageExportRef"> & {
|
||||
/**
|
||||
* @generated from field: string package_revision_id = 1;
|
||||
*/
|
||||
packageRevisionId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string export_id = 2;
|
||||
*/
|
||||
exportId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message quixos.PackageExportRef.
|
||||
* Use `create(PackageExportRefSchema)` to create a new message.
|
||||
*/
|
||||
export const PackageExportRefSchema: GenMessage<PackageExportRef> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_refs, 2);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.InjectedDependency
|
||||
*/
|
||||
export type InjectedDependency = Message<"quixos.InjectedDependency"> & {
|
||||
/**
|
||||
* @generated from field: string port_id = 1;
|
||||
*/
|
||||
portId: string;
|
||||
|
||||
/**
|
||||
* @generated from oneof quixos.InjectedDependency.binding
|
||||
*/
|
||||
binding: {
|
||||
/**
|
||||
* @generated from field: string state_slot_id = 2;
|
||||
*/
|
||||
value: string;
|
||||
case: "stateSlotId";
|
||||
} | {
|
||||
/**
|
||||
* @generated from field: quixos.EdgeDependency edge = 3;
|
||||
*/
|
||||
value: EdgeDependency;
|
||||
case: "edge";
|
||||
} | {
|
||||
/**
|
||||
* @generated from field: string interface_revision_id = 4;
|
||||
*/
|
||||
value: string;
|
||||
case: "interfaceRevisionId";
|
||||
} | {
|
||||
/**
|
||||
* @generated from field: string constructor_atom_id = 5;
|
||||
*/
|
||||
value: string;
|
||||
case: "constructorAtomId";
|
||||
} | {
|
||||
/**
|
||||
* @generated from field: string query_id = 7;
|
||||
*/
|
||||
value: string;
|
||||
case: "queryId";
|
||||
} | { case: undefined; value?: undefined };
|
||||
|
||||
/**
|
||||
* Defaults to the invocation receiver. A checked dependency traversal can
|
||||
* select a related object explicitly before the package runtime starts.
|
||||
*
|
||||
* @generated from field: string object_id = 6;
|
||||
*/
|
||||
objectId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message quixos.InjectedDependency.
|
||||
* Use `create(InjectedDependencySchema)` to create a new message.
|
||||
*/
|
||||
export const InjectedDependencySchema: GenMessage<InjectedDependency> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_refs, 3);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.EdgeDependency
|
||||
*/
|
||||
export type EdgeDependency = Message<"quixos.EdgeDependency"> & {
|
||||
/**
|
||||
* @generated from field: string edge_type_id = 1;
|
||||
*/
|
||||
edgeTypeId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string projection_id = 2;
|
||||
*/
|
||||
projectionId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message quixos.EdgeDependency.
|
||||
* Use `create(EdgeDependencySchema)` to create a new message.
|
||||
*/
|
||||
export const EdgeDependencySchema: GenMessage<EdgeDependency> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_refs, 4);
|
||||
|
||||
|
||||
+166
-25
@@ -6,7 +6,7 @@ import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegen
|
||||
import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2";
|
||||
import type { Value } from "../camino/api_pb.js";
|
||||
import { file_camino_api } from "../camino/api_pb.js";
|
||||
import type { FunctionRef } from "./refs_pb.js";
|
||||
import type { InjectedDependency, PackageExportRef } from "./refs_pb.js";
|
||||
import { file_quixos_refs } from "./refs_pb.js";
|
||||
import type { Message } from "@bufbuild/protobuf";
|
||||
|
||||
@@ -14,7 +14,7 @@ import type { Message } from "@bufbuild/protobuf";
|
||||
* Describes the file quixos/runtime.proto.
|
||||
*/
|
||||
export const file_quixos_runtime: GenFile = /*@__PURE__*/
|
||||
fileDesc("ChRxdWl4b3MvcnVudGltZS5wcm90bxIOcXVpeG9zLnJ1bnRpbWUiMQoQSGFuZHNoYWtlUmVxdWVzdBIdChVvcmNoX3Byb3RvY29sX3ZlcnNpb24YASABKAkijgEKEUhhbmRzaGFrZVJlc3BvbnNlEhkKEXBhY2thZ2VfbmFtZXNwYWNlGAEgASgJEhQKDHBhY2thZ2VfbmFtZRgCIAEoCRIgChhydW50aW1lX3Byb3RvY29sX3ZlcnNpb24YAyABKAkSJgoJZnVuY3Rpb25zGAQgAygLMhMucXVpeG9zLkZ1bmN0aW9uUmVmItYBCg1JbnZva2VSZXF1ZXN0EhUKDWludm9jYXRpb25faWQYASABKAkSJQoIZnVuY3Rpb24YAiABKAsyEy5xdWl4b3MuRnVuY3Rpb25SZWYSEQoJb2JqZWN0X2lkGAMgASgJEjcKBWlucHV0GAQgAygLMigucXVpeG9zLnJ1bnRpbWUuSW52b2tlUmVxdWVzdC5JbnB1dEVudHJ5GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJKCg5JbnZva2VSZXNwb25zZRIKCgJvaxgBIAEoCBIdCgZyZXN1bHQYAiABKAsyDS5jYW1pbm8uVmFsdWUSDQoFZXJyb3IYAyABKAki1AEKDFdhdGNoUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEiUKCGZ1bmN0aW9uGAIgASgLMhMucXVpeG9zLkZ1bmN0aW9uUmVmEhEKCW9iamVjdF9pZBgDIAEoCRI2CgVpbnB1dBgEIAMoCzInLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdC5JbnB1dEVudHJ5GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJeChFEZXJpdmVkRGVwZW5kZW5jeRIMCgRraW5kGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRISCgpmaWVsZF9uYW1lGAMgASgJEhQKDHNvdXJjZV9maWVsZBgEIAEoCSKVAQoKV2F0Y2hFdmVudBIQCgh3YXRjaF9pZBgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZRI3CgxkZXBlbmRlbmNpZXMYAyADKAsyIS5xdWl4b3MucnVudGltZS5EZXJpdmVkRGVwZW5kZW5jeRINCgVlcnJvchgEIAEoCRIPCgdpbml0aWFsGAUgASgIMvABCg5QYWNrYWdlUnVudGltZRJQCglIYW5kc2hha2USIC5xdWl4b3MucnVudGltZS5IYW5kc2hha2VSZXF1ZXN0GiEucXVpeG9zLnJ1bnRpbWUuSGFuZHNoYWtlUmVzcG9uc2USRwoGSW52b2tlEh0ucXVpeG9zLnJ1bnRpbWUuSW52b2tlUmVxdWVzdBoeLnF1aXhvcy5ydW50aW1lLkludm9rZVJlc3BvbnNlEkMKBVdhdGNoEhwucXVpeG9zLnJ1bnRpbWUuV2F0Y2hSZXF1ZXN0GhoucXVpeG9zLnJ1bnRpbWUuV2F0Y2hFdmVudDABYgZwcm90bzM", [file_camino_api, file_quixos_refs]);
|
||||
fileDesc("ChRxdWl4b3MvcnVudGltZS5wcm90bxIOcXVpeG9zLnJ1bnRpbWUiQAoQSGFuZHNoYWtlUmVxdWVzdBIdChVvcmNoX3Byb3RvY29sX3ZlcnNpb24YASABKAkSDQoFbm9uY2UYAiABKAkirwEKEUhhbmRzaGFrZVJlc3BvbnNlEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYASABKAkSIAoYcnVudGltZV9wcm90b2NvbF92ZXJzaW9uGAIgASgJEhIKCmV4cG9ydF9pZHMYAyADKAkSEwoLaW5zdGFuY2VfaWQYBCABKAkSHAoUYXV0aGVudGljYXRpb25fcHJvb2YYBSABKAkSFAoMY2FwYWJpbGl0aWVzGAYgAygJIpoBChFJbnZvY2F0aW9uQ29udGV4dBIXCg93b3Jrc3BhY2VfZXBvY2gYASABKAkSEwoLaW5zdGFuY2VfaWQYAiABKAkSFgoOYmluZGluZ19kaWdlc3QYAyABKAkSDQoFZ3JhbnQYBCABKAkSEgoKc2Vzc2lvbl9pZBgFIAEoCRIcChRvd25lcl9jb25mb3JtYW5jZV9pZBgGIAEoCSIxChhJbnZvY2F0aW9uQ29udHJvbFJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCSI4ChBJbnZvY2F0aW9uU3RhdHVzEhUKDWludm9jYXRpb25faWQYASABKAkSDQoFc3RhdGUYAiABKAkivwIKDUludm9rZVJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCRIoCgZleHBvcnQYAiABKAsyGC5xdWl4b3MuUGFja2FnZUV4cG9ydFJlZhIRCglvYmplY3RfaWQYAyABKAkSNwoFaW5wdXQYBCADKAsyKC5xdWl4b3MucnVudGltZS5JbnZva2VSZXF1ZXN0LklucHV0RW50cnkSMAoMZGVwZW5kZW5jaWVzGAUgAygLMhoucXVpeG9zLkluamVjdGVkRGVwZW5kZW5jeRIyCgdjb250ZXh0GAYgASgLMiEucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRleHQaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIoMBCg5JbnZva2VSZXNwb25zZRIKCgJvaxgBIAEoCBIdCgZyZXN1bHQYAiABKAsyDS5jYW1pbm8uVmFsdWUSDQoFZXJyb3IYAyABKAkSNwoMZGVwZW5kZW5jaWVzGAQgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kivQIKDFdhdGNoUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI2CgVpbnB1dBgEIAMoCzInLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdC5JbnB1dEVudHJ5EjAKDGRlcGVuZGVuY2llcxgFIAMoCzIaLnF1aXhvcy5JbmplY3RlZERlcGVuZGVuY3kSMgoHY29udGV4dBgGIAEoCzIhLnF1aXhvcy5ydW50aW1lLkludm9jYXRpb25Db250ZXh0GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJiChFEZXJpdmVkRGVwZW5kZW5jeRIMCgRraW5kGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRIVCg1hdHRhY2htZW50X2lkGAMgASgJEhUKDXByb2plY3Rpb25faWQYBCABKAkilQEKCldhdGNoRXZlbnQSEAoId2F0Y2hfaWQYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWUSNwoMZGVwZW5kZW5jaWVzGAMgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kSDQoFZXJyb3IYBCABKAkSDwoHaW5pdGlhbBgFIAEoCDKzAwoOUGFja2FnZVJ1bnRpbWUSUAoJSGFuZHNoYWtlEiAucXVpeG9zLnJ1bnRpbWUuSGFuZHNoYWtlUmVxdWVzdBohLnF1aXhvcy5ydW50aW1lLkhhbmRzaGFrZVJlc3BvbnNlEkcKBkludm9rZRIdLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QaHi5xdWl4b3MucnVudGltZS5JbnZva2VSZXNwb25zZRJDCgVXYXRjaBIcLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdBoaLnF1aXhvcy5ydW50aW1lLldhdGNoRXZlbnQwARJhChNHZXRJbnZvY2F0aW9uU3RhdHVzEigucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRyb2xSZXF1ZXN0GiAucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvblN0YXR1cxJeChBDYW5jZWxJbnZvY2F0aW9uEigucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRyb2xSZXF1ZXN0GiAucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvblN0YXR1c2IGcHJvdG8z", [file_camino_api, file_quixos_refs]);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.runtime.HandshakeRequest
|
||||
@@ -24,6 +24,11 @@ export type HandshakeRequest = Message<"quixos.runtime.HandshakeRequest"> & {
|
||||
* @generated from field: string orch_protocol_version = 1;
|
||||
*/
|
||||
orchProtocolVersion: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string nonce = 2;
|
||||
*/
|
||||
nonce: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -38,24 +43,34 @@ export const HandshakeRequestSchema: GenMessage<HandshakeRequest> = /*@__PURE__*
|
||||
*/
|
||||
export type HandshakeResponse = Message<"quixos.runtime.HandshakeResponse"> & {
|
||||
/**
|
||||
* @generated from field: string package_namespace = 1;
|
||||
* @generated from field: string package_revision_id = 1;
|
||||
*/
|
||||
packageNamespace: string;
|
||||
packageRevisionId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string package_name = 2;
|
||||
*/
|
||||
packageName: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string runtime_protocol_version = 3;
|
||||
* @generated from field: string runtime_protocol_version = 2;
|
||||
*/
|
||||
runtimeProtocolVersion: string;
|
||||
|
||||
/**
|
||||
* @generated from field: repeated quixos.FunctionRef functions = 4;
|
||||
* @generated from field: repeated string export_ids = 3;
|
||||
*/
|
||||
functions: FunctionRef[];
|
||||
exportIds: string[];
|
||||
|
||||
/**
|
||||
* @generated from field: string instance_id = 4;
|
||||
*/
|
||||
instanceId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string authentication_proof = 5;
|
||||
*/
|
||||
authenticationProof: string;
|
||||
|
||||
/**
|
||||
* @generated from field: repeated string capabilities = 6;
|
||||
*/
|
||||
capabilities: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -65,6 +80,91 @@ export type HandshakeResponse = Message<"quixos.runtime.HandshakeResponse"> & {
|
||||
export const HandshakeResponseSchema: GenMessage<HandshakeResponse> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_runtime, 1);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.runtime.InvocationContext
|
||||
*/
|
||||
export type InvocationContext = Message<"quixos.runtime.InvocationContext"> & {
|
||||
/**
|
||||
* @generated from field: string workspace_epoch = 1;
|
||||
*/
|
||||
workspaceEpoch: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string instance_id = 2;
|
||||
*/
|
||||
instanceId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string binding_digest = 3;
|
||||
*/
|
||||
bindingDigest: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string grant = 4;
|
||||
*/
|
||||
grant: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string session_id = 5;
|
||||
*/
|
||||
sessionId: string;
|
||||
|
||||
/**
|
||||
* Host-selected owner; packages must not invent workspace-local ownership.
|
||||
*
|
||||
* @generated from field: string owner_conformance_id = 6;
|
||||
*/
|
||||
ownerConformanceId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message quixos.runtime.InvocationContext.
|
||||
* Use `create(InvocationContextSchema)` to create a new message.
|
||||
*/
|
||||
export const InvocationContextSchema: GenMessage<InvocationContext> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_runtime, 2);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.runtime.InvocationControlRequest
|
||||
*/
|
||||
export type InvocationControlRequest = Message<"quixos.runtime.InvocationControlRequest"> & {
|
||||
/**
|
||||
* @generated from field: string invocation_id = 1;
|
||||
*/
|
||||
invocationId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message quixos.runtime.InvocationControlRequest.
|
||||
* Use `create(InvocationControlRequestSchema)` to create a new message.
|
||||
*/
|
||||
export const InvocationControlRequestSchema: GenMessage<InvocationControlRequest> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_runtime, 3);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.runtime.InvocationStatus
|
||||
*/
|
||||
export type InvocationStatus = Message<"quixos.runtime.InvocationStatus"> & {
|
||||
/**
|
||||
* @generated from field: string invocation_id = 1;
|
||||
*/
|
||||
invocationId: string;
|
||||
|
||||
/**
|
||||
* unknown, running, cancellation-requested, completed, failed
|
||||
*
|
||||
* @generated from field: string state = 2;
|
||||
*/
|
||||
state: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message quixos.runtime.InvocationStatus.
|
||||
* Use `create(InvocationStatusSchema)` to create a new message.
|
||||
*/
|
||||
export const InvocationStatusSchema: GenMessage<InvocationStatus> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_runtime, 4);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.runtime.InvokeRequest
|
||||
*/
|
||||
@@ -75,9 +175,9 @@ export type InvokeRequest = Message<"quixos.runtime.InvokeRequest"> & {
|
||||
invocationId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: quixos.FunctionRef function = 2;
|
||||
* @generated from field: quixos.PackageExportRef export = 2;
|
||||
*/
|
||||
function?: FunctionRef | undefined;
|
||||
export?: PackageExportRef | undefined;
|
||||
|
||||
/**
|
||||
* @generated from field: string object_id = 3;
|
||||
@@ -88,6 +188,16 @@ export type InvokeRequest = Message<"quixos.runtime.InvokeRequest"> & {
|
||||
* @generated from field: map<string, camino.Value> input = 4;
|
||||
*/
|
||||
input: { [key: string]: Value };
|
||||
|
||||
/**
|
||||
* @generated from field: repeated quixos.InjectedDependency dependencies = 5;
|
||||
*/
|
||||
dependencies: InjectedDependency[];
|
||||
|
||||
/**
|
||||
* @generated from field: quixos.runtime.InvocationContext context = 6;
|
||||
*/
|
||||
context?: InvocationContext | undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -95,7 +205,7 @@ export type InvokeRequest = Message<"quixos.runtime.InvokeRequest"> & {
|
||||
* Use `create(InvokeRequestSchema)` to create a new message.
|
||||
*/
|
||||
export const InvokeRequestSchema: GenMessage<InvokeRequest> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_runtime, 2);
|
||||
messageDesc(file_quixos_runtime, 5);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.runtime.InvokeResponse
|
||||
@@ -115,6 +225,11 @@ export type InvokeResponse = Message<"quixos.runtime.InvokeResponse"> & {
|
||||
* @generated from field: string error = 3;
|
||||
*/
|
||||
error: string;
|
||||
|
||||
/**
|
||||
* @generated from field: repeated quixos.runtime.DerivedDependency dependencies = 4;
|
||||
*/
|
||||
dependencies: DerivedDependency[];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -122,7 +237,7 @@ export type InvokeResponse = Message<"quixos.runtime.InvokeResponse"> & {
|
||||
* Use `create(InvokeResponseSchema)` to create a new message.
|
||||
*/
|
||||
export const InvokeResponseSchema: GenMessage<InvokeResponse> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_runtime, 3);
|
||||
messageDesc(file_quixos_runtime, 6);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.runtime.WatchRequest
|
||||
@@ -134,9 +249,9 @@ export type WatchRequest = Message<"quixos.runtime.WatchRequest"> & {
|
||||
invocationId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: quixos.FunctionRef function = 2;
|
||||
* @generated from field: quixos.PackageExportRef export = 2;
|
||||
*/
|
||||
function?: FunctionRef | undefined;
|
||||
export?: PackageExportRef | undefined;
|
||||
|
||||
/**
|
||||
* @generated from field: string object_id = 3;
|
||||
@@ -147,6 +262,16 @@ export type WatchRequest = Message<"quixos.runtime.WatchRequest"> & {
|
||||
* @generated from field: map<string, camino.Value> input = 4;
|
||||
*/
|
||||
input: { [key: string]: Value };
|
||||
|
||||
/**
|
||||
* @generated from field: repeated quixos.InjectedDependency dependencies = 5;
|
||||
*/
|
||||
dependencies: InjectedDependency[];
|
||||
|
||||
/**
|
||||
* @generated from field: quixos.runtime.InvocationContext context = 6;
|
||||
*/
|
||||
context?: InvocationContext | undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -154,7 +279,7 @@ export type WatchRequest = Message<"quixos.runtime.WatchRequest"> & {
|
||||
* Use `create(WatchRequestSchema)` to create a new message.
|
||||
*/
|
||||
export const WatchRequestSchema: GenMessage<WatchRequest> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_runtime, 4);
|
||||
messageDesc(file_quixos_runtime, 7);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.runtime.DerivedDependency
|
||||
@@ -171,14 +296,14 @@ export type DerivedDependency = Message<"quixos.runtime.DerivedDependency"> & {
|
||||
objectId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string field_name = 3;
|
||||
* @generated from field: string attachment_id = 3;
|
||||
*/
|
||||
fieldName: string;
|
||||
attachmentId: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string source_field = 4;
|
||||
* @generated from field: string projection_id = 4;
|
||||
*/
|
||||
sourceField: string;
|
||||
projectionId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -186,7 +311,7 @@ export type DerivedDependency = Message<"quixos.runtime.DerivedDependency"> & {
|
||||
* Use `create(DerivedDependencySchema)` to create a new message.
|
||||
*/
|
||||
export const DerivedDependencySchema: GenMessage<DerivedDependency> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_runtime, 5);
|
||||
messageDesc(file_quixos_runtime, 8);
|
||||
|
||||
/**
|
||||
* @generated from message quixos.runtime.WatchEvent
|
||||
@@ -223,7 +348,7 @@ export type WatchEvent = Message<"quixos.runtime.WatchEvent"> & {
|
||||
* Use `create(WatchEventSchema)` to create a new message.
|
||||
*/
|
||||
export const WatchEventSchema: GenMessage<WatchEvent> = /*@__PURE__*/
|
||||
messageDesc(file_quixos_runtime, 6);
|
||||
messageDesc(file_quixos_runtime, 9);
|
||||
|
||||
/**
|
||||
* @generated from service quixos.runtime.PackageRuntime
|
||||
@@ -253,6 +378,22 @@ export const PackageRuntime: GenService<{
|
||||
input: typeof WatchRequestSchema;
|
||||
output: typeof WatchEventSchema;
|
||||
},
|
||||
/**
|
||||
* @generated from rpc quixos.runtime.PackageRuntime.GetInvocationStatus
|
||||
*/
|
||||
getInvocationStatus: {
|
||||
methodKind: "unary";
|
||||
input: typeof InvocationControlRequestSchema;
|
||||
output: typeof InvocationStatusSchema;
|
||||
},
|
||||
/**
|
||||
* @generated from rpc quixos.runtime.PackageRuntime.CancelInvocation
|
||||
*/
|
||||
cancelInvocation: {
|
||||
methodKind: "unary";
|
||||
input: typeof InvocationControlRequestSchema;
|
||||
output: typeof InvocationStatusSchema;
|
||||
},
|
||||
}> = /*@__PURE__*/
|
||||
serviceDesc(file_quixos_runtime, 0);
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/** Opaque runtime identity. The wire codec, never ordinary package state, owns
|
||||
* the raw ID. These handles do not themselves confer authority or a lease. */
|
||||
const identities = new WeakMap<object, string>();
|
||||
declare const referenceBrand: unique symbol;
|
||||
export interface QxObjectRef<Identity extends string = string> {
|
||||
readonly [referenceBrand]: { readonly [K in Identity]: true };
|
||||
equals(other: QxObjectRef<string>): boolean;
|
||||
}
|
||||
class Reference {
|
||||
constructor(id: string) {
|
||||
identities.set(this, id);
|
||||
Object.freeze(this);
|
||||
}
|
||||
equals(other: unknown) {
|
||||
return isObjectReference(other) && identities.get(this) === identities.get(other);
|
||||
}
|
||||
toJSON(): never {
|
||||
throw new Error("Object references cannot be serialized into ordinary data");
|
||||
}
|
||||
toString(): never {
|
||||
throw new Error("Object references cannot be coerced to strings");
|
||||
}
|
||||
[Symbol.toPrimitive](): never {
|
||||
throw new Error("Object references cannot be coerced to scalar values");
|
||||
}
|
||||
}
|
||||
export const isObjectReference = (value: unknown): value is QxObjectRef =>
|
||||
typeof value === "object" && value !== null && identities.has(value);
|
||||
|
||||
/** Internal transport boundary; intentionally not exported from the SDK entry. */
|
||||
export const referenceFromWire = (id: string): QxObjectRef => {
|
||||
if (typeof id !== "string" || !id) throw new Error("Missing object reference identity");
|
||||
return new Reference(id) as unknown as QxObjectRef;
|
||||
};
|
||||
export const referenceToWire = (value: unknown): string => {
|
||||
if (!isObjectReference(value)) throw new Error("Expected an opaque object reference, not a raw ID");
|
||||
return identities.get(value)!;
|
||||
};
|
||||
export const assertReferenceFree = (value: unknown, seen = new Set<object>()): void => {
|
||||
if (!value || typeof value !== "object") return;
|
||||
if (isObjectReference(value))
|
||||
throw new Error(
|
||||
"Managed references belong in declared RPC references or graph relationships, not ordinary state/messages",
|
||||
);
|
||||
if (seen.has(value)) throw new Error("Cyclic ordinary data");
|
||||
seen.add(value);
|
||||
if (!(value instanceof Uint8Array)) for (const child of Object.values(value)) assertReferenceFree(child, seen);
|
||||
seen.delete(value);
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
import type { QxObjectRef } from "./references.js";
|
||||
import type { RelationshipCollection, RelationshipEntry } from "./index.js";
|
||||
type Key = string | boolean | bigint;
|
||||
type Port<T extends QxObjectRef> = {
|
||||
collection(): Promise<RelationshipCollection<T>>;
|
||||
replace(entries: RelationshipEntry<T>[], expectedRevision: bigint): Promise<RelationshipCollection<T>>;
|
||||
};
|
||||
const checked = async <T extends QxObjectRef>(port: Port<T>, revision: bigint) => {
|
||||
const snapshot = await port.collection();
|
||||
if (snapshot.revision !== revision) throw new Error("STALE_COLLECTION_REVISION");
|
||||
return snapshot;
|
||||
};
|
||||
/** Helpers never retry a failed CAS or silently overwrite concurrent edits. */
|
||||
export const relationshipMap = <T extends QxObjectRef, K extends Key = Key>(port: Port<T>) => ({
|
||||
read: () => port.collection(),
|
||||
async get(key: K) {
|
||||
const snapshot = await port.collection();
|
||||
return { revision: snapshot.revision, value: snapshot.entries.find((entry) => entry.key === key)?.target };
|
||||
},
|
||||
async set(key: K, target: T, expectedRevision: bigint) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
const entries = snapshot.entries.filter((entry) => entry.key !== key);
|
||||
const existing = snapshot.entries.find((entry) => entry.key === key && entry.target.equals(target));
|
||||
entries.push(existing ?? { key, target });
|
||||
return port.replace(entries, expectedRevision);
|
||||
},
|
||||
async delete(key: K, expectedRevision: bigint) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
return port.replace(
|
||||
snapshot.entries.filter((entry) => entry.key !== key),
|
||||
expectedRevision,
|
||||
);
|
||||
},
|
||||
});
|
||||
export const relationshipList = <T extends QxObjectRef>(port: Port<T>) => ({
|
||||
read: () => port.collection(),
|
||||
async insert(index: number, target: T, expectedRevision: bigint) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
if (!Number.isSafeInteger(index) || index < 0 || index > snapshot.entries.length)
|
||||
throw new Error("List index out of bounds");
|
||||
snapshot.entries.splice(index, 0, { target });
|
||||
return port.replace(snapshot.entries, expectedRevision);
|
||||
},
|
||||
async move(edgeId: string, index: number, expectedRevision: bigint) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
const prior = snapshot.entries.findIndex((entry) => entry.edgeId === edgeId);
|
||||
if (prior < 0 || !Number.isSafeInteger(index) || index < 0 || index >= snapshot.entries.length)
|
||||
throw new Error("Unknown list entry or invalid index");
|
||||
const [entry] = snapshot.entries.splice(prior, 1);
|
||||
snapshot.entries.splice(index, 0, entry);
|
||||
return port.replace(snapshot.entries, expectedRevision);
|
||||
},
|
||||
async delete(edgeId: string, expectedRevision: bigint) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
if (!snapshot.entries.some((entry) => entry.edgeId === edgeId)) throw new Error("Unknown list entry");
|
||||
return port.replace(
|
||||
snapshot.entries.filter((entry) => entry.edgeId !== edgeId),
|
||||
expectedRevision,
|
||||
);
|
||||
},
|
||||
});
|
||||
export const relationshipSet = <T extends QxObjectRef>(port: Port<T>) => ({
|
||||
read: () => port.collection(),
|
||||
async add(target: T, expectedRevision: bigint) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
if (snapshot.entries.some((entry) => entry.target.equals(target))) return snapshot;
|
||||
return port.replace([...snapshot.entries, { target }], expectedRevision);
|
||||
},
|
||||
async delete(target: T, expectedRevision: bigint) {
|
||||
const snapshot = await checked(port, expectedRevision);
|
||||
return port.replace(
|
||||
snapshot.entries.filter((entry) => !entry.target.equals(target)),
|
||||
expectedRevision,
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,212 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { referenceFromWire } from "../dist/references.js";
|
||||
import {
|
||||
bindQxHandler,
|
||||
decodeQxValue,
|
||||
encodeQxValue,
|
||||
jsToProtoValue,
|
||||
liveValue,
|
||||
protoValueToJs,
|
||||
} from "../dist/index.js";
|
||||
const scalar = (name) => ({ kind: "scalar", name });
|
||||
const unit = { kind: "builtin", name: "unit" };
|
||||
test("free function handlers never acquire a receiver or object session", async () => {
|
||||
const handler = bindQxHandler(
|
||||
{ receiver: "none", inputType: unit, outputType: unit, ports: {} },
|
||||
async (context) => {
|
||||
assert.equal("objectId" in context, false);
|
||||
assert.equal("openSession" in context, false);
|
||||
},
|
||||
{},
|
||||
);
|
||||
await handler({
|
||||
inputProto: {},
|
||||
get objectId() {
|
||||
throw new Error("no receiver exists");
|
||||
},
|
||||
openSession() {
|
||||
assert.fail("no object session");
|
||||
},
|
||||
});
|
||||
});
|
||||
test("React props no longer have an opaque-message reference escape hatch", () => {
|
||||
const descriptorId = "org.quixos.web-studio.ReactProps";
|
||||
const reference = referenceFromWire("obj:task");
|
||||
const type = { kind: "message", descriptorId };
|
||||
const messages = { [descriptorId]: { encode: jsToProtoValue, decode: protoValueToJs } };
|
||||
assert.throws(() => encodeQxValue(type, { subject: reference }, messages), /Managed references/);
|
||||
assert.throws(() => decodeQxValue(type, jsToProtoValue({ subject: reference }), messages), /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 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 () => {
|
||||
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();
|
||||
},
|
||||
{},
|
||||
);
|
||||
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],
|
||||
[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")],
|
||||
];
|
||||
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 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(() => 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/,
|
||||
);
|
||||
});
|
||||
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") } },
|
||||
},
|
||||
},
|
||||
};
|
||||
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])));
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
assert.equal(written.$quixosValue.kind.value, String(2n ** 60n));
|
||||
assert.deepEqual(result.$quixosValue.kind.value, new Uint8Array([7]));
|
||||
});
|
||||
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,
|
||||
);
|
||||
assert.equal(handler.kind, "derived");
|
||||
const result = await handler.get({ objectId: "obj", inputProto: { title: jsToProtoValue("hello") } });
|
||||
assert.deepEqual(protoValueToJs(result.$quixosValue), { value: "hello" });
|
||||
assert.throws(() => encodeQxValue(message, {}, {}), /Missing message binding/);
|
||||
});
|
||||
@@ -0,0 +1,72 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { bindQxHandler, createRuntimeContext, defineQxInterfaceContract, jsToProtoValue } from "../dist/index.js";
|
||||
import { referenceFromWire } from "../dist/references.js";
|
||||
|
||||
const unit = { kind: "builtin", name: "unit" };
|
||||
test("generated conformance views use checked codecs and retain their fence on invocation", async () => {
|
||||
const contract = defineQxInterfaceContract("Named", {
|
||||
"name.get": { id: "get", inputType: unit, outputType: { kind: "scalar", name: "string" } },
|
||||
});
|
||||
const object = referenceFromWire("object");
|
||||
const witness = {
|
||||
objectId: "object",
|
||||
interfaceRevisionId: "Named",
|
||||
workspaceEpoch: "1",
|
||||
workspaceRevisionId: "w",
|
||||
conformanceId: "named",
|
||||
};
|
||||
const requests = [];
|
||||
const raw = createRuntimeContext(
|
||||
{},
|
||||
{
|
||||
async tryConform(request) {
|
||||
requests.push(request);
|
||||
return { conformance: witness };
|
||||
},
|
||||
async invokeCapability(request) {
|
||||
for (const key of Object.keys(witness)) assert.equal(request.capability.conformance[key], witness[key]);
|
||||
assert.deepEqual(request.input, {});
|
||||
return { ok: true, result: jsToProtoValue("Hello"), dependencies: [] };
|
||||
},
|
||||
},
|
||||
{ objectId: "object", input: {}, dependencies: [] },
|
||||
);
|
||||
const handler = bindQxHandler(
|
||||
{ inputType: unit, outputType: unit, ports: {} },
|
||||
async (context) => {
|
||||
const view = await context.conform.tryConform(object, contract);
|
||||
assert.ok(view.objectId.equals(object));
|
||||
assert.equal(view.contract, contract);
|
||||
assert.equal(await view["name.get"](), "Hello");
|
||||
},
|
||||
{},
|
||||
);
|
||||
await handler(raw);
|
||||
assert.deepEqual(requests, [{ objectId: "object", interfaceRevisionId: "Named" }]);
|
||||
});
|
||||
|
||||
test("package discovery preserves absence and denied errors and refuses raw IDs", async () => {
|
||||
const request = { objectId: "object", input: {}, dependencies: [] };
|
||||
const raw = createRuntimeContext(
|
||||
{},
|
||||
{
|
||||
async tryConform() {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
request,
|
||||
);
|
||||
assert.equal(await raw.tryConform(referenceFromWire("object"), "Missing"), undefined);
|
||||
await assert.rejects(raw.tryConform("object", "Named"), /opaque object reference/);
|
||||
const denied = createRuntimeContext(
|
||||
{},
|
||||
{
|
||||
async tryConform() {
|
||||
throw Error("permission denied");
|
||||
},
|
||||
},
|
||||
request,
|
||||
);
|
||||
await assert.rejects(denied.tryConform(referenceFromWire("object"), "Named"), /permission denied/);
|
||||
});
|
||||
@@ -0,0 +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";
|
||||
|
||||
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)};
|
||||
createPackageRuntimeRoutes({packageRevisionId:'package:test',exports:{}})({
|
||||
service(_type, implementation) { console.log(JSON.stringify(implementation.handshake({nonce:'challenge'}))); }
|
||||
});
|
||||
`,
|
||||
],
|
||||
{ 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.ok(!result.stdout.includes(token));
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { createInvocationRegistry } from "../dist/invocations.js";
|
||||
|
||||
test("cancel requests do not acknowledge execution completion or allow replay", () => {
|
||||
const registry = createInvocationRegistry();
|
||||
const execution = registry.begin("call-1");
|
||||
assert.equal(registry.cancel("call-1").state, "cancellation-requested");
|
||||
assert.equal(execution.signal.aborted, true);
|
||||
assert.equal(registry.status("call-1").state, "cancellation-requested");
|
||||
execution.finish();
|
||||
assert.equal(registry.status("call-1").state, "completed");
|
||||
assert.throws(() => registry.begin("call-1"), /already used/);
|
||||
assert.equal(registry.status("missing").state, "unknown");
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
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);
|
||||
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/);
|
||||
context.write("new", "obj:one", "Alice");
|
||||
assert.equal(context.read("newRead", "obj:one"), "Alice");
|
||||
context.write("new", "obj:one", "Bob");
|
||||
assert.equal(context.read("newRead", "obj:one"), "Bob");
|
||||
assert.equal(context.read("old", "obj:one"), "Alice");
|
||||
const helper = context.create("helpers", "one");
|
||||
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" }]);
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { create } from "@bufbuild/protobuf";
|
||||
import { QueryResponseSchema } from "../dist/camino/api_pb.js";
|
||||
import { InjectedDependencySchema } from "../dist/quixos/refs_pb.js";
|
||||
import { createRuntimeContext, decodeQuerySnapshot, jsToProtoValue, protoValueToJs } from "../dist/index.js";
|
||||
|
||||
test("private relational captures cannot be decoded as a completed public query", () => {
|
||||
const response = create(QueryResponseSchema, { relationalCaptures: [{ rootObjectId: "obj:private" }] });
|
||||
assert.throws(
|
||||
() => decodeQuerySnapshot(response, { kind: "record", fields: {} }, "run", 1n),
|
||||
/QUERY_RESULT_UNFINISHED/,
|
||||
);
|
||||
});
|
||||
|
||||
test("query ports carry only an injected query identity and root", async () => {
|
||||
let seen;
|
||||
const context = createRuntimeContext(
|
||||
{},
|
||||
{
|
||||
executeQuery: async (request) => {
|
||||
seen = request;
|
||||
return create(QueryResponseSchema);
|
||||
},
|
||||
},
|
||||
{
|
||||
objectId: "obj:receiver",
|
||||
input: {},
|
||||
dependencies: [
|
||||
create(InjectedDependencySchema, {
|
||||
portId: "list",
|
||||
objectId: "obj:collection",
|
||||
binding: { case: "queryId", value: "pkg@1:upcoming" },
|
||||
}),
|
||||
],
|
||||
},
|
||||
);
|
||||
await context.query("list").execute({ first: jsToProtoValue(30) }, "checked-definition");
|
||||
assert.equal(seen.expectedDefinitionDigest, "checked-definition");
|
||||
assert.equal(seen.objectId, "obj:collection");
|
||||
assert.equal(seen.queryId, "pkg@1:upcoming");
|
||||
assert.equal(protoValueToJs(seen.variables.first), 30);
|
||||
assert.throws(() => context.query("not-injected"), /Missing/);
|
||||
});
|
||||
|
||||
test("query snapshots distinguish an unavailable scalar from a successful null", () => {
|
||||
const output = {
|
||||
kind: "record",
|
||||
fields: { title: { kind: "scalar", name: "string" }, score: { kind: "scalar", name: "int64" } },
|
||||
};
|
||||
const response = create(QueryResponseSchema, {
|
||||
value: jsToProtoValue({ title: "Native title", score: null }),
|
||||
pending: [{ path: [{ part: { case: "field", value: "score" } }] }],
|
||||
});
|
||||
const snapshot = decodeQuerySnapshot(response, output, "run1", 1n);
|
||||
assert.equal(snapshot.status, "partial");
|
||||
assert.deepEqual(snapshot.data, { title: "Native title" });
|
||||
assert.deepEqual(snapshot.fields, [{ path: ["score"], status: "pending" }]);
|
||||
assert.equal(output.fields.score.kind, "scalar");
|
||||
response.pending = [];
|
||||
response.value = jsToProtoValue({ title: "Native title", score: 9007199254740993n });
|
||||
assert.equal(decodeQuerySnapshot(response, output, "run1", 2n).data.score, 9007199254740993n);
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
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";
|
||||
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 })) }),
|
||||
replace: async (entries, revision) => {
|
||||
assert.equal(revision, current.revision);
|
||||
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 map = relationshipMap(port);
|
||||
await map.set("a1", a, 0n);
|
||||
assert.equal((await map.get("a1")).value.equals(a), true);
|
||||
await assert.rejects(() => map.set("b1", b, 0n), /STALE_COLLECTION/);
|
||||
await map.delete("a1", 1n);
|
||||
const list = relationshipList(port);
|
||||
const inserted = await list.insert(0, a, 2n);
|
||||
await list.insert(1, b, 3n);
|
||||
const moved = await list.move(inserted.entries[0].edgeId, 1, 4n);
|
||||
assert.equal(moved.entries[1].target.equals(a), true);
|
||||
const set = relationshipSet(port);
|
||||
const unchanged = await set.add(referenceFromWire("obj:a"), 5n);
|
||||
assert.equal(unchanged.revision, 5n);
|
||||
});
|
||||
@@ -0,0 +1,421 @@
|
||||
import assert from "node:assert/strict";
|
||||
import http from "node:http";
|
||||
import test from "node:test";
|
||||
import { referenceFromWire } from "../dist/references.js";
|
||||
import { create } from "@bufbuild/protobuf";
|
||||
import { createClient } from "@connectrpc/connect";
|
||||
import { connectNodeAdapter, createConnectTransport } from "@connectrpc/connect-node";
|
||||
import {
|
||||
createPackageRuntimeRoutes,
|
||||
createRuntimeContext,
|
||||
derived,
|
||||
jsToProtoValue,
|
||||
liveValue,
|
||||
protoValueToJs,
|
||||
} from "../dist/index.js";
|
||||
import {
|
||||
CaminoObjectSchema,
|
||||
CaminoService,
|
||||
CrdtValueSchema,
|
||||
StateValueSourceSchema,
|
||||
ValueSchema,
|
||||
ValueSourceSchema,
|
||||
} from "../dist/camino/api_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";
|
||||
|
||||
const listen = async (routes) => {
|
||||
const server = http.createServer((request, response) => void connectNodeAdapter({ routes })(request, response));
|
||||
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
||||
const address = server.address();
|
||||
assert.ok(address && typeof address === "object");
|
||||
return {
|
||||
url: `http://127.0.0.1:${address.port}`,
|
||||
close: async () => {
|
||||
server.closeAllConnections();
|
||||
await new Promise((resolve) => server.close(resolve));
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
test("generic values preserve nested values and object references", () => {
|
||||
const value = jsToProtoValue({
|
||||
title: "A task",
|
||||
target: referenceFromWire("obj:target"),
|
||||
tags: ["one", "two"],
|
||||
});
|
||||
assert.deepEqual(protoValueToJs(value), {
|
||||
title: "A task",
|
||||
target: referenceFromWire("obj:target"),
|
||||
tags: ["one", "two"],
|
||||
});
|
||||
});
|
||||
|
||||
test("live values preserve writable CRDT source identity through derivation", () => {
|
||||
const value = create(ValueSchema, {
|
||||
kind: { case: "stringValue", value: "notes" },
|
||||
source: create(ValueSourceSchema, {
|
||||
state: create(StateValueSourceSchema, {
|
||||
objectId: "obj:task",
|
||||
slotId: "slot:task:notes",
|
||||
revision: 7n,
|
||||
crdtSnapshot: create(CrdtValueSchema, {
|
||||
type: "quixos.automerge-document.v1",
|
||||
encoding: "automerge-snapshot-v1",
|
||||
payload: new Uint8Array([1, 2, 3]),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
const forwarded = jsToProtoValue(liveValue(value));
|
||||
assert.equal(forwarded.source?.state?.objectId, "obj:task");
|
||||
assert.equal(forwarded.source?.state?.slotId, "slot:task:notes");
|
||||
assert.equal(forwarded.source?.state?.revision, 7n);
|
||||
assert.deepEqual(forwarded.source?.state?.crdtSnapshot?.payload, new Uint8Array([1, 2, 3]));
|
||||
});
|
||||
|
||||
test("runtime context exposes only explicitly injected ports", async () => {
|
||||
const writes = [];
|
||||
const camino = {
|
||||
readState: async ({ objectId, slotId }) => ({
|
||||
value: jsToProtoValue(`${objectId}/${slotId}`),
|
||||
}),
|
||||
writeState: async (request) => {
|
||||
writes.push(request);
|
||||
return {};
|
||||
},
|
||||
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",
|
||||
}),
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
assert.equal(await context.state("port:title").get(), "obj:task/slot:task:title");
|
||||
await context.state("port:title").set("Changed");
|
||||
assert.equal(writes.length, 1);
|
||||
assert.equal("camino" in context, false);
|
||||
assert.equal("orch" in context, false);
|
||||
assert.throws(() => context.state("port:not-injected"), /Missing slotId dependency/);
|
||||
assert.throws(() => context.interface("port:title"), /Missing interfaceRevisionId dependency/);
|
||||
assert.deepEqual(await context.edge("port:children").resolve(), []);
|
||||
});
|
||||
|
||||
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",
|
||||
}),
|
||||
);
|
||||
try {
|
||||
const response = await client.invoke({
|
||||
export: create(PackageExportRefSchema, {
|
||||
packageRevisionId: "package:test@1",
|
||||
exportId: "export:test:value",
|
||||
}),
|
||||
objectId: "obj:component",
|
||||
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");
|
||||
assert.equal(reads.length, 1);
|
||||
assert.equal(reads[0]?.objectId, "obj:project");
|
||||
} finally {
|
||||
await runtimeServer.close();
|
||||
await caminoServer.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("interface views invoke a related object and propagate transitive live dependencies", async () => {
|
||||
const invocations = [];
|
||||
const sourceValue = create(ValueSchema, {
|
||||
kind: { case: "stringValue", value: "Project name" },
|
||||
source: create(ValueSourceSchema, {
|
||||
state: create(StateValueSourceSchema, {
|
||||
objectId: "obj:project",
|
||||
slotId: "slot:project:name",
|
||||
revision: 4n,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
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, {
|
||||
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" },
|
||||
}),
|
||||
],
|
||||
});
|
||||
assert.equal(response.ok, true);
|
||||
assert.equal(invocations[0]?.objectId, "obj:project");
|
||||
assert.equal(invocations[0]?.capability?.interfaceRevisionId, "interface:named@1");
|
||||
assert.equal(response.dependencies[0]?.objectId, "obj:project");
|
||||
assert.equal(response.dependencies[0]?.attachmentId, "slot:project:name");
|
||||
assert.equal(response.result?.source?.state?.revision, 4n);
|
||||
} finally {
|
||||
await runtimeServer.close();
|
||||
await orchServer.close();
|
||||
}
|
||||
});
|
||||
|
||||
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 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 initial = await stream.next();
|
||||
assert.equal(protoValueToJs(initial.value?.value), "after subscription");
|
||||
assert.equal(invocationCount, 2);
|
||||
} finally {
|
||||
controller.abort();
|
||||
await runtimeServer.close();
|
||||
await orchServer.close();
|
||||
await caminoServer.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("derived watches subscribe before reading and emit only real changes", async () => {
|
||||
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 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 initial = await stream.next();
|
||||
assert.equal(protoValueToJs(initial.value?.value), "before");
|
||||
assert.equal(initial.value?.initial, true);
|
||||
|
||||
current = "after";
|
||||
changes.shift()?.();
|
||||
const updated = await stream.next();
|
||||
assert.equal(protoValueToJs(updated.value?.value), "after");
|
||||
assert.equal(updated.value?.initial, false);
|
||||
} finally {
|
||||
controller.abort();
|
||||
await runtimeServer.close();
|
||||
await caminoServer.close();
|
||||
}
|
||||
});
|
||||
+5
-1
@@ -7,7 +7,11 @@
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"outDir": "dist"
|
||||
"types": ["node"],
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
|
||||
+6
-4
@@ -7,8 +7,8 @@
|
||||
let
|
||||
|
||||
yarnBin = fetchurl {
|
||||
url = "https://repo.yarnpkg.com/4.14.1/packages/yarnpkg-cli/bin/yarn.js";
|
||||
hash = "sha512-ZN9EgFWy03uiadfbU1pGm42pP47xFAwl/XqDwAqPuqyyFMoOAlU7kqLFTO94u2fQtIF/qwIAHfDiT6wPrMw7Qg==";
|
||||
url = "https://repo.yarnpkg.com/4.18.0/packages/yarnpkg-cli/bin/yarn.js";
|
||||
hash = "sha512-/Lhxb+fNDuzhQf/Bi5IZOp35IEwbqDGJwoiDUiP8C75kr0c7qw1emSen2utcryuwfrJ4fMkzjKBA6hJfKh8vfg==";
|
||||
};
|
||||
|
||||
cacheFolder = ".yarn/cache";
|
||||
@@ -162,13 +162,15 @@ cacheEntries = {
|
||||
"@connectrpc/connect-node@npm:2.1.2" = { filename = "@connectrpc-connect-node-npm-2.1.2-021434d5d5-ba8b0c9384.zip"; hash = "sha512-uosMk4TDgps3eqeoJtwM1Qpgk1J9LscBRgSRKDYzbqlgSitazqQrEEd/i+RWnknd7WbKD8d/X1sCcDXgKeE+qQ=="; };
|
||||
"@connectrpc/connect@npm:2.1.2" = { filename = "@connectrpc-connect-npm-2.1.2-ab34825de3-4e15000890.zip"; hash = "sha512-ThUACJAjt1Lv1E+pQKWuHh+gDhvrxLoM7ScruTWSDYw7hbd0UOZErUQruMqaJ1sMFxNviWuo7/A2F4Ex2wHWFQ=="; };
|
||||
"@types/node@npm:24.13.3" = { filename = "@types-node-npm-24.13.3-b512a0bbeb-a5bc08f49b.zip"; hash = "sha512-pbwI9JuVgdzcqQ4CzXcZejx5mECAdmSULlzVFhpVPU0q6AZPfjKUQQ10jX0Ji1wYSL5/pQwG8pxBk6sWvk5Z6w=="; };
|
||||
"@typescript/typescript-linux-arm64@npm:7.0.2" = { filename = "@typescript-typescript-linux-arm64-npm-7.0.2-9cacfc53a0-10c0.zip"; hash = "sha512-s4c7nGT/lQIw6x0IfrL0b3ECy/D0g7UoDLdiIWJoM6EGXk5N/dmXdxUdA8Cr3hV/3nO2BYKTQ6Ai8/zGhiSQ3A=="; };
|
||||
"@typescript/typescript-linux-x64@npm:7.0.2" = { filename = "@typescript-typescript-linux-x64-npm-7.0.2-8dd7ff8d24-10c0.zip"; hash = "sha512-k9EUK5CZ3OOPnyslp8SAAonHJpnpPmlaulppI/NmFyCzNs3UN/TLPUkyQia3KIxgbyTzKoXI5L5fl8Uj9bJ7Cg=="; };
|
||||
"@typescript/vfs@npm:1.6.4" = { filename = "@typescript-vfs-npm-1.6.4-78935c9d3e-acb9de42f2.zip"; hash = "sha512-rLneQvI/2j9149eQC6EG7zI6L0588OSpTbtFfibTU8pjuzUZPtGjL8hzPzrlkJlhKykLBr1iIWlIYb65v7YvYg=="; };
|
||||
"debug@npm:4.4.3" = { filename = "debug-npm-4.4.3-0105c6123a-d79136ec6c.zip"; hash = "sha512-15E27GyD7L79D2pVk9pqnJHsTX3cS1TIg9bnHsmsy19noaXpbQCjKBlrW1yG02XpjYo6cIVqrxa057GYXmf1pg=="; };
|
||||
"ms@npm:2.1.3" = { filename = "ms-npm-2.1.3-81ff3cfac1-d924b57e73.zip"; hash = "sha512-2SS1fnMSs7Y60h/Fs9wK9eeNYaH8fPtUV+2vJjJr9ivlMHzIf/toYu8cKzOwIzzbXU8BxMlYzA1mCUi2Wih6SA=="; };
|
||||
"typescript@npm:5.4.5" = { filename = "typescript-npm-5.4.5-8568a42232-2954022ada.zip"; hash = "sha512-KVQCKto0D9PWqeK45TT2XVfJLV85iaJjdUp4q6VJ9+ZSmswZIZE1YKS4FsRtzn30pNKfnxGj3A1CE7t20EMlHg=="; };
|
||||
"typescript@npm:5.9.3" = { filename = "typescript-npm-5.9.3-48715be868-6bd7552ce3.zip"; hash = "sha512-a9dVLOOfl+cR21qgSPb5mVtT8cUvfYZnwavcFwDGinajCPV5zTCc5rU2Rt606aG+fIE6k7qvCijM1TajAnDhxQ=="; };
|
||||
"typescript@npm:7.0.2" = { filename = "typescript-npm-7.0.2-0bde2bcec5-3dcee51ec8.zip"; hash = "sha512-Pc7lHsjDMkkjJbzb999ItmZodR8SfmIq59QbbHFusZGEQkpF4U93UPUPNAIyOItp5ih4WRVfBqXOLfdvEssxzw=="; };
|
||||
"typescript@patch:typescript@npm%3A5.4.5#optional!builtin<compat/typescript>::version=5.4.5&hash=5adc0c" = { filename = "typescript-patch-6e159bfddb-db2ad2a16c.zip"; hash = "sha512-2yrSoWyoKfUEJ+6x2hVeekXlmO7HsIbYtOi6ROWiNfdY5gbWgcZpkiMNP8O4mVhl5f0LIqLJVIbQsyAPgwcuyQ=="; };
|
||||
"typescript@patch:typescript@npm%3A5.9.3#optional!builtin<compat/typescript>::version=5.9.3&hash=5786d5" = { filename = "typescript-patch-6fda4d02cf-ad09fdf7a7.zip"; hash = "sha512-rQn996dWgU3OZbxgwWV7QNREUTRoWO6iMOEPLpWiidkYO24y5cEelazAzMIUtPNiidytS/GIawrbhNcR0zakMA=="; };
|
||||
"typescript@patch:typescript@npm%3A7.0.2#optional!builtin<compat/typescript>::version=7.0.2&hash=3bafbf" = { filename = "typescript-patch-4859cbaf66-6b3cdc369c.zip"; hash = "sha512-azzcNpzYKdRuAHNOpkIz7oRBnCglrY/kCJFa3ed6vO1LeiQB9+7VF9VKek9dHBhpdTy5kBjfHCFZx2HZ8zSDpg=="; };
|
||||
"undici-types@npm:7.18.2" = { filename = "undici-types-npm-7.18.2-3e6d69d829-85a7918911.zip"; hash = "sha512-haeRiRE6I4lZ16ZHNo5PfFVZw6QE69uPxEiBRc6UJvzYIlKoRKMCeY38Djfm+xeP9IHtA7xMr2NMV1fZ70NSHQ=="; };
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Manual changes might be lost - proceed with caution!
|
||||
|
||||
__metadata:
|
||||
version: 9
|
||||
version: 10
|
||||
cacheKey: 10c0
|
||||
|
||||
"@bufbuild/protobuf@npm:2.12.1, @bufbuild/protobuf@npm:^2.12.1":
|
||||
@@ -68,7 +68,7 @@ __metadata:
|
||||
"@connectrpc/connect": "npm:^2.1.2"
|
||||
"@connectrpc/connect-node": "npm:^2.1.2"
|
||||
"@types/node": "npm:^24"
|
||||
typescript: "npm:^5.9.3"
|
||||
typescript: "npm:^7.0.2"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@@ -81,6 +81,146 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-aix-ppc64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-aix-ppc64@npm:7.0.2"
|
||||
conditions: os=aix & cpu=ppc64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-darwin-arm64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-darwin-arm64@npm:7.0.2"
|
||||
conditions: os=darwin & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-darwin-x64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-darwin-x64@npm:7.0.2"
|
||||
conditions: os=darwin & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-freebsd-arm64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-freebsd-arm64@npm:7.0.2"
|
||||
conditions: os=freebsd & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-freebsd-x64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-freebsd-x64@npm:7.0.2"
|
||||
conditions: os=freebsd & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-linux-arm64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-linux-arm64@npm:7.0.2"
|
||||
conditions: os=linux & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-linux-arm@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-linux-arm@npm:7.0.2"
|
||||
conditions: os=linux & cpu=arm
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-linux-loong64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-linux-loong64@npm:7.0.2"
|
||||
conditions: os=linux & cpu=loong64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-linux-mips64el@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-linux-mips64el@npm:7.0.2"
|
||||
conditions: os=linux & cpu=mips64el
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-linux-ppc64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-linux-ppc64@npm:7.0.2"
|
||||
conditions: os=linux & cpu=ppc64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-linux-riscv64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-linux-riscv64@npm:7.0.2"
|
||||
conditions: os=linux & cpu=riscv64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-linux-s390x@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-linux-s390x@npm:7.0.2"
|
||||
conditions: os=linux & cpu=s390x
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-linux-x64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-linux-x64@npm:7.0.2"
|
||||
conditions: os=linux & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-netbsd-arm64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-netbsd-arm64@npm:7.0.2"
|
||||
conditions: os=netbsd & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-netbsd-x64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-netbsd-x64@npm:7.0.2"
|
||||
conditions: os=netbsd & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-openbsd-arm64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-openbsd-arm64@npm:7.0.2"
|
||||
conditions: os=openbsd & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-openbsd-x64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-openbsd-x64@npm:7.0.2"
|
||||
conditions: os=openbsd & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-sunos-x64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-sunos-x64@npm:7.0.2"
|
||||
conditions: os=sunos & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-win32-arm64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-win32-arm64@npm:7.0.2"
|
||||
conditions: os=win32 & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/typescript-win32-x64@npm:7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "@typescript/typescript-win32-x64@npm:7.0.2"
|
||||
conditions: os=win32 & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/vfs@npm:^1.6.2":
|
||||
version: 1.6.4
|
||||
resolution: "@typescript/vfs@npm:1.6.4"
|
||||
@@ -121,13 +261,74 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@npm:^5.9.3":
|
||||
version: 5.9.3
|
||||
resolution: "typescript@npm:5.9.3"
|
||||
"typescript@npm:^7.0.2":
|
||||
version: 7.0.2
|
||||
resolution: "typescript@npm:7.0.2"
|
||||
dependencies:
|
||||
"@typescript/typescript-aix-ppc64": "npm:7.0.2"
|
||||
"@typescript/typescript-darwin-arm64": "npm:7.0.2"
|
||||
"@typescript/typescript-darwin-x64": "npm:7.0.2"
|
||||
"@typescript/typescript-freebsd-arm64": "npm:7.0.2"
|
||||
"@typescript/typescript-freebsd-x64": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-arm": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-arm64": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-loong64": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-mips64el": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-ppc64": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-riscv64": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-s390x": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-x64": "npm:7.0.2"
|
||||
"@typescript/typescript-netbsd-arm64": "npm:7.0.2"
|
||||
"@typescript/typescript-netbsd-x64": "npm:7.0.2"
|
||||
"@typescript/typescript-openbsd-arm64": "npm:7.0.2"
|
||||
"@typescript/typescript-openbsd-x64": "npm:7.0.2"
|
||||
"@typescript/typescript-sunos-x64": "npm:7.0.2"
|
||||
"@typescript/typescript-win32-arm64": "npm:7.0.2"
|
||||
"@typescript/typescript-win32-x64": "npm:7.0.2"
|
||||
dependenciesMeta:
|
||||
"@typescript/typescript-aix-ppc64":
|
||||
optional: true
|
||||
"@typescript/typescript-darwin-arm64":
|
||||
optional: true
|
||||
"@typescript/typescript-darwin-x64":
|
||||
optional: true
|
||||
"@typescript/typescript-freebsd-arm64":
|
||||
optional: true
|
||||
"@typescript/typescript-freebsd-x64":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-arm":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-arm64":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-loong64":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-mips64el":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-ppc64":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-riscv64":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-s390x":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-x64":
|
||||
optional: true
|
||||
"@typescript/typescript-netbsd-arm64":
|
||||
optional: true
|
||||
"@typescript/typescript-netbsd-x64":
|
||||
optional: true
|
||||
"@typescript/typescript-openbsd-arm64":
|
||||
optional: true
|
||||
"@typescript/typescript-openbsd-x64":
|
||||
optional: true
|
||||
"@typescript/typescript-sunos-x64":
|
||||
optional: true
|
||||
"@typescript/typescript-win32-arm64":
|
||||
optional: true
|
||||
"@typescript/typescript-win32-x64":
|
||||
optional: true
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 10c0/6bd7552ce39f97e711db5aa048f6f9995b53f1c52f7d8667c1abdc1700c68a76a308f579cd309ce6b53646deb4e9a1be7c813a93baaf0a28ccd536a30270e1c5
|
||||
checksum: 10c0/3dcee51ec8c332492325bcdbf7df48b66668751f127e622ae7d41b6c716eb19184424a45e14f7750f50f340232388b69e6287859155f06a5ce2df76f12cb31cf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -141,13 +342,74 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@npm%3A^5.9.3#optional!builtin<compat/typescript>":
|
||||
version: 5.9.3
|
||||
resolution: "typescript@patch:typescript@npm%3A5.9.3#optional!builtin<compat/typescript>::version=5.9.3&hash=5786d5"
|
||||
"typescript@patch:typescript@npm%3A^7.0.2#optional!builtin<compat/typescript>":
|
||||
version: 7.0.2
|
||||
resolution: "typescript@patch:typescript@npm%3A7.0.2#optional!builtin<compat/typescript>::version=7.0.2&hash=3bafbf"
|
||||
dependencies:
|
||||
"@typescript/typescript-aix-ppc64": "npm:7.0.2"
|
||||
"@typescript/typescript-darwin-arm64": "npm:7.0.2"
|
||||
"@typescript/typescript-darwin-x64": "npm:7.0.2"
|
||||
"@typescript/typescript-freebsd-arm64": "npm:7.0.2"
|
||||
"@typescript/typescript-freebsd-x64": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-arm": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-arm64": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-loong64": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-mips64el": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-ppc64": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-riscv64": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-s390x": "npm:7.0.2"
|
||||
"@typescript/typescript-linux-x64": "npm:7.0.2"
|
||||
"@typescript/typescript-netbsd-arm64": "npm:7.0.2"
|
||||
"@typescript/typescript-netbsd-x64": "npm:7.0.2"
|
||||
"@typescript/typescript-openbsd-arm64": "npm:7.0.2"
|
||||
"@typescript/typescript-openbsd-x64": "npm:7.0.2"
|
||||
"@typescript/typescript-sunos-x64": "npm:7.0.2"
|
||||
"@typescript/typescript-win32-arm64": "npm:7.0.2"
|
||||
"@typescript/typescript-win32-x64": "npm:7.0.2"
|
||||
dependenciesMeta:
|
||||
"@typescript/typescript-aix-ppc64":
|
||||
optional: true
|
||||
"@typescript/typescript-darwin-arm64":
|
||||
optional: true
|
||||
"@typescript/typescript-darwin-x64":
|
||||
optional: true
|
||||
"@typescript/typescript-freebsd-arm64":
|
||||
optional: true
|
||||
"@typescript/typescript-freebsd-x64":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-arm":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-arm64":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-loong64":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-mips64el":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-ppc64":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-riscv64":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-s390x":
|
||||
optional: true
|
||||
"@typescript/typescript-linux-x64":
|
||||
optional: true
|
||||
"@typescript/typescript-netbsd-arm64":
|
||||
optional: true
|
||||
"@typescript/typescript-netbsd-x64":
|
||||
optional: true
|
||||
"@typescript/typescript-openbsd-arm64":
|
||||
optional: true
|
||||
"@typescript/typescript-openbsd-x64":
|
||||
optional: true
|
||||
"@typescript/typescript-sunos-x64":
|
||||
optional: true
|
||||
"@typescript/typescript-win32-arm64":
|
||||
optional: true
|
||||
"@typescript/typescript-win32-x64":
|
||||
optional: true
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 10c0/ad09fdf7a756814dce65bc60c1657b40d44451346858eea230e10f2e95a289d9183b6e32e5c11e95acc0ccc214b4f36289dcad4bf1886b0adb84d711d336a430
|
||||
checksum: 10c0/6b3cdc369cd829d46e00734ea64233ee84419c2825ad8fe408915adde77abced4b7a2401f7eed517d54a7a4f5d1c1869753cb99018df1c2159c761d9f33483a6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user