Skip to content

Commit dafaf2b

Browse files
committed
docs: add documentation for streams and TLS
Signed-off-by: NorthBlue333 <[email protected]>
1 parent e8d2443 commit dafaf2b

File tree

3 files changed

+196
-59
lines changed

3 files changed

+196
-59
lines changed

README.md

Lines changed: 164 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66

77
The `@loopback/grpc` component enables LoopBack 4 as a [gRPC](https://grpc.io/) Server. Also it provides with a gRPC decorator to define your RPC Method implementations from your Application Controllers.
88

9+
### Features
10+
11+
- Handles unary, client streaming, server streaming and bidirectional streaming calls
12+
- Provides options for TLS and mTLS
13+
914
## Installation
1015

1116
Install the `@loopback/grpc` component in your LoopBack 4 Application.
@@ -18,10 +23,10 @@ $ npm install --save @loopback/grpc
1823

1924
```js
2025
import {Application} from '@loopback/core';
21-
import {GrpcComponent, Config} from '@loopback/grpc';
22-
import {GreeterCtrl} from './controllers/greeter/greeter.ctrl';
26+
import {GrpcComponent, GrpcComponentConfig} from '@loopback/grpc';
27+
import {GreeterController} from './controllers/greeter.controller';
2328
// Grpc Configurations are optional.
24-
const config: Config.Component = {
29+
const config: GrpcComponentConfig = {
2530
/* Optional Configs */
2631
};
2732
// Pass the optional configurations
@@ -30,13 +35,15 @@ const app = new Application({
3035
});
3136
// Add Grpc as Component
3237
app.component(GrpcComponent);
33-
// Bind GreeterCtrl to the LoopBack Application
34-
app.controller(GreeterCtrl);
38+
// Bind GreeterController to the LoopBack Application
39+
// only if your Boot Mixins do not load this directory
40+
// see https://loopback.io/doc/en/lb4/Booting-an-Application.html
41+
// app.controller(GreeterController);
3542
// Start App
3643
app.start();
3744
```
3845

39-
## Grpc auto-generated code
46+
## gRPC auto-generated code
4047

4148
The `@loopback/grpc` extension provides you with auto-generated interfaces and configurations for strict development.
4249

@@ -46,71 +53,192 @@ Example:
4653

4754
```sh
4855
- app
56+
| - protos
57+
| | - greeter.proto
58+
| - protos-ts
4959
| - controllers
50-
| | - greeter
51-
| | | - greeter.proto
52-
| | | - greeter.ctrl.ts
60+
| | - greeter.controller.ts
5361
```
5462

5563
Once you start your app for first time it will automatically create your typescript interfaces from the `greeter.proto` file.
5664

5765
```sh
5866
- app
67+
| - protos
68+
| | - greeter.proto
69+
| - protos-ts
70+
| | - greeter.ts <--- Auto-generated
5971
| - controllers
60-
| | - greeter
61-
| | | - greeter.proto
62-
| | | - greeter.proto.ts <--- Auto-generated
63-
| | | - greeter.ctrl.ts
72+
| | - greeter.controller.ts
6473
```
6574

6675
Once your interfaces and configurations are created, you can start building your controller logic.
6776

68-
## Grpc Controller
77+
_NB: you can also manually generate your interfaces from _.proto files by creating a .js file like below.\*
6978

70-
The `@loopback/grpc` component provides you with a handy decorator to implement GRPC Methods within your LoopBack controllers.
79+
```ts
80+
const GrpcGenerator = require('@loopback/grpc').GrpcGenerator;
81+
const path = require('path');
82+
const fs = require('fs');
7183

72-
`app/controllers/greeter/greeter.ctrl.ts`
84+
function formatWithColor(message, color) {
85+
return `\x1b[${color}m${message}\x1b[0m`;
86+
}
7387

74-
```js
75-
import {grpc} from '@loopback/grpc';
76-
import {Greeter, HelloRequest, HelloReply} from '/greeter.proto';
77-
/**
78-
* @class GreeterCtrl
79-
* @description Implements grpc proto service
80-
**/
81-
export class GreeterCtrl implements Greeter.Service {
82-
// Tell LoopBack that this is a Service RPC implementation
83-
@grpc(Greeter.SayHello)
84-
sayHello(request: HelloRequest): HelloReply {
85-
return {message: 'Hello ' + request.name};
88+
const protoTsPath = path.join(process.cwd(), 'src', 'protos-ts');
89+
try {
90+
fs.statSync(protoTsPath);
91+
} catch (e) {
92+
fs.mkdirSync(protoTsPath);
93+
}
94+
95+
const generator = new GrpcGenerator({
96+
compilerOptions: {
97+
protoPattern: '**/protos/**/*.proto',
98+
// additionalArgs: '--experimental_allow_proto3_optional',
99+
tsOutputPath: protoTsPath,
100+
protoPath: path.join(process.cwd(), 'src', 'protos'),
101+
generate: true,
102+
load: false,
103+
},
104+
});
105+
106+
console.log(formatWithColor('Generating proto.ts files from *.proto...', 33));
107+
generator.execute();
108+
console.log(formatWithColor('All proto.ts files have been generated', 32));
109+
```
110+
111+
## gRPC Controller
112+
113+
The `@loopback/grpc` component provides you with a handy decorator to implement gRPC Methods within your LoopBack controllers. The decorator will automatically map the correct calls from the file descriptor, the method name and the controller name. If you want an other suffix than `(Ctrl|Controller)`, you can use the argument `controllerNameRegex`.
114+
115+
`app/controllers/greeter.controller.ts`
116+
117+
```ts
118+
import {
119+
TestRequest,
120+
TestResponse,
121+
Greeter,
122+
protoMetadata,
123+
} from '../protos-ts/greeter';
124+
125+
class GreeterCtrl implements Greeter {
126+
// Tell LoopBack that this is a Service RPC implementation
127+
@grpc(protoMetadata.fileDescriptor)
128+
async unaryTest(request: TestRequest): Promise<TestResponse> {
129+
return {
130+
message: 'Hello ' + request.name,
131+
};
132+
}
133+
134+
@grpc(protoMetadata.fileDescriptor)
135+
async clientStreamTest(
136+
request: Observable<TestRequest>,
137+
): Promise<TestResponse> {
138+
const names: string[] = [];
139+
let error;
140+
const observer: PartialObserver<TestRequest> = {
141+
next: (value) => names.push(value.name),
142+
error: (err) => (error = err),
143+
};
144+
request.subscribe(observer);
145+
await lastValueFrom(request);
146+
if (error) {
147+
throw error;
86148
}
149+
return {
150+
message: names.join(' '),
151+
};
152+
}
153+
154+
@grpc(protoMetadata.fileDescriptor)
155+
serverStreamTest(request: TestRequest): Observable<TestResponse> {
156+
const req = request.name.split(' ');
157+
const responseObservable = new Observable<TestResponse>((subscriber) => {
158+
subscriber.next({
159+
message: req[0],
160+
});
161+
for (let i = 1; i < req.length; i++) {
162+
setTimeout(() => {
163+
subscriber.next({
164+
message: req[i],
165+
});
166+
}, i * 200);
167+
if (i === req.length - 1) {
168+
setTimeout(() => {
169+
subscriber.complete();
170+
}, i * 200);
171+
}
172+
}
173+
});
174+
return responseObservable;
175+
}
176+
177+
@grpc(protoMetadata.fileDescriptor)
178+
bidiStreamTest(request: Observable<TestRequest>): Observable<TestResponse> {
179+
const responseObservable = new Observable<TestResponse>((subscriber) => {
180+
const observer: PartialObserver<TestRequest> = {
181+
next: (value) => {
182+
subscriber.next({message: `Got ${value.name} !`});
183+
},
184+
complete: () => subscriber.complete(),
185+
};
186+
request.subscribe(observer);
187+
});
188+
return responseObservable;
189+
}
87190
}
88191
```
89192

90193
## Proto Example
91194

92-
`app/controllers/greeter/greeter.proto`
195+
`app/protos/greeter.proto`
93196

94-
```txt
197+
```proto
95198
syntax = "proto3";
96199
package greeterpackage;
97200
98201
service Greeter {
99202
// Sends a greeting
100-
rpc SayHello (HelloRequest) returns (HelloReply) {}
203+
rpc UnaryTest (TestRequest) returns (TestResponse) {}
204+
rpc ClientStreamTest (stream TestRequest) returns (TestResponse) {}
205+
rpc ServerStreamTest (TestRequest) returns (stream TestResponse) {}
206+
rpc BidiStreamTest (stream TestRequest) returns (stream TestResponse) {}
101207
}
102208
103209
// The request message containing the user's name.
104-
message HelloRequest {
210+
message TestRequest {
105211
string name = 1;
106212
}
107213
108214
// The response message containing the greetings
109-
message HelloReply {
215+
message TestResponse {
110216
string message = 1;
111217
}
112218
```
113219

220+
## Setting up TLS and mTLS
221+
222+
```ts
223+
import {GrpcComponentConfig} from '@loopback/grpc';
224+
225+
const grpcConfig: GrpcComponentConfig = {
226+
server: {
227+
tls: {
228+
rootCertPath: 'path/to/root/cert',
229+
keyCertPairPaths: [
230+
{
231+
privateKeyPath: 'path/to/private/key/for/server',
232+
certChainPath: 'path/to/cert/chain/for/server',
233+
},
234+
],
235+
},
236+
// set it to false/undefined to disable client certificate verification
237+
checkClientCertificate: true,
238+
},
239+
};
240+
```
241+
114242
## Contribute
115243

116244
Get started by either downloading this project or cloning it as follows:
@@ -122,17 +250,16 @@ $ cd loopback4-extension-grpc && npm install
122250

123251
## Contributions
124252

125-
* [Guidelines](https://github.com/strongloop/loopback-next/wiki/Contributing#guidelines)
126-
* [Join the team](https://github.com/strongloop/loopback-next/issues/110)
253+
- [Guidelines](https://github.com/strongloop/loopback-next/wiki/Contributing#guidelines)
254+
- [Join the team](https://github.com/strongloop/loopback-next/issues/110)
127255

128256
## Tests
129257

130258
run `npm test` from the root folder.
131259

132260
## Todo
133261

134-
* Watch for proto changes.
135-
* Server/Client Streams
262+
- Maybe watch for proto changes.
136263

137264
## Contributors
138265

src/decorators/README.md

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
## Overview
32

43
Decorators provide annotations for class methods and arguments. Decorators use the form `@decorator` where `decorator` is the name of the function that will be called at runtime.
@@ -8,51 +7,62 @@ Decorators provide annotations for class methods and arguments. Decorators use t
87
This decorator allows you to annotate a `Controller` class. The decorator will setup a GRPC Service.
98

109
**Example**
11-
````js
10+
11+
```js
1212
/**
13-
* Setup gRPC MicroService
14-
**/
15-
//myproject/controllers/greeter/Greeter.ts
16-
//myproject/controllers/greeter/greeter.proto
17-
//myproject/controllers/greeter/greeter.proto.ts
13+
* Setup gRPC MicroService
14+
**/
15+
//myproject/controllers/greeter.controller.ts
16+
//myproject/protos/greeter/greeter.proto
17+
//myproject/protos-ts/greeter/greeter.ts
1818
//Note: greeter.proto.ts is automatically generated from
1919
//greeter.proto
2020
import {grpc} from '@loopback/grpc';
21-
import {Greeter, HelloRequest, HelloReply} from 'greeter.proto';
22-
class GreeterCtrl implements Greeter.Service {
23-
@grpc(Greeter.SayHello)
24-
public sayHello(request: HelloRequest): HelloResponse {
25-
return { message: 'Hello ' + call.request.name };
21+
import {
22+
Greeter,
23+
TestRequest,
24+
TestResponse,
25+
protoMetadata,
26+
} from '../protos-ts/greeter';
27+
class GreeterCtrl implements Greeter {
28+
@grpc(protoMetadata.fileDescriptor)
29+
async unaryTest(request: TestRequest): Promise<TestResponse> {
30+
return {
31+
message: 'Hello ' + request.name,
32+
};
2633
}
2734
}
28-
````
35+
```
2936

3037
## Example Proto File
3138

32-
````proto
39+
```proto
3340
syntax = "proto3";
34-
package awesomepackage;
35-
41+
package greeterpackage;
42+
3643
service Greeter {
3744
// Sends a greeting
38-
rpc SayHello (HelloRequest) returns (HelloReply) {}
45+
rpc UnaryTest (TestRequest) returns (TestResponse) {}
46+
rpc ClientStreamTest (stream TestRequest) returns (TestResponse) {}
47+
rpc ServerStreamTest (TestRequest) returns (stream TestResponse) {}
48+
rpc BidiStreamTest (stream TestRequest) returns (stream TestResponse) {}
3949
}
4050
4151
// The request message containing the user's name.
42-
message HelloRequest {
52+
message TestRequest {
4353
string name = 1;
4454
}
4555
4656
// The response message containing the greetings
47-
message HelloReply {
57+
message TestResponse {
4858
string message = 1;
4959
}
50-
````
60+
```
5161

5262
## Related Resources
5363

5464
You can check out the following resource to learn more about decorators and how they are used in LoopBack Next.
5565

5666
- [TypeScript Handbook: Decorators](https://www.typescriptlang.org/docs/handbook/decorators.html)
5767
- [Decorators in LoopBack](http://loopback.io/doc/en/lb4/Decorators.html)
58-
- [gRPC in NodeJS](https://grpc.io/docs/quickstart/node.html)
68+
- [gRPC in NodeJS](https://grpc.io/docs/quickstart/node.html)

src/providers/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Providers
22

3-
TODO: Need to analyze if this provider is actually valuable...
3+
TODO: Need to analyze if this provider is actually valuable...

0 commit comments

Comments
 (0)