Add Camino service-backed custom fields

This commit is contained in:
Timothy J. Aveni
2026-07-12 11:24:33 -07:00
parent c9202ed56c
commit b343e91078
3 changed files with 242 additions and 19 deletions
+52 -6
View File
@@ -34,6 +34,7 @@ export type CaminoClient = Client<typeof CaminoService>;
export type { InvokeRequest, Value };
export type Field<T> = {
get(): Promise<T | undefined>;
set(value: T): Promise<void>;
};
@@ -41,9 +42,25 @@ export type RuntimeHandler<Context> = (
context: Context,
) => Promise<unknown> | unknown;
export type FieldOperation<Context> = {
get?: RuntimeHandler<Context>;
set?: RuntimeHandler<Context>;
watchStart?: RuntimeHandler<Context>;
watchStop?: RuntimeHandler<Context>;
};
export const fieldOps = <Context>(
operation: FieldOperation<Context>,
): FieldOperation<Context> => operation;
export const derivedWithDeps = <Context>(operation: {
get: RuntimeHandler<Context>;
}): FieldOperation<Context> => fieldOps(operation);
export type RuntimeFunctionSpec<ExportName extends string = string> = {
exportName: ExportName;
symbol: string;
operation?: string;
};
const isRecord = (value: unknown): value is Record<string, unknown> =>
@@ -203,6 +220,10 @@ export const createField = <T>(
objectId: string,
fieldName: string,
): Field<T> => ({
async get() {
const response = await camino.getObject({ objectId });
return protoValueToJs(response.object?.fields[fieldName]) as T | undefined;
},
async set(value) {
await camino.setField({
objectId,
@@ -221,7 +242,9 @@ export const serveQuixosPackageRuntime = <
runtimeProtocolVersion: string;
functions: Spec;
implementation: {
[Name in Spec[number]["exportName"]]: RuntimeHandler<Context>;
[Name in Spec[number]["exportName"]]:
| RuntimeHandler<Context>
| FieldOperation<Context>;
};
createContext: (camino: CaminoClient, request: InvokeRequest) => Context;
}) => {
@@ -242,6 +265,7 @@ export const serveQuixosPackageRuntime = <
packageNamespace: params.packageNamespace,
packageName: params.packageName,
symbol: entry.symbol,
operation: entry.operation ?? "",
}),
);
@@ -261,19 +285,41 @@ export const serveQuixosPackageRuntime = <
try {
const symbol = request.function?.symbol ?? "";
const spec = params.functions.find(
(entry) => entry.symbol === symbol,
(entry) =>
entry.symbol === symbol &&
(entry.operation ?? "") === (request.function?.operation ?? ""),
);
if (!spec) {
throw new Error(
`Unknown ${params.packageName} function: ${symbol}`,
`Unknown ${params.packageName} function: ${symbol}${
request.function?.operation
? `.${request.function.operation}`
: ""
}`,
);
}
const runtimeFunction = (
params.implementation as Record<string, RuntimeHandler<Context>>
const implementationExport = (
params.implementation as Record<
string,
RuntimeHandler<Context> | FieldOperation<Context>
>
)[spec.exportName];
const runtimeFunction =
spec.operation && typeof implementationExport === "object"
? implementationExport[spec.operation as keyof FieldOperation<Context>]
: implementationExport;
if (!runtimeFunction) {
throw new Error(
`Missing ${params.packageName} implementation export: ${spec.exportName}`,
`Missing ${params.packageName} implementation export: ${spec.exportName}${
spec.operation ? `.${spec.operation}` : ""
}`,
);
}
if (typeof runtimeFunction !== "function") {
throw new Error(
`${params.packageName} implementation export is not callable: ${spec.exportName}${
spec.operation ? `.${spec.operation}` : ""
}`,
);
}
return create(InvokeResponseSchema, {