From ba68d4bcb683578e02d58a1b138a094b803a0bf8 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Wed, 5 Jul 2023 15:17:32 +0200 Subject: [PATCH] fix: generate different MessageType when using static-only Fixes #861 --- .../static-only-type-registry/bar/bar.bin | Bin 0 -> 11628 bytes .../static-only-type-registry/bar/bar.proto | 9 + .../static-only-type-registry/bar/bar.ts | 85 +++ integration/static-only-type-registry/foo.bin | Bin 0 -> 11423 bytes .../static-only-type-registry/foo.proto | 18 + integration/static-only-type-registry/foo.ts | 240 ++++++++ .../google/protobuf/struct.ts | 548 ++++++++++++++++++ .../google/protobuf/timestamp.ts | 236 ++++++++ .../static-only-type-registry/parameters.txt | 1 + .../static-only-type-registry-test.ts | 41 ++ .../static-only-type-registry/typeRegistry.ts | 21 + src/generate-type-registry.ts | 15 +- src/main.ts | 8 +- src/options.ts | 6 + 14 files changed, 1219 insertions(+), 9 deletions(-) create mode 100644 integration/static-only-type-registry/bar/bar.bin create mode 100644 integration/static-only-type-registry/bar/bar.proto create mode 100644 integration/static-only-type-registry/bar/bar.ts create mode 100644 integration/static-only-type-registry/foo.bin create mode 100644 integration/static-only-type-registry/foo.proto create mode 100644 integration/static-only-type-registry/foo.ts create mode 100644 integration/static-only-type-registry/google/protobuf/struct.ts create mode 100644 integration/static-only-type-registry/google/protobuf/timestamp.ts create mode 100755 integration/static-only-type-registry/parameters.txt create mode 100644 integration/static-only-type-registry/static-only-type-registry-test.ts create mode 100644 integration/static-only-type-registry/typeRegistry.ts diff --git a/integration/static-only-type-registry/bar/bar.bin b/integration/static-only-type-registry/bar/bar.bin new file mode 100644 index 0000000000000000000000000000000000000000..ae2eb7c68b5b04f86048ae1d93cd6d9d8c0e1cd0 GIT binary patch literal 11628 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 KnVP*6F!F!0jVs^) literal 0 HcmV?d00001 diff --git a/integration/static-only-type-registry/bar/bar.proto b/integration/static-only-type-registry/bar/bar.proto new file mode 100644 index 000000000..43aa08bd9 --- /dev/null +++ b/integration/static-only-type-registry/bar/bar.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +package foo.bar; + +import "foo.proto"; + +message Bar { + Foo foo = 1; +} diff --git a/integration/static-only-type-registry/bar/bar.ts b/integration/static-only-type-registry/bar/bar.ts new file mode 100644 index 000000000..114c3221c --- /dev/null +++ b/integration/static-only-type-registry/bar/bar.ts @@ -0,0 +1,85 @@ +/* eslint-disable */ +import * as _m0 from "protobufjs/minimal"; +import { Foo } from "../foo"; +import { messageTypeRegistry } from "../typeRegistry"; + +export const protobufPackage = "foo.bar"; + +export interface Bar { + foo: Foo | undefined; +} + +function createBaseBar(): Bar { + return { foo: undefined }; +} + +export const Bar = { + $type: "foo.bar.Bar" as const, + + encode(message: Bar, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.foo !== undefined) { + Foo.encode(message.foo, writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Bar { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseBar(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.foo = Foo.decode(reader, reader.uint32()); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Bar { + return { foo: isSet(object.foo) ? Foo.fromJSON(object.foo) : undefined }; + }, + + toJSON(message: Bar): unknown { + const obj: any = {}; + message.foo !== undefined && (obj.foo = message.foo ? Foo.toJSON(message.foo) : undefined); + return obj; + }, + + create, I>>(base?: I): Bar { + return Bar.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): Bar { + const message = createBaseBar(); + message.foo = (object.foo !== undefined && object.foo !== null) ? Foo.fromPartial(object.foo) : undefined; + return message; + }, +}; + +messageTypeRegistry.set(Bar.$type, Bar); + +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 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 isSet(value: any): boolean { + return value !== null && value !== undefined; +} diff --git a/integration/static-only-type-registry/foo.bin b/integration/static-only-type-registry/foo.bin new file mode 100644 index 0000000000000000000000000000000000000000..38bbe04e3ee3a1cb946b94539c059b0b8d007b9b GIT binary patch literal 11423 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 b?FH!OW6G^#3V`#!cQc#=y7~02(0cw4%cBn? literal 0 HcmV?d00001 diff --git a/integration/static-only-type-registry/foo.proto b/integration/static-only-type-registry/foo.proto new file mode 100644 index 000000000..a4d68c826 --- /dev/null +++ b/integration/static-only-type-registry/foo.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package foo; + +import "google/protobuf/timestamp.proto"; +import "google/protobuf/struct.proto"; + +message Foo { + google.protobuf.Timestamp timestamp = 1; +} + +message Foo2 { + google.protobuf.Timestamp timestamp = 1; +} + +message WithStruct { + google.protobuf.Struct struct = 1; +} diff --git a/integration/static-only-type-registry/foo.ts b/integration/static-only-type-registry/foo.ts new file mode 100644 index 000000000..88cc84809 --- /dev/null +++ b/integration/static-only-type-registry/foo.ts @@ -0,0 +1,240 @@ +/* eslint-disable */ +import * as _m0 from "protobufjs/minimal"; +import { Struct } from "./google/protobuf/struct"; +import { Timestamp } from "./google/protobuf/timestamp"; +import { messageTypeRegistry } from "./typeRegistry"; + +export const protobufPackage = "foo"; + +export interface Foo { + timestamp: Date | undefined; +} + +export interface Foo2 { + timestamp: Date | undefined; +} + +export interface WithStruct { + struct: { [key: string]: any } | undefined; +} + +function createBaseFoo(): Foo { + return { timestamp: undefined }; +} + +export const Foo = { + $type: "foo.Foo" as const, + + encode(message: Foo, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.timestamp !== undefined) { + Timestamp.encode(toTimestamp(message.timestamp), writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Foo { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseFoo(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.timestamp = fromTimestamp(Timestamp.decode(reader, reader.uint32())); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Foo { + return { timestamp: isSet(object.timestamp) ? fromJsonTimestamp(object.timestamp) : undefined }; + }, + + toJSON(message: Foo): unknown { + const obj: any = {}; + message.timestamp !== undefined && (obj.timestamp = message.timestamp.toISOString()); + return obj; + }, + + create, I>>(base?: I): Foo { + return Foo.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): Foo { + const message = createBaseFoo(); + message.timestamp = object.timestamp ?? undefined; + return message; + }, +}; + +messageTypeRegistry.set(Foo.$type, Foo); + +function createBaseFoo2(): Foo2 { + return { timestamp: undefined }; +} + +export const Foo2 = { + $type: "foo.Foo2" as const, + + encode(message: Foo2, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.timestamp !== undefined) { + Timestamp.encode(toTimestamp(message.timestamp), writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Foo2 { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseFoo2(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.timestamp = fromTimestamp(Timestamp.decode(reader, reader.uint32())); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Foo2 { + return { timestamp: isSet(object.timestamp) ? fromJsonTimestamp(object.timestamp) : undefined }; + }, + + toJSON(message: Foo2): unknown { + const obj: any = {}; + message.timestamp !== undefined && (obj.timestamp = message.timestamp.toISOString()); + return obj; + }, + + create, I>>(base?: I): Foo2 { + return Foo2.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): Foo2 { + const message = createBaseFoo2(); + message.timestamp = object.timestamp ?? undefined; + return message; + }, +}; + +messageTypeRegistry.set(Foo2.$type, Foo2); + +function createBaseWithStruct(): WithStruct { + return { struct: undefined }; +} + +export const WithStruct = { + $type: "foo.WithStruct" as const, + + encode(message: WithStruct, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.struct !== undefined) { + Struct.encode(Struct.wrap(message.struct), writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): WithStruct { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(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: + if (tag !== 10) { + break; + } + + message.struct = Struct.unwrap(Struct.decode(reader, reader.uint32())); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): WithStruct { + return { struct: isObject(object.struct) ? object.struct : undefined }; + }, + + toJSON(message: WithStruct): unknown { + const obj: any = {}; + message.struct !== undefined && (obj.struct = message.struct); + return obj; + }, + + create, I>>(base?: I): WithStruct { + return WithStruct.fromPartial(base ?? {}); + }, + + 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 ? T + : T extends Array ? 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 toTimestamp(date: Date): Timestamp { + const seconds = date.getTime() / 1_000; + const nanos = (date.getTime() % 1_000) * 1_000_000; + return { seconds, nanos }; +} + +function fromTimestamp(t: Timestamp): Date { + let millis = (t.seconds || 0) * 1_000; + millis += (t.nanos || 0) / 1_000_000; + return new Date(millis); +} + +function fromJsonTimestamp(o: any): Date { + if (o instanceof Date) { + return o; + } else if (typeof o === "string") { + return new Date(o); + } else { + return fromTimestamp(Timestamp.fromJSON(o)); + } +} + +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/static-only-type-registry/google/protobuf/struct.ts b/integration/static-only-type-registry/google/protobuf/struct.ts new file mode 100644 index 000000000..9bd5a3bcf --- /dev/null +++ b/integration/static-only-type-registry/google/protobuf/struct.ts @@ -0,0 +1,548 @@ +/* eslint-disable */ +import * as _m0 from "protobufjs/minimal"; +import { messageTypeRegistry } from "../../typeRegistry"; + +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 }; +} + +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[]; +} + +function createBaseStruct(): Struct { + return { fields: {} }; +} + +export const Struct = { + $type: "google.protobuf.Struct" as const, + + 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 = {}; + obj.fields = {}; + if (message.fields) { + Object.entries(message.fields).forEach(([k, v]) => { + obj.fields[k] = v; + }); + } + return obj; + }, + + create, I>>(base?: I): Struct { + return Struct.fromPartial(base ?? {}); + }, + + 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 } = {}; + if (message.fields) { + Object.keys(message.fields).forEach((key) => { + object[key] = message.fields[key]; + }); + } + return object; + }, +}; + +messageTypeRegistry.set(Struct.$type, Struct); + +function createBaseStruct_FieldsEntry(): Struct_FieldsEntry { + return { key: "", value: undefined }; +} + +export const Struct_FieldsEntry = { + $type: "google.protobuf.Struct.FieldsEntry" as const, + + 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) ? 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; + }, + + create, I>>(base?: I): Struct_FieldsEntry { + return Struct_FieldsEntry.fromPartial(base ?? {}); + }, + + 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 { + 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: _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) ? 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; + }, + + create, I>>(base?: I): Value { + return Value.fromPartial(base ?? {}); + }, + + 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: 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; + }, +}; + +messageTypeRegistry.set(Value.$type, Value); + +function createBaseListValue(): ListValue { + return { values: [] }; +} + +export const ListValue = { + $type: "google.protobuf.ListValue" as const, + + encode(message: ListValue, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + 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: 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; + }, + + create, I>>(base?: I): ListValue { + return ListValue.fromPartial(base ?? {}); + }, + + 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") && Array.isArray(message.values)) { + return message.values; + } else { + return message as any; + } + }, +}; + +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 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/static-only-type-registry/google/protobuf/timestamp.ts b/integration/static-only-type-registry/google/protobuf/timestamp.ts new file mode 100644 index 000000000..1630303b5 --- /dev/null +++ b/integration/static-only-type-registry/google/protobuf/timestamp.ts @@ -0,0 +1,236 @@ +/* eslint-disable */ +import * as Long from "long"; +import * as _m0 from "protobufjs/minimal"; +import { messageTypeRegistry } from "../../typeRegistry"; + +export const protobufPackage = "google.protobuf"; + +/** + * A Timestamp represents a point in time independent of any time zone or local + * calendar, encoded as a count of seconds and fractions of seconds at + * nanosecond resolution. The count is relative to an epoch at UTC midnight on + * January 1, 1970, in the proleptic Gregorian calendar which extends the + * Gregorian calendar backwards to year one. + * + * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + * second table is needed for interpretation, using a [24-hour linear + * smear](https://developers.google.com/time/smear). + * + * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + * restricting to that range, we ensure that we can convert to and from [RFC + * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + * + * # Examples + * + * Example 1: Compute Timestamp from POSIX `time()`. + * + * Timestamp timestamp; + * timestamp.set_seconds(time(NULL)); + * timestamp.set_nanos(0); + * + * Example 2: Compute Timestamp from POSIX `gettimeofday()`. + * + * struct timeval tv; + * gettimeofday(&tv, NULL); + * + * Timestamp timestamp; + * timestamp.set_seconds(tv.tv_sec); + * timestamp.set_nanos(tv.tv_usec * 1000); + * + * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + * + * FILETIME ft; + * GetSystemTimeAsFileTime(&ft); + * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + * + * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + * Timestamp timestamp; + * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + * + * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + * + * long millis = System.currentTimeMillis(); + * + * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + * .setNanos((int) ((millis % 1000) * 1000000)).build(); + * + * Example 5: Compute Timestamp from Java `Instant.now()`. + * + * Instant now = Instant.now(); + * + * Timestamp timestamp = + * Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + * .setNanos(now.getNano()).build(); + * + * Example 6: Compute Timestamp from current time in Python. + * + * timestamp = Timestamp() + * timestamp.GetCurrentTime() + * + * # JSON Mapping + * + * In JSON format, the Timestamp type is encoded as a string in the + * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + * where {year} is always expressed using four digits while {month}, {day}, + * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + * is required. A proto3 JSON serializer should always use UTC (as indicated by + * "Z") when printing the Timestamp type and a proto3 JSON parser should be + * able to accept both UTC and other timezones (as indicated by an offset). + * + * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + * 01:30 UTC on January 15, 2017. + * + * In JavaScript, one can convert a Date object to this format using the + * standard + * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + * method. In Python, a standard `datetime.datetime` object can be converted + * to this format using + * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with + * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use + * the Joda Time's [`ISODateTimeFormat.dateTime()`]( + * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D + * ) to obtain a formatter capable of generating timestamps in this format. + */ +export interface Timestamp { + /** + * Represents seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + */ + seconds: number; + /** + * Non-negative fractions of a second at nanosecond resolution. Negative + * second values with fractions must still have non-negative nanos values + * that count forward in time. Must be from 0 to 999,999,999 + * inclusive. + */ + nanos: number; +} + +function createBaseTimestamp(): Timestamp { + return { seconds: 0, nanos: 0 }; +} + +export const Timestamp = { + $type: "google.protobuf.Timestamp" as const, + + encode(message: Timestamp, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.seconds !== 0) { + writer.uint32(8).int64(message.seconds); + } + if (message.nanos !== 0) { + writer.uint32(16).int32(message.nanos); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Timestamp { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseTimestamp(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 8) { + break; + } + + message.seconds = longToNumber(reader.int64() as Long); + continue; + case 2: + if (tag !== 16) { + break; + } + + message.nanos = reader.int32(); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Timestamp { + return { + seconds: isSet(object.seconds) ? Number(object.seconds) : 0, + nanos: isSet(object.nanos) ? Number(object.nanos) : 0, + }; + }, + + toJSON(message: Timestamp): unknown { + const obj: any = {}; + message.seconds !== undefined && (obj.seconds = Math.round(message.seconds)); + message.nanos !== undefined && (obj.nanos = Math.round(message.nanos)); + return obj; + }, + + create, I>>(base?: I): Timestamp { + return Timestamp.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): Timestamp { + const message = createBaseTimestamp(); + message.seconds = object.seconds ?? 0; + message.nanos = object.nanos ?? 0; + return message; + }, +}; + +messageTypeRegistry.set(Timestamp.$type, Timestamp); + +declare var self: any | undefined; +declare var window: any | undefined; +declare var global: any | undefined; +var tsProtoGlobalThis: any = (() => { + if (typeof globalThis !== "undefined") { + return globalThis; + } + if (typeof self !== "undefined") { + return self; + } + if (typeof window !== "undefined") { + return window; + } + if (typeof global !== "undefined") { + return global; + } + throw "Unable to locate global object"; +})(); + +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 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 longToNumber(long: Long): number { + if (long.gt(Number.MAX_SAFE_INTEGER)) { + throw new tsProtoGlobalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); + } + return long.toNumber(); +} + +// 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 (_m0.util.Long !== Long) { + _m0.util.Long = Long as any; + _m0.configure(); +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} diff --git a/integration/static-only-type-registry/parameters.txt b/integration/static-only-type-registry/parameters.txt new file mode 100755 index 000000000..f79d88176 --- /dev/null +++ b/integration/static-only-type-registry/parameters.txt @@ -0,0 +1 @@ +outputTypeAnnotations=static-only,outputTypeRegistry=true diff --git a/integration/static-only-type-registry/static-only-type-registry-test.ts b/integration/static-only-type-registry/static-only-type-registry-test.ts new file mode 100644 index 000000000..088479570 --- /dev/null +++ b/integration/static-only-type-registry/static-only-type-registry-test.ts @@ -0,0 +1,41 @@ +import { Foo, Foo2 } from "./foo"; +import { Bar } from "./bar/bar"; +import { messageTypeRegistry } from "./typeRegistry"; + +describe("type-annotations", () => { + it("should not output $type field", () => { + expect(Foo.fromPartial({})).toMatchInlineSnapshot(` + { + "timestamp": undefined, + } + `); + expect(Bar.fromPartial({})).toMatchInlineSnapshot(` + { + "foo": undefined, + } + `); + }); + + it("should have a $type field on the static definition", () => { + expect(Foo.$type).toMatchInlineSnapshot(`"foo.Foo"`); + }); + + it("should ignore $type field when creating from partial", () => { + const foo2 = Foo2.fromPartial({}); + expect(foo2).toMatchInlineSnapshot(` + { + "timestamp": undefined, + } + `); + expect(Foo.fromPartial(foo2)).toMatchInlineSnapshot(` + { + "timestamp": undefined, + } + `); + }); + + it("should register every type", () => { + expect(messageTypeRegistry.get("foo.Foo")).toBe(Foo); + expect(messageTypeRegistry.get("foo.bar.Bar")).toBe(Bar); + }); +}); diff --git a/integration/static-only-type-registry/typeRegistry.ts b/integration/static-only-type-registry/typeRegistry.ts new file mode 100644 index 000000000..bd3a5c2eb --- /dev/null +++ b/integration/static-only-type-registry/typeRegistry.ts @@ -0,0 +1,21 @@ +/* eslint-disable */ +import * as _m0 from "protobufjs/minimal"; + +export interface MessageType { + $type: string; + encode(message: Message, writer?: _m0.Writer): _m0.Writer; + decode(input: _m0.Reader | Uint8Array, length?: number): Message; + fromJSON(object: any): Message; + toJSON(message: Message): unknown; + fromPartial(object: DeepPartial): Message; +} + +export type UnknownMessage = unknown; + +export const messageTypeRegistry = new Map(); + +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 keyof T]?: DeepPartial } + : Partial; diff --git a/src/generate-type-registry.ts b/src/generate-type-registry.ts index 8a65d18b5..c57cf9909 100644 --- a/src/generate-type-registry.ts +++ b/src/generate-type-registry.ts @@ -1,15 +1,22 @@ import { code, Code, joinCode } from "ts-poet"; import { Context } from "./context"; import { impFile } from "./utils"; +import { addTypeToMessages } from "./options"; export function generateTypeRegistry(ctx: Context): Code { const chunks: Code[] = []; chunks.push(generateMessageType(ctx)); - chunks.push(code` + if (addTypeToMessages(ctx.options)) { + chunks.push(code` export type UnknownMessage = {$type: string}; `); + } else { + chunks.push(code` + export type UnknownMessage = unknown; + `); + } chunks.push(code` export const messageTypeRegistry = new Map(); @@ -25,7 +32,11 @@ function generateMessageType(ctx: Context): Code { chunks.push(code`export interface MessageType {`); - chunks.push(code`$type: Message['$type'];`); + if (addTypeToMessages(ctx.options)) { + chunks.push(code`$type: Message['$type'];`); + } else { + chunks.push(code`$type: string;`); + } if (ctx.options.outputEncodeMethods) { const Writer = impFile(ctx.options, "Writer@protobufjs/minimal"); diff --git a/src/main.ts b/src/main.ts index 7f6fb27b0..d46340f62 100644 --- a/src/main.ts +++ b/src/main.ts @@ -77,7 +77,7 @@ import { import { generateEncodeTransform, generateDecodeTransform } from "./generate-async-iterable"; import { generateEnum } from "./enums"; import { visit, visitServices } from "./visit"; -import { DateOption, EnvOption, LongOption, OneofOption, Options, ServiceOption } from "./options"; +import { addTypeToMessages, DateOption, EnvOption, LongOption, OneofOption, Options, ServiceOption } from "./options"; import { Context } from "./context"; import { generateSchema } from "./schema"; import { ConditionalOutput } from "ts-poet/build/ConditionalOutput"; @@ -2300,9 +2300,3 @@ function maybeReadonly(options: Options): string { function maybeAsAny(options: Options): string { return options.useReadonlyTypes ? " as any" : ""; } - -function addTypeToMessages(options: Options): boolean { - return ( - (options.outputTypeAnnotations || options.outputTypeRegistry) && options.outputTypeAnnotations !== "static-only" - ); -} diff --git a/src/options.ts b/src/options.ts index ae74cd6a7..bab73fba0 100644 --- a/src/options.ts +++ b/src/options.ts @@ -269,3 +269,9 @@ export function getTsPoetOpts(_options: Options): ToStringOpts { ...(_options.esModuleInterop ? { forceDefaultImport: imports } : { forceModuleImport: imports }), }; } + +export function addTypeToMessages(options: Options): boolean { + return ( + (options.outputTypeAnnotations || options.outputTypeRegistry) && options.outputTypeAnnotations !== "static-only" + ); +}