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 +14 -0
- package/README.markdown +4 -0
- package/build/main.js +103 -31
- package/build/options.js +1 -0
- package/build/types.js +3 -0
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
807
|
-
|
|
808
|
-
${
|
|
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
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
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
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
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
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
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
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}[]`;
|