{"id":13818199,"url":"https://github.com/AlariCode/nestjs-rmq","last_synced_at":"2025-05-15T22:34:46.010Z","repository":{"id":32847192,"uuid":"144310738","full_name":"AlariCode/nestjs-rmq","owner":"AlariCode","description":"A custom library for NestJS microservice. It allows you to use RabbitMQ or AMQP.","archived":false,"fork":false,"pushed_at":"2025-02-04T10:05:38.000Z","size":1397,"stargazers_count":311,"open_issues_count":9,"forks_count":42,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-05-05T23:37:29.406Z","etag":null,"topics":["amqp","javascript","microservices","nestjs","nodejs","rabbitmq","typescript"],"latest_commit_sha":null,"homepage":"https://purpleschool.ru","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AlariCode.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-10T16:43:27.000Z","updated_at":"2025-05-01T19:10:26.000Z","dependencies_parsed_at":"2025-02-28T17:09:25.461Z","dependency_job_id":"710dfc23-31a4-4e18-ba7c-7a880e7b28f9","html_url":"https://github.com/AlariCode/nestjs-rmq","commit_stats":{"total_commits":154,"total_committers":16,"mean_commits":9.625,"dds":0.4285714285714286,"last_synced_commit":"3ef5ecc62b1e6e19254a4ae76288a35da96c463c"},"previous_names":[],"tags_count":58,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlariCode%2Fnestjs-rmq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlariCode%2Fnestjs-rmq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlariCode%2Fnestjs-rmq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlariCode%2Fnestjs-rmq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AlariCode","download_url":"https://codeload.github.com/AlariCode/nestjs-rmq/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254264765,"owners_count":22041793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amqp","javascript","microservices","nestjs","nodejs","rabbitmq","typescript"],"created_at":"2024-08-04T07:00:35.649Z","updated_at":"2025-05-15T22:34:45.987Z","avatar_url":"https://github.com/AlariCode.png","language":"TypeScript","readme":"# NestJS - RabbitMQ custom strategy\n\n![alt cover](https://github.com/AlariCode/nestjs-rmq/raw/master/img/new-logo.jpg)\n\n**More NestJS libs on [purpleschool.ru](https://purpleschool.ru)**\n\n[![npm version](https://badgen.net/npm/v/nestjs-rmq)](https://www.npmjs.com/package/nestjs-rmq)\n[![npm version](https://badgen.net/npm/license/nestjs-rmq)](https://www.npmjs.com/package/nestjs-rmq)\n[![npm version](https://badgen.net/github/open-issues/AlariCode/nestjs-rmq)](https://github.com/AlariCode/nestjs-rmq/issues)\n[![npm version](https://badgen.net/github/prs/AlariCode/nestjs-rmq)](https://github.com/AlariCode/nestjs-rmq/pulls)\n\nThis library will take care of RPC requests and messaging between microservices. It is easy to bind to our existing controllers to RMQ routes. This version is only for NestJS.\n\n**Updated for NestJS 9!**\n\n## Why use this over RabbitMQ transport in NestJS docs?\n\n-   Support for RMQ queue patterns with \\* and #.\n-   Using exchanges with topic bindings rather the direct queue sending.\n-   Additional `forTest()` method for emulating messages in unit or e2e tests without needing of RabbitMQ instance.\n-   Additional decorators for getting info out of messages.\n-   Support for class-validator decorators.\n-   Real production usage with more than 100 microservices.\n\n## Start\n\nFirst, install the package:\n\n```bash\nnpm i nestjs-rmq\n```\n\nSetup your connection in root module:\n\n```typescript\nimport { RMQModule } from 'nestjs-rmq';\n\n@Module({\n\timports: [\n\t\tRMQModule.forRoot({\n\t\t\texchangeName: configService.get('AMQP_EXCHANGE'),\n\t\t\tconnections: [\n\t\t\t\t{\n\t\t\t\t\tlogin: configService.get('AMQP_LOGIN'),\n\t\t\t\t\tpassword: configService.get('AMQP_PASSWORD'),\n\t\t\t\t\thost: configService.get('AMQP_HOST'),\n\t\t\t\t},\n\t\t\t],\n\t\t}),\n\t],\n})\nexport class AppModule {}\n```\n\nIn forRoot() you pass connection options:\n\n-   **exchangeName** (string) - Exchange that will be used to send messages to.\n-   **connections** (Object[]) - Array of connection parameters. You can use RMQ cluster by using multiple connections.\n\nAdditionally, you can use optional parameters:\n\n-   **queueName** (string) - Queue name which your microservice would listen and bind topics specified in '@RMQRoute' decorator to this queue. If this parameter is not specified, your microservice could send messages and listen to reply or send notifications, but it couldn't get messages or notifications from other services. If you use empty string, RabbitMQ will generate name for you.\n    Example:\n\n```typescript\n{\n\texchangeName: 'my_exchange',\n\tconnections: [\n\t\t{\n\t\t\tlogin: 'admin',\n\t\t\tpassword: 'admin',\n\t\t\thost: 'localhost',\n\t\t},\n\t],\n\tqueueName: 'my-service-queue',\n}\n```\n\n-   **connectionOptions** (object) - Additional connection options. You can read more [here](http://www.squaremobius.net/amqp.node/).\n-   **prefetchCount** (boolean) - You can read more [here](http://www.squaremobius.net/amqp.node/).\n-   **isGlobalPrefetchCount** (boolean) - You can read more [here](http://www.squaremobius.net/amqp.node/).\n-   **queueOptions** (object) - options for created queue.\n-   **reconnectTimeInSeconds** (number) - Time in seconds before reconnection retry. Default is 5 seconds.\n-   **heartbeatIntervalInSeconds** (number) - Interval to send heartbeats to broker. Defaults to 5 seconds.\n-   **queueArguments** (!!! deprecated. Use queueOptions instead) - You can read more about queue parameters [here](https://www.rabbitmq.com/parameters.html).\n-   **messagesTimeout** (number) - Number of milliseconds 'post' method will wait for the response before a timeout error. Default is 30 000.\n-   **isQueueDurable** (!!! deprecated. Use queueOptions instead) - Makes created queue durable. Default is true.\n-   **isExchangeDurable** (!!! deprecated. Use exchangeOptions instead) - Makes created exchange durable. Default is true.\n-   **exchangeOptions** (Options.AssertExchange) - You can read more about exchange options [here](squaremobius.net/amqp.node/channel_api.html#channel_assertExchange).\n-   **logMessages** (boolean) - Enable printing all sent and recieved messages in console with its route and content. Default is false.\n-   **logger** (LoggerService) - Your custom logger service that implements `LoggerService` interface. Compatible with Winston and other loggers.\n-   **middleware** (array) - Array of middleware functions that extends `RMQPipeClass` with one method `transform`. They will be triggered right after recieving message, before pipes and controller method. Trigger order is equal to array order.\n-   **errorHandler** (class) - custom error handler for dealing with errors from replies, use `errorHandler` in module options and pass class that extends `RMQErrorHandler`.\n-   **serviceName** (string) - service name for debugging.\n-   **autoBindingRoutes** (boolean) - set false you want to manage route binding manualy. Default to `true`.\n\n```typescript\nclass LogMiddleware extends RMQPipeClass {\n\tasync transfrom(msg: Message): Promise\u003cMessage\u003e {\n\t\tconsole.log(msg);\n\t\treturn msg;\n\t}\n}\n```\n\n-   **intercepters** (array) - Array of intercepter functions that extends `RMQIntercepterClass` with one method `intercept`. They will be triggered before replying on any message. Trigger order is equal to array order.\n\n```typescript\nexport class MyIntercepter extends RMQIntercepterClass {\n\tasync intercept(res: any, msg: Message, error: Error): Promise\u003cany\u003e {\n\t\t// res - response body\n\t\t// msg - initial message we are replying to\n\t\t// error - error if exists or null\n\t\treturn res;\n\t}\n}\n```\n\nConfig example with middleware and intercepters:\n\n```typescript\nimport { RMQModule } from 'nestjs-rmq';\n\n@Module({\n\timports: [\n\t\tRMQModule.forRoot({\n\t\t\texchangeName: configService.get('AMQP_EXCHANGE'),\n\t\t\tconnections: [\n\t\t\t\t{\n\t\t\t\t\tlogin: configService.get('AMQP_LOGIN'),\n\t\t\t\t\tpassword: configService.get('AMQP_PASSWORD'),\n\t\t\t\t\thost: configService.get('AMQP_HOST'),\n\t\t\t\t},\n\t\t\t],\n\t\t\tmiddleware: [LogMiddleware],\n\t\t\tintercepters: [MyIntercepter],\n\t\t}),\n\t],\n})\nexport class AppModule {}\n```\n\n## Async initialization\n\nIf you want to inject dependency into RMQ initialization like Configuration service, use `forRootAsync`:\n\n```typescript\nimport { RMQModule } from 'nestjs-rmq';\nimport { ConfigModule } from './config/config.module';\nimport { ConfigService } from './config/config.service';\n\n@Module({\n\timports: [\n\t\tRMQModule.forRootAsync({\n\t\t\timports: [ConfigModule],\n\t\t\tinject: [ConfigService],\n\t\t\tuseFactory: (configService: ConfigService) =\u003e {\n\t\t\t\treturn {\n\t\t\t\t\texchangeName: 'test',\n\t\t\t\t\tconnections: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlogin: 'guest',\n\t\t\t\t\t\t\tpassword: 'guest',\n\t\t\t\t\t\t\thost: configService.getHost(),\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tqueueName: 'test',\n\t\t\t\t};\n\t\t\t},\n\t\t}),\n\t],\n})\nexport class AppModule {}\n```\n\n-   **useFactory** - returns `IRMQServiceOptions`.\n-   **imports** - additional modules for configuration.\n-   **inject** - additional services for usage inside useFactory.\n\n## Sending messages\n\nTo send message with RPC topic use send() method in your controller or service:\n\n```typescript\n@Injectable()\nexport class ProxyUpdaterService {\n\tconstructor(private readonly rmqService: RMQService) {}\n\n\tmyMethod() {\n\t\tthis.rmqService.send\u003cnumber[], number\u003e('sum.rpc', [1, 2, 3]);\n\t}\n}\n```\n\nThis method returns a Promise. First type - is a type you send, and the second - you recive.\n\n-   'sum.rpc' - name of subscription topic that you are sending to.\n-   [1, 2, 3] - data payload.\n    To get a reply:\n\n```typescript\nthis.rmqService.send\u003cnumber[], number\u003e('sum.rpc', [1, 2, 3])\n    .then(reply =\u003e {\n        //...\n    })\n    .catch(error: RMQError =\u003e {\n        //...\n    });\n```\n\nAlso you can use send options:\n\n```typescript\nthis.rmqService.send\u003cnumber[], number\u003e('sum.rpc', [1, 2, 3], {\n\texpiration: 1000,\n\tpriority: 1,\n\tpersistent: true,\n\ttimeout: 30000,\n});\n```\n\n-   **expiration** - if supplied, the message will be discarded from a queue once it’s been there longer than the given number of milliseconds.\n-   **priority** - a priority for the message.\n-   **persistent** - if truthy, the message will survive broker restarts provided it’s in a queue that also survives restarts.\n-   **timeout** - if supplied, the message will have its own timeout.\n\nIf you want to just notify services:\n\n```typescript\nconst a = this.rmqService.notify\u003cstring\u003e('info.none', 'My data');\n```\n\nThis method returns a Promise.\n\n-   'info.none' - name of subscription topic that you are notifying.\n-   'My data' - data payload.\n\n## Recieving messages\n\nTo listen for messages bind your controller or service methods to subscription topics with **RMQRoute()** decorator:\n\n```typescript\nexport class AppController {\n\t//...\n\n\t@RMQRoute('sum.rpc')\n\tsum(numbers: number[]): number {\n\t\treturn numbers.reduce((a, b) =\u003e a + b, 0);\n\t}\n\n\t@RMQRoute('info.none')\n\tinfo(data: string) {\n\t\tconsole.log(data);\n\t}\n}\n```\n\nReturn value will be send back as a reply in RPC topic. In 'sum.rpc' example it will send sum of array values. And sender will get `6`:\n\n```typescript\nthis.rmqService.send('sum.rpc', [1, 2, 3]).then((reply) =\u003e {\n\t// reply: 6\n});\n```\n\nEach '@RMQRoute' topic will be automatically bound to queue specified in 'queueName' option. If you want to return an Error just throw it in your method. To set '-x-status-code' use custom RMQError class.\n\n```typescript\n@RMQRoute('my.rpc')\nmyMethod(numbers: number[]): number {\n\t//...\n    throw new RMQError('Error message', 2);\n\tthrow new Error('Error message');\n\t//...\n}\n```\n\n## Message patterns\n\nWith exchange type `topic` you can use message patterns to subscribe to messages that corresponds to that pattern. You can use special symbols:\n\n-   `*` - (star) can substitute for exactly one word.\n-   `#`- (hash) can substitute for zero or more words.\n\nFor example:\n\n-   Pattern `*.*.rpc` will match `my.own.rpc` or `any.other.rpc` and will not match `this.is.cool.rpc` or `my.rpc`.\n-   Pattern `compute.#` will match `compute.this.equation.rpc` and will not `do.compute.anything`.\n\nTo subscribe to pattern, use it as route:\n\n```typescript\nimport { RMQRoute } from 'nestjs-rmq';\n\n@RMQRoute('*.*.rpc')\nmyMethod(): number {\n\t// ...\n}\n```\n\n\u003e Note: If two routes patterns matches message topic, only the first will be used.\n\n## Getting message metadata\n\nTo get more information from message (not just content) you can use `@RMQMessage` parameter decorator:\n\n```typescript\nimport { RMQRoute, Validate, RMQMessage, ExtendedMessage } from 'nestjs-rmq';\n\n@RMQRoute('my.rpc')\nmyMethod(data: myClass, @RMQMessage msg: ExtendedMessage): number {\n\t// ...\n}\n```\n\nYou can get all message properties that RMQ gets. Example:\n\n```json\n{\n\t\"fields\": {\n\t\t\"consumerTag\": \"amq.ctag-1CtiEOM8ioNFv-bzbOIrGg\",\n\t\t\"deliveryTag\": 2,\n\t\t\"redelivered\": false,\n\t\t\"exchange\": \"test\",\n\t\t\"routingKey\": \"appid.rpc\"\n\t},\n\t\"properties\": {\n\t\t\"contentType\": \"undefined\",\n\t\t\"contentEncoding\": \"undefined\",\n\t\t\"headers\": {},\n\t\t\"deliveryMode\": \"undefined\",\n\t\t\"priority\": \"undefined\",\n\t\t\"correlationId\": \"ce7df8c5-913c-2808-c6c2-e57cfaba0296\",\n\t\t\"replyTo\": \"amq.rabbitmq.reply-to.g2dkABNyYWJiaXRAOTE4N2MzYWMyM2M0AAAenQAAAAAD.bDT8S9ZIl5o3TGjByqeh5g==\",\n\t\t\"expiration\": \"undefined\",\n\t\t\"messageId\": \"undefined\",\n\t\t\"timestamp\": \"undefined\",\n\t\t\"type\": \"undefined\",\n\t\t\"userId\": \"undefined\",\n\t\t\"appId\": \"test-service\",\n\t\t\"clusterId\": \"undefined\"\n\t},\n\t\"content\": \"\u003cBuffer 6e 75 6c 6c\u003e\"\n}\n```\n\n## TSL/SSL support\n\nTo configure certificates and learn why do you need it, [read here](https://www.rabbitmq.com/ssl.html).\n\nTo use `amqps` connection:\n\n```typescript\nRMQModule.forRoot({\n\texchangeName: 'test',\n\tconnections: [\n\t\t{\n\t\t\tprotocol: RMQ_PROTOCOL.AMQPS, // new\n\t\t\tlogin: 'admin',\n\t\t\tpassword: 'admin',\n\t\t\thost: 'localhost',\n\t\t},\n\t],\n\tconnectionOptions: {\n\t\tcert: fs.readFileSync('clientcert.pem'),\n\t\tkey: fs.readFileSync('clientkey.pem'),\n\t\tpassphrase: 'MySecretPassword',\n\t\tca: [fs.readFileSync('cacert.pem')]\n\t} // new\n}),\n```\n\nThis is the basic example with reading files, but you can do however you want. `cert`, `key` and `ca` must be Buffers. Notice: `ca` is array. If you don't need keys, just use `RMQ_PROTOCOL.AMQPS` protocol.\n\nTo use it with `pkcs12` files:\n\n```typescript\nconnectionOptions: {\n\tpfx: fs.readFileSync('clientcertkey.p12'),\n\tpassphrase: 'MySecretPassword',\n\tca: [fs.readFileSync('cacert.pem')]\n},\n```\n\n## Manual message Ack/Nack\n\nIf you want to use your own [ack](https://www.squaremobius.net/amqp.node/channel_api.html#channel_nack)/[nack](https://www.squaremobius.net/amqp.node/channel_api.html#channel_ack) logic, you can set manual acknowledgement to `@RMQRoute`. Than in any place you have to manually ack/nack message that you get with `@RMQMessage`.\n\n```typescript\nimport { RMQRoute, Validate, RMQMessage, ExtendedMessage, RMQService } from 'nestjs-rmq';\n\n@Controller()\nexport class MyController {\n\tconstructor(private readonly rmqService: RMQService) {}\n\n\t@RMQRoute('my.rpc', { manualAck: true })\n\tmyMethod(data: myClass, @RMQMessage msg: ExtendedMessage): number {\n\t\t// Any logic goes here\n\t\tthis.rmqService.ack(msg);\n\t\t// Any logic goes here\n\t}\n\n\t@RMQRoute('my.other-rpc', { manualAck: true })\n\tmyOtherMethod(data: myClass, @RMQMessage msg: ExtendedMessage): number {\n\t\t// Any logic goes here\n\t\tthis.rmqService.nack(msg);\n\t\t// Any logic goes here\n\t}\n}\n```\n\n## Send debug information to error or log\n\n`ExtendedMessage` has additional method to get all data from message to debug it. Also it serializes content and hides Buffers, because they can be massive. Then you can put all your debug info into Error or log it.\n\n```typescript\nimport { RMQRoute, Validate, RMQMessage, ExtendedMessage, RMQService } from 'nestjs-rmq';\n\n@Controller()\nexport class MyController {\n\tconstructor(private readonly rmqService: RMQService) {}\n\n\t@RMQRoute('my.rpc')\n\tmyMethod(data: myClass, @RMQMessage msg: ExtendedMessage): number {\n\t\t// ...\n\t\tconsole.log(msg.getDebugString());\n\t\t// ...\n\t}\n}\n```\n\nYou will get info about message, field and properties:\n\n```json\n{\n\t\"fields\": {\n\t\t\"consumerTag\": \"amq.ctag-Q-l8A4Oh76cUkIKbHWNZzA\",\n\t\t\"deliveryTag\": 4,\n\t\t\"redelivered\": false,\n\t\t\"exchange\": \"test\",\n\t\t\"routingKey\": \"debug.rpc\"\n\t},\n\t\"properties\": {\n\t\t\"headers\": {},\n\t\t\"correlationId\": \"388236ad-6f01-3de5-975d-f9665b73de33\",\n\t\t\"replyTo\": \"amq.rabbitmq.reply-to.g1hkABNyYWJiaXRANzQwNDVlYWQ5ZTgwAAAG2AAAAABfmnkW.9X12ySrcM6BOXpGXKkR+Yg==\",\n\t\t\"timestamp\": 1603959908996,\n\t\t\"appId\": \"test-service\"\n\t},\n\t\"message\": {\n\t\t\"prop1\": [1],\n\t\t\"prop2\": \"Buffer - length 11\"\n\t}\n}\n```\n\n## Customizing massage with msgFactory\n\n`@RMQRoute` handlers accepts a single parameter `msg` which is a ampq `message.content` parsed as a JSON. You may want to add additional custom layer to that message and change the way handler is called. For example, you may want to structure your message with two different parts: payload (containing actual data) and appId (containing request applicationId) and process them explicitly in your handler.\n\nTo do that, you may pass a param to the `RMQRoute` a custom message factory `msgFactory?: (msg: Message) =\u003e any;`.\n\nThe default msgFactory:\n\n```typescript\n@RMQRoute('topic', {\n\tmsgFactory: (msg: Message) =\u003e JSON.parse(msg.content.toString())\n})\n```\n\nCustom msgFactory that returns additional argument (sender appId) and change request:\n\n```typescript\n@RMQRoute(CustomMessageFactoryContracts.topic, {\n\tmsgFactory: (msg: Message) =\u003e {\n\t\tconst content: CustomMessageFactoryContracts.Request = JSON.parse(msg.content.toString());\n\t\tcontent.num = content.num * 2;\n\t\treturn [content, msg.properties.appId];\n\t}\n})\ncustomMessageFactory({ num }: CustomMessageFactoryContracts.Request, appId: string): CustomMessageFactoryContracts.Response {\n\treturn { num, appId };\n}\n```\n\n## Validating data\n\nNestJS-rmq uses [class-validator](https://github.com/typestack/class-validator) to validate incoming data. To use it, decorate your route method with `RMQValidate`:\n\n```typescript\nimport { RMQRoute, RMQValidate } from 'nestjs-rmq';\n\n@RMQValidate()\n@RMQRoute('my.rpc')\nmyMethod(data: myClass): number {\n\t// ...\n}\n```\n\nWhere `myClass` is data class with validation decorators:\n\n```typescript\nimport { IsString, MinLength, IsNumber } from 'class-validator';\n\nexport class myClass {\n\t@MinLength(2)\n\t@IsString()\n\tname: string;\n\n\t@IsNumber()\n\tage: string;\n}\n```\n\nIf your input data will be invalid, the library will send back an error without even entering your method. This will prevent you from manually validating your data inside route. You can check all available validators [here](https://github.com/typestack/class-validator).\n\n## Transforming data\n\nNestJS-rmq uses [class-transformer](https://github.com/typestack/class-transformer) to transform incoming data. To use it, decorate your route method with `RMQTransform`:\n\n```typescript\nimport { RMQRoute, RMQTransform } from 'nestjs-rmq';\n\n@RMQTransform()\n@RMQValidate()\n@RMQRoute('my.rpc')\nmyMethod(data: myClass): number {\n\t// ...\n}\n```\n\nWhere `myClass` is data class with transformation decorators:\n\n```typescript\nimport { Type } from 'class-transformer';\nimport { IsDate } from 'class-validator';\n\nexport class myClass {\n\t@IsDate()\n\t@Type(() =\u003e Date)\n\tdate: Date;\n}\n```\n\nAfter this you can use `data.date` in your controller as Date object and not a string. You can check class-validator docs [here](https://github.com/typestack/class-transformer). You can use transformation and validation at the same time - first transformation will be applied and then validation.\n\n## Using pipes\n\nTo intercept any message to any route, you can use `@RMQPipe` decorator:\n\n```typescript\nimport { RMQRoute, RMQPipe } from 'nestjs-rmq';\n\n@RMQPipe(MyPipeClass)\n@RMQRoute('my.rpc')\nmyMethod(numbers: number[]): number {\n\t//...\n}\n```\n\nwhere `MyPipeClass` extends `RMQPipeClass` with one method `transform`:\n\n```typescript\nclass MyPipeClass extends RMQPipeClass {\n\tasync transfrom(msg: Message): Promise\u003cMessage\u003e {\n\t\t// do something\n\t\treturn msg;\n\t}\n}\n```\n\n## Using RMQErrorHandler\n\nIf you want to use custom error handler for dealing with errors from replies, use `errorHandler` in module options and pass class that extends `RMQErrorHandler`:\n\n```typescript\nclass MyErrorHandler extends RMQErrorHandler {\n\tpublic static handle(headers: IRmqErrorHeaders): Error | RMQError {\n\t\t// do something\n\t\treturn new RMQError(\n\t\t\theaders['-x-error'],\n\t\t\theaders['-x-type'],\n\t\t\theaders['-x-status-code'],\n\t\t\theaders['-x-data'],\n\t\t\theaders['-x-service'],\n\t\t\theaders['-x-host']\n\t\t);\n\t}\n}\n```\n\n## HealthCheck\n\nRQMService provides additional method to check if you are still connected to RMQ. Although reconnection is automatic, you can provide wrong credentials and reconnection will not help. So to check connection for Docker healthCheck use:\n\n```typescript\nconst isConnected = this.rmqService.healthCheck();\n```\n\nIf `isConnected` equals `true`, you are successfully connected.\n\n## Disconnecting\n\nIf you want to close connection, for example, if you are using RMQ in testing tools, use `disconnect()` method;\n\n## Unit and E2e tests\n\n### Using in tests\n\nRMQ library supports using RMQ module in your test suites without needing RabbitMQ instance. To use library in tests, use `forTest` method in module.\n\n```typescript\nimport { RMQTestService } from 'nestjs-rmq';\n\nlet rmqService: RMQTestService;\n\nbeforeAll(async () =\u003e {\n\tconst apiModule = await Test.createTestingModule({\n\t\timports: [RMQModule.forTest({})],\n\t\tcontrollers: [MicroserviceController],\n\t}).compile();\n\tapi = apiModule.createNestApplication();\n\tawait api.init();\n\n\trmqService = apiModule.get(RMQService);\n});\n```\n\nYou can pass any options you pass in normal `forRoot` (except `errorHandler`).\n\nFrom module, you will get `rmqService` which is similar to normal service, with two additional methods:\n\n-   `triggerRoute` - trigger your RMQRoute, simulating incoming message.\n-   `mockReply` - mock reply if you are using `send` method.\n-   `mockError` - mock error if you are using `send` method.\n\n### triggerRoute\n\nEmulates message received buy your RMQRoute.\n\n```typescript\nconst { result } = await rmqService.triggerRoute\u003cRequest, Response\u003e(topic, data);\n```\n\n-   `topic` - topic, that you want to trigger (pattern supported).\n-   `data` - data to send in your method.\n\n### mockReply\n\nIf your service needs to send data to other microservice, you can emulate its reply with:\n\n```typescript\nrmqService.mockReply(topic, res);\n```\n\n-   `topic` - all messages sent to this topic will be mocked.\n-   `res` - mocked response data.\n\nAfter this, all `rmqService.send(topic, { ... })` calls will return `res` data.\n\n### mockError\n\nIf your service needs to send data to other microservice, you can emulate its error with:\n\n```typescript\nrmqService.mockError(topic, error);\n```\n\n-   `topic` - all messages sent to this topic will be mocked.\n-   `error` - error that `send` method will throw.\n\nAfter this, all `rmqService.send(topic, { ... })` calls will throw `error`.\n\n## Contributing\n\nFor e2e tests you need to install Docker in your machine and start RabbitMQ docker image with `docker-compose.yml` in `e2e` folder:\n\n```\ndocker-compose up -d\n```\n\nThen change IP in tests to `localhost` and run tests with:\n\n```\nnpm run test:e2e\n```\n\n![alt cover](https://github.com/AlariCode/nestjs-rmq/raw/master/img/tests.png)\n\nFor unit tests just run:\n\n```\nnpm run test\n```\n\n### Migrating from version 1\n\nNew version of nestjs-rmq contains minor breaking changes, and is simple to migrate to.\n\n-   `@RMQController` decorator is deprecated.\n    You will get warning if you continue to use it, and it will be deleted in future versions.\n    You can safely remove it from a controller or service. `msgFactory` inside options will not be functional anymore. You have to move it to `@RMQRoute`\n-   `msgFactory` changed its interface from\n\n```typescript\nmsgFactory?: (msg: Message, topic: IRouteMeta) =\u003e any[];\n```\n\nto\n\n```typescript\nmsgFactory?: (msg: Message) =\u003e any[];\n```\n\nbecause all `IRouteMeta` already contained in `Message`.\n\n-   `msgFactory` can be passed to `@RMQRoute` instead of `@RMQController`\n","funding_links":[],"categories":["Integrations","TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAlariCode%2Fnestjs-rmq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAlariCode%2Fnestjs-rmq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAlariCode%2Fnestjs-rmq/lists"}