ts-proto 1.84.0 → 1.87.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 +1 -1
- package/build/generate-grpc-web.js +1 -3
- package/build/generate-services.js +58 -21
- package/build/main.js +50 -62
- package/build/types.js +14 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## [1.87.1](https://github.com/stephenh/ts-proto/compare/v1.87.0...v1.87.1) (2021-11-21)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* code generation for int64 map values in fromPartial and fromJson ([#395](https://github.com/stephenh/ts-proto/issues/395)) ([d3ea8eb](https://github.com/stephenh/ts-proto/commit/d3ea8eb69e19a5e45fcc1766c4af1194b17e48fc))
|
|
7
|
+
|
|
8
|
+
# [1.87.0](https://github.com/stephenh/ts-proto/compare/v1.86.0...v1.87.0) (2021-11-16)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* Use ternary operator for conditional assignments ([#394](https://github.com/stephenh/ts-proto/issues/394)) ([d84c084](https://github.com/stephenh/ts-proto/commit/d84c084fb56c958c184f8971479979b8bfb17ccc))
|
|
14
|
+
|
|
15
|
+
# [1.86.0](https://github.com/stephenh/ts-proto/compare/v1.85.0...v1.86.0) (2021-11-15)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* Initialize lists with map ([#387](https://github.com/stephenh/ts-proto/issues/387)) ([200e674](https://github.com/stephenh/ts-proto/commit/200e674e4baf2640d67720ad535fe042d291d4a0))
|
|
21
|
+
|
|
22
|
+
# [1.85.0](https://github.com/stephenh/ts-proto/compare/v1.84.0...v1.85.0) (2021-11-02)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* Streaming support ([#373](https://github.com/stephenh/ts-proto/issues/373)) ([459b94f](https://github.com/stephenh/ts-proto/commit/459b94f5b2988d58d186461332e888c3e511603a))
|
|
28
|
+
|
|
1
29
|
# [1.84.0](https://github.com/stephenh/ts-proto/compare/v1.83.3...v1.84.0) (2021-11-02)
|
|
2
30
|
|
|
3
31
|
|
package/README.markdown
CHANGED
|
@@ -70,7 +70,7 @@ It will also generate client implementations of `PingService`; currently [Twirp]
|
|
|
70
70
|
- `npm install ts-proto`
|
|
71
71
|
- `protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=. ./simple.proto`
|
|
72
72
|
- (Note that the output parameter name, `ts_proto_out`, is named based on the suffix of the plugin's name, i.e. "ts_proto" suffix in the `--plugin=./node_modules/.bin/protoc-gen-ts_proto` parameter becomes the `_out` prefix, per `protoc`'s CLI conventions.)
|
|
73
|
-
- On Windows, use `protoc --plugin=protoc-gen-ts_proto=.\node_modules\.bin\protoc-gen-ts_proto.cmd --ts_proto_out=. ./simple.proto`
|
|
73
|
+
- On Windows, use `protoc --plugin=protoc-gen-ts_proto=.\node_modules\.bin\protoc-gen-ts_proto.cmd --ts_proto_out=. ./simple.proto` (see [#93](https://github.com/stephenh/ts-proto/issues/93))
|
|
74
74
|
- Ensure you're using a modern `protoc`, i.e. the original `protoc` `3.0.0` doesn't support the `_opt` flag
|
|
75
75
|
|
|
76
76
|
This will generate `*.ts` source files for the given `*.proto` types.
|
|
@@ -43,9 +43,7 @@ function generateRpcMethod(ctx, serviceDesc, methodDesc) {
|
|
|
43
43
|
const { options, utils } = ctx;
|
|
44
44
|
const inputType = types_1.requestType(ctx, methodDesc);
|
|
45
45
|
const partialInputType = ts_poet_1.code `${utils.DeepPartial}<${inputType}>`;
|
|
46
|
-
const returns =
|
|
47
|
-
? types_1.responseObservable(ctx, methodDesc)
|
|
48
|
-
: types_1.responsePromise(ctx, methodDesc);
|
|
46
|
+
const returns = types_1.responsePromiseOrObservable(ctx, methodDesc);
|
|
49
47
|
const method = methodDesc.serverStreaming ? 'invoke' : 'unary';
|
|
50
48
|
return ts_poet_1.code `
|
|
51
49
|
${methodDesc.formattedName}(
|
|
@@ -55,15 +55,7 @@ function generateService(ctx, fileDesc, sourceInfo, serviceDesc) {
|
|
|
55
55
|
if (options.addNestjsRestParameter) {
|
|
56
56
|
params.push(ts_poet_1.code `...rest: any`);
|
|
57
57
|
}
|
|
58
|
-
|
|
59
|
-
let returnType;
|
|
60
|
-
if (options.returnObservable || methodDesc.serverStreaming) {
|
|
61
|
-
returnType = types_1.responseObservable(ctx, methodDesc);
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
returnType = types_1.responsePromise(ctx, methodDesc);
|
|
65
|
-
}
|
|
66
|
-
chunks.push(ts_poet_1.code `${methodDesc.formattedName}(${ts_poet_1.joinCode(params, { on: ',' })}): ${returnType};`);
|
|
58
|
+
chunks.push(ts_poet_1.code `${methodDesc.formattedName}(${ts_poet_1.joinCode(params, { on: ',' })}): ${types_1.responsePromiseOrObservable(ctx, methodDesc)};`);
|
|
67
59
|
// If this is a batch method, auto-generate the singular version of it
|
|
68
60
|
if (options.context) {
|
|
69
61
|
const batchMethod = types_1.detectBatchMethod(ctx, fileDesc, serviceDesc, methodDesc);
|
|
@@ -83,22 +75,50 @@ function generateRegularRpcMethod(ctx, fileDesc, serviceDesc, methodDesc) {
|
|
|
83
75
|
utils_1.assertInstanceOf(methodDesc, utils_1.FormattedMethodDescriptor);
|
|
84
76
|
const { options } = ctx;
|
|
85
77
|
const Reader = ts_poet_1.imp('Reader@protobufjs/minimal');
|
|
78
|
+
const rawInputType = types_1.rawRequestType(ctx, methodDesc);
|
|
86
79
|
const inputType = types_1.requestType(ctx, methodDesc);
|
|
87
80
|
const outputType = types_1.responseType(ctx, methodDesc);
|
|
88
81
|
const params = [...(options.context ? [ts_poet_1.code `ctx: Context`] : []), ts_poet_1.code `request: ${inputType}`];
|
|
89
82
|
const maybeCtx = options.context ? 'ctx,' : '';
|
|
83
|
+
let encode = ts_poet_1.code `${rawInputType}.encode(request).finish()`;
|
|
84
|
+
let decode = ts_poet_1.code `data => ${outputType}.decode(new ${Reader}(data))`;
|
|
85
|
+
if (methodDesc.clientStreaming) {
|
|
86
|
+
encode = ts_poet_1.code `request.pipe(${ts_poet_1.imp('map@rxjs/operators')}(request => ${encode}))`;
|
|
87
|
+
}
|
|
88
|
+
let returnVariable;
|
|
89
|
+
if (options.returnObservable || methodDesc.serverStreaming) {
|
|
90
|
+
returnVariable = 'result';
|
|
91
|
+
decode = ts_poet_1.code `result.pipe(${ts_poet_1.imp('map@rxjs/operators')}(${decode}))`;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
returnVariable = 'promise';
|
|
95
|
+
decode = ts_poet_1.code `promise.then(${decode})`;
|
|
96
|
+
}
|
|
97
|
+
let rpcMethod;
|
|
98
|
+
if (methodDesc.clientStreaming && methodDesc.serverStreaming) {
|
|
99
|
+
rpcMethod = 'bidirectionalStreamingRequest';
|
|
100
|
+
}
|
|
101
|
+
else if (methodDesc.serverStreaming) {
|
|
102
|
+
rpcMethod = 'serverStreamingRequest';
|
|
103
|
+
}
|
|
104
|
+
else if (methodDesc.clientStreaming) {
|
|
105
|
+
rpcMethod = 'clientStreamingRequest';
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
rpcMethod = 'request';
|
|
109
|
+
}
|
|
90
110
|
return ts_poet_1.code `
|
|
91
111
|
${methodDesc.formattedName}(
|
|
92
112
|
${ts_poet_1.joinCode(params, { on: ',' })}
|
|
93
|
-
): ${types_1.
|
|
94
|
-
const data = ${
|
|
95
|
-
const
|
|
113
|
+
): ${types_1.responsePromiseOrObservable(ctx, methodDesc)} {
|
|
114
|
+
const data = ${encode};
|
|
115
|
+
const ${returnVariable} = this.rpc.${rpcMethod}(
|
|
96
116
|
${maybeCtx}
|
|
97
117
|
"${utils_1.maybePrefixPackage(fileDesc, serviceDesc.name)}",
|
|
98
118
|
"${methodDesc.name}",
|
|
99
119
|
data
|
|
100
120
|
);
|
|
101
|
-
return
|
|
121
|
+
return ${decode};
|
|
102
122
|
}
|
|
103
123
|
`;
|
|
104
124
|
}
|
|
@@ -217,24 +237,41 @@ function generateCachingRpcMethod(ctx, fileDesc, serviceDesc, methodDesc) {
|
|
|
217
237
|
*
|
|
218
238
|
* This lets clients pass in their own request-promise-ish client.
|
|
219
239
|
*
|
|
240
|
+
* This also requires clientStreamingRequest, serverStreamingRequest and
|
|
241
|
+
* bidirectionalStreamingRequest methods if any of the RPCs is streaming.
|
|
242
|
+
*
|
|
220
243
|
* We don't export this because if a project uses multiple `*.proto` files,
|
|
221
244
|
* we don't want our the barrel imports in `index.ts` to have multiple `Rpc`
|
|
222
245
|
* types.
|
|
223
246
|
*/
|
|
224
|
-
function generateRpcType(ctx) {
|
|
247
|
+
function generateRpcType(ctx, hasStreamingMethods) {
|
|
225
248
|
const { options } = ctx;
|
|
226
249
|
const maybeContext = options.context ? '<Context>' : '';
|
|
227
250
|
const maybeContextParam = options.context ? 'ctx: Context,' : '';
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
251
|
+
const methods = [[ts_poet_1.code `request`, ts_poet_1.code `Uint8Array`, ts_poet_1.code `Promise<Uint8Array>`]];
|
|
252
|
+
if (hasStreamingMethods) {
|
|
253
|
+
const observable = ts_poet_1.imp('Observable@rxjs');
|
|
254
|
+
methods.push([ts_poet_1.code `clientStreamingRequest`, ts_poet_1.code `${observable}<Uint8Array>`, ts_poet_1.code `Promise<Uint8Array>`]);
|
|
255
|
+
methods.push([ts_poet_1.code `serverStreamingRequest`, ts_poet_1.code `Uint8Array`, ts_poet_1.code `${observable}<Uint8Array>`]);
|
|
256
|
+
methods.push([
|
|
257
|
+
ts_poet_1.code `bidirectionalStreamingRequest`,
|
|
258
|
+
ts_poet_1.code `${observable}<Uint8Array>`,
|
|
259
|
+
ts_poet_1.code `${observable}<Uint8Array>`,
|
|
260
|
+
]);
|
|
261
|
+
}
|
|
262
|
+
const chunks = [];
|
|
263
|
+
chunks.push(ts_poet_1.code ` interface Rpc${maybeContext} {`);
|
|
264
|
+
methods.forEach((method) => {
|
|
265
|
+
chunks.push(ts_poet_1.code `
|
|
266
|
+
${method[0]}(
|
|
231
267
|
${maybeContextParam}
|
|
232
268
|
service: string,
|
|
233
269
|
method: string,
|
|
234
|
-
data:
|
|
235
|
-
):
|
|
236
|
-
}
|
|
237
|
-
|
|
270
|
+
data: ${method[1]}
|
|
271
|
+
): ${method[2]};`);
|
|
272
|
+
});
|
|
273
|
+
chunks.push(ts_poet_1.code ` }`);
|
|
274
|
+
return ts_poet_1.joinCode(chunks, { on: '\n' });
|
|
238
275
|
}
|
|
239
276
|
exports.generateRpcType = generateRpcType;
|
|
240
277
|
function generateDataLoadersType() {
|
package/build/main.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.contextTypeVar = exports.makeUtils = exports.generateFile = void 0;
|
|
4
4
|
const ts_poet_1 = require("ts-poet");
|
|
5
|
-
const ts_proto_descriptors_1 = require("ts-proto-descriptors");
|
|
6
5
|
const types_1 = require("./types");
|
|
7
6
|
const sourceInfo_1 = require("./sourceInfo");
|
|
8
7
|
const utils_1 = require("./utils");
|
|
@@ -91,6 +90,7 @@ function generateFile(ctx, fileDesc) {
|
|
|
91
90
|
}
|
|
92
91
|
}, options);
|
|
93
92
|
}
|
|
93
|
+
let hasServerStreamingMethods = false;
|
|
94
94
|
let hasStreamingMethods = false;
|
|
95
95
|
visit_1.visitServices(fileDesc, sourceInfo, (serviceDesc, sInfo) => {
|
|
96
96
|
if (options.nestJs) {
|
|
@@ -126,18 +126,23 @@ function generateFile(ctx, fileDesc) {
|
|
|
126
126
|
serviceDesc.method.forEach((method) => {
|
|
127
127
|
chunks.push(generate_grpc_web_1.generateGrpcMethodDesc(ctx, serviceDesc, method));
|
|
128
128
|
if (method.serverStreaming) {
|
|
129
|
-
|
|
129
|
+
hasServerStreamingMethods = true;
|
|
130
130
|
}
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
|
+
serviceDesc.method.forEach((methodDesc, index) => {
|
|
135
|
+
if (methodDesc.serverStreaming || methodDesc.clientStreaming) {
|
|
136
|
+
hasStreamingMethods = true;
|
|
137
|
+
}
|
|
138
|
+
});
|
|
134
139
|
});
|
|
135
140
|
if (options.outputServices === options_1.ServiceOption.DEFAULT && options.outputClientImpl && fileDesc.service.length > 0) {
|
|
136
141
|
if (options.outputClientImpl === true) {
|
|
137
|
-
chunks.push(generate_services_1.generateRpcType(ctx));
|
|
142
|
+
chunks.push(generate_services_1.generateRpcType(ctx, hasStreamingMethods));
|
|
138
143
|
}
|
|
139
144
|
else if (options.outputClientImpl === 'grpc-web') {
|
|
140
|
-
chunks.push(generate_grpc_web_1.addGrpcWebMisc(ctx,
|
|
145
|
+
chunks.push(generate_grpc_web_1.addGrpcWebMisc(ctx, hasServerStreamingMethods));
|
|
141
146
|
}
|
|
142
147
|
}
|
|
143
148
|
if (options.context) {
|
|
@@ -280,13 +285,15 @@ function makeDeepPartial(options, longs) {
|
|
|
280
285
|
`;
|
|
281
286
|
}
|
|
282
287
|
const maybeExport = options.exportCommonSymbols ? 'export' : '';
|
|
283
|
-
|
|
288
|
+
// Allow passing longs as numbers or strings, nad we'll convert them
|
|
289
|
+
const maybeLong = options.forceLong === options_1.LongOption.LONG ? ts_poet_1.code ` : T extends ${longs.Long} ? string | number | Long ` : '';
|
|
284
290
|
const keys = options.outputTypeRegistry ? ts_poet_1.code `Exclude<keyof T, '$type'>` : ts_poet_1.code `keyof T`;
|
|
285
291
|
// Based on the type from ts-essentials
|
|
286
292
|
const DeepPartial = ts_poet_1.conditionalOutput('DeepPartial', ts_poet_1.code `
|
|
287
|
-
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined
|
|
288
|
-
${maybeExport} type DeepPartial<T> =
|
|
293
|
+
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
294
|
+
${maybeExport} type DeepPartial<T> = T extends Builtin
|
|
289
295
|
? T
|
|
296
|
+
${maybeLong}
|
|
290
297
|
: T extends Array<infer U>
|
|
291
298
|
? Array<DeepPartial<U>>
|
|
292
299
|
: T extends ReadonlyArray<infer U>
|
|
@@ -733,20 +740,6 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
733
740
|
fromJSON(${messageDesc.field.length > 0 ? 'object' : '_'}: any): ${fullName} {
|
|
734
741
|
const message = { ...base${fullName} } as ${fullName};
|
|
735
742
|
`);
|
|
736
|
-
// initialize all lists
|
|
737
|
-
messageDesc.field.filter(types_1.isRepeated).forEach((field) => {
|
|
738
|
-
const value = types_1.isMapType(ctx, messageDesc, field) ? '{}' : '[]';
|
|
739
|
-
const name = case_1.maybeSnakeToCamel(field.name, options);
|
|
740
|
-
chunks.push(ts_poet_1.code `message.${name} = ${value};`);
|
|
741
|
-
});
|
|
742
|
-
// initialize all buffers
|
|
743
|
-
messageDesc.field
|
|
744
|
-
.filter((field) => !types_1.isRepeated(field) && !types_1.isWithinOneOf(field) && types_1.isBytes(field))
|
|
745
|
-
.forEach((field) => {
|
|
746
|
-
const value = options.env === options_1.EnvOption.NODE ? 'Buffer.alloc(0)' : 'new Uint8Array()';
|
|
747
|
-
const name = case_1.maybeSnakeToCamel(field.name, options);
|
|
748
|
-
chunks.push(ts_poet_1.code `message.${name} = ${value};`);
|
|
749
|
-
});
|
|
750
743
|
// add a check for each incoming field
|
|
751
744
|
messageDesc.field.forEach((field) => {
|
|
752
745
|
const fieldName = case_1.maybeSnakeToCamel(field.name, options);
|
|
@@ -807,6 +800,9 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
807
800
|
return ts_poet_1.code `${utils.bytesFromBase64}(${from} as string)`;
|
|
808
801
|
}
|
|
809
802
|
}
|
|
803
|
+
else if (types_1.isLong(valueType) && options.forceLong === options_1.LongOption.LONG) {
|
|
804
|
+
return ts_poet_1.code `Long.fromString(${from} as string)`;
|
|
805
|
+
}
|
|
810
806
|
else if (types_1.isEnum(valueType)) {
|
|
811
807
|
return ts_poet_1.code `${from} as number`;
|
|
812
808
|
}
|
|
@@ -841,42 +837,41 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
841
837
|
}
|
|
842
838
|
};
|
|
843
839
|
// and then use the snippet to handle repeated fields if necessary
|
|
844
|
-
chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
|
|
845
840
|
if (types_1.isRepeated(field)) {
|
|
846
841
|
if (types_1.isMapType(ctx, messageDesc, field)) {
|
|
842
|
+
chunks.push(ts_poet_1.code `message.${fieldName} = {};`);
|
|
843
|
+
chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
|
|
847
844
|
const i = maybeCastToNumber(ctx, messageDesc, field, 'key');
|
|
848
845
|
chunks.push(ts_poet_1.code `
|
|
849
846
|
Object.entries(object.${fieldName}).forEach(([key, value]) => {
|
|
850
847
|
message.${fieldName}[${i}] = ${readSnippet('value')};
|
|
851
848
|
});
|
|
852
849
|
`);
|
|
850
|
+
chunks.push(ts_poet_1.code `}`);
|
|
853
851
|
}
|
|
854
852
|
else {
|
|
853
|
+
// Explicit `any` type required to make TS with noImplicitAny happy. `object` is also `any` here.
|
|
855
854
|
chunks.push(ts_poet_1.code `
|
|
856
|
-
|
|
857
|
-
message.${fieldName}.push(${readSnippet('e')});
|
|
858
|
-
}
|
|
855
|
+
message.${fieldName} = (object.${fieldName} ?? []).map((e: any) => ${readSnippet('e')});
|
|
859
856
|
`);
|
|
860
857
|
}
|
|
861
858
|
}
|
|
862
859
|
else if (types_1.isWithinOneOfThatShouldBeUnion(options, field)) {
|
|
860
|
+
chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
|
|
863
861
|
const oneofName = case_1.maybeSnakeToCamel(messageDesc.oneofDecl[field.oneofIndex].name, options);
|
|
864
862
|
chunks.push(ts_poet_1.code `
|
|
865
863
|
message.${oneofName} = { $case: '${fieldName}', ${fieldName}: ${readSnippet(`object.${fieldName}`)} }
|
|
866
864
|
`);
|
|
865
|
+
chunks.push(ts_poet_1.code `}`);
|
|
867
866
|
}
|
|
868
867
|
else {
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
const v = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
|
|
876
|
-
chunks.push(ts_poet_1.code `} else {`);
|
|
877
|
-
chunks.push(ts_poet_1.code `message.${fieldName} = ${v};`);
|
|
868
|
+
const fallback = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
|
|
869
|
+
chunks.push(ts_poet_1.code `
|
|
870
|
+
message.${fieldName} = (object.${fieldName} !== undefined && object.${fieldName} !== null)
|
|
871
|
+
? ${readSnippet(`object.${fieldName}`)}
|
|
872
|
+
: ${fallback};
|
|
873
|
+
`);
|
|
878
874
|
}
|
|
879
|
-
chunks.push(ts_poet_1.code `}`);
|
|
880
875
|
});
|
|
881
876
|
// and then wrap up the switch/while/return
|
|
882
877
|
chunks.push(ts_poet_1.code `return message`);
|
|
@@ -929,6 +924,9 @@ function generateToJson(ctx, fullName, messageDesc) {
|
|
|
929
924
|
else if (types_1.isTimestamp(valueType) && options.useDate === options_1.DateOption.TIMESTAMP) {
|
|
930
925
|
return ts_poet_1.code `${utils.fromTimestamp}(${from}).toISOString()`;
|
|
931
926
|
}
|
|
927
|
+
else if (types_1.isLong(valueType) && options.forceLong === options_1.LongOption.LONG) {
|
|
928
|
+
return ts_poet_1.code `${from}.toString()`;
|
|
929
|
+
}
|
|
932
930
|
else if (types_1.isScalar(valueType) || types_1.isValueType(ctx, valueType)) {
|
|
933
931
|
return ts_poet_1.code `${from}`;
|
|
934
932
|
}
|
|
@@ -1006,7 +1004,10 @@ function generateFromPartial(ctx, fullName, messageDesc) {
|
|
|
1006
1004
|
messageDesc.field.forEach((field) => {
|
|
1007
1005
|
const fieldName = case_1.maybeSnakeToCamel(field.name, options);
|
|
1008
1006
|
const readSnippet = (from) => {
|
|
1009
|
-
if (types_1.
|
|
1007
|
+
if ((types_1.isLong(field) || types_1.isLongValueType(field)) && options.forceLong === options_1.LongOption.LONG) {
|
|
1008
|
+
return ts_poet_1.code `Long.fromValue(${from})`;
|
|
1009
|
+
}
|
|
1010
|
+
else if (types_1.isPrimitive(field) ||
|
|
1010
1011
|
(types_1.isTimestamp(field) && (options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) ||
|
|
1011
1012
|
types_1.isValueType(ctx, field)) {
|
|
1012
1013
|
return ts_poet_1.code `${from}`;
|
|
@@ -1021,6 +1022,9 @@ function generateFromPartial(ctx, fullName, messageDesc) {
|
|
|
1021
1022
|
else if (types_1.isEnum(valueType)) {
|
|
1022
1023
|
return ts_poet_1.code `${from} as number`;
|
|
1023
1024
|
}
|
|
1025
|
+
else if (types_1.isLong(valueType) && options.forceLong === options_1.LongOption.LONG) {
|
|
1026
|
+
return ts_poet_1.code `Long.fromValue(${from})`;
|
|
1027
|
+
}
|
|
1024
1028
|
else {
|
|
1025
1029
|
const cstr = case_1.capitalize(types_1.basicTypeName(ctx, valueType).toCodeString());
|
|
1026
1030
|
return ts_poet_1.code `${cstr}(${from})`;
|
|
@@ -1049,11 +1053,9 @@ function generateFromPartial(ctx, fullName, messageDesc) {
|
|
|
1049
1053
|
};
|
|
1050
1054
|
// and then use the snippet to handle repeated fields if necessary
|
|
1051
1055
|
if (types_1.isRepeated(field)) {
|
|
1052
|
-
const value = types_1.isMapType(ctx, messageDesc, field) ? '{}' : '[]';
|
|
1053
|
-
const name = case_1.maybeSnakeToCamel(field.name, options);
|
|
1054
|
-
chunks.push(ts_poet_1.code `message.${name} = ${value};`);
|
|
1055
|
-
chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
|
|
1056
1056
|
if (types_1.isMapType(ctx, messageDesc, field)) {
|
|
1057
|
+
chunks.push(ts_poet_1.code `message.${fieldName} = {};`);
|
|
1058
|
+
chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
|
|
1057
1059
|
const i = maybeCastToNumber(ctx, messageDesc, field, 'key');
|
|
1058
1060
|
chunks.push(ts_poet_1.code `
|
|
1059
1061
|
Object.entries(object.${fieldName}).forEach(([key, value]) => {
|
|
@@ -1062,15 +1064,13 @@ function generateFromPartial(ctx, fullName, messageDesc) {
|
|
|
1062
1064
|
}
|
|
1063
1065
|
});
|
|
1064
1066
|
`);
|
|
1067
|
+
chunks.push(ts_poet_1.code `}`);
|
|
1065
1068
|
}
|
|
1066
1069
|
else {
|
|
1067
1070
|
chunks.push(ts_poet_1.code `
|
|
1068
|
-
|
|
1069
|
-
message.${fieldName}.push(${readSnippet('e')});
|
|
1070
|
-
}
|
|
1071
|
+
message.${fieldName} = (object.${fieldName} ?? []).map((e) => ${readSnippet('e')});
|
|
1071
1072
|
`);
|
|
1072
1073
|
}
|
|
1073
|
-
chunks.push(ts_poet_1.code `}`);
|
|
1074
1074
|
}
|
|
1075
1075
|
else if (types_1.isWithinOneOfThatShouldBeUnion(options, field)) {
|
|
1076
1076
|
let oneofName = case_1.maybeSnakeToCamel(messageDesc.oneofDecl[field.oneofIndex].name, options);
|
|
@@ -1085,30 +1085,18 @@ function generateFromPartial(ctx, fullName, messageDesc) {
|
|
|
1085
1085
|
}
|
|
1086
1086
|
`);
|
|
1087
1087
|
}
|
|
1088
|
-
else if ((
|
|
1089
|
-
const v = readSnippet(`object.${fieldName}`);
|
|
1090
|
-
const type = types_1.basicTypeName(ctx, field);
|
|
1091
|
-
chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
|
|
1092
|
-
chunks.push(ts_poet_1.code `message.${fieldName} = ${v} as ${type};`);
|
|
1093
|
-
chunks.push(ts_poet_1.code `} else {`);
|
|
1094
|
-
const fallback = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
|
|
1095
|
-
chunks.push(ts_poet_1.code `message.${fieldName} = ${fallback}`);
|
|
1096
|
-
chunks.push(ts_poet_1.code `}`);
|
|
1097
|
-
}
|
|
1098
|
-
else if (types_1.isPrimitive(field) ||
|
|
1099
|
-
(types_1.isTimestamp(field) && (options.useDate === options_1.DateOption.DATE || options.useDate === options_1.DateOption.STRING)) ||
|
|
1100
|
-
types_1.isValueType(ctx, field)) {
|
|
1088
|
+
else if (readSnippet(`x`).toCodeString() == 'x') {
|
|
1101
1089
|
// An optimized case of the else below that works when `readSnippet` returns the plain input
|
|
1102
1090
|
const fallback = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
|
|
1103
1091
|
chunks.push(ts_poet_1.code `message.${fieldName} = object.${fieldName} ?? ${fallback};`);
|
|
1104
1092
|
}
|
|
1105
1093
|
else {
|
|
1106
|
-
chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
|
|
1107
|
-
chunks.push(ts_poet_1.code `message.${fieldName} = ${readSnippet(`object.${fieldName}`)};`);
|
|
1108
|
-
chunks.push(ts_poet_1.code `} else {`);
|
|
1109
1094
|
const fallback = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
|
|
1110
|
-
chunks.push(ts_poet_1.code `
|
|
1111
|
-
|
|
1095
|
+
chunks.push(ts_poet_1.code `
|
|
1096
|
+
message.${fieldName} = (object.${fieldName} !== undefined && object.${fieldName} !== null)
|
|
1097
|
+
? ${readSnippet(`object.${fieldName}`)}
|
|
1098
|
+
: ${fallback};
|
|
1099
|
+
`);
|
|
1112
1100
|
}
|
|
1113
1101
|
});
|
|
1114
1102
|
// and then wrap up the switch/while/return
|
package/build/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.detectBatchMethod = exports.responseObservable = exports.responsePromise = exports.responseType = exports.requestType = exports.detectMapType = exports.toTypeName = exports.getEnumMethod = exports.messageToTypeName = exports.wrapperTypeName = exports.valueTypeName = exports.isEmptyType = exports.isLongValueType = exports.isBytesValueType = exports.isValueType = exports.isTimestamp = exports.isMapType = exports.isLong = exports.isRepeated = exports.isWithinOneOfThatShouldBeUnion = exports.isWithinOneOf = exports.isEnum = exports.isMessage = exports.isBytes = exports.isPrimitive = exports.isScalar = exports.createTypeMap = exports.notDefaultCheck = exports.defaultValue = exports.packedType = exports.toReaderCall = exports.basicTypeName = exports.basicLongWireType = exports.basicWireType = void 0;
|
|
3
|
+
exports.detectBatchMethod = exports.responsePromiseOrObservable = exports.responseObservable = exports.responsePromise = exports.responseType = exports.requestType = exports.rawRequestType = exports.detectMapType = exports.toTypeName = exports.getEnumMethod = exports.messageToTypeName = exports.wrapperTypeName = exports.valueTypeName = exports.isEmptyType = exports.isLongValueType = exports.isBytesValueType = exports.isValueType = exports.isTimestamp = exports.isMapType = exports.isLong = exports.isRepeated = exports.isWithinOneOfThatShouldBeUnion = exports.isWithinOneOf = exports.isEnum = exports.isMessage = exports.isBytes = exports.isPrimitive = exports.isScalar = exports.createTypeMap = exports.notDefaultCheck = exports.defaultValue = exports.packedType = exports.toReaderCall = exports.basicTypeName = exports.basicLongWireType = exports.basicWireType = void 0;
|
|
4
4
|
const ts_proto_descriptors_1 = require("ts-proto-descriptors");
|
|
5
5
|
const ts_poet_1 = require("ts-poet");
|
|
6
6
|
const options_1 = require("./options");
|
|
@@ -512,8 +512,12 @@ function detectMapType(ctx, messageDesc, fieldDesc) {
|
|
|
512
512
|
return undefined;
|
|
513
513
|
}
|
|
514
514
|
exports.detectMapType = detectMapType;
|
|
515
|
+
function rawRequestType(ctx, methodDesc) {
|
|
516
|
+
return messageToTypeName(ctx, methodDesc.inputType);
|
|
517
|
+
}
|
|
518
|
+
exports.rawRequestType = rawRequestType;
|
|
515
519
|
function requestType(ctx, methodDesc) {
|
|
516
|
-
let typeName =
|
|
520
|
+
let typeName = rawRequestType(ctx, methodDesc);
|
|
517
521
|
if (methodDesc.clientStreaming) {
|
|
518
522
|
return ts_poet_1.code `${ts_poet_1.imp('Observable@rxjs')}<${typeName}>`;
|
|
519
523
|
}
|
|
@@ -532,6 +536,14 @@ function responseObservable(ctx, methodDesc) {
|
|
|
532
536
|
return ts_poet_1.code `${ts_poet_1.imp('Observable@rxjs')}<${responseType(ctx, methodDesc)}>`;
|
|
533
537
|
}
|
|
534
538
|
exports.responseObservable = responseObservable;
|
|
539
|
+
function responsePromiseOrObservable(ctx, methodDesc) {
|
|
540
|
+
const { options } = ctx;
|
|
541
|
+
if (options.returnObservable || methodDesc.serverStreaming) {
|
|
542
|
+
return responseObservable(ctx, methodDesc);
|
|
543
|
+
}
|
|
544
|
+
return responsePromise(ctx, methodDesc);
|
|
545
|
+
}
|
|
546
|
+
exports.responsePromiseOrObservable = responsePromiseOrObservable;
|
|
535
547
|
function detectBatchMethod(ctx, fileDesc, serviceDesc, methodDesc) {
|
|
536
548
|
const { typeMap } = ctx;
|
|
537
549
|
const nameMatches = methodDesc.name.startsWith('Batch');
|