From e36fac073d0530f817623df73c7b91b0b5fc65c8 Mon Sep 17 00:00:00 2001 From: Steven Borrelli Date: Thu, 5 Mar 2026 18:11:20 +0100 Subject: [PATCH 1/4] update docs and package metadata Signed-off-by: Steven Borrelli --- README.md | 110 ++++++++++++++++++++++++++++++++++++++++++---- package-lock.json | 4 +- package.json | 2 +- 3 files changed, 105 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 023cee1..682fb92 100644 --- a/README.md +++ b/README.md @@ -224,8 +224,14 @@ import { getObservedComposedResources, getInput, getContextKey, + getRequiredResource, getRequiredResources, + getRequiredSchema, + getRequiredSchemas, getCredentials, + advertiseCapabilities, + hasCapability, + Capability, } from "@crossplane-org/function-sdk-typescript"; // Get the observed composite resource (XR) @@ -246,11 +252,28 @@ const input = getInput(req); // Get context value from previous function const [value, exists] = getContextKey(req, "my-key"); -// Get required resources +// Get a specific required resource by name +const [resources, resolved] = getRequiredResource(req, "app-config"); + +// Get all required resources const required = getRequiredResources(req); +// Get a specific required schema by name +const [schema, resolved] = getRequiredSchema(req, "xr-schema"); + +// Get all required schemas +const schemas = getRequiredSchemas(req); + // Get credentials const creds = getCredentials(req, "aws-creds"); + +// Check if Crossplane advertises capabilities (v2.2+) +if (advertiseCapabilities(req)) { + // Check for specific capability support + if (hasCapability(req, Capability.CAPABILITY_REQUIRED_RESOURCES)) { + // Use required resources feature + } +} ``` #### Response Helpers @@ -268,7 +291,8 @@ import { normal, fatal, warning, - update, + requireResource, + requireSchema, DEFAULT_TTL, } from "@crossplane-org/function-sdk-typescript"; @@ -295,8 +319,16 @@ normal(rsp, "Success message"); warning(rsp, "Warning message"); fatal(rsp, "Fatal error message"); -// Update a resource by merging -const updated = update(sourceResource, targetResource); +// Request Crossplane fetch a resource (available in next invocation) +rsp = requireResource(rsp, "app-config", { + apiVersion: "v1", + kind: "ConfigMap", + matchName: "my-config", + namespace: "default" +}); + +// Request Crossplane fetch a schema (available in next invocation) +rsp = requireSchema(rsp, "xr-schema", "example.org/v1", "MyResource"); ``` #### Resource Helpers @@ -311,6 +343,8 @@ import { fromObject, toObject, newDesiredComposed, + update, + getCondition, } from "@crossplane-org/function-sdk-typescript"; // Create a Resource from a plain object @@ -329,6 +363,35 @@ const plainObj = asObject(struct); // Create a new empty DesiredComposed resource const desired = newDesiredComposed(); + +// Deep merge updates into a resource (arrays replaced by default) +update(resource, { + resource: { + spec: { + forProvider: { + region: "us-west-2", + tags: ["env:prod"] // Replaces existing tags + } + } + } +}); + +// Or merge with array concatenation +update(resource, { + resource: { + spec: { + forProvider: { + tags: ["new-tag"] // Appended to existing tags + } + } + } +}, { mergeArrays: true }); + +// Get a status condition from a resource +const readyCondition = getCondition(resource.resource, "Ready"); +if (readyCondition.status === "True") { + console.log("Resource is ready"); +} ``` ### Error Handling @@ -519,6 +582,10 @@ import { ObservedComposed, DesiredComposed, ConnectionDetails, + MergeOptions, + + // Status condition types + Condition as ResourceCondition, // Protocol buffer types Severity, @@ -531,6 +598,11 @@ import { Resources, Credentials, CredentialData, + Requirements, + ResourceSelector, + SchemaSelector, + Schema, + Capability, // Runtime types ServerOptions, @@ -539,21 +611,43 @@ import { ### Core Functions +#### Response Functions + - **`to(req, ttl?)`** - Initialize a response from a request - **`normal(rsp, message)`** - Add a normal (info) result - **`warning(rsp, message)`** - Add a warning result - **`fatal(rsp, message)`** - Add a fatal error result +- **`setDesiredComposedResources(rsp, resources)`** - Set desired composed resources +- **`setDesiredCompositeStatus({rsp, status})`** - Update XR status +- **`setContextKey(rsp, key, value)`** - Set context for next function +- **`setOutput(rsp, output)`** - Set function output +- **`requireResource(rsp, name, selector)`** - Request Crossplane fetch resources +- **`requireSchema(rsp, name, apiVersion, kind)`** - Request Crossplane fetch schemas + +#### Request Functions + - **`getObservedCompositeResource(req)`** - Get the observed XR - **`getDesiredCompositeResource(req)`** - Get the desired XR - **`getDesiredComposedResources(req)`** - Get desired composed resources - **`getObservedComposedResources(req)`** - Get observed composed resources -- **`setDesiredComposedResources(rsp, resources)`** - Set desired composed resources -- **`setDesiredCompositeStatus({rsp, status})`** - Update XR status -- **`setContextKey(rsp, key, value)`** - Set context for next function - **`getContextKey(req, key)`** - Get context from previous function - **`getInput(req)`** - Get function input configuration -- **`getRequiredResources(req)`** - Get required resources +- **`getRequiredResource(req, name)`** - Get a required resource by name +- **`getRequiredResources(req)`** - Get all required resources (deprecated) +- **`getRequiredSchema(req, name)`** - Get a required schema by name +- **`getRequiredSchemas(req)`** - Get all required schemas - **`getCredentials(req, name)`** - Get credentials by name (throws error if not found) +- **`advertiseCapabilities(req)`** - Check if Crossplane advertises capabilities +- **`hasCapability(req, capability)`** - Check for a specific capability + +#### Resource Functions + +- **`fromObject(obj, connectionDetails?, ready?)`** - Create Resource from plain object +- **`fromModel(model, connectionDetails?, ready?)`** - Create Resource from kubernetes-models +- **`toObject(resource)`** - Extract plain object from Resource +- **`update(resource, source, options?)`** - Deep merge data into a Resource +- **`getCondition(resource, type)`** - Extract a status condition by type +- **`newDesiredComposed()`** - Create an empty DesiredComposed resource See [USAGE.md](USAGE.md) for detailed API documentation and examples. diff --git a/package-lock.json b/package-lock.json index 17a9e78..ec63b20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@crossplane-org/function-sdk-typescript", - "version": "0.4.0", + "version": "0.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@crossplane-org/function-sdk-typescript", - "version": "0.4.0", + "version": "0.5.0", "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "^1.14.3", diff --git a/package.json b/package.json index b47c671..ddcae3b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@crossplane-org/function-sdk-typescript", - "version": "0.4.0", + "version": "0.5.0", "description": "A Crossplane Function SDK for Typescript", "keywords": [ "crossplane", From 21b8b5c4c2d9351dd9665d507384a54815fdf1e7 Mon Sep 17 00:00:00 2001 From: Steven Borrelli Date: Thu, 5 Mar 2026 18:39:51 +0100 Subject: [PATCH 2/4] add to protoc defs Signed-off-by: Steven Borrelli --- scripts/protoc-gen.sh | 2 +- src/proto/google/protobuf/duration.ts | 18 +- src/proto/google/protobuf/struct.ts | 53 ++- src/proto/run_function.ts | 538 +++++++++++++++++++------- src/proto/typeRegistry.ts | 27 ++ src/request/request.ts | 12 +- src/resource/resource.ts | 26 +- src/response/response.test.ts | 3 + src/response/response.ts | 67 ++-- 9 files changed, 543 insertions(+), 203 deletions(-) create mode 100644 src/proto/typeRegistry.ts diff --git a/scripts/protoc-gen.sh b/scripts/protoc-gen.sh index f0cbca8..a1ea8ce 100755 --- a/scripts/protoc-gen.sh +++ b/scripts/protoc-gen.sh @@ -6,7 +6,7 @@ rm -rf ./src/proto/*.js ./src/proto/*.ts protoc \ --plugin=./node_modules/.bin/protoc-gen-ts_proto \ - --ts_proto_opt=outputServices=grpc-js,esModuleInterop=true,env=node,importSuffix=.js,context=true \ + --ts_proto_opt=outputServices=grpc-js,esModuleInterop=true,env=node,importSuffix=.js,context=true,outputTypeRegistry=true \ --ts_proto_out=./src/proto \ --proto_path=./src/proto \ ./src/proto/run_function.proto diff --git a/src/proto/google/protobuf/duration.ts b/src/proto/google/protobuf/duration.ts index 53920cb..0cad7a6 100644 --- a/src/proto/google/protobuf/duration.ts +++ b/src/proto/google/protobuf/duration.ts @@ -6,6 +6,7 @@ /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; +import { messageTypeRegistry } from "../../typeRegistry.js"; export const protobufPackage = "google.protobuf"; @@ -70,6 +71,7 @@ export const protobufPackage = "google.protobuf"; * microsecond should be expressed in JSON format as "3.000001s". */ export interface Duration { + $type: "google.protobuf.Duration"; /** * Signed seconds of the span of time. Must be from -315,576,000,000 * to +315,576,000,000 inclusive. Note: these bounds are computed from: @@ -88,10 +90,12 @@ export interface Duration { } function createBaseDuration(): Duration { - return { seconds: 0, nanos: 0 }; + return { $type: "google.protobuf.Duration", seconds: 0, nanos: 0 }; } -export const Duration: MessageFns = { +export const Duration: MessageFns = { + $type: "google.protobuf.Duration" as const, + encode(message: Duration, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.seconds !== 0) { writer.uint32(8).int64(message.seconds); @@ -136,6 +140,7 @@ export const Duration: MessageFns = { fromJSON(object: any): Duration { return { + $type: Duration.$type, seconds: isSet(object.seconds) ? globalThis.Number(object.seconds) : 0, nanos: isSet(object.nanos) ? globalThis.Number(object.nanos) : 0, }; @@ -163,6 +168,8 @@ export const Duration: MessageFns = { }, }; +messageTypeRegistry.set(Duration.$type, Duration); + export interface DataLoaderOptions { cache?: boolean; } @@ -177,12 +184,12 @@ type Builtin = Date | Function | Uint8Array | string | number | boolean | undefi export type DeepPartial = T extends Builtin ? T : T extends globalThis.Array ? globalThis.Array> : T extends ReadonlyArray ? ReadonlyArray> - : T extends {} ? { [K in keyof T]?: DeepPartial } + : T extends {} ? { [K in Exclude]?: DeepPartial } : Partial; type KeysOfUnion = T extends T ? keyof T : never; export type Exact = P extends Builtin ? P - : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + : P & { [K in keyof P]: Exact } & { [K in Exclude | "$type">]: never }; function longToNumber(int64: { toString(): string }): number { const num = globalThis.Number(int64.toString()); @@ -199,7 +206,8 @@ function isSet(value: any): boolean { return value !== null && value !== undefined; } -export interface MessageFns { +export interface MessageFns { + readonly $type: V; encode(message: T, writer?: BinaryWriter): BinaryWriter; decode(input: BinaryReader | Uint8Array, length?: number): T; fromJSON(object: any): T; diff --git a/src/proto/google/protobuf/struct.ts b/src/proto/google/protobuf/struct.ts index f275f80..6fbbdce 100644 --- a/src/proto/google/protobuf/struct.ts +++ b/src/proto/google/protobuf/struct.ts @@ -6,6 +6,7 @@ /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; +import { messageTypeRegistry } from "../../typeRegistry.js"; export const protobufPackage = "google.protobuf"; @@ -54,11 +55,13 @@ export function nullValueToJSON(object: NullValue): string { * The JSON representation for `Struct` is JSON object. */ export interface Struct { + $type: "google.protobuf.Struct"; /** Unordered map of dynamically typed values. */ fields: { [key: string]: any | undefined }; } export interface Struct_FieldsEntry { + $type: "google.protobuf.Struct.FieldsEntry"; key: string; value: any | undefined; } @@ -72,6 +75,7 @@ export interface Struct_FieldsEntry { * The JSON representation for `Value` is JSON value. */ export interface Value { + $type: "google.protobuf.Value"; /** Represents a null value. */ nullValue?: | NullValue @@ -102,19 +106,25 @@ export interface Value { * The JSON representation for `ListValue` is JSON array. */ export interface ListValue { + $type: "google.protobuf.ListValue"; /** Repeated field of dynamically typed values. */ values: any[]; } function createBaseStruct(): Struct { - return { fields: {} }; + return { $type: "google.protobuf.Struct", fields: {} }; } -export const Struct: MessageFns & StructWrapperFns = { +export const Struct: MessageFns & StructWrapperFns = { + $type: "google.protobuf.Struct" as const, + encode(message: Struct, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { globalThis.Object.entries(message.fields).forEach(([key, value]: [string, any | undefined]) => { if (value !== undefined) { - Struct_FieldsEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join(); + Struct_FieldsEntry.encode( + { $type: "google.protobuf.Struct.FieldsEntry", key: key as any, value }, + writer.uint32(10).fork(), + ).join(); } }); return writer; @@ -149,6 +159,7 @@ export const Struct: MessageFns & StructWrapperFns = { fromJSON(object: any): Struct { return { + $type: Struct.$type, fields: isObject(object.fields) ? (globalThis.Object.entries(object.fields) as [string, any][]).reduce( (acc: { [key: string]: any | undefined }, [key, value]: [string, any]) => { @@ -214,11 +225,15 @@ export const Struct: MessageFns & StructWrapperFns = { }, }; +messageTypeRegistry.set(Struct.$type, Struct); + function createBaseStruct_FieldsEntry(): Struct_FieldsEntry { - return { key: "", value: undefined }; + return { $type: "google.protobuf.Struct.FieldsEntry", key: "", value: undefined }; } -export const Struct_FieldsEntry: MessageFns = { +export const Struct_FieldsEntry: MessageFns = { + $type: "google.protobuf.Struct.FieldsEntry" as const, + encode(message: Struct_FieldsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.key !== "") { writer.uint32(10).string(message.key); @@ -263,6 +278,7 @@ export const Struct_FieldsEntry: MessageFns = { fromJSON(object: any): Struct_FieldsEntry { return { + $type: Struct_FieldsEntry.$type, key: isSet(object.key) ? globalThis.String(object.key) : "", value: isSet(object?.value) ? object.value : undefined, }; @@ -290,8 +306,11 @@ export const Struct_FieldsEntry: MessageFns = { }, }; +messageTypeRegistry.set(Struct_FieldsEntry.$type, Struct_FieldsEntry); + function createBaseValue(): Value { return { + $type: "google.protobuf.Value", nullValue: undefined, numberValue: undefined, stringValue: undefined, @@ -301,7 +320,9 @@ function createBaseValue(): Value { }; } -export const Value: MessageFns & AnyValueWrapperFns = { +export const Value: MessageFns & AnyValueWrapperFns = { + $type: "google.protobuf.Value" as const, + encode(message: Value, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.nullValue !== undefined) { writer.uint32(8).int32(message.nullValue); @@ -390,6 +411,7 @@ export const Value: MessageFns & AnyValueWrapperFns = { fromJSON(object: any): Value { return { + $type: Value.$type, nullValue: isSet(object.nullValue) ? nullValueFromJSON(object.nullValue) : isSet(object.null_value) @@ -498,11 +520,15 @@ export const Value: MessageFns & AnyValueWrapperFns = { }, }; +messageTypeRegistry.set(Value.$type, Value); + function createBaseListValue(): ListValue { - return { values: [] }; + return { $type: "google.protobuf.ListValue", values: [] }; } -export const ListValue: MessageFns & ListValueWrapperFns = { +export const ListValue: MessageFns & ListValueWrapperFns = { + $type: "google.protobuf.ListValue" as const, + encode(message: ListValue, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { for (const v of message.values) { Value.encode(Value.wrap(v!), writer.uint32(10).fork()).join(); @@ -535,7 +561,7 @@ export const ListValue: MessageFns & ListValueWrapperFns = { }, fromJSON(object: any): ListValue { - return { values: globalThis.Array.isArray(object?.values) ? [...object.values] : [] }; + return { $type: ListValue.$type, values: globalThis.Array.isArray(object?.values) ? [...object.values] : [] }; }, toJSON(message: ListValue): unknown { @@ -570,6 +596,8 @@ export const ListValue: MessageFns & ListValueWrapperFns = { }, }; +messageTypeRegistry.set(ListValue.$type, ListValue); + export interface DataLoaderOptions { cache?: boolean; } @@ -584,12 +612,12 @@ type Builtin = Date | Function | Uint8Array | string | number | boolean | undefi export type DeepPartial = T extends Builtin ? T : T extends globalThis.Array ? globalThis.Array> : T extends ReadonlyArray ? ReadonlyArray> - : T extends {} ? { [K in keyof T]?: DeepPartial } + : T extends {} ? { [K in Exclude]?: DeepPartial } : Partial; type KeysOfUnion = T extends T ? keyof T : never; export type Exact = P extends Builtin ? P - : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + : P & { [K in keyof P]: Exact } & { [K in Exclude | "$type">]: never }; function isObject(value: any): boolean { return typeof value === "object" && value !== null; @@ -599,7 +627,8 @@ function isSet(value: any): boolean { return value !== null && value !== undefined; } -export interface MessageFns { +export interface MessageFns { + readonly $type: V; encode(message: T, writer?: BinaryWriter): BinaryWriter; decode(input: BinaryReader | Uint8Array, length?: number): T; fromJSON(object: any): T; diff --git a/src/proto/run_function.ts b/src/proto/run_function.ts index de19a01..b84a480 100644 --- a/src/proto/run_function.ts +++ b/src/proto/run_function.ts @@ -20,6 +20,7 @@ import { } from "@grpc/grpc-js"; import { Duration } from "./google/protobuf/duration.js"; import { Struct } from "./google/protobuf/struct.js"; +import { messageTypeRegistry } from "./typeRegistry.js"; export const protobufPackage = "apiextensions.fn.proto.v1"; @@ -309,6 +310,7 @@ export function statusToJSON(object: Status): string { /** A RunFunctionRequest requests that the function be run. */ export interface RunFunctionRequest { + $type: "apiextensions.fn.proto.v1.RunFunctionRequest"; /** Metadata pertaining to this request. */ meta: | RequestMeta @@ -392,48 +394,57 @@ export interface RunFunctionRequest { } export interface RunFunctionRequest_ExtraResourcesEntry { + $type: "apiextensions.fn.proto.v1.RunFunctionRequest.ExtraResourcesEntry"; key: string; value: Resources | undefined; } export interface RunFunctionRequest_CredentialsEntry { + $type: "apiextensions.fn.proto.v1.RunFunctionRequest.CredentialsEntry"; key: string; value: Credentials | undefined; } export interface RunFunctionRequest_RequiredResourcesEntry { + $type: "apiextensions.fn.proto.v1.RunFunctionRequest.RequiredResourcesEntry"; key: string; value: Resources | undefined; } export interface RunFunctionRequest_RequiredSchemasEntry { + $type: "apiextensions.fn.proto.v1.RunFunctionRequest.RequiredSchemasEntry"; key: string; value: Schema | undefined; } /** Credentials that a function may use to communicate with an external system. */ export interface Credentials { + $type: "apiextensions.fn.proto.v1.Credentials"; /** Credential data loaded by Crossplane, for example from a Secret. */ credentialData?: CredentialData | undefined; } /** CredentialData loaded by Crossplane, for example from a Secret. */ export interface CredentialData { + $type: "apiextensions.fn.proto.v1.CredentialData"; data: { [key: string]: Buffer }; } export interface CredentialData_DataEntry { + $type: "apiextensions.fn.proto.v1.CredentialData.DataEntry"; key: string; value: Buffer; } /** Resources represents the state of several Crossplane resources. */ export interface Resources { + $type: "apiextensions.fn.proto.v1.Resources"; items: Resource[]; } /** A RunFunctionResponse contains the result of a function run. */ export interface RunFunctionResponse { + $type: "apiextensions.fn.proto.v1.RunFunctionResponse"; /** Metadata pertaining to this response. */ meta: | ResponseMeta @@ -484,6 +495,7 @@ export interface RunFunctionResponse { /** RequestMeta contains metadata pertaining to a RunFunctionRequest. */ export interface RequestMeta { + $type: "apiextensions.fn.proto.v1.RequestMeta"; /** * An opaque string identifying a request. Requests with identical tags will * be otherwise identical. @@ -499,6 +511,7 @@ export interface RequestMeta { /** Requirements that must be satisfied for a function to run successfully. */ export interface Requirements { + $type: "apiextensions.fn.proto.v1.Requirements"; /** * Resources that this function requires. The map key uniquely identifies the * group of resources. @@ -521,22 +534,26 @@ export interface Requirements { } export interface Requirements_ExtraResourcesEntry { + $type: "apiextensions.fn.proto.v1.Requirements.ExtraResourcesEntry"; key: string; value: ResourceSelector | undefined; } export interface Requirements_ResourcesEntry { + $type: "apiextensions.fn.proto.v1.Requirements.ResourcesEntry"; key: string; value: ResourceSelector | undefined; } export interface Requirements_SchemasEntry { + $type: "apiextensions.fn.proto.v1.Requirements.SchemasEntry"; key: string; value: SchemaSelector | undefined; } /** SchemaSelector identifies a resource kind whose OpenAPI schema is requested. */ export interface SchemaSelector { + $type: "apiextensions.fn.proto.v1.SchemaSelector"; /** API version of the resource kind, e.g. "example.org/v1". */ apiVersion: string; /** Kind of resource, e.g. "MyResource". */ @@ -545,6 +562,7 @@ export interface SchemaSelector { /** Schema represents the OpenAPI schema for a resource kind. */ export interface Schema { + $type: "apiextensions.fn.proto.v1.Schema"; /** * The OpenAPI v3 schema of the resource kind as unstructured JSON. * For CRDs this is the spec.versions[].schema.openAPIV3Schema field. @@ -555,6 +573,7 @@ export interface Schema { /** ResourceSelector selects a group of resources, either by name or by label. */ export interface ResourceSelector { + $type: "apiextensions.fn.proto.v1.ResourceSelector"; /** API version of resources to select. */ apiVersion: string; /** Kind of resources to select. */ @@ -577,16 +596,19 @@ export interface ResourceSelector { /** MatchLabels defines a set of labels to match resources against. */ export interface MatchLabels { + $type: "apiextensions.fn.proto.v1.MatchLabels"; labels: { [key: string]: string }; } export interface MatchLabels_LabelsEntry { + $type: "apiextensions.fn.proto.v1.MatchLabels.LabelsEntry"; key: string; value: string; } /** ResponseMeta contains metadata pertaining to a RunFunctionResponse. */ export interface ResponseMeta { + $type: "apiextensions.fn.proto.v1.ResponseMeta"; /** * An opaque string identifying the content of the request. Must match the * meta.tag of the corresponding RunFunctionRequest. @@ -602,6 +624,7 @@ export interface ResponseMeta { /** State of the XR (XR) and any resources. */ export interface State { + $type: "apiextensions.fn.proto.v1.State"; /** The state of the XR (XR). */ composite: | Resource @@ -615,12 +638,14 @@ export interface State { } export interface State_ResourcesEntry { + $type: "apiextensions.fn.proto.v1.State.ResourcesEntry"; key: string; value: Resource | undefined; } /** A Resource represents the state of a Kubernetes resource. */ export interface Resource { + $type: "apiextensions.fn.proto.v1.Resource"; /** * The JSON representation of the resource. * @@ -677,12 +702,14 @@ export interface Resource { } export interface Resource_ConnectionDetailsEntry { + $type: "apiextensions.fn.proto.v1.Resource.ConnectionDetailsEntry"; key: string; value: Buffer; } /** A Result of running a function. */ export interface Result { + $type: "apiextensions.fn.proto.v1.Result"; /** Severity of this result. */ severity: Severity; /** Human-readable details about the result. */ @@ -705,6 +732,7 @@ export interface Result { * https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties. */ export interface Condition { + $type: "apiextensions.fn.proto.v1.Condition"; /** Type of condition in PascalCase. */ type: string; /** Status of the condition. */ @@ -730,6 +758,7 @@ export interface Condition { function createBaseRunFunctionRequest(): RunFunctionRequest { return { + $type: "apiextensions.fn.proto.v1.RunFunctionRequest", meta: undefined, observed: undefined, desired: undefined, @@ -742,7 +771,9 @@ function createBaseRunFunctionRequest(): RunFunctionRequest { }; } -export const RunFunctionRequest: MessageFns = { +export const RunFunctionRequest: MessageFns = { + $type: "apiextensions.fn.proto.v1.RunFunctionRequest" as const, + encode(message: RunFunctionRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.meta !== undefined) { RequestMeta.encode(message.meta, writer.uint32(10).fork()).join(); @@ -760,16 +791,32 @@ export const RunFunctionRequest: MessageFns = { Struct.encode(Struct.wrap(message.context), writer.uint32(42).fork()).join(); } globalThis.Object.entries(message.extraResources).forEach(([key, value]: [string, Resources]) => { - RunFunctionRequest_ExtraResourcesEntry.encode({ key: key as any, value }, writer.uint32(50).fork()).join(); + RunFunctionRequest_ExtraResourcesEntry.encode({ + $type: "apiextensions.fn.proto.v1.RunFunctionRequest.ExtraResourcesEntry", + key: key as any, + value, + }, writer.uint32(50).fork()).join(); }); globalThis.Object.entries(message.credentials).forEach(([key, value]: [string, Credentials]) => { - RunFunctionRequest_CredentialsEntry.encode({ key: key as any, value }, writer.uint32(58).fork()).join(); + RunFunctionRequest_CredentialsEntry.encode({ + $type: "apiextensions.fn.proto.v1.RunFunctionRequest.CredentialsEntry", + key: key as any, + value, + }, writer.uint32(58).fork()).join(); }); globalThis.Object.entries(message.requiredResources).forEach(([key, value]: [string, Resources]) => { - RunFunctionRequest_RequiredResourcesEntry.encode({ key: key as any, value }, writer.uint32(66).fork()).join(); + RunFunctionRequest_RequiredResourcesEntry.encode({ + $type: "apiextensions.fn.proto.v1.RunFunctionRequest.RequiredResourcesEntry", + key: key as any, + value, + }, writer.uint32(66).fork()).join(); }); globalThis.Object.entries(message.requiredSchemas).forEach(([key, value]: [string, Schema]) => { - RunFunctionRequest_RequiredSchemasEntry.encode({ key: key as any, value }, writer.uint32(74).fork()).join(); + RunFunctionRequest_RequiredSchemasEntry.encode({ + $type: "apiextensions.fn.proto.v1.RunFunctionRequest.RequiredSchemasEntry", + key: key as any, + value, + }, writer.uint32(74).fork()).join(); }); return writer; }, @@ -876,6 +923,7 @@ export const RunFunctionRequest: MessageFns = { fromJSON(object: any): RunFunctionRequest { return { + $type: RunFunctionRequest.$type, meta: isSet(object.meta) ? RequestMeta.fromJSON(object.meta) : undefined, observed: isSet(object.observed) ? State.fromJSON(object.observed) : undefined, desired: isSet(object.desired) ? State.fromJSON(object.desired) : undefined, @@ -1016,7 +1064,7 @@ export const RunFunctionRequest: MessageFns = { : undefined; message.input = object.input ?? undefined; message.context = object.context ?? undefined; - message.extraResources = (globalThis.Object.entries(object.extraResources ?? {}) as [string, Resources][]).reduce( + message.extraResources = (globalThis.Object.entries(object.extraResources ?? {}) as unknown as [string, Resources][]).reduce( (acc: { [key: string]: Resources }, [key, value]: [string, Resources]) => { if (value !== undefined) { acc[key] = Resources.fromPartial(value); @@ -1025,7 +1073,7 @@ export const RunFunctionRequest: MessageFns = { }, {}, ); - message.credentials = (globalThis.Object.entries(object.credentials ?? {}) as [string, Credentials][]).reduce( + message.credentials = (globalThis.Object.entries(object.credentials ?? {}) as unknown as [string, Credentials][]).reduce( (acc: { [key: string]: Credentials }, [key, value]: [string, Credentials]) => { if (value !== undefined) { acc[key] = Credentials.fromPartial(value); @@ -1034,14 +1082,14 @@ export const RunFunctionRequest: MessageFns = { }, {}, ); - message.requiredResources = (globalThis.Object.entries(object.requiredResources ?? {}) as [string, Resources][]) + message.requiredResources = (globalThis.Object.entries(object.requiredResources ?? {}) as unknown as [string, Resources][]) .reduce((acc: { [key: string]: Resources }, [key, value]: [string, Resources]) => { if (value !== undefined) { acc[key] = Resources.fromPartial(value); } return acc; }, {}); - message.requiredSchemas = (globalThis.Object.entries(object.requiredSchemas ?? {}) as [string, Schema][]).reduce( + message.requiredSchemas = (globalThis.Object.entries(object.requiredSchemas ?? {}) as unknown as [string, Schema][]).reduce( (acc: { [key: string]: Schema }, [key, value]: [string, Schema]) => { if (value !== undefined) { acc[key] = Schema.fromPartial(value); @@ -1054,11 +1102,18 @@ export const RunFunctionRequest: MessageFns = { }, }; +messageTypeRegistry.set(RunFunctionRequest.$type, RunFunctionRequest); + function createBaseRunFunctionRequest_ExtraResourcesEntry(): RunFunctionRequest_ExtraResourcesEntry { - return { key: "", value: undefined }; + return { $type: "apiextensions.fn.proto.v1.RunFunctionRequest.ExtraResourcesEntry", key: "", value: undefined }; } -export const RunFunctionRequest_ExtraResourcesEntry: MessageFns = { +export const RunFunctionRequest_ExtraResourcesEntry: MessageFns< + RunFunctionRequest_ExtraResourcesEntry, + "apiextensions.fn.proto.v1.RunFunctionRequest.ExtraResourcesEntry" +> = { + $type: "apiextensions.fn.proto.v1.RunFunctionRequest.ExtraResourcesEntry" as const, + encode(message: RunFunctionRequest_ExtraResourcesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.key !== "") { writer.uint32(10).string(message.key); @@ -1103,6 +1158,7 @@ export const RunFunctionRequest_ExtraResourcesEntry: MessageFns = { +export const RunFunctionRequest_CredentialsEntry: MessageFns< + RunFunctionRequest_CredentialsEntry, + "apiextensions.fn.proto.v1.RunFunctionRequest.CredentialsEntry" +> = { + $type: "apiextensions.fn.proto.v1.RunFunctionRequest.CredentialsEntry" as const, + encode(message: RunFunctionRequest_CredentialsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.key !== "") { writer.uint32(10).string(message.key); @@ -1185,6 +1248,7 @@ export const RunFunctionRequest_CredentialsEntry: MessageFns = { +export const RunFunctionRequest_RequiredResourcesEntry: MessageFns< + RunFunctionRequest_RequiredResourcesEntry, + "apiextensions.fn.proto.v1.RunFunctionRequest.RequiredResourcesEntry" +> = { + $type: "apiextensions.fn.proto.v1.RunFunctionRequest.RequiredResourcesEntry" as const, + encode(message: RunFunctionRequest_RequiredResourcesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.key !== "") { writer.uint32(10).string(message.key); @@ -1267,6 +1338,7 @@ export const RunFunctionRequest_RequiredResourcesEntry: MessageFns = { +export const RunFunctionRequest_RequiredSchemasEntry: MessageFns< + RunFunctionRequest_RequiredSchemasEntry, + "apiextensions.fn.proto.v1.RunFunctionRequest.RequiredSchemasEntry" +> = { + $type: "apiextensions.fn.proto.v1.RunFunctionRequest.RequiredSchemasEntry" as const, + encode(message: RunFunctionRequest_RequiredSchemasEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.key !== "") { writer.uint32(10).string(message.key); @@ -1349,6 +1428,7 @@ export const RunFunctionRequest_RequiredSchemasEntry: MessageFns = { +export const Credentials: MessageFns = { + $type: "apiextensions.fn.proto.v1.Credentials" as const, + encode(message: Credentials, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.credentialData !== undefined) { CredentialData.encode(message.credentialData, writer.uint32(10).fork()).join(); @@ -1420,6 +1504,7 @@ export const Credentials: MessageFns = { fromJSON(object: any): Credentials { return { + $type: Credentials.$type, credentialData: isSet(object.credentialData) ? CredentialData.fromJSON(object.credentialData) : isSet(object.credential_data) @@ -1448,14 +1533,22 @@ export const Credentials: MessageFns = { }, }; +messageTypeRegistry.set(Credentials.$type, Credentials); + function createBaseCredentialData(): CredentialData { - return { data: {} }; + return { $type: "apiextensions.fn.proto.v1.CredentialData", data: {} }; } -export const CredentialData: MessageFns = { +export const CredentialData: MessageFns = { + $type: "apiextensions.fn.proto.v1.CredentialData" as const, + encode(message: CredentialData, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { globalThis.Object.entries(message.data).forEach(([key, value]: [string, Buffer]) => { - CredentialData_DataEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join(); + CredentialData_DataEntry.encode({ + $type: "apiextensions.fn.proto.v1.CredentialData.DataEntry", + key: key as any, + value, + }, writer.uint32(10).fork()).join(); }); return writer; }, @@ -1489,6 +1582,7 @@ export const CredentialData: MessageFns = { fromJSON(object: any): CredentialData { return { + $type: CredentialData.$type, data: isObject(object.data) ? (globalThis.Object.entries(object.data) as [string, any][]).reduce( (acc: { [key: string]: Buffer }, [key, value]: [string, any]) => { @@ -1533,11 +1627,18 @@ export const CredentialData: MessageFns = { }, }; +messageTypeRegistry.set(CredentialData.$type, CredentialData); + function createBaseCredentialData_DataEntry(): CredentialData_DataEntry { - return { key: "", value: Buffer.alloc(0) }; + return { $type: "apiextensions.fn.proto.v1.CredentialData.DataEntry", key: "", value: Buffer.alloc(0) }; } -export const CredentialData_DataEntry: MessageFns = { +export const CredentialData_DataEntry: MessageFns< + CredentialData_DataEntry, + "apiextensions.fn.proto.v1.CredentialData.DataEntry" +> = { + $type: "apiextensions.fn.proto.v1.CredentialData.DataEntry" as const, + encode(message: CredentialData_DataEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.key !== "") { writer.uint32(10).string(message.key); @@ -1582,6 +1683,7 @@ export const CredentialData_DataEntry: MessageFns = { fromJSON(object: any): CredentialData_DataEntry { return { + $type: CredentialData_DataEntry.$type, key: isSet(object.key) ? globalThis.String(object.key) : "", value: isSet(object.value) ? Buffer.from(bytesFromBase64(object.value)) : Buffer.alloc(0), }; @@ -1609,11 +1711,15 @@ export const CredentialData_DataEntry: MessageFns = { }, }; +messageTypeRegistry.set(CredentialData_DataEntry.$type, CredentialData_DataEntry); + function createBaseResources(): Resources { - return { items: [] }; + return { $type: "apiextensions.fn.proto.v1.Resources", items: [] }; } -export const Resources: MessageFns = { +export const Resources: MessageFns = { + $type: "apiextensions.fn.proto.v1.Resources" as const, + encode(message: Resources, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { for (const v of message.items) { Resource.encode(v!, writer.uint32(10).fork()).join(); @@ -1646,7 +1752,10 @@ export const Resources: MessageFns = { }, fromJSON(object: any): Resources { - return { items: globalThis.Array.isArray(object?.items) ? object.items.map((e: any) => Resource.fromJSON(e)) : [] }; + return { + $type: Resources.$type, + items: globalThis.Array.isArray(object?.items) ? object.items.map((e: any) => Resource.fromJSON(e)) : [], + }; }, toJSON(message: Resources): unknown { @@ -1667,8 +1776,11 @@ export const Resources: MessageFns = { }, }; +messageTypeRegistry.set(Resources.$type, Resources); + function createBaseRunFunctionResponse(): RunFunctionResponse { return { + $type: "apiextensions.fn.proto.v1.RunFunctionResponse", meta: undefined, desired: undefined, results: [], @@ -1679,7 +1791,9 @@ function createBaseRunFunctionResponse(): RunFunctionResponse { }; } -export const RunFunctionResponse: MessageFns = { +export const RunFunctionResponse: MessageFns = { + $type: "apiextensions.fn.proto.v1.RunFunctionResponse" as const, + encode(message: RunFunctionResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.meta !== undefined) { ResponseMeta.encode(message.meta, writer.uint32(10).fork()).join(); @@ -1779,6 +1893,7 @@ export const RunFunctionResponse: MessageFns = { fromJSON(object: any): RunFunctionResponse { return { + $type: RunFunctionResponse.$type, meta: isSet(object.meta) ? ResponseMeta.fromJSON(object.meta) : undefined, desired: isSet(object.desired) ? State.fromJSON(object.desired) : undefined, results: globalThis.Array.isArray(object?.results) ? object.results.map((e: any) => Result.fromJSON(e)) : [], @@ -1839,11 +1954,15 @@ export const RunFunctionResponse: MessageFns = { }, }; +messageTypeRegistry.set(RunFunctionResponse.$type, RunFunctionResponse); + function createBaseRequestMeta(): RequestMeta { - return { tag: "", capabilities: [] }; + return { $type: "apiextensions.fn.proto.v1.RequestMeta", tag: "", capabilities: [] }; } -export const RequestMeta: MessageFns = { +export const RequestMeta: MessageFns = { + $type: "apiextensions.fn.proto.v1.RequestMeta" as const, + encode(message: RequestMeta, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.tag !== "") { writer.uint32(10).string(message.tag); @@ -1900,6 +2019,7 @@ export const RequestMeta: MessageFns = { fromJSON(object: any): RequestMeta { return { + $type: RequestMeta.$type, tag: isSet(object.tag) ? globalThis.String(object.tag) : "", capabilities: globalThis.Array.isArray(object?.capabilities) ? object.capabilities.map((e: any) => capabilityFromJSON(e)) @@ -1929,20 +2049,36 @@ export const RequestMeta: MessageFns = { }, }; +messageTypeRegistry.set(RequestMeta.$type, RequestMeta); + function createBaseRequirements(): Requirements { - return { extraResources: {}, resources: {}, schemas: {} }; + return { $type: "apiextensions.fn.proto.v1.Requirements", extraResources: {}, resources: {}, schemas: {} }; } -export const Requirements: MessageFns = { +export const Requirements: MessageFns = { + $type: "apiextensions.fn.proto.v1.Requirements" as const, + encode(message: Requirements, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { globalThis.Object.entries(message.extraResources).forEach(([key, value]: [string, ResourceSelector]) => { - Requirements_ExtraResourcesEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join(); + Requirements_ExtraResourcesEntry.encode({ + $type: "apiextensions.fn.proto.v1.Requirements.ExtraResourcesEntry", + key: key as any, + value, + }, writer.uint32(10).fork()).join(); }); globalThis.Object.entries(message.resources).forEach(([key, value]: [string, ResourceSelector]) => { - Requirements_ResourcesEntry.encode({ key: key as any, value }, writer.uint32(18).fork()).join(); + Requirements_ResourcesEntry.encode({ + $type: "apiextensions.fn.proto.v1.Requirements.ResourcesEntry", + key: key as any, + value, + }, writer.uint32(18).fork()).join(); }); globalThis.Object.entries(message.schemas).forEach(([key, value]: [string, SchemaSelector]) => { - Requirements_SchemasEntry.encode({ key: key as any, value }, writer.uint32(26).fork()).join(); + Requirements_SchemasEntry.encode({ + $type: "apiextensions.fn.proto.v1.Requirements.SchemasEntry", + key: key as any, + value, + }, writer.uint32(26).fork()).join(); }); return writer; }, @@ -1998,6 +2134,7 @@ export const Requirements: MessageFns = { fromJSON(object: any): Requirements { return { + $type: Requirements.$type, extraResources: isObject(object.extraResources) ? (globalThis.Object.entries(object.extraResources) as [string, any][]).reduce( (acc: { [key: string]: ResourceSelector }, [key, value]: [string, any]) => { @@ -2073,14 +2210,14 @@ export const Requirements: MessageFns = { }, fromPartial, I>>(object: I): Requirements { const message = createBaseRequirements(); - message.extraResources = (globalThis.Object.entries(object.extraResources ?? {}) as [string, ResourceSelector][]) + message.extraResources = (globalThis.Object.entries(object.extraResources ?? {}) as unknown as [string, ResourceSelector][]) .reduce((acc: { [key: string]: ResourceSelector }, [key, value]: [string, ResourceSelector]) => { if (value !== undefined) { acc[key] = ResourceSelector.fromPartial(value); } return acc; }, {}); - message.resources = (globalThis.Object.entries(object.resources ?? {}) as [string, ResourceSelector][]).reduce( + message.resources = (globalThis.Object.entries(object.resources ?? {}) as unknown as [string, ResourceSelector][]).reduce( (acc: { [key: string]: ResourceSelector }, [key, value]: [string, ResourceSelector]) => { if (value !== undefined) { acc[key] = ResourceSelector.fromPartial(value); @@ -2089,7 +2226,7 @@ export const Requirements: MessageFns = { }, {}, ); - message.schemas = (globalThis.Object.entries(object.schemas ?? {}) as [string, SchemaSelector][]).reduce( + message.schemas = (globalThis.Object.entries(object.schemas ?? {}) as unknown as [string, SchemaSelector][]).reduce( (acc: { [key: string]: SchemaSelector }, [key, value]: [string, SchemaSelector]) => { if (value !== undefined) { acc[key] = SchemaSelector.fromPartial(value); @@ -2102,11 +2239,18 @@ export const Requirements: MessageFns = { }, }; +messageTypeRegistry.set(Requirements.$type, Requirements); + function createBaseRequirements_ExtraResourcesEntry(): Requirements_ExtraResourcesEntry { - return { key: "", value: undefined }; + return { $type: "apiextensions.fn.proto.v1.Requirements.ExtraResourcesEntry", key: "", value: undefined }; } -export const Requirements_ExtraResourcesEntry: MessageFns = { +export const Requirements_ExtraResourcesEntry: MessageFns< + Requirements_ExtraResourcesEntry, + "apiextensions.fn.proto.v1.Requirements.ExtraResourcesEntry" +> = { + $type: "apiextensions.fn.proto.v1.Requirements.ExtraResourcesEntry" as const, + encode(message: Requirements_ExtraResourcesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.key !== "") { writer.uint32(10).string(message.key); @@ -2151,6 +2295,7 @@ export const Requirements_ExtraResourcesEntry: MessageFns = { +export const Requirements_ResourcesEntry: MessageFns< + Requirements_ResourcesEntry, + "apiextensions.fn.proto.v1.Requirements.ResourcesEntry" +> = { + $type: "apiextensions.fn.proto.v1.Requirements.ResourcesEntry" as const, + encode(message: Requirements_ResourcesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.key !== "") { writer.uint32(10).string(message.key); @@ -2233,6 +2385,7 @@ export const Requirements_ResourcesEntry: MessageFns = { +export const Requirements_SchemasEntry: MessageFns< + Requirements_SchemasEntry, + "apiextensions.fn.proto.v1.Requirements.SchemasEntry" +> = { + $type: "apiextensions.fn.proto.v1.Requirements.SchemasEntry" as const, + encode(message: Requirements_SchemasEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.key !== "") { writer.uint32(10).string(message.key); @@ -2311,6 +2471,7 @@ export const Requirements_SchemasEntry: MessageFns = fromJSON(object: any): Requirements_SchemasEntry { return { + $type: Requirements_SchemasEntry.$type, key: isSet(object.key) ? globalThis.String(object.key) : "", value: isSet(object.value) ? SchemaSelector.fromJSON(object.value) : undefined, }; @@ -2340,11 +2501,15 @@ export const Requirements_SchemasEntry: MessageFns = }, }; +messageTypeRegistry.set(Requirements_SchemasEntry.$type, Requirements_SchemasEntry); + function createBaseSchemaSelector(): SchemaSelector { - return { apiVersion: "", kind: "" }; + return { $type: "apiextensions.fn.proto.v1.SchemaSelector", apiVersion: "", kind: "" }; } -export const SchemaSelector: MessageFns = { +export const SchemaSelector: MessageFns = { + $type: "apiextensions.fn.proto.v1.SchemaSelector" as const, + encode(message: SchemaSelector, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.apiVersion !== "") { writer.uint32(10).string(message.apiVersion); @@ -2389,6 +2554,7 @@ export const SchemaSelector: MessageFns = { fromJSON(object: any): SchemaSelector { return { + $type: SchemaSelector.$type, apiVersion: isSet(object.apiVersion) ? globalThis.String(object.apiVersion) : isSet(object.api_version) @@ -2420,11 +2586,15 @@ export const SchemaSelector: MessageFns = { }, }; +messageTypeRegistry.set(SchemaSelector.$type, SchemaSelector); + function createBaseSchema(): Schema { - return { openapiV3: undefined }; + return { $type: "apiextensions.fn.proto.v1.Schema", openapiV3: undefined }; } -export const Schema: MessageFns = { +export const Schema: MessageFns = { + $type: "apiextensions.fn.proto.v1.Schema" as const, + encode(message: Schema, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.openapiV3 !== undefined) { Struct.encode(Struct.wrap(message.openapiV3), writer.uint32(10).fork()).join(); @@ -2458,6 +2628,7 @@ export const Schema: MessageFns = { fromJSON(object: any): Schema { return { + $type: Schema.$type, openapiV3: isObject(object.openapiV3) ? object.openapiV3 : isObject(object.openapi_v3) @@ -2484,11 +2655,22 @@ export const Schema: MessageFns = { }, }; +messageTypeRegistry.set(Schema.$type, Schema); + function createBaseResourceSelector(): ResourceSelector { - return { apiVersion: "", kind: "", matchName: undefined, matchLabels: undefined, namespace: undefined }; + return { + $type: "apiextensions.fn.proto.v1.ResourceSelector", + apiVersion: "", + kind: "", + matchName: undefined, + matchLabels: undefined, + namespace: undefined, + }; } -export const ResourceSelector: MessageFns = { +export const ResourceSelector: MessageFns = { + $type: "apiextensions.fn.proto.v1.ResourceSelector" as const, + encode(message: ResourceSelector, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.apiVersion !== "") { writer.uint32(10).string(message.apiVersion); @@ -2566,6 +2748,7 @@ export const ResourceSelector: MessageFns = { fromJSON(object: any): ResourceSelector { return { + $type: ResourceSelector.$type, apiVersion: isSet(object.apiVersion) ? globalThis.String(object.apiVersion) : isSet(object.api_version) @@ -2622,14 +2805,22 @@ export const ResourceSelector: MessageFns = { }, }; +messageTypeRegistry.set(ResourceSelector.$type, ResourceSelector); + function createBaseMatchLabels(): MatchLabels { - return { labels: {} }; + return { $type: "apiextensions.fn.proto.v1.MatchLabels", labels: {} }; } -export const MatchLabels: MessageFns = { +export const MatchLabels: MessageFns = { + $type: "apiextensions.fn.proto.v1.MatchLabels" as const, + encode(message: MatchLabels, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { globalThis.Object.entries(message.labels).forEach(([key, value]: [string, string]) => { - MatchLabels_LabelsEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join(); + MatchLabels_LabelsEntry.encode({ + $type: "apiextensions.fn.proto.v1.MatchLabels.LabelsEntry", + key: key as any, + value, + }, writer.uint32(10).fork()).join(); }); return writer; }, @@ -2663,6 +2854,7 @@ export const MatchLabels: MessageFns = { fromJSON(object: any): MatchLabels { return { + $type: MatchLabels.$type, labels: isObject(object.labels) ? (globalThis.Object.entries(object.labels) as [string, any][]).reduce( (acc: { [key: string]: string }, [key, value]: [string, any]) => { @@ -2707,11 +2899,18 @@ export const MatchLabels: MessageFns = { }, }; +messageTypeRegistry.set(MatchLabels.$type, MatchLabels); + function createBaseMatchLabels_LabelsEntry(): MatchLabels_LabelsEntry { - return { key: "", value: "" }; + return { $type: "apiextensions.fn.proto.v1.MatchLabels.LabelsEntry", key: "", value: "" }; } -export const MatchLabels_LabelsEntry: MessageFns = { +export const MatchLabels_LabelsEntry: MessageFns< + MatchLabels_LabelsEntry, + "apiextensions.fn.proto.v1.MatchLabels.LabelsEntry" +> = { + $type: "apiextensions.fn.proto.v1.MatchLabels.LabelsEntry" as const, + encode(message: MatchLabels_LabelsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.key !== "") { writer.uint32(10).string(message.key); @@ -2756,6 +2955,7 @@ export const MatchLabels_LabelsEntry: MessageFns = { fromJSON(object: any): MatchLabels_LabelsEntry { return { + $type: MatchLabels_LabelsEntry.$type, key: isSet(object.key) ? globalThis.String(object.key) : "", value: isSet(object.value) ? globalThis.String(object.value) : "", }; @@ -2783,11 +2983,15 @@ export const MatchLabels_LabelsEntry: MessageFns = { }, }; +messageTypeRegistry.set(MatchLabels_LabelsEntry.$type, MatchLabels_LabelsEntry); + function createBaseResponseMeta(): ResponseMeta { - return { tag: "", ttl: undefined }; + return { $type: "apiextensions.fn.proto.v1.ResponseMeta", tag: "", ttl: undefined }; } -export const ResponseMeta: MessageFns = { +export const ResponseMeta: MessageFns = { + $type: "apiextensions.fn.proto.v1.ResponseMeta" as const, + encode(message: ResponseMeta, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.tag !== "") { writer.uint32(10).string(message.tag); @@ -2832,6 +3036,7 @@ export const ResponseMeta: MessageFns = { fromJSON(object: any): ResponseMeta { return { + $type: ResponseMeta.$type, tag: isSet(object.tag) ? globalThis.String(object.tag) : "", ttl: isSet(object.ttl) ? Duration.fromJSON(object.ttl) : undefined, }; @@ -2859,17 +3064,24 @@ export const ResponseMeta: MessageFns = { }, }; +messageTypeRegistry.set(ResponseMeta.$type, ResponseMeta); + function createBaseState(): State { - return { composite: undefined, resources: {} }; + return { $type: "apiextensions.fn.proto.v1.State", composite: undefined, resources: {} }; } -export const State: MessageFns = { +export const State: MessageFns = { + $type: "apiextensions.fn.proto.v1.State" as const, + encode(message: State, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.composite !== undefined) { Resource.encode(message.composite, writer.uint32(10).fork()).join(); } globalThis.Object.entries(message.resources).forEach(([key, value]: [string, Resource]) => { - State_ResourcesEntry.encode({ key: key as any, value }, writer.uint32(18).fork()).join(); + State_ResourcesEntry.encode( + { $type: "apiextensions.fn.proto.v1.State.ResourcesEntry", key: key as any, value }, + writer.uint32(18).fork(), + ).join(); }); return writer; }, @@ -2911,6 +3123,7 @@ export const State: MessageFns = { fromJSON(object: any): State { return { + $type: State.$type, composite: isSet(object.composite) ? Resource.fromJSON(object.composite) : undefined, resources: isObject(object.resources) ? (globalThis.Object.entries(object.resources) as [string, any][]).reduce( @@ -2949,7 +3162,7 @@ export const State: MessageFns = { message.composite = (object.composite !== undefined && object.composite !== null) ? Resource.fromPartial(object.composite) : undefined; - message.resources = (globalThis.Object.entries(object.resources ?? {}) as [string, Resource][]).reduce( + message.resources = (globalThis.Object.entries(object.resources ?? {}) as unknown as [string, Resource][]).reduce( (acc: { [key: string]: Resource }, [key, value]: [string, Resource]) => { if (value !== undefined) { acc[key] = Resource.fromPartial(value); @@ -2962,95 +3175,109 @@ export const State: MessageFns = { }, }; +messageTypeRegistry.set(State.$type, State); + function createBaseState_ResourcesEntry(): State_ResourcesEntry { - return { key: "", value: undefined }; + return { $type: "apiextensions.fn.proto.v1.State.ResourcesEntry", key: "", value: undefined }; } -export const State_ResourcesEntry: MessageFns = { - encode(message: State_ResourcesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.key !== "") { - writer.uint32(10).string(message.key); - } - if (message.value !== undefined) { - Resource.encode(message.value, writer.uint32(18).fork()).join(); - } - return writer; - }, +export const State_ResourcesEntry: MessageFns = + { + $type: "apiextensions.fn.proto.v1.State.ResourcesEntry" as const, - decode(input: BinaryReader | Uint8Array, length?: number): State_ResourcesEntry { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseState_ResourcesEntry(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 10) { - break; - } - - message.key = reader.string(); - continue; - } - case 2: { - if (tag !== 18) { - break; - } - - message.value = Resource.decode(reader, reader.uint32()); - continue; - } + encode(message: State_ResourcesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== "") { + writer.uint32(10).string(message.key); } - if ((tag & 7) === 4 || tag === 0) { - break; + if (message.value !== undefined) { + Resource.encode(message.value, writer.uint32(18).fork()).join(); } - reader.skip(tag & 7); - } - return message; - }, + return writer; + }, - fromJSON(object: any): State_ResourcesEntry { - return { - key: isSet(object.key) ? globalThis.String(object.key) : "", - value: isSet(object.value) ? Resource.fromJSON(object.value) : undefined, - }; - }, + decode(input: BinaryReader | Uint8Array, length?: number): State_ResourcesEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseState_ResourcesEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } - toJSON(message: State_ResourcesEntry): unknown { - const obj: any = {}; - if (message.key !== "") { - obj.key = message.key; - } - if (message.value !== undefined) { - obj.value = Resource.toJSON(message.value); - } - return obj; - }, + message.key = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } - create, I>>(base?: I): State_ResourcesEntry { - return State_ResourcesEntry.fromPartial(base ?? ({} as any)); - }, - fromPartial, I>>(object: I): State_ResourcesEntry { - const message = createBaseState_ResourcesEntry(); - message.key = object.key ?? ""; - message.value = (object.value !== undefined && object.value !== null) - ? Resource.fromPartial(object.value) - : undefined; - return message; - }, -}; + message.value = Resource.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): State_ResourcesEntry { + return { + $type: State_ResourcesEntry.$type, + key: isSet(object.key) ? globalThis.String(object.key) : "", + value: isSet(object.value) ? Resource.fromJSON(object.value) : undefined, + }; + }, + + toJSON(message: State_ResourcesEntry): unknown { + const obj: any = {}; + if (message.key !== "") { + obj.key = message.key; + } + if (message.value !== undefined) { + obj.value = Resource.toJSON(message.value); + } + return obj; + }, + + create, I>>(base?: I): State_ResourcesEntry { + return State_ResourcesEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): State_ResourcesEntry { + const message = createBaseState_ResourcesEntry(); + message.key = object.key ?? ""; + message.value = (object.value !== undefined && object.value !== null) + ? Resource.fromPartial(object.value) + : undefined; + return message; + }, + }; + +messageTypeRegistry.set(State_ResourcesEntry.$type, State_ResourcesEntry); function createBaseResource(): Resource { - return { resource: undefined, connectionDetails: {}, ready: 0 }; + return { $type: "apiextensions.fn.proto.v1.Resource", resource: undefined, connectionDetails: {}, ready: 0 }; } -export const Resource: MessageFns = { +export const Resource: MessageFns = { + $type: "apiextensions.fn.proto.v1.Resource" as const, + encode(message: Resource, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.resource !== undefined) { Struct.encode(Struct.wrap(message.resource), writer.uint32(10).fork()).join(); } globalThis.Object.entries(message.connectionDetails).forEach(([key, value]: [string, Buffer]) => { - Resource_ConnectionDetailsEntry.encode({ key: key as any, value }, writer.uint32(18).fork()).join(); + Resource_ConnectionDetailsEntry.encode({ + $type: "apiextensions.fn.proto.v1.Resource.ConnectionDetailsEntry", + key: key as any, + value, + }, writer.uint32(18).fork()).join(); }); if (message.ready !== 0) { writer.uint32(24).int32(message.ready); @@ -3103,6 +3330,7 @@ export const Resource: MessageFns = { fromJSON(object: any): Resource { return { + $type: Resource.$type, resource: isObject(object.resource) ? object.resource : undefined, connectionDetails: isObject(object.connectionDetails) ? (globalThis.Object.entries(object.connectionDetails) as [string, any][]).reduce( @@ -3163,11 +3391,18 @@ export const Resource: MessageFns = { }, }; +messageTypeRegistry.set(Resource.$type, Resource); + function createBaseResource_ConnectionDetailsEntry(): Resource_ConnectionDetailsEntry { - return { key: "", value: Buffer.alloc(0) }; + return { $type: "apiextensions.fn.proto.v1.Resource.ConnectionDetailsEntry", key: "", value: Buffer.alloc(0) }; } -export const Resource_ConnectionDetailsEntry: MessageFns = { +export const Resource_ConnectionDetailsEntry: MessageFns< + Resource_ConnectionDetailsEntry, + "apiextensions.fn.proto.v1.Resource.ConnectionDetailsEntry" +> = { + $type: "apiextensions.fn.proto.v1.Resource.ConnectionDetailsEntry" as const, + encode(message: Resource_ConnectionDetailsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.key !== "") { writer.uint32(10).string(message.key); @@ -3212,6 +3447,7 @@ export const Resource_ConnectionDetailsEntry: MessageFns = { +export const Result: MessageFns = { + $type: "apiextensions.fn.proto.v1.Result" as const, + encode(message: Result, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.severity !== 0) { writer.uint32(8).int32(message.severity); @@ -3312,6 +3552,7 @@ export const Result: MessageFns = { fromJSON(object: any): Result { return { + $type: Result.$type, severity: isSet(object.severity) ? severityFromJSON(object.severity) : 0, message: isSet(object.message) ? globalThis.String(object.message) : "", reason: isSet(object.reason) ? globalThis.String(object.reason) : undefined, @@ -3349,11 +3590,22 @@ export const Result: MessageFns = { }, }; +messageTypeRegistry.set(Result.$type, Result); + function createBaseCondition(): Condition { - return { type: "", status: 0, reason: "", message: undefined, target: undefined }; + return { + $type: "apiextensions.fn.proto.v1.Condition", + type: "", + status: 0, + reason: "", + message: undefined, + target: undefined, + }; } -export const Condition: MessageFns = { +export const Condition: MessageFns = { + $type: "apiextensions.fn.proto.v1.Condition" as const, + encode(message: Condition, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { if (message.type !== "") { writer.uint32(10).string(message.type); @@ -3431,6 +3683,7 @@ export const Condition: MessageFns = { fromJSON(object: any): Condition { return { + $type: Condition.$type, type: isSet(object.type) ? globalThis.String(object.type) : "", status: isSet(object.status) ? statusFromJSON(object.status) : 0, reason: isSet(object.reason) ? globalThis.String(object.reason) : "", @@ -3473,6 +3726,8 @@ export const Condition: MessageFns = { }, }; +messageTypeRegistry.set(Condition.$type, Condition); + /** A FunctionRunnerService is a function. */ export type FunctionRunnerServiceService = typeof FunctionRunnerServiceService; export const FunctionRunnerServiceService = { @@ -3543,12 +3798,12 @@ type Builtin = Date | Function | Uint8Array | string | number | boolean | undefi export type DeepPartial = T extends Builtin ? T : T extends globalThis.Array ? globalThis.Array> : T extends ReadonlyArray ? ReadonlyArray> - : T extends {} ? { [K in keyof T]?: DeepPartial } + : T extends {} ? { [K in Exclude]?: DeepPartial } : Partial; type KeysOfUnion = T extends T ? keyof T : never; export type Exact = P extends Builtin ? P - : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + : P & { [K in keyof P]: Exact } & { [K in Exclude | "$type">]: never }; function isObject(value: any): boolean { return typeof value === "object" && value !== null; @@ -3558,7 +3813,8 @@ function isSet(value: any): boolean { return value !== null && value !== undefined; } -export interface MessageFns { +export interface MessageFns { + readonly $type: V; encode(message: T, writer?: BinaryWriter): BinaryWriter; decode(input: BinaryReader | Uint8Array, length?: number): T; fromJSON(object: any): T; diff --git a/src/proto/typeRegistry.ts b/src/proto/typeRegistry.ts new file mode 100644 index 0000000..9b4c292 --- /dev/null +++ b/src/proto/typeRegistry.ts @@ -0,0 +1,27 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.11.4 +// protoc v6.33.4 + +/* eslint-disable */ +import type { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; + +export interface MessageType { + $type: Message["$type"]; + encode(message: Message, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): Message; + fromJSON(object: any): Message; + toJSON(message: Message): unknown; + fromPartial(object: DeepPartial): Message; +} + +export type UnknownMessage = { $type: string }; + +export const messageTypeRegistry = new Map(); + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; +export type DeepPartial = T extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in Exclude]?: DeepPartial } + : Partial; diff --git a/src/request/request.ts b/src/request/request.ts index 1d683bb..27b5275 100644 --- a/src/request/request.ts +++ b/src/request/request.ts @@ -277,11 +277,13 @@ export function getRequiredResource(req: RunFunctionRequest, name: string): [Res continue; } - out.push({ - resource: item.resource, - connectionDetails: item.connectionDetails || {}, - ready: item.ready || 0, - }); + out.push( + Resource.create({ + resource: item.resource, + connectionDetails: item.connectionDetails || {}, + ready: item.ready || 0, + }) + ); } return [out, true]; diff --git a/src/resource/resource.ts b/src/resource/resource.ts index 4ace76f..e18a0f9 100644 --- a/src/resource/resource.ts +++ b/src/resource/resource.ts @@ -230,16 +230,19 @@ export function fromModel>( * * This function performs a deep merge of the source object into the target Resource, * allowing you to update specific fields while preserving others. The source can be - * a plain JavaScript object, a protobuf Struct (Record), or a - * Resource object. + * a plain JavaScript object or a protobuf Resource object. * - * The merge semantics match the Python SDK's behavior (similar to a dictionary's - * update method): fields that don't exist will be added, and fields that exist will - * be overwritten. By default, arrays are replaced rather than concatenated to match - * Python SDK behavior. + * The merge semantics match the Python SDK's behavior: fields that don't exist will + * be added, and fields that exist will be overwritten. By default, arrays are replaced + * rather than concatenated to match Python SDK behavior. + * + * When the source is a protobuf Resource (detected via the `$type` property), only its + * `resource` field is merged. When the source is a plain object with a top-level + * `resource` property, that property is treated as the payload. If the plain object + * also has a top-level `metadata` field, both are merged into the resource data. * * @param r - The Resource to update - * @param source - The source data to merge (plain object, Struct, or Resource) + * @param source - The source data to merge (plain object or protobuf Resource) * @param options - Optional merge configuration (default: { mergeArrays: false }) * * @example @@ -288,14 +291,13 @@ export function update( // Default to Python SDK behavior: replace arrays rather than concatenating const mergeArrays = options?.mergeArrays ?? false; - // Detect genuine protobuf `Resource` instances by checking for protobuf-specific fields - // (the generated Resource interface includes `connectionDetails` and `ready`). + // Detect genuine protobuf `Resource` instances by checking for the $type property + // that is automatically added by protoc-gen-ts_proto when outputTypeRegistry=true const isProtoResource = typeof source === 'object' && source !== null && - 'resource' in source && - typeof (source as { resource?: unknown }).resource === 'object' && - ('connectionDetails' in source || 'ready' in source); + '$type' in source && + (source as { $type?: string }).$type === 'apiextensions.fn.proto.v1.Resource'; let sourceData: Record; diff --git a/src/response/response.test.ts b/src/response/response.test.ts index e39c21b..36165f4 100644 --- a/src/response/response.test.ts +++ b/src/response/response.test.ts @@ -461,6 +461,7 @@ describe('requireSchema', () => { expect(result.requirements).toBeDefined(); expect(result.requirements?.schemas).toBeDefined(); expect(result.requirements?.schemas?.['xr-schema']).toEqual({ + $type: 'apiextensions.fn.proto.v1.SchemaSelector', apiVersion: 'example.org/v1', kind: 'MyResource', }); @@ -490,6 +491,7 @@ describe('requireSchema', () => { expect(result.requirements?.resources?.['existing-resource']).toBeDefined(); expect(result.requirements?.schemas?.['composite-schema']).toEqual({ + $type: 'apiextensions.fn.proto.v1.SchemaSelector', apiVersion: 'database.example.org/v1', kind: 'Database', }); @@ -537,6 +539,7 @@ describe('requireSchema', () => { const result = requireSchema(rsp, 'my-schema', 'new.example.org/v2', 'NewKind'); expect(result.requirements?.schemas?.['my-schema']).toEqual({ + $type: 'apiextensions.fn.proto.v1.SchemaSelector', apiVersion: 'new.example.org/v2', kind: 'NewKind', }); diff --git a/src/response/response.ts b/src/response/response.ts index 1550d83..1794827 100644 --- a/src/response/response.ts +++ b/src/response/response.ts @@ -14,6 +14,13 @@ import { Ready, ResourceSelector, } from '../proto/run_function.js'; +import { + State, + ResponseMeta, + Result, + Requirements, + SchemaSelector, +} from '../proto/run_function.js'; import { Duration } from '../proto/google/protobuf/duration.js'; import { merge } from 'ts-deepmerge'; @@ -21,7 +28,7 @@ import { merge } from 'ts-deepmerge'; * Default time-to-live for function responses (60 seconds). * Crossplane will call the function again when the TTL expires. */ -const DEFAULT_TTL: Duration = { seconds: 60, nanos: 0 }; +const DEFAULT_TTL = Duration.create({ seconds: 60, nanos: 0 }); export { DEFAULT_TTL }; @@ -58,7 +65,7 @@ export function to(req: RunFunctionRequest, ttl?: Duration): RunFunctionResponse // If desired is not set, initialize it if (!desired) { - desired = { composite: undefined, resources: {} }; + desired = State.create({ composite: undefined, resources: {} }); } // If composite is explicitly null, initialize it as an empty resource @@ -66,14 +73,14 @@ export function to(req: RunFunctionRequest, ttl?: Duration): RunFunctionResponse desired.composite = Resource.fromJSON({}); } - return { + return RunFunctionResponse.create({ conditions: [], context: req.context, desired: desired, - meta: { tag: req.meta?.tag || '', ttl: ttl || DEFAULT_TTL }, + meta: ResponseMeta.create({ tag: req.meta?.tag || '', ttl: ttl || DEFAULT_TTL }), requirements: undefined, results: [], - }; + }); } type NamedResource = { @@ -131,10 +138,12 @@ export function updateDesiredComposedResources( */ export function fatal(rsp: RunFunctionResponse, message: string): RunFunctionResponse { if (rsp && rsp.results) { - rsp.results.push({ - severity: Severity.SEVERITY_FATAL, - message: message, - }); + rsp.results.push( + Result.create({ + severity: Severity.SEVERITY_FATAL, + message: message, + }) + ); } return rsp; } @@ -156,10 +165,12 @@ export function fatal(rsp: RunFunctionResponse, message: string): RunFunctionRes */ export function normal(rsp: RunFunctionResponse, message: string) { if (rsp && rsp.results) { - rsp.results.push({ - severity: Severity.SEVERITY_NORMAL, - message: message, - }); + rsp.results.push( + Result.create({ + severity: Severity.SEVERITY_NORMAL, + message: message, + }) + ); } } @@ -182,10 +193,12 @@ export function normal(rsp: RunFunctionResponse, message: string) { */ export function warning(rsp: RunFunctionResponse, message: string) { if (rsp && rsp.results) { - rsp.results.push({ - severity: Severity.SEVERITY_WARNING, - message: message, - }); + rsp.results.push( + Result.create({ + severity: Severity.SEVERITY_WARNING, + message: message, + }) + ); } } @@ -218,7 +231,7 @@ export function setDesiredComposedResources( ): RunFunctionResponse { // Ensure desired state exists if (!rsp.desired) { - rsp.desired = { composite: undefined, resources: {} }; + rsp.desired = State.create({ composite: undefined, resources: {} }); } // Merge the new resources with existing ones @@ -268,7 +281,7 @@ export function setDesiredResources( ): RunFunctionResponse { // Ensure desired state exists if (!rsp.desired) { - rsp.desired = { composite: undefined, resources: {} }; + rsp.desired = State.create({ composite: undefined, resources: {} }); } // Convert each resource to Resource format @@ -342,7 +355,7 @@ export function setDesiredCompositeStatus({ }): RunFunctionResponse { // Ensure desired state exists if (!rsp.desired) { - rsp.desired = { composite: undefined, resources: {} }; + rsp.desired = State.create({ composite: undefined, resources: {} }); } // Ensure composite exists @@ -423,7 +436,7 @@ export function setDesiredCompositeResource( ready?: Ready ): RunFunctionResponse { if (!rsp.desired) { - rsp.desired = { composite: undefined, resources: {} }; + rsp.desired = State.create({ composite: undefined, resources: {} }); } // Create a new resource with the specified ready status using fromPartial @@ -502,19 +515,19 @@ export function requireSchema( kind: string ): RunFunctionResponse { if (!rsp.requirements) { - rsp.requirements = { + rsp.requirements = Requirements.create({ extraResources: {}, resources: {}, schemas: {}, - }; + }); } if (!rsp.requirements.schemas) { rsp.requirements.schemas = {}; } - rsp.requirements.schemas[name] = { + rsp.requirements.schemas[name] = SchemaSelector.create({ apiVersion, kind, - }; + }); return rsp; } @@ -570,11 +583,11 @@ export function requireResource( selector: ResourceSelector ): RunFunctionResponse { if (!rsp.requirements) { - rsp.requirements = { + rsp.requirements = Requirements.create({ extraResources: {}, resources: {}, schemas: {}, - }; + }); } if (!rsp.requirements.resources) { rsp.requirements.resources = {}; From 94394a499b486268762f78177d21c796445e75db Mon Sep 17 00:00:00 2001 From: Steven Borrelli Date: Thu, 5 Mar 2026 18:47:44 +0100 Subject: [PATCH 3/4] add bufbuild/protobuf Signed-off-by: Steven Borrelli --- package-lock.json | 1 + package.json | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index ec63b20..fe597a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.5.0", "license": "Apache-2.0", "dependencies": { + "@bufbuild/protobuf": "^2.11.0", "@grpc/grpc-js": "^1.14.3", "@grpc/proto-loader": "^0.8.0", "google-protobuf": "^4.0.1", diff --git a/package.json b/package.json index ddcae3b..760427c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@crossplane-org/function-sdk-typescript", - "version": "0.5.0", + "version": "0.4.0", "description": "A Crossplane Function SDK for Typescript", "keywords": [ "crossplane", @@ -41,6 +41,7 @@ "format:check": "prettier --check \"src/**/*.{ts,tsx,json,md}\"" }, "dependencies": { + "@bufbuild/protobuf": "^2.11.0", "@grpc/grpc-js": "^1.14.3", "@grpc/proto-loader": "^0.8.0", "google-protobuf": "^4.0.1", @@ -61,4 +62,4 @@ "typescript-eslint": "^8.56.1", "vitest": "^4.0.16" } -} \ No newline at end of file +} From c8760b2349f0013e554e42d7ecf45d18df042b78 Mon Sep 17 00:00:00 2001 From: Steven Borrelli Date: Thu, 5 Mar 2026 22:04:37 +0100 Subject: [PATCH 4/4] use forked ts-proto to generate Signed-off-by: Steven Borrelli --- package-lock.json | 6 +- package.json | 2 +- src/proto/google/protobuf/struct.ts | 6 +- src/proto/run_function.ts | 146 ++++++++++++++-------------- 4 files changed, 82 insertions(+), 78 deletions(-) diff --git a/package-lock.json b/package-lock.json index fe597a5..0d76e8c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@crossplane-org/function-sdk-typescript", - "version": "0.5.0", + "version": "0.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@crossplane-org/function-sdk-typescript", - "version": "0.5.0", + "version": "0.4.0", "license": "Apache-2.0", "dependencies": { "@bufbuild/protobuf": "^2.11.0", @@ -16,7 +16,7 @@ "kubernetes-models": "^4.5.1", "pino": "^10.1.0", "ts-deepmerge": "^7.0.3", - "ts-proto": "^2.10.1" + "ts-proto": "^2.11.4" }, "devDependencies": { "@eslint/js": "^9.39.2", diff --git a/package.json b/package.json index 760427c..87f552a 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "kubernetes-models": "^4.5.1", "pino": "^10.1.0", "ts-deepmerge": "^7.0.3", - "ts-proto": "^2.10.1" + "ts-proto": "stevendborrelli/ts-proto#fix-type-annotations" }, "devDependencies": { "@eslint/js": "^9.39.2", diff --git a/src/proto/google/protobuf/struct.ts b/src/proto/google/protobuf/struct.ts index 6fbbdce..858eaee 100644 --- a/src/proto/google/protobuf/struct.ts +++ b/src/proto/google/protobuf/struct.ts @@ -161,7 +161,7 @@ export const Struct: MessageFns & StructWrappe return { $type: Struct.$type, fields: isObject(object.fields) - ? (globalThis.Object.entries(object.fields) as [string, any][]).reduce( + ? (globalThis.Object.entries(object.fields) as unknown as [string, any][]).reduce( (acc: { [key: string]: any | undefined }, [key, value]: [string, any]) => { acc[key] = value as any | undefined; return acc; @@ -175,7 +175,7 @@ export const Struct: MessageFns & StructWrappe toJSON(message: Struct): unknown { const obj: any = {}; if (message.fields) { - const entries = globalThis.Object.entries(message.fields) as [string, any | undefined][]; + const entries = globalThis.Object.entries(message.fields) as unknown as [string, any | undefined][]; if (entries.length > 0) { obj.fields = {}; entries.forEach(([k, v]) => { @@ -191,7 +191,7 @@ export const Struct: MessageFns & StructWrappe }, fromPartial, I>>(object: I): Struct { const message = createBaseStruct(); - message.fields = (globalThis.Object.entries(object.fields ?? {}) as [string, any | undefined][]).reduce( + message.fields = (globalThis.Object.entries(object.fields ?? {}) as unknown as [string, any | undefined][]).reduce( (acc: { [key: string]: any | undefined }, [key, value]: [string, any | undefined]) => { if (value !== undefined) { acc[key] = value; diff --git a/src/proto/run_function.ts b/src/proto/run_function.ts index b84a480..8f594d0 100644 --- a/src/proto/run_function.ts +++ b/src/proto/run_function.ts @@ -930,7 +930,7 @@ export const RunFunctionRequest: MessageFns { acc[key] = Resources.fromJSON(value); return acc; @@ -938,7 +938,7 @@ export const RunFunctionRequest: MessageFns { acc[key] = Resources.fromJSON(value); return acc; @@ -947,7 +947,7 @@ export const RunFunctionRequest: MessageFns { acc[key] = Credentials.fromJSON(value); return acc; @@ -956,7 +956,7 @@ export const RunFunctionRequest: MessageFns { acc[key] = Resources.fromJSON(value); return acc; @@ -964,7 +964,7 @@ export const RunFunctionRequest: MessageFns { acc[key] = Resources.fromJSON(value); return acc; @@ -973,7 +973,7 @@ export const RunFunctionRequest: MessageFns { acc[key] = Schema.fromJSON(value); return acc; @@ -981,7 +981,7 @@ export const RunFunctionRequest: MessageFns { acc[key] = Schema.fromJSON(value); return acc; @@ -1010,7 +1010,7 @@ export const RunFunctionRequest: MessageFns 0) { obj.extraResources = {}; entries.forEach(([k, v]) => { @@ -1019,7 +1019,7 @@ export const RunFunctionRequest: MessageFns 0) { obj.credentials = {}; entries.forEach(([k, v]) => { @@ -1028,7 +1028,7 @@ export const RunFunctionRequest: MessageFns 0) { obj.requiredResources = {}; entries.forEach(([k, v]) => { @@ -1037,7 +1037,7 @@ export const RunFunctionRequest: MessageFns 0) { obj.requiredSchemas = {}; entries.forEach(([k, v]) => { @@ -1064,40 +1064,40 @@ export const RunFunctionRequest: MessageFns { - if (value !== undefined) { - acc[key] = Resources.fromPartial(value); - } - return acc; - }, - {}, - ); - message.credentials = (globalThis.Object.entries(object.credentials ?? {}) as unknown as [string, Credentials][]).reduce( - (acc: { [key: string]: Credentials }, [key, value]: [string, Credentials]) => { + message.extraResources = + (globalThis.Object.entries(object.extraResources ?? {}) as unknown as [string, Resources][]).reduce( + (acc: { [key: string]: Resources }, [key, value]: [string, Resources]) => { + if (value !== undefined) { + acc[key] = Resources.fromPartial(value); + } + return acc; + }, + {}, + ); + message.credentials = (globalThis.Object.entries(object.credentials ?? {}) as unknown as [string, Credentials][]) + .reduce((acc: { [key: string]: Credentials }, [key, value]: [string, Credentials]) => { if (value !== undefined) { acc[key] = Credentials.fromPartial(value); } return acc; - }, - {}, - ); - message.requiredResources = (globalThis.Object.entries(object.requiredResources ?? {}) as unknown as [string, Resources][]) - .reduce((acc: { [key: string]: Resources }, [key, value]: [string, Resources]) => { - if (value !== undefined) { - acc[key] = Resources.fromPartial(value); - } - return acc; }, {}); - message.requiredSchemas = (globalThis.Object.entries(object.requiredSchemas ?? {}) as unknown as [string, Schema][]).reduce( - (acc: { [key: string]: Schema }, [key, value]: [string, Schema]) => { + message.requiredResources = + (globalThis.Object.entries(object.requiredResources ?? {}) as unknown as [string, Resources][]).reduce( + (acc: { [key: string]: Resources }, [key, value]: [string, Resources]) => { + if (value !== undefined) { + acc[key] = Resources.fromPartial(value); + } + return acc; + }, + {}, + ); + message.requiredSchemas = (globalThis.Object.entries(object.requiredSchemas ?? {}) as unknown as [string, Schema][]) + .reduce((acc: { [key: string]: Schema }, [key, value]: [string, Schema]) => { if (value !== undefined) { acc[key] = Schema.fromPartial(value); } return acc; - }, - {}, - ); + }, {}); return message; }, }; @@ -1584,7 +1584,7 @@ export const CredentialData: MessageFns { acc[key] = Buffer.from(bytesFromBase64(value as string)); return acc; @@ -1598,7 +1598,7 @@ export const CredentialData: MessageFns 0) { obj.data = {}; entries.forEach(([k, v]) => { @@ -1614,7 +1614,7 @@ export const CredentialData: MessageFns, I>>(object: I): CredentialData { const message = createBaseCredentialData(); - message.data = (globalThis.Object.entries(object.data ?? {}) as [string, Buffer][]).reduce( + message.data = (globalThis.Object.entries(object.data ?? {}) as unknown as [string, Buffer][]).reduce( (acc: { [key: string]: Buffer }, [key, value]: [string, Buffer]) => { if (value !== undefined) { acc[key] = value; @@ -2136,7 +2136,7 @@ export const Requirements: MessageFns { acc[key] = ResourceSelector.fromJSON(value); return acc; @@ -2144,7 +2144,7 @@ export const Requirements: MessageFns { acc[key] = ResourceSelector.fromJSON(value); return acc; @@ -2153,7 +2153,7 @@ export const Requirements: MessageFns { acc[key] = ResourceSelector.fromJSON(value); return acc; @@ -2162,7 +2162,7 @@ export const Requirements: MessageFns { acc[key] = SchemaSelector.fromJSON(value); return acc; @@ -2176,7 +2176,7 @@ export const Requirements: MessageFns 0) { obj.extraResources = {}; entries.forEach(([k, v]) => { @@ -2185,7 +2185,7 @@ export const Requirements: MessageFns 0) { obj.resources = {}; entries.forEach(([k, v]) => { @@ -2194,7 +2194,7 @@ export const Requirements: MessageFns 0) { obj.schemas = {}; entries.forEach(([k, v]) => { @@ -2210,22 +2210,23 @@ export const Requirements: MessageFns, I>>(object: I): Requirements { const message = createBaseRequirements(); - message.extraResources = (globalThis.Object.entries(object.extraResources ?? {}) as unknown as [string, ResourceSelector][]) + message.extraResources = + (globalThis.Object.entries(object.extraResources ?? {}) as unknown as [string, ResourceSelector][]).reduce( + (acc: { [key: string]: ResourceSelector }, [key, value]: [string, ResourceSelector]) => { + if (value !== undefined) { + acc[key] = ResourceSelector.fromPartial(value); + } + return acc; + }, + {}, + ); + message.resources = (globalThis.Object.entries(object.resources ?? {}) as unknown as [string, ResourceSelector][]) .reduce((acc: { [key: string]: ResourceSelector }, [key, value]: [string, ResourceSelector]) => { if (value !== undefined) { acc[key] = ResourceSelector.fromPartial(value); } return acc; }, {}); - message.resources = (globalThis.Object.entries(object.resources ?? {}) as unknown as [string, ResourceSelector][]).reduce( - (acc: { [key: string]: ResourceSelector }, [key, value]: [string, ResourceSelector]) => { - if (value !== undefined) { - acc[key] = ResourceSelector.fromPartial(value); - } - return acc; - }, - {}, - ); message.schemas = (globalThis.Object.entries(object.schemas ?? {}) as unknown as [string, SchemaSelector][]).reduce( (acc: { [key: string]: SchemaSelector }, [key, value]: [string, SchemaSelector]) => { if (value !== undefined) { @@ -2856,7 +2857,7 @@ export const MatchLabels: MessageFns { acc[key] = globalThis.String(value); return acc; @@ -2870,7 +2871,7 @@ export const MatchLabels: MessageFns 0) { obj.labels = {}; entries.forEach(([k, v]) => { @@ -2886,7 +2887,7 @@ export const MatchLabels: MessageFns, I>>(object: I): MatchLabels { const message = createBaseMatchLabels(); - message.labels = (globalThis.Object.entries(object.labels ?? {}) as [string, string][]).reduce( + message.labels = (globalThis.Object.entries(object.labels ?? {}) as unknown as [string, string][]).reduce( (acc: { [key: string]: string }, [key, value]: [string, string]) => { if (value !== undefined) { acc[key] = globalThis.String(value); @@ -3126,7 +3127,7 @@ export const State: MessageFns = { $type: State.$type, composite: isSet(object.composite) ? Resource.fromJSON(object.composite) : undefined, resources: isObject(object.resources) - ? (globalThis.Object.entries(object.resources) as [string, any][]).reduce( + ? (globalThis.Object.entries(object.resources) as unknown as [string, any][]).reduce( (acc: { [key: string]: Resource }, [key, value]: [string, any]) => { acc[key] = Resource.fromJSON(value); return acc; @@ -3143,7 +3144,7 @@ export const State: MessageFns = { obj.composite = Resource.toJSON(message.composite); } if (message.resources) { - const entries = globalThis.Object.entries(message.resources) as [string, Resource][]; + const entries = globalThis.Object.entries(message.resources) as unknown as [string, Resource][]; if (entries.length > 0) { obj.resources = {}; entries.forEach(([k, v]) => { @@ -3333,7 +3334,7 @@ export const Resource: MessageFns { acc[key] = Buffer.from(bytesFromBase64(value as string)); return acc; @@ -3341,7 +3342,7 @@ export const Resource: MessageFns { acc[key] = Buffer.from(bytesFromBase64(value as string)); return acc; @@ -3359,7 +3360,7 @@ export const Resource: MessageFns 0) { obj.connectionDetails = {}; entries.forEach(([k, v]) => { @@ -3379,13 +3380,16 @@ export const Resource: MessageFns, I>>(object: I): Resource { const message = createBaseResource(); message.resource = object.resource ?? undefined; - message.connectionDetails = (globalThis.Object.entries(object.connectionDetails ?? {}) as [string, Buffer][]) - .reduce((acc: { [key: string]: Buffer }, [key, value]: [string, Buffer]) => { - if (value !== undefined) { - acc[key] = value; - } - return acc; - }, {}); + message.connectionDetails = + (globalThis.Object.entries(object.connectionDetails ?? {}) as unknown as [string, Buffer][]).reduce( + (acc: { [key: string]: Buffer }, [key, value]: [string, Buffer]) => { + if (value !== undefined) { + acc[key] = value; + } + return acc; + }, + {}, + ); message.ready = object.ready ?? 0; return message; },