@open-rlb/nestjs-amqp 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 (136) hide show
  1. package/README.md +300 -0
  2. package/amqp-lib/amqp/connection.d.ts +51 -0
  3. package/amqp-lib/amqp/connection.js +503 -0
  4. package/amqp-lib/amqp/connection.js.map +1 -0
  5. package/amqp-lib/amqp/errorBehaviors.d.ts +9 -0
  6. package/amqp-lib/amqp/errorBehaviors.js +47 -0
  7. package/amqp-lib/amqp/errorBehaviors.js.map +1 -0
  8. package/amqp-lib/amqp/utils.d.ts +7 -0
  9. package/amqp-lib/amqp/utils.js +110 -0
  10. package/amqp-lib/amqp/utils.js.map +1 -0
  11. package/amqp-lib/config/rabbitmq-exchange.config.d.ts +13 -0
  12. package/amqp-lib/config/rabbitmq-exchange.config.js +3 -0
  13. package/amqp-lib/config/rabbitmq-exchange.config.js.map +1 -0
  14. package/amqp-lib/config/rabbitmq-queue.config.d.ts +25 -0
  15. package/amqp-lib/config/rabbitmq-queue.config.js +3 -0
  16. package/amqp-lib/config/rabbitmq-queue.config.js.map +1 -0
  17. package/amqp-lib/config/rabbitmq.config.d.ts +49 -0
  18. package/amqp-lib/config/rabbitmq.config.js +3 -0
  19. package/amqp-lib/config/rabbitmq.config.js.map +1 -0
  20. package/amqp-lib/index.d.ts +4 -0
  21. package/amqp-lib/index.js +21 -0
  22. package/amqp-lib/index.js.map +1 -0
  23. package/amqp-lib/models/correlation-message.model.d.ts +5 -0
  24. package/amqp-lib/models/correlation-message.model.js +3 -0
  25. package/amqp-lib/models/correlation-message.model.js.map +1 -0
  26. package/amqp-lib/models/errors.model.d.ts +15 -0
  27. package/amqp-lib/models/errors.model.js +35 -0
  28. package/amqp-lib/models/errors.model.js.map +1 -0
  29. package/amqp-lib/models/nack.model.d.ts +5 -0
  30. package/amqp-lib/models/nack.model.js +13 -0
  31. package/amqp-lib/models/nack.model.js.map +1 -0
  32. package/amqp-lib/models/rabbitmq-handler.model.d.ts +38 -0
  33. package/amqp-lib/models/rabbitmq-handler.model.js +3 -0
  34. package/amqp-lib/models/rabbitmq-handler.model.js.map +1 -0
  35. package/amqp-lib/models/subscription-result.model.d.ts +4 -0
  36. package/amqp-lib/models/subscription-result.model.js +3 -0
  37. package/amqp-lib/models/subscription-result.model.js.map +1 -0
  38. package/amqp-lib/types.d.ts +45 -0
  39. package/amqp-lib/types.js +11 -0
  40. package/amqp-lib/types.js.map +1 -0
  41. package/amqp.module.d.ts +2 -0
  42. package/amqp.module.js +29 -0
  43. package/amqp.module.js.map +1 -0
  44. package/index.d.ts +4 -0
  45. package/index.js +21 -0
  46. package/index.js.map +1 -0
  47. package/modules/broker/broker.module.d.ts +27 -0
  48. package/modules/broker/broker.module.js +132 -0
  49. package/modules/broker/broker.module.js.map +1 -0
  50. package/modules/broker/config/broker.config.d.ts +3 -0
  51. package/modules/broker/config/broker.config.js +3 -0
  52. package/modules/broker/config/broker.config.js.map +1 -0
  53. package/modules/broker/config/handler-auth.config.d.ts +22 -0
  54. package/modules/broker/config/handler-auth.config.js +3 -0
  55. package/modules/broker/config/handler-auth.config.js.map +1 -0
  56. package/modules/broker/config/topics.config.d.ts +8 -0
  57. package/modules/broker/config/topics.config.js +3 -0
  58. package/modules/broker/config/topics.config.js.map +1 -0
  59. package/modules/broker/const.d.ts +9 -0
  60. package/modules/broker/const.js +13 -0
  61. package/modules/broker/const.js.map +1 -0
  62. package/modules/broker/data/events/messages.d.ts +29 -0
  63. package/modules/broker/data/events/messages.js +3 -0
  64. package/modules/broker/data/events/messages.js.map +1 -0
  65. package/modules/broker/decorators/broker-action.decorator.d.ts +8 -0
  66. package/modules/broker/decorators/broker-action.decorator.js +66 -0
  67. package/modules/broker/decorators/broker-action.decorator.js.map +1 -0
  68. package/modules/broker/decorators/index.d.ts +1 -0
  69. package/modules/broker/decorators/index.js +18 -0
  70. package/modules/broker/decorators/index.js.map +1 -0
  71. package/modules/broker/index.d.ts +9 -0
  72. package/modules/broker/index.js +26 -0
  73. package/modules/broker/index.js.map +1 -0
  74. package/modules/broker/pipes/boolean.pipe.d.ts +4 -0
  75. package/modules/broker/pipes/boolean.pipe.js +23 -0
  76. package/modules/broker/pipes/boolean.pipe.js.map +1 -0
  77. package/modules/broker/pipes/index.d.ts +2 -0
  78. package/modules/broker/pipes/index.js +19 -0
  79. package/modules/broker/pipes/index.js.map +1 -0
  80. package/modules/broker/pipes/number.pipe.d.ts +4 -0
  81. package/modules/broker/pipes/number.pipe.js +10 -0
  82. package/modules/broker/pipes/number.pipe.js.map +1 -0
  83. package/modules/broker/services/auto-discovery.service.d.ts +6 -0
  84. package/modules/broker/services/auto-discovery.service.js +28 -0
  85. package/modules/broker/services/auto-discovery.service.js.map +1 -0
  86. package/modules/broker/services/broker.service.d.ts +31 -0
  87. package/modules/broker/services/broker.service.js +323 -0
  88. package/modules/broker/services/broker.service.js.map +1 -0
  89. package/modules/broker/services/handler-registry.service.d.ts +12 -0
  90. package/modules/broker/services/handler-registry.service.js +58 -0
  91. package/modules/broker/services/handler-registry.service.js.map +1 -0
  92. package/modules/broker/services/metadata-scanner.service.d.ts +23 -0
  93. package/modules/broker/services/metadata-scanner.service.js +238 -0
  94. package/modules/broker/services/metadata-scanner.service.js.map +1 -0
  95. package/modules/broker/services/reflect.service.d.ts +22 -0
  96. package/modules/broker/services/reflect.service.js +195 -0
  97. package/modules/broker/services/reflect.service.js.map +1 -0
  98. package/modules/broker/services/utils.service.d.ts +8 -0
  99. package/modules/broker/services/utils.service.js +28 -0
  100. package/modules/broker/services/utils.service.js.map +1 -0
  101. package/modules/proxy/config/path-definition.config.d.ts +51 -0
  102. package/modules/proxy/config/path-definition.config.js +3 -0
  103. package/modules/proxy/config/path-definition.config.js.map +1 -0
  104. package/modules/proxy/index.d.ts +7 -0
  105. package/modules/proxy/index.js +20 -0
  106. package/modules/proxy/index.js.map +1 -0
  107. package/modules/proxy/proxy.module.d.ts +4 -0
  108. package/modules/proxy/proxy.module.js +38 -0
  109. package/modules/proxy/proxy.module.js.map +1 -0
  110. package/modules/proxy/services/acl.service.d.ts +4 -0
  111. package/modules/proxy/services/acl.service.js +5 -0
  112. package/modules/proxy/services/acl.service.js.map +1 -0
  113. package/modules/proxy/services/http-auth-handler.service.d.ts +19 -0
  114. package/modules/proxy/services/http-auth-handler.service.js +146 -0
  115. package/modules/proxy/services/http-auth-handler.service.js.map +1 -0
  116. package/modules/proxy/services/http-handler.service.d.ts +21 -0
  117. package/modules/proxy/services/http-handler.service.js +210 -0
  118. package/modules/proxy/services/http-handler.service.js.map +1 -0
  119. package/modules/proxy/services/jwt.service.d.ts +12 -0
  120. package/modules/proxy/services/jwt.service.js +107 -0
  121. package/modules/proxy/services/jwt.service.js.map +1 -0
  122. package/modules/proxy/services/websocket.service.d.ts +21 -0
  123. package/modules/proxy/services/websocket.service.js +180 -0
  124. package/modules/proxy/services/websocket.service.js.map +1 -0
  125. package/modules/remote-config/index.d.ts +2 -0
  126. package/modules/remote-config/index.js +19 -0
  127. package/modules/remote-config/index.js.map +1 -0
  128. package/modules/remote-config/remote-config.module.d.ts +2 -0
  129. package/modules/remote-config/remote-config.module.js +22 -0
  130. package/modules/remote-config/remote-config.module.js.map +1 -0
  131. package/modules/remote-config/remote-config.service.d.ts +12 -0
  132. package/modules/remote-config/remote-config.service.js +68 -0
  133. package/modules/remote-config/remote-config.service.js.map +1 -0
  134. package/open-rlb-amqp.schema.json +1297 -0
  135. package/package.json +88 -0
  136. package/tsconfig.build.tsbuildinfo +1 -0
