diff --git a/integration/grpc-js/google/protobuf/struct.ts b/integration/grpc-js/google/protobuf/struct.ts index 3298aac71..6a3fc5696 100644 --- a/integration/grpc-js/google/protobuf/struct.ts +++ b/integration/grpc-js/google/protobuf/struct.ts @@ -162,7 +162,7 @@ export const Struct = { }, wrap(object: { [key: string]: any } | undefined): Struct { - const struct = Struct.fromPartial({}); + const struct = createBaseStruct(); if (object !== undefined) { Object.keys(object).forEach((key) => { struct.fields[key] = object[key]; @@ -340,23 +340,25 @@ export const Value = { }, wrap(value: any): Value { + const result = createBaseValue(); + if (value === null) { - return { nullValue: NullValue.NULL_VALUE } as Value; + result.nullValue = NullValue.NULL_VALUE; } else if (typeof value === 'boolean') { - return { boolValue: value } as Value; + result.boolValue = value; } else if (typeof value === 'number') { - return { numberValue: value } as Value; + result.numberValue = value; } else if (typeof value === 'string') { - return { stringValue: value } as Value; + result.stringValue = value; } else if (Array.isArray(value)) { - return { listValue: value } as Value; + result.listValue = value; } else if (typeof value === 'object') { - return { structValue: value } as Value; - } else if (typeof value === 'undefined') { - return {} as Value; - } else { + result.structValue = value; + } else if (typeof value !== 'undefined') { throw new Error('Unsupported any value type: ' + typeof value); } + + return result; }, unwrap(message: Value): string | number | boolean | Object | null | Array | undefined { @@ -430,7 +432,11 @@ export const ListValue = { }, wrap(value: Array | undefined): ListValue { - return { values: value ?? [] }; + const result = createBaseListValue(); + + result.values = value ?? []; + + return result; }, unwrap(message: ListValue): Array { diff --git a/integration/oneof-unions/google/protobuf/struct.ts b/integration/oneof-unions/google/protobuf/struct.ts index a35b55e8a..f524ec268 100644 --- a/integration/oneof-unions/google/protobuf/struct.ts +++ b/integration/oneof-unions/google/protobuf/struct.ts @@ -157,7 +157,7 @@ export const Struct = { }, wrap(object: { [key: string]: any } | undefined): Struct { - const struct = Struct.fromPartial({}); + const struct = createBaseStruct(); if (object !== undefined) { Object.keys(object).forEach((key) => { struct.fields[key] = object[key]; @@ -359,23 +359,25 @@ export const Value = { }, wrap(value: any): Value { + const result = createBaseValue(); + if (value === null) { - return { kind: { $case: 'nullValue', nullValue: NullValue.NULL_VALUE } }; + result.kind = { $case: 'nullValue', nullValue: NullValue.NULL_VALUE }; } else if (typeof value === 'boolean') { - return { kind: { $case: 'boolValue', boolValue: value } }; + result.kind = { $case: 'boolValue', boolValue: value }; } else if (typeof value === 'number') { - return { kind: { $case: 'numberValue', numberValue: value } }; + result.kind = { $case: 'numberValue', numberValue: value }; } else if (typeof value === 'string') { - return { kind: { $case: 'stringValue', stringValue: value } }; + result.kind = { $case: 'stringValue', stringValue: value }; } else if (Array.isArray(value)) { - return { kind: { $case: 'listValue', listValue: value } }; + result.kind = { $case: 'listValue', listValue: value }; } else if (typeof value === 'object') { - return { kind: { $case: 'structValue', structValue: value } }; - } else if (typeof value === 'undefined') { - return {} as Value; - } else { + result.kind = { $case: 'structValue', structValue: value }; + } else if (typeof value !== 'undefined') { throw new Error('Unsupported any value type: ' + typeof value); } + + return result; }, unwrap(message: Value): string | number | boolean | Object | null | Array | undefined { @@ -450,7 +452,11 @@ export const ListValue = { }, wrap(value: Array | undefined): ListValue { - return { values: value ?? [] }; + const result = createBaseListValue(); + + result.values = value ?? []; + + return result; }, unwrap(message: ListValue): Array { diff --git a/integration/simple-string-enums/google/protobuf/struct.ts b/integration/simple-string-enums/google/protobuf/struct.ts index f3adc17bb..47a6f2b7b 100644 --- a/integration/simple-string-enums/google/protobuf/struct.ts +++ b/integration/simple-string-enums/google/protobuf/struct.ts @@ -171,7 +171,7 @@ export const Struct = { }, wrap(object: { [key: string]: any } | undefined): Struct { - const struct = Struct.fromPartial({}); + const struct = createBaseStruct(); if (object !== undefined) { Object.keys(object).forEach((key) => { struct.fields[key] = object[key]; @@ -349,23 +349,25 @@ export const Value = { }, wrap(value: any): Value { + const result = createBaseValue(); + if (value === null) { - return { nullValue: NullValue.NULL_VALUE } as Value; + result.nullValue = NullValue.NULL_VALUE; } else if (typeof value === 'boolean') { - return { boolValue: value } as Value; + result.boolValue = value; } else if (typeof value === 'number') { - return { numberValue: value } as Value; + result.numberValue = value; } else if (typeof value === 'string') { - return { stringValue: value } as Value; + result.stringValue = value; } else if (Array.isArray(value)) { - return { listValue: value } as Value; + result.listValue = value; } else if (typeof value === 'object') { - return { structValue: value } as Value; - } else if (typeof value === 'undefined') { - return {} as Value; - } else { + result.structValue = value; + } else if (typeof value !== 'undefined') { throw new Error('Unsupported any value type: ' + typeof value); } + + return result; }, unwrap(message: Value): string | number | boolean | Object | null | Array | undefined { @@ -439,7 +441,11 @@ export const ListValue = { }, wrap(value: Array | undefined): ListValue { - return { values: value ?? [] }; + const result = createBaseListValue(); + + result.values = value ?? []; + + return result; }, unwrap(message: ListValue): Array { diff --git a/integration/struct/google/protobuf/struct.ts b/integration/struct/google/protobuf/struct.ts index 3298aac71..6a3fc5696 100644 --- a/integration/struct/google/protobuf/struct.ts +++ b/integration/struct/google/protobuf/struct.ts @@ -162,7 +162,7 @@ export const Struct = { }, wrap(object: { [key: string]: any } | undefined): Struct { - const struct = Struct.fromPartial({}); + const struct = createBaseStruct(); if (object !== undefined) { Object.keys(object).forEach((key) => { struct.fields[key] = object[key]; @@ -340,23 +340,25 @@ export const Value = { }, wrap(value: any): Value { + const result = createBaseValue(); + if (value === null) { - return { nullValue: NullValue.NULL_VALUE } as Value; + result.nullValue = NullValue.NULL_VALUE; } else if (typeof value === 'boolean') { - return { boolValue: value } as Value; + result.boolValue = value; } else if (typeof value === 'number') { - return { numberValue: value } as Value; + result.numberValue = value; } else if (typeof value === 'string') { - return { stringValue: value } as Value; + result.stringValue = value; } else if (Array.isArray(value)) { - return { listValue: value } as Value; + result.listValue = value; } else if (typeof value === 'object') { - return { structValue: value } as Value; - } else if (typeof value === 'undefined') { - return {} as Value; - } else { + result.structValue = value; + } else if (typeof value !== 'undefined') { throw new Error('Unsupported any value type: ' + typeof value); } + + return result; }, unwrap(message: Value): string | number | boolean | Object | null | Array | undefined { @@ -430,7 +432,11 @@ export const ListValue = { }, wrap(value: Array | undefined): ListValue { - return { values: value ?? [] }; + const result = createBaseListValue(); + + result.values = value ?? []; + + return result; }, unwrap(message: ListValue): Array { diff --git a/integration/type-registry/bar/bar.bin b/integration/type-registry/bar/bar.bin index 528ece108..3aa6c75d1 100644 Binary files a/integration/type-registry/bar/bar.bin and b/integration/type-registry/bar/bar.bin differ diff --git a/integration/type-registry/foo.bin b/integration/type-registry/foo.bin index f6f140796..85b788882 100644 Binary files a/integration/type-registry/foo.bin and b/integration/type-registry/foo.bin differ diff --git a/integration/type-registry/foo.proto b/integration/type-registry/foo.proto index 488e2f006..24f1432fc 100644 --- a/integration/type-registry/foo.proto +++ b/integration/type-registry/foo.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package foo; import "google/protobuf/timestamp.proto"; +import "google/protobuf/struct.proto"; message Foo { google.protobuf.Timestamp timestamp = 1; @@ -11,3 +12,7 @@ message Foo { message Foo2 { google.protobuf.Timestamp timestamp = 1; } + +message WithStruct { + google.protobuf.Struct struct = 1; +} \ No newline at end of file diff --git a/integration/type-registry/foo.ts b/integration/type-registry/foo.ts index ca8b55f96..59a1c3a85 100644 --- a/integration/type-registry/foo.ts +++ b/integration/type-registry/foo.ts @@ -3,6 +3,7 @@ import { messageTypeRegistry } from './typeRegistry'; import { util, configure, Writer, Reader } from 'protobufjs/minimal'; import * as Long from 'long'; import { Timestamp } from './google/protobuf/timestamp'; +import { Struct } from './google/protobuf/struct'; export const protobufPackage = 'foo'; @@ -16,6 +17,11 @@ export interface Foo2 { timestamp: Date | undefined; } +export interface WithStruct { + $type: 'foo.WithStruct'; + struct: { [key: string]: any } | undefined; +} + function createBaseFoo(): Foo { return { $type: 'foo.Foo', timestamp: undefined }; } @@ -124,6 +130,60 @@ export const Foo2 = { messageTypeRegistry.set(Foo2.$type, Foo2); +function createBaseWithStruct(): WithStruct { + return { $type: 'foo.WithStruct', struct: undefined }; +} + +export const WithStruct = { + $type: 'foo.WithStruct' as const, + + encode(message: WithStruct, writer: Writer = Writer.create()): Writer { + if (message.struct !== undefined) { + Struct.encode(Struct.wrap(message.struct), writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: Reader | Uint8Array, length?: number): WithStruct { + const reader = input instanceof Reader ? input : new Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseWithStruct(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.struct = Struct.unwrap(Struct.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): WithStruct { + return { + $type: WithStruct.$type, + struct: isObject(object.struct) ? object.struct : undefined, + }; + }, + + toJSON(message: WithStruct): unknown { + const obj: any = {}; + message.struct !== undefined && (obj.struct = message.struct); + return obj; + }, + + fromPartial, I>>(object: I): WithStruct { + const message = createBaseWithStruct(); + message.struct = object.struct ?? undefined; + return message; + }, +}; + +messageTypeRegistry.set(WithStruct.$type, WithStruct); + type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; export type DeepPartial = T extends Builtin @@ -170,6 +230,10 @@ if (util.Long !== Long) { configure(); } +function isObject(value: any): boolean { + return typeof value === 'object' && value !== null; +} + function isSet(value: any): boolean { return value !== null && value !== undefined; } diff --git a/integration/type-registry/google/protobuf/struct.ts b/integration/type-registry/google/protobuf/struct.ts new file mode 100644 index 000000000..a3d18eb06 --- /dev/null +++ b/integration/type-registry/google/protobuf/struct.ts @@ -0,0 +1,506 @@ +/* eslint-disable */ +import { messageTypeRegistry } from '../../typeRegistry'; +import { util, configure, Writer, Reader } from 'protobufjs/minimal'; +import * as Long from 'long'; + +export const protobufPackage = 'google.protobuf'; + +/** + * `NullValue` is a singleton enumeration to represent the null value for the + * `Value` type union. + * + * The JSON representation for `NullValue` is JSON `null`. + */ +export enum NullValue { + /** NULL_VALUE - Null value. */ + NULL_VALUE = 0, + UNRECOGNIZED = -1, +} + +export function nullValueFromJSON(object: any): NullValue { + switch (object) { + case 0: + case 'NULL_VALUE': + return NullValue.NULL_VALUE; + case -1: + case 'UNRECOGNIZED': + default: + return NullValue.UNRECOGNIZED; + } +} + +export function nullValueToJSON(object: NullValue): string { + switch (object) { + case NullValue.NULL_VALUE: + return 'NULL_VALUE'; + default: + return 'UNKNOWN'; + } +} + +/** + * `Struct` represents a structured data value, consisting of fields + * which map to dynamically typed values. In some languages, `Struct` + * might be supported by a native representation. For example, in + * scripting languages like JS a struct is represented as an + * object. The details of that representation are described together + * with the proto support for the language. + * + * 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; +} + +/** + * `Value` represents a dynamically typed value which can be either + * null, a number, a string, a boolean, a recursive struct value, or a + * list of values. A producer of value is expected to set one of these + * variants. Absence of any variant indicates an error. + * + * The JSON representation for `Value` is JSON value. + */ +export interface Value { + $type: 'google.protobuf.Value'; + /** Represents a null value. */ + nullValue: NullValue | undefined; + /** Represents a double value. */ + numberValue: number | undefined; + /** Represents a string value. */ + stringValue: string | undefined; + /** Represents a boolean value. */ + boolValue: boolean | undefined; + /** Represents a structured value. */ + structValue: { [key: string]: any } | undefined; + /** Represents a repeated `Value`. */ + listValue: Array | undefined; +} + +/** + * `ListValue` is a wrapper around a repeated field of values. + * + * 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 { $type: 'google.protobuf.Struct', fields: {} }; +} + +export const Struct = { + $type: 'google.protobuf.Struct' as const, + + encode(message: Struct, writer: Writer = Writer.create()): Writer { + Object.entries(message.fields).forEach(([key, value]) => { + if (value !== undefined) { + Struct_FieldsEntry.encode( + { $type: 'google.protobuf.Struct.FieldsEntry', key: key as any, value }, + writer.uint32(10).fork() + ).ldelim(); + } + }); + return writer; + }, + + decode(input: Reader | Uint8Array, length?: number): Struct { + const reader = input instanceof Reader ? input : new Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseStruct(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + const entry1 = Struct_FieldsEntry.decode(reader, reader.uint32()); + if (entry1.value !== undefined) { + message.fields[entry1.key] = entry1.value; + } + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Struct { + return { + $type: Struct.$type, + fields: isObject(object.fields) + ? Object.entries(object.fields).reduce<{ [key: string]: any | undefined }>((acc, [key, value]) => { + acc[key] = value as any | undefined; + return acc; + }, {}) + : {}, + }; + }, + + toJSON(message: Struct): unknown { + const obj: any = {}; + obj.fields = {}; + if (message.fields) { + Object.entries(message.fields).forEach(([k, v]) => { + obj.fields[k] = v; + }); + } + return obj; + }, + + fromPartial, I>>(object: I): Struct { + const message = createBaseStruct(); + message.fields = Object.entries(object.fields ?? {}).reduce<{ [key: string]: any | undefined }>( + (acc, [key, value]) => { + if (value !== undefined) { + acc[key] = value; + } + return acc; + }, + {} + ); + return message; + }, + + wrap(object: { [key: string]: any } | undefined): Struct { + const struct = createBaseStruct(); + if (object !== undefined) { + Object.keys(object).forEach((key) => { + struct.fields[key] = object[key]; + }); + } + return struct; + }, + + unwrap(message: Struct): { [key: string]: any } { + const object: { [key: string]: any } = {}; + Object.keys(message.fields).forEach((key) => { + object[key] = message.fields[key]; + }); + return object; + }, +}; + +messageTypeRegistry.set(Struct.$type, Struct); + +function createBaseStruct_FieldsEntry(): Struct_FieldsEntry { + return { $type: 'google.protobuf.Struct.FieldsEntry', key: '', value: undefined }; +} + +export const Struct_FieldsEntry = { + $type: 'google.protobuf.Struct.FieldsEntry' as const, + + encode(message: Struct_FieldsEntry, writer: Writer = Writer.create()): Writer { + if (message.key !== '') { + writer.uint32(10).string(message.key); + } + if (message.value !== undefined) { + Value.encode(Value.wrap(message.value), writer.uint32(18).fork()).ldelim(); + } + return writer; + }, + + decode(input: Reader | Uint8Array, length?: number): Struct_FieldsEntry { + const reader = input instanceof Reader ? input : new Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseStruct_FieldsEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.key = reader.string(); + break; + case 2: + message.value = Value.unwrap(Value.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Struct_FieldsEntry { + return { + $type: Struct_FieldsEntry.$type, + key: isSet(object.key) ? String(object.key) : '', + value: isSet(object?.value) ? object.value : undefined, + }; + }, + + toJSON(message: Struct_FieldsEntry): unknown { + const obj: any = {}; + message.key !== undefined && (obj.key = message.key); + message.value !== undefined && (obj.value = message.value); + return obj; + }, + + fromPartial, I>>(object: I): Struct_FieldsEntry { + const message = createBaseStruct_FieldsEntry(); + message.key = object.key ?? ''; + message.value = object.value ?? undefined; + return message; + }, +}; + +messageTypeRegistry.set(Struct_FieldsEntry.$type, Struct_FieldsEntry); + +function createBaseValue(): Value { + return { + $type: 'google.protobuf.Value', + nullValue: undefined, + numberValue: undefined, + stringValue: undefined, + boolValue: undefined, + structValue: undefined, + listValue: undefined, + }; +} + +export const Value = { + $type: 'google.protobuf.Value' as const, + + encode(message: Value, writer: Writer = Writer.create()): Writer { + if (message.nullValue !== undefined) { + writer.uint32(8).int32(message.nullValue); + } + if (message.numberValue !== undefined) { + writer.uint32(17).double(message.numberValue); + } + if (message.stringValue !== undefined) { + writer.uint32(26).string(message.stringValue); + } + if (message.boolValue !== undefined) { + writer.uint32(32).bool(message.boolValue); + } + if (message.structValue !== undefined) { + Struct.encode(Struct.wrap(message.structValue), writer.uint32(42).fork()).ldelim(); + } + if (message.listValue !== undefined) { + ListValue.encode(ListValue.wrap(message.listValue), writer.uint32(50).fork()).ldelim(); + } + return writer; + }, + + decode(input: Reader | Uint8Array, length?: number): Value { + const reader = input instanceof Reader ? input : new Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseValue(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.nullValue = reader.int32() as any; + break; + case 2: + message.numberValue = reader.double(); + break; + case 3: + message.stringValue = reader.string(); + break; + case 4: + message.boolValue = reader.bool(); + break; + case 5: + message.structValue = Struct.unwrap(Struct.decode(reader, reader.uint32())); + break; + case 6: + message.listValue = ListValue.unwrap(ListValue.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Value { + return { + $type: Value.$type, + nullValue: isSet(object.nullValue) ? nullValueFromJSON(object.nullValue) : undefined, + numberValue: isSet(object.numberValue) ? Number(object.numberValue) : undefined, + stringValue: isSet(object.stringValue) ? String(object.stringValue) : undefined, + boolValue: isSet(object.boolValue) ? Boolean(object.boolValue) : undefined, + structValue: isObject(object.structValue) ? object.structValue : undefined, + listValue: Array.isArray(object.listValue) ? [...object.listValue] : undefined, + }; + }, + + toJSON(message: Value): unknown { + const obj: any = {}; + message.nullValue !== undefined && + (obj.nullValue = message.nullValue !== undefined ? nullValueToJSON(message.nullValue) : undefined); + message.numberValue !== undefined && (obj.numberValue = message.numberValue); + message.stringValue !== undefined && (obj.stringValue = message.stringValue); + message.boolValue !== undefined && (obj.boolValue = message.boolValue); + message.structValue !== undefined && (obj.structValue = message.structValue); + message.listValue !== undefined && (obj.listValue = message.listValue); + return obj; + }, + + fromPartial, I>>(object: I): Value { + const message = createBaseValue(); + message.nullValue = object.nullValue ?? undefined; + message.numberValue = object.numberValue ?? undefined; + message.stringValue = object.stringValue ?? undefined; + message.boolValue = object.boolValue ?? undefined; + message.structValue = object.structValue ?? undefined; + message.listValue = object.listValue ?? undefined; + return message; + }, + + wrap(value: any): Value { + const result = createBaseValue(); + + if (value === null) { + result.nullValue = NullValue.NULL_VALUE; + } else if (typeof value === 'boolean') { + result.boolValue = value; + } else if (typeof value === 'number') { + result.numberValue = value; + } else if (typeof value === 'string') { + result.stringValue = value; + } else if (Array.isArray(value)) { + result.listValue = value; + } else if (typeof value === 'object') { + result.structValue = value; + } else if (typeof value !== 'undefined') { + throw new Error('Unsupported any value type: ' + typeof value); + } + + return result; + }, + + unwrap(message: Value): string | number | boolean | Object | null | Array | undefined { + if (message?.stringValue !== undefined) { + return message.stringValue; + } else if (message?.numberValue !== undefined) { + return message.numberValue; + } else if (message?.boolValue !== undefined) { + return message.boolValue; + } else if (message?.structValue !== undefined) { + return message.structValue; + } else if (message?.listValue !== undefined) { + return message.listValue; + } else if (message?.nullValue !== undefined) { + return null; + } + return undefined; + }, +}; + +messageTypeRegistry.set(Value.$type, Value); + +function createBaseListValue(): ListValue { + return { $type: 'google.protobuf.ListValue', values: [] }; +} + +export const ListValue = { + $type: 'google.protobuf.ListValue' as const, + + encode(message: ListValue, writer: Writer = Writer.create()): Writer { + for (const v of message.values) { + Value.encode(Value.wrap(v!), writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: Reader | Uint8Array, length?: number): ListValue { + const reader = input instanceof Reader ? input : new Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseListValue(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.values.push(Value.unwrap(Value.decode(reader, reader.uint32()))); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): ListValue { + return { + $type: ListValue.$type, + values: Array.isArray(object?.values) ? [...object.values] : [], + }; + }, + + toJSON(message: ListValue): unknown { + const obj: any = {}; + if (message.values) { + obj.values = message.values.map((e) => e); + } else { + obj.values = []; + } + return obj; + }, + + fromPartial, I>>(object: I): ListValue { + const message = createBaseListValue(); + message.values = object.values?.map((e) => e) || []; + return message; + }, + + wrap(value: Array | undefined): ListValue { + const result = createBaseListValue(); + + result.values = value ?? []; + + return result; + }, + + unwrap(message: ListValue): Array { + return message.values; + }, +}; + +messageTypeRegistry.set(ListValue.$type, ListValue); + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin + ? T + : T extends Array + ? Array> + : T extends ReadonlyArray + ? ReadonlyArray> + : 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 } & Record | '$type'>, never>; + +// If you get a compile-error about 'Constructor and ... have no overlap', +// add '--ts_proto_opt=esModuleInterop=true' as a flag when calling 'protoc'. +if (util.Long !== Long) { + util.Long = Long as any; + configure(); +} + +function isObject(value: any): boolean { + return typeof value === 'object' && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} diff --git a/integration/value/google/protobuf/struct.ts b/integration/value/google/protobuf/struct.ts index 3298aac71..6a3fc5696 100644 --- a/integration/value/google/protobuf/struct.ts +++ b/integration/value/google/protobuf/struct.ts @@ -162,7 +162,7 @@ export const Struct = { }, wrap(object: { [key: string]: any } | undefined): Struct { - const struct = Struct.fromPartial({}); + const struct = createBaseStruct(); if (object !== undefined) { Object.keys(object).forEach((key) => { struct.fields[key] = object[key]; @@ -340,23 +340,25 @@ export const Value = { }, wrap(value: any): Value { + const result = createBaseValue(); + if (value === null) { - return { nullValue: NullValue.NULL_VALUE } as Value; + result.nullValue = NullValue.NULL_VALUE; } else if (typeof value === 'boolean') { - return { boolValue: value } as Value; + result.boolValue = value; } else if (typeof value === 'number') { - return { numberValue: value } as Value; + result.numberValue = value; } else if (typeof value === 'string') { - return { stringValue: value } as Value; + result.stringValue = value; } else if (Array.isArray(value)) { - return { listValue: value } as Value; + result.listValue = value; } else if (typeof value === 'object') { - return { structValue: value } as Value; - } else if (typeof value === 'undefined') { - return {} as Value; - } else { + result.structValue = value; + } else if (typeof value !== 'undefined') { throw new Error('Unsupported any value type: ' + typeof value); } + + return result; }, unwrap(message: Value): string | number | boolean | Object | null | Array | undefined { @@ -430,7 +432,11 @@ export const ListValue = { }, wrap(value: Array | undefined): ListValue { - return { values: value ?? [] }; + const result = createBaseListValue(); + + result.values = value ?? []; + + return result; }, unwrap(message: ListValue): Array { diff --git a/src/main.ts b/src/main.ts index be90bd2df..120c36925 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1521,7 +1521,7 @@ function generateWrap(ctx: Context, fullProtoTypeName: string): Code[] { const chunks: Code[] = []; if (isStructTypeName(fullProtoTypeName)) { chunks.push(code`wrap(object: {[key: string]: any} | undefined): Struct { - const struct = Struct.fromPartial({}); + const struct = createBaseStruct(); if (object !== undefined) { Object.keys(object).forEach(key => { struct.fields[key] = object[key]; @@ -1534,50 +1534,58 @@ function generateWrap(ctx: Context, fullProtoTypeName: string): Code[] { if (isAnyValueTypeName(fullProtoTypeName)) { if (ctx.options.oneof === OneofOption.UNIONS) { chunks.push(code`wrap(value: any): Value { - if (value === null) { - return {kind: {$case: 'nullValue', nullValue: NullValue.NULL_VALUE}}; - } else if (typeof value === 'boolean') { - return {kind: {$case: 'boolValue', boolValue: value}}; - } else if (typeof value === 'number') { - return {kind: {$case: 'numberValue', numberValue: value}}; - } else if (typeof value === 'string') { - return {kind: {$case: 'stringValue', stringValue: value}}; - } else if (Array.isArray(value)) { - return {kind: {$case: 'listValue', listValue: value}}; - } else if (typeof value === 'object') { - return {kind: {$case: 'structValue', structValue: value}}; - } else if (typeof value === 'undefined') { - return {} as Value; - } else { - throw new Error('Unsupported any value type: ' + typeof value); - } + const result = createBaseValue(); + + if (value === null) { + result.kind = {$case: 'nullValue', nullValue: NullValue.NULL_VALUE}; + } else if (typeof value === 'boolean') { + result.kind = {$case: 'boolValue', boolValue: value}; + } else if (typeof value === 'number') { + result.kind = {$case: 'numberValue', numberValue: value}; + } else if (typeof value === 'string') { + result.kind = {$case: 'stringValue', stringValue: value}; + } else if (Array.isArray(value)) { + result.kind = {$case: 'listValue', listValue: value}; + } else if (typeof value === 'object') { + result.kind = {$case: 'structValue', structValue: value}; + } else if (typeof value !== 'undefined') { + throw new Error('Unsupported any value type: ' + typeof value); + } + + return result; }`); } else { chunks.push(code`wrap(value: any): Value { - if (value === null) { - return {nullValue: NullValue.NULL_VALUE} as Value; - } else if (typeof value === 'boolean') { - return {boolValue: value} as Value; - } else if (typeof value === 'number') { - return {numberValue: value} as Value; - } else if (typeof value === 'string') { - return {stringValue: value} as Value; - } else if (Array.isArray(value)) { - return {listValue: value} as Value; - } else if (typeof value === 'object') { - return {structValue: value} as Value; - } else if (typeof value === 'undefined') { - return {} as Value; - } else { - throw new Error('Unsupported any value type: ' + typeof value); - } + const result = createBaseValue(); + + if (value === null) { + result.nullValue = NullValue.NULL_VALUE; + } else if (typeof value === 'boolean') { + result.boolValue = value; + } else if (typeof value === 'number') { + result.numberValue = value; + } else if (typeof value === 'string') { + result.stringValue = value; + } else if (Array.isArray(value)) { + result.listValue = value; + } else if (typeof value === 'object') { + result.structValue = value; + } else if (typeof value !== 'undefined') { + throw new Error('Unsupported any value type: ' + typeof value); + } + + return result; }`); } } if (isListValueTypeName(fullProtoTypeName)) { chunks.push(code`wrap(value: Array | undefined): ListValue { - return {values: value ?? []}; + const result = createBaseListValue(); + + result.values = value ?? []; + + return result; }`); }