ts-proto 1.118.0 → 1.119.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 +7 -0
- package/README.markdown +7 -0
- package/build/generate-grpc-web.js +75 -13
- package/build/generate-services.js +8 -1
- package/build/main.js +2 -8
- package/build/types.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [1.119.0](https://github.com/stephenh/ts-proto/compare/v1.118.0...v1.119.0) (2022-07-21)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* support grpc-web client straming ([#617](https://github.com/stephenh/ts-proto/issues/617)) ([d3e7f1f](https://github.com/stephenh/ts-proto/commit/d3e7f1f4aac12db87c54d6357e557a351c96a2ca))
|
|
7
|
+
|
|
1
8
|
# [1.118.0](https://github.com/stephenh/ts-proto/compare/v1.117.1...v1.118.0) (2022-07-19)
|
|
2
9
|
|
|
3
10
|
|
package/README.markdown
CHANGED
|
@@ -99,6 +99,13 @@ plugins:
|
|
|
99
99
|
path: ../node_modules/ts-proto/protoc-gen-ts_proto
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
+
To prevent `buf push` from reading irrelevent `.proto` files, configure `buf.yaml` like so:
|
|
103
|
+
|
|
104
|
+
```yaml
|
|
105
|
+
build:
|
|
106
|
+
excludes: [node_modules]
|
|
107
|
+
```
|
|
108
|
+
|
|
102
109
|
You can also use the official plugin published to the Buf Registry.
|
|
103
110
|
|
|
104
111
|
```yaml
|
|
@@ -18,7 +18,7 @@ function generateGrpcClientImpl(ctx, _fileDesc, serviceDesc) {
|
|
|
18
18
|
// Create the constructor(rpc: Rpc)
|
|
19
19
|
chunks.push((0, ts_poet_1.code) `
|
|
20
20
|
private readonly rpc: Rpc;
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
constructor(rpc: Rpc) {
|
|
23
23
|
`);
|
|
24
24
|
chunks.push((0, ts_poet_1.code) `this.rpc = rpc;`);
|
|
@@ -46,9 +46,11 @@ function generateRpcMethod(ctx, serviceDesc, methodDesc) {
|
|
|
46
46
|
return (0, ts_poet_1.code) `
|
|
47
47
|
${methodDesc.formattedName}(
|
|
48
48
|
request: ${inputType},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
options?: {
|
|
50
|
+
metadata?: grpc.Metadata,
|
|
51
|
+
rpcOptions?: grpc.RpcOptions,
|
|
52
|
+
}): ${returns} {
|
|
53
|
+
return this.rpc.stream(${methodDescName(serviceDesc, methodDesc)}, request, options?.metadata, options?.rpcOptions)
|
|
52
54
|
}
|
|
53
55
|
`;
|
|
54
56
|
}
|
|
@@ -83,7 +85,7 @@ exports.generateGrpcServiceDesc = generateGrpcServiceDesc;
|
|
|
83
85
|
* implementation.
|
|
84
86
|
*/
|
|
85
87
|
function generateGrpcMethodDesc(ctx, serviceDesc, methodDesc) {
|
|
86
|
-
const inputType = (0, types_1.
|
|
88
|
+
const inputType = (0, types_1.rawRequestType)(ctx, methodDesc);
|
|
87
89
|
const outputType = (0, types_1.responseType)(ctx, methodDesc);
|
|
88
90
|
// grpc-web expects this to be a class, but the ts-proto messages are just interfaces.
|
|
89
91
|
//
|
|
@@ -109,13 +111,15 @@ function generateGrpcMethodDesc(ctx, serviceDesc, methodDesc) {
|
|
|
109
111
|
deserializeBinary(data: Uint8Array) {
|
|
110
112
|
return { ...${outputType}.decode(data), toObject() { return this; } };
|
|
111
113
|
}
|
|
112
|
-
|
|
114
|
+
}`;
|
|
115
|
+
const streaming = methodDesc.clientStreaming || methodDesc.serverStreaming;
|
|
116
|
+
const methodDef = streaming ? 'MethodDefinitionish' : 'UnaryMethodDefinitionish';
|
|
113
117
|
return (0, ts_poet_1.code) `
|
|
114
|
-
export const ${methodDescName(serviceDesc, methodDesc)}:
|
|
118
|
+
export const ${methodDescName(serviceDesc, methodDesc)}: ${methodDef} = {
|
|
115
119
|
methodName: "${methodDesc.name}",
|
|
116
120
|
service: ${serviceDesc.name}Desc,
|
|
117
|
-
requestStream: false,
|
|
118
|
-
responseStream: ${methodDesc.serverStreaming ?
|
|
121
|
+
requestStream: ${methodDesc.clientStreaming ? true : false},
|
|
122
|
+
responseStream: ${methodDesc.serverStreaming ? true : false},
|
|
119
123
|
requestType: ${requestFn} as any,
|
|
120
124
|
responseType: ${responseFn} as any,
|
|
121
125
|
};
|
|
@@ -133,6 +137,10 @@ function addGrpcWebMisc(ctx, hasStreamingMethods) {
|
|
|
133
137
|
interface UnaryMethodDefinitionishR extends ${grpc}.UnaryMethodDefinition<any, any> { requestStream: any; responseStream: any; }
|
|
134
138
|
`);
|
|
135
139
|
chunks.push((0, ts_poet_1.code) `type UnaryMethodDefinitionish = UnaryMethodDefinitionishR;`);
|
|
140
|
+
chunks.push((0, ts_poet_1.code) `
|
|
141
|
+
interface MethodDefinitionishR extends ${grpc}.MethodDefinition<any, any> { requestStream: any; responseStream: any; }
|
|
142
|
+
`);
|
|
143
|
+
chunks.push((0, ts_poet_1.code) `type MethodDefinitionish = MethodDefinitionishR;`);
|
|
136
144
|
chunks.push(generateGrpcWebRpcType(ctx, options.returnObservable, hasStreamingMethods));
|
|
137
145
|
chunks.push(generateGrpcWebImpl(ctx, options.returnObservable, hasStreamingMethods));
|
|
138
146
|
return (0, ts_poet_1.joinCode)(chunks, { on: '\n\n' });
|
|
@@ -156,8 +164,14 @@ function generateGrpcWebRpcType(ctx, returnObservable, hasStreamingMethods) {
|
|
|
156
164
|
methodDesc: T,
|
|
157
165
|
request: any,
|
|
158
166
|
metadata: grpc.Metadata | undefined,
|
|
159
|
-
): ${(0, types_1.observableType)(ctx)}<any
|
|
160
|
-
|
|
167
|
+
): ${(0, types_1.observableType)(ctx)}<any>;`);
|
|
168
|
+
chunks.push((0, ts_poet_1.code) `
|
|
169
|
+
stream<T extends MethodDefinitionish>(
|
|
170
|
+
methodDesc: T,
|
|
171
|
+
request: ${(0, types_1.observableType)(ctx)}<any>,
|
|
172
|
+
metadata: grpc.Metadata | undefined,
|
|
173
|
+
rpcOptions: grpc.RpcOptions | undefined
|
|
174
|
+
): ${(0, types_1.observableType)(ctx)}<any>;`);
|
|
161
175
|
}
|
|
162
176
|
chunks.push((0, ts_poet_1.code) `}`);
|
|
163
177
|
return (0, ts_poet_1.joinCode)(chunks, { on: '\n' });
|
|
@@ -178,7 +192,7 @@ function generateGrpcWebImpl(ctx, returnObservable, hasStreamingMethods) {
|
|
|
178
192
|
export class GrpcWebImpl {
|
|
179
193
|
private host: string;
|
|
180
194
|
private options: ${options};
|
|
181
|
-
|
|
195
|
+
|
|
182
196
|
constructor(host: string, options: ${options}) {
|
|
183
197
|
this.host = host;
|
|
184
198
|
this.options = options;
|
|
@@ -192,6 +206,7 @@ function generateGrpcWebImpl(ctx, returnObservable, hasStreamingMethods) {
|
|
|
192
206
|
}
|
|
193
207
|
if (hasStreamingMethods) {
|
|
194
208
|
chunks.push(createInvokeMethod(ctx));
|
|
209
|
+
chunks.push(createStreamMethod(ctx));
|
|
195
210
|
}
|
|
196
211
|
chunks.push((0, ts_poet_1.code) `}`);
|
|
197
212
|
return (0, ts_poet_1.joinCode)(chunks, { trim: false });
|
|
@@ -259,7 +274,7 @@ function createObservableUnaryMethod(ctx) {
|
|
|
259
274
|
},
|
|
260
275
|
});
|
|
261
276
|
}).pipe(${take}(1));
|
|
262
|
-
}
|
|
277
|
+
}
|
|
263
278
|
`;
|
|
264
279
|
}
|
|
265
280
|
function createInvokeMethod(ctx) {
|
|
@@ -302,3 +317,50 @@ function createInvokeMethod(ctx) {
|
|
|
302
317
|
}
|
|
303
318
|
`;
|
|
304
319
|
}
|
|
320
|
+
function createStreamMethod(ctx) {
|
|
321
|
+
return (0, ts_poet_1.code) `
|
|
322
|
+
stream<T extends MethodDefinitionish>(
|
|
323
|
+
methodDesc: T,
|
|
324
|
+
_request: ${(0, types_1.observableType)(ctx)}<any>,
|
|
325
|
+
metadata: ${grpc}.Metadata | undefined,
|
|
326
|
+
rpcOptions: ${grpc}.RpcOptions | undefined
|
|
327
|
+
): ${(0, types_1.observableType)(ctx)}<any> {
|
|
328
|
+
const defaultOptions = {
|
|
329
|
+
host: this.host,
|
|
330
|
+
debug: rpcOptions?.debug || this.options.debug,
|
|
331
|
+
transport: rpcOptions?.transport || this.options.streamingTransport || this.options.transport,
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
let started = false;
|
|
335
|
+
const client = ${grpc}.client(methodDesc, defaultOptions);
|
|
336
|
+
|
|
337
|
+
const subscription = _request.subscribe((_req: any) => {
|
|
338
|
+
const request = { ..._req, ...methodDesc.requestType };
|
|
339
|
+
if (!started) {
|
|
340
|
+
client.start(metadata);
|
|
341
|
+
started = true;
|
|
342
|
+
}
|
|
343
|
+
client.send(request);
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
subscription.add(() => {
|
|
347
|
+
client.finishSend();
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
return new Observable((observer) => {
|
|
351
|
+
client.onEnd((code: ${grpc}.Code, message: string, trailers: ${grpc}.Metadata) => {
|
|
352
|
+
subscription.unsubscribe();
|
|
353
|
+
if (code === 0) {
|
|
354
|
+
observer.complete();
|
|
355
|
+
} else {
|
|
356
|
+
observer.error(new Error(\`Error \${code} \${message}\`));
|
|
357
|
+
}
|
|
358
|
+
})
|
|
359
|
+
client.onMessage((res: any) => {
|
|
360
|
+
observer.next(res);
|
|
361
|
+
})
|
|
362
|
+
observer.add(() => client.close())
|
|
363
|
+
}).pipe(share());
|
|
364
|
+
}
|
|
365
|
+
`;
|
|
366
|
+
}
|
|
@@ -42,7 +42,14 @@ function generateService(ctx, fileDesc, sourceInfo, serviceDesc) {
|
|
|
42
42
|
// Use metadata as last argument for interface only configuration
|
|
43
43
|
if (options.outputClientImpl === 'grpc-web') {
|
|
44
44
|
// We have to use grpc.Metadata where grpc will come from @improbable-eng
|
|
45
|
-
|
|
45
|
+
if (methodDesc.clientStreaming) {
|
|
46
|
+
params.push((0, ts_poet_1.code) `options?: {
|
|
47
|
+
metadata?: grpc.Metadata,
|
|
48
|
+
rpcOptions?: grpc.RpcOptions}`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
params.push((0, ts_poet_1.code) `metadata?: grpc.Metadata`);
|
|
52
|
+
}
|
|
46
53
|
}
|
|
47
54
|
else if (options.addGrpcMetadata) {
|
|
48
55
|
const Metadata = (0, ts_poet_1.imp)('Metadata@@grpc/grpc-js');
|
package/build/main.js
CHANGED
|
@@ -115,7 +115,6 @@ function generateFile(ctx, fileDesc) {
|
|
|
115
115
|
}
|
|
116
116
|
}, options);
|
|
117
117
|
}
|
|
118
|
-
let hasServerStreamingMethods = false;
|
|
119
118
|
let hasStreamingMethods = false;
|
|
120
119
|
(0, visit_1.visitServices)(fileDesc, sourceInfo, (serviceDesc, sInfo) => {
|
|
121
120
|
if (options.nestJs) {
|
|
@@ -155,12 +154,7 @@ function generateFile(ctx, fileDesc) {
|
|
|
155
154
|
chunks.push((0, generate_grpc_web_1.generateGrpcClientImpl)(ctx, fileDesc, serviceDesc));
|
|
156
155
|
chunks.push((0, generate_grpc_web_1.generateGrpcServiceDesc)(fileDesc, serviceDesc));
|
|
157
156
|
serviceDesc.method.forEach((method) => {
|
|
158
|
-
|
|
159
|
-
chunks.push((0, generate_grpc_web_1.generateGrpcMethodDesc)(ctx, serviceDesc, method));
|
|
160
|
-
}
|
|
161
|
-
if (method.serverStreaming) {
|
|
162
|
-
hasServerStreamingMethods = true;
|
|
163
|
-
}
|
|
157
|
+
chunks.push((0, generate_grpc_web_1.generateGrpcMethodDesc)(ctx, serviceDesc, method));
|
|
164
158
|
});
|
|
165
159
|
}
|
|
166
160
|
}
|
|
@@ -179,7 +173,7 @@ function generateFile(ctx, fileDesc) {
|
|
|
179
173
|
chunks.push((0, generate_services_1.generateRpcType)(ctx, hasStreamingMethods));
|
|
180
174
|
}
|
|
181
175
|
else if (options.outputClientImpl === 'grpc-web') {
|
|
182
|
-
chunks.push((0, generate_grpc_web_1.addGrpcWebMisc)(ctx,
|
|
176
|
+
chunks.push((0, generate_grpc_web_1.addGrpcWebMisc)(ctx, hasStreamingMethods));
|
|
183
177
|
}
|
|
184
178
|
}
|
|
185
179
|
if (options.context) {
|
package/build/types.js
CHANGED
|
@@ -641,7 +641,7 @@ function responseObservable(ctx, methodDesc) {
|
|
|
641
641
|
exports.responseObservable = responseObservable;
|
|
642
642
|
function responsePromiseOrObservable(ctx, methodDesc) {
|
|
643
643
|
const { options } = ctx;
|
|
644
|
-
if (options.returnObservable || methodDesc.serverStreaming) {
|
|
644
|
+
if (options.returnObservable || methodDesc.serverStreaming || methodDesc.clientStreaming) {
|
|
645
645
|
return responseObservable(ctx, methodDesc);
|
|
646
646
|
}
|
|
647
647
|
return responsePromise(ctx, methodDesc);
|