@bgaldino/nestjs-rabbitmq 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,428 @@
1
+ # @bgaldino/nestjs-rabbitmq
2
+
3
+ # Table of Contents
4
+
5
+ <!--toc:start-->
6
+
7
+ - [@bgaldino/nestjs-rabbitmq](#bgaldinonestjs-rabbitmq)
8
+ - [Table of Contents](#table-of-contents)
9
+ - [Description](#description)
10
+ - [Requirements](#requirements)
11
+ - [Instalation](#instalation)
12
+ - [Getting Started](#getting-started)
13
+ - [Importing the module](#importing-the-module)
14
+ - [The configuration file](#the-configuration-file)
15
+ - [Publishers](#publishers)
16
+ - [Publishing messages](#publishing-messages)
17
+ - [Consumers](#consumers)
18
+ - [The messageHandler callback](#the-messagehandler-callback)
19
+ - [Strongly typed consumer](#strongly-typed-consumer)
20
+ - [Consumer late loading](#consumer-late-loading)
21
+ - [Declaration example](#declaration-example)
22
+ - [Retrying strategy](#retrying-strategy)
23
+ - [Disabling the automatic ack](#disabling-the-automatic-ack)
24
+ - [Message inspection and logging](#message-inspection-and-logging)
25
+ - [How to build this library locally ?](#how-to-build-this-library-locally)
26
+ - [License](#license)
27
+ <!--toc:end-->
28
+
29
+ ## Description
30
+
31
+ This module features an opinionated way of configuring the RabbitMQ connection
32
+ by using a configuration file that describes the behaviour of all publishers
33
+ and consumers present in your project
34
+
35
+ ### Requirements
36
+
37
+ - @nestjs/common: ">9"
38
+ - An RabbitMQ instance with the
39
+ [RabbitMQ Delayed Message Plugin](https://github.com/rabbitmq/rabbitmq-delayed-message-exchange) installed
40
+
41
+ ### Instalation
42
+
43
+ **PNPM**
44
+
45
+ ```shell
46
+ pnpm add @nestjs-rabbitmq
47
+ ```
48
+
49
+ **YARN**
50
+
51
+ ```shell
52
+ yarn add @nestjs-rabbitmq
53
+ ```
54
+
55
+ **NPM**
56
+
57
+ ```shell
58
+ npm add @nestjs-rabbitmq
59
+ ```
60
+
61
+ <!-- ## Connection Management -->
62
+ <!---->
63
+ <!-- This package wraps around the [`amqp-connection-manager`](https://github.com/benbria/node-amqp-connection-manager) -->
64
+ <!-- to manage all AMQP connections with RabbitMQ -->
65
+ <!---->
66
+ <!-- When starting a connection, an instance of `AmqpConnectionManager` is created, passing the following information: -->
67
+ <!---->
68
+ <!-- ```typescript -->
69
+ <!-- this.connection = connect(options.connectionString, { -->
70
+ <!-- heartbeatIntervalInSeconds: 60, -->
71
+ <!-- reconnectTimeInSeconds: 5, -->
72
+ <!-- connectionOptions: { -->
73
+ <!-- keepAlive: true, -->
74
+ <!-- keepAliveDelay: 5000, -->
75
+ <!-- servername: hostname(), -->
76
+ <!-- clientProperties: { -->
77
+ <!-- connection_name: `${process.env.npm_package_name}-${hostname()}`, -->
78
+ <!-- }, -->
79
+ <!-- }, -->
80
+ <!-- }); -->
81
+ <!-- ```` -->
82
+
83
+ <!-- Esta conexão é então utilizada para criar quaisquer canais necessários para consumidores registrados e um único canal para publicar mensagens, portanto, apenas UMA conexão é criada ao longo de todo o ciclo de vida do SDK. -->
84
+
85
+ ## Getting Started
86
+
87
+ ### Importing the module
88
+
89
+ Import the `RabbitMQModule` in your `app.module.ts` and call the method `register({})`
90
+
91
+ ```typescript
92
+ import { RabbitMQModule } from '@bgaldino/nestjs-rabbitmq';
93
+ import { RabbitOptions } from '@bgaldino/nestjs-rabbitmq';
94
+
95
+ @Module({
96
+ imports: [
97
+ ...
98
+ RabbitMQModule.register({ useClass: RabbitOptions, injects: [...] }),
99
+ ...
100
+ ]
101
+ })
102
+ export class AppModule {}
103
+ ```
104
+
105
+ The `RabbitMQModule` is marked as `@Global`, therefore, calling it once is enough
106
+ to allow the injection of the `RabbitMQService`
107
+
108
+ ### The configuration file
109
+
110
+ Create a `rabbitmq.config.ts` or whatever the name you prefer containing the minimum configuration:
111
+
112
+ ```typescript
113
+ import { Injectable } from "@nestjs/common";
114
+ import {
115
+ RabbitMQModuleOptions,
116
+ RabbitOptionsFactory,
117
+ } from "@bgaldino/nestjs-rabbitmq";
118
+
119
+ @Injectable()
120
+ export class RabbitOptions implements RabbitOptionsFactory {
121
+ createRabbitOptions(): RabbitMQModuleOptions {
122
+ return {
123
+ connectionString: "amqp://{user}:{password}@{url}/{vhost}",
124
+ delayExchangeName: "MyDelayExchange",
125
+ assertExchanges: [],
126
+ consumerChannels: [],
127
+ };
128
+ }
129
+ }
130
+ ```
131
+
132
+ ## Publishers
133
+
134
+ **Example config file**:
135
+
136
+ ```typescript
137
+ assertExchanges: [
138
+ { name: 'webhooks', type: 'topic',options: { durable: true, autoDelete: false } },
139
+ { name: 'test-fanout', type: 'fanout' },
140
+ { name: 'example-direct', type: 'direct', , options: {exchangeSuffix: '.mySufix'}},
141
+ ],
142
+ ```
143
+
144
+ The `assertExchanges` property expects an array of `RabbitMQAssertExchange`
145
+ and each entry will asserted against the RabbitMQ connected server.
146
+
147
+ If any entry does not match a current configuration, or cannot be
148
+ created/attached. A terminal error `406 - PRECONDITION_FAILED` will be thrown
149
+ with the reason and the server will not initialize
150
+
151
+ By default every exchange will have the `.exchange` attached to its name.
152
+ If you want to remove this, you can pass an empty value to the
153
+ `exchangeSuffix` property
154
+
155
+ ### Publishing messages
156
+
157
+ **Example**:
158
+
159
+ ```typescript
160
+ import { Injectable } from "@nestjs/common";
161
+ import { RabbitMQService } from "@bgaldino/nestjs-rabbitmq";
162
+
163
+ @Injectable()
164
+ export class MyService {
165
+ constructor(private readonly rabbitMQService: RabbitMQService) {}
166
+ }
167
+
168
+ async publishMe(){
169
+ const isPublished = await this.rabbitMQService.publish('exchange_name', 'routing_key', {});
170
+ }
171
+
172
+ //or
173
+
174
+ async publishMeTyped() {
175
+ const isPublished = await this.rabbitMQService.publish<CustomType>('exchange_name', 'routing_key', {});
176
+ //This will return an error if the object is not properly typed
177
+ }
178
+ ```
179
+
180
+ The `publish()` method uses [Publish Confirms](https://www.rabbitmq.com/docs/confirms#publisher-confirms)
181
+ to make sure that the message is delivered to the broker before returning
182
+ the promise.
183
+
184
+ ## Consumers
185
+
186
+ Inside the configuration file you can declare your consumers on the section
187
+ `consumerChannels`. This list of `RabbitMQConsumerChannel` will be evaluated
188
+ and each entry will try to create the queue and bind it to the declared
189
+ exchange.
190
+
191
+ **Example:**
192
+
193
+ ```typescript
194
+
195
+ createRabbitOptions(): RabbitMQModuleOptions {
196
+ return {
197
+ ...,
198
+ consumerChannels: [
199
+ {
200
+ options: {
201
+ queue: 'myqueue',
202
+ exchangeName: 'foobar.exchange',
203
+ routingKey: 'myqueue',
204
+ prefetch: Number(process.env.RABBIT_PREFETCH ?? 10),
205
+ retryStrategy: {
206
+ enabled: true,
207
+ maxAttempts: 5,
208
+ delay: (attempt: number) => {
209
+ return attempt * 5000;
210
+ },
211
+ },
212
+ },
213
+ messageHandler: this.consumerService.messageHandler.bind(
214
+ this.consumerService,
215
+ ),
216
+ },
217
+ ]
218
+ }
219
+ }
220
+ ```
221
+
222
+ The consumer **DOES NOT** create exchanges and only bind to ones that already
223
+ exists. This is to avoid creating exchanges with typos and misconfigurations.
224
+
225
+ ### The messageHandler callback
226
+
227
+ As declared in the example above, the `messageHandler` property expects a
228
+ callback of the type `IRabbitHandler`. Because of the nature of the library,
229
+ we will need to call the `.bind(this.yourService)` in order to bind the `this`
230
+ context of the origin service to the callback.
231
+
232
+ The `RabbitMQModule.register()` accepts an array of NestJS Modules with the
233
+ any module that contains an consumer callback function.
234
+
235
+ The `callback` has the following signature:
236
+
237
+ ```typescript
238
+ async messageHandler(content: any, params?: RabbitConsumerParams): Promise<void>;
239
+ ```
240
+
241
+ where `RabbitConsumerParams` is optional and contains the following info:
242
+
243
+ ```typescript
244
+ export type RabbitConsumerParameters = {
245
+ message: ConsumeMessage;
246
+ channel: ConfirmChannel;
247
+ queue: string;
248
+ };
249
+ ```
250
+
251
+ ### Strongly typed consumer
252
+
253
+ You can use the `IRabbitConsumer<T>` to type the consumer first parameter `content`.
254
+
255
+ ```typescript
256
+ export interface MyInterface {
257
+ type: string;
258
+ id: number;
259
+ }
260
+
261
+ @Injectable()
262
+ export class MyClass implements IRabbitConsumer<MyInterface> {
263
+ public async messageHandler(content: MyInterface): Promise<void> {
264
+ console.log(content.type);
265
+ }
266
+ }
267
+ ```
268
+
269
+ ### Consumer late loading
270
+
271
+ This library attaches the consumers during the `OnApplicationBootstrap` lifecycle
272
+ of the NestJS Application, meaning that the application will begin to receive
273
+ messages as soon as the lifecycle is done.
274
+
275
+ If your application needs some time to initiate the consumers for some reason,
276
+ (pods with limited resource for example), you can set the flag
277
+ `consumerManualLoad: true` on the configuration file and manually call the
278
+ consumer instantiation.
279
+
280
+ **Example:**
281
+
282
+ ```typescript
283
+ async function bootstrap() {
284
+ const app = await NestFactory.create(AppModule);
285
+ await app.listen(3000);
286
+
287
+ const rabbit: RabbitMQService = app.get(RabbitMQService);
288
+ await rabbit.createConsumers();
289
+ }
290
+ bootstrap();
291
+ ```
292
+
293
+ ### Declaration example
294
+
295
+ **Service example:**
296
+
297
+ ```typescript
298
+ //consumer.module.ts
299
+ @Module({
300
+ provides: [ConsumerService],
301
+ exports: [ConsumerService],
302
+ })
303
+ export class ConsumerModule {}
304
+
305
+ //consumer.service.ts
306
+ @Injectable()
307
+ export class ConsumerService {
308
+ async messageHandler(content: any) {
309
+ return null;
310
+ }
311
+ }
312
+ ```
313
+
314
+ **Config Example:**
315
+
316
+ ```typescript
317
+ //rabbit.config.ts
318
+ @Injectable()
319
+ export class RabbitOptions implements RabbitOptionsFactory {
320
+ constructor(
321
+ readonly consumerService: ConsumerService ,
322
+ ) {}
323
+
324
+ createRabbitOptions(): RabbitMQModuleOptions {
325
+ return {
326
+ ...
327
+ consumerchannels: [
328
+ {
329
+ options: {
330
+ queue: "myqueue",
331
+ exchangename: "test.exchange",
332
+ routingkey: "myqueue",
333
+ prefetch: number(process.env.rabbit_prefetch ?? 10),
334
+ },
335
+ messagehandler: this.MyService.messageHandler.bind(this.MyService),
336
+ },
337
+ ];
338
+ }
339
+ }
340
+
341
+ //app.module.ts
342
+ @Module({
343
+ imports: [
344
+ ...,
345
+ RabbitMQModule.register({
346
+ useClass: RabbitConfig,
347
+ injects: [ConsumerModule]
348
+ })
349
+ ]
350
+ })
351
+ export class AppModule {}
352
+ ```
353
+
354
+ ## Retrying strategy
355
+
356
+ On each consumer declaration you can pass the optional parameter: `retryStrategy`
357
+ with following the contract:
358
+
359
+ ```typescript
360
+ retryStrategy: {
361
+ enabled?: true,
362
+ maxAttempts?: 5,
363
+ delay?: (attempt) => {return attempt * 5000};
364
+ }
365
+ ```
366
+
367
+ By default, the `retryStrategy` is enabled. When consuming a new message and
368
+ the callback throws an error.
369
+
370
+ When enabled, the library will create a `{options.queue}.dlq` queue and will use
371
+ the `delayExchangeName` exchange as the retrying orchestrator where the
372
+ `x-delay` value is the return of the anonymous callback `delay`.
373
+
374
+ When the maximum attempts is reached, the library issues a nack, sending the
375
+ message to the `.dlq` queue.
376
+
377
+ ## Disabling the automatic ack
378
+
379
+ By default, the consumer will automatically send an ack at the end of the
380
+ callback execution. If you need to disable this behaviour, you can pass:
381
+
382
+ ```typescript
383
+ consumerChannels: [
384
+ options: {
385
+ ...,
386
+ autoAck: false
387
+ }
388
+ ]
389
+ ```
390
+
391
+ When disabled, it is necessary to manually acknowledge the message as follows:
392
+
393
+ ```typescript
394
+ public async messageHandler(content: any, params: RabbitConsumerParameters): Promise<void> {
395
+ params.channel.ack(params.message);
396
+ }
397
+ ```
398
+
399
+ ## Message inspection and logging
400
+
401
+ You can inspect the consumer/publisher messages by setting the parameter
402
+ `trafficInspection` or setting the environment variable `RABBITMQ_TRAFFIC_TYPE`
403
+ to either: `all | consumer | publisher | none`.
404
+
405
+ The default value is `none`
406
+
407
+ ## How to build this library locally ?
408
+
409
+ Just pull the project and run:
410
+
411
+ ```shell
412
+ pnpm install
413
+ pnpm build
414
+ ```
415
+
416
+ And should be good to go
417
+
418
+ # Planned features
419
+
420
+ TBD
421
+
422
+ # Contribute
423
+
424
+ TBD
425
+
426
+ # License
427
+
428
+ [MIT License](https://github.com/golevelup/nestjs/blob/master/LICENSE)
@@ -0,0 +1,20 @@
1
+ import { OnApplicationBootstrap, OnApplicationShutdown, OnModuleInit } from "@nestjs/common";
2
+ import { AmqpConnectionManager, ChannelWrapper } from "amqp-connection-manager";
3
+ import { RabbitMQModuleOptions } from "src/rabbitmq.types";
4
+ import { RabbitOptionsFactory } from "./rabbitmq.interfaces";
5
+ export declare class AMQPConnectionManager implements OnModuleInit, OnApplicationBootstrap, OnApplicationShutdown {
6
+ private readonly logger;
7
+ private rabbitTerminalErrors;
8
+ static rabbitModuleOptions: RabbitMQModuleOptions;
9
+ static publishChannelWrapper: ChannelWrapper;
10
+ static connection: AmqpConnectionManager;
11
+ static isConsumersLoaded: boolean;
12
+ constructor(options: RabbitOptionsFactory);
13
+ onModuleInit(): Promise<void>;
14
+ onApplicationBootstrap(): Promise<void>;
15
+ onApplicationShutdown(): Promise<void>;
16
+ private connect;
17
+ private attachEvents;
18
+ private getConnection;
19
+ private assertExchanges;
20
+ }
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var AMQPConnectionManager_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.AMQPConnectionManager = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const amqp_connection_manager_1 = require("amqp-connection-manager");
19
+ const node_os_1 = require("node:os");
20
+ const rabbitmq_consumers_1 = require("./rabbitmq-consumers");
21
+ let AMQPConnectionManager = AMQPConnectionManager_1 = class AMQPConnectionManager {
22
+ constructor(options) {
23
+ this.logger = new common_1.Logger(AMQPConnectionManager_1.name);
24
+ this.rabbitTerminalErrors = [
25
+ "channel-error",
26
+ "precondition-failed",
27
+ "not-allowed",
28
+ "access-refused",
29
+ "closed via management plugin",
30
+ ];
31
+ AMQPConnectionManager_1.rabbitModuleOptions = options.createRabbitOptions();
32
+ }
33
+ async onModuleInit() {
34
+ if (process.env.NODE_ENV != "test") {
35
+ return this.connect();
36
+ }
37
+ }
38
+ async onApplicationBootstrap() {
39
+ var _a;
40
+ if (((_a = AMQPConnectionManager_1.rabbitModuleOptions) === null || _a === void 0 ? void 0 : _a.consumerManualLoad) == true)
41
+ return;
42
+ const consumerInstance = new rabbitmq_consumers_1.RabbitMQConsumer(this.getConnection(), AMQPConnectionManager_1.rabbitModuleOptions, AMQPConnectionManager_1.publishChannelWrapper);
43
+ await consumerInstance.createConsumers();
44
+ this.logger.debug("Initiating RabbitMQ consumers automatically");
45
+ }
46
+ async onApplicationShutdown() {
47
+ var _a;
48
+ this.logger.log("Closing RabbitMQ Connection");
49
+ await ((_a = AMQPConnectionManager_1 === null || AMQPConnectionManager_1 === void 0 ? void 0 : AMQPConnectionManager_1.connection) === null || _a === void 0 ? void 0 : _a.close());
50
+ }
51
+ async connect() {
52
+ await new Promise((resolve) => {
53
+ AMQPConnectionManager_1.connection = (0, amqp_connection_manager_1.connect)(AMQPConnectionManager_1.rabbitModuleOptions.connectionString, {
54
+ heartbeatIntervalInSeconds: 5,
55
+ reconnectTimeInSeconds: 5,
56
+ connectionOptions: {
57
+ keepAlive: true,
58
+ keepAliveDelay: 5000,
59
+ servername: (0, node_os_1.hostname)(),
60
+ clientProperties: {
61
+ connection_name: `${process.env.npm_package_name}-${(0, node_os_1.hostname)()}`,
62
+ },
63
+ },
64
+ });
65
+ this.attachEvents(resolve);
66
+ });
67
+ await this.assertExchanges();
68
+ }
69
+ attachEvents(resolve) {
70
+ var _a;
71
+ if (((_a = AMQPConnectionManager_1.rabbitModuleOptions) === null || _a === void 0 ? void 0 : _a.waitConnection) === false)
72
+ resolve(true);
73
+ this.getConnection().on("connect", async ({ url }) => {
74
+ this.logger.log(`Rabbit connected to ${url.replace(new RegExp(url.replace(/amqp:\/\/[^:]*:([^@]*)@.*?$/i, "$1"), "g"), "***")}`);
75
+ resolve(true);
76
+ });
77
+ this.getConnection().on("disconnect", ({ err }) => {
78
+ console.warn(`Disconnected from rabbitmq: ${err.message}`);
79
+ if (this.rabbitTerminalErrors.some((errorMessage) => err.message.toLowerCase().includes(errorMessage))) {
80
+ this.getConnection().close();
81
+ console.error("RabbitMQ Disconnected with a terminal error, impossible to reconnect");
82
+ }
83
+ });
84
+ this.getConnection().on("connectFailed", ({ err }) => {
85
+ console.error(`Failure to connect to RabbitMQ instance: ${err.message}`);
86
+ });
87
+ }
88
+ getConnection() {
89
+ return AMQPConnectionManager_1.connection;
90
+ }
91
+ async assertExchanges() {
92
+ this.logger.debug("Initiating RabbitMQ producers");
93
+ AMQPConnectionManager_1.publishChannelWrapper =
94
+ this.getConnection().createChannel({
95
+ name: `${process.env.npm_package_name}_publish`,
96
+ confirm: true,
97
+ publishTimeout: 60000,
98
+ });
99
+ await AMQPConnectionManager_1.publishChannelWrapper.addSetup(async (channel) => {
100
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
101
+ for (const publisher of (_b = (_a = AMQPConnectionManager_1.rabbitModuleOptions) === null || _a === void 0 ? void 0 : _a.assertExchanges) !== null && _b !== void 0 ? _b : []) {
102
+ const exchangeName = publisher.name.endsWith((_d = (_c = publisher.options) === null || _c === void 0 ? void 0 : _c.exchangeSufix) !== null && _d !== void 0 ? _d : ".exchange")
103
+ ? publisher.name
104
+ : `${publisher.name}${(_f = (_e = publisher.options) === null || _e === void 0 ? void 0 : _e.exchangeSufix) !== null && _f !== void 0 ? _f : ".exchange"}`;
105
+ const isDelayed = (_h = (_g = publisher.options) === null || _g === void 0 ? void 0 : _g.isDelayed) !== null && _h !== void 0 ? _h : false;
106
+ const type = isDelayed ? "x-delayed-message" : publisher.type;
107
+ const argument = isDelayed
108
+ ? { arguments: { "x-delayed-type": publisher.type } }
109
+ : null;
110
+ await channel.assertExchange(exchangeName, type, Object.assign({ durable: (_k = (_j = publisher === null || publisher === void 0 ? void 0 : publisher.options) === null || _j === void 0 ? void 0 : _j.durable) !== null && _k !== void 0 ? _k : true, autoDelete: (_m = (_l = publisher === null || publisher === void 0 ? void 0 : publisher.options) === null || _l === void 0 ? void 0 : _l.autoDelete) !== null && _m !== void 0 ? _m : false }, argument));
111
+ }
112
+ });
113
+ }
114
+ };
115
+ exports.AMQPConnectionManager = AMQPConnectionManager;
116
+ AMQPConnectionManager.publishChannelWrapper = null;
117
+ AMQPConnectionManager.isConsumersLoaded = false;
118
+ exports.AMQPConnectionManager = AMQPConnectionManager = AMQPConnectionManager_1 = __decorate([
119
+ (0, common_1.Injectable)(),
120
+ __param(0, (0, common_1.Inject)("RABBIT_OPTIONS")),
121
+ __metadata("design:paramtypes", [Object])
122
+ ], AMQPConnectionManager);
123
+ //# sourceMappingURL=amqp-connection-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"amqp-connection-manager.js","sourceRoot":"","sources":["../src/amqp-connection-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { RabbitMQModule } from "./rabbitmq.module";
2
+ export { RabbitMQService } from "./rabbitmq-service";
3
+ export { ConfirmChannel, ConsumeMessage } from "amqplib";
4
+ export { IRabbitConsumer, RabbitOptionsFactory, RabbitConsumerParameters, } from "./rabbitmq.interfaces";
5
+ export { RabbitMQExchangeTypes, RabbitMQModuleOptions, RabbitMQAssertExchange, RabbitMQConsumerOptions, RabbitConnectionOptions, RabbitMQConsumerChannel, PublishOptions, } from "./rabbitmq.types";
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RabbitMQService = exports.RabbitMQModule = void 0;
4
+ var rabbitmq_module_1 = require("./rabbitmq.module");
5
+ Object.defineProperty(exports, "RabbitMQModule", { enumerable: true, get: function () { return rabbitmq_module_1.RabbitMQModule; } });
6
+ var rabbitmq_service_1 = require("./rabbitmq-service");
7
+ Object.defineProperty(exports, "RabbitMQService", { enumerable: true, get: function () { return rabbitmq_service_1.RabbitMQService; } });
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,qDAAmD;AAA1C,iHAAA,cAAc,OAAA;AACvB,uDAAqD;AAA5C,mHAAA,eAAe,OAAA"}
@@ -0,0 +1,15 @@
1
+ import { AmqpConnectionManager, ChannelWrapper } from "amqp-connection-manager";
2
+ import { RabbitMQModuleOptions } from "./rabbitmq.types";
3
+ export declare class RabbitMQConsumer {
4
+ private readonly connection;
5
+ private readonly options;
6
+ private readonly delayExchange;
7
+ private readonly publishChannel;
8
+ private readonly logType;
9
+ constructor(connection: AmqpConnectionManager, options: RabbitMQModuleOptions, publishChannelWrapper: ChannelWrapper);
10
+ createConsumers(): Promise<void>;
11
+ private processConsumerMessage;
12
+ private attachRetryAndDLQ;
13
+ private processRetry;
14
+ private inspectConsumer;
15
+ }