ts-proto 1.145.0 → 1.146.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
@@ -461,7 +461,7 @@ Generated code will be placed in the Gradle build directory.
461
461
 
462
462
  - With `--ts_proto_opt=useJsonWireFormat=true`, the generated code will reflect the JSON representation of Protobuf messages.
463
463
 
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.
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.
465
465
  You may also want to set `useOptionals=all`, as gRPC gateways are not required to send default value for scalar values.
466
466
 
467
467
  - With `--ts_proto_opt=useNumericEnumForJson=true`, the JSON converter (`toJSON`) will encode enum values as int, rather than a string literal.
@@ -502,6 +502,11 @@ Generated code will be placed in the Gradle build directory.
502
502
 
503
503
  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
504
 
505
+ - With `--ts_proto_opt=outputExtensions=true`, the generated code will include proto2 extensions
506
+
507
+ Extension encode/decode methods are compliant with the `outputEncodeMethods` option, and if `unknownFields=true`,
508
+ the `setExtension` and `getExtension` methods will be created for extendable messages, also compliant with `outputEncodeMethods` (setExtension = encode, getExtension = decode).
509
+
505
510
  ### NestJS Support
506
511
 
507
512
  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/main.js CHANGED
@@ -92,14 +92,26 @@ function generateFile(ctx, fileDesc) {
92
92
  if (options.outputTypeRegistry) {
93
93
  staticMembers.push((0, ts_poet_1.code) `$type: '${fullTypeName}' as const`);
94
94
  }
95
+ if (options.outputExtensions) {
96
+ for (const extension of message.extension) {
97
+ const { name, type, extensionInfo } = generateExtension(ctx, message, extension);
98
+ staticMembers.push((0, ts_poet_1.code) `${name}: <${ctx.utils.Extension}<${type}>> ${extensionInfo}`);
99
+ }
100
+ }
95
101
  if (options.outputEncodeMethods) {
96
102
  if (options.outputEncodeMethods === true ||
97
103
  options.outputEncodeMethods === "encode-only" ||
98
104
  options.outputEncodeMethods === "encode-no-creation") {
99
105
  staticMembers.push(generateEncode(ctx, fullName, message));
106
+ if (options.outputExtensions && options.unknownFields && message.extensionRange.length) {
107
+ staticMembers.push(generateSetExtension(ctx, fullName));
108
+ }
100
109
  }
101
110
  if (options.outputEncodeMethods === true || options.outputEncodeMethods === "decode-only") {
102
111
  staticMembers.push(generateDecode(ctx, fullName, message));
112
+ if (options.outputExtensions && options.unknownFields && message.extensionRange.length) {
113
+ staticMembers.push(generateGetExtension(ctx, fullName));
114
+ }
103
115
  }
104
116
  }
105
117
  if (options.useAsyncIterable) {
@@ -144,6 +156,12 @@ function generateFile(ctx, fileDesc) {
144
156
  }
145
157
  }, options);
146
158
  }
