diff --git a/integration/grpc-js/google/protobuf/struct.ts b/integration/grpc-js/google/protobuf/struct.ts index 5760ebc59..849206f64 100644 --- a/integration/grpc-js/google/protobuf/struct.ts +++ b/integration/grpc-js/google/protobuf/struct.ts @@ -184,10 +184,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -195,9 +196,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/integration/nestjs-simple/google/protobuf/struct.ts b/integration/nestjs-simple/google/protobuf/struct.ts index a3485c05d..de6125dfb 100644 --- a/integration/nestjs-simple/google/protobuf/struct.ts +++ b/integration/nestjs-simple/google/protobuf/struct.ts @@ -87,10 +87,11 @@ function createBaseStruct(): Struct { export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = Value.wrap(object[key]); - }); + } } return struct; }, @@ -98,9 +99,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = Value.unwrap(message.fields[key]); - }); + } } return object; }, diff --git a/integration/nice-grpc/google/protobuf/struct.ts b/integration/nice-grpc/google/protobuf/struct.ts index c14e39613..d773b780c 100644 --- a/integration/nice-grpc/google/protobuf/struct.ts +++ b/integration/nice-grpc/google/protobuf/struct.ts @@ -184,10 +184,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -195,9 +196,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/integration/oneof-unions-snake/google/protobuf/struct.ts b/integration/oneof-unions-snake/google/protobuf/struct.ts index 4208674b9..76745053b 100644 --- a/integration/oneof-unions-snake/google/protobuf/struct.ts +++ b/integration/oneof-unions-snake/google/protobuf/struct.ts @@ -170,10 +170,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -181,9 +182,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/integration/oneof-unions/google/protobuf/struct.ts b/integration/oneof-unions/google/protobuf/struct.ts index e7ee042b7..a12c690df 100644 --- a/integration/oneof-unions/google/protobuf/struct.ts +++ b/integration/oneof-unions/google/protobuf/struct.ts @@ -170,10 +170,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -181,9 +182,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/integration/simple-esmodule-interop/empty.bin b/integration/simple-esmodule-interop/empty.bin new file mode 100644 index 000000000..fda409fb6 Binary files /dev/null and b/integration/simple-esmodule-interop/empty.bin differ diff --git a/integration/simple-snake/google/protobuf/struct.ts b/integration/simple-snake/google/protobuf/struct.ts index 5dc64396f..0a84f9dc7 100644 --- a/integration/simple-snake/google/protobuf/struct.ts +++ b/integration/simple-snake/google/protobuf/struct.ts @@ -184,10 +184,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -195,9 +196,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/integration/simple-string-enums/google/protobuf/struct.ts b/integration/simple-string-enums/google/protobuf/struct.ts index e866f6505..8f12e5f25 100644 --- a/integration/simple-string-enums/google/protobuf/struct.ts +++ b/integration/simple-string-enums/google/protobuf/struct.ts @@ -194,10 +194,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -205,9 +206,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/integration/static-only-type-registry/google/protobuf/struct.ts b/integration/static-only-type-registry/google/protobuf/struct.ts index 6d44332d0..ca34a0f08 100644 --- a/integration/static-only-type-registry/google/protobuf/struct.ts +++ b/integration/static-only-type-registry/google/protobuf/struct.ts @@ -187,10 +187,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -198,9 +199,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/integration/static-only/google/protobuf/struct.ts b/integration/static-only/google/protobuf/struct.ts index 4831a6f92..046a09e01 100644 --- a/integration/static-only/google/protobuf/struct.ts +++ b/integration/static-only/google/protobuf/struct.ts @@ -186,10 +186,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -197,9 +198,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/integration/struct/google/protobuf/struct.ts b/integration/struct/google/protobuf/struct.ts index 5760ebc59..849206f64 100644 --- a/integration/struct/google/protobuf/struct.ts +++ b/integration/struct/google/protobuf/struct.ts @@ -184,10 +184,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -195,9 +196,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/integration/type-annotations/google/protobuf/struct.ts b/integration/type-annotations/google/protobuf/struct.ts index e1cd21542..de5edcd11 100644 --- a/integration/type-annotations/google/protobuf/struct.ts +++ b/integration/type-annotations/google/protobuf/struct.ts @@ -194,10 +194,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -205,9 +206,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/integration/type-registry/google/protobuf/struct.ts b/integration/type-registry/google/protobuf/struct.ts index 122718b12..3f445b3de 100644 --- a/integration/type-registry/google/protobuf/struct.ts +++ b/integration/type-registry/google/protobuf/struct.ts @@ -195,10 +195,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -206,9 +207,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/integration/use-map-type/google/protobuf/struct.ts b/integration/use-map-type/google/protobuf/struct.ts index ca709b109..1d5514fa1 100644 --- a/integration/use-map-type/google/protobuf/struct.ts +++ b/integration/use-map-type/google/protobuf/struct.ts @@ -181,19 +181,22 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields.set(key, object[key]); - }); + } } return struct; }, unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; - [...message.fields.keys()].forEach((key) => { - object[key] = message.fields.get(key); - }); + if (message.fields) { + for (const key of message.fields.keys()) { + object[key] = message.fields.get(key); + } + } return object; }, }; diff --git a/integration/use-numeric-enum-json/google/protobuf/struct.ts b/integration/use-numeric-enum-json/google/protobuf/struct.ts index 276b617e8..956cb310e 100644 --- a/integration/use-numeric-enum-json/google/protobuf/struct.ts +++ b/integration/use-numeric-enum-json/google/protobuf/struct.ts @@ -184,10 +184,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -195,9 +196,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/integration/use-optionals-all/google/protobuf/struct.ts b/integration/use-optionals-all/google/protobuf/struct.ts new file mode 100644 index 000000000..e465e0978 --- /dev/null +++ b/integration/use-optionals-all/google/protobuf/struct.ts @@ -0,0 +1,550 @@ +/* eslint-disable */ +import * as _m0 from "protobufjs/minimal"; + +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"; + case NullValue.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } +} + +/** + * `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 { + /** Unordered map of dynamically typed values. */ + fields?: { [key: string]: any | undefined } | undefined; +} + +export interface 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 { + /** 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 { + /** Repeated field of dynamically typed values. */ + values?: any[] | undefined; +} + +function createBaseStruct(): Struct { + return { fields: {} }; +} + +export const Struct = { + encode(message: Struct, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + Object.entries(message.fields || {}).forEach(([key, value]) => { + if (value !== undefined) { + Struct_FieldsEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).ldelim(); + } + }); + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Struct { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(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: + if (tag !== 10) { + break; + } + + const entry1 = Struct_FieldsEntry.decode(reader, reader.uint32()); + if (entry1.value !== undefined) { + message.fields![entry1.key] = entry1.value; + } + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Struct { + return { + 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 = {}; + if (message.fields) { + const entries = Object.entries(message.fields); + if (entries.length > 0) { + obj.fields = {}; + entries.forEach(([k, v]) => { + obj.fields[k] = v; + }); + } + } + return obj; + }, + + create, I>>(base?: I): Struct { + return Struct.fromPartial(base ?? ({} as any)); + }, + 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(); + struct.fields ??= {}; + if (object !== undefined) { + for (const key of Object.keys(object)) { + struct.fields[key] = object[key]; + } + } + return struct; + }, + + unwrap(message: Struct): { [key: string]: any } { + const object: { [key: string]: any } = {}; + if (message.fields) { + for (const key of Object.keys(message.fields)) { + object[key] = message.fields[key]; + } + } + return object; + }, +}; + +function createBaseStruct_FieldsEntry(): Struct_FieldsEntry { + return { key: "", value: undefined }; +} + +export const Struct_FieldsEntry = { + encode(message: Struct_FieldsEntry, writer: _m0.Writer = _m0.Writer.create()): _m0.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: _m0.Reader | Uint8Array, length?: number): Struct_FieldsEntry { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(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: + if (tag !== 10) { + break; + } + + message.key = reader.string(); + continue; + case 2: + if (tag !== 18) { + break; + } + + message.value = Value.unwrap(Value.decode(reader, reader.uint32())); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Struct_FieldsEntry { + return { + key: isSet(object.key) ? globalThis.String(object.key) : "", + value: isSet(object?.value) ? object.value : undefined, + }; + }, + + toJSON(message: Struct_FieldsEntry): unknown { + const obj: any = {}; + if (message.key !== "") { + obj.key = message.key; + } + if (message.value !== undefined) { + obj.value = message.value; + } + return obj; + }, + + create, I>>(base?: I): Struct_FieldsEntry { + return Struct_FieldsEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Struct_FieldsEntry { + const message = createBaseStruct_FieldsEntry(); + message.key = object.key ?? ""; + message.value = object.value ?? undefined; + return message; + }, +}; + +function createBaseValue(): Value { + return { + nullValue: undefined, + numberValue: undefined, + stringValue: undefined, + boolValue: undefined, + structValue: undefined, + listValue: undefined, + }; +} + +export const Value = { + encode(message: Value, writer: _m0.Writer = _m0.Writer.create()): _m0.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: _m0.Reader | Uint8Array, length?: number): Value { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(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: + if (tag !== 8) { + break; + } + + message.nullValue = reader.int32() as any; + continue; + case 2: + if (tag !== 17) { + break; + } + + message.numberValue = reader.double(); + continue; + case 3: + if (tag !== 26) { + break; + } + + message.stringValue = reader.string(); + continue; + case 4: + if (tag !== 32) { + break; + } + + message.boolValue = reader.bool(); + continue; + case 5: + if (tag !== 42) { + break; + } + + message.structValue = Struct.unwrap(Struct.decode(reader, reader.uint32())); + continue; + case 6: + if (tag !== 50) { + break; + } + + message.listValue = ListValue.unwrap(ListValue.decode(reader, reader.uint32())); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Value { + return { + nullValue: isSet(object.nullValue) ? nullValueFromJSON(object.nullValue) : undefined, + numberValue: isSet(object.numberValue) ? globalThis.Number(object.numberValue) : undefined, + stringValue: isSet(object.stringValue) ? globalThis.String(object.stringValue) : undefined, + boolValue: isSet(object.boolValue) ? globalThis.Boolean(object.boolValue) : undefined, + structValue: isObject(object.structValue) ? object.structValue : undefined, + listValue: globalThis.Array.isArray(object.listValue) ? [...object.listValue] : undefined, + }; + }, + + toJSON(message: Value): unknown { + const obj: any = {}; + if (message.nullValue !== undefined) { + obj.nullValue = nullValueToJSON(message.nullValue); + } + if (message.numberValue !== undefined) { + obj.numberValue = message.numberValue; + } + if (message.stringValue !== undefined) { + obj.stringValue = message.stringValue; + } + if (message.boolValue !== undefined) { + obj.boolValue = message.boolValue; + } + if (message.structValue !== undefined) { + obj.structValue = message.structValue; + } + if (message.listValue !== undefined) { + obj.listValue = message.listValue; + } + return obj; + }, + + create, I>>(base?: I): Value { + return Value.fromPartial(base ?? ({} as any)); + }, + 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 (globalThis.Array.isArray(value)) { + result.listValue = value; + } else if (typeof value === "object") { + result.structValue = value; + } else if (typeof value !== "undefined") { + throw new globalThis.Error("Unsupported any value type: " + typeof value); + } + return result; + }, + + unwrap(message: any): 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 as any; + } else if (message?.listValue !== undefined) { + return message.listValue; + } else if (message?.nullValue !== undefined) { + return null; + } + return undefined; + }, +}; + +function createBaseListValue(): ListValue { + return { values: [] }; +} + +export const ListValue = { + encode(message: ListValue, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.values !== undefined && message.values.length !== 0) { + for (const v of message.values) { + Value.encode(Value.wrap(v!), writer.uint32(10).fork()).ldelim(); + } + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): ListValue { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(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: + if (tag !== 10) { + break; + } + + message.values!.push(Value.unwrap(Value.decode(reader, reader.uint32()))); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): ListValue { + return { values: globalThis.Array.isArray(object?.values) ? [...object.values] : [] }; + }, + + toJSON(message: ListValue): unknown { + const obj: any = {}; + if (message.values?.length) { + obj.values = message.values; + } + return obj; + }, + + create, I>>(base?: I): ListValue { + return ListValue.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ListValue { + const message = createBaseListValue(); + message.values = object.values?.map((e) => e) || []; + return message; + }, + + wrap(array: Array | undefined): ListValue { + const result = createBaseListValue(); + result.values = array ?? []; + return result; + }, + + unwrap(message: ListValue): Array { + if (message?.hasOwnProperty("values") && globalThis.Array.isArray(message.values)) { + return message.values; + } else { + return message as any; + } + }, +}; + +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 keyof T]?: 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 }; + +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/use-optionals-all/test.bin b/integration/use-optionals-all/test.bin index 9cf270203..18b318f74 100644 Binary files a/integration/use-optionals-all/test.bin and b/integration/use-optionals-all/test.bin differ diff --git a/integration/use-optionals-all/test.proto b/integration/use-optionals-all/test.proto index 754ebf3b6..71de752d6 100644 --- a/integration/use-optionals-all/test.proto +++ b/integration/use-optionals-all/test.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package optionalstest; import "google/protobuf/timestamp.proto"; +import "google/protobuf/struct.proto"; message OptionalsTest { int32 id = 1; @@ -31,6 +32,7 @@ message OptionalsTest { map translations = 30; google.protobuf.Timestamp timestamp = 31; + google.protobuf.Struct struct = 32; } enum StateEnum { diff --git a/integration/use-optionals-all/test.ts b/integration/use-optionals-all/test.ts index bb2115609..5ddbea317 100644 --- a/integration/use-optionals-all/test.ts +++ b/integration/use-optionals-all/test.ts @@ -1,5 +1,6 @@ /* eslint-disable */ import * as _m0 from "protobufjs/minimal"; +import { Struct } from "./google/protobuf/struct"; import { Timestamp } from "./google/protobuf/timestamp"; import Long = require("long"); @@ -68,6 +69,7 @@ export interface OptionalsTest { optData?: Uint8Array | undefined; translations?: { [key: string]: string } | undefined; timestamp?: Date | undefined; + struct?: { [key: string]: any } | undefined; } export interface OptionalsTest_TranslationsEntry { @@ -103,6 +105,7 @@ function createBaseOptionalsTest(): OptionalsTest { optData: undefined, translations: {}, timestamp: undefined, + struct: undefined, }; } @@ -199,6 +202,9 @@ export const OptionalsTest = { if (message.timestamp !== undefined) { Timestamp.encode(toTimestamp(message.timestamp), writer.uint32(250).fork()).ldelim(); } + if (message.struct !== undefined) { + Struct.encode(Struct.wrap(message.struct), writer.uint32(258).fork()).ldelim(); + } return writer; }, @@ -413,6 +419,13 @@ export const OptionalsTest = { message.timestamp = fromTimestamp(Timestamp.decode(reader, reader.uint32())); continue; + case 32: + if (tag !== 258) { + break; + } + + message.struct = Struct.unwrap(Struct.decode(reader, reader.uint32())); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -456,6 +469,7 @@ export const OptionalsTest = { }, {}) : {}, timestamp: isSet(object.timestamp) ? fromJsonTimestamp(object.timestamp) : undefined, + struct: isObject(object.struct) ? object.struct : undefined, }; }, @@ -536,6 +550,9 @@ export const OptionalsTest = { if (message.timestamp !== undefined) { obj.timestamp = message.timestamp.toISOString(); } + if (message.struct !== undefined) { + obj.struct = message.struct; + } return obj; }, @@ -577,6 +594,7 @@ export const OptionalsTest = { {}, ); message.timestamp = object.timestamp ?? undefined; + message.struct = object.struct ?? undefined; return message; }, }; diff --git a/integration/use-optionals-no-undefined/google/protobuf/struct.ts b/integration/use-optionals-no-undefined/google/protobuf/struct.ts new file mode 100644 index 000000000..6b72c2577 --- /dev/null +++ b/integration/use-optionals-no-undefined/google/protobuf/struct.ts @@ -0,0 +1,548 @@ +/* eslint-disable */ +import * as _m0 from "protobufjs/minimal"; + +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"; + case NullValue.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } +} + +/** + * `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 { + /** Unordered map of dynamically typed values. */ + fields?: { [key: string]: any | undefined } | undefined; +} + +export interface 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 { + /** 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 { + /** Repeated field of dynamically typed values. */ + values?: any[] | undefined; +} + +function createBaseStruct(): Struct { + return {}; +} + +export const Struct = { + encode(message: Struct, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + Object.entries(message.fields || {}).forEach(([key, value]) => { + if (value !== undefined) { + Struct_FieldsEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).ldelim(); + } + }); + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Struct { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(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: + if (tag !== 10) { + break; + } + + const entry1 = Struct_FieldsEntry.decode(reader, reader.uint32()); + if (entry1.value !== undefined) { + if (message.fields === undefined) { + message.fields = {}; + } + message.fields![entry1.key] = entry1.value; + } + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Struct { + return { + fields: isObject(object.fields) + ? Object.entries(object.fields).reduce<{ [key: string]: any | undefined }>((acc, [key, value]) => { + acc[key] = value as any | undefined; + return acc; + }, {}) + : undefined, + }; + }, + + toJSON(message: Struct): unknown { + const obj: any = {}; + if (message.fields) { + const entries = Object.entries(message.fields); + if (entries.length > 0) { + obj.fields = {}; + entries.forEach(([k, v]) => { + obj.fields[k] = v; + }); + } + } + return obj; + }, + + create, I>>(base?: I): Struct { + return Struct.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Struct { + const message = createBaseStruct(); + message.fields = (object.fields === undefined || object.fields === null) + ? undefined + : 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(); + struct.fields ??= {}; + if (object !== undefined) { + for (const key of Object.keys(object)) { + struct.fields[key] = object[key]; + } + } + return struct; + }, + + unwrap(message: Struct): { [key: string]: any } { + const object: { [key: string]: any } = {}; + if (message.fields) { + for (const key of Object.keys(message.fields)) { + object[key] = message.fields[key]; + } + } + return object; + }, +}; + +function createBaseStruct_FieldsEntry(): Struct_FieldsEntry { + return { key: "" }; +} + +export const Struct_FieldsEntry = { + encode(message: Struct_FieldsEntry, writer: _m0.Writer = _m0.Writer.create()): _m0.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: _m0.Reader | Uint8Array, length?: number): Struct_FieldsEntry { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(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: + if (tag !== 10) { + break; + } + + message.key = reader.string(); + continue; + case 2: + if (tag !== 18) { + break; + } + + message.value = Value.unwrap(Value.decode(reader, reader.uint32())); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Struct_FieldsEntry { + return { + key: isSet(object.key) ? globalThis.String(object.key) : "", + value: isSet(object?.value) ? object.value : undefined, + }; + }, + + toJSON(message: Struct_FieldsEntry): unknown { + const obj: any = {}; + if (message.key !== "") { + obj.key = message.key; + } + if (message.value !== undefined) { + obj.value = message.value; + } + return obj; + }, + + create, I>>(base?: I): Struct_FieldsEntry { + return Struct_FieldsEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Struct_FieldsEntry { + const message = createBaseStruct_FieldsEntry(); + message.key = object.key ?? ""; + message.value = object.value ?? undefined; + return message; + }, +}; + +function createBaseValue(): Value { + return {}; +} + +export const Value = { + encode(message: Value, writer: _m0.Writer = _m0.Writer.create()): _m0.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: _m0.Reader | Uint8Array, length?: number): Value { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(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: + if (tag !== 8) { + break; + } + + message.nullValue = reader.int32() as any; + continue; + case 2: + if (tag !== 17) { + break; + } + + message.numberValue = reader.double(); + continue; + case 3: + if (tag !== 26) { + break; + } + + message.stringValue = reader.string(); + continue; + case 4: + if (tag !== 32) { + break; + } + + message.boolValue = reader.bool(); + continue; + case 5: + if (tag !== 42) { + break; + } + + message.structValue = Struct.unwrap(Struct.decode(reader, reader.uint32())); + continue; + case 6: + if (tag !== 50) { + break; + } + + message.listValue = ListValue.unwrap(ListValue.decode(reader, reader.uint32())); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Value { + return { + nullValue: isSet(object.nullValue) ? nullValueFromJSON(object.nullValue) : undefined, + numberValue: isSet(object.numberValue) ? globalThis.Number(object.numberValue) : undefined, + stringValue: isSet(object.stringValue) ? globalThis.String(object.stringValue) : undefined, + boolValue: isSet(object.boolValue) ? globalThis.Boolean(object.boolValue) : undefined, + structValue: isObject(object.structValue) ? object.structValue : undefined, + listValue: globalThis.Array.isArray(object.listValue) ? [...object.listValue] : undefined, + }; + }, + + toJSON(message: Value): unknown { + const obj: any = {}; + if (message.nullValue !== undefined) { + obj.nullValue = nullValueToJSON(message.nullValue); + } + if (message.numberValue !== undefined) { + obj.numberValue = message.numberValue; + } + if (message.stringValue !== undefined) { + obj.stringValue = message.stringValue; + } + if (message.boolValue !== undefined) { + obj.boolValue = message.boolValue; + } + if (message.structValue !== undefined) { + obj.structValue = message.structValue; + } + if (message.listValue !== undefined) { + obj.listValue = message.listValue; + } + return obj; + }, + + create, I>>(base?: I): Value { + return Value.fromPartial(base ?? ({} as any)); + }, + 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 (globalThis.Array.isArray(value)) { + result.listValue = value; + } else if (typeof value === "object") { + result.structValue = value; + } else if (typeof value !== "undefined") { + throw new globalThis.Error("Unsupported any value type: " + typeof value); + } + return result; + }, + + unwrap(message: any): 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 as any; + } else if (message?.listValue !== undefined) { + return message.listValue; + } else if (message?.nullValue !== undefined) { + return null; + } + return undefined; + }, +}; + +function createBaseListValue(): ListValue { + return {}; +} + +export const ListValue = { + encode(message: ListValue, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.values !== undefined && message.values.length !== 0) { + for (const v of message.values) { + Value.encode(Value.wrap(v!), writer.uint32(10).fork()).ldelim(); + } + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): ListValue { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(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: + if (tag !== 10) { + break; + } + + if (message.values === undefined) { + message.values = []; + } + message.values!.push(Value.unwrap(Value.decode(reader, reader.uint32()))); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): ListValue { + return { values: globalThis.Array.isArray(object?.values) ? [...object.values] : [] }; + }, + + toJSON(message: ListValue): unknown { + const obj: any = {}; + if (message.values?.length) { + obj.values = message.values; + } + return obj; + }, + + create, I>>(base?: I): ListValue { + return ListValue.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ListValue { + const message = createBaseListValue(); + message.values = object.values?.map((e) => e) || undefined; + return message; + }, + + wrap(array: Array | undefined): ListValue { + const result = createBaseListValue(); + result.values = array ?? []; + return result; + }, + + unwrap(message: ListValue): Array { + if (message?.hasOwnProperty("values") && globalThis.Array.isArray(message.values)) { + return message.values; + } else { + return message as any; + } + }, +}; + +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 keyof T]?: 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 }; + +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/use-optionals-no-undefined/test.bin b/integration/use-optionals-no-undefined/test.bin index 11c02597f..b55039e57 100644 Binary files a/integration/use-optionals-no-undefined/test.bin and b/integration/use-optionals-no-undefined/test.bin differ diff --git a/integration/use-optionals-no-undefined/test.proto b/integration/use-optionals-no-undefined/test.proto index d752ce261..5a888b9c5 100644 --- a/integration/use-optionals-no-undefined/test.proto +++ b/integration/use-optionals-no-undefined/test.proto @@ -1,6 +1,8 @@ syntax = "proto3"; package optionalstest; +import "google/protobuf/struct.proto"; + message OptionalsTest { int32 id = 1; Child child = 2; @@ -27,6 +29,8 @@ message OptionalsTest { optional bytes opt_data = 27; map translations = 30; + + google.protobuf.Struct struct = 32; } enum StateEnum { diff --git a/integration/use-optionals-no-undefined/test.ts b/integration/use-optionals-no-undefined/test.ts index 0cb49c2b9..a8ac8b164 100644 --- a/integration/use-optionals-no-undefined/test.ts +++ b/integration/use-optionals-no-undefined/test.ts @@ -1,5 +1,6 @@ /* eslint-disable */ import * as _m0 from "protobufjs/minimal"; +import { Struct } from "./google/protobuf/struct"; import Long = require("long"); export const protobufPackage = "optionalstest"; @@ -66,6 +67,7 @@ export interface OptionalsTest { optDescription?: string | undefined; optData?: Uint8Array | undefined; translations?: { [key: string]: string } | undefined; + struct?: { [key: string]: any } | undefined; } export interface OptionalsTest_TranslationsEntry { @@ -170,6 +172,9 @@ export const OptionalsTest = { Object.entries(message.translations || {}).forEach(([key, value]) => { OptionalsTest_TranslationsEntry.encode({ key: key as any, value }, writer.uint32(242).fork()).ldelim(); }); + if (message.struct !== undefined) { + Struct.encode(Struct.wrap(message.struct), writer.uint32(258).fork()).ldelim(); + } return writer; }, @@ -413,6 +418,13 @@ export const OptionalsTest = { message.translations![entry30.key] = entry30.value; } continue; + case 32: + if (tag !== 258) { + break; + } + + message.struct = Struct.unwrap(Struct.decode(reader, reader.uint32())); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -463,6 +475,7 @@ export const OptionalsTest = { return acc; }, {}) : undefined, + struct: isObject(object.struct) ? object.struct : undefined, }; }, @@ -540,6 +553,9 @@ export const OptionalsTest = { }); } } + if (message.struct !== undefined) { + obj.struct = message.struct; + } return obj; }, @@ -579,6 +595,7 @@ export const OptionalsTest = { } return acc; }, {}); + message.struct = object.struct ?? undefined; return message; }, }; diff --git a/integration/use-readonly-types/google/protobuf/struct.ts b/integration/use-readonly-types/google/protobuf/struct.ts index 1c1c45bca..83ef5f717 100644 --- a/integration/use-readonly-types/google/protobuf/struct.ts +++ b/integration/use-readonly-types/google/protobuf/struct.ts @@ -170,10 +170,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -181,9 +182,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/integration/value/google/protobuf/struct.ts b/integration/value/google/protobuf/struct.ts index 5760ebc59..849206f64 100644 --- a/integration/value/google/protobuf/struct.ts +++ b/integration/value/google/protobuf/struct.ts @@ -184,10 +184,11 @@ export const Struct = { wrap(object: { [key: string]: any } | undefined): Struct { const struct = createBaseStruct(); + if (object !== undefined) { - Object.keys(object).forEach((key) => { + for (const key of Object.keys(object)) { struct.fields[key] = object[key]; - }); + } } return struct; }, @@ -195,9 +196,9 @@ export const Struct = { unwrap(message: Struct): { [key: string]: any } { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach((key) => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }, diff --git a/src/generate-struct-wrappers.ts b/src/generate-struct-wrappers.ts index bcf65d4d9..b08e08459 100644 --- a/src/generate-struct-wrappers.ts +++ b/src/generate-struct-wrappers.ts @@ -31,15 +31,20 @@ export function generateWrapDeep(ctx: Context, fullProtoTypeName: string, fieldN const chunks: Code[] = []; if (isStructTypeName(fullProtoTypeName)) { let setStatement = "struct.fields[key] = Value.wrap(object[key]);"; + let defaultFields = "struct.fields ??= {};"; if (ctx.options.useMapType) { setStatement = "struct.fields.set(key, Value.wrap(object[key]));"; + defaultFields = "struct.fields ??= new Map();"; } + if (ctx.options.useOptionals !== "all") defaultFields = ""; + chunks.push(code`wrap(object: {[key: string]: any} | undefined): Struct { const struct = createBaseStruct(); + ${defaultFields} if (object !== undefined) { - Object.keys(object).forEach(key => { + for (const key of Object.keys(object)) { ${setStatement} - }); + } } return struct; }`); @@ -99,18 +104,20 @@ export function generateUnwrapDeep(ctx: Context, fullProtoTypeName: string, fiel if (ctx.options.useMapType) { chunks.push(code`unwrap(message: Struct): {[key: string]: any} { const object: { [key: string]: any } = {}; - [...message.fields.keys()].forEach((key) => { - object[key] = Value.unwrap(message.fields.get(key)); - }); + if (message.fields) { + for (const key of message.fields.keys()) { + object[key] = Value.unwrap(message.fields.get(key)); + } + } return object; }`); } else { chunks.push(code`unwrap(message: Struct): {[key: string]: any} { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach(key => { + for (const key of Object.keys(message.fields)) { object[key] = Value.unwrap(message.fields[key]); - }); + } } return object; }`); @@ -165,15 +172,20 @@ export function generateWrapShallow(ctx: Context, fullProtoTypeName: string, fie const chunks: Code[] = []; if (isStructTypeName(fullProtoTypeName)) { let setStatement = "struct.fields[key] = object[key];"; + let defaultFields = "struct.fields ??= {};"; if (ctx.options.useMapType) { setStatement = "struct.fields.set(key, object[key]);"; + defaultFields = "struct.fields ??= new Map();"; } + if (ctx.options.useOptionals !== "all") defaultFields = ""; + chunks.push(code`wrap(object: {[key: string]: any} | undefined): Struct { const struct = createBaseStruct(); + ${defaultFields} if (object !== undefined) { - Object.keys(object).forEach(key => { + for (const key of Object.keys(object)) { ${setStatement} - }); + } } return struct; }`); @@ -254,18 +266,20 @@ export function generateUnwrapShallow(ctx: Context, fullProtoTypeName: string, f if (ctx.options.useMapType) { chunks.push(code`unwrap(message: Struct): {[key: string]: any} { const object: { [key: string]: any } = {}; - [...message.fields.keys()].forEach((key) => { - object[key] = message.fields.get(key); - }); + if (message.fields) { + for (const key of message.fields.keys()) { + object[key] = message.fields.get(key); + } + } return object; }`); } else { chunks.push(code`unwrap(message: Struct): {[key: string]: any} { const object: { [key: string]: any } = {}; if (message.fields) { - Object.keys(message.fields).forEach(key => { + for (const key of Object.keys(message.fields)) { object[key] = message.fields[key]; - }); + } } return object; }`);