From b343e910780fe5c60e9291d015fb4d0a3f00e427 Mon Sep 17 00:00:00 2001 From: "Timothy J. Aveni" Date: Sun, 12 Jul 2026 11:24:33 -0700 Subject: [PATCH] Add Camino service-backed custom fields --- src/camino/schema_pb.ts | 196 +++++++++++++++++++++++++++++++++++++--- src/index.ts | 58 ++++++++++-- src/quixos/refs_pb.ts | 7 +- 3 files changed, 242 insertions(+), 19 deletions(-) diff --git a/src/camino/schema_pb.ts b/src/camino/schema_pb.ts index 44a9aac..c9729b2 100644 --- a/src/camino/schema_pb.ts +++ b/src/camino/schema_pb.ts @@ -12,7 +12,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file camino/schema.proto. */ export const file_camino_schema: GenFile = /*@__PURE__*/ - fileDesc("ChNjYW1pbm8vc2NoZW1hLnByb3RvEgZjYW1pbm8iSwoJU3ltYm9sUmVmEhEKCW5hbWVzcGFjZRgBIAEoCRIMCgRuYW1lGAIgASgJEg8KB3ZlcnNpb24YAyABKAkSDAoEaGFzaBgEIAEoCSIYCgNSZWYSEQoJb2JqZWN0X2lkGAEgASgJIhsKCENyZHRUZXh0Eg8KB3BheWxvYWQYASABKAwiHwoMQ3JkdFJpY2hUZXh0Eg8KB3BheWxvYWQYASABKAwiGwoIQ3JkdEpzb24SDwoHcGF5bG9hZBgBIAEoDCKDAgoLQ2xhc3NTY2hlbWESHQoCaWQYASABKAsyES5jYW1pbm8uU3ltYm9sUmVmEg8KB3ZlcnNpb24YAiABKA0SIwoGZmllbGRzGAMgAygLMhMuY2FtaW5vLkZpZWxkU2NoZW1hEiEKBWVkZ2VzGAQgAygLMhIuY2FtaW5vLkVkZ2VTY2hlbWESJQoHbWV0aG9kcxgFIAMoCzIULmNhbWluby5NZXRob2RTY2hlbWESKQoKbWlncmF0aW9ucxgGIAMoCzIVLmNhbWluby5NaWdyYXRpb25TcGVjEhMKC3NvdXJjZV9maWxlGAcgASgJEhUKDXByb3RvX21lc3NhZ2UYCCABKAkivgEKC0ZpZWxkU2NoZW1hEgwKBG5hbWUYASABKAkSCwoDdGFnGAIgASgNEh0KBHR5cGUYAyABKAsyDy5jYW1pbm8uVHlwZVJlZhIqCghjb25mbGljdBgEIAEoDjIYLmNhbWluby5Db25mbGljdFN0cmF0ZWd5EhAKCHJlcGVhdGVkGAUgASgIEhAKCG9wdGlvbmFsGAYgASgIEiUKB3N0b3JhZ2UYByABKAsyFC5jYW1pbm8uRmllbGRTdG9yYWdlImwKDEZpZWxkU3RvcmFnZRImCgRraW5kGAEgASgOMhguY2FtaW5vLkZpZWxkU3RvcmFnZUtpbmQSJQoIcmVzb2x2ZXIYAiABKAsyEy5xdWl4b3MuRnVuY3Rpb25SZWYSDQoFY2FjaGUYAyABKAgiQAoHVHlwZVJlZhISCgpwcm90b190eXBlGAEgASgJEiEKBnN5bWJvbBgCIAEoCzIRLmNhbWluby5TeW1ib2xSZWYi7QEKCkVkZ2VTY2hlbWESHQoCaWQYASABKAsyES5jYW1pbm8uU3ltYm9sUmVmEhQKDHNvdXJjZV9maWVsZBgCIAEoCRIlCgpmcm9tX2NsYXNzGAMgASgLMhEuY2FtaW5vLlN5bWJvbFJlZhIjCgh0b19jbGFzcxgEIAEoCzIRLmNhbWluby5TeW1ib2xSZWYSKAoLY2FyZGluYWxpdHkYBSABKA4yEy5jYW1pbm8uQ2FyZGluYWxpdHkSDwoHaW52ZXJzZRgGIAEoCRIjCgZmaWVsZHMYByADKAsyEy5jYW1pbm8uRmllbGRTY2hlbWEiQwoMTWV0aG9kU2NoZW1hEgwKBG5hbWUYASABKAkSJQoIZnVuY3Rpb24YAiABKAsyEy5xdWl4b3MuRnVuY3Rpb25SZWYiYAoNTWlncmF0aW9uU3BlYxIUCgxmcm9tX3ZlcnNpb24YASABKA0SEgoKdG9fdmVyc2lvbhgCIAEoDRIlCghmdW5jdGlvbhgDIAEoCzITLnF1aXhvcy5GdW5jdGlvblJlZiKbAQoRRG9jUmVmRGVjbGFyYXRpb24SEgoKbG9jYWxfbmFtZRgBIAEoCRIfCgR0eXBlGAIgASgLMhEuY2FtaW5vLlN5bWJvbFJlZhInCgx0YXJnZXRfY2xhc3MYAyABKAsyES5jYW1pbm8uU3ltYm9sUmVmEigKCHN0cmVuZ3RoGAQgASgOMhYuY2FtaW5vLkRvY1JlZlN0cmVuZ3RoKmQKEENvbmZsaWN0U3RyYXRlZ3kSIQodQ09ORkxJQ1RfU1RSQVRFR1lfVU5TUEVDSUZJRUQQABILCgdSRVBMQUNFEAESFgoSUFJFU0VSVkVfQ09ORkxJQ1RTEAISCAoEQ1JEVBADKnoKC0NhcmRpbmFsaXR5EhsKF0NBUkRJTkFMSVRZX1VOU1BFQ0lGSUVEEAASEAoMT1BUSU9OQUxfT05FEAESDwoLRVhBQ1RMWV9PTkUQAhIICgRNQU5ZEAMSDwoLTUFOWV9VTklRVUUQBBIQCgxNQU5ZX09SREVSRUQQBSpUCg5Eb2NSZWZTdHJlbmd0aBIgChxET0NfUkVGX1NUUkVOR1RIX1VOU1BFQ0lGSUVEEAASDAoIU09GVF9SRUYQARISCg5QUk9KRUNURURfRURHRRACKmcKEEZpZWxkU3RvcmFnZUtpbmQSIgoeRklFTERfU1RPUkFHRV9LSU5EX1VOU1BFQ0lGSUVEEAASCgoGU1RPUkVEEAESCwoHREVSSVZFRBACEggKBExBWlkQAxIMCghFWFRFUk5BTBAEYgZwcm90bzM", [file_quixos_refs]); + fileDesc("ChNjYW1pbm8vc2NoZW1hLnByb3RvEgZjYW1pbm8iSwoJU3ltYm9sUmVmEhEKCW5hbWVzcGFjZRgBIAEoCRIMCgRuYW1lGAIgASgJEg8KB3ZlcnNpb24YAyABKAkSDAoEaGFzaBgEIAEoCSIYCgNSZWYSEQoJb2JqZWN0X2lkGAEgASgJIg0KC0N1c3RvbUZpZWxkIiQKEFdhdGNoU3RhcnRSZXN1bHQSEAoId2F0Y2hfaWQYASABKAkiJAoQV2F0Y2hTdG9wUmVxdWVzdBIQCgh3YXRjaF9pZBgBIAEoCSIRCg9XYXRjaFN0b3BSZXN1bHQiGwoIQ3JkdFRleHQSDwoHcGF5bG9hZBgBIAEoDCIfCgxDcmR0UmljaFRleHQSDwoHcGF5bG9hZBgBIAEoDCIbCghDcmR0SnNvbhIPCgdwYXlsb2FkGAEgASgMIr8CCgtDbGFzc1NjaGVtYRIdCgJpZBgBIAEoCzIRLmNhbWluby5TeW1ib2xSZWYSDwoHdmVyc2lvbhgCIAEoDRIjCgZmaWVsZHMYAyADKAsyEy5jYW1pbm8uRmllbGRTY2hlbWESIQoFZWRnZXMYBCADKAsyEi5jYW1pbm8uRWRnZVNjaGVtYRIlCgdtZXRob2RzGAUgAygLMhQuY2FtaW5vLk1ldGhvZFNjaGVtYRIpCgptaWdyYXRpb25zGAYgAygLMhUuY2FtaW5vLk1pZ3JhdGlvblNwZWMSEwoLc291cmNlX2ZpbGUYByABKAkSFQoNcHJvdG9fbWVzc2FnZRgIIAEoCRI6ChJvcGVyYXRpb25fc2VydmljZXMYCSADKAsyHi5jYW1pbm8uT3BlcmF0aW9uU2VydmljZVNjaGVtYSLdAQoLRmllbGRTY2hlbWESDAoEbmFtZRgBIAEoCRILCgN0YWcYAiABKA0SHQoEdHlwZRgDIAEoCzIPLmNhbWluby5UeXBlUmVmEioKCGNvbmZsaWN0GAQgASgOMhguY2FtaW5vLkNvbmZsaWN0U3RyYXRlZ3kSEAoIcmVwZWF0ZWQYBSABKAgSEAoIb3B0aW9uYWwYBiABKAgSJQoHc3RvcmFnZRgHIAEoCzIULmNhbWluby5GaWVsZFN0b3JhZ2USHQoDb3BzGAggASgLMhAuY2FtaW5vLkZpZWxkT3BzImwKDEZpZWxkU3RvcmFnZRImCgRraW5kGAEgASgOMhguY2FtaW5vLkZpZWxkU3RvcmFnZUtpbmQSJQoIcmVzb2x2ZXIYAiABKAsyEy5xdWl4b3MuRnVuY3Rpb25SZWYSDQoFY2FjaGUYAyABKAgiQAoHVHlwZVJlZhISCgpwcm90b190eXBlGAEgASgJEiEKBnN5bWJvbBgCIAEoCzIRLmNhbWluby5TeW1ib2xSZWYiUAoIRmllbGRPcHMSMwoOaW1wbGVtZW50YXRpb24YASABKA4yGy5jYW1pbm8uRmllbGRJbXBsZW1lbnRhdGlvbhIPCgdzZXJ2aWNlGAIgASgJIu0BCgpFZGdlU2NoZW1hEh0KAmlkGAEgASgLMhEuY2FtaW5vLlN5bWJvbFJlZhIUCgxzb3VyY2VfZmllbGQYAiABKAkSJQoKZnJvbV9jbGFzcxgDIAEoCzIRLmNhbWluby5TeW1ib2xSZWYSIwoIdG9fY2xhc3MYBCABKAsyES5jYW1pbm8uU3ltYm9sUmVmEigKC2NhcmRpbmFsaXR5GAUgASgOMhMuY2FtaW5vLkNhcmRpbmFsaXR5Eg8KB2ludmVyc2UYBiABKAkSIwoGZmllbGRzGAcgAygLMhMuY2FtaW5vLkZpZWxkU2NoZW1hIkMKDE1ldGhvZFNjaGVtYRIMCgRuYW1lGAEgASgJEiUKCGZ1bmN0aW9uGAIgASgLMhMucXVpeG9zLkZ1bmN0aW9uUmVmImAKDU1pZ3JhdGlvblNwZWMSFAoMZnJvbV92ZXJzaW9uGAEgASgNEhIKCnRvX3ZlcnNpb24YAiABKA0SJQoIZnVuY3Rpb24YAyABKAsyEy5xdWl4b3MuRnVuY3Rpb25SZWYikQEKD09wZXJhdGlvblNjaGVtYRIMCgRuYW1lGAEgASgJEiMKCmlucHV0X3R5cGUYAiABKAsyDy5jYW1pbm8uVHlwZVJlZhIkCgtvdXRwdXRfdHlwZRgDIAEoCzIPLmNhbWluby5UeXBlUmVmEiUKCGZ1bmN0aW9uGAQgASgLMhMucXVpeG9zLkZ1bmN0aW9uUmVmImYKFk9wZXJhdGlvblNlcnZpY2VTY2hlbWESDAoEbmFtZRgBIAEoCRIRCglmdWxsX25hbWUYAiABKAkSKwoKb3BlcmF0aW9ucxgDIAMoCzIXLmNhbWluby5PcGVyYXRpb25TY2hlbWEimwEKEURvY1JlZkRlY2xhcmF0aW9uEhIKCmxvY2FsX25hbWUYASABKAkSHwoEdHlwZRgCIAEoCzIRLmNhbWluby5TeW1ib2xSZWYSJwoMdGFyZ2V0X2NsYXNzGAMgASgLMhEuY2FtaW5vLlN5bWJvbFJlZhIoCghzdHJlbmd0aBgEIAEoDjIWLmNhbWluby5Eb2NSZWZTdHJlbmd0aCpkChBDb25mbGljdFN0cmF0ZWd5EiEKHUNPTkZMSUNUX1NUUkFURUdZX1VOU1BFQ0lGSUVEEAASCwoHUkVQTEFDRRABEhYKElBSRVNFUlZFX0NPTkZMSUNUUxACEggKBENSRFQQAyp6CgtDYXJkaW5hbGl0eRIbChdDQVJESU5BTElUWV9VTlNQRUNJRklFRBAAEhAKDE9QVElPTkFMX09ORRABEg8KC0VYQUNUTFlfT05FEAISCAoETUFOWRADEg8KC01BTllfVU5JUVVFEAQSEAoMTUFOWV9PUkRFUkVEEAUqVAoORG9jUmVmU3RyZW5ndGgSIAocRE9DX1JFRl9TVFJFTkdUSF9VTlNQRUNJRklFRBAAEgwKCFNPRlRfUkVGEAESEgoOUFJPSkVDVEVEX0VER0UQAipnChBGaWVsZFN0b3JhZ2VLaW5kEiIKHkZJRUxEX1NUT1JBR0VfS0lORF9VTlNQRUNJRklFRBAAEgoKBlNUT1JFRBABEgsKB0RFUklWRUQQAhIICgRMQVpZEAMSDAoIRVhURVJOQUwQBCpIChNGaWVsZEltcGxlbWVudGF0aW9uEiQKIEZJRUxEX0lNUExFTUVOVEFUSU9OX1VOU1BFQ0lGSUVEEAASCwoHU0VSVklDRRABYgZwcm90bzM", [file_quixos_refs]); /** * @generated from message camino.SymbolRef @@ -63,6 +63,66 @@ export type Ref = Message<"camino.Ref"> & { export const RefSchema: GenMessage = /*@__PURE__*/ messageDesc(file_camino_schema, 1); +/** + * @generated from message camino.CustomField + */ +export type CustomField = Message<"camino.CustomField"> & { +}; + +/** + * Describes the message camino.CustomField. + * Use `create(CustomFieldSchema)` to create a new message. + */ +export const CustomFieldSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_camino_schema, 2); + +/** + * @generated from message camino.WatchStartResult + */ +export type WatchStartResult = Message<"camino.WatchStartResult"> & { + /** + * @generated from field: string watch_id = 1; + */ + watchId: string; +}; + +/** + * Describes the message camino.WatchStartResult. + * Use `create(WatchStartResultSchema)` to create a new message. + */ +export const WatchStartResultSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_camino_schema, 3); + +/** + * @generated from message camino.WatchStopRequest + */ +export type WatchStopRequest = Message<"camino.WatchStopRequest"> & { + /** + * @generated from field: string watch_id = 1; + */ + watchId: string; +}; + +/** + * Describes the message camino.WatchStopRequest. + * Use `create(WatchStopRequestSchema)` to create a new message. + */ +export const WatchStopRequestSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_camino_schema, 4); + +/** + * @generated from message camino.WatchStopResult + */ +export type WatchStopResult = Message<"camino.WatchStopResult"> & { +}; + +/** + * Describes the message camino.WatchStopResult. + * Use `create(WatchStopResultSchema)` to create a new message. + */ +export const WatchStopResultSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_camino_schema, 5); + /** * @generated from message camino.CrdtText */ @@ -78,7 +138,7 @@ export type CrdtText = Message<"camino.CrdtText"> & { * Use `create(CrdtTextSchema)` to create a new message. */ export const CrdtTextSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_schema, 2); + messageDesc(file_camino_schema, 6); /** * @generated from message camino.CrdtRichText @@ -95,7 +155,7 @@ export type CrdtRichText = Message<"camino.CrdtRichText"> & { * Use `create(CrdtRichTextSchema)` to create a new message. */ export const CrdtRichTextSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_schema, 3); + messageDesc(file_camino_schema, 7); /** * @generated from message camino.CrdtJson @@ -112,7 +172,7 @@ export type CrdtJson = Message<"camino.CrdtJson"> & { * Use `create(CrdtJsonSchema)` to create a new message. */ export const CrdtJsonSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_schema, 4); + messageDesc(file_camino_schema, 8); /** * @generated from message camino.ClassSchema @@ -157,6 +217,11 @@ export type ClassSchema = Message<"camino.ClassSchema"> & { * @generated from field: string proto_message = 8; */ protoMessage: string; + + /** + * @generated from field: repeated camino.OperationServiceSchema operation_services = 9; + */ + operationServices: OperationServiceSchema[]; }; /** @@ -164,7 +229,7 @@ export type ClassSchema = Message<"camino.ClassSchema"> & { * Use `create(ClassSchemaSchema)` to create a new message. */ export const ClassSchemaSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_schema, 5); + messageDesc(file_camino_schema, 9); /** * @generated from message camino.FieldSchema @@ -204,6 +269,11 @@ export type FieldSchema = Message<"camino.FieldSchema"> & { * @generated from field: camino.FieldStorage storage = 7; */ storage?: FieldStorage | undefined; + + /** + * @generated from field: camino.FieldOps ops = 8; + */ + ops?: FieldOps | undefined; }; /** @@ -211,7 +281,7 @@ export type FieldSchema = Message<"camino.FieldSchema"> & { * Use `create(FieldSchemaSchema)` to create a new message. */ export const FieldSchemaSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_schema, 6); + messageDesc(file_camino_schema, 10); /** * @generated from message camino.FieldStorage @@ -238,7 +308,7 @@ export type FieldStorage = Message<"camino.FieldStorage"> & { * Use `create(FieldStorageSchema)` to create a new message. */ export const FieldStorageSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_schema, 7); + messageDesc(file_camino_schema, 11); /** * @generated from message camino.TypeRef @@ -260,7 +330,29 @@ export type TypeRef = Message<"camino.TypeRef"> & { * Use `create(TypeRefSchema)` to create a new message. */ export const TypeRefSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_schema, 8); + messageDesc(file_camino_schema, 12); + +/** + * @generated from message camino.FieldOps + */ +export type FieldOps = Message<"camino.FieldOps"> & { + /** + * @generated from field: camino.FieldImplementation implementation = 1; + */ + implementation: FieldImplementation; + + /** + * @generated from field: string service = 2; + */ + service: string; +}; + +/** + * Describes the message camino.FieldOps. + * Use `create(FieldOpsSchema)` to create a new message. + */ +export const FieldOpsSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_camino_schema, 13); /** * @generated from message camino.EdgeSchema @@ -307,7 +399,7 @@ export type EdgeSchema = Message<"camino.EdgeSchema"> & { * Use `create(EdgeSchemaSchema)` to create a new message. */ export const EdgeSchemaSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_schema, 9); + messageDesc(file_camino_schema, 14); /** * @generated from message camino.MethodSchema @@ -329,7 +421,7 @@ export type MethodSchema = Message<"camino.MethodSchema"> & { * Use `create(MethodSchemaSchema)` to create a new message. */ export const MethodSchemaSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_schema, 10); + messageDesc(file_camino_schema, 15); /** * @generated from message camino.MigrationSpec @@ -356,7 +448,66 @@ export type MigrationSpec = Message<"camino.MigrationSpec"> & { * Use `create(MigrationSpecSchema)` to create a new message. */ export const MigrationSpecSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_schema, 11); + messageDesc(file_camino_schema, 16); + +/** + * @generated from message camino.OperationSchema + */ +export type OperationSchema = Message<"camino.OperationSchema"> & { + /** + * @generated from field: string name = 1; + */ + name: string; + + /** + * @generated from field: camino.TypeRef input_type = 2; + */ + inputType?: TypeRef | undefined; + + /** + * @generated from field: camino.TypeRef output_type = 3; + */ + outputType?: TypeRef | undefined; + + /** + * @generated from field: quixos.FunctionRef function = 4; + */ + function?: FunctionRef | undefined; +}; + +/** + * Describes the message camino.OperationSchema. + * Use `create(OperationSchemaSchema)` to create a new message. + */ +export const OperationSchemaSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_camino_schema, 17); + +/** + * @generated from message camino.OperationServiceSchema + */ +export type OperationServiceSchema = Message<"camino.OperationServiceSchema"> & { + /** + * @generated from field: string name = 1; + */ + name: string; + + /** + * @generated from field: string full_name = 2; + */ + fullName: string; + + /** + * @generated from field: repeated camino.OperationSchema operations = 3; + */ + operations: OperationSchema[]; +}; + +/** + * Describes the message camino.OperationServiceSchema. + * Use `create(OperationServiceSchemaSchema)` to create a new message. + */ +export const OperationServiceSchemaSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_camino_schema, 18); /** * @generated from message camino.DocRefDeclaration @@ -388,7 +539,7 @@ export type DocRefDeclaration = Message<"camino.DocRefDeclaration"> & { * Use `create(DocRefDeclarationSchema)` to create a new message. */ export const DocRefDeclarationSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_schema, 12); + messageDesc(file_camino_schema, 19); /** * @generated from enum camino.ConflictStrategy @@ -523,3 +674,24 @@ export enum FieldStorageKind { */ export const FieldStorageKindSchema: GenEnum = /*@__PURE__*/ enumDesc(file_camino_schema, 3); + +/** + * @generated from enum camino.FieldImplementation + */ +export enum FieldImplementation { + /** + * @generated from enum value: FIELD_IMPLEMENTATION_UNSPECIFIED = 0; + */ + FIELD_IMPLEMENTATION_UNSPECIFIED = 0, + + /** + * @generated from enum value: SERVICE = 1; + */ + SERVICE = 1, +} + +/** + * Describes the enum camino.FieldImplementation. + */ +export const FieldImplementationSchema: GenEnum = /*@__PURE__*/ + enumDesc(file_camino_schema, 4); diff --git a/src/index.ts b/src/index.ts index 7b7ac91..a0f08b1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,6 +34,7 @@ export type CaminoClient = Client; export type { InvokeRequest, Value }; export type Field = { + get(): Promise; set(value: T): Promise; }; @@ -41,9 +42,25 @@ export type RuntimeHandler = ( context: Context, ) => Promise | unknown; +export type FieldOperation = { + get?: RuntimeHandler; + set?: RuntimeHandler; + watchStart?: RuntimeHandler; + watchStop?: RuntimeHandler; +}; + +export const fieldOps = ( + operation: FieldOperation, +): FieldOperation => operation; + +export const derivedWithDeps = (operation: { + get: RuntimeHandler; +}): FieldOperation => fieldOps(operation); + export type RuntimeFunctionSpec = { exportName: ExportName; symbol: string; + operation?: string; }; const isRecord = (value: unknown): value is Record => @@ -203,6 +220,10 @@ export const createField = ( objectId: string, fieldName: string, ): Field => ({ + 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; + [Name in Spec[number]["exportName"]]: + | RuntimeHandler + | FieldOperation; }; 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> + const implementationExport = ( + params.implementation as Record< + string, + RuntimeHandler | FieldOperation + > )[spec.exportName]; + const runtimeFunction = + spec.operation && typeof implementationExport === "object" + ? implementationExport[spec.operation as keyof FieldOperation] + : 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, { diff --git a/src/quixos/refs_pb.ts b/src/quixos/refs_pb.ts index 05a1adb..ee3f89e 100644 --- a/src/quixos/refs_pb.ts +++ b/src/quixos/refs_pb.ts @@ -10,7 +10,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file quixos/refs.proto. */ export const file_quixos_refs: GenFile = /*@__PURE__*/ - fileDesc("ChFxdWl4b3MvcmVmcy5wcm90bxIGcXVpeG9zImMKC0Z1bmN0aW9uUmVmEhkKEXBhY2thZ2VfbmFtZXNwYWNlGAEgASgJEhQKDHBhY2thZ2VfbmFtZRgCIAEoCRIOCgZzeW1ib2wYAyABKAkSEwoLdmVyc2lvbl9yZWYYBCABKAliBnByb3RvMw"); + fileDesc("ChFxdWl4b3MvcmVmcy5wcm90bxIGcXVpeG9zInYKC0Z1bmN0aW9uUmVmEhkKEXBhY2thZ2VfbmFtZXNwYWNlGAEgASgJEhQKDHBhY2thZ2VfbmFtZRgCIAEoCRIOCgZzeW1ib2wYAyABKAkSEwoLdmVyc2lvbl9yZWYYBCABKAkSEQoJb3BlcmF0aW9uGAUgASgJYgZwcm90bzM"); /** * @generated from message quixos.FunctionRef @@ -35,6 +35,11 @@ export type FunctionRef = Message<"quixos.FunctionRef"> & { * @generated from field: string version_ref = 4; */ versionRef: string; + + /** + * @generated from field: string operation = 5; + */ + operation: string; }; /**