Skip to content

Commit

Permalink
Improved main README and fixed npm install issues
Browse files Browse the repository at this point in the history
- Fix: #9
- Fix: #10
  • Loading branch information
Jonathan committed Nov 3, 2017
1 parent 6cb01f4 commit 6315b54
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 65 deletions.
75 changes: 46 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,65 @@

gRPC Extension for LoopBack 4

## Summary
A gRPC extension for LoopBack Next.

## Overview
TODO.
The `@loopback/grpc` component enables LoopBack 4 as a Grpc Server, also provides with a @grpc decorator to set RPC Method implementations from your Con.

## Installation
Get started by either downloading this project or cloning it as follows:
Install the `@loopback/grpc` component in your LoopBack 4 Application.

```sh
$ git clone https://github.com/strongloop/loopback4-extension-grpc.git
$ cd loopback4-extension-grpc && npm install
$ npm install --save @loopback/grpc
```

## Basic Usage
TODO
## Component Configuration
```js
import {Application} from '@loopback/core';
import {GrpcComponent, GrpcConfig} from '@loopback/grpc';
import {MyGreeter} from './MyGreeter';

### Components
TODO.
const config: GrpcConfig = {
proto: './file.proto',
package: 'myawesomepackage'
}

### Controllers
TODO.
const app = new Application({
components: [GrpcComponent],
grpc: config
});

### Decorators
TODO.
app.controller(MyGreeter});

### Mixins
TODO.

### Providers
TODO.

### Repositories
TODO.
await app.start();
```

### Project Layout
## Grpc Decorator
The `@loopback/grpc` component provides you with a handy decorator to implement GRPC Methods.

```js
import {grpc} from '@loopback/grpc';
// You create the following types according your own proto.file
import {Greeter, HelloRequest, HelloReply} from './types';
/**
* @class MyGreeter
* @description Implements grpc proto service
**/
export class MyGreeter implements Greeter {
// Tell LoopBack that this is a Service RPC implementation
@grpc()
SayHello(request: HelloRequest): HelloReply {
const reply: HelloReply = {message: 'Hello ' + request.name};
return reply;
}
}
```

#### `src/`
TODO.
## Contribute
Get started by either downloading this project or cloning it as follows:

#### `test/`
TODO.
```sh
$ git clone https://github.com/strongloop/loopback4-extension-grpc.git
$ cd loopback4-extension-grpc && npm install
```

