## Description
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->

![release](https://gitlab.com/jtimmons/nestjs-grpc-reflection-module/-/badges/release.svg?order_by=release_at)
![coverage](https://gitlab.com/jtimmons/nestjs-grpc-reflection-module/badges/master/coverage.svg)
![pipeline](https://gitlab.com/jtimmons/nestjs-grpc-reflection-module/badges/master/pipeline.svg)

A pluggable [gRPC Reflection Server](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md) for the excellent [NestJS](https://github.com/nestjs/nest) framework.

Adding this module to your existing NestJS-based gRPC microservice will allow clients [such as postman](https://blog.postman.com/postman-now-supports-grpc/) to dynamically load your API definitions from your running application rather than needing to load each proto file manually.

![example of reflection working with postman](https://gitlab.com/jtimmons/nestjs-grpc-reflection-module/-/raw/master/images/example.gif)

## Supported gRPC Clients
While this library should work with any gRPC client, in practice there could be some implementation issues that cause issues with some clients. Below is the list of gRPC clients that this library has been tested against:

| Client                                             | Status             | Notes |
| ---                                                | ---                | ---   |
| [Postman](https://www.postman.com/)                | :white_check_mark: |       |
| [grpcurl](https://github.com/fullstorydev/grpcurl) | :white_check_mark: |       |
| [grpcui](https://github.com/fullstorydev/grpcui)   | :white_check_mark: |       |
| [kreya](https://kreya.app/)                        | :x:                |       |

If you're using a client not on this list, please add it here! If you've hit a problem with one, please open a [bug](https://gitlab.com/jtimmons/nestjs-grpc-reflection-module/-/issues)!

## Getting Started

To get started, first install the package:

```bash
$ npm install nestjs-grpc-reflection
```

Then simply register the `GrpcReflectionModule` from the root module of your application - it takes in the same `GrpcOptions` that are used to create your microservice. The gRPC Reflection Server module runs within your application's existing gRPC server just as any other controller in your microservice, so loading the module will add the appropriate routes to your application.

This module can either be loaded syncronously with the `register` method:
```ts
import { GrpcReflectionModule } from 'nestjs-grpc-reflection';
...
@Module({
  imports: [GrpcReflectionModule.register(grpcClientOptions)],
  ...
})
export class AppModule {}
```

or asyncronously with the `registerAsync` method if you need dynamic gRPC options. This is common if you are using the `@nestjs/config` module to configure your gRPC server, for example.
```ts
import { GrpcReflectionModule } from 'nestjs-grpc-reflection';
...
@Module({
  imports: [GrpcReflectionModule.registerAsync({
    useFactory: async (configService: ConfigService) => {
      const grpcClientOptions: GrpcClientOptions = new GrpcClientOptions(
        configService,
      );
      return grpcClientOptions.getGRPCConfig;
    },
    inject: [ConfigService],
  }),
  ],
  ...
})


export class AppModule {}
```

Finally, NestJS needs to know where the reflection proto files are so that it can serialize/deserialize its message traffic. For convenience, this can be automatically added to your `GrpcOptions` using the `addReflectionToGrpcConfig` function like so:

```ts
import { addReflectionToGrpcConfig } from 'nestjs-grpc-reflection';
...
export const grpcClientOptions: GrpcOptions = addReflectionToGrpcConfig({
  transport: Transport.GRPC,
  options: {
    package: 'sample',
    protoPath: join(__dirname, 'sample/proto/sample.proto'),
  },
});
```

Alternatively, these paths can be added manually by appending the `REFLECTION_PACKAGES` and `REFLECTION_PROTOS` constants to the `package` and `protoPath` lists respectively.

> :warning: **If you are using [@grpc/proto-loader's `keepCase` option](https://github.com/grpc/grpc-node/blob/master/packages/proto-loader/README.md) you may experience some issues with the server reflection API**. This module assumes that the microservice server is running with `keepCase` off (the NestJS default) and will attempt to convert *back* to the original case if it's on but this may not be perfect in all cases.

## Examples
There is an example of both a syncronous and asynchronously configured application in the `src/sample` directory, so see those for a running example

## Local Development

This repository contains two simple example gRPC services as well as the gRPC reflection module library, so new features can be tested against that service.

```bash
$ npm install
```

### Generating Types

This repo uses [ts-proto](https://github.com/stephenh/ts-proto/blob/main/NESTJS.markdown) for type generation. If any of the the reflection API proto files are changed, we'll need to regenerate the types to reflect that change. This relies on the `protoc` compiler, so if that's not installed already you'll need to do so first - instructions can be found on their site [here](https://grpc.io/docs/protoc-installation/).

```bash
$ npm run generate # regenerate reflection types, requires 'protoc' to be installed
```

### Running the sample app

```bash
# development
$ npm run start register
$ npm run start registerAsync

# watch mode
$ npm run start:dev register
$ npm run start:dev registerAsync

# production mode
$ npm run start:prod register
$ npm run start:prod registerAsync
```

### Test

```bash
# unit tests
$ npm run test

# test coverage
$ npm run test:cov
```

## Contributors ✨

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
  <tbody>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://gitlab.com/jtimmons"><img src="https://gitlab.com/uploads/-/system/user/avatar/839414/avatar.png?s=100" width="100px;" alt="Justin Timmons"/><br /><sub><b>Justin Timmons</b></sub></a><br /><a href="https://gitlab.com/jtimmons/nestjs-grpc-reflection-module/commits/master" title="Code">💻</a> <a href="https://gitlab.com/jtimmons/nestjs-grpc-reflection-module/commits/master" title="Documentation">📖</a> <a href="#ideas-jtimmons" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-jtimmons" title="Maintenance">🚧</a> <a href="#projectManagement-jtimmons" title="Project Management">📆</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://gitlab.com/cblazquez"><img src="https://gitlab.com/uploads/-/system/user/avatar/3037442/avatar.png?s=100" width="100px;" alt="Cristian"/><br /><sub><b>Cristian</b></sub></a><br /><a href="https://gitlab.com/jtimmons/nestjs-grpc-reflection-module/commits/master" title="Code">💻</a> <a href="https://gitlab.com/jtimmons/nestjs-grpc-reflection-module/commits/master" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://gitlab.com/gliheng"><img src="https://secure.gravatar.com/avatar/62a73f3cd5a324fb02065a00c1b9e3f2?s=80&d=identicon?s=100" width="100px;" alt="juju"/><br /><sub><b>juju</b></sub></a><br /><a href="https://gitlab.com/jtimmons/nestjs-grpc-reflection-module/commits/master" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://gitlab.com/b0er"><img src="https://secure.gravatar.com/avatar/83092c642cd7a0ed6be2b15ef72e5dbb?s=80&d=identicon?s=100" width="100px;" alt="Alexandr Ishchuk"/><br /><sub><b>Alexandr Ishchuk</b></sub></a><br /><a href="https://gitlab.com/jtimmons/nestjs-grpc-reflection-module/issues?author_username=b0er" title="Bug reports">🐛</a></td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td align="center" size="13px" colspan="7">
        <img src="https://raw.githubusercontent.com/all-contributors/all-contributors-cli/1b8533af435da9854653492b1327a23a4dbd0a10/assets/logo-small.svg">
          <a href="https://all-contributors.js.org/docs/en/bot/usage">Add your contributions</a>
        </img>
      </td>
    </tr>
  </tfoot>
</table>

<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
