@makebelieve21213-packages/rabbitmq-client 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.
Files changed (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +461 -0
  3. package/dist/__tests__/__mocks__/logger.d.ts +10 -0
  4. package/dist/__tests__/__mocks__/logger.d.ts.map +1 -0
  5. package/dist/__tests__/__mocks__/logger.js +11 -0
  6. package/dist/__tests__/__mocks__/logger.js.map +1 -0
  7. package/dist/__tests__/__mocks__/redis-client.d.ts +9 -0
  8. package/dist/__tests__/__mocks__/redis-client.d.ts.map +1 -0
  9. package/dist/__tests__/__mocks__/redis-client.js +10 -0
  10. package/dist/__tests__/__mocks__/redis-client.js.map +1 -0
  11. package/dist/__tests__/connect-rabbitmq-receiver.spec.d.ts +2 -0
  12. package/dist/__tests__/connect-rabbitmq-receiver.spec.d.ts.map +1 -0
  13. package/dist/__tests__/connect-rabbitmq-receiver.spec.js +206 -0
  14. package/dist/__tests__/connect-rabbitmq-receiver.spec.js.map +1 -0
  15. package/dist/__tests__/connect-rabbitmq-receivers.spec.d.ts +2 -0
  16. package/dist/__tests__/connect-rabbitmq-receivers.spec.d.ts.map +1 -0
  17. package/dist/__tests__/connect-rabbitmq-receivers.spec.js +139 -0
  18. package/dist/__tests__/connect-rabbitmq-receivers.spec.js.map +1 -0
  19. package/dist/__tests__/index.spec.d.ts +2 -0
  20. package/dist/__tests__/index.spec.d.ts.map +1 -0
  21. package/dist/__tests__/index.spec.js +206 -0
  22. package/dist/__tests__/index.spec.js.map +1 -0
  23. package/dist/__tests__/setup.d.ts +2 -0
  24. package/dist/__tests__/setup.d.ts.map +1 -0
  25. package/dist/__tests__/setup.js +15 -0
  26. package/dist/__tests__/setup.js.map +1 -0
  27. package/dist/__tests__/test-types.d.ts +52 -0
  28. package/dist/__tests__/test-types.d.ts.map +1 -0
  29. package/dist/__tests__/test-types.js +2 -0
  30. package/dist/__tests__/test-types.js.map +1 -0
  31. package/dist/config/__tests__/factories.spec.d.ts +2 -0
  32. package/dist/config/__tests__/factories.spec.d.ts.map +1 -0
  33. package/dist/config/__tests__/factories.spec.js +168 -0
  34. package/dist/config/__tests__/factories.spec.js.map +1 -0
  35. package/dist/config/factories.d.ts +23 -0
  36. package/dist/config/factories.d.ts.map +1 -0
  37. package/dist/config/factories.js +123 -0
  38. package/dist/config/factories.js.map +1 -0
  39. package/dist/connect-rabbitmq-receiver.d.ts +8 -0
  40. package/dist/connect-rabbitmq-receiver.d.ts.map +1 -0
  41. package/dist/connect-rabbitmq-receiver.js +49 -0
  42. package/dist/connect-rabbitmq-receiver.js.map +1 -0
  43. package/dist/connect-rabbitmq-receivers.d.ts +8 -0
  44. package/dist/connect-rabbitmq-receivers.d.ts.map +1 -0
  45. package/dist/connect-rabbitmq-receivers.js +18 -0
  46. package/dist/connect-rabbitmq-receivers.js.map +1 -0
  47. package/dist/index.d.ts +14 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +8 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/interceptors/__tests__/rabbitmq.interceptor.spec.d.ts +2 -0
  52. package/dist/interceptors/__tests__/rabbitmq.interceptor.spec.d.ts.map +1 -0
  53. package/dist/interceptors/__tests__/rabbitmq.interceptor.spec.js +647 -0
  54. package/dist/interceptors/__tests__/rabbitmq.interceptor.spec.js.map +1 -0
  55. package/dist/interceptors/rabbitmq.interceptor.d.ts +18 -0
  56. package/dist/interceptors/rabbitmq.interceptor.d.ts.map +1 -0
  57. package/dist/interceptors/rabbitmq.interceptor.js +107 -0
  58. package/dist/interceptors/rabbitmq.interceptor.js.map +1 -0
  59. package/dist/main/__tests__/rabbitmq.module.spec.d.ts +2 -0
  60. package/dist/main/__tests__/rabbitmq.module.spec.d.ts.map +1 -0
  61. package/dist/main/__tests__/rabbitmq.module.spec.js +266 -0
  62. package/dist/main/__tests__/rabbitmq.module.spec.js.map +1 -0
  63. package/dist/main/__tests__/rabbitmq.service.spec.d.ts +2 -0
  64. package/dist/main/__tests__/rabbitmq.service.spec.d.ts.map +1 -0
  65. package/dist/main/__tests__/rabbitmq.service.spec.js +349 -0
  66. package/dist/main/__tests__/rabbitmq.service.spec.js.map +1 -0
  67. package/dist/main/rabbitmq.module.d.ts +10 -0
  68. package/dist/main/rabbitmq.module.d.ts.map +1 -0
  69. package/dist/main/rabbitmq.module.js +51 -0
  70. package/dist/main/rabbitmq.module.js.map +1 -0
  71. package/dist/main/rabbitmq.service.d.ts +26 -0
  72. package/dist/main/rabbitmq.service.d.ts.map +1 -0
  73. package/dist/main/rabbitmq.service.js +100 -0
  74. package/dist/main/rabbitmq.service.js.map +1 -0
  75. package/dist/types/base.config.d.ts +15 -0
  76. package/dist/types/base.config.d.ts.map +1 -0
  77. package/dist/types/base.config.js +2 -0
  78. package/dist/types/base.config.js.map +1 -0
  79. package/dist/types/idempotent-message.d.ts +6 -0
  80. package/dist/types/idempotent-message.d.ts.map +1 -0
  81. package/dist/types/idempotent-message.js +2 -0
  82. package/dist/types/idempotent-message.js.map +1 -0
  83. package/dist/types/message-with-correlation-id.d.ts +10 -0
  84. package/dist/types/message-with-correlation-id.d.ts.map +1 -0
  85. package/dist/types/message-with-correlation-id.js +2 -0
  86. package/dist/types/message-with-correlation-id.js.map +1 -0
  87. package/dist/types/rabbitmq-config-dlx.d.ts +4 -0
  88. package/dist/types/rabbitmq-config-dlx.d.ts.map +1 -0
  89. package/dist/types/rabbitmq-config-dlx.js +2 -0
  90. package/dist/types/rabbitmq-config-dlx.js.map +1 -0
  91. package/dist/types/rabbitmq-config-receiver.d.ts +15 -0
  92. package/dist/types/rabbitmq-config-receiver.d.ts.map +1 -0
  93. package/dist/types/rabbitmq-config-receiver.js +2 -0
  94. package/dist/types/rabbitmq-config-receiver.js.map +1 -0
  95. package/dist/types/rabbitmq-config-retry.d.ts +13 -0
  96. package/dist/types/rabbitmq-config-retry.d.ts.map +1 -0
  97. package/dist/types/rabbitmq-config-retry.js +2 -0
  98. package/dist/types/rabbitmq-config-retry.js.map +1 -0
  99. package/dist/types/rabbitmq-config-sender.d.ts +14 -0
  100. package/dist/types/rabbitmq-config-sender.d.ts.map +1 -0
  101. package/dist/types/rabbitmq-config-sender.js +2 -0
  102. package/dist/types/rabbitmq-config-sender.js.map +1 -0
  103. package/dist/types/rabbitmq-module-options.d.ts +17 -0
  104. package/dist/types/rabbitmq-module-options.d.ts.map +1 -0
  105. package/dist/types/rabbitmq-module-options.js +2 -0
  106. package/dist/types/rabbitmq-module-options.js.map +1 -0
  107. package/dist/types/rabbitmq-receiver-options.d.ts +18 -0
  108. package/dist/types/rabbitmq-receiver-options.d.ts.map +1 -0
  109. package/dist/types/rabbitmq-receiver-options.js +2 -0
  110. package/dist/types/rabbitmq-receiver-options.js.map +1 -0
  111. package/dist/types/rabbitmq-receiver-subscription.d.ts +19 -0
  112. package/dist/types/rabbitmq-receiver-subscription.d.ts.map +1 -0
  113. package/dist/types/rabbitmq-receiver-subscription.js +2 -0
  114. package/dist/types/rabbitmq-receiver-subscription.js.map +1 -0
  115. package/dist/types/rabbitmq-receivers-config.d.ts +14 -0
  116. package/dist/types/rabbitmq-receivers-config.d.ts.map +1 -0
  117. package/dist/types/rabbitmq-receivers-config.js +2 -0
  118. package/dist/types/rabbitmq-receivers-config.js.map +1 -0
  119. package/dist/types/rabbitmq-sender-options.d.ts +10 -0
  120. package/dist/types/rabbitmq-sender-options.d.ts.map +1 -0
  121. package/dist/types/rabbitmq-sender-options.js +2 -0
  122. package/dist/types/rabbitmq-sender-options.js.map +1 -0
  123. package/dist/types/routing-keys.d.ts +24 -0
  124. package/dist/types/routing-keys.d.ts.map +1 -0
  125. package/dist/types/routing-keys.js +29 -0
  126. package/dist/types/routing-keys.js.map +1 -0
  127. package/dist/utils/__tests__/injections.spec.d.ts +2 -0
  128. package/dist/utils/__tests__/injections.spec.d.ts.map +1 -0
  129. package/dist/utils/__tests__/injections.spec.js +174 -0
  130. package/dist/utils/__tests__/injections.spec.js.map +1 -0
  131. package/dist/utils/injections.d.ts +2 -0
  132. package/dist/utils/injections.d.ts.map +1 -0
  133. package/dist/utils/injections.js +2 -0
  134. package/dist/utils/injections.js.map +1 -0
  135. package/package.json +91 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Skriabin Aleksei
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,461 @@
1
+ # @makebelieve21213-packages/rabbitmq-client
2
+
3
+ RabbitMQ клиент для NestJS с поддержкой TypeScript и полной типобезопасностью. Обеспечивает надежную отправку и получение сообщений между микросервисами с поддержкой retry-механизмов, Dead Letter Queue (DLQ) и идемпотентности сообщений.
4
+
5
+ ## 📋 Содержание
6
+
7
+ - [Возможности](#-возможности)
8
+ - [Требования](#-требования)
9
+ - [Установка](#-установка)
10
+ - [Структура пакета](#-структура-пакета)
11
+ - [Быстрый старт](#-быстрый-старт)
12
+ - [API Reference](#-api-reference)
13
+ - [Примеры использования](#-примеры-использования)
14
+ - [Troubleshooting](#-troubleshooting)
15
+ - [Тестирование](#-тестирование)
16
+
17
+ ## 🚀 Возможности
18
+
19
+ - ✅ **NestJS интеграция** - глобальный модуль с forRootAsync для простой интеграции
20
+ - ✅ **Type-safe API** - полная типобезопасность TypeScript с экспортируемыми типами
21
+ - ✅ **Отправка и получение сообщений** - поддержка fire-and-forget и request-response паттернов
22
+ - ✅ **Идемпотентность** - автоматическая проверка дубликатов сообщений через Redis
23
+ - ✅ **Retry механизм** - автоматические повторные попытки с настраиваемым TTL
24
+ - ✅ **Dead Letter Queue** - обработка критических ошибок через DLX
25
+ - ✅ **Множественные подписки** - поддержка подключения нескольких очередей одновременно
26
+ - ✅ **Обработка ошибок** - интеграция с UnifiedExceptionFilter для корректной обработки ошибок
27
+ - ✅ **100% покрытие тестами** - надежность и качество кода
28
+
29
+ ## 📋 Требования
30
+
31
+ - **Node.js**: >= 22.13.0
32
+ - **NestJS**: >= 11.0.0
33
+ - **RabbitMQ**: сервер RabbitMQ
34
+ - **Redis**: сервер Redis (обязательно для полноценного использования идемпотентности)
35
+
36
+ ## 📦 Установка
37
+
38
+ ```bash
39
+ npm install @makebelieve21213-packages/rabbitmq-client
40
+ ```
41
+
42
+ ### Зависимости
43
+
44
+ ```json
45
+ {
46
+ "@nestjs/common": "^11.0.0",
47
+ "@nestjs/config": "^4.0.0",
48
+ "@nestjs/microservices": "^11.0.0",
49
+ "@makebelieve21213-packages/logger": "^1.0.0",
50
+ "@makebelieve21213-packages/nest-common": "^1.0.0",
51
+ "@makebelieve21213-packages/redis-client": "^1.0.0",
52
+ "rxjs": "^7.8.0",
53
+ "uuid": "^11.0.0"
54
+ }
55
+ ```
56
+
57
+ ## 📁 Структура пакета
58
+
59
+ ```
60
+ src/
61
+ ├── main/ # NestJS модуль и сервисы
62
+ ├── config/ # Фабрики конфигураций
63
+ ├── types/ # TypeScript типы
64
+ ├── utils/ # Утилиты
65
+ ├── connect-rabbitmq-receiver.ts # Функция подключения одной подписки
66
+ ├── connect-rabbitmq-receivers.ts # Функция подключения множественных подписок
67
+ └── index.ts # Экспорты
68
+ ```
69
+
70
+ ## 🏗️ Архитектура
71
+
72
+ Пакет предоставляет NestJS глобальный модуль `RabbitMQModule` для отправки сообщений и функции `connectRabbitMQReceiver` / `connectRabbitMQReceivers` для получения сообщений через RabbitMQ.
73
+
74
+ **Основные компоненты:**
75
+ - `RabbitMQModule` - NestJS глобальный модуль для отправки
76
+ - `RabbitMQService` - сервис для отправки сообщений
77
+ - `connectRabbitMQReceiver` - функция подключения одной подписки
78
+ - `connectRabbitMQReceivers` - функция подключения множественных подписок
79
+ - `RabbitMQIdempotencyInterceptor` - интерцептор для проверки идемпотентности
80
+ - Типы: `RabbitMQSenderOptions`, `RabbitMQReceiverOptions`, `IdempotentMessage`
81
+
82
+ ## 🔧 Быстрый старт
83
+
84
+ ### Шаг 1: Настройка переменных окружения
85
+
86
+ ```env
87
+ RABBITMQ_URL=amqp://localhost:5672
88
+ RABBITMQ_EXCHANGE=events_exchange
89
+ RABBITMQ_EXCHANGE_TYPE=topic
90
+ RABBITMQ_QUEUE=your-service-queue
91
+ RABBITMQ_PATTERN=your.pattern.*
92
+ ```
93
+
94
+ ### Шаг 2: Подключение Redis (обязательно для идемпотентности)
95
+
96
+ ```typescript
97
+ import { Module } from "@nestjs/common";
98
+ import { RedisModule } from "@makebelieve21213-packages/redis-client";
99
+
100
+ @Module({
101
+ imports: [
102
+ RedisModule.forRootAsync({
103
+ // конфигурация Redis
104
+ }),
105
+ ],
106
+ })
107
+ export class AppModule {}
108
+ ```
109
+
110
+ **Важно:** Без подключенного `RedisService` в DI контейнере приложения интерцептор `RabbitMQIdempotencyInterceptor` не сможет проверять дубликаты сообщений и будет пропускать проверку идемпотентности (graceful degradation).
111
+
112
+ ### Шаг 3: Создание конфигурации
113
+
114
+ Создайте файл `rabbitmq.config.ts` в вашем сервисе:
115
+
116
+ ```typescript
117
+ import { registerAs } from "@nestjs/config";
118
+ import type { RabbitMQSenderOptions, RabbitMQReceiverOptions } from "@makebelieve21213-packages/rabbitmq-client";
119
+ import { EnvVariable } from "src/types/enums";
120
+
121
+ export type RabbitMQConfiguration = {
122
+ sender: RabbitMQSenderOptions;
123
+ receiver: RabbitMQReceiverOptions;
124
+ };
125
+
126
+ const rabbitmqConfig = registerAs<RabbitMQConfiguration>(
127
+ "rabbitmq",
128
+ (): RabbitMQConfiguration => ({
129
+ sender: {
130
+ url: process.env[EnvVariable.RABBITMQ_URL]!,
131
+ exchange: process.env[EnvVariable.RABBITMQ_EXCHANGE] || "events_exchange",
132
+ exchangeType: process.env[EnvVariable.RABBITMQ_EXCHANGE_TYPE] || "topic",
133
+ },
134
+ receiver: {
135
+ url: process.env[EnvVariable.RABBITMQ_URL]!,
136
+ exchange: process.env[EnvVariable.RABBITMQ_EXCHANGE] || "events_exchange",
137
+ exchangeType: process.env[EnvVariable.RABBITMQ_EXCHANGE_TYPE] || "topic",
138
+ queue: process.env[EnvVariable.RABBITMQ_QUEUE]!,
139
+ pattern: process.env[EnvVariable.RABBITMQ_PATTERN]!,
140
+ },
141
+ }),
142
+ );
143
+
144
+ export default rabbitmqConfig;
145
+ ```
146
+
147
+ ### Шаг 4: Регистрация модуля
148
+
149
+ ```typescript
150
+ // app.module.ts
151
+ import { Module } from '@nestjs/common';
152
+ import { ConfigModule } from '@nestjs/config';
153
+ import { RabbitMQModule } from '@makebelieve21213-packages/rabbitmq-client';
154
+ import rabbitmqConfig from 'src/configs/rabbitmq.config';
155
+ import type { RabbitMQConfiguration } from 'src/configs/rabbitmq.config';
156
+
157
+ @Module({
158
+ imports: [
159
+ ConfigModule.forRoot({
160
+ isGlobal: true,
161
+ load: [rabbitmqConfig],
162
+ }),
163
+ RabbitMQModule.forRootAsync<[RabbitMQConfiguration]>({
164
+ useFactory: (config: RabbitMQConfiguration) => config.sender,
165
+ inject: [rabbitmqConfig.KEY],
166
+ imports: [ConfigModule],
167
+ }),
168
+ ],
169
+ })
170
+ export class AppModule {}
171
+ ```
172
+
173
+ ### Шаг 5: Подключение receiver в main.ts
174
+
175
+ ```typescript
176
+ // main.ts
177
+ import { ConfigService } from "@nestjs/config";
178
+ import { NestFactory } from "@nestjs/core";
179
+ import { connectLogger } from "@makebelieve21213-packages/logger";
180
+ import { UnifiedExceptionFilter, UnifiedInterceptor } from "@makebelieve21213-packages/nest-common";
181
+ import { connectRabbitMQReceiver, type RabbitMQReceiverOptions } from "@makebelieve21213-packages/rabbitmq-client";
182
+ import { AppModule } from "./app.module";
183
+
184
+ async function bootstrap() {
185
+ const app = await NestFactory.create(AppModule);
186
+
187
+ const config = app.get(ConfigService);
188
+ const receiverOptions = config.get<RabbitMQReceiverOptions>("rabbitmq.receiver")!;
189
+
190
+ // Перезаписываем стандартный логгер сервиса
191
+ const logger = await connectLogger(app, "YourService");
192
+
193
+ // Получаем dlxExchange из конфигурации RabbitMQ для RPC обработки ошибок
194
+ const dlxExchange = receiverOptions.dlxExchange || "events_exchange.dlx";
195
+
196
+ // Подключаем глобально единый фильтр для HTTP и RPC запросов (обработка ошибок)
197
+ app.useGlobalFilters(new UnifiedExceptionFilter(logger, dlxExchange));
198
+
199
+ // Подключаем глобально единый перехватчик для HTTP и RPC запросов (логирование и метрики всех запросов)
200
+ app.useGlobalInterceptors(new UnifiedInterceptor(logger));
201
+
202
+ // Подключаем RabbitMQ микросервис для получения сообщений
203
+ await connectRabbitMQReceiver(app, receiverOptions);
204
+
205
+ await app.startAllMicroservices();
206
+ await app.listen(3000);
207
+ }
208
+
209
+ bootstrap();
210
+ ```
211
+
212
+ ### Шаг 6: Использование сервиса
213
+
214
+ ```typescript
215
+ // your.service.ts
216
+ import { Injectable } from '@nestjs/common';
217
+ import { RabbitMQService } from '@makebelieve21213-packages/rabbitmq-client';
218
+ import { ROUTING_KEYS } from '@makebelieve21213-packages/rabbitmq-client';
219
+
220
+ @Injectable()
221
+ export class YourService {
222
+ constructor(private readonly rabbitMQ: RabbitMQService) {}
223
+
224
+ async sendFireAndForget() {
225
+ await this.rabbitMQ.fireAndForget(ROUTING_KEYS.ANALYTICS_UPDATE_GLOBAL, {
226
+ data: "example"
227
+ });
228
+ }
229
+
230
+ async sendRequestResponse() {
231
+ const result = await this.rabbitMQ.publish<RequestData, ResponseData>(
232
+ ROUTING_KEYS.ANALYTICS_GLOBAL,
233
+ { query: "analytics" }
234
+ );
235
+ return result;
236
+ }
237
+ }
238
+ ```
239
+
240
+ ## 📚 API Reference
241
+
242
+ ### RabbitMQModule
243
+
244
+ **forRootAsync(options):**
245
+
246
+ ```typescript
247
+ RabbitMQModule.forRootAsync<[RabbitMQConfiguration]>({
248
+ useFactory: (config: RabbitMQConfiguration) => config.sender,
249
+ inject: [rabbitmqConfig.KEY],
250
+ imports: [ConfigModule],
251
+ })
252
+ ```
253
+
254
+ **Экспортирует:** `RabbitMQService` (глобально)
255
+
256
+ ### RabbitMQService
257
+
258
+ **Методы:**
259
+
260
+ #### `fireAndForget<I>(key: ROUTING_KEYS, data: I)`
261
+
262
+ Отправляет сообщение без ожидания ответа (fire-and-forget паттерн). Не добавляет `correlationId`.
263
+
264
+ ```typescript
265
+ fireAndForget<I>(key: ROUTING_KEYS, data: I): void
266
+ ```
267
+
268
+ #### `publish<I, O>(key: ROUTING_KEYS, data: I): Promise<O>`
269
+
270
+ Отправляет сообщение и ожидает ответ (RPC паттерн). Автоматически добавляет `correlationId` и `correlationTimestamp` для идемпотентности.
271
+
272
+ ```typescript
273
+ publish<I, O>(key: ROUTING_KEYS, data: I): Promise<O>
274
+ ```
275
+
276
+ ### connectRabbitMQReceiver
277
+
278
+ Асинхронная функция для подключения одной подписки RabbitMQ.
279
+
280
+ ```typescript
281
+ connectRabbitMQReceiver(
282
+ app: INestApplication,
283
+ receiverOptions: RabbitMQReceiverOptions,
284
+ skipGlobalSetup?: boolean
285
+ ): Promise<void>
286
+ ```
287
+
288
+ **Параметры:**
289
+ - `app` - экземпляр NestJS приложения
290
+ - `receiverOptions` - опции для настройки receiver
291
+ - `skipGlobalSetup` (опционально) - пропустить установку глобальных компонентов
292
+
293
+ ### connectRabbitMQReceivers
294
+
295
+ Асинхронная функция для подключения множественных подписок RabbitMQ.
296
+
297
+ ```typescript
298
+ connectRabbitMQReceivers(
299
+ app: INestApplication,
300
+ receiverOptionsList: RabbitMQReceiverOptions[]
301
+ ): Promise<void>
302
+ ```
303
+
304
+ **Параметры:**
305
+ - `app` - экземпляр NestJS приложения
306
+ - `receiverOptionsList` - массив опций для настройки receivers
307
+
308
+ ### RabbitMQIdempotencyInterceptor
309
+
310
+ Глобальный интерцептор для проверки идемпотентности сообщений. Устанавливается автоматически в `connectRabbitMQReceiver` (если `skipGlobalSetup = false`).
311
+
312
+ **⚠️ Важно:** Требует наличия `RedisService` из пакета `@makebelieve21213-packages/redis-client` в DI контейнере приложения.
313
+
314
+ ## 🧪 Примеры использования
315
+
316
+ ### Отправка fire-and-forget сообщения
317
+
318
+ ```typescript
319
+ await this.rabbitMQ.fireAndForget(ROUTING_KEYS.ANALYTICS_UPDATE_GLOBAL, {
320
+ data: "example"
321
+ });
322
+ ```
323
+
324
+ ### Отправка request-response сообщения
325
+
326
+ ```typescript
327
+ const result = await this.rabbitMQ.publish<RequestData, ResponseData>(
328
+ ROUTING_KEYS.ANALYTICS_GLOBAL,
329
+ { query: "analytics" }
330
+ );
331
+ console.log(result);
332
+ ```
333
+
334
+ ### Создание обработчика сообщений
335
+
336
+ ```typescript
337
+ import { Controller } from "@nestjs/common";
338
+ import { MessagePattern, RmqContext, Ctx } from "@nestjs/microservices";
339
+ import { ROUTING_KEYS } from "@makebelieve21213-packages/types";
340
+ import { RpcError, RpcErrorType } from "@makebelieve21213-packages/nest-common";
341
+
342
+ @Controller()
343
+ export class MessageController {
344
+ @MessagePattern(ROUTING_KEYS.TOKENS_FETCH_ALL)
345
+ async handleTokenFetch(data: unknown, @Ctx() context: RmqContext) {
346
+ try {
347
+ // Ваша логика обработки
348
+ return { success: true };
349
+ } catch (error) {
350
+ throw new RpcError(
351
+ "Failed to fetch tokens",
352
+ RpcErrorType.INTERNAL_ERROR,
353
+ );
354
+ }
355
+ }
356
+ }
357
+ ```
358
+
359
+ ### Подключение множественных подписок
360
+
361
+ ```typescript
362
+ import { connectRabbitMQReceivers } from "@makebelieve21213-packages/rabbitmq-client";
363
+
364
+ async function bootstrap() {
365
+ const app = await NestFactory.create(AppModule);
366
+
367
+ const config = app.get(ConfigService);
368
+ const receiverOptionsList = config.get<RabbitMQReceiverOptions[]>("rabbitmq.receivers")!;
369
+
370
+ const logger = await connectLogger(app, "YourService");
371
+ const dlxExchange = receiverOptionsList[0]?.dlxExchange || "events_exchange.dlx";
372
+
373
+ app.useGlobalFilters(new UnifiedExceptionFilter(logger, dlxExchange));
374
+ app.useGlobalInterceptors(new UnifiedInterceptor(logger));
375
+
376
+ await connectRabbitMQReceivers(app, receiverOptionsList);
377
+
378
+ await app.startAllMicroservices();
379
+ await app.listen(3000);
380
+ }
381
+ ```
382
+
383
+ ## 🚨 Troubleshooting
384
+
385
+ ### Идемпотентность не работает
386
+
387
+ **Решение:** Убедитесь, что `RedisModule` подключен в корневом модуле приложения. Без Redis интерцептор будет пропускать проверку идемпотентности (graceful degradation).
388
+
389
+ ### Сообщения не доставляются
390
+
391
+ **Решение:** Проверьте конфигурацию RabbitMQ (URL, exchange, queue, pattern), убедитесь, что сервер RabbitMQ запущен и доступен.
392
+
393
+ ### Ошибки не обрабатываются корректно
394
+
395
+ **Решение:** Убедитесь, что `UnifiedExceptionFilter` и `UnifiedInterceptor` установлены в `main.ts` перед вызовом `connectRabbitMQReceiver` или `connectRabbitMQReceivers`.
396
+
397
+ ### Сообщения застревают в очереди
398
+
399
+ **Решение:** Проверьте обработчики сообщений - они должны корректно обрабатывать сообщения и возвращать результат или выбрасывать `RpcError` для ошибок.
400
+
401
+ ## 🧪 Тестирование
402
+
403
+ Пакет имеет **высокое покрытие тестами** (>95% для веток, 100% для statements и функций).
404
+
405
+ ```bash
406
+ pnpm test # Все тесты
407
+ pnpm test:coverage # С покрытием
408
+ ```
409
+
410
+ ## 🔧 Конфигурация
411
+
412
+ ```typescript
413
+ interface RabbitMQSenderOptions {
414
+ url: string; // URL подключения к RabbitMQ
415
+ exchange: string; // Имя основного exchange
416
+ exchangeType: string; // Тип exchange (обычно "topic")
417
+ replyQueueOptions?: { // Опции для reply очередей RPC паттерна
418
+ durable?: boolean; // По умолчанию: false
419
+ autoDelete?: boolean; // По умолчанию: true
420
+ };
421
+ }
422
+
423
+ interface RabbitMQReceiverOptions {
424
+ url: string; // URL подключения к RabbitMQ
425
+ exchange: string; // Имя основного exchange
426
+ exchangeType: string; // Тип exchange
427
+ queue: string; // Имя основной очереди
428
+ pattern: string; // Паттерн routing key
429
+ prefetchCount?: number; // По умолчанию: 10
430
+ noAck?: boolean; // По умолчанию: false
431
+ replyQueue?: string; // По умолчанию: ${queue}.reply
432
+ retryQueue?: string; // По умолчанию: ${queue}.retry
433
+ retryExchange?: string; // По умолчанию: ${exchange}.retry
434
+ retryExchangeType?: string; // По умолчанию: exchangeType
435
+ retryTtl?: number; // По умолчанию: 5000
436
+ dlxQueue?: string; // По умолчанию: global.dlx
437
+ dlxExchange?: string; // По умолчанию: events_exchange.dlx
438
+ dlxExchangeType?: string; // По умолчанию: exchangeType
439
+ }
440
+ ```
441
+
442
+ **Примечание:** Конфигурация должна создаваться в сервисе, который использует пакет.
443
+
444
+ ## 📦 Зависимости
445
+
446
+ - `@nestjs/common` - NestJS core
447
+ - `@nestjs/config` - NestJS config
448
+ - `@nestjs/microservices` - NestJS microservices
449
+ - `@makebelieve21213-packages/logger` - Логирование
450
+ - `@makebelieve21213-packages/nest-common` - Общие компоненты NestJS (RpcError, UnifiedExceptionFilter, UnifiedInterceptor)
451
+ - `@makebelieve21213-packages/redis-client` - Redis клиент для идемпотентности
452
+ - `rxjs` - Реактивные расширения
453
+ - `uuid` - Генерация уникальных ID
454
+
455
+ ## 📄 Лицензия
456
+
457
+ MIT
458
+
459
+ ## 👥 Автор
460
+
461
+ Skriabin Aleksei
@@ -0,0 +1,10 @@
1
+ export declare class LoggerService {
2
+ log: jest.Mock<any, any, any>;
3
+ error: jest.Mock<any, any, any>;
4
+ warn: jest.Mock<any, any, any>;
5
+ debug: jest.Mock<any, any, any>;
6
+ info: jest.Mock<any, any, any>;
7
+ setContext: jest.Mock<any, any, any>;
8
+ }
9
+ export default LoggerService;
10
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/__tests__/__mocks__/logger.ts"],"names":[],"mappings":"AACA,qBAAa,aAAa;IACzB,GAAG,2BAAa;IAChB,KAAK,2BAAa;IAClB,IAAI,2BAAa;IACjB,KAAK,2BAAa;IAClB,IAAI,2BAAa;IACjB,UAAU,2BAAa;CACvB;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,11 @@
1
+ // Мок для @makebelieve21213-packages/logger
2
+ export class LoggerService {
3
+ log = jest.fn();
4
+ error = jest.fn();
5
+ warn = jest.fn();
6
+ debug = jest.fn();
7
+ info = jest.fn();
8
+ setContext = jest.fn();
9
+ }
10
+ export default LoggerService;
11
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/__tests__/__mocks__/logger.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,MAAM,OAAO,aAAa;IACzB,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IAChB,KAAK,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IAClB,IAAI,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IACjB,KAAK,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IAClB,IAAI,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IACjB,UAAU,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;CACvB;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare class RedisClientService {
2
+ get: jest.Mock<any, any, any>;
3
+ set: jest.Mock<any, any, any>;
4
+ del: jest.Mock<any, any, any>;
5
+ exists: jest.Mock<any, any, any>;
6
+ hexists: jest.Mock<any, any, any>;
7
+ }
8
+ export default RedisClientService;
9
+ //# sourceMappingURL=redis-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-client.d.ts","sourceRoot":"","sources":["../../../src/__tests__/__mocks__/redis-client.ts"],"names":[],"mappings":"AACA,qBAAa,kBAAkB;IAC9B,GAAG,2BAAa;IAChB,GAAG,2BAAa;IAChB,GAAG,2BAAa;IAChB,MAAM,2BAAa;IACnB,OAAO,2BAAa;CACpB;AAED,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,10 @@
1
+ // Мок для @makebelieve21213-packages/redis-client
2
+ export class RedisClientService {
3
+ get = jest.fn();
4
+ set = jest.fn();
5
+ del = jest.fn();
6
+ exists = jest.fn();
7
+ hexists = jest.fn();
8
+ }
9
+ export default RedisClientService;
10
+ //# sourceMappingURL=redis-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-client.js","sourceRoot":"","sources":["../../../src/__tests__/__mocks__/redis-client.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,MAAM,OAAO,kBAAkB;IAC9B,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IAChB,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IAChB,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IAChB,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IACnB,OAAO,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;CACpB;AAED,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=connect-rabbitmq-receiver.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect-rabbitmq-receiver.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/connect-rabbitmq-receiver.spec.ts"],"names":[],"mappings":""}