package/README.md ADDED
@@ -0,0 +1,300 @@
1
+ # @open-rlb/nestjs-amqp
2
+
3
+ Quick guide for using the npm package.
4
+
5
+ Guide scope: `rpc`, `handle`, `broadcast`.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm i @open-rlb/nestjs-amqp
11
+ ```
12
+
13
+ ## Basic setup
14
+
15
+ ### `AppModule`
16
+
17
+ ```ts
18
+ import { HttpModule } from '@nestjs/axios';
19
+ import { Module } from '@nestjs/common';
20
+ import { ConfigModule, ConfigService } from '@nestjs/config';
21
+ import { BrokerModule, ProxyModule } from '@open-rlb/nestjs-amqp';
22
+
23
+ @Module({
24
+ imports: [
25
+ BrokerModule.forRootAsync({
26
+ imports: [ConfigModule],
27
+ inject: [ConfigService],
28
+ useFactory: async (config: ConfigService) => ({
29
+ options: config.get('broker'),
30
+ topics: config.get('topics'),
31
+ appOptions: config.get('app'),
32
+ authOptions: config.get('auth-providers'),
33
+ gatewayOptions: config.get('gateway'),
34
+ }),
35
+ }),
36
+ HttpModule,
37
+ ProxyModule.forRoot([]),
38
+ ],
39
+ })
40
+ export class AppModule {}
41
+ ```
42
+
43
+ ### Bootstrap
44
+
45
+ If you use `parseRaw: true` in gateway routes:
46
+
47
+ ```ts
48
+ const app = await NestFactory.create(AppModule, { rawBody: true });
49
+ ```
50
+
51
+ ## Minimal `config.yaml`
52
+
53
+ ```yaml
54
+ # yaml-language-server: $schema=./schema.json
55
+
56
+ app:
57
+ environment: development
58
+
59
+ broker:
60
+ uri: "amqp://localhost/<vhost>"
61
+ defaultSubscribeErrorBehavior: "ack"
62
+ defaultPublishErrorBehavior: "reject"
63
+ connectionManagerOptions:
64
+ heartbeatIntervalInSeconds: 60
65
+ reconnectTimeInSeconds: 60
66
+ connectionOptions:
67
+ clientProperties:
68
+ connection_name: "connection-name"
69
+ credentials:
70
+ mechanism: PLAIN
71
+ username: guest
72
+ password: guest
73
+
74
+ exchanges:
75
+ - name: users-ex
76
+ type: direct
77
+ createExchangeIfNotExists: true
78
+ options:
79
+ durable: true
80
+
81
+ queues:
82
+ - name: users-rpc-q
83
+ exchange: users-ex
84
+ routingKey: users.rpc
85
+ createQueueIfNotExists: true
86
+ options:
87
+ durable: true
88
+
89
+ replyQueues:
90
+ users-ex: users-reply-q
91
+
92
+ topics:
93
+ - name: users-rpc
94
+ mode: rpc
95
+ queue: users-rpc-q
96
+
97
+ gateway:
98
+ mode: gateway
99
+ paths:
100
+ - name: users-create
101
+ method: POST
102
+ path: /users
103
+ dataSource: body
104
+ topic: users-rpc
105
+ action: user.create
106
+ mode: rpc
107
+ events: []
108
+ ```
109
+
110
+ ## Quick usage
111
+
112
+ ### RPC handler with decorators
113
+
114
+ ```ts
115
+ import { Injectable } from '@nestjs/common';
116
+ import { BrokerAction, BrokerParam } from '@open-rlb/nestjs-amqp';
117
+
118
+ @Injectable()
119
+ export class UsersActionService {
120
+ @BrokerAction('users-rpc', 'user.create', 'rpc')
121
+ async createUser(
122
+ @BrokerParam('body', 'email') email: string,
123
+ @BrokerParam('body', 'role') role: string,
124
+ @BrokerParam('header', 'X-GTW-AUTH-USERID') userId: string,
125
+ ) {
126
+ return { id: 'usr_1', email, role, createdBy: userId };
127
+ }
128
+ }
129
+ ```
130
+
131
+ ### RPC call from code
132
+
133
+ ```ts
134
+ import { Injectable } from '@nestjs/common';
135
+ import { BrokerService } from '@open-rlb/nestjs-amqp';
136
+
137
+ @Injectable()
138
+ export class UsersClientService {
139
+ constructor(private readonly broker: BrokerService) {}
140
+
141
+ async createUser() {
142
+ return this.broker.requestData(
143
+ 'users-rpc',
144
+ 'user.create',
145
+ { email: 'john@example.com', role: 'admin' },
146
+ { 'X-Tenant': 'acme' },
147
+ 5000,
148
+ );
149
+ }
150
+ }
151
+ ```
152
+
153
+ ### Manual consumer (without decorators)
154
+
155
+ ```ts
156
+ await broker.registerRpc<{ id: string }, { ok: boolean }>('health-rpc', async (event) => {
157
+ return { ok: !!event.payload?.id };
158
+ });
159
+
160
+ await broker.registerHandler<{ invoiceId: string }>('invoice-handle', async (event) => {
161
+ console.log(event.payload.invoiceId);
162
+ });
163
+ ```
164
+
165
+ ## Quick reference
166
+
167
+ ### `BrokerService`
168
+
169
+ | Method | Use |
170
+ | ---------------------------------------------------------- | ------------------------------- |
171
+ | `requestData(topic, action, payload?, headers?, timeout?)` | RPC request/response |
172
+ | `registerRpc(topic, handler)` | manual RPC consumer |
173
+ | `registerHandler(topic, handler)` | `handle` / `broadcast` consumer |
174
+
175
+ ### Topic types (`topics[].mode`)
176
+
177
+ | Type | Use it when | Minimal config | Why |
178
+ | ----------- | -------------------------------------- | ------------------------------------------------------- | ------------------------------------ |
179
+ | `rpc` | you need request/response | `name`, `mode: rpc`, `queue` (or `exchange+routingKey`) | immediate response + timeout control |
180
+ | `handle` | you need a worker on one queue | `name`, `mode: handle`, `queue` | simple queue consumer |
181
+ | `broadcast` | you need one message to many consumers | `name`, `mode: broadcast`, `exchange`, `routingKey` | fanout/topic pattern |
182
+ | `event` | you need publish without response | `name`, `mode: event`, `queue` or `exchange+routingKey` | fire-and-forget (not covered here) |
183
+
184
+ Quick snippet:
185
+
186
+ ```yaml
187
+ topics:
188
+ - name: users-rpc
189
+ mode: rpc
190
+ queue: users-rpc-q
191
+
192
+ - name: invoice-handle
193
+ mode: handle
194
+ queue: invoice-handle-q
195
+
196
+ - name: notify-broadcast
197
+ mode: broadcast
198
+ exchange: notify-ex
199
+ routingKey: notify.#
200
+ ```
201
+
202
+ ### Decorators
203
+
204
+ | Decorator | Use |
205
+ | ------------------------------------------------------------- | ------------------------------------ |
206
+ | `@BrokerAction(topic, action, type?)` | binds method to topic/action |
207
+ | `@BrokerParam(source, name?)` | maps method params from message data |
208
+ | `@BrokerAuth(authName, allowAnonymous?, roles?)` | auth metadata |
209
+ | `@BrokerHTTP(method, path, dataSource?, timeout?, parseRaw?)` | HTTP metadata |
210
+
211
+ ### `@BrokerParam` sources
212
+
213
+ | Source | Injected value |
214
+ | ----------- | --------------------------------- |
215
+ | `body` | `payload[name or parameter name]` |
216
+ | `body-full` | full payload |
217
+ | `header` | `headers[name or parameter name]` |
218
+ | `tag` | AMQP consumer tag |
219
+ | `action` | message action |
220
+ | `topic` | current topic |
221
+
222
+ ### `gateway.paths[].dataSource`
223
+
224
+ | Value | Payload |
225
+ | ------------ | -------------------------------- |
226
+ | `body` | `{...params, ...body}` |
227
+ | `query` | `{...params, ...query}` |
228
+ | `params` | `params` |
229
+ | `body-query` | `{...params, ...query, ...body}` |
230
+ | `query-body` | `{...params, ...body, ...query}` |
231
+
232
+ ### Auth providers
233
+
234
+ #### Type: `jwks`
235
+
236
+ ```yaml
237
+ auth-providers:
238
+ - name: gateway-jwks
239
+ type: jwks
240
+ issuer: https://issuer.example.com/realms/main
241
+ jwksUri: https://issuer.example.com/certs
242
+ algorithms: [RS256]
243
+ jwtMap:
244
+ - sub:userId
245
+ - roles:roles
246
+ headerPrefix: X-GTW-AUTH-
247
+ uidClaim: USERID
248
+ usernameClaim: USERNAME
249
+ aclTopic: acl
250
+ aclAction: can-user-do
251
+ ```
252
+
253
+ #### Type: `jwt`
254
+
255
+ ```yaml
256
+ auth-providers:
257
+ - name: gateway-jwt
258
+ type: jwt
259
+ secret: your-jwt-secret
260
+ issuer: https://issuer.example.com/realms/main
261
+ audience: your-audience
262
+ algorithms: [HS256]
263
+ jwtMap:
264
+ - sub:userId
265
+ - roles:roles
266
+ headerPrefix: X-GTW-AUTH-
267
+ uidClaim: USERID
268
+ usernameClaim: USERNAME
269
+ aclTopic: acl
270
+ aclAction: can-user-do
271
+ ```
272
+
273
+ #### Type: `str-compare`
274
+
275
+ ```yaml
276
+ auth-providers:
277
+ - name: gateway-str
278
+ type: str-compare
279
+ secret: your-static-token
280
+ headerPrefix: Bearer
281
+ ```
282
+
283
+ ### Gateway path (RPC)
284
+
285
+ ```yaml
286
+ - name: users-create
287
+ method: POST
288
+ path: /users
289
+ dataSource: body
290
+ topic: users-rpc
291
+ action: user.create
292
+ mode: rpc
293
+ timeout: 7000
294
+ ```
295
+
296
+ ## Common errors
297
+
298
+ - `Topic <name> not found in configuration`: check `topics[].name`, `@BrokerAction`, `requestData`, `gateway.paths[].topic`.
299
+ - `Queue <name> not found in configuration`: check that `topics[].queue` exists in `broker.queues[]`.
300
+ - `401/403` from gateway: check `gateway.paths[].auth`, `auth-providers[]`, ACL service when using `roles`.
@@ -0,0 +1,51 @@
1
+ import { OnApplicationShutdown, OnModuleInit } from '@nestjs/common';
2
+ import { AmqpConnectionManager, ChannelWrapper } from 'amqp-connection-manager';
3
+ import { Channel, ConfirmChannel, Connection, Options } from 'amqplib';
4
+ import { RabbitMQConfig } from '../config/rabbitmq.config';
5
+ import { MessageHandlerOptions, RequestOptions } from '../models/rabbitmq-handler.model';
6
+ import { SubscriptionResult } from '../models/subscription-result.model';
7
+ import { ConsumeOptions, ConsumerTag, RpcSubscriberHandler, SubscriberHandler } from '../types';
8
+ export declare class AmqpConnection implements OnApplicationShutdown, OnModuleInit {
9
+ private readonly config;
10
+ private readonly messageSubject;
11
+ private readonly logger;
12
+ private readonly initialized;
13
+ private _managedConnection;
14
+ private _managedChannel;
15
+ private _managedChannels;
16
+ private _channel;
17
+ private _channels;
18
+ private _connection?;
19
+ private _consumers;
20
+ private readonly outstandingMessageProcessing;
21
+ constructor(config: RabbitMQConfig);
22
+ onModuleInit(): Promise<void>;
23
+ get channel(): Channel;
24
+ get connection(): Connection;
25
+ get managedChannel(): ChannelWrapper;
26
+ get managedConnection(): AmqpConnectionManager;
27
+ get configuration(): RabbitMQConfig;
28
+ get channels(): Record<string, ConfirmChannel>;
29
+ get managedChannels(): Record<string, import("amqp-connection-manager/dist/types/ChannelWrapper").default>;
30
+ get connected(): boolean;
31
+ init(): Promise<void>;
32
+ request<T>(requestOptions: RequestOptions): Promise<T>;
33
+ createSubscriber<T>(handler: SubscriberHandler<T>, msgOptions: MessageHandlerOptions, originalHandlerName: string, consumeOptions?: ConsumeOptions): Promise<SubscriptionResult>;
34
+ createRpc<T, U>(handler: RpcSubscriberHandler<T, U>, rpcOptions: MessageHandlerOptions): Promise<SubscriptionResult>;
35
+ setupRpcChannel<T, U>(handler: RpcSubscriberHandler<T, U>, rpcOptions: MessageHandlerOptions, channel: ConfirmChannel): Promise<ConsumerTag>;
36
+ publish(exchange: string, routingKey: string, message: any, options?: Options.Publish): Promise<boolean>;
37
+ onApplicationShutdown(signal?: string): Promise<void>;
38
+ private initCore;
39
+ private setupManagedChannel;
40
+ private setupInitChannel;
41
+ private setupQueuesWithBindings;
42
+ private processDirectReplyToMessage;
43
+ private consumerFactory;
44
+ private wrapConsumer;
45
+ private setupSubscriberChannel;
46
+ private deserializeMessage;
47
+ private setupQueue;
48
+ private selectManagedChannel;
49
+ private registerConsumerForQueue;
50
+ close(): Promise<void>;
51
+ }