ts-proto 1.83.3 → 1.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ # [1.87.0](https://github.com/stephenh/ts-proto/compare/v1.86.0...v1.87.0) (2021-11-16)
2
+
3
+
4
+ ### Features
5
+
6
+ * Use ternary operator for conditional assignments ([#394](https://github.com/stephenh/ts-proto/issues/394)) ([d84c084](https://github.com/stephenh/ts-proto/commit/d84c084fb56c958c184f8971479979b8bfb17ccc))
7
+
8
+ # [1.86.0](https://github.com/stephenh/ts-proto/compare/v1.85.0...v1.86.0) (2021-11-15)
9
+
10
+
11
+ ### Features
12
+
13
+ * Initialize lists with map ([#387](https://github.com/stephenh/ts-proto/issues/387)) ([200e674](https://github.com/stephenh/ts-proto/commit/200e674e4baf2640d67720ad535fe042d291d4a0))
14
+
15
+ # [1.85.0](https://github.com/stephenh/ts-proto/compare/v1.84.0...v1.85.0) (2021-11-02)
16
+
17
+
18
+ ### Features
19
+
20
+ * Streaming support ([#373](https://github.com/stephenh/ts-proto/issues/373)) ([459b94f](https://github.com/stephenh/ts-proto/commit/459b94f5b2988d58d186461332e888c3e511603a))
21
+
22
+ # [1.84.0](https://github.com/stephenh/ts-proto/compare/v1.83.3...v1.84.0) (2021-11-02)
23
+
24
+
25
+ ### Features
26
+
27
+ * Reduce code size by using nullish coalescing operator in fromPartial ([#376](https://github.com/stephenh/ts-proto/issues/376)) ([19d2ded](https://github.com/stephenh/ts-proto/commit/19d2deda2cf7c47b1b56bfc65cf58653291dba4a))
28
+
1
29
  ## [1.83.3](https://github.com/stephenh/ts-proto/compare/v1.83.2...v1.83.3) (2021-10-28)
2
30
 
3
31
 
@@ -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 = options.returnObservable || methodDesc.serverStreaming
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
- // Return observable for interface only configuration, passing returnObservable=true and methodDesc.serverStreaming=true
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.responsePromise(ctx, methodDesc)} {
94
- const data = ${inputType}.encode(request).finish();
95
- const promise = this.rpc.request(
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 promise.then(data => ${outputType}.decode(new ${Reader}(data)));
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
- return ts_poet_1.code `
229
- interface Rpc${maybeContext} {
230
- request(
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: Uint8Array
235
- ): Promise<Uint8Array>;
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
- hasStreamingMethods = true;
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, hasStreamingMethods));
145
+ chunks.push(generate_grpc_web_1.addGrpcWebMisc(ctx, hasServerStreamingMethods));
141
146
  }
142
147
  }
143
148
  if (options.context) {
@@ -733,20 +738,6 @@ function generateFromJson(ctx, fullName, messageDesc) {
733
738
  fromJSON(${messageDesc.field.length > 0 ? 'object' : '_'}: any): ${fullName} {
734
739
  const message = { ...base${fullName} } as ${fullName};
735
740
  `);
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
741
  // add a check for each incoming field
751
742
  messageDesc.field.forEach((field) => {
752
743
  const fieldName = case_1.maybeSnakeToCamel(field.name, options);
@@ -841,42 +832,41 @@ function generateFromJson(ctx, fullName, messageDesc) {
841
832
  }
842
833
  };
843
834
  // 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
835
  if (types_1.isRepeated(field)) {
846
836
  if (types_1.isMapType(ctx, messageDesc, field)) {
837
+ chunks.push(ts_poet_1.code `message.${fieldName} = {};`);
838
+ chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
847
839
  const i = maybeCastToNumber(ctx, messageDesc, field, 'key');
848
840
  chunks.push(ts_poet_1.code `
849
841
  Object.entries(object.${fieldName}).forEach(([key, value]) => {
850
842
  message.${fieldName}[${i}] = ${readSnippet('value')};
851
843
  });
852
844
  `);
845
+ chunks.push(ts_poet_1.code `}`);
853
846
  }
854
847
  else {
848
+ // Explicit `any` type required to make TS with noImplicitAny happy. `object` is also `any` here.
855
849
  chunks.push(ts_poet_1.code `
856
- for (const e of object.${fieldName}) {
857
- message.${fieldName}.push(${readSnippet('e')});
858
- }
850
+ message.${fieldName} = (object.${fieldName} ?? []).map((e: any) => ${readSnippet('e')});
859
851
  `);
860
852
  }
861
853
  }
862
854
  else if (types_1.isWithinOneOfThatShouldBeUnion(options, field)) {
855
+ chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
863
856
  const oneofName = case_1.maybeSnakeToCamel(messageDesc.oneofDecl[field.oneofIndex].name, options);
864
857
  chunks.push(ts_poet_1.code `
865
858
  message.${oneofName} = { $case: '${fieldName}', ${fieldName}: ${readSnippet(`object.${fieldName}`)} }
866
859
  `);
860
+ chunks.push(ts_poet_1.code `}`);
867
861
  }
868
862
  else {
869
- chunks.push(ts_poet_1.code `message.${fieldName} = ${readSnippet(`object.${fieldName}`)};`);
870
- }
871
- // set the default value (TODO Support bytes)
872
- if (!types_1.isRepeated(field) &&
873
- field.type !== ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_BYTES &&
874
- options.oneof !== options_1.OneofOption.UNIONS) {
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};`);
863
+ const fallback = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
864
+ chunks.push(ts_poet_1.code `
865
+ message.${fieldName} = (object.${fieldName} !== undefined && object.${fieldName} !== null)
866
+ ? ${readSnippet(`object.${fieldName}`)}
867
+ : ${fallback};
868
+ `);
878
869
  }
879
- chunks.push(ts_poet_1.code `}`);
880
870
  });
881
871
  // and then wrap up the switch/while/return
882
872
  chunks.push(ts_poet_1.code `return message`);
@@ -1002,12 +992,6 @@ function generateFromPartial(ctx, fullName, messageDesc) {
1002
992
  fromPartial(${messageDesc.field.length > 0 ? 'object' : '_'}: ${utils.DeepPartial}<${fullName}>): ${fullName} {
1003
993
  const message = { ...base${fullName} } as ${fullName};
1004
994
  `);
1005
- // initialize all lists
1006
- messageDesc.field.filter(types_1.isRepeated).forEach((field) => {
1007
- const value = types_1.isMapType(ctx, messageDesc, field) ? '{}' : '[]';
1008
- const name = case_1.maybeSnakeToCamel(field.name, options);
1009
- chunks.push(ts_poet_1.code `message.${name} = ${value};`);
1010
- });
1011
995
  // add a check for each incoming field
1012
996
  messageDesc.field.forEach((field) => {
1013
997
  const fieldName = case_1.maybeSnakeToCamel(field.name, options);
@@ -1055,8 +1039,9 @@ function generateFromPartial(ctx, fullName, messageDesc) {
1055
1039
  };
1056
1040
  // and then use the snippet to handle repeated fields if necessary
1057
1041
  if (types_1.isRepeated(field)) {
1058
- chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
1059
1042
  if (types_1.isMapType(ctx, messageDesc, field)) {
1043
+ chunks.push(ts_poet_1.code `message.${fieldName} = {};`);
1044
+ chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
1060
1045
  const i = maybeCastToNumber(ctx, messageDesc, field, 'key');
1061
1046
  chunks.push(ts_poet_1.code `
1062
1047
  Object.entries(object.${fieldName}).forEach(([key, value]) => {
@@ -1065,12 +1050,11 @@ function generateFromPartial(ctx, fullName, messageDesc) {
1065
1050
  }
1066
1051
  });
1067
1052
  `);
1053
+ chunks.push(ts_poet_1.code `}`);
1068
1054
  }
1069
1055
  else {
1070
1056
  chunks.push(ts_poet_1.code `
1071
- for (const e of object.${fieldName}) {
1072
- message.${fieldName}.push(${readSnippet('e')});
1073
- }
1057
+ message.${fieldName} = (object.${fieldName} ?? []).map((e) => ${readSnippet('e')});
1074
1058
  `);
1075
1059
  }
1076
1060
  }
@@ -1084,25 +1068,32 @@ function generateFromPartial(ctx, fullName, messageDesc) {
1084
1068
  && object.${oneofName}?.${fieldName} !== null
1085
1069
  ) {
1086
1070
  message.${oneofName} = { $case: '${fieldName}', ${fieldName}: ${v} };
1071
+ }
1087
1072
  `);
1088
1073
  }
1089
- else {
1074
+ else if ((types_1.isLong(field) || types_1.isLongValueType(field)) && options.forceLong === options_1.LongOption.LONG) {
1075
+ const v = readSnippet(`object.${fieldName}`);
1076
+ const type = types_1.basicTypeName(ctx, field);
1090
1077
  chunks.push(ts_poet_1.code `if (object.${fieldName} !== undefined && object.${fieldName} !== null) {`);
1091
- if ((types_1.isLong(field) || types_1.isLongValueType(field)) && options.forceLong === options_1.LongOption.LONG) {
1092
- const v = readSnippet(`object.${fieldName}`);
1093
- const type = types_1.basicTypeName(ctx, field);
1094
- chunks.push(ts_poet_1.code `message.${fieldName} = ${v} as ${type};`);
1095
- }
1096
- else {
1097
- chunks.push(ts_poet_1.code `message.${fieldName} = ${readSnippet(`object.${fieldName}`)};`);
1098
- }
1099
- }
1100
- if (!types_1.isRepeated(field) && !types_1.isWithinOneOfThatShouldBeUnion(options, field)) {
1078
+ chunks.push(ts_poet_1.code `message.${fieldName} = ${v} as ${type};`);
1101
1079
  chunks.push(ts_poet_1.code `} else {`);
1102
- const v = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
1103
- chunks.push(ts_poet_1.code `message.${fieldName} = ${v}`);
1080
+ const fallback = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
1081
+ chunks.push(ts_poet_1.code `message.${fieldName} = ${fallback}`);
1082
+ chunks.push(ts_poet_1.code `}`);
1083
+ }
1084
+ else if (readSnippet(`x`).toCodeString() == 'x') {
1085
+ // An optimized case of the else below that works when `readSnippet` returns the plain input
1086
+ const fallback = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
1087
+ chunks.push(ts_poet_1.code `message.${fieldName} = object.${fieldName} ?? ${fallback};`);
1088
+ }
1089
+ else {
1090
+ const fallback = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
1091
+ chunks.push(ts_poet_1.code `
1092
+ message.${fieldName} = (object.${fieldName} !== undefined && object.${fieldName} !== null)
1093
+ ? ${readSnippet(`object.${fieldName}`)}
1094
+ : ${fallback};
1095
+ `);
1104
1096
  }
1105
- chunks.push(ts_poet_1.code `}`);
1106
1097
  });
1107
1098
  // and then wrap up the switch/while/return
1108
1099
  chunks.push(ts_poet_1.code `return message;`);
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 = messageToTypeName(ctx, methodDesc.inputType);
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');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "1.83.3",
3
+ "version": "1.87.0",
4
4
  "description": "",
5
5
  "main": "build/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",