159
+ if (options.outputExtensions) {
160
+ for (const extension of fileDesc.extension) {
161
+ const { name, type, extensionInfo } = generateExtension(ctx, undefined, extension);
162
+ chunks.push((0, ts_poet_1.code) `export const ${name}: ${ctx.utils.Extension}<${type}> = ${extensionInfo};`);
163
+ }
164
+ }
147
165
  if (options.nestJs) {
148
166
  if (fileDesc.messageType.find((message) => message.field.find(types_1.isStructType))) {
149
167
  chunks.push(makeProtobufStructWrapper(options));
@@ -256,6 +274,7 @@ function makeUtils(options) {
256
274
  ...makeComparisonUtils(),
257
275
  ...makeNiceGrpcServerStreamingMethodResult(),
258
276
  ...makeGrpcWebErrorClass(bytes),
277
+ ...makeExtensionClass(options),
259
278
  };
260
279
  }
261
280
  exports.makeUtils = makeUtils;
@@ -550,6 +569,22 @@ function makeGrpcWebErrorClass(bytes) {
550
569
  `);
551
570
  return { GrpcWebError };
552
571
  }
572
+ function makeExtensionClass(options) {
573
+ const Reader = (0, utils_1.impFile)(options, "Reader@protobufjs/minimal");
574
+ const Writer = (0, utils_1.impFile)(options, "Writer@protobufjs/minimal");
575
+ const Extension = (0, ts_poet_1.conditionalOutput)("Extension", (0, ts_poet_1.code) `
576
+ export interface Extension <T> {
577
+ number: number;
578
+ tag: number;
579
+ singularTag?: number;
580
+ encode?: (message: T) => Uint8Array[];
581
+ decode?: (tag: number, input: Uint8Array[]) => T;
582
+ repeated: boolean;
583
+ packed: boolean;
584
+ }
585
+ `);
586
+ return { Extension };
587
+ }
553
588
  // Create the interface with properties
554
589
  function generateInterfaceDeclaration(ctx, fullName, messageDesc, sourceInfo, fullTypeName) {
555
590
  var _a;
@@ -661,6 +696,71 @@ function generateBaseInstanceFactory(ctx, fullName, messageDesc, fullTypeName) {
661
696
  }
662
697
  `;
663
698
  }
699
+ function getDecodeReadSnippet(ctx, field) {
700
+ const { options, utils } = ctx;
701
+ let readSnippet;
702
+ if ((0, types_1.isPrimitive)(field)) {
703
+ readSnippet = (0, ts_poet_1.code) `reader.${(0, types_1.toReaderCall)(field)}()`;
704
+ if ((0, types_1.isBytes)(field)) {
705
+ if (options.env === options_1.EnvOption.NODE) {
706
+ readSnippet = (0, ts_poet_1.code) `${readSnippet} as Buffer`;
707
+ }
708
+ }
709
+ else if ((0, types_1.basicLongWireType)(field.type) !== undefined) {
710
+ if (options.forceLong === options_1.LongOption.LONG) {
711
+ readSnippet = (0, ts_poet_1.code) `${readSnippet} as Long`;
712
+ }
713
+ else if (options.forceLong === options_1.LongOption.STRING) {
714
+ readSnippet = (0, ts_poet_1.code) `${utils.longToString}(${readSnippet} as Long)`;
715
+ }
716
+ else if (options.forceLong === options_1.LongOption.BIGINT) {
717
+ readSnippet = (0, ts_poet_1.code) `${utils.longToBigint}(${readSnippet} as Long)`;
718
+ }
719
+ else {
720
+ readSnippet = (0, ts_poet_1.code) `${utils.longToNumber}(${readSnippet} as Long)`;
721
+ }
722
+ }
723
+ else if ((0, types_1.isEnum)(field)) {
724
+ if (options.stringEnums) {
725
+ const fromJson = (0, types_1.getEnumMethod)(ctx, field.typeName, "FromJSON");
726
+ readSnippet = (0, ts_poet_1.code) `${fromJson}(${readSnippet})`;
727
+ }
728
+ else {
729
+ readSnippet = (0, ts_poet_1.code) `${readSnippet} as any`;
730
+ }
731
+ }
732
+ }
733
+ else if ((0, types_1.isValueType)(ctx, field)) {
734
+ const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
735
+ const unwrap = (decodedValue) => {
736
+ if ((0, types_1.isListValueType)(field) || (0, types_1.isStructType)(field) || (0, types_1.isAnyValueType)(field) || (0, types_1.isFieldMaskType)(field)) {
737
+ return (0, ts_poet_1.code) `${type}.unwrap(${decodedValue})`;
738
+ }
739
+ return (0, ts_poet_1.code) `${decodedValue}.value`;
740
+ };
741
+ const decoder = (0, ts_poet_1.code) `${type}.decode(reader, reader.uint32())`;
742
+ readSnippet = (0, ts_poet_1.code) `${unwrap(decoder)}`;
743
+ }
744
+ else if ((0, types_1.isTimestamp)(field) && (options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) {
745
+ const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
746
+ readSnippet = (0, ts_poet_1.code) `${utils.fromTimestamp}(${type}.decode(reader, reader.uint32()))`;
747
+ }
748
+ else if ((0, types_1.isObjectId)(field) && options.useMongoObjectId) {
749
+ const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
750
+ readSnippet = (0, ts_poet_1.code) `${utils.fromProtoObjectId}(${type}.decode(reader, reader.uint32()))`;
751
+ }
752
+ else if ((0, types_1.isMessage)(field)) {
753
+ const type = (0, types_1.basicTypeName)(ctx, field);
754
+ if (field.type == ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_GROUP)
755
+ readSnippet = (0, ts_poet_1.code) `${type}.decode(reader)`;
756
+ else
757
+ readSnippet = (0, ts_poet_1.code) `${type}.decode(reader, reader.uint32())`;
758
+ }
759
+ else {
760
+ throw new Error(`Unhandled field ${field}`);
761
+ }
762
+ return readSnippet;
763
+ }
664
764
  /** Creates a function to decode a message by loop overing the tags. */
665
765
  function generateDecode(ctx, fullName, messageDesc) {
666
766
  const { options, utils, typeMap } = ctx;
@@ -696,67 +796,7 @@ function generateDecode(ctx, fullName, messageDesc) {
696
796
  break;
697
797
  `;
698
798
  // 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
- }
799
+ const readSnippet = getDecodeReadSnippet(ctx, field);
760
800
  // and then use the snippet to handle repeated fields if necessary
761
801
  const initializerNecessary = !options.initializeFieldsAsUndefined && (0, types_1.isOptionalProperty)(field, messageDesc.options, options);
762
802
  if ((0, types_1.isRepeated)(field)) {
@@ -1099,6 +1139,226 @@ function generateEncode(ctx, fullName, messageDesc) {
1099
1139
  chunks.push((0, ts_poet_1.code) `}`);
1100
1140
  return (0, ts_poet_1.joinCode)(chunks, { on: "\n" });
1101
1141
  }
1142
+ function generateSetExtension(ctx, fullName) {
1143
+ return (0, ts_poet_1.code) `
1144
+ setExtension <T> (message: ${fullName}, extension: ${ctx.utils.Extension}<T>, value: T): void {
1145
+ const encoded = extension.encode!(value);
1146
+
1147
+ if (message._unknownFields !== undefined){
1148
+ delete message._unknownFields[extension.tag];
1149
+
1150
+ if (extension.singularTag !== undefined) {
1151
+ delete message._unknownFields[extension.singularTag];
1152
+ }
1153
+ }
1154
+
1155
+ if (encoded.length !== 0) {
1156
+ if (message._unknownFields === undefined) {
1157
+ message._unknownFields = {};
1158
+ }
1159
+
1160
+ message._unknownFields[extension.tag] = encoded;
1161
+ }
1162
+ }
1163
+ `;
1164
+ }
1165
+ function generateGetExtension(ctx, fullName) {
1166
+ return (0, ts_poet_1.code) `
1167
+ getExtension <T> (message: ${fullName}, extension: ${ctx.utils.Extension}<T>): T | undefined {
1168
+ let results: T | undefined = undefined;
1169
+
1170
+ if (message._unknownFields === undefined) {
1171
+ return undefined;
1172
+ }
1173
+
1174
+ let list = message._unknownFields[extension.tag];
1175
+
1176
+ if (list !== undefined) {
1177
+ results = extension.decode!(extension.tag, list);
1178
+ }
1179
+
1180
+ if (extension.singularTag === undefined) {
1181
+ return results;
1182
+ }
1183
+
1184
+ list = message._unknownFields[extension.singularTag];
1185
+
1186
+ if (list !== undefined) {
1187
+ const results2 = extension.decode!(extension.singularTag, list);
1188
+
1189
+ if (results !== undefined && (results as any).length !== 0) {
1190
+ results = (results as any).concat(results2);
1191
+ } else {
1192
+ results = results2;
1193
+ }
1194
+ }
1195
+
1196
+ return results;
1197
+ }
1198
+ `;
1199
+ }
1200
+ function generateExtension(ctx, message, extension) {
1201
+ var _a;
1202
+ const type = (0, types_1.toTypeName)(ctx, message, extension);
1203
+ const packedTag = (0, types_1.isRepeated)(extension) && (0, types_1.packedType)(extension.type) !== undefined ? ((extension.number << 3) | 2) >>> 0 : undefined;
1204
+ const singularTag = ((extension.number << 3) | (0, types_1.basicWireType)(extension.type)) >>> 0;
1205
+ const tag = packedTag !== null && packedTag !== void 0 ? packedTag : singularTag;
1206
+ const chunks = [];
1207
+ chunks.push((0, ts_poet_1.code) `{`);
1208
+ chunks.push((0, ts_poet_1.code) `number: ${extension.number},`);
1209
+ chunks.push((0, ts_poet_1.code) `tag: ${tag},`);
1210
+ if (packedTag !== undefined)
1211
+ chunks.push((0, ts_poet_1.code) `singularTag: ${singularTag},`);
1212
+ chunks.push((0, ts_poet_1.code) `repeated: ${extension.label == ts_proto_descriptors_1.FieldDescriptorProto_Label.LABEL_REPEATED},`);
1213
+ chunks.push((0, ts_poet_1.code) `packed: ${((_a = extension.options) === null || _a === void 0 ? void 0 : _a.packed) ? true : false},`);
1214
+ const Reader = (0, utils_1.impFile)(ctx.options, "Reader@protobufjs/minimal");
1215
+ const Writer = (0, utils_1.impFile)(ctx.options, "Writer@protobufjs/minimal");
1216
+ if (ctx.options.outputEncodeMethods === true ||
1217
+ ctx.options.outputEncodeMethods === "encode-only" ||
1218
+ ctx.options.outputEncodeMethods === "encode-no-creation") {
1219
+ chunks.push((0, ts_poet_1.code) `
1220
+ encode: (value: ${type}): Uint8Array[] => {
1221
+ const encoded: Uint8Array[] = [];
1222
+ `);
1223
+ function getEncodeSnippet(ctx, field) {
1224
+ const { options, utils } = ctx;
1225
+ if ((0, types_1.isEnum)(field) && options.stringEnums) {
1226
+ const toNumber = (0, types_1.getEnumMethod)(ctx, field.typeName, "ToNumber");
1227
+ return (place) => (0, ts_poet_1.code) `writer.${(0, types_1.toReaderCall)(field)}(${toNumber}(${place}))`;
1228
+ }
1229
+ else if ((0, types_1.isLong)(field) && options.forceLong === options_1.LongOption.BIGINT) {
1230
+ return (place) => (0, ts_poet_1.code) `writer.${(0, types_1.toReaderCall)(field)}(${place}.toString())`;
1231
+ }
1232
+ else if ((0, types_1.isScalar)(field) || (0, types_1.isEnum)(field)) {
1233
+ return (place) => (0, ts_poet_1.code) `writer.${(0, types_1.toReaderCall)(field)}(${place})`;
1234
+ }
1235
+ else if ((0, types_1.isObjectId)(field) && options.useMongoObjectId) {
1236
+ const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
1237
+ return (place) => (0, ts_poet_1.code) `${type}.encode(${utils.toProtoObjectId}(${place}), writer.fork()).ldelim()`;
1238
+ }
1239
+ else if ((0, types_1.isTimestamp)(field) && (options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) {
1240
+ const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
1241
+ return (place) => (0, ts_poet_1.code) `${type}.encode(${utils.toTimestamp}(${place}), writer.fork()).ldelim()`;
1242
+ }
1243
+ else if ((0, types_1.isValueType)(ctx, field)) {
1244
+ const maybeTypeField = options.outputTypeRegistry ? `$type: '${field.typeName.slice(1)}',` : "";
1245
+ const type = (0, types_1.basicTypeName)(ctx, field, { keepValueType: true });
1246
+ const wrappedValue = (place) => {
1247
+ if ((0, types_1.isAnyValueType)(field) || (0, types_1.isListValueType)(field) || (0, types_1.isStructType)(field) || (0, types_1.isFieldMaskType)(field)) {
1248
+ return (0, ts_poet_1.code) `${type}.wrap(${place})`;
1249
+ }
1250
+ return (0, ts_poet_1.code) `{${maybeTypeField} value: ${place}!}`;
1251
+ };
1252
+ return (place) => (0, ts_poet_1.code) `${type}.encode(${wrappedValue(place)}, writer.fork()).ldelim()`;
1253
+ }
1254
+ else if ((0, types_1.isMessage)(field)) {
1255
+ const type = (0, types_1.basicTypeName)(ctx, field);
1256
+ if (field.type == ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_GROUP) {
1257
+ const endTag = ((field.number << 3) | 4) >>> 0;
1258
+ return (place) => (0, ts_poet_1.code) `${type}.encode(${place}, writer).uint32(${endTag})`;
1259
+ }
1260
+ return (place) => (0, ts_poet_1.code) `${type}.encode(${place}, writer.fork()).ldelim()`;
1261
+ }
1262
+ else {
1263
+ throw new Error(`Unhandled field ${field}`);
1264
+ }
1265
+ }
1266
+ const writeSnippet = getEncodeSnippet(ctx, extension);
1267
+ if ((0, types_1.isRepeated)(extension)) {
1268
+ if (packedTag === undefined) {
1269
+ chunks.push((0, ts_poet_1.code) `
1270
+ for (const v of value) {
1271
+ const writer = ${Writer}.create();
1272
+ ${writeSnippet("v")};
1273
+ encoded.push(writer.finish());
1274
+ }
1275
+ `);
1276
+ }
1277
+ else {
1278
+ const rhs = (x) => (0, types_1.isLong)(extension) && ctx.options.forceLong === options_1.LongOption.BIGINT ? `${x}.toString()` : x;
1279
+ chunks.push((0, ts_poet_1.code) `
1280
+ const writer = ${Writer}.create();
1281
+ writer.fork();
1282
+ for (const v of value) {
1283
+ ${writeSnippet(rhs("v"))};
1284
+ }
1285
+ writer.ldelim();
1286
+ encoded.push(writer.finish());
1287
+ `);
1288
+ }
1289
+ }
1290
+ else if ((0, types_1.isScalar)(extension) || (0, types_1.isEnum)(extension)) {
1291
+ chunks.push((0, ts_poet_1.code) `
1292
+ if (${(0, types_1.notDefaultCheck)(ctx, extension, message === null || message === void 0 ? void 0 : message.options, "value")}) {
1293
+ const writer = ${Writer}.create();
1294
+ ${writeSnippet("value")};
1295
+ encoded.push(writer.finish());
1296
+ }
1297
+ `);
1298
+ }
1299
+ else {
1300
+ chunks.push((0, ts_poet_1.code) `
1301
+ const writer = ${Writer}.create();
1302
+ ${writeSnippet("value")};
1303
+ encoded.push(writer.finish());
1304
+ `);
1305
+ }
1306
+ chunks.push((0, ts_poet_1.code) `
1307
+ return encoded;
1308
+ },
1309
+ `);
1310
+ }
1311
+ if (ctx.options.outputEncodeMethods === true || ctx.options.outputEncodeMethods === "decode-only") {
1312
+ chunks.push((0, ts_poet_1.code) `decode: (tag: number, input: Uint8Array[]): ${type} => {`);
1313
+ // get a generic 'reader.doSomething' bit that is specific to the basic type
1314
+ const readSnippet = getDecodeReadSnippet(ctx, extension);
1315
+ if ((0, types_1.isRepeated)(extension)) {
1316
+ chunks.push((0, ts_poet_1.code) `const values: ${type} = [];`);
1317
+ // start loop over all buffers
1318
+ chunks.push((0, ts_poet_1.code) `
1319
+ for (var buffer of input) {
1320
+ const reader = ${Reader}.create(buffer);
1321
+ `);
1322
+ if ((0, types_1.packedType)(extension.type) === undefined) {
1323
+ chunks.push((0, ts_poet_1.code) `
1324
+ values.push(${readSnippet});
1325
+ `);
1326
+ }
1327
+ else {
1328
+ chunks.push((0, ts_poet_1.code) `
1329
+ if(tag == ${packedTag}){
1330
+ const end2 = reader.uint32() + reader.pos;
1331
+ while (reader.pos < end2) {
1332
+ values.push(${readSnippet});
1333
+ }
1334
+ }else{
1335
+ values.push(${readSnippet});
1336
+ }
1337
+ `);
1338
+ }
1339
+ chunks.push((0, ts_poet_1.code) `
1340
+ }
1341
+
1342
+ return values;
1343
+ },
1344
+ `);
1345
+ }
1346
+ else {
1347
+ // pick the last entry, since it overrides all previous entries if not repeated
1348
+ chunks.push((0, ts_poet_1.code) `
1349
+ const reader = ${Reader}.create(input[input.length -1]);
1350
+ return ${readSnippet};
1351
+ },
1352
+ `);
1353
+ }
1354
+ }
1355
+ chunks.push((0, ts_poet_1.code) `}`);
1356
+ return {
1357
+ name: (0, case_1.maybeSnakeToCamel)(extension.name, ctx.options),
1358
+ type,
1359
+ extensionInfo: (0, ts_poet_1.joinCode)(chunks, { on: "\n" }),
1360
+ };
1361
+ }
1102
1362
  /**
1103
1363
  * Creates a function to decode a message from JSON.
1104
1364
  *
package/build/options.js CHANGED
@@ -78,6 +78,7 @@ function defaultOptions() {
78
78
  useMapType: false,
79
79
  useReadonlyTypes: false,
80
80
  useSnakeTypeName: true,
81
+ outputExtensions: false,
81
82
  M: {},
82
83
  };
83
84
  }
package/build/types.js CHANGED
@@ -578,7 +578,7 @@ exports.getEnumMethod = getEnumMethod;
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "1.145.0",
3
+ "version": "1.146.0",
4
4
  "description": "",
5
5
  "main": "build/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",