ts-proto 1.127.0 → 1.129.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/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [1.129.0](https://github.com/stephenh/ts-proto/compare/v1.128.0...v1.129.0) (2022-10-16)
2
+
3
+
4
+ ### Features
5
+
6
+ * support `useMapType` option ([#686](https://github.com/stephenh/ts-proto/issues/686)) ([f2e80ab](https://github.com/stephenh/ts-proto/commit/f2e80ab3ecc3a438ecbd88b2170b8119ebadfcd3))
7
+
8
+ # [1.128.0](https://github.com/stephenh/ts-proto/compare/v1.127.0...v1.128.0) (2022-10-13)
9
+
10
+
11
+ ### Features
12
+
13
+ * added nestJsTimestampTypeWrapper ([#567](https://github.com/stephenh/ts-proto/issues/567)) ([59d451e](https://github.com/stephenh/ts-proto/commit/59d451e2857856ff54a3afe03ae115a1824df66f))
14
+
1
15
  # [1.127.0](https://github.com/stephenh/ts-proto/compare/v1.126.1...v1.127.0) (2022-10-12)
2
16
 
3
17
 
package/README.markdown CHANGED
@@ -458,6 +458,10 @@ Generated code will be placed in the Gradle build directory.
458
458
  - **Note**: Uses are accummulated, so multiple values are expected in the form of `--ts_proto_opt=M... --ts_proto_opt=M...` (one `ts_proto_opt` per mapping).
459
459
  - **Note**: Proto files that match mapped imports **will not be generated**.
460
460
 
461
+ - With `--ts_proto_opt=useMapType=true`, the generated code for protobuf `map<key_type, value_type>` will become `Map<key_type, value_type>` that uses JavaScript Map type.
462
+
463
+ The default behavior is `useMapType=false`, which makes it generate the code for protobuf `map<key_type, value_type` with the key-value pair like `{[key: key_type]: value_type}`.
464
+
461
465
  ### NestJS Support
462
466
 
463
467
  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
@@ -67,6 +67,10 @@ function generateFile(ctx, fileDesc) {
67
67
  if (options.nestJs) {
68
68
  const prefix = (0, case_1.camelToSnake)(fileDesc.package.replace(/\./g, "_"));
69
69
  chunks.push((0, ts_poet_1.code) `export const ${prefix}_PACKAGE_NAME = '${fileDesc.package}';`);
70
+ if (options.useDate === options_1.DateOption.DATE &&
71
+ fileDesc.messageType.find((message) => message.field.find((field) => field.typeName === ".google.protobuf.Timestamp"))) {
72
+ chunks.push(makeProtobufTimestampWrapper());
73
+ }
70
74
  }
71
75
  if (options.outputEncodeMethods || options.outputJsonMethods || options.outputTypeRegistry) {
72
76
  // then add the encoder/decoder/base instance
@@ -225,6 +229,21 @@ function makeUtils(options) {
225
229
  };
226
230
  }
227
231
  exports.makeUtils = makeUtils;
232
+ function makeProtobufTimestampWrapper() {
233
+ const wrappers = (0, ts_poet_1.imp)("wrappers@protobufjs");
234
+ return (0, ts_poet_1.code) `
235
+ ${wrappers}['.google.protobuf.Timestamp'] = {
236
+ fromObject(value: Date) {
237
+ return {
238
+ seconds: value.getTime() / 1000,
239
+ nanos: (value.getTime() % 1000) * 1e6,
240
+ };
241
+ },
242
+ toObject(message: { seconds: number; nanos: number }) {
243
+ return new Date(message.seconds * 1000 + message.nanos / 1e6);
244
+ },
245
+ } as any;`;
246
+ }
228
247
  function makeLongUtils(options, bytes) {
229
248
  // Regardless of which `forceLong` config option we're using, we always use
230
249
  // the `long` library to either represent or at least sanity-check 64-bit values
@@ -570,7 +589,9 @@ function generateBaseInstanceFactory(ctx, fullName, messageDesc, fullTypeName) {
570
589
  const val = (0, types_1.isWithinOneOf)(field)
571
590
  ? "undefined"
572
591
  : (0, types_1.isMapType)(ctx, messageDesc, field)
573
- ? "{}"
592
+ ? ctx.options.useMapType
593
+ ? "new Map()"
594
+ : "{}"
574
595
  : (0, types_1.isRepeated)(field)
575
596
  ? "[]"
576
597
  : (0, types_1.defaultValue)(ctx, field);
@@ -679,10 +700,13 @@ function generateDecode(ctx, fullName, messageDesc) {
679
700
  if ((0, types_1.isMapType)(ctx, messageDesc, field)) {
680
701
  // We need a unique const within the `cast` statement
681
702
  const varName = `entry${field.number}`;
703
+ const valueSetterSnippet = ctx.options.useMapType
704
+ ? `message.${fieldName}${maybeNonNullAssertion}.set(${varName}.key, ${varName}.value)`
705
+ : `message.${fieldName}${maybeNonNullAssertion}[${varName}.key] = ${varName}.value`;
682
706
  chunks.push((0, ts_poet_1.code) `
683
707
  const ${varName} = ${readSnippet};
684
708
  if (${varName}.value !== undefined) {
685
- message.${fieldName}${maybeNonNullAssertion}[${varName}.key] = ${varName}.value;
709
+ ${valueSetterSnippet};
686
710
  }
687
711
  `);
688
712
  }
@@ -803,11 +827,20 @@ function generateEncode(ctx, fullName, messageDesc) {
803
827
  `
804
828
  : writeSnippet(`{ ${maybeTypeField} key: key as any, value }`);
805
829
  const optionalAlternative = isOptional ? " || {}" : "";
806
- chunks.push((0, ts_poet_1.code) `
807
- Object.entries(message.${fieldName}${optionalAlternative}).forEach(([key, value]) => {
808
- ${entryWriteSnippet}
809
- });
810
- `);
830
+ if (ctx.options.useMapType) {
831
+ chunks.push((0, ts_poet_1.code) `
832
+ message.${fieldName}${optionalAlternative}.forEach((value, key) => {
833
+ ${entryWriteSnippet}
834
+ });
835
+ `);
836
+ }
837
+ else {
838
+ chunks.push((0, ts_poet_1.code) `
839
+ Object.entries(message.${fieldName}${optionalAlternative}).forEach(([key, value]) => {
840
+ ${entryWriteSnippet}
841
+ });
842
+ `);
843
+ }
811
844
  }
812
845
  else if ((0, types_1.packedType)(field.type) === undefined) {
813
846
  const listWriteSnippet = (0, ts_poet_1.code) `
@@ -1080,14 +1113,26 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
1080
1113
  if ((0, types_1.isMapType)(ctx, messageDesc, field)) {
1081
1114
  const fieldType = (0, types_1.toTypeName)(ctx, messageDesc, field);
1082
1115
  const i = maybeCastToNumber(ctx, messageDesc, field, "key");
1083
- chunks.push((0, ts_poet_1.code) `
1084
- ${fieldName}: ${ctx.utils.isObject}(${jsonProperty})
1085
- ? Object.entries(${jsonProperty}).reduce<${fieldType}>((acc, [key, value]) => {
1086
- acc[${i}] = ${readSnippet("value")};
1087
- return acc;
1088
- }, {})
1089
- : {},
1090
- `);
1116
+ if (ctx.options.useMapType) {
1117
+ chunks.push((0, ts_poet_1.code) `
1118
+ ${fieldName}: ${ctx.utils.isObject}(${jsonProperty})
1119
+ ? Object.entries(${jsonProperty}).reduce<${fieldType}>((acc, [key, value]) => {
1120
+ acc.set(${i}, ${readSnippet("value")});
1121
+ return acc;
1122
+ }, new Map())
1123
+ : new Map(),
1124
+ `);
1125
+ }
1126
+ else {
1127
+ chunks.push((0, ts_poet_1.code) `
1128
+ ${fieldName}: ${ctx.utils.isObject}(${jsonProperty})
1129
+ ? Object.entries(${jsonProperty}).reduce<${fieldType}>((acc, [key, value]) => {
1130
+ acc[${i}] = ${readSnippet("value")};
1131
+ return acc;
1132
+ }, {})
1133
+ : {},
1134
+ `);
1135
+ }
1091
1136
  }
1092
1137
  else {
1093
1138
  const readValueSnippet = readSnippet("e");
@@ -1267,14 +1312,26 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
1267
1312
  };
1268
1313
  if ((0, types_1.isMapType)(ctx, messageDesc, field)) {
1269
1314
  // Maps might need their values transformed, i.e. bytes --> base64
1270
- chunks.push((0, ts_poet_1.code) `
1271
- ${jsonProperty} = {};
1272
- if (message.${fieldName}) {
1273
- Object.entries(message.${fieldName}).forEach(([k, v]) => {
1274
- ${jsonProperty}[k] = ${readSnippet("v")};
1275
- });
1276
- }
1277
- `);
1315
+ if (ctx.options.useMapType) {
1316
+ chunks.push((0, ts_poet_1.code) `
1317
+ ${jsonProperty} = {};
1318
+ if (message.${fieldName}) {
1319
+ message.${fieldName}.forEach((v, k) => {
1320
+ ${jsonProperty}[k] = ${readSnippet("v")};
1321
+ });
1322
+ }
1323
+ `);
1324
+ }
1325
+ else {
1326
+ chunks.push((0, ts_poet_1.code) `
1327
+ ${jsonProperty} = {};
1328
+ if (message.${fieldName}) {
1329
+ Object.entries(message.${fieldName}).forEach(([k, v]) => {
1330
+ ${jsonProperty}[k] = ${readSnippet("v")};
1331
+ });
1332
+ }
1333
+ `);
1334
+ }
1278
1335
  }
1279
1336
  else if ((0, types_1.isRepeated)(field)) {
1280
1337
  // Arrays might need their elements transformed
@@ -1389,14 +1446,29 @@ function generateFromPartial(ctx, fullName, messageDesc) {
1389
1446
  if ((0, types_1.isMapType)(ctx, messageDesc, field)) {
1390
1447
  const fieldType = (0, types_1.toTypeName)(ctx, messageDesc, field);
1391
1448
  const i = maybeCastToNumber(ctx, messageDesc, field, "key");
1392
- chunks.push((0, ts_poet_1.code) `
1393
- message.${fieldName} = Object.entries(object.${fieldName} ?? {}).reduce<${fieldType}>((acc, [key, value]) => {
1394
- if (value !== undefined) {
1395
- acc[${i}] = ${readSnippet("value")};
1396
- }
1397
- return acc;
1398
- }, {});
1399
- `);
1449
+ if (ctx.options.useMapType) {
1450
+ chunks.push((0, ts_poet_1.code) `
1451
+ message.${fieldName} = (() => {
1452
+ const m = new Map();
1453
+ (object.${fieldName} as ${fieldType} ?? new Map()).forEach((value, key) => {
1454
+ if (value !== undefined) {
1455
+ m.set(${i}, ${readSnippet("value")});
1456
+ }
1457
+ });
1458
+ return m;
1459
+ })();
1460
+ `);
1461
+ }
1462
+ else {
1463
+ chunks.push((0, ts_poet_1.code) `
1464
+ message.${fieldName} = Object.entries(object.${fieldName} ?? {}).reduce<${fieldType}>((acc, [key, value]) => {
1465
+ if (value !== undefined) {
1466
+ acc[${i}] = ${readSnippet("value")};
1467
+ }
1468
+ return acc;
1469
+ }, {});
1470
+ `);
1471
+ }
1400
1472
  }
1401
1473
  else {
1402
1474
  chunks.push((0, ts_poet_1.code) `
package/build/options.js CHANGED
@@ -72,6 +72,7 @@ function defaultOptions() {
72
72
  useJsonWireFormat: false,
73
73
  useNumericEnumForJson: false,
74
74
  initializeFieldsAsUndefined: true,
75
+ useMapType: false,
75
76
  M: {},
76
77
  };
77
78
  }
package/build/types.js CHANGED
@@ -557,6 +557,9 @@ function toTypeName(ctx, messageDesc, field) {
557
557
  const mapType = detectMapType(ctx, messageDesc, field);
558
558
  if (mapType) {
559
559
  const { keyType, valueType } = mapType;
560
+ if (ctx.options.useMapType) {
561
+ return (0, ts_poet_1.code) `Map<${keyType}, ${valueType}>`;
562
+ }
560
563
  return (0, ts_poet_1.code) `{ [key: ${keyType} ]: ${valueType} }`;
561
564
  }
562
565
  return (0, ts_poet_1.code) `${type}[]`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "1.127.0",
3
+ "version": "1.129.0",
4
4
  "description": "",
5
5
  "main": "build/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",