ts-proto 1.178.0 → 1.180.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 +46 -8
- package/build/enums.js +2 -4
- package/build/generate-generic-service-definition.js +3 -4
- package/build/generate-grpc-js.js +4 -7
- package/build/generate-nestjs.js +3 -6
- package/build/generate-nice-grpc.js +2 -4
- package/build/generate-services.js +2 -4
- package/build/generate-struct-wrappers.js +26 -0
- package/build/main.js +32 -27
- package/build/options.d.ts +3 -1
- package/build/options.js +2 -0
- package/build/schema.js +1 -2
- package/build/types.js +15 -20
- package/build/utils.d.ts +1 -0
- package/build/utils.js +6 -3
- package/package.json +1 -1
package/README.markdown
CHANGED
|
@@ -551,6 +551,8 @@ Generated code will be placed in the Gradle build directory.
|
|
|
551
551
|
|
|
552
552
|
- With `--ts_proto_opt=comments=false`, comments won't be copied from the proto files to the generated code.
|
|
553
553
|
|
|
554
|
+
- With `--ts_proto_opt=bigIntLiteral=false`, the generated code will use `BigInt("0")` instead of `0n` for BigInt literals. BigInt literals aren't supported by TypeScript when the "target" compiler option set to something older than "ES2020".
|
|
555
|
+
|
|
554
556
|
- 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:
|
|
555
557
|
|
|
556
558
|
```protobuf
|
|
@@ -603,7 +605,7 @@ export interface User {
|
|
|
603
605
|
}
|
|
604
606
|
```
|
|
605
607
|
|
|
606
|
-
- With `--ts_proto_opt=noDefaultsForOptionals=true`, `undefined` primitive values will not be defaulted as per the protobuf spec. Additionally unlike the standard behavior, when a field is set to it's standard default value, it *will* be encoded allowing it to be sent over the wire and distinguished from undefined values. For example if a message does not set a boolean value, ordinarily this would be defaulted to `false` which is different to it being undefined.
|
|
608
|
+
- With `--ts_proto_opt=noDefaultsForOptionals=true`, `undefined` primitive values will not be defaulted as per the protobuf spec. Additionally unlike the standard behavior, when a field is set to it's standard default value, it *will* be encoded allowing it to be sent over the wire and distinguished from undefined values. For example if a message does not set a boolean value, ordinarily this would be defaulted to `false` which is different to it being undefined.
|
|
607
609
|
|
|
608
610
|
This option allows the library to act in a compatible way with the [Wire implementation](https://square.github.io/wire/) maintained and used by Square/Block. Note: this option should only be used in combination with other client/server code generated using Wire or ts-proto with this option enabled.
|
|
609
611
|
|
|
@@ -752,7 +754,7 @@ ts-protoc --ts_proto_out=./output -I=./protos ./protoc/*.proto
|
|
|
752
754
|
# Todo
|
|
753
755
|
|
|
754
756
|
- Support the string-based encoding of duration in `fromJSON`/`toJSON`
|
|
755
|
-
- Make `oneof=unions` the default behavior in 2.0
|
|
757
|
+
- Make `oneof=unions-value` the default behavior in 2.0
|
|
756
758
|
- Probably change `forceLong` default in 2.0, should default to `forceLong=long`
|
|
757
759
|
- Make `esModuleInterop=true` the default in 2.0
|
|
758
760
|
|
|
@@ -770,11 +772,11 @@ Will generate a `Foo` type with two fields: `field_a: string | undefined;` and `
|
|
|
770
772
|
|
|
771
773
|
With this output, you'll have to check both `if object.field_a` and `if object.field_b`, and if you set one, you'll have to remember to unset the other.
|
|
772
774
|
|
|
773
|
-
Instead, we recommend using the `oneof=unions` option, which will change the output to be an Abstract Data Type/ADT like:
|
|
775
|
+
Instead, we recommend using the `oneof=unions-value` option, which will change the output to be an Abstract Data Type/ADT like:
|
|
774
776
|
|
|
775
777
|
```typescript
|
|
776
778
|
interface YourMessage {
|
|
777
|
-
eitherField?: { $case: "field_a";
|
|
779
|
+
eitherField?: { $case: "field_a"; value: string } | { $case: "field_b"; value: string };
|
|
778
780
|
}
|
|
779
781
|
```
|
|
780
782
|
|
|
@@ -782,11 +784,21 @@ As this will automatically enforce only one of `field_a` or `field_b` "being set
|
|
|
782
784
|
|
|
783
785
|
(Note that `eitherField` is optional b/c `oneof` in Protobuf means "at most one field" is set, and does not mean one of the fields _must_ be set.)
|
|
784
786
|
|
|
785
|
-
In ts-proto's currently-unscheduled 2.x release, `oneof=unions` will become the default behavior.
|
|
787
|
+
In ts-proto's currently-unscheduled 2.x release, `oneof=unions-value` will become the default behavior.
|
|
788
|
+
|
|
789
|
+
There is also a `oneof=unions` option, which generates a union where the field names are included in each option:
|
|
790
|
+
|
|
791
|
+
```typescript
|
|
792
|
+
interface YourMessage {
|
|
793
|
+
eitherField?: { $case: "field_a"; field_a: string } | { $case: "field_b"; field_b: string };
|
|
794
|
+
}
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
This is no longer recommended as it can be difficult to write code and types to handle multiple oneof options:
|
|
786
798
|
|
|
787
799
|
## OneOf Type Helpers
|
|
788
800
|
|
|
789
|
-
The following helper types may make it easier to work with the types generated from `oneof=unions`:
|
|
801
|
+
The following helper types may make it easier to work with the types generated from `oneof=unions`, though they are generally not needed if you use `oneof=unions-value`:
|
|
790
802
|
|
|
791
803
|
```ts
|
|
792
804
|
/** Extracts all the case names from a oneOf field. */
|
|
@@ -797,19 +809,45 @@ type OneOfValues<T> = T extends { $case: infer U extends string; [key: string]:
|
|
|
797
809
|
|
|
798
810
|
/** Extracts the specific type of a oneOf case based on its field name */
|
|
799
811
|
type OneOfCase<T, K extends OneOfCases<T>> = T extends {
|
|
812
|
+
$case: K;
|
|
813
|
+
[key: string]: unknown;
|
|
814
|
+
}
|
|
815
|
+
? T
|
|
816
|
+
: never;
|
|
817
|
+
|
|
818
|
+
/** Extracts the specific type of a value type from a oneOf field */
|
|
819
|
+
type OneOfValue<T, K extends OneOfCases<T>> = T extends {
|
|
800
820
|
$case: infer U extends K;
|
|
801
821
|
[key: string]: unknown;
|
|
802
822
|
}
|
|
803
823
|
? T[U]
|
|
804
824
|
: never;
|
|
825
|
+
```
|
|
805
826
|
|
|
806
|
-
|
|
807
|
-
|
|
827
|
+
For comparison, the equivalents for `oneof=unions-value`:
|
|
828
|
+
|
|
829
|
+
```ts
|
|
830
|
+
/** Extracts all the case names from a oneOf field. */
|
|
831
|
+
type OneOfCases<T> = T['$case'];
|
|
832
|
+
|
|
833
|
+
/** Extracts a union of all the value types from a oneOf field */
|
|
834
|
+
type OneOfValues<T> = T['value'];
|
|
835
|
+
|
|
836
|
+
/** Extracts the specific type of a oneOf case based on its field name */
|
|
837
|
+
type OneOfCase<T, K extends OneOfCases<T>> = T extends {
|
|
808
838
|
$case: K;
|
|
809
839
|
[key: string]: unknown;
|
|
810
840
|
}
|
|
811
841
|
? T
|
|
812
842
|
: never;
|
|
843
|
+
|
|
844
|
+
/** Extracts the specific type of a value type from a oneOf field */
|
|
845
|
+
type OneOfValue<T, K extends OneOfCases<T>> = T extends {
|
|
846
|
+
$case: infer U extends K;
|
|
847
|
+
value: unknown;
|
|
848
|
+
}
|
|
849
|
+
? T[U]
|
|
850
|
+
: never;
|
|
813
851
|
```
|
|
814
852
|
|
|
815
853
|
# Default values and unset fields
|
package/build/enums.js
CHANGED
|
@@ -7,11 +7,10 @@ const case_1 = require("./case");
|
|
|
7
7
|
const sourceInfo_1 = require("./sourceInfo");
|
|
8
8
|
// Output the `enum { Foo, A = 0, B = 1 }`
|
|
9
9
|
function generateEnum(ctx, fullName, enumDesc, sourceInfo) {
|
|
10
|
-
var _a;
|
|
11
10
|
const { options } = ctx;
|
|
12
11
|
const chunks = [];
|
|
13
12
|
let unrecognizedEnum = { present: false };
|
|
14
|
-
(0, utils_1.maybeAddComment)(options, sourceInfo, chunks,
|
|
13
|
+
(0, utils_1.maybeAddComment)(options, sourceInfo, chunks, enumDesc.options?.deprecated);
|
|
15
14
|
if (options.enumsAsLiterals) {
|
|
16
15
|
chunks.push((0, ts_poet_1.code) `export const ${(0, ts_poet_1.def)(fullName)} = {`);
|
|
17
16
|
}
|
|
@@ -20,14 +19,13 @@ function generateEnum(ctx, fullName, enumDesc, sourceInfo) {
|
|
|
20
19
|
}
|
|
21
20
|
const delimiter = options.enumsAsLiterals ? ":" : "=";
|
|
22
21
|
enumDesc.value.forEach((valueDesc, index) => {
|
|
23
|
-
var _a;
|
|
24
22
|
const info = sourceInfo.lookup(sourceInfo_1.Fields.enum.value, index);
|
|
25
23
|
const valueName = getValueName(ctx, fullName, valueDesc);
|
|
26
24
|
const memberName = getMemberName(ctx, enumDesc, valueDesc);
|
|
27
25
|
if (valueDesc.number === options.unrecognizedEnumValue) {
|
|
28
26
|
unrecognizedEnum = { present: true, name: memberName };
|
|
29
27
|
}
|
|
30
|
-
(0, utils_1.maybeAddComment)(options, info, chunks,
|
|
28
|
+
(0, utils_1.maybeAddComment)(options, info, chunks, valueDesc.options?.deprecated, `${memberName} - `);
|
|
31
29
|
chunks.push((0, ts_poet_1.code) `${memberName} ${delimiter} ${options.stringEnums ? `"${valueName}"` : valueDesc.number.toString()},`);
|
|
32
30
|
});
|
|
33
31
|
if (options.unrecognizedEnum && !unrecognizedEnum.present) {
|
|
@@ -11,9 +11,8 @@ const utils_1 = require("./utils");
|
|
|
11
11
|
* Generates a framework-agnostic service descriptor.
|
|
12
12
|
*/
|
|
13
13
|
function generateGenericServiceDefinition(ctx, fileDesc, sourceInfo, serviceDesc) {
|
|
14
|
-
var _a, _b, _c;
|
|
15
14
|
const chunks = [];
|
|
16
|
-
(0, utils_1.maybeAddComment)(ctx.options, sourceInfo, chunks,
|
|
15
|
+
(0, utils_1.maybeAddComment)(ctx.options, sourceInfo, chunks, serviceDesc.options?.deprecated);
|
|
17
16
|
// Service definition type
|
|
18
17
|
const name = (0, ts_poet_1.def)(`${serviceDesc.name}Definition`);
|
|
19
18
|
chunks.push((0, ts_poet_1.code) `
|
|
@@ -23,7 +22,7 @@ function generateGenericServiceDefinition(ctx, fileDesc, sourceInfo, serviceDesc
|
|
|
23
22
|
chunks.push((0, ts_poet_1.code) `
|
|
24
23
|
export const ${name} = {
|
|
25
24
|
`);
|
|
26
|
-
|
|
25
|
+
serviceDesc.options?.uninterpretedOption;
|
|
27
26
|
chunks.push((0, ts_poet_1.code) `
|
|
28
27
|
name: '${serviceDesc.name}',
|
|
29
28
|
fullName: '${(0, utils_1.maybePrefixPackage)(fileDesc, serviceDesc.name)}',
|
|
@@ -31,7 +30,7 @@ function generateGenericServiceDefinition(ctx, fileDesc, sourceInfo, serviceDesc
|
|
|
31
30
|
`);
|
|
32
31
|
for (const [index, methodDesc] of serviceDesc.method.entries()) {
|
|
33
32
|
const info = sourceInfo.lookup(sourceInfo_1.Fields.service.method, index);
|
|
34
|
-
(0, utils_1.maybeAddComment)(ctx.options, info, chunks,
|
|
33
|
+
(0, utils_1.maybeAddComment)(ctx.options, info, chunks, methodDesc.options?.deprecated);
|
|
35
34
|
chunks.push((0, ts_poet_1.code) `
|
|
36
35
|
${(0, case_1.uncapitalize)(methodDesc.name)}: ${generateMethodDefinition(ctx, methodDesc)},
|
|
37
36
|
`);
|
|
@@ -39,9 +39,8 @@ function generateGrpcJsService(ctx, fileDesc, sourceInfo, serviceDesc) {
|
|
|
39
39
|
}
|
|
40
40
|
exports.generateGrpcJsService = generateGrpcJsService;
|
|
41
41
|
function generateServiceDefinition(ctx, fileDesc, sourceInfo, serviceDesc) {
|
|
42
|
-
var _a, _b;
|
|
43
42
|
const chunks = [];
|
|
44
|
-
(0, utils_1.maybeAddComment)(ctx.options, sourceInfo, chunks,
|
|
43
|
+
(0, utils_1.maybeAddComment)(ctx.options, sourceInfo, chunks, serviceDesc.options?.deprecated);
|
|
45
44
|
// Service definition type
|
|
46
45
|
const name = (0, ts_poet_1.def)(`${serviceDesc.name}Service`);
|
|
47
46
|
chunks.push((0, ts_poet_1.code) `
|
|
@@ -56,7 +55,7 @@ function generateServiceDefinition(ctx, fileDesc, sourceInfo, serviceDesc) {
|
|
|
56
55
|
const inputType = (0, types_1.messageToTypeName)(ctx, methodDesc.inputType);
|
|
57
56
|
const outputType = (0, types_1.messageToTypeName)(ctx, methodDesc.outputType);
|
|
58
57
|
const info = sourceInfo.lookup(sourceInfo_1.Fields.service.method, index);
|
|
59
|
-
(0, utils_1.maybeAddComment)(ctx.options, info, chunks,
|
|
58
|
+
(0, utils_1.maybeAddComment)(ctx.options, info, chunks, methodDesc.options?.deprecated);
|
|
60
59
|
const inputEncoder = (0, encode_1.generateEncoder)(ctx, methodDesc.inputType);
|
|
61
60
|
const outputEncoder = (0, encode_1.generateEncoder)(ctx, methodDesc.outputType);
|
|
62
61
|
const inputDecoder = (0, encode_1.generateDecoder)(ctx, methodDesc.inputType);
|
|
@@ -79,7 +78,6 @@ function generateServiceDefinition(ctx, fileDesc, sourceInfo, serviceDesc) {
|
|
|
79
78
|
return (0, ts_poet_1.joinCode)(chunks, { on: "\n" });
|
|
80
79
|
}
|
|
81
80
|
function generateServerStub(ctx, sourceInfo, serviceDesc) {
|
|
82
|
-
var _a;
|
|
83
81
|
const chunks = [];
|
|
84
82
|
chunks.push((0, ts_poet_1.code) `export interface ${(0, ts_poet_1.def)(`${serviceDesc.name}Server`)} extends ${UntypedServiceImplementation} {`);
|
|
85
83
|
for (const [index, methodDesc] of serviceDesc.method.entries()) {
|
|
@@ -87,7 +85,7 @@ function generateServerStub(ctx, sourceInfo, serviceDesc) {
|
|
|
87
85
|
const inputType = (0, types_1.messageToTypeName)(ctx, methodDesc.inputType);
|
|
88
86
|
const outputType = (0, types_1.messageToTypeName)(ctx, methodDesc.outputType);
|
|
89
87
|
const info = sourceInfo.lookup(sourceInfo_1.Fields.service.method, index);
|
|
90
|
-
(0, utils_1.maybeAddComment)(ctx.options, info, chunks,
|
|
88
|
+
(0, utils_1.maybeAddComment)(ctx.options, info, chunks, methodDesc.options?.deprecated);
|
|
91
89
|
const callType = methodDesc.clientStreaming
|
|
92
90
|
? methodDesc.serverStreaming
|
|
93
91
|
? handleBidiStreamingCall
|
|
@@ -103,7 +101,6 @@ function generateServerStub(ctx, sourceInfo, serviceDesc) {
|
|
|
103
101
|
return (0, ts_poet_1.joinCode)(chunks, { on: "\n" });
|
|
104
102
|
}
|
|
105
103
|
function generateClientStub(ctx, sourceInfo, serviceDesc) {
|
|
106
|
-
var _a;
|
|
107
104
|
const chunks = [];
|
|
108
105
|
chunks.push((0, ts_poet_1.code) `export interface ${(0, ts_poet_1.def)(`${serviceDesc.name}Client`)} extends ${Client} {`);
|
|
109
106
|
for (const [index, methodDesc] of serviceDesc.method.entries()) {
|
|
@@ -111,7 +108,7 @@ function generateClientStub(ctx, sourceInfo, serviceDesc) {
|
|
|
111
108
|
const inputType = (0, types_1.messageToTypeName)(ctx, methodDesc.inputType);
|
|
112
109
|
const outputType = (0, types_1.messageToTypeName)(ctx, methodDesc.outputType);
|
|
113
110
|
const info = sourceInfo.lookup(sourceInfo_1.Fields.service.method, index);
|
|
114
|
-
(0, utils_1.maybeAddComment)(ctx.options, info, chunks,
|
|
111
|
+
(0, utils_1.maybeAddComment)(ctx.options, info, chunks, methodDesc.options?.deprecated);
|
|
115
112
|
const responseCallback = (0, ts_poet_1.code) `(error: ${ServiceError} | null, response: ${outputType}) => void`;
|
|
116
113
|
if (methodDesc.clientStreaming) {
|
|
117
114
|
if (methodDesc.serverStreaming) {
|
package/build/generate-nestjs.js
CHANGED
|
@@ -7,20 +7,18 @@ const sourceInfo_1 = require("./sourceInfo");
|
|
|
7
7
|
const main_1 = require("./main");
|
|
8
8
|
const utils_1 = require("./utils");
|
|
9
9
|
function generateNestjsServiceController(ctx, fileDesc, sourceInfo, serviceDesc) {
|
|
10
|
-
var _a;
|
|
11
10
|
const { options } = ctx;
|
|
12
11
|
const chunks = [];
|
|
13
12
|
const Metadata = (0, ts_poet_1.imp)("Metadata@@grpc/grpc-js");
|
|
14
|
-
(0, utils_1.maybeAddComment)(options, sourceInfo, chunks,
|
|
13
|
+
(0, utils_1.maybeAddComment)(options, sourceInfo, chunks, serviceDesc.options?.deprecated);
|
|
15
14
|
const t = options.context ? `<${main_1.contextTypeVar}>` : "";
|
|
16
15
|
chunks.push((0, ts_poet_1.code) `
|
|
17
16
|
export interface ${serviceDesc.name}Controller${t} {
|
|
18
17
|
`);
|
|
19
18
|
serviceDesc.method.forEach((methodDesc, index) => {
|
|
20
|
-
var _a;
|
|
21
19
|
(0, utils_1.assertInstanceOf)(methodDesc, utils_1.FormattedMethodDescriptor);
|
|
22
20
|
const info = sourceInfo.lookup(sourceInfo_1.Fields.service.method, index);
|
|
23
|
-
(0, utils_1.maybeAddComment)(options, info, chunks,
|
|
21
|
+
(0, utils_1.maybeAddComment)(options, info, chunks, serviceDesc.options?.deprecated);
|
|
24
22
|
const params = [];
|
|
25
23
|
if (options.context) {
|
|
26
24
|
params.push((0, ts_poet_1.code) `ctx: Context`);
|
|
@@ -80,7 +78,6 @@ function generateNestjsServiceClient(ctx, fileDesc, sourceInfo, serviceDesc) {
|
|
|
80
78
|
export interface ${serviceDesc.name}Client${t} {
|
|
81
79
|
`);
|
|
82
80
|
serviceDesc.method.forEach((methodDesc, index) => {
|
|
83
|
-
var _a;
|
|
84
81
|
(0, utils_1.assertInstanceOf)(methodDesc, utils_1.FormattedMethodDescriptor);
|
|
85
82
|
const params = [];
|
|
86
83
|
if (options.context) {
|
|
@@ -98,7 +95,7 @@ function generateNestjsServiceClient(ctx, fileDesc, sourceInfo, serviceDesc) {
|
|
|
98
95
|
// Return observable since nestjs client always returns an Observable
|
|
99
96
|
const returns = (0, types_1.responseObservable)(ctx, methodDesc);
|
|
100
97
|
const info = sourceInfo.lookup(sourceInfo_1.Fields.service.method, index);
|
|
101
|
-
(0, utils_1.maybeAddComment)(options, info, chunks,
|
|
98
|
+
(0, utils_1.maybeAddComment)(options, info, chunks, methodDesc.options?.deprecated);
|
|
102
99
|
chunks.push((0, ts_poet_1.code) `
|
|
103
100
|
${methodDesc.formattedName}(
|
|
104
101
|
${(0, ts_poet_1.joinCode)(params, { on: "," })}
|
|
@@ -19,7 +19,6 @@ function generateNiceGrpcService(ctx, fileDesc, sourceInfo, serviceDesc) {
|
|
|
19
19
|
}
|
|
20
20
|
exports.generateNiceGrpcService = generateNiceGrpcService;
|
|
21
21
|
function generateServerStub(ctx, sourceInfo, serviceDesc) {
|
|
22
|
-
var _a;
|
|
23
22
|
const chunks = [];
|
|
24
23
|
const maybeSuffix = serviceDesc.name.endsWith("Service") ? "" : "Service";
|
|
25
24
|
chunks.push((0, ts_poet_1.code) `export interface ${(0, ts_poet_1.def)(`${serviceDesc.name}${maybeSuffix}Implementation`)}<CallContextExt = {}> {`);
|
|
@@ -32,7 +31,7 @@ function generateServerStub(ctx, sourceInfo, serviceDesc) {
|
|
|
32
31
|
}
|
|
33
32
|
const ServerStreamingMethodResult = ctx.utils.NiceGrpcServerStreamingMethodResult;
|
|
34
33
|
const info = sourceInfo.lookup(sourceInfo_1.Fields.service.method, index);
|
|
35
|
-
(0, utils_1.maybeAddComment)(ctx.options, info, chunks,
|
|
34
|
+
(0, utils_1.maybeAddComment)(ctx.options, info, chunks, methodDesc.options?.deprecated);
|
|
36
35
|
if (methodDesc.clientStreaming) {
|
|
37
36
|
if (methodDesc.serverStreaming) {
|
|
38
37
|
// bidi streaming
|
|
@@ -78,7 +77,6 @@ function generateServerStub(ctx, sourceInfo, serviceDesc) {
|
|
|
78
77
|
return (0, ts_poet_1.joinCode)(chunks, { on: "\n" });
|
|
79
78
|
}
|
|
80
79
|
function generateClientStub(ctx, sourceInfo, serviceDesc) {
|
|
81
|
-
var _a;
|
|
82
80
|
const chunks = [];
|
|
83
81
|
chunks.push((0, ts_poet_1.code) `export interface ${(0, ts_poet_1.def)(`${serviceDesc.name}Client`)}<CallOptionsExt = {}> {`);
|
|
84
82
|
for (const [index, methodDesc] of serviceDesc.method.entries()) {
|
|
@@ -89,7 +87,7 @@ function generateClientStub(ctx, sourceInfo, serviceDesc) {
|
|
|
89
87
|
}
|
|
90
88
|
const outputType = (0, types_1.messageToTypeName)(ctx, methodDesc.outputType, { keepValueType: true });
|
|
91
89
|
const info = sourceInfo.lookup(sourceInfo_1.Fields.service.method, index);
|
|
92
|
-
(0, utils_1.maybeAddComment)(ctx.options, info, chunks,
|
|
90
|
+
(0, utils_1.maybeAddComment)(ctx.options, info, chunks, methodDesc.options?.deprecated);
|
|
93
91
|
if (methodDesc.clientStreaming) {
|
|
94
92
|
if (methodDesc.serverStreaming) {
|
|
95
93
|
// bidi streaming
|
|
@@ -17,17 +17,15 @@ const main_1 = require("./main");
|
|
|
17
17
|
* vs. server-side code/interfaces are handled separately.
|
|
18
18
|
*/
|
|
19
19
|
function generateService(ctx, fileDesc, sourceInfo, serviceDesc) {
|
|
20
|
-
var _a;
|
|
21
20
|
const { options } = ctx;
|
|
22
21
|
const chunks = [];
|
|
23
|
-
(0, utils_1.maybeAddComment)(options, sourceInfo, chunks,
|
|
22
|
+
(0, utils_1.maybeAddComment)(options, sourceInfo, chunks, serviceDesc.options?.deprecated);
|
|
24
23
|
const maybeTypeVar = options.context ? `<${main_1.contextTypeVar}>` : "";
|
|
25
24
|
chunks.push((0, ts_poet_1.code) `export interface ${(0, ts_poet_1.def)(serviceDesc.name)}${maybeTypeVar} {`);
|
|
26
25
|
serviceDesc.method.forEach((methodDesc, index) => {
|
|
27
|
-
var _a;
|
|
28
26
|
(0, utils_1.assertInstanceOf)(methodDesc, utils_1.FormattedMethodDescriptor);
|
|
29
27
|
const info = sourceInfo.lookup(sourceInfo_1.Fields.service.method, index);
|
|
30
|
-
(0, utils_1.maybeAddComment)(options, info, chunks,
|
|
28
|
+
(0, utils_1.maybeAddComment)(options, info, chunks, methodDesc.options?.deprecated);
|
|
31
29
|
const params = [];
|
|
32
30
|
if (options.context) {
|
|
33
31
|
params.push((0, ts_poet_1.code) `ctx: Context`);
|
|
@@ -193,6 +193,27 @@ function generateWrapShallow(ctx, fullProtoTypeName, fieldNames) {
|
|
|
193
193
|
throw new ${ctx.utils.globalThis}.Error('Unsupported any value type: ' + typeof value);
|
|
194
194
|
}
|
|
195
195
|
return result;
|
|
196
|
+
}`);
|
|
197
|
+
}
|
|
198
|
+
else if (ctx.options.oneof === options_1.OneofOption.UNIONS_VALUE) {
|
|
199
|
+
chunks.push((0, ts_poet_1.code) `wrap(value: any): Value {
|
|
200
|
+
const result = createBaseValue()${maybeAsAny(ctx.options)};
|
|
201
|
+
if (value === null) {
|
|
202
|
+
result.kind = {$case: '${fieldNames.nullValue}', value };
|
|
203
|
+
} else if (typeof value === 'boolean') {
|
|
204
|
+
result.kind = {$case: '${fieldNames.boolValue}', value };
|
|
205
|
+
} else if (typeof value === 'number') {
|
|
206
|
+
result.kind = {$case: '${fieldNames.numberValue}', value };
|
|
207
|
+
} else if (typeof value === 'string') {
|
|
208
|
+
result.kind = {$case: '${fieldNames.stringValue}', value };
|
|
209
|
+
} else if (${ctx.utils.globalThis}.Array.isArray(value)) {
|
|
210
|
+
result.kind = {$case: '${fieldNames.listValue}', value };
|
|
211
|
+
} else if (typeof value === 'object') {
|
|
212
|
+
result.kind = {$case: '${fieldNames.structValue}', value };
|
|
213
|
+
} else if (typeof value !== 'undefined') {
|
|
214
|
+
throw new ${ctx.utils.globalThis}.Error('Unsupported any value type: ' + typeof value);
|
|
215
|
+
}
|
|
216
|
+
return result;
|
|
196
217
|
}`);
|
|
197
218
|
}
|
|
198
219
|
else {
|
|
@@ -284,6 +305,11 @@ function generateUnwrapShallow(ctx, fullProtoTypeName, fieldNames) {
|
|
|
284
305
|
} else {
|
|
285
306
|
return undefined;
|
|
286
307
|
}
|
|
308
|
+
}`);
|
|
309
|
+
}
|
|
310
|
+
else if (ctx.options.oneof === options_1.OneofOption.UNIONS_VALUE) {
|
|
311
|
+
chunks.push((0, ts_poet_1.code) `unwrap(message: Value): string | number | boolean | Object | null | Array<any> | undefined {
|
|
312
|
+
return message.kind?.value;
|
|
287
313
|
}`);
|
|
288
314
|
}
|
|
289
315
|
else {
|
package/build/main.js
CHANGED
|
@@ -21,7 +21,6 @@ const types_1 = require("./types");
|
|
|
21
21
|
const utils_1 = require("./utils");
|
|
22
22
|
const visit_1 = require("./visit");
|
|
23
23
|
function generateFile(ctx, fileDesc) {
|
|
24
|
-
var _a;
|
|
25
24
|
const { options, utils } = ctx;
|
|
26
25
|
if (options.useOptionals === false) {
|
|
27
26
|
console.warn("ts-proto: Passing useOptionals as a boolean option is deprecated and will be removed in a future version. Please pass the string 'none' instead of false.");
|
|
@@ -52,7 +51,7 @@ function generateFile(ctx, fileDesc) {
|
|
|
52
51
|
// Syntax, unlike most fields, is not repeated and thus does not use an index
|
|
53
52
|
const sourceInfo = sourceInfo_1.default.fromDescriptor(fileDesc);
|
|
54
53
|
const headerComment = sourceInfo.lookup(sourceInfo_1.Fields.file.syntax, undefined);
|
|
55
|
-
(0, utils_1.maybeAddComment)(options, headerComment, chunks,
|
|
54
|
+
(0, utils_1.maybeAddComment)(options, headerComment, chunks, fileDesc.options?.deprecated);
|
|
56
55
|
// Apply formatting to methods here, so they propagate globally
|
|
57
56
|
for (let svc of fileDesc.service) {
|
|
58
57
|
for (let i = 0; i < svc.method.length; i++) {
|
|
@@ -449,6 +448,12 @@ function makeDeepPartial(options, longs) {
|
|
|
449
448
|
? { [K in keyof Omit<T, '$case'>]?: DeepPartial<T[K]> } & { ${maybeReadonly(options)}$case: T['$case'] }
|
|
450
449
|
`;
|
|
451
450
|
}
|
|
451
|
+
else if (options.oneof === options_1.OneofOption.UNIONS_VALUE) {
|
|
452
|
+
oneofCase = `
|
|
453
|
+
: T extends { ${maybeReadonly(options)}$case: string; value: unknown; }
|
|
454
|
+
? { ${maybeReadonly(options)}$case: T['$case']; value?: DeepPartial<T['value']>; }
|
|
455
|
+
`;
|
|
456
|
+
}
|
|
452
457
|
const maybeExport = options.exportCommonSymbols ? "export" : "";
|
|
453
458
|
// Allow passing longs as numbers or strings, nad we'll convert them
|
|
454
459
|
const maybeLong = options.forceLong === options_1.LongOption.LONG ? (0, ts_poet_1.code) ` : T extends ${longs.Long} ? string | number | Long ` : "";
|
|
@@ -673,10 +678,9 @@ function makeAssertionUtils(bytes) {
|
|
|
673
678
|
}
|
|
674
679
|
// Create the interface with properties
|
|
675
680
|
function generateInterfaceDeclaration(ctx, fullName, messageDesc, sourceInfo, fullTypeName) {
|
|
676
|
-
var _a;
|
|
677
681
|
const { options, currentFile } = ctx;
|
|
678
682
|
const chunks = [];
|
|
679
|
-
(0, utils_1.maybeAddComment)(options, sourceInfo, chunks,
|
|
683
|
+
(0, utils_1.maybeAddComment)(options, sourceInfo, chunks, messageDesc.options?.deprecated);
|
|
680
684
|
// interface name should be defined to avoid import collisions
|
|
681
685
|
chunks.push((0, ts_poet_1.code) `export interface ${(0, ts_poet_1.def)(fullName)} {`);
|
|
682
686
|
if ((0, options_1.addTypeToMessages)(options)) {
|
|
@@ -685,7 +689,6 @@ function generateInterfaceDeclaration(ctx, fullName, messageDesc, sourceInfo, fu
|
|
|
685
689
|
// When oneof=unions, we generate a single property with an ADT per `oneof` clause.
|
|
686
690
|
const processedOneofs = new Set();
|
|
687
691
|
messageDesc.field.forEach((fieldDesc, index) => {
|
|
688
|
-
var _a;
|
|
689
692
|
if ((0, types_1.isWithinOneOfThatShouldBeUnion)(options, fieldDesc)) {
|
|
690
693
|
const { oneofIndex } = fieldDesc;
|
|
691
694
|
if (!processedOneofs.has(oneofIndex)) {
|
|
@@ -695,7 +698,7 @@ function generateInterfaceDeclaration(ctx, fullName, messageDesc, sourceInfo, fu
|
|
|
695
698
|
return;
|
|
696
699
|
}
|
|
697
700
|
const info = sourceInfo.lookup(sourceInfo_1.Fields.message.field, index);
|
|
698
|
-
(0, utils_1.maybeAddComment)(options, info, chunks,
|
|
701
|
+
(0, utils_1.maybeAddComment)(options, info, chunks, fieldDesc.options?.deprecated);
|
|
699
702
|
const fieldKey = (0, utils_1.safeAccessor)((0, utils_1.getFieldName)(fieldDesc, options));
|
|
700
703
|
const isOptional = (0, types_1.isOptionalProperty)(fieldDesc, messageDesc.options, options, currentFile.isProto3Syntax);
|
|
701
704
|
const type = (0, types_1.toTypeName)(ctx, messageDesc, fieldDesc, isOptional);
|
|
@@ -714,7 +717,8 @@ function generateOneofProperty(ctx, messageDesc, oneofIndex, sourceInfo) {
|
|
|
714
717
|
const unionType = (0, ts_poet_1.joinCode)(fields.map((f) => {
|
|
715
718
|
let fieldName = (0, case_1.maybeSnakeToCamel)(f.name, options);
|
|
716
719
|
let typeName = (0, types_1.toTypeName)(ctx, messageDesc, f);
|
|
717
|
-
|
|
720
|
+
let valueName = (0, utils_1.oneofValueName)(fieldName, options);
|
|
721
|
+
return (0, ts_poet_1.code) `{ ${mbReadonly}$case: '${fieldName}', ${mbReadonly}${valueName}: ${typeName} }`;
|
|
718
722
|
}), { on: " | " });
|
|
719
723
|
const name = (0, case_1.maybeSnakeToCamel)(messageDesc.oneofDecl[oneofIndex].name, options);
|
|
720
724
|
return (0, ts_poet_1.code) `${mbReadonly}${name}?: ${unionType} | ${(0, utils_1.nullOrUndefined)(options)},`;
|
|
@@ -982,9 +986,10 @@ function generateDecode(ctx, fullName, messageDesc) {
|
|
|
982
986
|
const oneofNameWithMessage = options.useJsonName
|
|
983
987
|
? messageProperty
|
|
984
988
|
: (0, utils_1.getPropertyAccessor)("message", (0, case_1.maybeSnakeToCamel)(messageDesc.oneofDecl[field.oneofIndex].name, options));
|
|
989
|
+
const valueName = (0, utils_1.oneofValueName)(fieldName, options);
|
|
985
990
|
chunks.push((0, ts_poet_1.code) `
|
|
986
991
|
${tagCheck}
|
|
987
|
-
${oneofNameWithMessage} = { $case: '${fieldName}', ${
|
|
992
|
+
${oneofNameWithMessage} = { $case: '${fieldName}', ${valueName}: ${readSnippet} };
|
|
988
993
|
`);
|
|
989
994
|
}
|
|
990
995
|
else {
|
|
@@ -1054,13 +1059,13 @@ function getEncodeWriteSnippet(ctx, field) {
|
|
|
1054
1059
|
case "int64":
|
|
1055
1060
|
case "sint64":
|
|
1056
1061
|
case "sfixed64":
|
|
1057
|
-
return (place, placeAlt) => (0, ts_poet_1.code) `if (BigInt.asIntN(64, ${place}) !== ${placeAlt
|
|
1062
|
+
return (place, placeAlt) => (0, ts_poet_1.code) `if (BigInt.asIntN(64, ${place}) !== ${placeAlt ?? place}) {
|
|
1058
1063
|
throw new ${utils.globalThis}.Error('value provided for field ${place} of type ${fieldType} too large');
|
|
1059
1064
|
}
|
|
1060
1065
|
writer.uint32(${tag}).${(0, types_1.toReaderCall)(field)}(${place}.toString())`;
|
|
1061
1066
|
case "uint64":
|
|
1062
1067
|
case "fixed64":
|
|
1063
|
-
return (place, placeAlt) => (0, ts_poet_1.code) `if (BigInt.asUintN(64, ${place}) !== ${placeAlt
|
|
1068
|
+
return (place, placeAlt) => (0, ts_poet_1.code) `if (BigInt.asUintN(64, ${place}) !== ${placeAlt ?? place}) {
|
|
1064
1069
|
throw new ${utils.globalThis}.Error('value provided for field ${place} of type ${fieldType} too large');
|
|
1065
1070
|
}
|
|
1066
1071
|
writer.uint32(${tag}).${(0, types_1.toReaderCall)(field)}(${place}.toString())`;
|
|
@@ -1270,8 +1275,9 @@ function generateEncode(ctx, fullName, messageDesc) {
|
|
|
1270
1275
|
for (const oneOfField of oneOfFieldsDict[field.oneofIndex]) {
|
|
1271
1276
|
const writeSnippet = getEncodeWriteSnippet(ctx, oneOfField);
|
|
1272
1277
|
const oneOfFieldName = (0, case_1.maybeSnakeToCamel)(oneOfField.name, ctx.options);
|
|
1278
|
+
const valueName = (0, utils_1.oneofValueName)(oneOfFieldName, ctx.options);
|
|
1273
1279
|
chunks.push((0, ts_poet_1.code) `case "${oneOfFieldName}":
|
|
1274
|
-
${writeSnippet(`${oneofNameWithMessage}.${
|
|
1280
|
+
${writeSnippet(`${oneofNameWithMessage}.${valueName}`)};
|
|
1275
1281
|
break;`);
|
|
1276
1282
|
}
|
|
1277
1283
|
chunks.push((0, ts_poet_1.code) `}`);
|
|
@@ -1385,11 +1391,10 @@ function generateGetExtension(ctx, fullName) {
|
|
|
1385
1391
|
`;
|
|
1386
1392
|
}
|
|
1387
1393
|
function generateExtension(ctx, message, extension) {
|
|
1388
|
-
var _a;
|
|
1389
1394
|
const type = (0, types_1.toTypeName)(ctx, message, extension);
|
|
1390
1395
|
const packedTag = (0, types_1.isRepeated)(extension) && (0, types_1.packedType)(extension.type) !== undefined ? ((extension.number << 3) | 2) >>> 0 : undefined;
|
|
1391
1396
|
const singularTag = ((extension.number << 3) | (0, types_1.basicWireType)(extension.type)) >>> 0;
|
|
1392
|
-
const tag = packedTag
|
|
1397
|
+
const tag = packedTag ?? singularTag;
|
|
1393
1398
|
const chunks = [];
|
|
1394
1399
|
chunks.push((0, ts_poet_1.code) `{`);
|
|
1395
1400
|
chunks.push((0, ts_poet_1.code) `number: ${extension.number},`);
|
|
@@ -1397,7 +1402,7 @@ function generateExtension(ctx, message, extension) {
|
|
|
1397
1402
|
if (packedTag !== undefined)
|
|
1398
1403
|
chunks.push((0, ts_poet_1.code) `singularTag: ${singularTag},`);
|
|
1399
1404
|
chunks.push((0, ts_poet_1.code) `repeated: ${extension.label == ts_proto_descriptors_1.FieldDescriptorProto_Label.LABEL_REPEATED},`);
|
|
1400
|
-
chunks.push((0, ts_poet_1.code) `packed: ${
|
|
1405
|
+
chunks.push((0, ts_poet_1.code) `packed: ${extension.options?.packed ? true : false},`);
|
|
1401
1406
|
const Reader = (0, utils_1.impFile)(ctx.options, "Reader@protobufjs/minimal");
|
|
1402
1407
|
const Writer = (0, utils_1.impFile)(ctx.options, "Writer@protobufjs/minimal");
|
|
1403
1408
|
if (ctx.options.outputEncodeMethods === true ||
|
|
@@ -1479,7 +1484,7 @@ function generateExtension(ctx, message, extension) {
|
|
|
1479
1484
|
}
|
|
1480
1485
|
else if ((0, types_1.isScalar)(extension) || (0, types_1.isEnum)(extension)) {
|
|
1481
1486
|
chunks.push((0, ts_poet_1.code) `
|
|
1482
|
-
if (${(0, types_1.notDefaultCheck)(ctx, extension, message
|
|
1487
|
+
if (${(0, types_1.notDefaultCheck)(ctx, extension, message?.options, "value")}) {
|
|
1483
1488
|
const writer = ${Writer}.create();
|
|
1484
1489
|
${writeSnippet("value")};
|
|
1485
1490
|
encoded.push(writer.finish());
|
|
@@ -1578,7 +1583,6 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
1578
1583
|
};
|
|
1579
1584
|
// add a check for each incoming field
|
|
1580
1585
|
messageDesc.field.forEach((field) => {
|
|
1581
|
-
var _a;
|
|
1582
1586
|
const fieldName = (0, utils_1.getFieldName)(field, options);
|
|
1583
1587
|
const fieldKey = (0, utils_1.safeAccessor)(fieldName);
|
|
1584
1588
|
const jsonName = (0, utils_1.getFieldJsonName)(field, options);
|
|
@@ -1586,7 +1590,6 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
1586
1590
|
const jsonPropertyOptional = (0, utils_1.getPropertyAccessor)("object", jsonName, true);
|
|
1587
1591
|
// get code that extracts value from incoming object
|
|
1588
1592
|
const readSnippet = (from) => {
|
|
1589
|
-
var _a;
|
|
1590
1593
|
if ((0, types_1.isEnum)(field)) {
|
|
1591
1594
|
const fromJson = (0, types_1.getEnumMethod)(ctx, field.typeName, "FromJSON");
|
|
1592
1595
|
return (0, ts_poet_1.code) `${fromJson}(${from})`;
|
|
@@ -1602,7 +1605,7 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
1602
1605
|
}
|
|
1603
1606
|
}
|
|
1604
1607
|
else if ((0, types_1.isLong)(field) && (0, types_1.isJsTypeFieldOption)(options, field)) {
|
|
1605
|
-
const fieldType = (
|
|
1608
|
+
const fieldType = (0, types_1.getFieldOptionsJsType)(field, ctx.options) ?? field.type;
|
|
1606
1609
|
const cstr = (0, case_1.capitalize)((0, types_1.basicTypeName)(ctx, { ...field, type: fieldType }, { keepValueType: true }).toCodeString([]));
|
|
1607
1610
|
return (0, ts_poet_1.code) `${utils.globalThis}.${cstr}(${from})`;
|
|
1608
1611
|
}
|
|
@@ -1715,7 +1718,7 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
1715
1718
|
const noDefaultValue = !options.initializeFieldsAsUndefined &&
|
|
1716
1719
|
(0, types_1.isOptionalProperty)(field, messageDesc.options, options, currentFile.isProto3Syntax);
|
|
1717
1720
|
// and then use the snippet to handle repeated fields if necessary
|
|
1718
|
-
if (
|
|
1721
|
+
if (canonicalFromJson[fullTypeName]?.[fieldName]) {
|
|
1719
1722
|
chunks.push((0, ts_poet_1.code) `${fieldName}: ${canonicalFromJson[fullTypeName][fieldName]("object")},`);
|
|
1720
1723
|
}
|
|
1721
1724
|
else if ((0, types_1.isRepeated)(field)) {
|
|
@@ -1767,8 +1770,9 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
|
|
|
1767
1770
|
const fieldName = (0, case_1.maybeSnakeToCamel)(messageDesc.oneofDecl[field.oneofIndex].name, options);
|
|
1768
1771
|
chunks.push((0, ts_poet_1.code) `${fieldName}: `);
|
|
1769
1772
|
}
|
|
1773
|
+
const valueName = (0, utils_1.oneofValueName)(fieldKey, options);
|
|
1770
1774
|
const ternaryIf = (0, ts_poet_1.code) `${ctx.utils.isSet}(${jsonProperty})`;
|
|
1771
|
-
const ternaryThen = (0, ts_poet_1.code) `{ $case: '${fieldName}', ${
|
|
1775
|
+
const ternaryThen = (0, ts_poet_1.code) `{ $case: '${fieldName}', ${valueName}: ${readSnippet(`${jsonProperty}`)}`;
|
|
1772
1776
|
chunks.push((0, ts_poet_1.code) `${ternaryIf} ? ${ternaryThen}} : `);
|
|
1773
1777
|
if (field === lastCase) {
|
|
1774
1778
|
chunks.push((0, ts_poet_1.code) `${(0, utils_1.nullOrUndefined)(options)},`);
|
|
@@ -1838,7 +1842,6 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
|
|
|
1838
1842
|
const jsonProperty = (0, utils_1.getPropertyAccessor)("obj", jsonName);
|
|
1839
1843
|
const messageProperty = (0, utils_1.getPropertyAccessor)("message", fieldName);
|
|
1840
1844
|
const readSnippet = (from) => {
|
|
1841
|
-
var _a;
|
|
1842
1845
|
if ((0, types_1.isEnum)(field)) {
|
|
1843
1846
|
const toJson = (0, types_1.getEnumMethod)(ctx, field.typeName, "ToJSON");
|
|
1844
1847
|
return (0, ts_poet_1.code) `${toJson}(${from})`;
|
|
@@ -1917,7 +1920,7 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
|
|
|
1917
1920
|
return (0, ts_poet_1.code) `${utils.base64FromBytes}(${from})`;
|
|
1918
1921
|
}
|
|
1919
1922
|
else if ((0, types_1.isLong)(field) && (0, types_1.isJsTypeFieldOption)(options, field)) {
|
|
1920
|
-
const fieldType = (
|
|
1923
|
+
const fieldType = (0, types_1.getFieldOptionsJsType)(field, ctx.options) ?? field.type;
|
|
1921
1924
|
if (!fieldType) {
|
|
1922
1925
|
return (0, ts_poet_1.code) `${from}`;
|
|
1923
1926
|
}
|
|
@@ -1979,9 +1982,10 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
|
|
|
1979
1982
|
const oneofNameWithMessage = options.useJsonName
|
|
1980
1983
|
? messageProperty
|
|
1981
1984
|
: (0, utils_1.getPropertyAccessor)("message", (0, case_1.maybeSnakeToCamel)(messageDesc.oneofDecl[field.oneofIndex].name, options));
|
|
1985
|
+
const valueName = (0, utils_1.oneofValueName)(fieldName, options);
|
|
1982
1986
|
chunks.push((0, ts_poet_1.code) `
|
|
1983
1987
|
if (${oneofNameWithMessage}?.$case === '${fieldName}') {
|
|
1984
|
-
${jsonProperty} = ${readSnippet(`${oneofNameWithMessage}.${
|
|
1988
|
+
${jsonProperty} = ${readSnippet(`${oneofNameWithMessage}.${valueName}`)};
|
|
1985
1989
|
}
|
|
1986
1990
|
`);
|
|
1987
1991
|
}
|
|
@@ -2155,14 +2159,15 @@ function generateFromPartial(ctx, fullName, messageDesc) {
|
|
|
2155
2159
|
const oneofName = (0, case_1.maybeSnakeToCamel)(messageDesc.oneofDecl[field.oneofIndex].name, options);
|
|
2156
2160
|
const oneofNameWithMessage = (0, utils_1.getPropertyAccessor)("message", oneofName);
|
|
2157
2161
|
const oneofNameWithObject = (0, utils_1.getPropertyAccessor)("object", oneofName);
|
|
2158
|
-
const
|
|
2162
|
+
const valueName = (0, utils_1.oneofValueName)(fieldName, options);
|
|
2163
|
+
const v = readSnippet(`${oneofNameWithObject}.${valueName}`);
|
|
2159
2164
|
chunks.push((0, ts_poet_1.code) `
|
|
2160
2165
|
if (
|
|
2161
2166
|
${oneofNameWithObject}?.$case === '${fieldName}'
|
|
2162
|
-
&& ${oneofNameWithObject}?.${
|
|
2163
|
-
&& ${oneofNameWithObject}?.${
|
|
2167
|
+
&& ${oneofNameWithObject}?.${valueName} !== undefined
|
|
2168
|
+
&& ${oneofNameWithObject}?.${valueName} !== null
|
|
2164
2169
|
) {
|
|
2165
|
-
${oneofNameWithMessage} = { $case: '${fieldName}', ${
|
|
2170
|
+
${oneofNameWithMessage} = { $case: '${fieldName}', ${valueName}: ${v} };
|
|
2166
2171
|
}
|
|
2167
2172
|
`);
|
|
2168
2173
|
}
|
package/build/options.d.ts
CHANGED
|
@@ -22,7 +22,8 @@ export declare enum EnvOption {
|
|
|
22
22
|
}
|
|
23
23
|
export declare enum OneofOption {
|
|
24
24
|
PROPERTIES = "properties",
|
|
25
|
-
UNIONS = "unions"
|
|
25
|
+
UNIONS = "unions",
|
|
26
|
+
UNIONS_VALUE = "unions-value"
|
|
26
27
|
}
|
|
27
28
|
export declare enum ServiceOption {
|
|
28
29
|
GRPC = "grpc-js",
|
|
@@ -97,6 +98,7 @@ export type Options = {
|
|
|
97
98
|
useNullAsOptional: boolean;
|
|
98
99
|
annotateFilesWithVersion: boolean;
|
|
99
100
|
noDefaultsForOptionals: boolean;
|
|
101
|
+
bigIntLiteral: boolean;
|
|
100
102
|
};
|
|
101
103
|
export declare function defaultOptions(): Options;
|
|
102
104
|
export declare function optionsFromParameter(parameter: string | undefined): Options;
|
package/build/options.js
CHANGED
|
@@ -30,6 +30,7 @@ var OneofOption;
|
|
|
30
30
|
(function (OneofOption) {
|
|
31
31
|
OneofOption["PROPERTIES"] = "properties";
|
|
32
32
|
OneofOption["UNIONS"] = "unions";
|
|
33
|
+
OneofOption["UNIONS_VALUE"] = "unions-value";
|
|
33
34
|
})(OneofOption || (exports.OneofOption = OneofOption = {}));
|
|
34
35
|
var ServiceOption;
|
|
35
36
|
(function (ServiceOption) {
|
|
@@ -104,6 +105,7 @@ function defaultOptions() {
|
|
|
104
105
|
useNullAsOptional: false,
|
|
105
106
|
annotateFilesWithVersion: true,
|
|
106
107
|
noDefaultsForOptionals: false,
|
|
108
|
+
bigIntLiteral: true,
|
|
107
109
|
};
|
|
108
110
|
}
|
|
109
111
|
exports.defaultOptions = defaultOptions;
|
package/build/schema.js
CHANGED
|
@@ -10,7 +10,6 @@ const minimal_1 = require("protobufjs/minimal");
|
|
|
10
10
|
const fileDescriptorProto = (0, ts_poet_1.imp)("FileDescriptorProto@ts-proto-descriptors");
|
|
11
11
|
const extensionCache = {};
|
|
12
12
|
function generateSchema(ctx, fileDesc, sourceInfo) {
|
|
13
|
-
var _a;
|
|
14
13
|
const { options } = ctx;
|
|
15
14
|
const chunks = [];
|
|
16
15
|
fileDesc.extension.forEach((extension) => {
|
|
@@ -73,7 +72,7 @@ function generateSchema(ctx, fileDesc, sourceInfo) {
|
|
|
73
72
|
const descriptor = ts_proto_descriptors_1.FileDescriptorProto.fromPartial(fileDesc);
|
|
74
73
|
// Only keep locations that include comments
|
|
75
74
|
descriptor.sourceCodeInfo = {
|
|
76
|
-
location:
|
|
75
|
+
location: descriptor.sourceCodeInfo?.location.filter((loc) => loc["leadingComments"] || loc["trailingComments"]) || [],
|
|
77
76
|
};
|
|
78
77
|
let fileOptions;
|
|
79
78
|
if (fileDesc.options) {
|
package/build/types.js
CHANGED
|
@@ -61,9 +61,8 @@ function basicLongWireType(type) {
|
|
|
61
61
|
exports.basicLongWireType = basicLongWireType;
|
|
62
62
|
/** Returns the type name without any repeated/required/etc. labels. */
|
|
63
63
|
function basicTypeName(ctx, field, typeOptions = {}) {
|
|
64
|
-
var _a, _b;
|
|
65
64
|
const { options } = ctx;
|
|
66
|
-
const fieldType =
|
|
65
|
+
const fieldType = getFieldOptionsJsType(field, ctx.options) ?? field.type;
|
|
67
66
|
switch (fieldType) {
|
|
68
67
|
case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_DOUBLE:
|
|
69
68
|
case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_FLOAT:
|
|
@@ -79,7 +78,7 @@ function basicTypeName(ctx, field, typeOptions = {}) {
|
|
|
79
78
|
case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_FIXED64:
|
|
80
79
|
case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_SFIXED64:
|
|
81
80
|
return isJsTypeFieldOption(options, field)
|
|
82
|
-
?
|
|
81
|
+
? jsTypeName(field) ?? longTypeName(ctx)
|
|
83
82
|
: // this handles 2^53, Long is only needed for 2^64; this is effectively pbjs's forceNumber
|
|
84
83
|
longTypeName(ctx);
|
|
85
84
|
case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_BOOL:
|
|
@@ -170,8 +169,7 @@ function packedType(type) {
|
|
|
170
169
|
}
|
|
171
170
|
exports.packedType = packedType;
|
|
172
171
|
function getFieldOptionsJsType(field, options) {
|
|
173
|
-
|
|
174
|
-
if (!options.useJsTypeOverride || ((_a = field.options) === null || _a === void 0 ? void 0 : _a.jstype) === undefined) {
|
|
172
|
+
if (!options.useJsTypeOverride || field.options?.jstype === undefined) {
|
|
175
173
|
return;
|
|
176
174
|
}
|
|
177
175
|
switch (field.options.jstype) {
|
|
@@ -242,7 +240,7 @@ function defaultValue(ctx, field) {
|
|
|
242
240
|
return `"${numericDefaultVal}"`;
|
|
243
241
|
}
|
|
244
242
|
else if (options.forceLong === options_1.LongOption.BIGINT) {
|
|
245
|
-
return `BigInt("${numericDefaultVal}")`;
|
|
243
|
+
return options.bigIntLiteral ? (0, ts_poet_1.code) `${numericDefaultVal}n` : (0, ts_poet_1.code) `BigInt("${numericDefaultVal}")`;
|
|
246
244
|
}
|
|
247
245
|
else {
|
|
248
246
|
return numericDefaultVal;
|
|
@@ -375,12 +373,12 @@ function isOptionalProperty(field, messageOptions, options, isProto3Syntax) {
|
|
|
375
373
|
const optionalAll = options.useOptionals === "all";
|
|
376
374
|
const deprecatedOnly = options.useOptionals === "deprecatedOnly" && field.options && field.options.deprecated;
|
|
377
375
|
return ((optionalMessages && isMessage(field) && !isRepeated(field)) ||
|
|
378
|
-
((optionalAll || deprecatedOnly) && !
|
|
376
|
+
((optionalAll || deprecatedOnly) && !messageOptions?.mapEntry) ||
|
|
379
377
|
(options.noDefaultsForOptionals && !isRepeated(field) && (isScalar(field) || isEnum(field))) ||
|
|
380
378
|
// file is proto2, we have enabled proto2 optionals, and the field itself is optional
|
|
381
379
|
(!isProto3Syntax &&
|
|
382
380
|
field.label === ts_proto_descriptors_1.FieldDescriptorProto_Label.LABEL_OPTIONAL &&
|
|
383
|
-
!
|
|
381
|
+
!messageOptions?.mapEntry &&
|
|
384
382
|
!options.disableProto2Optionals) ||
|
|
385
383
|
// don't bother verifying that oneof is not union. union oneofs generate their own properties.
|
|
386
384
|
isWithinOneOf(field) ||
|
|
@@ -409,7 +407,9 @@ function isWithinOneOf(field) {
|
|
|
409
407
|
}
|
|
410
408
|
exports.isWithinOneOf = isWithinOneOf;
|
|
411
409
|
function isWithinOneOfThatShouldBeUnion(options, field) {
|
|
412
|
-
return isWithinOneOf(field) &&
|
|
410
|
+
return (isWithinOneOf(field) &&
|
|
411
|
+
(options.oneof === options_1.OneofOption.UNIONS || options.oneof === options_1.OneofOption.UNIONS_VALUE) &&
|
|
412
|
+
!field.proto3Optional);
|
|
413
413
|
}
|
|
414
414
|
exports.isWithinOneOfThatShouldBeUnion = isWithinOneOfThatShouldBeUnion;
|
|
415
415
|
function isRepeated(field) {
|
|
@@ -573,17 +573,15 @@ function longTypeName(ctx) {
|
|
|
573
573
|
}
|
|
574
574
|
}
|
|
575
575
|
function jsTypeName(field) {
|
|
576
|
-
|
|
577
|
-
if (((_a = field.options) === null || _a === void 0 ? void 0 : _a.jstype) === ts_proto_descriptors_1.FieldOptions_JSType.JS_STRING) {
|
|
576
|
+
if (field.options?.jstype === ts_proto_descriptors_1.FieldOptions_JSType.JS_STRING) {
|
|
578
577
|
return (0, ts_poet_1.code) `string`;
|
|
579
578
|
}
|
|
580
|
-
else if (
|
|
579
|
+
else if (field.options?.jstype === ts_proto_descriptors_1.FieldOptions_JSType.JS_NUMBER) {
|
|
581
580
|
return (0, ts_poet_1.code) `number`;
|
|
582
581
|
}
|
|
583
582
|
}
|
|
584
583
|
/** Maps `.some_proto_namespace.Message` to a TypeName. */
|
|
585
584
|
function messageToTypeName(ctx, protoType, typeOptions = {}) {
|
|
586
|
-
var _a;
|
|
587
585
|
const { options, typeMap } = ctx;
|
|
588
586
|
// Watch for the wrapper types `.google.protobuf.*Value`. If we're mapping
|
|
589
587
|
// them to basic built-in types, we union the type with undefined to
|
|
@@ -591,7 +589,7 @@ function messageToTypeName(ctx, protoType, typeOptions = {}) {
|
|
|
591
589
|
// - If the field is repeated, values cannot be undefined.
|
|
592
590
|
let valueType = valueTypeName(ctx, protoType);
|
|
593
591
|
if (!typeOptions.keepValueType && valueType) {
|
|
594
|
-
if (
|
|
592
|
+
if (typeOptions.repeated ?? false) {
|
|
595
593
|
return valueType;
|
|
596
594
|
}
|
|
597
595
|
return (0, ts_poet_1.code) `${valueType} | ${(0, utils_1.nullOrUndefined)(options)}`;
|
|
@@ -624,14 +622,13 @@ function getEnumMethod(ctx, enumProtoType, methodSuffix) {
|
|
|
624
622
|
exports.getEnumMethod = getEnumMethod;
|
|
625
623
|
/** Return the TypeName for any field (primitive/message/etc.) as exposed in the interface. */
|
|
626
624
|
function toTypeName(ctx, messageDesc, field, ensureOptional = false) {
|
|
627
|
-
var _a;
|
|
628
625
|
function finalize(type, isOptional) {
|
|
629
626
|
if (isOptional) {
|
|
630
627
|
return (0, ts_poet_1.code) `${type} | ${(0, utils_1.nullOrUndefined)(ctx.options, field.proto3Optional)}`;
|
|
631
628
|
}
|
|
632
629
|
return type;
|
|
633
630
|
}
|
|
634
|
-
const fieldType =
|
|
631
|
+
const fieldType = getFieldOptionsJsType(field, ctx.options) ?? field.type;
|
|
635
632
|
const type = basicTypeName(ctx, { ...field, type: fieldType }, { keepValueType: false });
|
|
636
633
|
if (isRepeated(field)) {
|
|
637
634
|
const mapType = messageDesc ? detectMapType(ctx, messageDesc, field) : false;
|
|
@@ -697,12 +694,11 @@ function shouldGenerateJSMapType(ctx, message, field) {
|
|
|
697
694
|
}
|
|
698
695
|
exports.shouldGenerateJSMapType = shouldGenerateJSMapType;
|
|
699
696
|
function detectMapType(ctx, messageDesc, fieldDesc) {
|
|
700
|
-
var _a;
|
|
701
697
|
const { typeMap } = ctx;
|
|
702
698
|
if (fieldDesc.label === ts_proto_descriptors_1.FieldDescriptorProto_Label.LABEL_REPEATED &&
|
|
703
699
|
fieldDesc.type === ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_MESSAGE) {
|
|
704
700
|
const mapType = typeMap.get(fieldDesc.typeName)[2];
|
|
705
|
-
if (!
|
|
701
|
+
if (!mapType.options?.mapEntry)
|
|
706
702
|
return undefined;
|
|
707
703
|
const [keyField, valueField] = mapType.field;
|
|
708
704
|
const keyType = toTypeName(ctx, messageDesc, keyField);
|
|
@@ -799,8 +795,7 @@ function hasSingleRepeatedField(messageDesc) {
|
|
|
799
795
|
return messageDesc.field.length == 1 && messageDesc.field[0].label === ts_proto_descriptors_1.FieldDescriptorProto_Label.LABEL_REPEATED;
|
|
800
796
|
}
|
|
801
797
|
function isJsTypeFieldOption(options, field) {
|
|
802
|
-
var _a, _b;
|
|
803
798
|
return (options.useJsTypeOverride &&
|
|
804
|
-
(
|
|
799
|
+
(field.options?.jstype === ts_proto_descriptors_1.FieldOptions_JSType.JS_NUMBER || field.options?.jstype === ts_proto_descriptors_1.FieldOptions_JSType.JS_STRING));
|
|
805
800
|
}
|
|
806
801
|
exports.isJsTypeFieldOption = isJsTypeFieldOption;
|
package/build/utils.d.ts
CHANGED
|
@@ -73,6 +73,7 @@ export declare function arrowFunction(params: string, body: Code | string, isOne
|
|
|
73
73
|
export declare function nullOrUndefined(options: Pick<Options, "useNullAsOptional">, hasProto3Optional?: boolean): string;
|
|
74
74
|
export declare function maybeCheckIsNotNull(options: Pick<Options, "useNullAsOptional">, typeName: string, prefix?: string): string;
|
|
75
75
|
export declare function maybeCheckIsNull(options: Pick<Options, "useNullAsOptional">, typeName: string, prefix?: string): string;
|
|
76
|
+
export declare function oneofValueName(fieldName: string, options: Pick<Options, "oneof">): string;
|
|
76
77
|
export declare function withOrMaybeCheckIsNotNull(options: Pick<Options, "useNullAsOptional">, typeName: string): string;
|
|
77
78
|
export declare function withOrMaybeCheckIsNull(options: Pick<Options, "useNullAsOptional">, typeName: string): string;
|
|
78
79
|
export declare function withAndMaybeCheckIsNotNull(options: Pick<Options, "useNullAsOptional">, typeName: string): string;
|
package/build/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getVersions = 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.maybeAddComment = exports.upperFirst = exports.lowerFirst = exports.singular = exports.fail = exports.readToBuffer = exports.generateIndexFiles = exports.protoFilesToGenerate = void 0;
|
|
3
|
+
exports.getVersions = exports.withAndMaybeCheckIsNull = exports.withAndMaybeCheckIsNotNull = exports.withOrMaybeCheckIsNull = exports.withOrMaybeCheckIsNotNull = exports.oneofValueName = 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.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");
|
|
@@ -266,6 +266,10 @@ function maybeCheckIsNull(options, typeName, prefix) {
|
|
|
266
266
|
return options.useNullAsOptional ? ` ${prefix} ${typeName} === null` : "";
|
|
267
267
|
}
|
|
268
268
|
exports.maybeCheckIsNull = maybeCheckIsNull;
|
|
269
|
+
function oneofValueName(fieldName, options) {
|
|
270
|
+
return options.oneof === options_1.OneofOption.UNIONS ? fieldName : "value";
|
|
271
|
+
}
|
|
272
|
+
exports.oneofValueName = oneofValueName;
|
|
269
273
|
function withOrMaybeCheckIsNotNull(options, typeName) {
|
|
270
274
|
return maybeCheckIsNotNull(options, typeName, "||");
|
|
271
275
|
}
|
|
@@ -283,7 +287,6 @@ function withAndMaybeCheckIsNull(options, typeName) {
|
|
|
283
287
|
}
|
|
284
288
|
exports.withAndMaybeCheckIsNull = withAndMaybeCheckIsNull;
|
|
285
289
|
async function getVersions(request) {
|
|
286
|
-
var _a;
|
|
287
290
|
let protocVersion = "unknown";
|
|
288
291
|
if (request.compilerVersion) {
|
|
289
292
|
const { major, minor, patch } = request.compilerVersion;
|
|
@@ -291,7 +294,7 @@ async function getVersions(request) {
|
|
|
291
294
|
}
|
|
292
295
|
const path = "../package.json";
|
|
293
296
|
const packageJson = await Promise.resolve(`${path}`).then(s => require(s));
|
|
294
|
-
const tsProtoVersion = `v${
|
|
297
|
+
const tsProtoVersion = `v${packageJson?.version ?? "unknown"}`;
|
|
295
298
|
return {
|
|
296
299
|
protocVersion,
|
|
297
300
|
tsProtoVersion,
|