ts-proto 1.169.1 → 1.171.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 +74 -0
- package/build/main.js +24 -24
- package/build/options.js +1 -0
- package/build/types.js +13 -6
- package/build/utils.js +29 -1
- package/package.json +1 -1
package/README.markdown
CHANGED
|
@@ -547,6 +547,58 @@ Generated code will be placed in the Gradle build directory.
|
|
|
547
547
|
|
|
548
548
|
- With `--ts_proto_opt=comments=false`, comments won't be copied from the proto files to the generated code.
|
|
549
549
|
|
|
550
|
+
- With `--ts_proto_opt=useNullAsOptional=true`, `undefined` values will be converted to `null`, and if you use `optional` label in your `.proto` file, the field will have `undefined` type as well. for example:
|
|
551
|
+
|
|
552
|
+
```protobuf
|
|
553
|
+
message ProfileInfo {
|
|
554
|
+
int32 id = 1;
|
|
555
|
+
string bio = 2;
|
|
556
|
+
string phone = 3;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
message Department {
|
|
560
|
+
int32 id = 1;
|
|
561
|
+
string name = 2;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
message User {
|
|
565
|
+
int32 id = 1;
|
|
566
|
+
string username = 2;
|
|
567
|
+
/*
|
|
568
|
+
ProfileInfo will be optional in typescript, the type will be ProfileInfo | null | undefined
|
|
569
|
+
this is needed in cases where you don't wanna provide any value for the profile.
|
|
570
|
+
*/
|
|
571
|
+
optional ProfileInfo profile = 3;
|
|
572
|
+
|
|
573
|
+
/*
|
|
574
|
+
Department only accepts a Department type or null, so this means you have to pass it null if there is no value available.
|
|
575
|
+
*/
|
|
576
|
+
Department department = 4;
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
the generated interfaces will be:
|
|
581
|
+
|
|
582
|
+
```typescript
|
|
583
|
+
export interface ProfileInfo {
|
|
584
|
+
id: number;
|
|
585
|
+
bio: string;
|
|
586
|
+
phone: string;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
export interface Department {
|
|
590
|
+
id: number;
|
|
591
|
+
name: string;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
export interface User {
|
|
595
|
+
id: number;
|
|
596
|
+
username: string;
|
|
597
|
+
profile?: ProfileInfo | null | undefined; // check this one
|
|
598
|
+
department: Department | null; // check this one
|
|
599
|
+
}
|
|
600
|
+
```
|
|
601
|
+
|
|
550
602
|
### NestJS Support
|
|
551
603
|
|
|
552
604
|
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).
|
|
@@ -724,6 +776,28 @@ As this will automatically enforce only one of `field_a` or `field_b` "being set
|
|
|
724
776
|
|
|
725
777
|
In ts-proto's currently-unscheduled 2.x release, `oneof=unions` will become the default behavior.
|
|
726
778
|
|
|
779
|
+
## OneOf Type Helpers
|
|
780
|
+
|
|
781
|
+
The following helper types may make it easier to work with the types generated from `oneof=unions`:
|
|
782
|
+
|
|
783
|
+
```ts
|
|
784
|
+
/** Extracts all the case names from a oneOf field. */
|
|
785
|
+
type OneOfCases<T> = T extends { $case: infer U extends string } ? U : never;
|
|
786
|
+
|
|
787
|
+
/** Extracts a union of all the value types from a oneOf field */
|
|
788
|
+
type OneOfValues<T> = T extends { $case: infer U extends string; [key: string]: unknown }
|
|
789
|
+
? T[U]
|
|
790
|
+
: never;
|
|
791
|
+
|
|
792
|
+
/** Extracts the specific type of a oneOf case based on its field name */
|
|
793
|
+
type OneOfCase<T, K extends OneOfCases<T>> = T extends {
|
|
794
|
+
$case: infer U extends K;
|
|
795
|
+
[key: string]: unknown;
|
|
796
|
+
}
|
|
797
|
+
? T[U]
|
|
798
|
+
: never;
|
|
799
|
+
```
|
|
800
|
+
|
|
727
801
|
# Default values and unset fields
|
|
728
802
|
|
|
729
803
|
In core Protobuf (and so also `ts-proto`), values that are _unset_ or equal to the default value are not sent over the wire.
|
package/build/main.js
CHANGED
|
@@ -715,7 +715,7 @@ function generateOneofProperty(ctx, messageDesc, oneofIndex, sourceInfo) {
|
|
|
715
715
|
return (0, ts_poet_1.code) `{ ${mbReadonly}$case: '${fieldName}', ${mbReadonly}${fieldName}: ${typeName} }`;
|
|
716
716
|
}), { on: " | " });
|
|
717
717
|
const name = (0, case_1.maybeSnakeToCamel)(messageDesc.oneofDecl[oneofIndex].name, options);
|
|
718
|
-
return (0, ts_poet_1.code) `${mbReadonly}${name}?: ${unionType} |
|
|
718
|
+
return (0, ts_poet_1.code) `${mbReadonly}${name}?: ${unionType} | ${(0, utils_1.nullOrUndefined)(options)},`;
|
|
719
719
|
/*
|
|
720
720
|
// Ideally we'd put the comments for each oneof field next to the anonymous
|
|
721
721
|
// type we've created in the type union above, but ts-poet currently lacks
|
|
@@ -751,7 +751,7 @@ function generateBaseInstanceFactory(ctx, fullName, messageDesc, fullTypeName) {
|
|
|
751
751
|
const name = options.useJsonName
|
|
752
752
|
? (0, utils_1.getFieldName)(field, options)
|
|
753
753
|
: (0, case_1.maybeSnakeToCamel)(messageDesc.oneofDecl[oneofIndex].name, ctx.options);
|
|
754
|
-
fields.push((0, ts_poet_1.code) `${(0, utils_1.safeAccessor)(name)}:
|
|
754
|
+
fields.push((0, ts_poet_1.code) `${(0, utils_1.safeAccessor)(name)}: ${(0, utils_1.nullOrUndefined)(options)}`);
|
|
755
755
|
}
|
|
756
756
|
continue;
|
|
757
757
|
}
|
|
@@ -761,7 +761,7 @@ function generateBaseInstanceFactory(ctx, fullName, messageDesc, fullTypeName) {
|
|
|
761
761
|
}
|
|
762
762
|
const fieldKey = (0, utils_1.safeAccessor)((0, utils_1.getFieldName)(field, options));
|
|
763
763
|
const val = (0, types_1.isWithinOneOf)(field)
|
|
764
|
-
?
|
|
764
|
+
? (0, utils_1.nullOrUndefined)(options)
|
|
765
765
|
: (0, types_1.isMapType)(ctx, messageDesc, field)
|
|
766
766
|
? (0, types_1.shouldGenerateJSMapType)(ctx, messageDesc, field)
|
|
767
767
|
? "new Map()"
|
|
@@ -895,7 +895,7 @@ function generateDecode(ctx, fullName, messageDesc) {
|
|
|
895
895
|
const initializerNecessary = !options.initializeFieldsAsUndefined &&
|
|
896
896
|
(0, types_1.isOptionalProperty)(field, messageDesc.options, options, currentFile.isProto3Syntax);
|
|
897
897
|
if ((0, types_1.isRepeated)(field)) {
|
|
898
|
-
const maybeNonNullAssertion = ctx.options.useOptionals === "all" ? "!" : "";
|
|
898
|
+
const maybeNonNullAssertion = ctx.options.useOptionals === "all" || ctx.options.useOptionals === "deprecatedOnly" ? "!" : "";
|
|
899
899
|
const mapType = (0, types_1.detectMapType)(ctx, messageDesc, field);
|
|
900
900
|
if (mapType) {
|
|
901
901
|
// We need a unique const within the `cast` statement
|
|
@@ -910,14 +910,14 @@ function generateDecode(ctx, fullName, messageDesc) {
|
|
|
910
910
|
}
|
|
911
911
|
const initializerSnippet = initializerNecessary
|
|
912
912
|
? `
|
|
913
|
-
if (${messageProperty} === undefined) {
|
|
913
|
+
if (${messageProperty} === undefined ${(0, utils_1.withOrMaybeCheckIsNull)(options, messageProperty)}) {
|
|
914
914
|
${messageProperty} = ${generateMapType ? "new Map()" : "{}"};
|
|
915
915
|
}`
|
|
916
916
|
: "";
|
|
917
917
|
chunks.push((0, ts_poet_1.code) `
|
|
918
918
|
${tagCheck}
|
|
919
919
|
const ${varName} = ${readSnippet};
|
|
920
|
-
if (${varName}.value !== undefined) {
|
|
920
|
+
if (${varName}.value !== undefined ${(0, utils_1.withAndMaybeCheckIsNotNull)(options, `${varName}.value`)}) {
|
|
921
921
|
${initializerSnippet}
|
|
922
922
|
${valueSetterSnippet};
|
|
923
923
|
}
|
|
@@ -926,7 +926,7 @@ function generateDecode(ctx, fullName, messageDesc) {
|
|
|
926
926
|
else {
|
|
927
927
|
const initializerSnippet = initializerNecessary
|
|
928
928
|
? `
|
|
929
|
-
if (${messageProperty} === undefined) {
|
|
929
|
+
if (${messageProperty} === undefined ${(0, utils_1.withOrMaybeCheckIsNull)(options, messageProperty)}) {
|
|
930
930
|
${messageProperty} = [];
|
|
931
931
|
}`
|
|
932
932
|
: "";
|
|
@@ -992,7 +992,7 @@ function generateDecode(ctx, fullName, messageDesc) {
|
|
|
992
992
|
let maybeNonNullAssertion = options.initializeFieldsAsUndefined ? "!" : "";
|
|
993
993
|
if (!options.initializeFieldsAsUndefined) {
|
|
994
994
|
unknownFieldsInitializerSnippet = `
|
|
995
|
-
if (message._unknownFields === undefined) {
|
|
995
|
+
if (message._unknownFields === undefined ${(0, utils_1.withOrMaybeCheckIsNull)(options, `message._unknownFields`)}) {
|
|
996
996
|
message._unknownFields = {};
|
|
997
997
|
}
|
|
998
998
|
`;
|
|
@@ -1005,7 +1005,7 @@ function generateDecode(ctx, fullName, messageDesc) {
|
|
|
1005
1005
|
${unknownFieldsInitializerSnippet}
|
|
1006
1006
|
const list = message._unknownFields${maybeNonNullAssertion}[tag];
|
|
1007
1007
|
|
|
1008
|
-
if (list === undefined) {
|
|
1008
|
+
if (list === undefined ${(0, utils_1.withOrMaybeCheckIsNull)(options, `message._unknownFields`)}) {
|
|
1009
1009
|
message._unknownFields${maybeNonNullAssertion}[tag] = [buf];
|
|
1010
1010
|
} else {
|
|
1011
1011
|
list.push(buf);
|
|
@@ -1123,7 +1123,7 @@ function generateEncode(ctx, fullName, messageDesc) {
|
|
|
1123
1123
|
const maybeTypeField = (0, options_1.addTypeToMessages)(options) ? `$type: '${field.typeName.slice(1)}',` : "";
|
|
1124
1124
|
const entryWriteSnippet = (0, types_1.isValueType)(ctx, valueType)
|
|
1125
1125
|
? (0, ts_poet_1.code) `
|
|
1126
|
-
if (value !== undefined) {
|
|
1126
|
+
if (value !== undefined ${(0, utils_1.withOrMaybeCheckIsNotNull)(options, `value`)}) {
|
|
1127
1127
|
${writeSnippet(`{ ${maybeTypeField} key: key as any, value }`)};
|
|
1128
1128
|
}
|
|
1129
1129
|
`
|
|
@@ -1234,7 +1234,7 @@ function generateEncode(ctx, fullName, messageDesc) {
|
|
|
1234
1234
|
}
|
|
1235
1235
|
if (isOptional) {
|
|
1236
1236
|
chunks.push((0, ts_poet_1.code) `
|
|
1237
|
-
if (${messageProperty} !== undefined && ${messageProperty}.length !== 0) {
|
|
1237
|
+
if (${messageProperty} !== undefined ${(0, utils_1.withAndMaybeCheckIsNotNull)(options, messageProperty)} && ${messageProperty}.length !== 0) {
|
|
1238
1238
|
${listWriteSnippet}
|
|
1239
1239
|
}
|
|
1240
1240
|
`);
|
|
@@ -1264,14 +1264,14 @@ function generateEncode(ctx, fullName, messageDesc) {
|
|
|
1264
1264
|
else if ((0, types_1.isWithinOneOf)(field)) {
|
|
1265
1265
|
// Oneofs don't have a default value check b/c they need to denote which-oneof presence
|
|
1266
1266
|
chunks.push((0, ts_poet_1.code) `
|
|
1267
|
-
if (${messageProperty} !== undefined) {
|
|
1267
|
+
if (${messageProperty} !== undefined ${(0, utils_1.withAndMaybeCheckIsNotNull)(options, messageProperty)}) {
|
|
1268
1268
|
${writeSnippet(`${messageProperty}`)};
|
|
1269
1269
|
}
|
|
1270
1270
|
`);
|
|
1271
1271
|
}
|
|
1272
1272
|
else if ((0, types_1.isMessage)(field)) {
|
|
1273
1273
|
chunks.push((0, ts_poet_1.code) `
|
|
1274
|
-
if (${messageProperty} !== undefined) {
|
|
1274
|
+
if (${messageProperty} !== undefined ${(0, utils_1.withAndMaybeCheckIsNotNull)(options, messageProperty)}) {
|
|
1275
1275
|
${writeSnippet(`${messageProperty}`)};
|
|
1276
1276
|
}
|
|
1277
1277
|
`);
|
|
@@ -1697,7 +1697,7 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
1697
1697
|
const fieldType = (0, types_1.toTypeName)(ctx, messageDesc, field);
|
|
1698
1698
|
const i = convertFromObjectKey(ctx, messageDesc, field, "key");
|
|
1699
1699
|
if ((0, types_1.shouldGenerateJSMapType)(ctx, messageDesc, field)) {
|
|
1700
|
-
const fallback = noDefaultValue ?
|
|
1700
|
+
const fallback = noDefaultValue ? (0, utils_1.nullOrUndefined)(options) : "new Map()";
|
|
1701
1701
|
chunks.push((0, ts_poet_1.code) `
|
|
1702
1702
|
${fieldKey}: ${ctx.utils.isObject}(${jsonProperty})
|
|
1703
1703
|
? Object.entries(${jsonProperty}).reduce<${fieldType}>((acc, [key, value]) => {
|
|
@@ -1708,7 +1708,7 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
1708
1708
|
`);
|
|
1709
1709
|
}
|
|
1710
1710
|
else {
|
|
1711
|
-
const fallback = noDefaultValue ?
|
|
1711
|
+
const fallback = noDefaultValue ? (0, utils_1.nullOrUndefined)(options) : "{}";
|
|
1712
1712
|
chunks.push((0, ts_poet_1.code) `
|
|
1713
1713
|
${fieldKey}: ${ctx.utils.isObject}(${jsonProperty})
|
|
1714
1714
|
? Object.entries(${jsonProperty}).reduce<${fieldType}>((acc, [key, value]) => {
|
|
@@ -1720,7 +1720,7 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
1720
1720
|
}
|
|
1721
1721
|
}
|
|
1722
1722
|
else {
|
|
1723
|
-
const fallback = noDefaultValue ?
|
|
1723
|
+
const fallback = noDefaultValue ? (0, utils_1.nullOrUndefined)(options) : "[]";
|
|
1724
1724
|
const readValueSnippet = readSnippet("e");
|
|
1725
1725
|
if (readValueSnippet.toString() === (0, ts_poet_1.code) `e`.toString()) {
|
|
1726
1726
|
chunks.push((0, ts_poet_1.code) `${fieldKey}: ${ctx.utils.globalThis}.Array.isArray(${jsonPropertyOptional}) ? [...${jsonProperty}] : [],`);
|
|
@@ -1745,29 +1745,29 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
1745
1745
|
const ternaryThen = (0, ts_poet_1.code) `{ $case: '${fieldName}', ${fieldKey}: ${readSnippet(`${jsonProperty}`)}`;
|
|
1746
1746
|
chunks.push((0, ts_poet_1.code) `${ternaryIf} ? ${ternaryThen}} : `);
|
|
1747
1747
|
if (field === lastCase) {
|
|
1748
|
-
chunks.push((0, ts_poet_1.code)
|
|
1748
|
+
chunks.push((0, ts_poet_1.code) `${(0, utils_1.nullOrUndefined)(options)},`);
|
|
1749
1749
|
}
|
|
1750
1750
|
}
|
|
1751
1751
|
else if ((0, types_1.isAnyValueType)(field)) {
|
|
1752
1752
|
chunks.push((0, ts_poet_1.code) `${fieldKey}: ${ctx.utils.isSet}(${jsonPropertyOptional})
|
|
1753
1753
|
? ${readSnippet(`${jsonProperty}`)}
|
|
1754
|
-
:
|
|
1754
|
+
: ${(0, utils_1.nullOrUndefined)(options)},
|
|
1755
1755
|
`);
|
|
1756
1756
|
}
|
|
1757
1757
|
else if ((0, types_1.isStructType)(field)) {
|
|
1758
1758
|
chunks.push((0, ts_poet_1.code) `${fieldKey}: ${ctx.utils.isObject}(${jsonProperty})
|
|
1759
1759
|
? ${readSnippet(`${jsonProperty}`)}
|
|
1760
|
-
:
|
|
1760
|
+
: ${(0, utils_1.nullOrUndefined)(options)},`);
|
|
1761
1761
|
}
|
|
1762
1762
|
else if ((0, types_1.isListValueType)(field)) {
|
|
1763
1763
|
chunks.push((0, ts_poet_1.code) `
|
|
1764
1764
|
${fieldKey}: ${ctx.utils.globalThis}.Array.isArray(${jsonProperty})
|
|
1765
1765
|
? ${readSnippet(`${jsonProperty}`)}
|
|
1766
|
-
:
|
|
1766
|
+
: ${(0, utils_1.nullOrUndefined)(options)},
|
|
1767
1767
|
`);
|
|
1768
1768
|
}
|
|
1769
1769
|
else {
|
|
1770
|
-
const fallback = (0, types_1.isWithinOneOf)(field) || noDefaultValue ?
|
|
1770
|
+
const fallback = (0, types_1.isWithinOneOf)(field) || noDefaultValue ? (0, utils_1.nullOrUndefined)(options) : (0, types_1.defaultValue)(ctx, field);
|
|
1771
1771
|
chunks.push((0, ts_poet_1.code) `
|
|
1772
1772
|
${fieldKey}: ${ctx.utils.isSet}(${jsonProperty})
|
|
1773
1773
|
? ${readSnippet(`${jsonProperty}`)}
|
|
@@ -1780,9 +1780,9 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
1780
1780
|
chunks.push((0, ts_poet_1.code) `}`);
|
|
1781
1781
|
return (0, ts_poet_1.joinCode)(chunks, { on: "\n" });
|
|
1782
1782
|
}
|
|
1783
|
-
function generateCanonicalToJson(fullName, fullProtobufTypeName, { useOptionals }) {
|
|
1783
|
+
function generateCanonicalToJson(fullName, fullProtobufTypeName, { useOptionals, useNullAsOptional }) {
|
|
1784
1784
|
if ((0, types_1.isFieldMaskTypeName)(fullProtobufTypeName)) {
|
|
1785
|
-
const returnType = useOptionals === "all" ?
|
|
1785
|
+
const returnType = useOptionals === "all" ? `string | ${(0, utils_1.nullOrUndefined)({ useNullAsOptional })}` : "string";
|
|
1786
1786
|
const pathModifier = useOptionals === "all" ? "?" : "";
|
|
1787
1787
|
return (0, ts_poet_1.code) `
|
|
1788
1788
|
toJSON(message: ${fullName}): ${returnType} {
|
|
@@ -1954,7 +1954,7 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
|
|
|
1954
1954
|
let emitDefaultValuesForJson = ctx.options.emitDefaultValues.includes("json-methods");
|
|
1955
1955
|
const check = ((0, types_1.isScalar)(field) || (0, types_1.isEnum)(field)) && !((0, types_1.isWithinOneOf)(field) || emitDefaultValuesForJson)
|
|
1956
1956
|
? (0, types_1.notDefaultCheck)(ctx, field, messageDesc.options, `${messageProperty}`)
|
|
1957
|
-
: `${messageProperty} !== undefined`;
|
|
1957
|
+
: `${messageProperty} !== undefined ${(0, utils_1.withAndMaybeCheckIsNotNull)(options, messageProperty)}`;
|
|
1958
1958
|
chunks.push((0, ts_poet_1.code) `
|
|
1959
1959
|
if (${check}) {
|
|
1960
1960
|
${jsonProperty} = ${readSnippet(`${messageProperty}`)};
|
package/build/options.js
CHANGED
package/build/types.js
CHANGED
|
@@ -235,7 +235,7 @@ function defaultValue(ctx, field) {
|
|
|
235
235
|
case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_MESSAGE:
|
|
236
236
|
case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_GROUP:
|
|
237
237
|
default:
|
|
238
|
-
return
|
|
238
|
+
return (0, utils_1.nullOrUndefined)(options);
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
241
|
exports.defaultValue = defaultValue;
|
|
@@ -243,7 +243,9 @@ exports.defaultValue = defaultValue;
|
|
|
243
243
|
function notDefaultCheck(ctx, field, messageOptions, place) {
|
|
244
244
|
const { typeMap, options, currentFile } = ctx;
|
|
245
245
|
const isOptional = isOptionalProperty(field, messageOptions, options, currentFile.isProto3Syntax);
|
|
246
|
-
const maybeNotUndefinedAnd = isOptional
|
|
246
|
+
const maybeNotUndefinedAnd = isOptional
|
|
247
|
+
? `${place} !== undefined ${(0, utils_1.withAndMaybeCheckIsNotNull)(options, place)} &&`
|
|
248
|
+
: "";
|
|
247
249
|
switch (field.type) {
|
|
248
250
|
case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_DOUBLE:
|
|
249
251
|
case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_FLOAT:
|
|
@@ -330,15 +332,20 @@ function isScalar(field) {
|
|
|
330
332
|
}
|
|
331
333
|
exports.isScalar = isScalar;
|
|
332
334
|
// When useOptionals='messages', non-scalar fields are translated into optional
|
|
333
|
-
// properties.
|
|
335
|
+
// properties.
|
|
336
|
+
// When useOptionals='all', all fields are translated into
|
|
337
|
+
// optional properties, with the exception of map Entry key/values, which must
|
|
338
|
+
// always be present.
|
|
339
|
+
// When useOptionals='deprecatedOnly', all deprecated fields are translated into
|
|
334
340
|
// optional properties, with the exception of map Entry key/values, which must
|
|
335
341
|
// always be present.
|
|
336
342
|
// OneOf fields are always optional, whenever oneof=unions option not in use.
|
|
337
343
|
function isOptionalProperty(field, messageOptions, options, isProto3Syntax) {
|
|
338
344
|
const optionalMessages = options.useOptionals === true || options.useOptionals === "messages" || options.useOptionals === "all";
|
|
339
345
|
const optionalAll = options.useOptionals === "all";
|
|
346
|
+
const deprecatedOnly = options.useOptionals === "deprecatedOnly" && field.options && field.options.deprecated;
|
|
340
347
|
return ((optionalMessages && isMessage(field) && !isRepeated(field)) ||
|
|
341
|
-
(optionalAll && !(messageOptions === null || messageOptions === void 0 ? void 0 : messageOptions.mapEntry)) ||
|
|
348
|
+
((optionalAll || deprecatedOnly) && !(messageOptions === null || messageOptions === void 0 ? void 0 : messageOptions.mapEntry)) ||
|
|
342
349
|
// file is proto2, we have enabled proto2 optionals, and the field itself is optional
|
|
343
350
|
(!isProto3Syntax &&
|
|
344
351
|
field.label === ts_proto_descriptors_1.FieldDescriptorProto_Label.LABEL_OPTIONAL &&
|
|
@@ -547,7 +554,7 @@ function messageToTypeName(ctx, protoType, typeOptions = {}) {
|
|
|
547
554
|
if ((_a = typeOptions.repeated) !== null && _a !== void 0 ? _a : false) {
|
|
548
555
|
return valueType;
|
|
549
556
|
}
|
|
550
|
-
return (0, ts_poet_1.code) `${valueType} |
|
|
557
|
+
return (0, ts_poet_1.code) `${valueType} | ${(0, utils_1.nullOrUndefined)(options)}`;
|
|
551
558
|
}
|
|
552
559
|
// Look for other special prototypes like Timestamp that aren't technically wrapper types
|
|
553
560
|
if (!typeOptions.keepValueType && protoType === ".google.protobuf.Timestamp") {
|
|
@@ -579,7 +586,7 @@ exports.getEnumMethod = getEnumMethod;
|
|
|
579
586
|
function toTypeName(ctx, messageDesc, field, ensureOptional = false) {
|
|
580
587
|
function finalize(type, isOptional) {
|
|
581
588
|
if (isOptional) {
|
|
582
|
-
return (0, ts_poet_1.code) `${type} |
|
|
589
|
+
return (0, ts_poet_1.code) `${type} | ${(0, utils_1.nullOrUndefined)(ctx.options, field.proto3Optional)}`;
|
|
583
590
|
}
|
|
584
591
|
return type;
|
|
585
592
|
}
|
package/build/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.arrowFunction = exports.tryCatchBlock = exports.impProto = exports.impFile = exports.getPropertyAccessor = exports.safeAccessor = exports.getFieldName = exports.getFieldJsonName = exports.FormattedMethodDescriptor = exports.assertInstanceOf = exports.maybePrefixPackage = exports.prefixDisableLinter = exports.maybeAddComment = exports.upperFirst = exports.lowerFirst = exports.singular = exports.fail = exports.readToBuffer = exports.generateIndexFiles = exports.protoFilesToGenerate = void 0;
|
|
3
|
+
exports.withAndMaybeCheckIsNull = exports.withAndMaybeCheckIsNotNull = exports.withOrMaybeCheckIsNull = exports.withOrMaybeCheckIsNotNull = exports.maybeCheckIsNull = exports.maybeCheckIsNotNull = exports.nullOrUndefined = exports.arrowFunction = exports.tryCatchBlock = exports.impProto = exports.impFile = exports.getPropertyAccessor = exports.safeAccessor = exports.getFieldName = exports.getFieldJsonName = exports.FormattedMethodDescriptor = exports.assertInstanceOf = exports.maybePrefixPackage = exports.prefixDisableLinter = exports.maybeAddComment = exports.upperFirst = exports.lowerFirst = exports.singular = exports.fail = exports.readToBuffer = exports.generateIndexFiles = exports.protoFilesToGenerate = void 0;
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const ts_poet_1 = require("ts-poet");
|
|
6
6
|
const options_1 = require("./options");
|
|
@@ -261,3 +261,31 @@ function arrowFunction(params, body, isOneLine = true) {
|
|
|
261
261
|
return (0, ts_poet_1.code) `(${params}) => { ${body} }`;
|
|
262
262
|
}
|
|
263
263
|
exports.arrowFunction = arrowFunction;
|
|
264
|
+
function nullOrUndefined(options, hasProto3Optional = false) {
|
|
265
|
+
return options.useNullAsOptional ? `null ${hasProto3Optional ? "| undefined" : ""}` : "undefined";
|
|
266
|
+
}
|
|
267
|
+
exports.nullOrUndefined = nullOrUndefined;
|
|
268
|
+
function maybeCheckIsNotNull(options, typeName, prefix) {
|
|
269
|
+
return options.useNullAsOptional ? ` ${prefix} ${typeName} !== null` : "";
|
|
270
|
+
}
|
|
271
|
+
exports.maybeCheckIsNotNull = maybeCheckIsNotNull;
|
|
272
|
+
function maybeCheckIsNull(options, typeName, prefix) {
|
|
273
|
+
return options.useNullAsOptional ? ` ${prefix} ${typeName} === null` : "";
|
|
274
|
+
}
|
|
275
|
+
exports.maybeCheckIsNull = maybeCheckIsNull;
|
|
276
|
+
function withOrMaybeCheckIsNotNull(options, typeName) {
|
|
277
|
+
return maybeCheckIsNotNull(options, typeName, "||");
|
|
278
|
+
}
|
|
279
|
+
exports.withOrMaybeCheckIsNotNull = withOrMaybeCheckIsNotNull;
|
|
280
|
+
function withOrMaybeCheckIsNull(options, typeName) {
|
|
281
|
+
return maybeCheckIsNull(options, typeName, "||");
|
|
282
|
+
}
|
|
283
|
+
exports.withOrMaybeCheckIsNull = withOrMaybeCheckIsNull;
|
|
284
|
+
function withAndMaybeCheckIsNotNull(options, typeName) {
|
|
285
|
+
return maybeCheckIsNotNull(options, typeName, "&&");
|
|
286
|
+
}
|
|
287
|
+
exports.withAndMaybeCheckIsNotNull = withAndMaybeCheckIsNotNull;
|
|
288
|
+
function withAndMaybeCheckIsNull(options, typeName) {
|
|
289
|
+
return maybeCheckIsNotNull(options, typeName, "&&");
|
|
290
|
+
}
|
|
291
|
+
exports.withAndMaybeCheckIsNull = withAndMaybeCheckIsNull;
|