---
# System prepended metadata

title: NestJS GRPC
tags: [' grpc', nestjs]

---

# 安裝套件
```
npm i @grpc/grpc-js @grpc/proto-loader
npm i @nestjs/microservices@9.0.0
npm i -D ts-proto
```

# 修改nest-cli.json
```json=
"compilerOptions": {
  "assets": ["**/*.proto"],
  "watchAssets": true
}
```

# 新增proto檔
```protobuf=
syntax = "proto3";

package echo;

service EchoService {
  rpc EchoMessage(EchoRequest) returns (EchoResponse);
}

message EchoRequest{
  string name = 1;
}

message EchoResponse {
  string name =  1;
  string timestamp = 2;
}
```
# 加入Makefile
```
DIRNAME:= src/protos

proto:
	protoc --plugin=node_modules/ts-proto/protoc-gen-ts_proto \
			$(DIRNAME)/*.proto -I. \
			--ts_proto_out=. \
			--ts_proto_opt=fileSuffix=.pb \
			--ts_proto_opt=nestJs=true \
			--ts_proto_opt=addGrpcMetadata=false \
			--ts_proto_opt=addNestjsRestParameter=false
clean:
	rm -rf $(DIRNAME)/*.pb.ts
```

# 產生的型別
* Server端介面: xxxServiceController
* Client端介面: xxxServiceClient
* package名稱: xxx_PACKAGE_NAME
* service名稱: xxx_SERVICE_NAME
* GrpcMethod修飾詞: xxxServiceControllerMethods

# Server端
* grpcs需設定credentials

```typescript=
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Transport } from '@nestjs/microservices';
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.connectMicroservice({
    transport: Transport.GRPC,
    options: {
      url: 'localhost:50051',
      package: 'echo',
      protoPath: __dirname + '/echo/echo.proto',
    },
  });
  app.startAllMicroservices();
  app.listen(3000);
}
bootstrap();
```

```typescript=
@Controller()
@EchoServiceControllerMethods()
export class EchoController implements EchoServiceController {
  echoMessage(
    request: EchoRequest,
  ): EchoResponse | Promise<EchoResponse> | Observable<EchoResponse> {
    return {
      name: request.name,
      timestamp: Date.now().toString(),
    };
  }
}
```

# Client端
```typescript=
import { Module } from '@nestjs/common';
import { HelloController } from './hello.controller';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { ECHO_PACKAGE_NAME, ECHO_SERVICE_NAME } from 'src/echo/echo.pb';
import { HelloService } from './hello.service';

@Module({
  imports: [
    ClientsModule.register([
      {
        name: ECHO_SERVICE_NAME,
        transport: Transport.GRPC,
        options: {
          url: 'localhost:50051',
          package: ECHO_PACKAGE_NAME,
          protoPath: __dirname + '/../echo/echo.proto',
        },
      },
    ]),
  ],
  controllers: [HelloController],
  providers: [HelloService],
})
export class HelloModule {}

```

```typescript=

@Injectable()
export class HelloService {
  private svc: EchoServiceClient;

  constructor(
    @Inject(ECHO_SERVICE_NAME)
    private readonly client: ClientGrpc,
  ) {
    this.svc = this.client.getService<EchoServiceClient>(ECHO_SERVICE_NAME);
  }

  hello() {
    return this.svc.echoMessage({ name: 'abc' });
  }
}
```