ts-proto 1.145.0 → 1.147.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.markdown CHANGED
@@ -220,7 +220,7 @@ creating a class and calling the right getters/setters.
220
220
 
221
221
  - ObjectIds can be mapped as `mongodb.ObjectId`
222
222
 
223
- (Configurable with the `useObjectId` parameter.)
223
+ (Configurable with the `useMongoObjectId` parameter.)
224
224
 
225
225
  # Auto-Batching / N+1 Prevention
226
226
 
@@ -410,11 +410,13 @@ Generated code will be placed in the Gradle build directory.
410
410
 
411
411
  - With `--ts_proto_opt=useDate=false`, fields of type `google.protobuf.Timestamp` will not be mapped to type `Date` in the generated types. See [Timestamp](#timestamp) for more details.
412
412
 
413
- - With `--ts_proto_opt=useObjectId=true`, fields of a type called ObjectId where the message is constructed to have on field called value that is a string will be mapped to type `mongodb.ObjectId` in the generated types. This will require your project to install the mongodb npm package. See [ObjectId](#objectid) for more details.
413
+ - With `--ts_proto_opt=useMongoObjectId=true`, fields of a type called ObjectId where the message is constructed to have on field called value that is a string will be mapped to type `mongodb.ObjectId` in the generated types. This will require your project to install the mongodb npm package. See [ObjectId](#objectid) for more details.
414
414
 
415
415
  - With `--ts_proto_opt=outputSchema=true`, meta typings will be generated that can later be used in other code generators.
416
416
 
417
- - With `--ts_proto_opt=outputTypeRegistry=true`, the type registry will be generated that can be used to resolve message types by fully-qualified name. Also, each message will get extra `$type` field containing fully-qualified name.
417
+ - With `--ts_proto_opt=outputTypeAnnotations=true`, each message will be given a `$type` field containing its fully-qualified name.
418
+
419
+ - With `--ts_proto_opt=outputTypeRegistry=true`, the type registry will be generated that can be used to resolve message types by fully-qualified name. Also, each message will be given a `$type` field containing its fully-qualified name.
418
420
 
419
421
  - With `--ts_proto_opt=outputServices=grpc-js`, ts-proto will output service definitions and server / client stubs in [grpc-js](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js) format.
420
422
 
@@ -461,7 +463,7 @@ Generated code will be placed in the Gradle build directory.
461
463
 
462
464
  - With `--ts_proto_opt=useJsonWireFormat=true`, the generated code will reflect the JSON representation of Protobuf messages.
463
465
 
464
- Requires `onlyTypes=true`. Implies `useDate=string` and `stringEnums=true`. This option is to generate types that can be directly used with marshalling/unmarshalling Protobuf messages serialized as JSON.
466
+ Requires `onlyTypes=true`. Implies `useDate=string` and `stringEnums=true`. This option is to generate types that can be directly used with marshalling/unmarshalling Protobuf messages serialized as JSON.
465
467
  You may also want to set `useOptionals=all`, as gRPC gateways are not required to send default value for scalar values.
466
468
 
467
469
  - With `--ts_proto_opt=useNumericEnumForJson=true`, the JSON converter (`toJSON`) will encode enum values as int, rather than a string literal.
@@ -502,6 +504,11 @@ Generated code will be placed in the Gradle build directory.
502
504
 
503
505
  by default this is enabled which would generate a type of `Box_Element_Image_Alignment`. By disabling this option the type that is generated would be `BoxElementImageAlignment`.
504
506
 
507
+ - With `--ts_proto_opt=outputExtensions=true`, the generated code will include proto2 extensions
508
+
509
+ Extension encode/decode methods are compliant with the `outputEncodeMethods` option, and if `unknownFields=true`,
510
+ the `setExtension` and `getExtension` methods will be created for extendable messages, also compliant with `outputEncodeMethods` (setExtension = encode, getExtension = decode).
511
+
505
512
  ### NestJS Support
506
513
 
507
514
  We have a great way of working together with [nestjs](https://docs.nestjs.com/microservices/grpc). `ts-proto` generates `interfaces` and `decorators` for you controller, client. For more information see the [nestjs readme](NESTJS.markdown).
package/build/case.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.camelCaseGrpc = exports.camelCase = exports.capitalize = exports.camelToSnake = exports.snakeToCamel = exports.maybeSnakeToCamel = void 0;
3
+ exports.camelCaseGrpc = exports.uncapitalize = exports.capitalize = exports.camelToSnake = exports.snakeToCamel = exports.maybeSnakeToCamel = void 0;
4
4
  const case_anything_1 = require("case-anything");
5
5
  /** Converts `key` to TS/JS camel-case idiom, unless overridden not to. */
6
6
  function maybeSnakeToCamel(key, options) {
@@ -32,16 +32,16 @@ function capitalize(s) {
32
32
  return s.substring(0, 1).toUpperCase() + s.substring(1);
33
33
  }
34
34
  exports.capitalize = capitalize;
35
- function camelCase(s) {
35
+ function uncapitalize(s) {
36
36
  return s.substring(0, 1).toLowerCase() + s.substring(1);
37
37
  }
38
- exports.camelCase = camelCase;
38
+ exports.uncapitalize = uncapitalize;
39
+ /* This function uses the exact same semantics found inside the grpc
40
+ * nodejs library. Camel case splitting must be done by word i.e
41
+ * GetAPIValue must become getApiValue (notice the API becomes Api).
42
+ * This needs to be followed otherwise it will not succeed in the grpc nodejs module.
43
+ */
39
44
  function camelCaseGrpc(s) {
40
- /* This function uses the exact same semantics found inside the grpc
41
- * nodejs library. Camel case splitting must be done by word i.e
42
- * GetAPIValue must become getApiValue (notice the API becomes Api).
43
- * This needs to be followed otherwise it will not succeed in the grpc nodejs module.
44
- */
45
45
  return (0, case_anything_1.camelCase)(s);
46
46
  }
47
47
  exports.camelCaseGrpc = camelCaseGrpc;
package/build/enums.js CHANGED
@@ -58,7 +58,7 @@ exports.generateEnum = generateEnum;
58
58
  function generateEnumFromJson(ctx, fullName, enumDesc) {
59
59
  const { options, utils } = ctx;
60
60
  const chunks = [];
61
- const functionName = (0, case_1.camelCase)(fullName) + "FromJSON";
61
+ const functionName = (0, case_1.uncapitalize)(fullName) + "FromJSON";
62
62
  chunks.push((0, ts_poet_1.code) `export function ${(0, ts_poet_1.def)(functionName)}(object: any): ${fullName} {`);
63
63
  chunks.push((0, ts_poet_1.code) `switch (object) {`);
64
64
  for (const valueDesc of enumDesc.value) {
@@ -94,7 +94,7 @@ exports.generateEnumFromJson = generateEnumFromJson;
94
94
  function generateEnumToJson(ctx, fullName, enumDesc) {
95
95
  const { options, utils } = ctx;
96
96
  const chunks = [];
97
- const functionName = (0, case_1.camelCase)(fullName) + "ToJSON";
97
+ const functionName = (0, case_1.uncapitalize)(fullName) + "ToJSON";
98
98
  chunks.push((0, ts_poet_1.code) `export function ${(0, ts_poet_1.def)(functionName)}(object: ${fullName}): ${ctx.options.useNumericEnumForJson ? "number" : "string"} {`);
99
99
  chunks.push((0, ts_poet_1.code) `switch (object) {`);
100
100
  for (const valueDesc of enumDesc.value) {
@@ -140,7 +140,7 @@ exports.generateEnumToJson = generateEnumToJson;
140
140
  function generateEnumToNumber(ctx, fullName, enumDesc) {
141
141
  const { options, utils } = ctx;
142
142
  const chunks = [];
143
- const functionName = (0, case_1.camelCase)(fullName) + "ToNumber";
143
+ const functionName = (0, case_1.uncapitalize)(fullName) + "ToNumber";
144
144
  chunks.push((0, ts_poet_1.code) `export function ${(0, ts_poet_1.def)(functionName)}(object: ${fullName}): number {`);
145
145
  chunks.push((0, ts_poet_1.code) `switch (object) {`);
146
146
  for (const valueDesc of enumDesc.value) {
@@ -33,7 +33,7 @@ function generateGenericServiceDefinition(ctx, fileDesc, sourceInfo, serviceDesc
33
33
  const info = sourceInfo.lookup(sourceInfo_1.Fields.service.method, index);
34
34
  (0, utils_1.maybeAddComment)(info, chunks, (_c = methodDesc.options) === null || _c === void 0 ? void 0 : _c.deprecated);
35
35
  chunks.push((0, ts_poet_1.code) `
36
- ${(0, case_1.camelCase)(methodDesc.name)}: ${generateMethodDefinition(ctx, methodDesc)},
36
+ ${(0, case_1.uncapitalize)(methodDesc.name)}: ${generateMethodDefinition(ctx, methodDesc)},
37
37
  `);
38
38
  }
39
39
  chunks.push((0, ts_poet_1.code) `
@@ -76,10 +76,10 @@ function generateMethodOptions(ctx, options) {
76
76
  for (const value of values) {
77
77
  valuesChunks.push((0, ts_poet_1.code) `${ctx.options.env == "node" ? "Buffer.from" : "new Uint8Array"}([${value.join(", ")}])`);
78
78
  }
79
- unknownFieldsChunks.push((0, ts_poet_1.code) `${key}: [\n${(0, ts_poet_1.joinCode)(valuesChunks, { on: "," }).toCodeString([])}\n],`);
79
+ unknownFieldsChunks.push((0, ts_poet_1.code) `${key}: [\n${(0, ts_poet_1.joinCode)(valuesChunks, { on: "," })}\n],`);
80
80
  }
81
81
  unknownFieldsChunks.push((0, ts_poet_1.code) `}`);
82
- chunks.push((0, ts_poet_1.code) `_unknownFields: ${(0, ts_poet_1.joinCode)(unknownFieldsChunks, { on: "\n" }).toCodeString([])}`);
82
+ chunks.push((0, ts_poet_1.code) `_unknownFields: ${(0, ts_poet_1.joinCode)(unknownFieldsChunks, { on: "\n" })}`);
83
83
  }
84
84
  }
85
85
  chunks.push((0, ts_poet_1.code) `}`);
@@ -37,7 +37,7 @@ function generateServerStub(ctx, sourceInfo, serviceDesc) {
37
37
  if (methodDesc.serverStreaming) {
38
38
  // bidi streaming
39
39
  chunks.push((0, ts_poet_1.code) `
40
- ${(0, case_1.camelCase)(methodDesc.name)}(
40
+ ${(0, case_1.uncapitalize)(methodDesc.name)}(
41
41
  request: AsyncIterable<${inputType}>,
42
42
  context: ${CallContext} & CallContextExt,
43
43
  ): ${ServerStreamingMethodResult}<${outputType}>;
@@ -46,7 +46,7 @@ function generateServerStub(ctx, sourceInfo, serviceDesc) {
46
46
  else {
47
47
  // client streaming
48
48
  chunks.push((0, ts_poet_1.code) `
49
- ${(0, case_1.camelCase)(methodDesc.name)}(
49
+ ${(0, case_1.uncapitalize)(methodDesc.name)}(
50
50
  request: AsyncIterable<${inputType}>,
51
51
  context: ${CallContext} & CallContextExt,
52
52
  ): Promise<${outputType}>;
@@ -57,7 +57,7 @@ function generateServerStub(ctx, sourceInfo, serviceDesc) {
57
57
  if (methodDesc.serverStreaming) {
58
58
  // server streaming
59
59
  chunks.push((0, ts_poet_1.code) `
60
- ${(0, case_1.camelCase)(methodDesc.name)}(
60
+ ${(0, case_1.uncapitalize)(methodDesc.name)}(
61
61
  request: ${inputType},
62
62
  context: ${CallContext} & CallContextExt,
63
63
  ): ${ServerStreamingMethodResult}<${outputType}>;
@@ -66,7 +66,7 @@ function generateServerStub(ctx, sourceInfo, serviceDesc) {
66
66
  else {
67
67
  // unary
68
68
  chunks.push((0, ts_poet_1.code) `
69
- ${(0, case_1.camelCase)(methodDesc.name)}(
69
+ ${(0, case_1.uncapitalize)(methodDesc.name)}(
70
70
  request: ${inputType},
71
71
  context: ${CallContext} & CallContextExt,
72
72
  ): Promise<${outputType}>;
@@ -94,7 +94,7 @@ function generateClientStub(ctx, sourceInfo, serviceDesc) {
94
94
  if (methodDesc.serverStreaming) {
95
95
  // bidi streaming
96
96
  chunks.push((0, ts_poet_1.code) `
97
- ${(0, case_1.camelCase)(methodDesc.name)}(
97
+ ${(0, case_1.uncapitalize)(methodDesc.name)}(
98
98
  request: AsyncIterable<${inputType}>,
99
99
  options?: ${CallOptions} & CallOptionsExt,
100
100
  ): AsyncIterable<${outputType}>;
@@ -103,7 +103,7 @@ function generateClientStub(ctx, sourceInfo, serviceDesc) {
103
103
  else {
104
104
  // client streaming
105
105
  chunks.push((0, ts_poet_1.code) `
106
- ${(0, case_1.camelCase)(methodDesc.name)}(
106
+ ${(0, case_1.uncapitalize)(methodDesc.name)}(
107
107
  request: AsyncIterable<${inputType}>,
108
108
  options?: ${CallOptions} & CallOptionsExt,
109
109
  ): Promise<${outputType}>;
@@ -114,7 +114,7 @@ function generateClientStub(ctx, sourceInfo, serviceDesc) {
114
114
  if (methodDesc.serverStreaming) {
115
115
  // server streaming
116
116
  chunks.push((0, ts_poet_1.code) `
117
- ${(0, case_1.camelCase)(methodDesc.name)}(
117
+ ${(0, case_1.uncapitalize)(methodDesc.name)}(
118
118
  request: ${inputType},
119
119
  options?: ${CallOptions} & CallOptionsExt,
120
120
  ): AsyncIterable<${outputType}>;
@@ -123,7 +123,7 @@ function generateClientStub(ctx, sourceInfo, serviceDesc) {
123
123
  else {
124
124
  // unary
125
125
  chunks.push((0, ts_poet_1.code) `
126
- ${(0, case_1.camelCase)(methodDesc.name)}(
126
+ ${(0, case_1.uncapitalize)(methodDesc.name)}(
127
127
  request: ${inputType},
128
128
  options?: ${CallOptions} & CallOptionsExt,
129
129
  ): Promise<${outputType}>;
package/build/main.js CHANGED
@@ -77,7 +77,11 @@ function generateFile(ctx, fileDesc) {
77
77
  // We add `nestJs` here because enough though it doesn't use our encode/decode methods
78
78
  // for most/vanilla messages, we do generate static wrap/unwrap methods for the special
79
79
  // Struct/Value/wrapper types and use the `wrappers[...]` to have NestJS know about them.
80
- if (options.outputEncodeMethods || options.outputJsonMethods || options.outputTypeRegistry || options.nestJs) {
80
+ if (options.outputEncodeMethods ||
81
+ options.outputJsonMethods ||
82
+ options.outputTypeAnnotations ||
83
+ options.outputTypeRegistry ||
84
+ options.nestJs) {
81
85
  // then add the encoder/decoder/base instance
82
86
  (0, visit_1.visit)(fileDesc, sourceInfo, (fullName, message, _sInfo, fullProtoTypeName) => {
83
87
  const fullTypeName = (0, utils_1.maybePrefixPackage)(fileDesc, fullProtoTypeName);
@@ -89,17 +93,29 @@ function generateFile(ctx, fileDesc) {
89
93
  chunks.push(generateBaseInstanceFactory(ctx, fullName, message, fullTypeName));
90
94
  }
91
95
  const staticMembers = [];
92
- if (options.outputTypeRegistry) {
96
+ if (options.outputTypeAnnotations || options.outputTypeRegistry) {
93
97
  staticMembers.push((0, ts_poet_1.code) `$type: '${fullTypeName}' as const`);
94
98
  }
99
+ if (options.outputExtensions) {
100
+ for (const extension of message.extension) {
101
+ const { name, type, extensionInfo } = generateExtension(ctx, message, extension);
102
+ staticMembers.push((0, ts_poet_1.code) `${name}: <${ctx.utils.Extension}<${type}>> ${extensionInfo}`);
103
+ }
104
+ }
95
105
  if (options.outputEncodeMethods) {
96
106
  if (options.outputEncodeMethods === true ||
97
107
  options.outputEncodeMethods === "encode-only" ||
98
108
  options.outputEncodeMethods === "encode-no-creation") {
99
109
  staticMembers.push(generateEncode(ctx, fullName, message));
110
+ if (options.outputExtensions && options.unknownFields && message.extensionRange.length) {
111
+ staticMembers.push(generateSetExtension(ctx, fullName));
112
+ }
100
113
  }
101
114
  if (options.outputEncodeMethods === true || options.outputEncodeMethods === "decode-only") {
102
115
  staticMembers.push(generateDecode(ctx, fullName, message));
116
+ if (options.outputExtensions && options.unknownFields && message.extensionRange.length) {
117
+ staticMembers.push(generateGetExtension(ctx, fullName));
118
+ }
103
119
  }
104
120
  }
105
121
  if (options.useAsyncIterable) {
@@ -144,6 +160,12 @@ function generateFile(ctx, fileDesc) {
144
160
  }
145
161
  }, options);
146
162
  }
163
+ if (options.outputExtensions) {
164
+ for (const extension of fileDesc.extension) {
165
+ const { name, type, extensionInfo } = generateExtension(ctx, undefined, extension);
166
+ chunks.push((0, ts_poet_1.code) `export const ${name}: ${ctx.utils.Extension}<${type}> = ${extensionInfo};`);
167
+ }
168
+ }
147
169
  if (options.nestJs) {
148
170
  if (fileDesc.messageType.find((message) => message.field.find(types_1.isStructType))) {
149
171
  chunks.push(makeProtobufStructWrapper(options));
@@ -256,6 +278,7 @@ function makeUtils(options) {
256
278
  ...makeComparisonUtils(),
257
279
  ...makeNiceGrpcServerStreamingMethodResult(),
258
280
  ...makeGrpcWebErrorClass(bytes),
281
+ ...makeExtensionClass(options),
259
282
  };
260
283
  }
261
284
  exports.makeUtils = makeUtils;
@@ -395,7 +418,7 @@ function makeDeepPartial(options, longs) {
395
418
  const maybeLong = options.forceLong === options_1.LongOption.LONG ? (0, ts_poet_1.code) ` : T extends ${longs.Long} ? string | number | Long ` : "";
396
419
  const Builtin = (0, ts_poet_1.conditionalOutput)("Builtin", (0, ts_poet_1.code) `type Builtin = Date | Function | Uint8Array | string | number | boolean |${options.forceLong === options_1.LongOption.BIGINT ? " bigint |" : ""} undefined;`);
397
420
  // Based on https://github.com/sindresorhus/type-fest/pull/259
398
- const maybeExcludeType = options.outputTypeRegistry ? `| '$type'` : "";
421
+ const maybeExcludeType = options.outputTypeAnnotations || options.outputTypeRegistry ? `| '$type'` : "";
399
422
  const Exact = (0, ts_poet_1.conditionalOutput)("Exact", (0, ts_poet_1.code) `
400
423
  type KeysOfUnion<T> = T extends T ? keyof T : never;
401
424
  ${maybeExport} type Exact<P, I extends P> = P extends ${Builtin}
@@ -404,7 +427,7 @@ function makeDeepPartial(options, longs) {
404
427
  { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P> ${maybeExcludeType}>]: never };
405
428
  `);
406
429
  // Based on the type from ts-essentials
407
- const keys = options.outputTypeRegistry ? (0, ts_poet_1.code) `Exclude<keyof T, '$type'>` : (0, ts_poet_1.code) `keyof T`;
430
+ const keys = options.outputTypeAnnotations || options.outputTypeRegistry ? (0, ts_poet_1.code) `Exclude<keyof T, '$type'>` : (0, ts_poet_1.code) `keyof T`;
408
431
  const DeepPartial = (0, ts_poet_1.conditionalOutput)("DeepPartial", (0, ts_poet_1.code) `
409
432
  ${maybeExport} type DeepPartial<T> = T extends ${Builtin}
410
433
  ? T
@@ -464,7 +487,7 @@ function makeTimestampMethods(options, longs) {
464
487
  // (note this only occurs when the string is > 8 characters)
465
488
  seconds = "Math.trunc(date.getTime() / 1_000).toString()";
466
489
  }
467
- const maybeTypeField = options.outputTypeRegistry ? `$type: 'google.protobuf.Timestamp',` : "";
490
+ const maybeTypeField = options.outputTypeAnnotations || options.outputTypeRegistry ? `$type: 'google.protobuf.Timestamp',` : "";
468
491
  const toTimestamp = (0, ts_poet_1.conditionalOutput)("toTimestamp", options.useDate === options_1.DateOption.STRING
469
492
  ? (0, ts_poet_1.code) `
470
493
  function toTimestamp(dateStr: string): ${Timestamp} {
@@ -550,6 +573,22 @@ function makeGrpcWebErrorClass(bytes) {
550
573
  `);
551
574
  return { GrpcWebError };
552
575
  }
576
+ function makeExtensionClass(options) {
577
+ const Reader = (0, utils_1.impFile)(options, "Reader@protobufjs/minimal");
578
+ const Writer = (0, utils_1.impFile)(options, "Writer@protobufjs/minimal");
579
+ const Extension = (0, ts_poet_1.conditionalOutput)("Extension", (0, ts_poet_1.code) `
580
+ export interface Extension <T> {
581
+ number: number;
582
+ tag: number;
583
+ singularTag?: number;
584
+ encode?: (message: T) => Uint8Array[];
585
+ decode?: (tag: number, input: Uint8Array[]) => T;
586
+ repeated: boolean;
587
+ packed: boolean;
588
+ }
589
+ `);
590
+ return { Extension };
591
+ }
553
592
  // Create the interface with properties
554
593
  function generateInterfaceDeclaration(ctx, fullName, messageDesc, sourceInfo, fullTypeName) {
555
594
  var _a;
@@ -558,7 +597,7 @@ function generateInterfaceDeclaration(ctx, fullName, messageDesc, sourceInfo, fu
558
597
  (0, utils_1.maybeAddComment)(sourceInfo, chunks, (_a = messageDesc.options) === null || _a === void 0 ? void 0 : _a.deprecated);
559
598
  // interface name should be defined to avoid import collisions
560
599
  chunks.push((0, ts_poet_1.code) `export interface ${(0, ts_poet_1.def)(fullName)} {`);
561
- if (ctx.options.outputTypeRegistry) {
600
+ if (ctx.options.outputTypeAnnotations || ctx.options.outputTypeRegistry) {
562
601
  chunks.push((0, ts_poet_1.code) `$type: '${fullTypeName}',`);
563
602
  }
564
603
  // When oneof=unions, we generate a single property with an ADT per `oneof` clause.
@@ -649,7 +688,7 @@ function generateBaseInstanceFactory(ctx, fullName, messageDesc, fullTypeName) {
649
688
  : (0, types_1.defaultValue)(ctx, field);
650
689
  fields.push((0, ts_poet_1.code) `${name}: ${val}`);
651
690
  }
652
- if (ctx.options.outputTypeRegistry) {
691
+ if (ctx.options.outputTypeAnnotations || ctx.options.outputTypeRegistry) {
653
692
  fields.unshift((0, ts_poet_1.code) `$type: '${fullTypeName}'`);
654
693
  }
655
694
  if (ctx.options.unknownFields && ctx.options.initializeFieldsAsUndefined) {
@@ -661,6 +700,73 @@ function generateBaseInstanceFactory(ctx, fullName, messageDesc, fullTypeName) {
661
700
  }
662
701
  `;
663
702
  }
703
+ function getDecodeReadSnippet(ctx, field) {
704
+ const { options, utils } = ctx;
705
+ let readSnippet;
706
+ if ((0, types_1.isPrimitive)(field)) {
707
+ readSnippet = (0, ts_poet_1.code) `reader.${(0, types_1.toReaderCall)(field)}()`;
708
+ if ((0, types_1.isBytes)(field)) {
709
+ if (options.env === options_1.EnvOption.NODE) {
710
+ readSnippet = (0, ts_poet_1.code) `${readSnippet} as Buffer`;
711
+ }
712
+ }
713
+ else if ((0, types_1.basicLongWireType)(field.type) !== undefined) {
714
+ if (options.forceLong === options_1.LongOption.LONG) {
715
+ readSnippet = (0, ts_poet_1.code) `${readSnippet} as Long`;
716
+ }
717
+ else if (options.forceLong === options_1.LongOption.STRING) {
718
+ readSnippet = (0, ts_poet_1.code) `${utils.longToString}(${readSnippet} as Long)`;
719
+ }
720
+ else if (options.forceLong === options_1.LongOption.BIGINT) {
721
+ readSnippet = (0, ts_poet_1.code) `${utils.longToBigint}(${readSnippet} as Long)`;
722
+ }
723
+ else {
724
+ readSnippet = (0, ts_poet_1.code) `${utils.longToNumber}(${readSnippet} as Long)`;
725
+ }
726
+ }
727
+ else if ((0, types_1.isEnum)(field)) {
728
+ if (options.stringEnums) {
729
+ const fromJson = (0, types_1.getEnumMethod)(ctx, field.typeName, "FromJSON");
730
+ readSnippet = (0, ts_poet_1.code) `${fromJson}(${readSnippet})`;
731
+ }
732
+ else {
733
+ readSnippet = (0, ts_poet_1.code) `${readSnippet} as any`;
734
+ }
735
+ }
736
+ }
737
+ else if ((0, types_1.isValueType)(ctx, field)) {
738
+ const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
739
+ const unwrap = (decodedValue) => {
740
+ if ((0, types_1.isListValueType)(field) || (0, types_1.isStructType)(field) || (0, types_1.isAnyValueType)(field) || (0, types_1.isFieldMaskType)(field)) {
741
+ return (0, ts_poet_1.code) `${type}.unwrap(${decodedValue})`;
742
+ }
743
+ return (0, ts_poet_1.code) `${decodedValue}.value`;
744
+ };
745
+ const decoder = (0, ts_poet_1.code) `${type}.decode(reader, reader.uint32())`;
746
+ readSnippet = (0, ts_poet_1.code) `${unwrap(decoder)}`;
747
+ }
748
+ else if ((0, types_1.isTimestamp)(field) && (options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) {
749
+ const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
750
+ readSnippet = (0, ts_poet_1.code) `${utils.fromTimestamp}(${type}.decode(reader, reader.uint32()))`;
751
+ }
752
+ else if ((0, types_1.isObjectId)(field) && options.useMongoObjectId) {
753
+ const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
754
+ readSnippet = (0, ts_poet_1.code) `${utils.fromProtoObjectId}(${type}.decode(reader, reader.uint32()))`;
755
+ }
756
+ else if ((0, types_1.isMessage)(field)) {
757
+ const type = (0, types_1.basicTypeName)(ctx, field);
758
+ if (field.type == ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_GROUP) {
759
+ readSnippet = (0, ts_poet_1.code) `${type}.decode(reader)`;
760
+ }
761
+ else {
762
+ readSnippet = (0, ts_poet_1.code) `${type}.decode(reader, reader.uint32())`;
763
+ }
764
+ }
765
+ else {
766
+ throw new Error(`Unhandled field ${field}`);
767
+ }
768
+ return readSnippet;
769
+ }
664
770
  /** Creates a function to decode a message by loop overing the tags. */
665
771
  function generateDecode(ctx, fullName, messageDesc) {
666
772
  const { options, utils, typeMap } = ctx;
@@ -692,71 +798,12 @@ function generateDecode(ctx, fullName, messageDesc) {
692
798
  chunks.push((0, ts_poet_1.code) `case ${field.number}:`);
693
799
  const tag = ((field.number << 3) | (0, types_1.basicWireType)(field.type)) >>> 0;
694
800
  const tagCheck = (0, ts_poet_1.code) `
695
- if(tag != ${tag})
801
+ if (tag !== ${tag}) {
696
802
  break;
803
+ }
697
804
  `;
698
805
  // get a generic 'reader.doSomething' bit that is specific to the basic type
699
- let readSnippet;
700
- if ((0, types_1.isPrimitive)(field)) {
701
- readSnippet = (0, ts_poet_1.code) `reader.${(0, types_1.toReaderCall)(field)}()`;
702
- if ((0, types_1.isBytes)(field)) {
703
- if (options.env === options_1.EnvOption.NODE) {
704
- readSnippet = (0, ts_poet_1.code) `${readSnippet} as Buffer`;
705
- }
706
- }
707
- else if ((0, types_1.basicLongWireType)(field.type) !== undefined) {
708
- if (options.forceLong === options_1.LongOption.LONG) {
709
- readSnippet = (0, ts_poet_1.code) `${readSnippet} as Long`;
710
- }
711
- else if (options.forceLong === options_1.LongOption.STRING) {
712
- readSnippet = (0, ts_poet_1.code) `${utils.longToString}(${readSnippet} as Long)`;
713
- }
714
- else if (options.forceLong === options_1.LongOption.BIGINT) {
715
- readSnippet = (0, ts_poet_1.code) `${utils.longToBigint}(${readSnippet} as Long)`;
716
- }
717
- else {
718
- readSnippet = (0, ts_poet_1.code) `${utils.longToNumber}(${readSnippet} as Long)`;
719
- }
720
- }
721
- else if ((0, types_1.isEnum)(field)) {
722
- if (options.stringEnums) {
723
- const fromJson = (0, types_1.getEnumMethod)(ctx, field.typeName, "FromJSON");
724
- readSnippet = (0, ts_poet_1.code) `${fromJson}(${readSnippet})`;
725
- }
726
- else {
727
- readSnippet = (0, ts_poet_1.code) `${readSnippet} as any`;
728
- }
729
- }
730
- }
731
- else if ((0, types_1.isValueType)(ctx, field)) {
732
- const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
733
- const unwrap = (decodedValue) => {
734
- if ((0, types_1.isListValueType)(field) || (0, types_1.isStructType)(field) || (0, types_1.isAnyValueType)(field) || (0, types_1.isFieldMaskType)(field)) {
735
- return (0, ts_poet_1.code) `${type}.unwrap(${decodedValue})`;
736
- }
737
- return (0, ts_poet_1.code) `${decodedValue}.value`;
738
- };
739
- const decoder = (0, ts_poet_1.code) `${type}.decode(reader, reader.uint32())`;
740
- readSnippet = (0, ts_poet_1.code) `${unwrap(decoder)}`;
741
- }
742
- else if ((0, types_1.isTimestamp)(field) && (options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) {
743
- const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
744
- readSnippet = (0, ts_poet_1.code) `${utils.fromTimestamp}(${type}.decode(reader, reader.uint32()))`;
745
- }
746
- else if ((0, types_1.isObjectId)(field) && options.useMongoObjectId) {
747
- const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
748
- readSnippet = (0, ts_poet_1.code) `${utils.fromProtoObjectId}(${type}.decode(reader, reader.uint32()))`;
749
- }
750
- else if ((0, types_1.isMessage)(field)) {
751
- const type = (0, types_1.basicTypeName)(ctx, field);
752
- if (field.type == ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_GROUP)
753
- readSnippet = (0, ts_poet_1.code) `${type}.decode(reader)`;
754
- else
755
- readSnippet = (0, ts_poet_1.code) `${type}.decode(reader, reader.uint32())`;
756
- }
757
- else {
758
- throw new Error(`Unhandled field ${field}`);
759
- }
806
+ const readSnippet = getDecodeReadSnippet(ctx, field);
760
807
  // and then use the snippet to handle repeated fields if necessary
761
808
  const initializerNecessary = !options.initializeFieldsAsUndefined && (0, types_1.isOptionalProperty)(field, messageDesc.options, options);
762
809
  if ((0, types_1.isRepeated)(field)) {
@@ -769,9 +816,9 @@ function generateDecode(ctx, fullName, messageDesc) {
769
816
  : `message.${fieldName}${maybeNonNullAssertion}[${varName}.key] = ${varName}.value`;
770
817
  const initializerSnippet = initializerNecessary
771
818
  ? `
772
- if(message.${fieldName} === undefined)
819
+ if (message.${fieldName} === undefined) {
773
820
  message.${fieldName} = ${ctx.options.useMapType ? "new Map()" : "{}"};
774
- `
821
+ }`
775
822
  : "";
776
823
  chunks.push((0, ts_poet_1.code) `
777
824
  ${tagCheck}
@@ -784,8 +831,10 @@ function generateDecode(ctx, fullName, messageDesc) {
784
831
  }
785
832
  else {
786
833
  const initializerSnippet = initializerNecessary
787
- ? `if(message.${fieldName} === undefined)
788
- message.${fieldName} = [];`
834
+ ? `
835
+ if (message.${fieldName} === undefined) {
836
+ message.${fieldName} = [];
837
+ }`
789
838
  : "";
790
839
  if ((0, types_1.packedType)(field.type) === undefined) {
791
840
  chunks.push((0, ts_poet_1.code) `
@@ -797,13 +846,14 @@ function generateDecode(ctx, fullName, messageDesc) {
797
846
  else {
798
847
  const packedTag = ((field.number << 3) | 2) >>> 0;
799
848
  chunks.push((0, ts_poet_1.code) `
800
- if(tag == ${tag}){
849
+ if (tag === ${tag}) {
801
850
  ${initializerSnippet}
802
851
  message.${fieldName}${maybeNonNullAssertion}.push(${readSnippet});
852
+
803
853
  continue;
804
854
  }
805
855
 
806
- if(tag == ${packedTag}){
856
+ if (tag === ${packedTag}) {
807
857
  ${initializerSnippet}
808
858
  const end2 = reader.uint32() + reader.pos;
809
859
  while (reader.pos < end2) {
@@ -831,21 +881,24 @@ function generateDecode(ctx, fullName, messageDesc) {
831
881
  message.${fieldName} = ${readSnippet};
832
882
  `);
833
883
  }
834
- if (!(0, types_1.isRepeated)(field) || (0, types_1.packedType)(field.type) === undefined)
884
+ if (!(0, types_1.isRepeated)(field) || (0, types_1.packedType)(field.type) === undefined) {
835
885
  chunks.push((0, ts_poet_1.code) `continue;`);
886
+ }
836
887
  });
837
888
  chunks.push((0, ts_poet_1.code) `}`);
838
889
  chunks.push((0, ts_poet_1.code) `
839
- if((tag & 7) == 4 || tag == 0)
890
+ if ((tag & 7) === 4 || tag === 0) {
840
891
  break;
892
+ }
841
893
  `);
842
894
  if (options.unknownFields) {
843
895
  let unknownFieldsInitializerSnippet = "";
844
896
  let maybeNonNullAssertion = options.initializeFieldsAsUndefined ? "!" : "";
845
897
  if (!options.initializeFieldsAsUndefined) {
846
898
  unknownFieldsInitializerSnippet = `
847
- if(message._unknownFields === undefined)
899
+ if (message._unknownFields === undefined) {
848
900
  message._unknownFields = {};
901
+ }
849
902
  `;
850
903
  }
851
904
  chunks.push((0, ts_poet_1.code) `
@@ -856,10 +909,11 @@ function generateDecode(ctx, fullName, messageDesc) {
856
909
  ${unknownFieldsInitializerSnippet}
857
910
  const list = message._unknownFields${maybeNonNullAssertion}[tag];
858
911
 
859
- if(list === undefined)
912
+ if (list === undefined) {
860
913
  message._unknownFields${maybeNonNullAssertion}[tag] = [buf];
861
- else
914
+ } else {
862
915
  list.push(buf);
916
+ }
863
917
  `);
864
918
  }
865
919
  else {
@@ -900,7 +954,7 @@ function getEncodeWriteSnippet(ctx, field) {
900
954
  return (place) => (0, ts_poet_1.code) `${type}.encode(${utils.toTimestamp}(${place}), writer.uint32(${tag}).fork()).ldelim()`;
901
955
  }
902
956
  else if ((0, types_1.isValueType)(ctx, field)) {
903
- const maybeTypeField = options.outputTypeRegistry ? `$type: '${field.typeName.slice(1)}',` : "";
957
+ const maybeTypeField = options.outputTypeAnnotations || options.outputTypeRegistry ? `$type: '${field.typeName.slice(1)}',` : "";
904
958
  const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
905
959
  const wrappedValue = (place) => {
906
960
  if ((0, types_1.isAnyValueType)(field) || (0, types_1.isListValueType)(field) || (0, types_1.isStructType)(field) || (0, types_1.isFieldMaskType)(field)) {
@@ -949,7 +1003,7 @@ function generateEncode(ctx, fullName, messageDesc) {
949
1003
  if ((0, types_1.isRepeated)(field)) {
950
1004
  if ((0, types_1.isMapType)(ctx, messageDesc, field)) {
951
1005
  const valueType = typeMap.get(field.typeName)[2].field[1];
952
- const maybeTypeField = options.outputTypeRegistry ? `$type: '${field.typeName.slice(1)}',` : "";
1006
+ const maybeTypeField = options.outputTypeAnnotations || options.outputTypeRegistry ? `$type: '${field.typeName.slice(1)}',` : "";
953
1007
  const entryWriteSnippet = (0, types_1.isValueType)(ctx, valueType)
954
1008
  ? (0, ts_poet_1.code) `
955
1009
  if (value !== undefined) {
@@ -1099,6 +1153,226 @@ function generateEncode(ctx, fullName, messageDesc) {
1099
1153
  chunks.push((0, ts_poet_1.code) `}`);
1100
1154
  return (0, ts_poet_1.joinCode)(chunks, { on: "\n" });
1101
1155
  }
1156
+ function generateSetExtension(ctx, fullName) {
1157
+ return (0, ts_poet_1.code) `
1158
+ setExtension <T> (message: ${fullName}, extension: ${ctx.utils.Extension}<T>, value: T): void {
1159
+ const encoded = extension.encode!(value);
1160
+
1161
+ if (message._unknownFields !== undefined) {
1162
+ delete message._unknownFields[extension.tag];
1163
+
1164
+ if (extension.singularTag !== undefined) {
1165
+ delete message._unknownFields[extension.singularTag];
1166
+ }
1167
+ }
1168
+
1169
+ if (encoded.length !== 0) {
1170
+ if (message._unknownFields === undefined) {
1171
+ message._unknownFields = {};
1172
+ }
1173
+
1174
+ message._unknownFields[extension.tag] = encoded;
1175
+ }
1176
+ }
1177
+ `;
1178
+ }
1179
+ function generateGetExtension(ctx, fullName) {
1180
+ return (0, ts_poet_1.code) `
1181
+ getExtension <T> (message: ${fullName}, extension: ${ctx.utils.Extension}<T>): T | undefined {
1182
+ let results: T | undefined = undefined;
1183
+
1184
+ if (message._unknownFields === undefined) {
1185
+ return undefined;
1186
+ }
1187
+
1188
+ let list = message._unknownFields[extension.tag];
1189
+
1190
+ if (list !== undefined) {
1191
+ results = extension.decode!(extension.tag, list);
1192
+ }
1193
+
1194
+ if (extension.singularTag === undefined) {
1195
+ return results;
1196
+ }
1197
+
1198
+ list = message._unknownFields[extension.singularTag];
1199
+
1200
+ if (list !== undefined) {
1201
+ const results2 = extension.decode!(extension.singularTag, list);
1202
+
1203
+ if (results !== undefined && (results as any).length !== 0) {
1204
+ results = (results as any).concat(results2);
1205
+ } else {
1206
+ results = results2;
1207
+ }
1208
+ }
1209
+
1210
+ return results;
1211
+ }
1212
+ `;
1213
+ }
1214
+ function generateExtension(ctx, message, extension) {
1215
+ var _a;
1216
+ const type = (0, types_1.toTypeName)(ctx, message, extension);
1217
+ const packedTag = (0, types_1.isRepeated)(extension) && (0, types_1.packedType)(extension.type) !== undefined ? ((extension.number << 3) | 2) >>> 0 : undefined;
1218
+ const singularTag = ((extension.number << 3) | (0, types_1.basicWireType)(extension.type)) >>> 0;
1219
+ const tag = packedTag !== null && packedTag !== void 0 ? packedTag : singularTag;
1220
+ const chunks = [];
1221
+ chunks.push((0, ts_poet_1.code) `{`);
1222
+ chunks.push((0, ts_poet_1.code) `number: ${extension.number},`);
1223
+ chunks.push((0, ts_poet_1.code) `tag: ${tag},`);
1224
+ if (packedTag !== undefined)
1225
+ chunks.push((0, ts_poet_1.code) `singularTag: ${singularTag},`);
1226
+ chunks.push((0, ts_poet_1.code) `repeated: ${extension.label == ts_proto_descriptors_1.FieldDescriptorProto_Label.LABEL_REPEATED},`);
1227
+ chunks.push((0, ts_poet_1.code) `packed: ${((_a = extension.options) === null || _a === void 0 ? void 0 : _a.packed) ? true : false},`);
1228
+ const Reader = (0, utils_1.impFile)(ctx.options, "Reader@protobufjs/minimal");
1229
+ const Writer = (0, utils_1.impFile)(ctx.options, "Writer@protobufjs/minimal");
1230
+ if (ctx.options.outputEncodeMethods === true ||
1231
+ ctx.options.outputEncodeMethods === "encode-only" ||
1232
+ ctx.options.outputEncodeMethods === "encode-no-creation") {
1233
+ chunks.push((0, ts_poet_1.code) `
1234
+ encode: (value: ${type}): Uint8Array[] => {
1235
+ const encoded: Uint8Array[] = [];
1236
+ `);
1237
+ function getEncodeSnippet(ctx, field) {
1238
+ const { options, utils } = ctx;
1239
+ if ((0, types_1.isEnum)(field) && options.stringEnums) {
1240
+ const toNumber = (0, types_1.getEnumMethod)(ctx, field.typeName, "ToNumber");
1241
+ return (place) => (0, ts_poet_1.code) `writer.${(0, types_1.toReaderCall)(field)}(${toNumber}(${place}))`;
1242
+ }
1243
+ else if ((0, types_1.isLong)(field) && options.forceLong === options_1.LongOption.BIGINT) {
1244
+ return (place) => (0, ts_poet_1.code) `writer.${(0, types_1.toReaderCall)(field)}(${place}.toString())`;
1245
+ }
1246
+ else if ((0, types_1.isScalar)(field) || (0, types_1.isEnum)(field)) {
1247
+ return (place) => (0, ts_poet_1.code) `writer.${(0, types_1.toReaderCall)(field)}(${place})`;
1248
+ }
1249
+ else if ((0, types_1.isObjectId)(field) && options.useMongoObjectId) {
1250
+ const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
1251
+ return (place) => (0, ts_poet_1.code) `${type}.encode(${utils.toProtoObjectId}(${place}), writer.fork()).ldelim()`;
1252
+ }
1253
+ else if ((0, types_1.isTimestamp)(field) && (options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) {
1254
+ const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
1255
+ return (place) => (0, ts_poet_1.code) `${type}.encode(${utils.toTimestamp}(${place}), writer.fork()).ldelim()`;
1256
+ }
1257
+ else if ((0, types_1.isValueType)(ctx, field)) {
1258
+ const maybeTypeField = options.outputTypeAnnotations || options.outputTypeRegistry ? `$type: '${field.typeName.slice(1)}',` : "";
1259
+ const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
1260
+ const wrappedValue = (place) => {
1261
+ if ((0, types_1.isAnyValueType)(field) || (0, types_1.isListValueType)(field) || (0, types_1.isStructType)(field) || (0, types_1.isFieldMaskType)(field)) {
1262
+ return (0, ts_poet_1.code) `${type}.wrap(${place})`;
1263
+ }
1264
+ return (0, ts_poet_1.code) `{${maybeTypeField} value: ${place}!}`;
1265
+ };
1266
+ return (place) => (0, ts_poet_1.code) `${type}.encode(${wrappedValue(place)}, writer.fork()).ldelim()`;
1267
+ }
1268
+ else if ((0, types_1.isMessage)(field)) {
1269
+ const type = (0, types_1.basicTypeName)(ctx, field);
1270
+ if (field.type == ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_GROUP) {
1271
+ const endTag = ((field.number << 3) | 4) >>> 0;
1272
+ return (place) => (0, ts_poet_1.code) `${type}.encode(${place}, writer).uint32(${endTag})`;
1273
+ }
1274
+ return (place) => (0, ts_poet_1.code) `${type}.encode(${place}, writer.fork()).ldelim()`;
1275
+ }
1276
+ else {
1277
+ throw new Error(`Unhandled field ${field}`);
1278
+ }
1279
+ }
1280
+ const writeSnippet = getEncodeSnippet(ctx, extension);
1281
+ if ((0, types_1.isRepeated)(extension)) {
1282
+ if (packedTag === undefined) {
1283
+ chunks.push((0, ts_poet_1.code) `
1284
+ for (const v of value) {
1285
+ const writer = ${Writer}.create();
1286
+ ${writeSnippet("v")};
1287
+ encoded.push(writer.finish());
1288
+ }
1289
+ `);
1290
+ }
1291
+ else {
1292
+ const rhs = (x) => (0, types_1.isLong)(extension) && ctx.options.forceLong === options_1.LongOption.BIGINT ? `${x}.toString()` : x;
1293
+ chunks.push((0, ts_poet_1.code) `
1294
+ const writer = ${Writer}.create();
1295
+ writer.fork();
1296
+ for (const v of value) {
1297
+ ${writeSnippet(rhs("v"))};
1298
+ }
1299
+ writer.ldelim();
1300
+ encoded.push(writer.finish());
1301
+ `);
1302
+ }
1303
+ }
1304
+ else if ((0, types_1.isScalar)(extension) || (0, types_1.isEnum)(extension)) {
1305
+ chunks.push((0, ts_poet_1.code) `
1306
+ if (${(0, types_1.notDefaultCheck)(ctx, extension, message === null || message === void 0 ? void 0 : message.options, "value")}) {
1307
+ const writer = ${Writer}.create();
1308
+ ${writeSnippet("value")};
1309
+ encoded.push(writer.finish());
1310
+ }
1311
+ `);
1312
+ }
1313
+ else {
1314
+ chunks.push((0, ts_poet_1.code) `
1315
+ const writer = ${Writer}.create();
1316
+ ${writeSnippet("value")};
1317
+ encoded.push(writer.finish());
1318
+ `);
1319
+ }
1320
+ chunks.push((0, ts_poet_1.code) `
1321
+ return encoded;
1322
+ },
1323
+ `);
1324
+ }
1325
+ if (ctx.options.outputEncodeMethods === true || ctx.options.outputEncodeMethods === "decode-only") {
1326
+ chunks.push((0, ts_poet_1.code) `decode: (tag: number, input: Uint8Array[]): ${type} => {`);
1327
+ // get a generic 'reader.doSomething' bit that is specific to the basic type
1328
+ const readSnippet = getDecodeReadSnippet(ctx, extension);
1329
+ if ((0, types_1.isRepeated)(extension)) {
1330
+ chunks.push((0, ts_poet_1.code) `const values: ${type} = [];`);
1331
+ // start loop over all buffers
1332
+ chunks.push((0, ts_poet_1.code) `
1333
+ for (var buffer of input) {
1334
+ const reader = ${Reader}.create(buffer);
1335
+ `);
1336
+ if ((0, types_1.packedType)(extension.type) === undefined) {
1337
+ chunks.push((0, ts_poet_1.code) `
1338
+ values.push(${readSnippet});
1339
+ `);
1340
+ }
1341
+ else {
1342
+ chunks.push((0, ts_poet_1.code) `
1343
+ if (tag == ${packedTag}) {
1344
+ const end2 = reader.uint32() + reader.pos;
1345
+ while (reader.pos < end2) {
1346
+ values.push(${readSnippet});
1347
+ }
1348
+ } else {
1349
+ values.push(${readSnippet});
1350
+ }
1351
+ `);
1352
+ }
1353
+ chunks.push((0, ts_poet_1.code) `
1354
+ }
1355
+
1356
+ return values;
1357
+ },
1358
+ `);
1359
+ }
1360
+ else {
1361
+ // pick the last entry, since it overrides all previous entries if not repeated
1362
+ chunks.push((0, ts_poet_1.code) `
1363
+ const reader = ${Reader}.create(input[input.length -1]);
1364
+ return ${readSnippet};
1365
+ },
1366
+ `);
1367
+ }
1368
+ }
1369
+ chunks.push((0, ts_poet_1.code) `}`);
1370
+ return {
1371
+ name: (0, case_1.maybeSnakeToCamel)(extension.name, ctx.options),
1372
+ type,
1373
+ extensionInfo: (0, ts_poet_1.joinCode)(chunks, { on: "\n" }),
1374
+ };
1375
+ }
1102
1376
  /**
1103
1377
  * Creates a function to decode a message from JSON.
1104
1378
  *
@@ -1113,7 +1387,7 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
1113
1387
  fromJSON(${messageDesc.field.length > 0 ? "object" : "_"}: any): ${fullName} {
1114
1388
  return {
1115
1389
  `);
1116
- if (ctx.options.outputTypeRegistry) {
1390
+ if (ctx.options.outputTypeAnnotations || ctx.options.outputTypeRegistry) {
1117
1391
  chunks.push((0, ts_poet_1.code) `$type: ${fullName}.$type,`);
1118
1392
  }
1119
1393
  const oneofFieldsCases = messageDesc.oneofDecl.map((oneof, oneofIndex) => messageDesc.field.filter(types_1.isWithinOneOf).filter((field) => field.oneofIndex === oneofIndex));
package/build/options.js CHANGED
@@ -49,6 +49,7 @@ function defaultOptions() {
49
49
  outputEncodeMethods: true,
50
50
  outputJsonMethods: true,
51
51
  outputPartialMethods: true,
52
+ outputTypeAnnotations: false,
52
53
  outputTypeRegistry: false,
53
54
  stringEnums: false,
54
55
  constEnums: false,
@@ -78,6 +79,7 @@ function defaultOptions() {
78
79
  useMapType: false,
79
80
  useReadonlyTypes: false,
80
81
  useSnakeTypeName: true,
82
+ outputExtensions: false,
81
83
  M: {},
82
84
  };
83
85
  }
package/build/types.js CHANGED
@@ -571,14 +571,14 @@ function toModuleAndType(typeMap, protoType) {
571
571
  }
572
572
  function getEnumMethod(ctx, enumProtoType, methodSuffix) {
573
573
  const [module, type] = toModuleAndType(ctx.typeMap, enumProtoType);
574
- return (0, utils_1.impProto)(ctx.options, module, `${(0, case_1.camelCase)(type)}${methodSuffix}`);
574
+ return (0, utils_1.impProto)(ctx.options, module, `${(0, case_1.uncapitalize)(type)}${methodSuffix}`);
575
575
  }
576
576
  exports.getEnumMethod = getEnumMethod;
577
577
  /** Return the TypeName for any field (primitive/message/etc.) as exposed in the interface. */
578
578
  function toTypeName(ctx, messageDesc, field) {
579
579
  let type = basicTypeName(ctx, field, { keepValueType: false });
580
580
  if (isRepeated(field)) {
581
- const mapType = detectMapType(ctx, messageDesc, field);
581
+ const mapType = messageDesc ? detectMapType(ctx, messageDesc, field) : false;
582
582
  if (mapType) {
583
583
  const { keyType, valueType } = mapType;
584
584
  if (ctx.options.useMapType) {
package/build/utils.js CHANGED
@@ -138,7 +138,8 @@ class FormattedMethodDescriptor {
138
138
  static formatName(methodName, options) {
139
139
  let result = methodName;
140
140
  if (options.lowerCaseServiceMethods || options.outputServices.includes(options_1.ServiceOption.GRPC)) {
141
- result = (0, case_1.camelCaseGrpc)(result);
141
+ if (options.snakeToCamel)
142
+ result = (0, case_1.camelCaseGrpc)(result);
142
143
  }
143
144
  return result;
144
145
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "1.145.0",
3
+ "version": "1.147.0",
4
4
  "description": "",
5
5
  "main": "build/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",
@@ -65,7 +65,7 @@
65
65
  "object-hash": "^1.3.1",
66
66
  "protobufjs": "^6.11.3",
67
67
  "ts-poet": "^6.4.1",
68
- "ts-proto-descriptors": "1.8.0"
68
+ "ts-proto-descriptors": "1.9.0"
69
69
  },
70
70
  "packageManager": "yarn@3.3.0"
71
71
  }