ts-proto 1.95.1 → 1.97.1
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 +28 -0
- package/README.markdown +7 -1
- package/build/enums.js +17 -4
- package/build/main.js +137 -63
- package/build/options.js +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## [1.97.1](https://github.com/stephenh/ts-proto/compare/v1.97.0...v1.97.1) (2022-01-05)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* oneof=union breaks wrapper types [#458](https://github.com/stephenh/ts-proto/issues/458) ([#462](https://github.com/stephenh/ts-proto/issues/462)) ([dd16992](https://github.com/stephenh/ts-proto/commit/dd16992a409f24e88e3a142830cd0745f50dbd10))
|
|
7
|
+
|
|
8
|
+
# [1.97.0](https://github.com/stephenh/ts-proto/compare/v1.96.1...v1.97.0) (2021-12-30)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add an option to disable Exact types ([#456](https://github.com/stephenh/ts-proto/issues/456)) ([9c53d7e](https://github.com/stephenh/ts-proto/commit/9c53d7efb0252c7ea0af85a5d161ff94bcd69760))
|
|
14
|
+
|
|
15
|
+
## [1.96.1](https://github.com/stephenh/ts-proto/compare/v1.96.0...v1.96.1) (2021-12-28)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Performance Improvements
|
|
19
|
+
|
|
20
|
+
* optimize object creation in `decode`, `fromJSON` and `fromPartial` ([#457](https://github.com/stephenh/ts-proto/issues/457)) ([70832d3](https://github.com/stephenh/ts-proto/commit/70832d33bae82ecb3c5f87845d14e992a13437e4))
|
|
21
|
+
|
|
22
|
+
# [1.96.0](https://github.com/stephenh/ts-proto/compare/v1.95.1...v1.96.0) (2021-12-24)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* `enumsAsLiterals` option ([#450](https://github.com/stephenh/ts-proto/issues/450)) ([fcaade2](https://github.com/stephenh/ts-proto/commit/fcaade2855ae28ea3553a365556ccb92a9644d70))
|
|
28
|
+
|
|
1
29
|
## [1.95.1](https://github.com/stephenh/ts-proto/compare/v1.95.0...v1.95.1) (2021-12-23)
|
|
2
30
|
|
|
3
31
|
|
package/README.markdown
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
> `ts-proto` transforms your `.proto` files into strongly-typed, idiomatic TypeScript files!
|
|
7
7
|
|
|
8
|
-
(Note, if you're a new user of ts-proto and using a modern TS setup with `esModuleInterop`, you need to also pass that as a `ts_proto_opt`.)
|
|
8
|
+
(Note, if you're a new user of ts-proto and using a modern TS setup with `esModuleInterop`, or want to use ts-proto in ESM / snowpack / vite, you need to also pass that as a `ts_proto_opt`.)
|
|
9
9
|
|
|
10
10
|
## Table of contents
|
|
11
11
|
|
|
@@ -348,6 +348,12 @@ Generated code will be placed in the Gradle build directory.
|
|
|
348
348
|
|
|
349
349
|
- With `--ts_proto_opt=fileSuffix=<SUFFIX>`, ts-proto will emit generated files using the specified suffix. A `helloworld.proto` file with `fileSuffix=.pb` would be generated as `helloworld.pb.ts`. This is common behavior in other protoc plugins and provides a way to quickly glob all the generated files.
|
|
350
350
|
|
|
351
|
+
- With `--ts_proto_opt=enumsAsLiterals=true`, the generated enum types will be enum-ish object with `as const`.
|
|
352
|
+
|
|
353
|
+
- With `--ts_proto_opt=useExactTypes=false`, the generated `fromPartial` method will not use Exact types.
|
|
354
|
+
|
|
355
|
+
The default behavior is `useExactTypes=true`, which makes `fromPartial` use Exact type for its argument to make TypeScript reject any unknown properties.
|
|
356
|
+
|
|
351
357
|
### Only Types
|
|
352
358
|
|
|
353
359
|
If you're looking for `ts-proto` to generate only types for your Protobuf types then passing all three of `outputEncodeMethods`, `outputJsonMethods`, and `outputClientImpl` as `false` is probably what you want, i.e.:
|
package/build/enums.js
CHANGED
|
@@ -13,17 +13,30 @@ function generateEnum(ctx, fullName, enumDesc, sourceInfo) {
|
|
|
13
13
|
const { options } = ctx;
|
|
14
14
|
const chunks = [];
|
|
15
15
|
utils_1.maybeAddComment(sourceInfo, chunks, (_a = enumDesc.options) === null || _a === void 0 ? void 0 : _a.deprecated);
|
|
16
|
-
|
|
16
|
+
if (options.enumsAsLiterals) {
|
|
17
|
+
chunks.push(ts_poet_1.code `export const ${ts_poet_1.def(fullName)} = {`);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
chunks.push(ts_poet_1.code `export ${options.constEnums ? 'const ' : ''}enum ${ts_poet_1.def(fullName)} {`);
|
|
21
|
+
}
|
|
22
|
+
const delimiter = options.enumsAsLiterals ? ':' : '=';
|
|
17
23
|
enumDesc.value.forEach((valueDesc, index) => {
|
|
18
24
|
var _a;
|
|
19
25
|
const info = sourceInfo.lookup(sourceInfo_1.Fields.enum.value, index);
|
|
20
26
|
utils_1.maybeAddComment(info, chunks, (_a = valueDesc.options) === null || _a === void 0 ? void 0 : _a.deprecated, `${valueDesc.name} - `);
|
|
21
|
-
chunks.push(ts_poet_1.code `${valueDesc.name}
|
|
27
|
+
chunks.push(ts_poet_1.code `${valueDesc.name} ${delimiter} ${options.stringEnums ? `"${valueDesc.name}"` : valueDesc.number.toString()},`);
|
|
22
28
|
});
|
|
23
29
|
if (options.unrecognizedEnum)
|
|
24
30
|
chunks.push(ts_poet_1.code `
|
|
25
|
-
${UNRECOGNIZED_ENUM_NAME}
|
|
26
|
-
|
|
31
|
+
${UNRECOGNIZED_ENUM_NAME} ${delimiter} ${options.stringEnums ? `"${UNRECOGNIZED_ENUM_NAME}"` : UNRECOGNIZED_ENUM_VALUE.toString()},`);
|
|
32
|
+
if (options.enumsAsLiterals) {
|
|
33
|
+
chunks.push(ts_poet_1.code `} as const`);
|
|
34
|
+
chunks.push(ts_poet_1.code `\n`);
|
|
35
|
+
chunks.push(ts_poet_1.code `export type ${ts_poet_1.def(fullName)} = typeof ${ts_poet_1.def(fullName)}[keyof typeof ${ts_poet_1.def(fullName)}]`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
chunks.push(ts_poet_1.code `}`);
|
|
39
|
+
}
|
|
27
40
|
if (options.outputJsonMethods || (options.stringEnums && options.outputEncodeMethods)) {
|
|
28
41
|
chunks.push(ts_poet_1.code `\n`);
|
|
29
42
|
chunks.push(generateEnumFromJson(ctx, fullName, enumDesc));
|
package/build/main.js
CHANGED
|
@@ -70,7 +70,7 @@ function generateFile(ctx, fileDesc) {
|
|
|
70
70
|
// then add the encoder/decoder/base instance
|
|
71
71
|
visit_1.visit(fileDesc, sourceInfo, (fullName, message, sInfo, fullProtoTypeName) => {
|
|
72
72
|
const fullTypeName = utils_1.maybePrefixPackage(fileDesc, fullProtoTypeName);
|
|
73
|
-
chunks.push(
|
|
73
|
+
chunks.push(generateBaseInstanceFactory(ctx, fullName, message, fullTypeName));
|
|
74
74
|
const staticMembers = [];
|
|
75
75
|
if (options.outputTypeRegistry) {
|
|
76
76
|
staticMembers.push(ts_poet_1.code `$type: '${fullTypeName}' as const`);
|
|
@@ -86,8 +86,8 @@ function generateFile(ctx, fileDesc) {
|
|
|
86
86
|
if (options.outputPartialMethods) {
|
|
87
87
|
staticMembers.push(generateFromPartial(ctx, fullName, message));
|
|
88
88
|
}
|
|
89
|
-
staticMembers.push(...generateWrap(fullTypeName));
|
|
90
|
-
staticMembers.push(...generateUnwrap(fullTypeName));
|
|
89
|
+
staticMembers.push(...generateWrap(ctx, fullTypeName));
|
|
90
|
+
staticMembers.push(...generateUnwrap(ctx, fullTypeName));
|
|
91
91
|
chunks.push(ts_poet_1.code `
|
|
92
92
|
export const ${ts_poet_1.def(fullName)} = {
|
|
93
93
|
${ts_poet_1.joinCode(staticMembers, { on: ',\n\n' })}
|
|
@@ -195,6 +195,7 @@ function makeUtils(options) {
|
|
|
195
195
|
...makeDeepPartial(options, longs),
|
|
196
196
|
...makeTimestampMethods(options, longs),
|
|
197
197
|
...longs,
|
|
198
|
+
...makeComparisonUtils(),
|
|
198
199
|
};
|
|
199
200
|
}
|
|
200
201
|
exports.makeUtils = makeUtils;
|
|
@@ -396,6 +397,17 @@ function makeTimestampMethods(options, longs) {
|
|
|
396
397
|
`);
|
|
397
398
|
return { toTimestamp, fromTimestamp, fromJsonTimestamp };
|
|
398
399
|
}
|
|
400
|
+
function makeComparisonUtils() {
|
|
401
|
+
const isObject = ts_poet_1.conditionalOutput('isObject', ts_poet_1.code `
|
|
402
|
+
function isObject(value: any): boolean {
|
|
403
|
+
return typeof value === 'object' && value !== null;
|
|
404
|
+
}`);
|
|
405
|
+
const isSet = ts_poet_1.conditionalOutput('isSet', ts_poet_1.code `
|
|
406
|
+
function isSet(value: any): boolean {
|
|
407
|
+
return value !== null && value !== undefined;
|
|
408
|
+
}`);
|
|
409
|
+
return { isObject, isSet };
|
|
410
|
+
}
|
|
399
411
|
// Create the interface with properties
|
|
400
412
|
function generateInterfaceDeclaration(ctx, fullName, messageDesc, sourceInfo, fullTypeName) {
|
|
401
413
|
var _a;
|
|
@@ -460,20 +472,39 @@ function generateOneofProperty(ctx, messageDesc, oneofIndex, sourceInfo) {
|
|
|
460
472
|
return prop;
|
|
461
473
|
*/
|
|
462
474
|
}
|
|
463
|
-
// Create a 'base' instance with default values for decode to use as a prototype
|
|
464
|
-
function
|
|
465
|
-
const fields =
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
.
|
|
475
|
+
// Create a function that constructs 'base' instance with default values for decode to use as a prototype
|
|
476
|
+
function generateBaseInstanceFactory(ctx, fullName, messageDesc, fullTypeName) {
|
|
477
|
+
const fields = [];
|
|
478
|
+
// When oneof=unions, we generate a single property with an ADT per `oneof` clause.
|
|
479
|
+
const processedOneofs = new Set();
|
|
480
|
+
for (const field of messageDesc.field) {
|
|
481
|
+
if (types_1.isWithinOneOfThatShouldBeUnion(ctx.options, field)) {
|
|
482
|
+
const { oneofIndex } = field;
|
|
483
|
+
if (!processedOneofs.has(oneofIndex)) {
|
|
484
|
+
processedOneofs.add(oneofIndex);
|
|
485
|
+
const name = case_1.maybeSnakeToCamel(messageDesc.oneofDecl[oneofIndex].name, ctx.options);
|
|
486
|
+
fields.push(ts_poet_1.code `${name}: undefined`);
|
|
487
|
+
}
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
470
490
|
const name = case_1.maybeSnakeToCamel(field.name, ctx.options);
|
|
471
|
-
|
|
472
|
-
|
|
491
|
+
const val = types_1.isWithinOneOf(field)
|
|
492
|
+
? 'undefined'
|
|
493
|
+
: types_1.isMapType(ctx, messageDesc, field)
|
|
494
|
+
? '{}'
|
|
495
|
+
: types_1.isRepeated(field)
|
|
496
|
+
? '[]'
|
|
497
|
+
: types_1.defaultValue(ctx, field);
|
|
498
|
+
fields.push(ts_poet_1.code `${name}: ${val}`);
|
|
499
|
+
}
|
|
473
500
|
if (ctx.options.outputTypeRegistry) {
|
|
474
501
|
fields.unshift(ts_poet_1.code `$type: '${fullTypeName}'`);
|
|
475
502
|
}
|
|
476
|
-
return ts_poet_1.code `
|
|
503
|
+
return ts_poet_1.code `
|
|
504
|
+
function createBase${fullName}(): ${fullName} {
|
|
505
|
+
return { ${ts_poet_1.joinCode(fields, { on: ',' })} };
|
|
506
|
+
}
|
|
507
|
+
`;
|
|
477
508
|
}
|
|
478
509
|
/** Creates a function to decode a message by loop overing the tags. */
|
|
479
510
|
function generateDecode(ctx, fullName, messageDesc) {
|
|
@@ -487,22 +518,8 @@ function generateDecode(ctx, fullName, messageDesc) {
|
|
|
487
518
|
): ${fullName} {
|
|
488
519
|
const reader = input instanceof ${Reader} ? input : new ${Reader}(input);
|
|
489
520
|
let end = length === undefined ? reader.len : reader.pos + length;
|
|
490
|
-
const message =
|
|
521
|
+
const message = createBase${fullName}();
|
|
491
522
|
`);
|
|
492
|
-
// initialize all lists
|
|
493
|
-
messageDesc.field.filter(types_1.isRepeated).forEach((field) => {
|
|
494
|
-
const name = case_1.maybeSnakeToCamel(field.name, options);
|
|
495
|
-
const value = types_1.isMapType(ctx, messageDesc, field) ? '{}' : '[]';
|
|
496
|
-
chunks.push(ts_poet_1.code `message.${name} = ${value};`);
|
|
497
|
-
});
|
|
498
|
-
// initialize all buffers
|
|
499
|
-
messageDesc.field
|
|
500
|
-
.filter((field) => !types_1.isRepeated(field) && !types_1.isWithinOneOf(field) && types_1.isBytes(field))
|
|
501
|
-
.forEach((field) => {
|
|
502
|
-
const value = options.env === options_1.EnvOption.NODE ? 'Buffer.alloc(0)' : 'new Uint8Array()';
|
|
503
|
-
const name = case_1.maybeSnakeToCamel(field.name, options);
|
|
504
|
-
chunks.push(ts_poet_1.code `message.${name} = ${value};`);
|
|
505
|
-
});
|
|
506
523
|
// start the tag loop
|
|
507
524
|
chunks.push(ts_poet_1.code `
|
|
508
525
|
while (reader.pos < end) {
|
|
@@ -567,28 +584,29 @@ function generateDecode(ctx, fullName, messageDesc) {
|
|
|
567
584
|
}
|
|
568
585
|
// and then use the snippet to handle repeated fields if necessary
|
|
569
586
|
if (types_1.isRepeated(field)) {
|
|
587
|
+
const maybeNonNullAssertion = ctx.options.useOptionals === 'all' ? '!' : '';
|
|
570
588
|
if (types_1.isMapType(ctx, messageDesc, field)) {
|
|
571
589
|
// We need a unique const within the `cast` statement
|
|
572
590
|
const varName = `entry${field.number}`;
|
|
573
591
|
chunks.push(ts_poet_1.code `
|
|
574
592
|
const ${varName} = ${readSnippet};
|
|
575
593
|
if (${varName}.value !== undefined) {
|
|
576
|
-
message.${fieldName}[${varName}.key] = ${varName}.value;
|
|
594
|
+
message.${fieldName}${maybeNonNullAssertion}[${varName}.key] = ${varName}.value;
|
|
577
595
|
}
|
|
578
596
|
`);
|
|
579
597
|
}
|
|
580
598
|
else if (types_1.packedType(field.type) === undefined) {
|
|
581
|
-
chunks.push(ts_poet_1.code `message.${fieldName}.push(${readSnippet});`);
|
|
599
|
+
chunks.push(ts_poet_1.code `message.${fieldName}${maybeNonNullAssertion}.push(${readSnippet});`);
|
|
582
600
|
}
|
|
583
601
|
else {
|
|
584
602
|
chunks.push(ts_poet_1.code `
|
|
585
603
|
if ((tag & 7) === 2) {
|
|
586
604
|
const end2 = reader.uint32() + reader.pos;
|
|
587
605
|
while (reader.pos < end2) {
|
|
588
|
-
message.${fieldName}.push(${readSnippet});
|
|
606
|
+
message.${fieldName}${maybeNonNullAssertion}.push(${readSnippet});
|
|
589
607
|
}
|
|
590
608
|
} else {
|
|
591
|
-
message.${fieldName}.push(${readSnippet});
|
|
609
|
+
message.${fieldName}${maybeNonNullAssertion}.push(${readSnippet});
|
|
592
610
|
}
|
|
593
611
|
`);
|
|
594
612
|
}
|
|
@@ -799,13 +817,13 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
799
817
|
// create the basic function declaration
|
|
800
818
|
chunks.push(ts_poet_1.code `
|
|
801
819
|
fromJSON(${messageDesc.field.length > 0 ? 'object' : '_'}: any): ${fullName} {
|
|
802
|
-
const message =
|
|
820
|
+
const message = createBase${fullName}();
|
|
803
821
|
`);
|
|
804
822
|
// add a check for each incoming field
|
|
805
823
|
messageDesc.field.forEach((field) => {
|
|
806
824
|
const fieldName = case_1.maybeSnakeToCamel(field.name, options);
|
|
807
825
|
const jsonName = utils_1.determineFieldJsonName(field, options);
|
|
808
|
-
// get
|
|
826
|
+
// get code that extracts value from incoming object
|
|
809
827
|
const readSnippet = (from) => {
|
|
810
828
|
if (types_1.isEnum(field)) {
|
|
811
829
|
const fromJson = types_1.getEnumMethod(ctx, field.typeName, 'FromJSON');
|
|
@@ -840,6 +858,9 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
840
858
|
else if (types_1.isAnyValueType(field) || types_1.isStructType(field)) {
|
|
841
859
|
return ts_poet_1.code `${from}`;
|
|
842
860
|
}
|
|
861
|
+
else if (types_1.isListValueType(field)) {
|
|
862
|
+
return ts_poet_1.code `[...${from}]`;
|
|
863
|
+
}
|
|
843
864
|
else if (types_1.isValueType(ctx, field)) {
|
|
844
865
|
const valueType = types_1.valueTypeName(ctx, field.typeName);
|
|
845
866
|
if (types_1.isLongValueType(field) && options.forceLong === options_1.LongOption.LONG) {
|
|
@@ -848,9 +869,6 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
848
869
|
else if (types_1.isBytesValueType(field)) {
|
|
849
870
|
return ts_poet_1.code `new ${case_1.capitalize(valueType.toCodeString())}(${from})`;
|
|
850
871
|
}
|
|
851
|
-
else if (types_1.isListValueType(field)) {
|
|
852
|
-
return ts_poet_1.code `[...${from}]`;
|
|
853
|
-
}
|
|
854
872
|
else {
|
|
855
873
|
return ts_poet_1.code `${case_1.capitalize(valueType.toCodeString())}(${from})`;
|
|
856
874
|
}
|
|
@@ -917,22 +935,23 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
917
935
|
acc[${i}] = ${readSnippet('value')};
|
|
918
936
|
return acc;
|
|
919
937
|
}, {});
|
|
920
|
-
`);
|
|
921
|
-
}
|
|
922
|
-
else if (types_1.isAnyValueType(field)) {
|
|
923
|
-
chunks.push(ts_poet_1.code `
|
|
924
|
-
message.${fieldName} = Array.isArray(object?.${jsonName}) ? [...object.${jsonName}] : [];
|
|
925
938
|
`);
|
|
926
939
|
}
|
|
927
940
|
else {
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
941
|
+
const readValueSnippet = readSnippet('e');
|
|
942
|
+
if (readValueSnippet.toString() === ts_poet_1.code `e`.toString()) {
|
|
943
|
+
chunks.push(ts_poet_1.code `message.${fieldName} = Array.isArray(object?.${jsonName}) ? [...object.${jsonName}] : [];`);
|
|
944
|
+
}
|
|
945
|
+
else {
|
|
946
|
+
// Explicit `any` type required to make TS with noImplicitAny happy. `object` is also `any` here.
|
|
947
|
+
chunks.push(ts_poet_1.code `
|
|
948
|
+
message.${fieldName} = Array.isArray(object?.${jsonName}) ? object.${jsonName}.map((e: any) => ${readValueSnippet}): [];
|
|
949
|
+
`);
|
|
950
|
+
}
|
|
932
951
|
}
|
|
933
952
|
}
|
|
934
953
|
else if (types_1.isWithinOneOfThatShouldBeUnion(options, field)) {
|
|
935
|
-
chunks.push(ts_poet_1.code `if (
|
|
954
|
+
chunks.push(ts_poet_1.code `if (${ctx.utils.isSet}(object.${jsonName})) {`);
|
|
936
955
|
const oneofName = case_1.maybeSnakeToCamel(messageDesc.oneofDecl[field.oneofIndex].name, options);
|
|
937
956
|
chunks.push(ts_poet_1.code `
|
|
938
957
|
message.${oneofName} = { $case: '${fieldName}', ${fieldName}: ${readSnippet(`object.${jsonName}`)} }
|
|
@@ -940,22 +959,27 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
940
959
|
chunks.push(ts_poet_1.code `}`);
|
|
941
960
|
}
|
|
942
961
|
else if (types_1.isAnyValueType(field)) {
|
|
943
|
-
chunks.push(ts_poet_1.code `message.${fieldName} = object
|
|
962
|
+
chunks.push(ts_poet_1.code `message.${fieldName} = ${ctx.utils.isSet}(object?.${jsonName})
|
|
963
|
+
? ${readSnippet(`object.${jsonName}`)}
|
|
964
|
+
: undefined;
|
|
965
|
+
`);
|
|
944
966
|
}
|
|
945
967
|
else if (types_1.isStructType(field)) {
|
|
946
|
-
chunks.push(ts_poet_1.code `message.${fieldName} =
|
|
968
|
+
chunks.push(ts_poet_1.code `message.${fieldName} = ${ctx.utils.isObject}(object.${jsonName})
|
|
969
|
+
? ${readSnippet(`object.${jsonName}`)}
|
|
970
|
+
: undefined;`);
|
|
947
971
|
}
|
|
948
972
|
else if (types_1.isListValueType(field)) {
|
|
949
973
|
chunks.push(ts_poet_1.code `
|
|
950
|
-
message.${fieldName} = Array.isArray(object
|
|
951
|
-
? ${readSnippet(`object.${
|
|
974
|
+
message.${fieldName} = Array.isArray(object.${jsonName})
|
|
975
|
+
? ${readSnippet(`object.${jsonName}`)}
|
|
952
976
|
: ${'undefined'};
|
|
953
977
|
`);
|
|
954
978
|
}
|
|
955
979
|
else {
|
|
956
980
|
const fallback = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
|
|
957
981
|
chunks.push(ts_poet_1.code `
|
|
958
|
-
message.${fieldName} =
|
|
982
|
+
message.${fieldName} = ${ctx.utils.isSet}(object.${jsonName})
|
|
959
983
|
? ${readSnippet(`object.${jsonName}`)}
|
|
960
984
|
: ${fallback};
|
|
961
985
|
`);
|
|
@@ -1095,13 +1119,19 @@ function generateToJson(ctx, fullName, messageDesc) {
|
|
|
1095
1119
|
function generateFromPartial(ctx, fullName, messageDesc) {
|
|
1096
1120
|
const { options, utils, typeMap } = ctx;
|
|
1097
1121
|
const chunks = [];
|
|
1098
|
-
const Timestamp = utils_1.impProto(options, 'google/protobuf/timestamp', 'Timestamp');
|
|
1099
1122
|
// create the basic function declaration
|
|
1100
1123
|
const paramName = messageDesc.field.length > 0 ? 'object' : '_';
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1124
|
+
if (ctx.options.useExactTypes) {
|
|
1125
|
+
chunks.push(ts_poet_1.code `
|
|
1126
|
+
fromPartial<I extends ${utils.Exact}<${utils.DeepPartial}<${fullName}>, I>>(${paramName}: I): ${fullName} {
|
|
1127
|
+
`);
|
|
1128
|
+
}
|
|
1129
|
+
else {
|
|
1130
|
+
chunks.push(ts_poet_1.code `
|
|
1131
|
+
fromPartial(${paramName}: ${utils.DeepPartial}<${fullName}>): ${fullName} {
|
|
1132
|
+
`);
|
|
1133
|
+
}
|
|
1134
|
+
chunks.push(ts_poet_1.code `const message = createBase${fullName}();`);
|
|
1105
1135
|
// add a check for each incoming field
|
|
1106
1136
|
messageDesc.field.forEach((field) => {
|
|
1107
1137
|
const fieldName = case_1.maybeSnakeToCamel(field.name, options);
|
|
@@ -1211,7 +1241,7 @@ function generateFromPartial(ctx, fullName, messageDesc) {
|
|
|
1211
1241
|
chunks.push(ts_poet_1.code `}`);
|
|
1212
1242
|
return ts_poet_1.joinCode(chunks, { on: '\n' });
|
|
1213
1243
|
}
|
|
1214
|
-
function generateWrap(fullProtoTypeName) {
|
|
1244
|
+
function generateWrap(ctx, fullProtoTypeName) {
|
|
1215
1245
|
const chunks = [];
|
|
1216
1246
|
if (types_1.isStructTypeName(fullProtoTypeName)) {
|
|
1217
1247
|
chunks.push(ts_poet_1.code `wrap(object: {[key: string]: any} | undefined): Struct {
|
|
@@ -1225,7 +1255,29 @@ function generateWrap(fullProtoTypeName) {
|
|
|
1225
1255
|
}`);
|
|
1226
1256
|
}
|
|
1227
1257
|
if (types_1.isAnyValueTypeName(fullProtoTypeName)) {
|
|
1228
|
-
|
|
1258
|
+
if (ctx.options.oneof === options_1.OneofOption.UNIONS) {
|
|
1259
|
+
chunks.push(ts_poet_1.code `wrap(value: any): Value {
|
|
1260
|
+
if (value === null) {
|
|
1261
|
+
return {kind: {$case: 'nullValue', nullValue: NullValue.NULL_VALUE}};
|
|
1262
|
+
} else if (typeof value === 'boolean') {
|
|
1263
|
+
return {kind: {$case: 'boolValue', boolValue: value}};
|
|
1264
|
+
} else if (typeof value === 'number') {
|
|
1265
|
+
return {kind: {$case: 'numberValue', numberValue: value}};
|
|
1266
|
+
} else if (typeof value === 'string') {
|
|
1267
|
+
return {kind: {$case: 'stringValue', stringValue: value}};
|
|
1268
|
+
} else if (Array.isArray(value)) {
|
|
1269
|
+
return {kind: {$case: 'listValue', listValue: value}};
|
|
1270
|
+
} else if (typeof value === 'object') {
|
|
1271
|
+
return {kind: {$case: 'structValue', structValue: value}};
|
|
1272
|
+
} else if (typeof value === 'undefined') {
|
|
1273
|
+
return {} as Value;
|
|
1274
|
+
} else {
|
|
1275
|
+
throw new Error('Unsupported any value type: ' + typeof value);
|
|
1276
|
+
}
|
|
1277
|
+
}`);
|
|
1278
|
+
}
|
|
1279
|
+
else {
|
|
1280
|
+
chunks.push(ts_poet_1.code `wrap(value: any): Value {
|
|
1229
1281
|
if (value === null) {
|
|
1230
1282
|
return {nullValue: NullValue.NULL_VALUE} as Value;
|
|
1231
1283
|
} else if (typeof value === 'boolean') {
|
|
@@ -1244,15 +1296,16 @@ function generateWrap(fullProtoTypeName) {
|
|
|
1244
1296
|
throw new Error('Unsupported any value type: ' + typeof value);
|
|
1245
1297
|
}
|
|
1246
1298
|
}`);
|
|
1299
|
+
}
|
|
1247
1300
|
}
|
|
1248
1301
|
if (types_1.isListValueTypeName(fullProtoTypeName)) {
|
|
1249
|
-
chunks.push(ts_poet_1.code `wrap(value: Array<any>): ListValue {
|
|
1250
|
-
return {values: value};
|
|
1302
|
+
chunks.push(ts_poet_1.code `wrap(value: Array<any> | undefined): ListValue {
|
|
1303
|
+
return {values: value ?? []};
|
|
1251
1304
|
}`);
|
|
1252
1305
|
}
|
|
1253
1306
|
return chunks;
|
|
1254
1307
|
}
|
|
1255
|
-
function generateUnwrap(fullProtoTypeName) {
|
|
1308
|
+
function generateUnwrap(ctx, fullProtoTypeName) {
|
|
1256
1309
|
const chunks = [];
|
|
1257
1310
|
if (types_1.isStructTypeName(fullProtoTypeName)) {
|
|
1258
1311
|
chunks.push(ts_poet_1.code `unwrap(message: Struct): {[key: string]: any} {
|
|
@@ -1264,7 +1317,27 @@ function generateUnwrap(fullProtoTypeName) {
|
|
|
1264
1317
|
}`);
|
|
1265
1318
|
}
|
|
1266
1319
|
if (types_1.isAnyValueTypeName(fullProtoTypeName)) {
|
|
1267
|
-
|
|
1320
|
+
if (ctx.options.oneof === options_1.OneofOption.UNIONS) {
|
|
1321
|
+
chunks.push(ts_poet_1.code `unwrap(message: Value): string | number | boolean | Object | null | Array<any> | undefined {
|
|
1322
|
+
if (message.kind?.$case === 'nullValue') {
|
|
1323
|
+
return null;
|
|
1324
|
+
} else if (message.kind?.$case === 'numberValue') {
|
|
1325
|
+
return message.kind?.numberValue;
|
|
1326
|
+
} else if (message.kind?.$case === 'stringValue') {
|
|
1327
|
+
return message.kind?.stringValue;
|
|
1328
|
+
} else if (message.kind?.$case === 'boolValue') {
|
|
1329
|
+
return message.kind?.boolValue;
|
|
1330
|
+
} else if (message.kind?.$case === 'structValue') {
|
|
1331
|
+
return message.kind?.structValue;
|
|
1332
|
+
} else if (message.kind?.$case === 'listValue') {
|
|
1333
|
+
return message.kind?.listValue;
|
|
1334
|
+
} else {
|
|
1335
|
+
return undefined;
|
|
1336
|
+
}
|
|
1337
|
+
}`);
|
|
1338
|
+
}
|
|
1339
|
+
else {
|
|
1340
|
+
chunks.push(ts_poet_1.code `unwrap(message: Value): string | number | boolean | Object | null | Array<any> | undefined {
|
|
1268
1341
|
if (message?.stringValue !== undefined) {
|
|
1269
1342
|
return message.stringValue;
|
|
1270
1343
|
} else if (message?.numberValue !== undefined) {
|
|
@@ -1280,6 +1353,7 @@ function generateUnwrap(fullProtoTypeName) {
|
|
|
1280
1353
|
}
|
|
1281
1354
|
return undefined;
|
|
1282
1355
|
}`);
|
|
1356
|
+
}
|
|
1283
1357
|
}
|
|
1284
1358
|
if (types_1.isListValueTypeName(fullProtoTypeName)) {
|
|
1285
1359
|
chunks.push(ts_poet_1.code `unwrap(message: ListValue): Array<any> {
|
package/build/options.js
CHANGED
|
@@ -48,6 +48,7 @@ function defaultOptions() {
|
|
|
48
48
|
outputTypeRegistry: false,
|
|
49
49
|
stringEnums: false,
|
|
50
50
|
constEnums: false,
|
|
51
|
+
enumsAsLiterals: false,
|
|
51
52
|
outputClientImpl: true,
|
|
52
53
|
outputServices: ServiceOption.DEFAULT,
|
|
53
54
|
returnObservable: false,
|
|
@@ -60,6 +61,7 @@ function defaultOptions() {
|
|
|
60
61
|
outputSchema: false,
|
|
61
62
|
onlyTypes: false,
|
|
62
63
|
emitImportedFiles: true,
|
|
64
|
+
useExactTypes: true,
|
|
63
65
|
};
|
|
64
66
|
}
|
|
65
67
|
exports.defaultOptions = defaultOptions;
|