## Contributions
- [Guidelines](https://github.com/strongloop/loopback-next/wiki/Contributing#guidelines)
Expand All @@ -58,4 +75,4 @@ run `npm test` from the root folder.
See [all contributors](https://github.com/strongloop/loopback4-extension-grpc/graphs/contributors).

## License
MIT
MIT
6 changes: 3 additions & 3 deletions src/grpc.sequence.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {inject} from '@loopback/context';
import {GrpcBindings} from './keys';
import {UnaryCall, UnaryReply} from './types';
import * as grpc from 'grpc';
/**
* @interface GrpcSequenceInterface
* @author Jonathan Casarrubias <t: johncasarrubias>
* @license MIT
* @description Interface that describes a GRPC Sequence
*/
export interface GrpcSequenceInterface {
unaryCall(request: UnaryCall): Promise<UnaryReply>;
unaryCall(request: grpc.ServerUnaryCall): Promise<any>;
}
/**
* @class GrpcSequence
Expand All @@ -22,7 +22,7 @@ export class GrpcSequence implements GrpcSequenceInterface {
@inject(GrpcBindings.GRPC_METHOD) protected method,
) {}

async unaryCall(call: UnaryCall): Promise<UnaryReply> {
async unaryCall(call: grpc.ServerUnaryCall): Promise<any> {
// Do something before call
const reply = await this.method(call.request);
// Do something after call
Expand Down
18 changes: 10 additions & 8 deletions src/grpc.server.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import {Application, CoreBindings, Server} from '@loopback/core';
import {Context, inject, Reflector} from '@loopback/context';
import {GrpcBindings} from './keys';
import {GrpcServerInstance, UnaryReply, UnaryCall} from './types';
import {GrpcSequence} from './grpc.sequence';
import * as grpcModule from 'grpc';
import * as grpc from 'grpc';
const debug = require('debug')('loopback:grpc:server');
/**
* @class GrpcServer
Expand All @@ -27,7 +26,7 @@ export class GrpcServer extends Context implements Server {
*/
constructor(
@inject(CoreBindings.APPLICATION_INSTANCE) protected app: Application,
@inject(GrpcBindings.GRPC_SERVER) protected server: GrpcServerInstance,
@inject(GrpcBindings.GRPC_SERVER) protected server: grpc.Server,
@inject(GrpcBindings.HOST) protected host: string,
@inject(GrpcBindings.PORT) protected port: string,
@inject(GrpcBindings.PROTO_PROVIDER) protected protoProvider: any,
Expand All @@ -49,7 +48,7 @@ export class GrpcServer extends Context implements Server {
return new Promise<void>((resolve, reject) => {
this.server.bind(
`${this.host}:${this.port}`,
grpcModule.ServerCredentials.createInsecure(),
grpc.ServerCredentials.createInsecure(),
);
this.server.start();
resolve();
Expand All @@ -68,7 +67,7 @@ export class GrpcServer extends Context implements Server {
if (!proto) {
throw new Error(`Grpc Server: No proto file was provided.`);
}
const handlers: {[key: string]: Function} = {};
const handlers: {[key: string]: grpc.handleUnaryCall} = {};
const className = prototype.constructor.name || '<UnknownClass>';
// If this class is defined within the proto file
// then we search for rpc methods and register handlers.
Expand Down Expand Up @@ -101,17 +100,20 @@ export class GrpcServer extends Context implements Server {
* @param prototype
* @param methodName
*/
private setupGrpcCall(prototype, methodName: string): Function {
private setupGrpcCall(prototype, methodName: string): grpc.handleUnaryCall {
const context: Context = this;
return function(call: UnaryCall, callback: (err, value?) => void) {
return function(
call: grpc.ServerUnaryCall,
callback: (err, value?) => void,
) {
handleUnary().then(
result => callback(null, result),
error => {
debugger;
callback(error);
},
);
async function handleUnary(): Promise<UnaryReply> {
async function handleUnary(): Promise<any> {
context.bind(GrpcBindings.CONTEXT).to(context);
context.bind(GrpcBindings.GRPC_METHOD).to(prototype[methodName]);
const sequence: GrpcSequence = await context.get(
Expand Down
6 changes: 2 additions & 4 deletions src/providers/server.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
//import {Provider} from '@loopback/context';
import {GrpcServerInstance} from '../types';
// Require gRPC Module
import * as grpc from 'grpc';
/**
* @class ServerProvider
Expand All @@ -13,8 +11,8 @@ import * as grpc from 'grpc';
* @description This provider will return the GRPC Server
*/
export class ServerProvider {
private server: GrpcServerInstance = new grpc.Server();
public value(): GrpcServerInstance {
private server: grpc.Server = new grpc.Server();
public value(): grpc.Server {
return this.server;
}
}
17 changes: 0 additions & 17 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,6 @@
// License text available at https://opensource.org/licenses/MIT

// Types and interfaces exposed by the extension go here
export interface GrpcServerInstance {
addService: (service: string, handlers: {[key: string]: Function}) => void;
addProtoService: (
service: string,
handlers: {[key: string]: Function},
) => void;
bind: (host: string, secure: boolean) => void;
start: (callback?: () => void) => void;
tryShutdown: (callback?: () => void) => void;
forceShutdown: (callback?: () => void) => void;
register: () => void;
}
export interface UnaryCall {
request: UnaryCall;
}
export interface UnaryRequest {}
export interface UnaryReply {}
export interface GrpcConfig {
host?: string;
port?: number;
Expand Down
4 changes: 2 additions & 2 deletions test/acceptance/grpc.component.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import {expect} from '@loopback/testlab';
import {inject} from '@loopback/context';
import {Application} from '@loopback/core';
import {GrpcSequenceInterface, GrpcConfig, UnaryCall, UnaryReply} from '../../';
import {GrpcSequenceInterface, GrpcConfig} from '../../';
import {grpc} from '../../src/decorators/grpc.decorator';
import * as grpcModule from 'grpc';
import {GrpcComponent, GrpcBindings} from '../..';
Expand Down Expand Up @@ -66,7 +66,7 @@ describe('GrpcComponent', () => {
@inject(GrpcBindings.CONTEXT) protected context,
@inject(GrpcBindings.GRPC_METHOD) protected method,
) {}
async unaryCall(call: UnaryCall): Promise<UnaryReply> {
async unaryCall(call: grpcModule.ServerUnaryCall): Promise<HelloReply> {
// Do something before call
const reply = await this.method(call.request);
reply.message += ' Sequenced';
Expand Down
5 changes: 3 additions & 2 deletions test/unit/providers/server.provider.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
// License text available at https://opensource.org/licenses/MIT

import {expect} from '@loopback/testlab';
import {ServerProvider, GrpcServerInstance} from '../../..';
import {ServerProvider} from '../../..';
import * as grpc from 'grpc';

describe('ServerProvider', () => {
it('returns a grpc singleton server', () => {
const server: GrpcServerInstance = new ServerProvider().value();
const server: grpc.Server = new ServerProvider().value();
expect(server).to.be.an.Object();
expect(server.bind).to.be.a.Function();
expect(server.start).to.be.a.Function();
Expand Down

0 comments on commit 6315b54

Please sign in to comment.