{"id":18337197,"url":"https://github.com/team-supercharge/nest-amqp","last_synced_at":"2025-04-06T16:10:53.607Z","repository":{"id":37977884,"uuid":"296360432","full_name":"team-supercharge/nest-amqp","owner":"team-supercharge","description":"Nest AMQP 1.0 module - NPM package: https://www.npmjs.com/package/@team-supercharge/nest-amqp","archived":false,"fork":false,"pushed_at":"2025-03-07T15:53:27.000Z","size":1155,"stargazers_count":27,"open_issues_count":9,"forks_count":16,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-30T15:07:49.473Z","etag":null,"topics":["amqp","nest","nodejs","queue"],"latest_commit_sha":null,"homepage":"https://supercharge.io","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/team-supercharge.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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":"2020-09-17T15:02:47.000Z","updated_at":"2025-03-07T14:44:10.000Z","dependencies_parsed_at":"2024-06-20T21:24:59.693Z","dependency_job_id":null,"html_url":"https://github.com/team-supercharge/nest-amqp","commit_stats":{"total_commits":83,"total_committers":6,"mean_commits":"13.833333333333334","dds":0.6746987951807228,"last_synced_commit":"dc38682f46cc1d15ccb5ff8a4d51041f3b8e0d1d"},"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/team-supercharge%2Fnest-amqp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/team-supercharge%2Fnest-amqp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/team-supercharge%2Fnest-amqp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/team-supercharge%2Fnest-amqp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/team-supercharge","download_url":"https://codeload.github.com/team-supercharge/nest-amqp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247509221,"owners_count":20950232,"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","nest","nodejs","queue"],"created_at":"2024-11-05T20:10:25.628Z","updated_at":"2025-04-06T16:10:53.586Z","avatar_url":"https://github.com/team-supercharge.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nest AMQP 1.0 Module\n\n[![Build Status](https://github.com/team-supercharge/nest-amqp/actions/workflows/master-branch.yml/badge.svg)](https://github.com/team-supercharge/nest-amqp/actions/workflows/master-branch.yml)\n[![Coverage Status](https://codecov.io/github/team-supercharge/nest-amqp/coverage.svg?branch=master)](https://codecov.io/github/team-supercharge/nest-amqp)\n\u003ca href=\"https://www.npmjs.com/@team-supercharge/nest-amqp\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@team-supercharge/nest-amqp.svg\" alt=\"NPM Version\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://www.npmjs.com/@team-supercharge/nest-amqp\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/npm/l/@team-supercharge/nest-amqp.svg\" alt=\"Package License\" /\u003e\u003c/a\u003e\n\n## Description\n\nAMQP 1.0 module for [Nest](https://github.com/nestjs/nest). It is based on the\n[rhea-promise](https://www.npmjs.com/package/rhea-promise) package. This package is for\nworking with a message broker with extra data validation functionality. It uses the\n[class-transformer](https://www.npmjs.com/package/class-transformer) and\n[class-validator](https://www.npmjs.com/package/class-validator) packages to transform\nand validate the payload of the messages. With this we can easily verify the message's\npayload structure and its data types with Data Transfer Objects. Besides, it gives\ncontrol over the message how to handle it: accept, reject or release.\n\n## Installation\n\n```bash\n$ npm install --save @team-supercharge/nest-amqp\n```\n\nTo use the library, the peer dependencies must also be installed:\n```bash\n$ npm install --save class-transformer class-validator\n```\n\n## Usage\n\nIn the following subsections you can see how to send and receive messages, how to handle message transfer and how to use DTO classes for message\npayload transformation and validation.\n\n### Module import and connection options\n\nTo create a connection, you have to set the connection details. The library provides an easy way to set the connection details via a string\nconnection URI. The library will parse this connection URI and set the appropriate connection options. Besides, you can add your custom\nconnection options or other library settings with the module options.\n\n#### Connection URI\n\nThis library provides an easier way to set the connection options with a connection URI: you can describe the connection settings with a\nURL. The library will parse the URL and set the corresponding options. Here you can see the description of the URL:\n```bash\nprotocol://[username:password@]host:port\n```\n\nThe `username` and `password` components are optional, with these you can set the authentication credentials to the message queue server.\n\n\u003e Note: if you would like to use special characters in username or password, then you have to `encodeURIComponent()` these values, because\n\u003e the library will decode the values right before connection creation. If you don't encode these values, then you will get a URL parse\n\u003e error.\n\u003e\n\u003e If you use environment variables to connection username or password, then use the env values with `encodeURIComponent()` as well.\n\u003e\n\u003e Example:\n\u003e ```\n\u003e const username = encodeURIComponent('Jörg');\n\u003e const password = encodeURIComponent('Gt|N#R=6$5(TE@rH\"Pvc$7a');\n\u003e const connectionUri = `amqps://${username}:${password}@localhost:5672`;\n\u003e ```\n\nYou can set custom protocol which will set the connection transport automatically, so you don't have to add the `transport` to the connection\noptions object. The protocol can be:\n* **amqp**: in this case the `transport` will be `tcp`\n* **amqps**: in this case the `transport` will be `ssl`\n* **amqp+ssl**: in this case the `transport` will be `ssl`\n* **amqp+tls**: in this case the `transport` will be `tls`\n\nExamples:\n* `amqp://localhost:5672`\n* `amqps://user:password@my-server.com:5672`\n* `amqp+tls://admin:secret@127.0.0.1:5672`\n\n#### Create connection\n\nTo create a connection, you have to import the `QueueModule.forRoot()` module into your application's root module. The `forRoot()`\nstatic method has multiple parameters:\n* for single connection:\n  * the first and required is either the connection URI string, or the module configuration object\n  * the *optional* second parameter is the module and connection configuration object sans the connection URI, if you provided the URI as a first parameter\n* for multiple connections:\n  * the first and required parameter is an array of *connection configuration* objects\n  * the *optional* second parameter is the module configuration object\n\nTo see the available module options, scroll down.\nHere are some simple examples:\n\n```typescript\n// for single connection\n\nimport { Module } from '@nestjs/common';\nimport { QueueModule } from '@team-supercharge/nest-amqp';\n\n@Module({\n  imports: [\n    QueueModule.forRoot('amqp://user:password@localhost:5672'),\n    // or alternatively\n    // QueueModule.forRoot({ connectionUri: 'amqp://user:password@localhost:5672' }),\n  ],\n})\nexport class AppModule {}\n```\n\n```typescript\n// for multiple connections\n\nimport { Module } from '@nestjs/common';\nimport { QueueModule } from '@team-supercharge/nest-amqp';\n\n@Module({\n  imports: [\n    QueueModule.forRoot([\n      { connectionUri: 'amqp://user1:password1@localhost:5671' },\n      { connectionUri: 'amqp://user2:password2@localhost:5672', name: Connections.WORKER },\n    ]),\n  ],\n})\nexport class AppModule {}\n```\n\n#### Create connection with asynchronous module configuration\n\nGenerally we are using environment variables to configure our application. Nest provides the\n[ConfigService](https://docs.nestjs.com/techniques/configuration) to use these env variables nicely. If you would like to configure the\nAMQP module with env variables, or you are using another asynchronous way to get the configuration, then you have to use the\n`forRootAsync()` static method instead of `forRoot()` on the `QueueModule` class. To see the available module options, scroll down.\nHere is an example:\n\n\u003e Note: the @team-supercharge/nest-amqp package does not support multiple connection on asynchronous module configuration!\n\n```typescript\nimport { Module } from '@nestjs/common';\nimport { ConfigModule, ConfigService } from '@nestjs/config';\nimport { QueueModule, QueueModuleOptions } from '@team-supercharge/nest-amqp';\n\n@Module({\n  imports: [\n    QueueModule.forRootAsync({\n      imports: [ConfigModule],\n      useFactory: (configService: ConfigService): QueueModuleOptions =\u003e ({\n        connectionUri: configService.get\u003cstring\u003e('AMQP_CONNECTION_URI'),\n        connectionOptions: {\n          transport: configService.get\u003cstring\u003e('AMQP_CONNECTION_TRANSPORT'),\n        }\n      }),\n      inject: [ConfigService],\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\nInstead of `useFactory` you can use `useClass` or `useExisting` to set module options. You can see the examples in the\n[test file](https://github.com/team-supercharge/nest-amqp/tree/master/src/queue.module.spec.ts).\n\n#### Module options\n\nThe module options object needs to be added to the `forRoot()` or `forRootAsync()` static method. The possible options can be these:\n* **isGlobal**?: A boolean value. If this property is `true`, then you can skip the import with`.forFeature()` method in the feature\n  modules, because the public services will be available in all modules which imports the root module. Default value is\n  `false`. (You can read more about it on [Nest modules page](https://docs.nestjs.com/modules#global-modules))\n* **logger**?: A custom object or class instance which implements the `LoggerService` interface from the `@nestjs/common` package.\n  With this option, you can use your own logging method to log information in `@team-supercharge/nest-amqp` library. If it is\n  not set then the library will use Nest's `Logger` service to logging. You can see a full example below in the readme.\n  Default value is `undefined`.\n* **throwExceptionOnConnectionError**?: A boolean value. If it's `true` then QueueModule will throw forward the exception which occurs\n  during the connection creation. Default value is `false`.\n* **connectionUri**?: It is an optional string property. This is required only when you are use the `forRootAsync()` method or the\n  `forRoot()` method for single connection with only an object argument.\n* **connectionOptions**?: It is an optional object. With this you can set\n  [Rhea's connection options](https://www.npmjs.com/package/rhea#connectoptions) which will be passed to the `Connection` object\n  during connection creation. The default value is `{}`.\n\nFirst basic example:\n```typescript\n@Module({\n  imports: [\n    QueueModule.forRoot(\n      'amqp://user:password@localhost:5672',\n      {\n        isGlobal: true,\n        throwExceptionOnConnectionError: true,\n        connectionOptions: {\n          transport: 'tcp'\n        }\n      }\n    ),\n  ],\n})\nexport class AppModule {}\n```\n\nSecond example with asynchronous configuration:\n```typescript\n@Module({\n  imports: [\n    QueueModule.forRootAsync({\n      // in case of `QueueModule.forRootAsync`, isGlobal property goes here and\n      // not into the object returned by 'useFactory' or 'useClass' or 'useExisting'\n      isGlobal: true,\n      imports: [ConfigModule],\n      useFactory: (configService: ConfigService): QueueModuleOptions =\u003e ({\n        connectionUri: configService.get\u003cstring\u003e('AMQP_CONNECTION_URI'),\n        throwExceptionOnConnectionError: true,\n        connectionOptions: {\n          transport: configService.get\u003cstring\u003e('AMQP_CONNECTION_TRANSPORT'),\n        }\n      }),\n      inject: [ConfigService],\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n### Custom logger\n\nYou can use your own logger solution in the library. To do this, you have to create a class which implements the `LoggerService` interface\nfrom the `@nestjs/common` package. After that you can add the class instance to the module options, and the logging will work with your\ncustom solution. The `@team-supercharge/nest-amqp` library will use this one instance/object to log everything inside, so it is good if you\nuse the `context` argument in the log methods to determine who is logging currently. Here is an example:\n\n```typescript\nimport { LoggerService, Module } from \"@nestjs/common\";\n\nclass MyLogger implements LoggerService {\n  public log(message: any, context: string): void {\n    console.log(`[${context}] ${message}`);\n  }\n  public error(message: any, trace: string, context: string): void {\n    console.error(`[${context}] ${message}`);\n  }\n  public warn(message: any, context: string): void {\n    console.warn(`[${context}] ${message}`);\n  }\n  public debug(message: any, context: string): void {\n    console.debug(`[${context}] ${message}`);\n  }\n  public verbose(message: any, context: string): void {\n    console.log(`[${context}] ${message}`);\n  }\n}\n\n@Module({\n  imports: [\n    QueueModule.forRoot(\n      'amqp://user:password@localhost:5672',\n      {\n        logger: new MyLogger()\n      }\n    ),\n  ],\n})\nexport class AppModule {}\n```\n\n### Send a message\n\n#### Single connection\nYou can send messages with the `QueueService`. First you have to inject the service instance in the constructor, then you can use it to\nsend a message. Here is an example:\n\n```typescript\nimport { Injectable } from '@nestjs/common';\nimport { QueueService } from '@team-supercharge/nest-amqp';\n\n@Injectable()\nexport class TestService {\n  constructor(private readonly queueService: QueueService) {}\n\n  public async sendMessage(): Promise\u003cvoid\u003e {\n    const payload = { text: 'hello world', date: new Date() };\n    await this.queueService.send\u003cTestDto\u003e('example', payload);\n  }\n}\n```\n\nIn the example we send a message to the `example` queue with an object payload. The `QueueService` will stringify the object and send the\nmessage with the stringified object as payload. You can add a DTO class as generic type to the `send\u003cT\u003e()` method and TypeScript will\ncheck that the second argument is matches with the DTO class.\n\n\u003e Note: the `send\u003cT\u003e()` method won't validate and transform the payload, it only stringifies the payload to a string value and send objects\n\u003e as string payload.\n\nThe `send\u003cT\u003e()` method's third parameter is the options which is an optional object. You can set here the\n[rhea connection options](https://github.com/amqp/rhea/blob/2cbe55795b86a43375111f2f446089f55b948ecf/typings/connection.d.ts#L525)\nas well. Other custom available options:\n* **schedule.divideMinute**?: Send the message multiple times a minute given by this number.\n* **schedule.cron**?: Send the message multiple times given by this standard cron string.\n* **schedule.afterSeconds**?: Message sending delay in seconds.\n\n#### Multiple connections\n\nSending messages with multiple connections works mostly the same, the only difference is that we need to define to which connection do we want to send the message. Here is an example:\n\n```typescript\nimport { Injectable } from '@nestjs/common';\nimport { QueueService } from '@team-supercharge/nest-amqp';\n\nimport { Connections } from './constants';\n\n@Injectable()\nexport class TestService {\n  constructor(private readonly queueService: QueueService) {}\n\n  public async sendMessage(): Promise\u003cvoid\u003e {\n    const payload = { text: 'hello world', date: new Date() };\n\n    await this.queueService.send\u003cTestDto\u003e('example', payload, Connections.TEST);\n  }\n\n  public async sendDelayedMessage(): Promise\u003cvoid\u003e {\n    const payload = { text: 'hello world', date: new Date() };\n    const sendOptions = { schedule: { afterSeconds: 10 } };\n\n    await this.queueService.send\u003cTestDto\u003e('example', payload, sendOptions, Connections.TEST);\n  }\n}\n```\n\n\u003e Note: It is assumed that there is an enum named `Connections`, and\nthe connections defined in the `forRoot` method contains a connection named `Connections.TEST`.\n\n\u003e Note: If you leave out the name of the connection, it will be sent a to the default connection (if exists).\n\n### Listen to a queue\n\n#### Single connection\n\nIf you want to receive the messages which arrive at a queue then you have to listen on the specific queue. You can do this with the\n`@Listen()` decorator which you can add to a method of a class which has the `@Injectable()` decorator. Here is an example:\n\n```typescript\n@Injectable()\nexport class ExampleListener {\n  @Listen('example', { type: PayloadDto })\n  public async listenForQueueMessages(data: PayloadDto, control: MessageControl): Promise\u003cvoid\u003e {\n    console.log('new message arrived on the \"example\" queue:', data);\n  }\n}\n```\n\nThe `@Listen()` decorator's first parameter is the name of the queue, which we are listening to. When a new message arrives, this method\nwill be invoked with 2 arguments in order: `message payload` and `message control`. The `message payload` is a Data Transfer Object (DTO)\nclass's instance. The task of this DTO class is to describe the payload's data structure for validation and transformation. We do this with\ndecorators. The second argument is the `message control` object which gives control how to handle the message transfer.\n\nThe `@Listen()` decorator has a second argument which is the options object. The options object can have these **optional** properties:\n* **type**?: A class reference which is decorated with [class-transformer](https://www.npmjs.com/package/class-transformer) and\n  [class-validator](https://www.npmjs.com/package/class-validator) decorators. The data validation and transformation will be done\n  with this class.\n  \u003e Note: if `type` is not provided, the incoming message will not be processed, and the handler will not receive the message, but `null` instead\n* **skipValidation**?: if it is `true` then the message payload won't be validated and transformed by the `type` property's value. The\n  default value is `false`.\n* **acceptValidationNullObjectException**?: A boolean value. If it's `true` then QueueModule will accept the message when a\n`ValidationNullObjectException` error is thrown during message transformation and validation. (`ValidationNullObjectException` will be thrown when message body is null). Otherwise the\nmessage will be rejected on `ValidationNullObjectException` error. Default value is `false`.\n* **parallelMessageProcessing**?: The most number of messages that should be processed at the same time. The default value is `1`.\n* **transformerOptions**?: [class-transformer options](https://github.com/typestack/class-transformer/blob/develop/src/interfaces/class-transformer-options.interface.ts)\n* **validatorOptions**?: [class-validator options](https://github.com/typestack/class-validator#passing-options)\n\n#### Multiple connections\n\nListening for messages with multiple connections works mostly the same, the only difference is that we need to define on which connection are we listening for messages. Here is an example:\n\n```typescript\n@Injectable()\nexport class ExampleListener {\n  @Listen('example', Connections.INTERNAL)\n  public async listenForInternalTicks(_tick: unknown, control: MessageControl): Promise\u003cvoid\u003e {\n    console.log(`new tick arrived on the \"example\" queue on connection ${Connections.INTERNAL}:`, data);\n  }\n\n  @Listen('example', { type: PayloadDto }, Connections.WORKER)\n  public async listenForWorkerMessages(data: PayloadDto, control: MessageControl): Promise\u003cvoid\u003e {\n    console.log(`new message arrived on the \"example\" queue on connection ${Connections.WORKER}:`, data);\n  }\n}\n```\n\n\u003e Note: It is assumed that there is an enum named `Connections`, and\nthe connections defined in the `forRoot` method contains a connection named `Connections.INTERNAL` and `Connections.WORKER`.\n\n\u003e Note: If you leave out the name of the connection, the listener will be attached to the default connection (if exists).\n\n\n### Removing a listener\n\nIf you want to remove a listener, you can use the `removeListener()` method of the `QueueService`. The method's first parameter is the name string or `Source` object of the queue, and the second (optional) parameter is the connection name if you have set it up. Here is an example:\n\n```typescript\n// with the default connection\nawait this.queueService.removeListener('example');\n```\n\n```typescript\n// with named connection\nawait this.queueService.removeListener('example', Connections.TEST);\n```\n\n### Message control\n\nWhen a new message arrives at a queue, the assigned method with `@Listen()` decorator receives the transformed and validated message body\nand the message control. The latter object is to control the message transfer. It is possible to accept, reject or release the transfer.\nHere are the examples:\n\n```typescript\n// accept the message\ncontrol.accept();\n\n// reject the message\ncontrol.reject('processing failed');\n\n// release the message\ncontrol.release();\n```\n\nUse `accept` when message has been handled normally. It will remove the message from the queue.\nUse `reject` when message was unprocessable. It contained either malformed or semantically incorrect data. In other words\nit can't be successfully processed in the future without modifications. It will remove the message from the queue.\nUse `release` when a temporary problem happened during message handling, e.g. could not save record to DB, 3rd party service\nerrored, etc. The message is not malformed and theoretically can be processed at a later time without modifications. The\nmessage will not be removed from the queue but will be processed by another consumer.\n\n\u003e If the message was not handled manually and the method with `@Listen()` decorator executed successfully then the message\nwill be accepted. If the message was not handled manually and there was an `Error` or `Exception` then the message will be rejected\nautomatically.\n\n\u003e Note relating to ActiveMQ: Active MQ current version (5.16.2 as of this writing) does not differentiate between `release` and `reject`, both will be understood as `release`.\n\n### Payload validation and transformation\n\nThe module provides an opportunity for adding transformation and validation process to the message payload.\nWith transformation, we can set what properties are important for us and what properties should be skipped during the transformation.\nWith validation, we can check that the payload has the expected properties with valid values.\n\nHere is an example DTO class:\n\n```typescript\nimport { Exclude, Expose, Transform } from 'class-transformer';\nimport { IsIn, IsDateString, IsString } from 'class-validator';\n\n@Exclude()\nexport class LogEntryDto {\n  @Expose()\n  @IsString()\n  public readonly message: string;\n\n  @Expose()\n  @IsDateString()\n  @Transform(value =\u003e new Date(value), { toClassOnly: true })\n  public readonly date: Date;\n\n  @Expose()\n  @IsIn([1, 2, 3, 4, 5])\n  public readonly level: number;\n\n  constructor(props: Partial\u003cLogEntryDto\u003e) {\n    Object.assign(this, props);\n  }\n}\n```\n\nThe `@Expose()` decorator says that after the transformation, the properties with this decorator should stay in the `LogEntryDto` class\ninstance. The DTO class has an `@Exclude()` decorator which means that the properties that are not described in the class definition or\ndon't have `@Expose()` decorator will be removed from the resulting instance during the transformation . With these 2 decorators we can specify which\nproperties we want from the payload when the message arrives at the consumer side.\n\nThe `@Transform()` decorator is to manually cast or transform a value during the transformation process. In the example we can see that when the message arrives, the body will contain a JSON object which is converted to string.\nThe stringified JSON object has only primitive values so the `date` property will be a string\ndate. We want it as a `Date` object instance, so we manually transform it into a Date object with the `@Transform()` decorator. We have to notice that only when the payload will be transformed to the DTO object (i.e. when the message arrives at the consumer side) and not when\nthe object will be transformed to a string (i.e. before the sending on the producer side), because the DTO object will be represented as\na string in the message payload. The other decorators are to validate the property values.\n\nAn object payload's lifetime during the whole sending-receiving process:\n```\n                                        send                               receive\nMessage's way:     sender (producer)  ---------\u003e  queue (message broker)  ---------\u003e  receiver (consumer)\n                                      transform                           transform\nPayload's format:   DTO instance or   ---------\u003e          string          ---------\u003e     DTO instance\n                   JavaScript object\n```\n\nYou can see that the sender sends a DTO object instance or a plain object which will be converted to string and the message broker receives this string as message body.\nWhen the consumer gets the message, the body is a string and the transformation process will transform it into a DTO instance.\nOnly one thing left: set this DTO class as message payload:\n\n```typescript\n@Listen('logsQueue', { type: LogEntryDto })\npublic async listenForLogsQueueMessages(data: LogEntryDto): Promise\u003cvoid\u003e {\n  console.log('log entry:', data);\n}\n```\n\nYou can send any other primitive values as message payload but in this case you have to take care to disable the validation and\ntransformation process. Here is the example:\n\n```typescript\n@Listen('stringQueue', { type: String, skipValidation: true })\npublic async listenForStringQueueMessages(data: string): Promise\u003cvoid\u003e {\n  console.log('message payload:', data);\n}\n```\n\n\u003e Note: Defining `type` is required if we want to receive primitive values as the message.\n### Module logs\n\nThe module uses [debug](https://www.npmjs.com/package/debug) package for logging. If you start the Nest application with the `DEBUG`\nenvironment variable, then you can set the level of logging:\n\n```bash\n# log everything\n$ DEBUG=nest-amqp:* nest start\n\n# log only the errors\n$ DEBUG=nest-amqp:error:* nest start\n```\n\n### Shutdown\n\nIf you stop your application, then Nest will wait for the end of the currently processing messages and will exit after the processes\nfinished.\n\n## Example\n\nFirst you have to import the Queue module into the app module. The `QueueModule.forRoot()` method's first parameter\nis the connection URI for the message broker server:\n\n\u003e Note: the `QueueModule.forRoot()` can be added only to the application's root module and only once\n\n```typescript\nimport { QueueModule } from '@team-supercharge/nest-amqp';\n// ...\n\n@Module({\n  imports: [\n    QueueModule.forRoot('amqp://user:password@localhost:5672'),\n    // ...\n  ],\n})\nexport class AppModule {}\n```\n\nThen create a `user.module.ts` feature module what will give all the functionality which belongs to the users.\n\n\u003e Note: the `QueueModule.forFeature()` module must be imported to each feature module of the application.\n\n```typescript\nimport { Module } from '@nestjs/common';\nimport { QueueModule } from '@team-supercharge/nest-amqp';\n\n@Module({\n  imports: [QueueModule.forFeature()],\n  controllers: [],\n  providers: [],\n})\nexport class UserModule {}\n```\n\nImport this `UserModule` in the `AppModule`.\n\nAfter that create the `user.dto.ts` file and add a data transfer object (DTO) class to it which will be sent as body in the queue message.\nThe [class-transformer](https://www.npmjs.com/package/class-transformer) package is used to transform (rename, remove, alter type, etc...) the object properties before sending it to / after receiving it from the queue and\nthe [class-validator](https://www.npmjs.com/package/class-validator) package is used to validate the received object on the consumer side:\n\n```typescript\nimport { Expose } from 'class-transformer';\nimport { IsInt, IsString } from 'class-validator';\n\n@Expose()\nexport class AddUserDto {\n  @IsString()\n  public readonly name: string;\n\n  @IsInt()\n  public readonly age: number;\n\n  constructor(userData: AddUserDto) {\n    Object.assign(this, userData);\n  }\n}\n```\n\nAfter that create the `user.listener.ts` file and add  a new listener class to it which has a method\nwith the `@Listen()` decorator to listen the specified queue's messages:\n\n\u003e Note: you can add the `@Listen()` decorator for any class which have the `@Injectable()` decorator.\n\n```typescript\nimport { Injectable } from '@nestjs/common';\nimport { Listen, MessageControl } from '@team-supercharge/nest-amqp';\n\nimport { AddUserDto } from './user.dto';\n\n@Injectable()\nexport class UserListener {\n  @Listen('addUser', { type: AddUserDto })\n  public async listenForQueueNameMessages(data: AddUserDto, control: MessageControl): Promise\u003cvoid\u003e {\n    console.log('new message arrived on the \"addUser\" queue:', data);\n    control.accept();\n  }\n}\n```\n\nThen we create a `user.controller.ts` file and add a HTTP endpoint which will send the message to the queue with the payload what it gets as HTTP body:\n\n```typescript\nimport { Body, Controller, Post } from '@nestjs/common';\nimport { QueueService } from '@team-supercharge/nest-amqp';\n\nimport { AddUserDto } from './user.dto';\n\n@Controller('user')\nexport class UserController {\n  constructor(private readonly queueService: QueueService) {}\n\n  @Post()\n  public async sendAddUserMessage(@Body() body: AddUserDto): Promise\u003cstring\u003e {\n    await this.queueService.send\u003cAddUserDto\u003e('addUser', body);\n\n    return 'Add user message sent';\n  }\n}\n```\n\nWe can see that the `send()` method is responsible to add a message to the given queue.\n\nThe last thing is to add this controller to the corresponding module:\n\n```typescript\nimport { UserController } from './user.controller';\nimport { UserListener } from './user.listener';\n// ...\n\n@Module({\n  controllers: [UserController],\n  providers: [UserListener],\n})\nexport class UserModule {}\n```\n\nFinally, start the app with `npm run start` and it will listen on http://localhost:4444 URL. You can test the functionality with sample HTTP requests which are in the `examples/01-Basic_Connection/http-requests/add-user.http` file.\n\n## License\n\n@team-supercharge/nest-amqp is [MIT licensed](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteam-supercharge%2Fnest-amqp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fteam-supercharge%2Fnest-amqp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteam-supercharge%2Fnest-amqp/lists"}