ts-proto 1.111.0 → 1.112.2

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,29 @@
1
+ ## [1.112.2](https://github.com/stephenh/ts-proto/compare/v1.112.1...v1.112.2) (2022-05-18)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * enum type returns 'UNRECOGNIZED' or '-1' in xxxToJSON/xxxToNumber ([#566](https://github.com/stephenh/ts-proto/issues/566)) ([19911a1](https://github.com/stephenh/ts-proto/commit/19911a1c62e3fe5c8a0eb0a795489340512898da))
7
+
8
+ ## [1.112.1](https://github.com/stephenh/ts-proto/compare/v1.112.0...v1.112.1) (2022-05-06)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * use Long.fromValue instead of Long.fromString ([#562](https://github.com/stephenh/ts-proto/issues/562)) ([c99891e](https://github.com/stephenh/ts-proto/commit/c99891e0fec6d9b7225025eb0c5bd7393e80af36))
14
+
15
+ # [1.112.0](https://github.com/stephenh/ts-proto/compare/v1.111.0...v1.112.0) (2022-05-02)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * update codegen for `nice-grpc` ([#561](https://github.com/stephenh/ts-proto/issues/561)) ([d503f67](https://github.com/stephenh/ts-proto/commit/d503f677922402e880b5d8502b3d8bc099b7f39d))
21
+
22
+
23
+ ### Features
24
+
25
+ * add support for generating `nice-grpc` server and client stubs ([#555](https://github.com/stephenh/ts-proto/issues/555)) ([8c19361](https://github.com/stephenh/ts-proto/commit/8c19361ede9a7a039acf3a1375913d012b0fcb7d)), closes [#545](https://github.com/stephenh/ts-proto/issues/545)
26
+
1
27
  # [1.111.0](https://github.com/stephenh/ts-proto/compare/v1.110.4...v1.111.0) (2022-05-01)
2
28
 
3
29
 
package/README.markdown CHANGED
@@ -362,6 +362,8 @@ Generated code will be placed in the Gradle build directory.
362
362
 
363
363
  - With `--ts_proto_opt=outputServices=generic-definitions`, ts-proto will output generic (framework-agnostic) service definitions. These definitions contain descriptors for each method with links to request and response types, which allows to generate server and client stubs at runtime, and also generate strong types for them at compile time. An example of a library that uses this approach is [nice-grpc](https://github.com/deeplay-io/nice-grpc).
364
364
 
365
+ - With `--ts_proto_opt=outputServices=nice-grpc`, ts-proto will output server and client stubs for [nice-grpc](https://github.com/deeplay-io/nice-grpc). This should be used together with generic definitions, i.e. you should specify two options: `outputServices=nice-grpc,outputServices=generic-definitions`.
366
+
365
367
  - With `--ts_proto_opt=metadataType=Foo@./some-file`, ts-proto add a generic (framework-agnostic) metadata field to the generic service definition.
366
368
 
367
369
  - With `--ts_proto_opt=outputServices=generic-definitions,outputServices=default`, ts-proto will output both generic definitions and interfaces. This is useful if you want to rely on the interfaces, but also have some reflection capabilities at runtime.
package/build/enums.js CHANGED
@@ -43,11 +43,11 @@ function generateEnum(ctx, fullName, enumDesc, sourceInfo) {
43
43
  }
44
44
  if (options.outputJsonMethods) {
45
45
  chunks.push(ts_poet_1.code `\n`);
46
- chunks.push(generateEnumToJson(fullName, enumDesc));
46
+ chunks.push(generateEnumToJson(ctx, fullName, enumDesc));
47
47
  }
48
48
  if (options.stringEnums && options.outputEncodeMethods) {
49
49
  chunks.push(ts_poet_1.code `\n`);
50
- chunks.push(generateEnumToNumber(fullName, enumDesc));
50
+ chunks.push(generateEnumToNumber(ctx, fullName, enumDesc));
51
51
  }
52
52
  return ts_poet_1.joinCode(chunks, { on: '\n' });
53
53
  }
@@ -87,7 +87,8 @@ function generateEnumFromJson(ctx, fullName, enumDesc) {
87
87
  }
88
88
  exports.generateEnumFromJson = generateEnumFromJson;
89
89
  /** Generates a function with a big switch statement to encode our enum -> JSON. */
90
- function generateEnumToJson(fullName, enumDesc) {
90
+ function generateEnumToJson(ctx, fullName, enumDesc) {
91
+ const { options, utils } = ctx;
91
92
  const chunks = [];
92
93
  const functionName = case_1.camelCase(fullName) + 'ToJSON';
93
94
  chunks.push(ts_poet_1.code `export function ${ts_poet_1.def(functionName)}(object: ${fullName}): string {`);
@@ -95,14 +96,28 @@ function generateEnumToJson(fullName, enumDesc) {
95
96
  for (const valueDesc of enumDesc.value) {
96
97
  chunks.push(ts_poet_1.code `case ${fullName}.${valueDesc.name}: return "${valueDesc.name}";`);
97
98
  }
98
- chunks.push(ts_poet_1.code `default: return "UNKNOWN";`);
99
+ if (options.unrecognizedEnum) {
100
+ chunks.push(ts_poet_1.code `
101
+ case ${fullName}.${UNRECOGNIZED_ENUM_NAME}:
102
+ default:
103
+ return "${UNRECOGNIZED_ENUM_NAME}";
104
+ `);
105
+ }
106
+ else {
107
+ // We use globalThis to avoid conflicts on protobuf types named `Error`.
108
+ chunks.push(ts_poet_1.code `
109
+ default:
110
+ throw new ${utils.globalThis}.Error("Unrecognized enum value " + object + " for enum ${fullName}");
111
+ `);
112
+ }
99
113
  chunks.push(ts_poet_1.code `}`);
100
114
  chunks.push(ts_poet_1.code `}`);
101
115
  return ts_poet_1.joinCode(chunks, { on: '\n' });
102
116
  }
103
117
  exports.generateEnumToJson = generateEnumToJson;
104
118
  /** Generates a function with a big switch statement to encode our string enum -> int value. */
105
- function generateEnumToNumber(fullName, enumDesc) {
119
+ function generateEnumToNumber(ctx, fullName, enumDesc) {
120
+ const { options, utils } = ctx;
106
121
  const chunks = [];
107
122
  const functionName = case_1.camelCase(fullName) + 'ToNumber';
108
123
  chunks.push(ts_poet_1.code `export function ${ts_poet_1.def(functionName)}(object: ${fullName}): number {`);
@@ -110,7 +125,20 @@ function generateEnumToNumber(fullName, enumDesc) {
110
125
  for (const valueDesc of enumDesc.value) {
111
126
  chunks.push(ts_poet_1.code `case ${fullName}.${valueDesc.name}: return ${valueDesc.number};`);
112
127
  }
113
- chunks.push(ts_poet_1.code `default: return 0;`);
128
+ if (options.unrecognizedEnum) {
129
+ chunks.push(ts_poet_1.code `
130
+ case ${fullName}.${UNRECOGNIZED_ENUM_NAME}:
131
+ default:
132
+ return ${UNRECOGNIZED_ENUM_VALUE};
133
+ `);
134
+ }
135
+ else {
136
+ // We use globalThis to avoid conflicts on protobuf types named `Error`.
137
+ chunks.push(ts_poet_1.code `
138
+ default:
139
+ throw new ${utils.globalThis}.Error("Unrecognized enum value " + object + " for enum ${fullName}");
140
+ `);
141
+ }
114
142
  chunks.push(ts_poet_1.code `}`);
115
143
  chunks.push(ts_poet_1.code `}`);
116
144
  return ts_poet_1.joinCode(chunks, { on: '\n' });
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateNiceGrpcService = void 0;
4
+ const ts_poet_1 = require("ts-poet");
5
+ const case_1 = require("./case");
6
+ const sourceInfo_1 = require("./sourceInfo");
7
+ const types_1 = require("./types");
8
+ const utils_1 = require("./utils");
9
+ const CallOptions = ts_poet_1.imp('CallOptions@nice-grpc-common');
10
+ const CallContext = ts_poet_1.imp('CallContext@nice-grpc-common');
11
+ /**
12
+ * Generates server / client stubs for `nice-grpc` library.
13
+ */
14
+ function generateNiceGrpcService(ctx, fileDesc, sourceInfo, serviceDesc) {
15
+ const chunks = [];
16
+ chunks.push(generateServerStub(ctx, sourceInfo, serviceDesc));
17
+ chunks.push(generateClientStub(ctx, sourceInfo, serviceDesc));
18
+ return ts_poet_1.joinCode(chunks, { on: '\n\n' });
19
+ }
20
+ exports.generateNiceGrpcService = generateNiceGrpcService;
21
+ function generateServerStub(ctx, sourceInfo, serviceDesc) {
22
+ var _a;
23
+ const chunks = [];
24
+ chunks.push(ts_poet_1.code `export interface ${ts_poet_1.def(`${serviceDesc.name}ServiceImplementation`)}<CallContextExt = {}> {`);
25
+ for (const [index, methodDesc] of serviceDesc.method.entries()) {
26
+ utils_1.assertInstanceOf(methodDesc, utils_1.FormattedMethodDescriptor);
27
+ const inputType = types_1.messageToTypeName(ctx, methodDesc.inputType, { keepValueType: true });
28
+ let outputType = types_1.messageToTypeName(ctx, methodDesc.outputType, { keepValueType: true });
29
+ if (ctx.options.outputPartialMethods) {
30
+ outputType = ts_poet_1.code `${ctx.utils.DeepPartial}<${outputType}>`;
31
+ }
32
+ const ServerStreamingMethodResult = ctx.utils.NiceGrpcServerStreamingMethodResult;
33
+ const info = sourceInfo.lookup(sourceInfo_1.Fields.service.method, index);
34
+ utils_1.maybeAddComment(info, chunks, (_a = methodDesc.options) === null || _a === void 0 ? void 0 : _a.deprecated);
35
+ if (methodDesc.clientStreaming) {
36
+ if (methodDesc.serverStreaming) {
37
+ // bidi streaming
38
+ chunks.push(ts_poet_1.code `
39
+ ${case_1.camelCase(methodDesc.name)}(
40
+ request: AsyncIterable<${inputType}>,
41
+ context: ${CallContext} & CallContextExt,
42
+ ): ${ServerStreamingMethodResult}<${outputType}>;
43
+ `);
44
+ }
45
+ else {
46
+ // client streaming
47
+ chunks.push(ts_poet_1.code `
48
+ ${case_1.camelCase(methodDesc.name)}(
49
+ request: AsyncIterable<${inputType}>,
50
+ context: ${CallContext} & CallContextExt,
51
+ ): Promise<${outputType}>;
52
+ `);
53
+ }
54
+ }
55
+ else {
56
+ if (methodDesc.serverStreaming) {
57
+ // server streaming
58
+ chunks.push(ts_poet_1.code `
59
+ ${case_1.camelCase(methodDesc.name)}(
60
+ request: ${inputType},
61
+ context: ${CallContext} & CallContextExt,
62
+ ): ${ServerStreamingMethodResult}<${outputType}>;
63
+ `);
64
+ }
65
+ else {
66
+ // unary
67
+ chunks.push(ts_poet_1.code `
68
+ ${case_1.camelCase(methodDesc.name)}(
69
+ request: ${inputType},
70
+ context: ${CallContext} & CallContextExt,
71
+ ): Promise<${outputType}>;
72
+ `);
73
+ }
74
+ }
75
+ }
76
+ chunks.push(ts_poet_1.code `}`);
77
+ return ts_poet_1.joinCode(chunks, { on: '\n' });
78
+ }
79
+ function generateClientStub(ctx, sourceInfo, serviceDesc) {
80
+ var _a;
81
+ const chunks = [];
82
+ chunks.push(ts_poet_1.code `export interface ${ts_poet_1.def(`${serviceDesc.name}Client`)}<CallOptionsExt = {}> {`);
83
+ for (const [index, methodDesc] of serviceDesc.method.entries()) {
84
+ utils_1.assertInstanceOf(methodDesc, utils_1.FormattedMethodDescriptor);
85
+ let inputType = types_1.messageToTypeName(ctx, methodDesc.inputType, { keepValueType: true });
86
+ if (ctx.options.outputPartialMethods) {
87
+ inputType = ts_poet_1.code `${ctx.utils.DeepPartial}<${inputType}>`;
88
+ }
89
+ const outputType = types_1.messageToTypeName(ctx, methodDesc.outputType, { keepValueType: true });
90
+ const info = sourceInfo.lookup(sourceInfo_1.Fields.service.method, index);
91
+ utils_1.maybeAddComment(info, chunks, (_a = methodDesc.options) === null || _a === void 0 ? void 0 : _a.deprecated);
92
+ if (methodDesc.clientStreaming) {
93
+ if (methodDesc.serverStreaming) {
94
+ // bidi streaming
95
+ chunks.push(ts_poet_1.code `
96
+ ${case_1.camelCase(methodDesc.name)}(
97
+ request: AsyncIterable<${inputType}>,
98
+ options?: ${CallOptions} & CallOptionsExt,
99
+ ): AsyncIterable<${outputType}>;
100
+ `);
101
+ }
102
+ else {
103
+ // client streaming
104
+ chunks.push(ts_poet_1.code `
105
+ ${case_1.camelCase(methodDesc.name)}(
106
+ request: AsyncIterable<${inputType}>,
107
+ options?: ${CallOptions} & CallOptionsExt,
108
+ ): Promise<${outputType}>;
109
+ `);
110
+ }
111
+ }
112
+ else {
113
+ if (methodDesc.serverStreaming) {
114
+ // server streaming
115
+ chunks.push(ts_poet_1.code `
116
+ ${case_1.camelCase(methodDesc.name)}(
117
+ request: ${inputType},
118
+ options?: ${CallOptions} & CallOptionsExt,
119
+ ): AsyncIterable<${outputType}>;
120
+ `);
121
+ }
122
+ else {
123
+ // unary
124
+ chunks.push(ts_poet_1.code `
125
+ ${case_1.camelCase(methodDesc.name)}(
126
+ request: ${inputType},
127
+ options?: ${CallOptions} & CallOptionsExt,
128
+ ): Promise<${outputType}>;
129
+ `);
130
+ }
131
+ }
132
+ }
133
+ chunks.push(ts_poet_1.code `}`);
134
+ return ts_poet_1.joinCode(chunks, { on: '\n' });
135
+ }
package/build/main.js CHANGED
@@ -16,6 +16,7 @@ const schema_1 = require("./schema");
16
16
  const ConditionalOutput_1 = require("ts-poet/build/ConditionalOutput");
17
17
  const generate_grpc_js_1 = require("./generate-grpc-js");
18
18
  const generate_generic_service_definition_1 = require("./generate-generic-service-definition");
19
+ const generate_nice_grpc_1 = require("./generate-nice-grpc");
19
20
  function generateFile(ctx, fileDesc) {
20
21
  var _a;
21
22
  const { options, utils } = ctx;
@@ -124,6 +125,9 @@ function generateFile(ctx, fileDesc) {
124
125
  if (outputService === options_1.ServiceOption.GRPC) {
125
126
  chunks.push(generate_grpc_js_1.generateGrpcJsService(ctx, fileDesc, sInfo, serviceDesc));
126
127
  }
128
+ else if (outputService === options_1.ServiceOption.NICE_GRPC) {
129
+ chunks.push(generate_nice_grpc_1.generateNiceGrpcService(ctx, fileDesc, sInfo, serviceDesc));
130
+ }
127
131
  else if (outputService === options_1.ServiceOption.GENERIC) {
128
132
  chunks.push(generate_generic_service_definition_1.generateGenericServiceDefinition(ctx, fileDesc, sInfo, serviceDesc));
129
133
  }
@@ -206,6 +210,7 @@ function makeUtils(options) {
206
210
  ...makeTimestampMethods(options, longs),
207
211
  ...longs,
208
212
  ...makeComparisonUtils(),
213
+ ...makeNiceGrpcServerStreamingMethodResult(),
209
214
  };
210
215
  }
211
216
  exports.makeUtils = makeUtils;
@@ -444,6 +449,14 @@ function makeComparisonUtils() {
444
449
  }`);
445
450
  return { isObject, isSet };
446
451
  }
452
+ function makeNiceGrpcServerStreamingMethodResult() {
453
+ const NiceGrpcServerStreamingMethodResult = ts_poet_1.conditionalOutput('ServerStreamingMethodResult', ts_poet_1.code `
454
+ export type ServerStreamingMethodResult<Response> = {
455
+ [Symbol.asyncIterator](): AsyncIterator<Response, void>;
456
+ };
457
+ `);
458
+ return { NiceGrpcServerStreamingMethodResult };
459
+ }
447
460
  // Create the interface with properties
448
461
  function generateInterfaceDeclaration(ctx, fullName, messageDesc, sourceInfo, fullTypeName) {
449
462
  var _a;
@@ -935,7 +948,7 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
935
948
  }
936
949
  else if (types_1.isLong(field) && options.forceLong === options_1.LongOption.LONG) {
937
950
  const cstr = case_1.capitalize(types_1.basicTypeName(ctx, field, { keepValueType: true }).toCodeString());
938
- return ts_poet_1.code `${cstr}.fromString(${from})`;
951
+ return ts_poet_1.code `${cstr}.fromValue(${from})`;
939
952
  }
940
953
  else {
941
954
  const cstr = case_1.capitalize(types_1.basicTypeName(ctx, field, { keepValueType: true }).toCodeString());
package/build/options.js CHANGED
@@ -27,6 +27,7 @@ var OneofOption;
27
27
  var ServiceOption;
28
28
  (function (ServiceOption) {
29
29
  ServiceOption["GRPC"] = "grpc-js";
30
+ ServiceOption["NICE_GRPC"] = "nice-grpc";
30
31
  ServiceOption["GENERIC"] = "generic-definitions";
31
32
  ServiceOption["DEFAULT"] = "default";
32
33
  ServiceOption["NONE"] = "none";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "1.111.0",
3
+ "version": "1.112.2",
4
4
  "description": "",
5
5
  "main": "build/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",
@@ -50,6 +50,7 @@
50
50
  "chokidar": "^3.5.2",
51
51
  "jest": "^26.6.3",
52
52
  "mongodb": "^4.3.0",
53
+ "nice-grpc": "^1.1.1",
53
54
  "prettier": "^2.2.1",
54
55
  "reflect-metadata": "^0.1.13",
55
56
  "rxjs": "^7.4.0",