@amqp-contract/contract 0.11.0 → 0.13.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 +28 -14
- package/dist/index.cjs +550 -238
- package/dist/index.d.cts +787 -405
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +787 -405
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +540 -236
- package/dist/index.mjs.map +1 -1
- package/docs/index.md +738 -216
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region src/builder.ts
|
|
1
|
+
//#region src/builder/exchange.ts
|
|
2
2
|
/**
|
|
3
3
|
* Define an AMQP exchange.
|
|
4
4
|
*
|
|
@@ -19,6 +19,263 @@ function defineExchange(name, type, options) {
|
|
|
19
19
|
...options
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/builder/message.ts
|
|
25
|
+
/**
|
|
26
|
+
* Define a message definition with payload and optional headers/metadata.
|
|
27
|
+
*
|
|
28
|
+
* A message definition specifies the schema for message payloads and headers using
|
|
29
|
+
* Standard Schema v1 compatible libraries (Zod, Valibot, ArkType, etc.).
|
|
30
|
+
* The schemas are used for automatic validation when publishing or consuming messages.
|
|
31
|
+
*
|
|
32
|
+
* @param payload - The payload schema (must be Standard Schema v1 compatible)
|
|
33
|
+
* @param options - Optional message metadata
|
|
34
|
+
* @param options.headers - Optional header schema for message headers
|
|
35
|
+
* @param options.summary - Brief description for documentation (used in AsyncAPI generation)
|
|
36
|
+
* @param options.description - Detailed description for documentation (used in AsyncAPI generation)
|
|
37
|
+
* @returns A message definition with inferred types
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* import { z } from 'zod';
|
|
42
|
+
*
|
|
43
|
+
* const orderMessage = defineMessage(
|
|
44
|
+
* z.object({
|
|
45
|
+
* orderId: z.string().uuid(),
|
|
46
|
+
* customerId: z.string().uuid(),
|
|
47
|
+
* amount: z.number().positive(),
|
|
48
|
+
* items: z.array(z.object({
|
|
49
|
+
* productId: z.string(),
|
|
50
|
+
* quantity: z.number().int().positive(),
|
|
51
|
+
* })),
|
|
52
|
+
* }),
|
|
53
|
+
* {
|
|
54
|
+
* summary: 'Order created event',
|
|
55
|
+
* description: 'Emitted when a new order is created in the system'
|
|
56
|
+
* }
|
|
57
|
+
* );
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
function defineMessage(payload, options) {
|
|
61
|
+
return {
|
|
62
|
+
payload,
|
|
63
|
+
...options
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/builder/binding.ts
|
|
69
|
+
/**
|
|
70
|
+
* Type guard to check if a queue entry is a QueueWithTtlBackoffInfrastructure.
|
|
71
|
+
* Duplicated here to avoid circular dependency with queue.ts.
|
|
72
|
+
* @internal
|
|
73
|
+
*/
|
|
74
|
+
function isQueueWithTtlBackoffInfrastructure$1(entry) {
|
|
75
|
+
return typeof entry === "object" && entry !== null && "__brand" in entry && entry.__brand === "QueueWithTtlBackoffInfrastructure";
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Extract the plain QueueDefinition from a QueueEntry.
|
|
79
|
+
* Duplicated here to avoid circular dependency with queue.ts.
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
82
|
+
function extractQueueInternal(entry) {
|
|
83
|
+
if (isQueueWithTtlBackoffInfrastructure$1(entry)) return entry.queue;
|
|
84
|
+
return entry;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Define a binding between a queue and an exchange.
|
|
88
|
+
*
|
|
89
|
+
* This is the implementation function - use the type-specific overloads for better type safety.
|
|
90
|
+
*
|
|
91
|
+
* @param queue - The queue definition or queue with infrastructure to bind
|
|
92
|
+
* @param exchange - The exchange definition
|
|
93
|
+
* @param options - Optional binding configuration
|
|
94
|
+
* @returns A queue binding definition
|
|
95
|
+
* @internal
|
|
96
|
+
*/
|
|
97
|
+
function defineQueueBinding(queue, exchange, options) {
|
|
98
|
+
const queueDef = extractQueueInternal(queue);
|
|
99
|
+
if (exchange.type === "fanout") return {
|
|
100
|
+
type: "queue",
|
|
101
|
+
queue: queueDef,
|
|
102
|
+
exchange,
|
|
103
|
+
...options?.arguments && { arguments: options.arguments }
|
|
104
|
+
};
|
|
105
|
+
return {
|
|
106
|
+
type: "queue",
|
|
107
|
+
queue: queueDef,
|
|
108
|
+
exchange,
|
|
109
|
+
routingKey: options?.routingKey,
|
|
110
|
+
...options?.arguments && { arguments: options.arguments }
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Internal helper to call defineQueueBinding with proper type handling.
|
|
115
|
+
* Used by queue.ts to avoid circular dependency.
|
|
116
|
+
* @internal
|
|
117
|
+
*/
|
|
118
|
+
function defineQueueBindingInternal(queue, exchange, options) {
|
|
119
|
+
if (exchange.type === "fanout") return defineQueueBinding(queue, exchange, options);
|
|
120
|
+
return defineQueueBinding(queue, exchange, options);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Define a binding between two exchanges (exchange-to-exchange routing).
|
|
124
|
+
*
|
|
125
|
+
* This is the implementation function - use the type-specific overloads for better type safety.
|
|
126
|
+
*
|
|
127
|
+
* @param destination - The destination exchange definition
|
|
128
|
+
* @param source - The source exchange definition
|
|
129
|
+
* @param options - Optional binding configuration
|
|
130
|
+
* @returns An exchange binding definition
|
|
131
|
+
* @internal
|
|
132
|
+
*/
|
|
133
|
+
function defineExchangeBinding(destination, source, options) {
|
|
134
|
+
if (source.type === "fanout") return {
|
|
135
|
+
type: "exchange",
|
|
136
|
+
source,
|
|
137
|
+
destination,
|
|
138
|
+
...options?.arguments && { arguments: options.arguments }
|
|
139
|
+
};
|
|
140
|
+
return {
|
|
141
|
+
type: "exchange",
|
|
142
|
+
source,
|
|
143
|
+
destination,
|
|
144
|
+
routingKey: options?.routingKey ?? "",
|
|
145
|
+
...options?.arguments && { arguments: options.arguments }
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region src/builder/queue.ts
|
|
151
|
+
/**
|
|
152
|
+
* Resolve TTL-backoff retry options with defaults applied.
|
|
153
|
+
* @internal
|
|
154
|
+
*/
|
|
155
|
+
function resolveTtlBackoffOptions(options) {
|
|
156
|
+
return {
|
|
157
|
+
mode: "ttl-backoff",
|
|
158
|
+
maxRetries: options?.maxRetries ?? 3,
|
|
159
|
+
initialDelayMs: options?.initialDelayMs ?? 1e3,
|
|
160
|
+
maxDelayMs: options?.maxDelayMs ?? 3e4,
|
|
161
|
+
backoffMultiplier: options?.backoffMultiplier ?? 2,
|
|
162
|
+
jitter: options?.jitter ?? true
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Type guard to check if a queue entry is a QueueWithTtlBackoffInfrastructure.
|
|
167
|
+
*
|
|
168
|
+
* When you configure a queue with TTL-backoff retry and a dead letter exchange,
|
|
169
|
+
* `defineQueue` returns a `QueueWithTtlBackoffInfrastructure` instead of a plain
|
|
170
|
+
* `QueueDefinition`. This type guard helps you distinguish between the two.
|
|
171
|
+
*
|
|
172
|
+
* **When to use:**
|
|
173
|
+
* - When you need to check the type of a queue entry at runtime
|
|
174
|
+
* - When writing generic code that handles both plain queues and infrastructure wrappers
|
|
175
|
+
*
|
|
176
|
+
* **Related functions:**
|
|
177
|
+
* - `extractQueue()` - Use this to get the underlying queue definition from either type
|
|
178
|
+
*
|
|
179
|
+
* @param entry - The queue entry to check
|
|
180
|
+
* @returns True if the entry is a QueueWithTtlBackoffInfrastructure, false otherwise
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* const queue = defineQueue('orders', {
|
|
185
|
+
* deadLetter: { exchange: dlx },
|
|
186
|
+
* retry: { mode: 'ttl-backoff' },
|
|
187
|
+
* });
|
|
188
|
+
*
|
|
189
|
+
* if (isQueueWithTtlBackoffInfrastructure(queue)) {
|
|
190
|
+
* // queue has .queue, .waitQueue, .waitQueueBinding, .mainQueueRetryBinding
|
|
191
|
+
* console.log('Wait queue:', queue.waitQueue.name);
|
|
192
|
+
* } else {
|
|
193
|
+
* // queue is a plain QueueDefinition
|
|
194
|
+
* console.log('Queue:', queue.name);
|
|
195
|
+
* }
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
function isQueueWithTtlBackoffInfrastructure(entry) {
|
|
199
|
+
return typeof entry === "object" && entry !== null && "__brand" in entry && entry.__brand === "QueueWithTtlBackoffInfrastructure";
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Extract the plain QueueDefinition from a QueueEntry.
|
|
203
|
+
*
|
|
204
|
+
* **Why this function exists:**
|
|
205
|
+
* When you configure a queue with TTL-backoff retry and a dead letter exchange,
|
|
206
|
+
* `defineQueue` (or `defineTtlBackoffQueue`) returns a wrapper object that includes
|
|
207
|
+
* the main queue, wait queue, and bindings. This function extracts the underlying
|
|
208
|
+
* queue definition so you can access properties like `name`, `type`, etc.
|
|
209
|
+
*
|
|
210
|
+
* **When to use:**
|
|
211
|
+
* - When you need to access queue properties (name, type, deadLetter, etc.)
|
|
212
|
+
* - When passing a queue to functions that expect a plain QueueDefinition
|
|
213
|
+
* - Works safely on both plain queues and infrastructure wrappers
|
|
214
|
+
*
|
|
215
|
+
* **How it works:**
|
|
216
|
+
* - If the entry is a `QueueWithTtlBackoffInfrastructure`, returns `entry.queue`
|
|
217
|
+
* - Otherwise, returns the entry as-is (it's already a plain QueueDefinition)
|
|
218
|
+
*
|
|
219
|
+
* @param entry - The queue entry (either plain QueueDefinition or QueueWithTtlBackoffInfrastructure)
|
|
220
|
+
* @returns The plain QueueDefinition
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* import { defineQueue, defineTtlBackoffQueue, extractQueue } from '@amqp-contract/contract';
|
|
225
|
+
*
|
|
226
|
+
* // TTL-backoff queue returns a wrapper
|
|
227
|
+
* const orderQueue = defineTtlBackoffQueue('orders', {
|
|
228
|
+
* deadLetterExchange: dlx,
|
|
229
|
+
* maxRetries: 3,
|
|
230
|
+
* });
|
|
231
|
+
*
|
|
232
|
+
* // Use extractQueue to access the queue name
|
|
233
|
+
* const queueName = extractQueue(orderQueue).name; // 'orders'
|
|
234
|
+
*
|
|
235
|
+
* // Also works safely on plain queues
|
|
236
|
+
* const plainQueue = defineQueue('simple', { type: 'quorum', retry: { mode: 'quorum-native' } });
|
|
237
|
+
* const plainName = extractQueue(plainQueue).name; // 'simple'
|
|
238
|
+
*
|
|
239
|
+
* // Access other properties
|
|
240
|
+
* const queueDef = extractQueue(orderQueue);
|
|
241
|
+
* console.log(queueDef.name); // 'orders'
|
|
242
|
+
* console.log(queueDef.type); // 'quorum'
|
|
243
|
+
* console.log(queueDef.deadLetter); // { exchange: dlx, ... }
|
|
244
|
+
* ```
|
|
245
|
+
*
|
|
246
|
+
* @see isQueueWithTtlBackoffInfrastructure - Type guard to check if extraction is needed
|
|
247
|
+
* @see defineTtlBackoffQueue - Creates queues with TTL-backoff infrastructure
|
|
248
|
+
*/
|
|
249
|
+
function extractQueue(entry) {
|
|
250
|
+
if (isQueueWithTtlBackoffInfrastructure(entry)) return entry.queue;
|
|
251
|
+
return entry;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Wrap a queue definition with TTL-backoff retry infrastructure.
|
|
255
|
+
* @internal
|
|
256
|
+
*/
|
|
257
|
+
function wrapWithTtlBackoffInfrastructure(queue) {
|
|
258
|
+
if (!queue.deadLetter) throw new Error(`Queue "${queue.name}" does not have a dead letter exchange configured. TTL-backoff retry requires deadLetter to be set on the queue.`);
|
|
259
|
+
const dlx = queue.deadLetter.exchange;
|
|
260
|
+
const waitQueueName = `${queue.name}-wait`;
|
|
261
|
+
const waitQueue = {
|
|
262
|
+
name: waitQueueName,
|
|
263
|
+
type: "quorum",
|
|
264
|
+
durable: queue.durable ?? true,
|
|
265
|
+
deadLetter: {
|
|
266
|
+
exchange: dlx,
|
|
267
|
+
routingKey: queue.name
|
|
268
|
+
},
|
|
269
|
+
retry: resolveTtlBackoffOptions(void 0)
|
|
270
|
+
};
|
|
271
|
+
return {
|
|
272
|
+
__brand: "QueueWithTtlBackoffInfrastructure",
|
|
273
|
+
queue,
|
|
274
|
+
waitQueue,
|
|
275
|
+
waitQueueBinding: defineQueueBindingInternal(waitQueue, dlx, { routingKey: waitQueueName }),
|
|
276
|
+
mainQueueRetryBinding: defineQueueBindingInternal(queue, dlx, { routingKey: queue.name })
|
|
277
|
+
};
|
|
278
|
+
}
|
|
22
279
|
/**
|
|
23
280
|
* Define an AMQP queue.
|
|
24
281
|
*
|
|
@@ -91,22 +348,30 @@ function defineQueue(name, options) {
|
|
|
91
348
|
if (opts.arguments !== void 0) baseProps.arguments = opts.arguments;
|
|
92
349
|
if (type === "quorum") {
|
|
93
350
|
const quorumOpts = opts;
|
|
351
|
+
const inputRetry = quorumOpts.retry ?? { mode: "ttl-backoff" };
|
|
352
|
+
if (inputRetry.mode === "quorum-native") {
|
|
353
|
+
if (quorumOpts.deliveryLimit === void 0) throw new Error(`Queue "${name}" uses quorum-native retry mode but deliveryLimit is not configured. Quorum-native retry requires deliveryLimit to be set.`);
|
|
354
|
+
}
|
|
355
|
+
const retry$1 = inputRetry.mode === "quorum-native" ? inputRetry : resolveTtlBackoffOptions(inputRetry);
|
|
94
356
|
const queueDefinition$1 = {
|
|
95
357
|
...baseProps,
|
|
96
|
-
type: "quorum"
|
|
358
|
+
type: "quorum",
|
|
359
|
+
retry: retry$1
|
|
97
360
|
};
|
|
98
361
|
if (quorumOpts.deliveryLimit !== void 0) {
|
|
99
362
|
if (quorumOpts.deliveryLimit < 1 || !Number.isInteger(quorumOpts.deliveryLimit)) throw new Error(`Invalid deliveryLimit: ${quorumOpts.deliveryLimit}. Must be a positive integer.`);
|
|
100
363
|
queueDefinition$1.deliveryLimit = quorumOpts.deliveryLimit;
|
|
101
364
|
}
|
|
102
|
-
if (
|
|
103
|
-
if (quorumOpts.retry?.mode === "ttl-backoff" && queueDefinition$1.deadLetter) return wrapWithTtlBackoffInfrastructure(queueDefinition$1);
|
|
365
|
+
if (retry$1.mode === "ttl-backoff" && queueDefinition$1.deadLetter) return wrapWithTtlBackoffInfrastructure(queueDefinition$1);
|
|
104
366
|
return queueDefinition$1;
|
|
105
367
|
}
|
|
106
368
|
const classicOpts = opts;
|
|
369
|
+
if (classicOpts.retry?.mode === "quorum-native") throw new Error(`Queue "${name}" uses quorum-native retry mode but is a classic queue. Quorum-native retry requires quorum queues (type: "quorum").`);
|
|
370
|
+
const retry = resolveTtlBackoffOptions(classicOpts.retry);
|
|
107
371
|
const queueDefinition = {
|
|
108
372
|
...baseProps,
|
|
109
|
-
type: "classic"
|
|
373
|
+
type: "classic",
|
|
374
|
+
retry
|
|
110
375
|
};
|
|
111
376
|
if (classicOpts.exclusive !== void 0) queueDefinition.exclusive = classicOpts.exclusive;
|
|
112
377
|
if (classicOpts.maxPriority !== void 0) {
|
|
@@ -116,129 +381,132 @@ function defineQueue(name, options) {
|
|
|
116
381
|
"x-max-priority": classicOpts.maxPriority
|
|
117
382
|
};
|
|
118
383
|
}
|
|
119
|
-
if (
|
|
120
|
-
if (classicOpts.retry?.mode === "ttl-backoff" && queueDefinition.deadLetter) return wrapWithTtlBackoffInfrastructure(queueDefinition);
|
|
384
|
+
if (retry.mode === "ttl-backoff" && queueDefinition.deadLetter) return wrapWithTtlBackoffInfrastructure(queueDefinition);
|
|
121
385
|
return queueDefinition;
|
|
122
386
|
}
|
|
123
387
|
/**
|
|
124
|
-
*
|
|
125
|
-
* @internal
|
|
126
|
-
*/
|
|
127
|
-
function wrapWithTtlBackoffInfrastructure(queue) {
|
|
128
|
-
if (!queue.deadLetter) throw new Error(`Queue "${queue.name}" does not have a dead letter exchange configured. TTL-backoff retry requires deadLetter to be set on the queue.`);
|
|
129
|
-
const dlx = queue.deadLetter.exchange;
|
|
130
|
-
const waitQueueName = `${queue.name}-wait`;
|
|
131
|
-
const waitQueue = {
|
|
132
|
-
name: waitQueueName,
|
|
133
|
-
type: "quorum",
|
|
134
|
-
durable: queue.durable ?? true,
|
|
135
|
-
deadLetter: {
|
|
136
|
-
exchange: dlx,
|
|
137
|
-
routingKey: queue.name
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
return {
|
|
141
|
-
__brand: "QueueWithTtlBackoffInfrastructure",
|
|
142
|
-
queue,
|
|
143
|
-
waitQueue,
|
|
144
|
-
waitQueueBinding: callDefineQueueBinding(waitQueue, dlx, { routingKey: waitQueueName }),
|
|
145
|
-
mainQueueRetryBinding: callDefineQueueBinding(queue, dlx, { routingKey: queue.name })
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Define a message definition with payload and optional headers/metadata.
|
|
388
|
+
* Create a quorum queue with quorum-native retry.
|
|
150
389
|
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
390
|
+
* This is a simplified helper that enforces best practices:
|
|
391
|
+
* - Uses quorum queues (recommended for most use cases)
|
|
392
|
+
* - Requires dead letter exchange for failed message handling
|
|
393
|
+
* - Uses quorum-native retry mode (simpler than TTL-backoff)
|
|
154
394
|
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
* @
|
|
395
|
+
* **When to use:**
|
|
396
|
+
* - You want simple, immediate retries without exponential backoff
|
|
397
|
+
* - You don't need configurable delays between retries
|
|
398
|
+
* - You want the simplest retry configuration
|
|
399
|
+
*
|
|
400
|
+
* @param name - The queue name
|
|
401
|
+
* @param options - Configuration options
|
|
402
|
+
* @returns A quorum queue definition with quorum-native retry
|
|
161
403
|
*
|
|
162
404
|
* @example
|
|
163
405
|
* ```typescript
|
|
164
|
-
*
|
|
406
|
+
* const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
|
|
165
407
|
*
|
|
166
|
-
* const
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
* {
|
|
177
|
-
* summary: 'Order created event',
|
|
178
|
-
* description: 'Emitted when a new order is created in the system'
|
|
179
|
-
* }
|
|
180
|
-
* );
|
|
408
|
+
* const orderQueue = defineQuorumQueue('order-processing', {
|
|
409
|
+
* deadLetterExchange: dlx,
|
|
410
|
+
* deliveryLimit: 3, // Retry up to 3 times
|
|
411
|
+
* });
|
|
412
|
+
*
|
|
413
|
+
* const contract = defineContract({
|
|
414
|
+
* exchanges: { dlx },
|
|
415
|
+
* queues: { orderProcessing: orderQueue },
|
|
416
|
+
* // ...
|
|
417
|
+
* });
|
|
181
418
|
* ```
|
|
419
|
+
*
|
|
420
|
+
* @see defineQueue - For full queue configuration options
|
|
421
|
+
* @see defineTtlBackoffQueue - For queues with exponential backoff retry
|
|
182
422
|
*/
|
|
183
|
-
function
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
423
|
+
function defineQuorumQueue(name, options) {
|
|
424
|
+
const { deadLetterExchange, deadLetterRoutingKey, deliveryLimit, autoDelete, arguments: args } = options;
|
|
425
|
+
const queueOptions = {
|
|
426
|
+
type: "quorum",
|
|
427
|
+
deadLetter: deadLetterRoutingKey ? {
|
|
428
|
+
exchange: deadLetterExchange,
|
|
429
|
+
routingKey: deadLetterRoutingKey
|
|
430
|
+
} : { exchange: deadLetterExchange },
|
|
431
|
+
deliveryLimit,
|
|
432
|
+
retry: { mode: "quorum-native" }
|
|
187
433
|
};
|
|
434
|
+
if (autoDelete !== void 0) queueOptions.autoDelete = autoDelete;
|
|
435
|
+
if (args !== void 0) queueOptions.arguments = args;
|
|
436
|
+
return defineQueue(name, queueOptions);
|
|
188
437
|
}
|
|
189
438
|
/**
|
|
190
|
-
*
|
|
439
|
+
* Create a queue with TTL-backoff retry (exponential backoff).
|
|
191
440
|
*
|
|
192
|
-
* This is
|
|
441
|
+
* This is a simplified helper that enforces best practices:
|
|
442
|
+
* - Uses quorum queues (recommended for most use cases)
|
|
443
|
+
* - Requires dead letter exchange for retry routing
|
|
444
|
+
* - Uses TTL-backoff retry mode with configurable delays
|
|
445
|
+
* - Automatically generates wait queue and bindings
|
|
193
446
|
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
* @internal
|
|
199
|
-
*/
|
|
200
|
-
function defineQueueBinding(queue, exchange, options) {
|
|
201
|
-
const queueDef = extractQueue(queue);
|
|
202
|
-
if (exchange.type === "fanout") return {
|
|
203
|
-
type: "queue",
|
|
204
|
-
queue: queueDef,
|
|
205
|
-
exchange,
|
|
206
|
-
...options?.arguments && { arguments: options.arguments }
|
|
207
|
-
};
|
|
208
|
-
return {
|
|
209
|
-
type: "queue",
|
|
210
|
-
queue: queueDef,
|
|
211
|
-
exchange,
|
|
212
|
-
routingKey: options?.routingKey,
|
|
213
|
-
...options?.arguments && { arguments: options.arguments }
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Define a binding between two exchanges (exchange-to-exchange routing).
|
|
447
|
+
* **When to use:**
|
|
448
|
+
* - You need exponential backoff between retries
|
|
449
|
+
* - You want configurable delays (initial delay, max delay, jitter)
|
|
450
|
+
* - You're processing messages that may need time before retry
|
|
218
451
|
*
|
|
219
|
-
*
|
|
452
|
+
* **Returns:** A `QueueWithTtlBackoffInfrastructure` object that includes the
|
|
453
|
+
* main queue, wait queue, and bindings. Pass this directly to `defineContract`
|
|
454
|
+
* and it will be expanded automatically.
|
|
220
455
|
*
|
|
221
|
-
* @param
|
|
222
|
-
* @param
|
|
223
|
-
* @
|
|
224
|
-
*
|
|
225
|
-
* @
|
|
456
|
+
* @param name - The queue name
|
|
457
|
+
* @param options - Configuration options
|
|
458
|
+
* @returns A queue with TTL-backoff infrastructure
|
|
459
|
+
*
|
|
460
|
+
* @example
|
|
461
|
+
* ```typescript
|
|
462
|
+
* const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
|
|
463
|
+
*
|
|
464
|
+
* const orderQueue = defineTtlBackoffQueue('order-processing', {
|
|
465
|
+
* deadLetterExchange: dlx,
|
|
466
|
+
* maxRetries: 5,
|
|
467
|
+
* initialDelayMs: 1000, // Start with 1s delay
|
|
468
|
+
* maxDelayMs: 30000, // Cap at 30s
|
|
469
|
+
* });
|
|
470
|
+
*
|
|
471
|
+
* const contract = defineContract({
|
|
472
|
+
* exchanges: { dlx },
|
|
473
|
+
* queues: { orderProcessing: orderQueue }, // Wait queue auto-added
|
|
474
|
+
* // ... bindings auto-generated
|
|
475
|
+
* });
|
|
476
|
+
*
|
|
477
|
+
* // To access the underlying queue definition (e.g., for the queue name):
|
|
478
|
+
* import { extractQueue } from '@amqp-contract/contract';
|
|
479
|
+
* const queueName = extractQueue(orderQueue).name;
|
|
480
|
+
* ```
|
|
481
|
+
*
|
|
482
|
+
* @see defineQueue - For full queue configuration options
|
|
483
|
+
* @see defineQuorumQueue - For queues with quorum-native retry (simpler, immediate retries)
|
|
484
|
+
* @see extractQueue - To access the underlying queue definition
|
|
226
485
|
*/
|
|
227
|
-
function
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
486
|
+
function defineTtlBackoffQueue(name, options) {
|
|
487
|
+
const { deadLetterExchange, deadLetterRoutingKey, maxRetries, initialDelayMs, maxDelayMs, backoffMultiplier, jitter, autoDelete, arguments: args } = options;
|
|
488
|
+
const deadLetter = deadLetterRoutingKey ? {
|
|
489
|
+
exchange: deadLetterExchange,
|
|
490
|
+
routingKey: deadLetterRoutingKey
|
|
491
|
+
} : { exchange: deadLetterExchange };
|
|
492
|
+
const retryOptions = { mode: "ttl-backoff" };
|
|
493
|
+
if (maxRetries !== void 0) retryOptions.maxRetries = maxRetries;
|
|
494
|
+
if (initialDelayMs !== void 0) retryOptions.initialDelayMs = initialDelayMs;
|
|
495
|
+
if (maxDelayMs !== void 0) retryOptions.maxDelayMs = maxDelayMs;
|
|
496
|
+
if (backoffMultiplier !== void 0) retryOptions.backoffMultiplier = backoffMultiplier;
|
|
497
|
+
if (jitter !== void 0) retryOptions.jitter = jitter;
|
|
498
|
+
const queueOptions = {
|
|
499
|
+
type: "quorum",
|
|
500
|
+
deadLetter,
|
|
501
|
+
retry: retryOptions
|
|
240
502
|
};
|
|
503
|
+
if (autoDelete !== void 0) queueOptions.autoDelete = autoDelete;
|
|
504
|
+
if (args !== void 0) queueOptions.arguments = args;
|
|
505
|
+
return defineQueue(name, queueOptions);
|
|
241
506
|
}
|
|
507
|
+
|
|
508
|
+
//#endregion
|
|
509
|
+
//#region src/builder/publisher.ts
|
|
242
510
|
/**
|
|
243
511
|
* Define a message publisher.
|
|
244
512
|
*
|
|
@@ -262,6 +530,18 @@ function definePublisher(exchange, message, options) {
|
|
|
262
530
|
};
|
|
263
531
|
}
|
|
264
532
|
/**
|
|
533
|
+
* Helper to call definePublisher with proper type handling.
|
|
534
|
+
* Type safety is enforced by overloaded public function signatures.
|
|
535
|
+
* @internal
|
|
536
|
+
*/
|
|
537
|
+
function definePublisherInternal(exchange, message, options) {
|
|
538
|
+
if (exchange.type === "fanout") return definePublisher(exchange, message, options);
|
|
539
|
+
return definePublisher(exchange, message, options);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
//#endregion
|
|
543
|
+
//#region src/builder/consumer.ts
|
|
544
|
+
/**
|
|
265
545
|
* Define a message consumer.
|
|
266
546
|
*
|
|
267
547
|
* A consumer receives and processes messages from a queue. The message schema is validated
|
|
@@ -270,6 +550,19 @@ function definePublisher(exchange, message, options) {
|
|
|
270
550
|
* Consumers are associated with a specific queue and message type. When you create a worker
|
|
271
551
|
* with this consumer, it will process messages from the queue according to the schema.
|
|
272
552
|
*
|
|
553
|
+
* **Which pattern to use:**
|
|
554
|
+
*
|
|
555
|
+
* | Pattern | Best for | Description |
|
|
556
|
+
* |---------|----------|-------------|
|
|
557
|
+
* | `definePublisher` + `defineConsumer` | Independent definition | Define publishers and consumers separately with manual schema consistency |
|
|
558
|
+
* | `defineEventPublisher` + `defineEventConsumer` | Event broadcasting | Define event publisher first, create consumers that subscribe to it |
|
|
559
|
+
* | `defineCommandConsumer` + `defineCommandPublisher` | Task queues | Define command consumer first, create publishers that send commands to it |
|
|
560
|
+
*
|
|
561
|
+
* Use `defineCommandConsumer` when:
|
|
562
|
+
* - One consumer receives from multiple publishers
|
|
563
|
+
* - You want automatic schema consistency between consumer and publishers
|
|
564
|
+
* - You're building task queue or command patterns
|
|
565
|
+
*
|
|
273
566
|
* @param queue - The queue definition to consume from
|
|
274
567
|
* @param message - The message definition with payload schema
|
|
275
568
|
* @param options - Optional consumer configuration
|
|
@@ -302,6 +595,9 @@ function definePublisher(exchange, message, options) {
|
|
|
302
595
|
* // connection
|
|
303
596
|
* // });
|
|
304
597
|
* ```
|
|
598
|
+
*
|
|
599
|
+
* @see defineCommandConsumer - For task queue patterns with automatic schema consistency
|
|
600
|
+
* @see defineEventPublisher - For event-driven patterns with automatic schema consistency
|
|
305
601
|
*/
|
|
306
602
|
function defineConsumer(queue, message, options) {
|
|
307
603
|
return {
|
|
@@ -310,6 +606,99 @@ function defineConsumer(queue, message, options) {
|
|
|
310
606
|
...options
|
|
311
607
|
};
|
|
312
608
|
}
|
|
609
|
+
|
|
610
|
+
//#endregion
|
|
611
|
+
//#region src/builder/event.ts
|
|
612
|
+
/**
|
|
613
|
+
* Implementation of defineEventPublisher.
|
|
614
|
+
* @internal
|
|
615
|
+
*/
|
|
616
|
+
function defineEventPublisher(exchange, message, options) {
|
|
617
|
+
const config = {
|
|
618
|
+
__brand: "EventPublisherConfig",
|
|
619
|
+
exchange,
|
|
620
|
+
message,
|
|
621
|
+
routingKey: options?.routingKey
|
|
622
|
+
};
|
|
623
|
+
if (options?.arguments !== void 0) config.arguments = options.arguments;
|
|
624
|
+
return config;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Implementation of defineEventConsumer.
|
|
628
|
+
* @internal
|
|
629
|
+
*/
|
|
630
|
+
function defineEventConsumer(eventPublisher, queue, options) {
|
|
631
|
+
const { exchange, message, routingKey: publisherRoutingKey } = eventPublisher;
|
|
632
|
+
const bindingRoutingKey = options?.routingKey ?? publisherRoutingKey;
|
|
633
|
+
const bindingOptions = {};
|
|
634
|
+
if (bindingRoutingKey !== void 0) bindingOptions.routingKey = bindingRoutingKey;
|
|
635
|
+
const bindingArguments = options?.arguments ?? eventPublisher.arguments;
|
|
636
|
+
if (bindingArguments !== void 0) bindingOptions.arguments = bindingArguments;
|
|
637
|
+
const binding = defineQueueBindingInternal(queue, exchange, bindingOptions);
|
|
638
|
+
return {
|
|
639
|
+
__brand: "EventConsumerResult",
|
|
640
|
+
consumer: defineConsumer(queue, message),
|
|
641
|
+
binding
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Type guard to check if a value is an EventPublisherConfig.
|
|
646
|
+
*
|
|
647
|
+
* @param value - The value to check
|
|
648
|
+
* @returns True if the value is an EventPublisherConfig
|
|
649
|
+
*/
|
|
650
|
+
function isEventPublisherConfig(value) {
|
|
651
|
+
return typeof value === "object" && value !== null && "__brand" in value && value.__brand === "EventPublisherConfig";
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Type guard to check if a value is an EventConsumerResult.
|
|
655
|
+
*
|
|
656
|
+
* @param value - The value to check
|
|
657
|
+
* @returns True if the value is an EventConsumerResult
|
|
658
|
+
*/
|
|
659
|
+
function isEventConsumerResult(value) {
|
|
660
|
+
return typeof value === "object" && value !== null && "__brand" in value && value.__brand === "EventConsumerResult";
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
//#endregion
|
|
664
|
+
//#region src/builder/command.ts
|
|
665
|
+
/**
|
|
666
|
+
* Implementation of defineCommandConsumer.
|
|
667
|
+
* @internal
|
|
668
|
+
*/
|
|
669
|
+
function defineCommandConsumer(queue, exchange, message, options) {
|
|
670
|
+
return {
|
|
671
|
+
__brand: "CommandConsumerConfig",
|
|
672
|
+
consumer: defineConsumer(queue, message),
|
|
673
|
+
binding: defineQueueBindingInternal(queue, exchange, options),
|
|
674
|
+
exchange,
|
|
675
|
+
message,
|
|
676
|
+
routingKey: options?.routingKey
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Implementation of defineCommandPublisher.
|
|
681
|
+
* @internal
|
|
682
|
+
*/
|
|
683
|
+
function defineCommandPublisher(commandConsumer, options) {
|
|
684
|
+
const { exchange, message, routingKey: consumerRoutingKey } = commandConsumer;
|
|
685
|
+
const publisherRoutingKey = options?.routingKey ?? consumerRoutingKey;
|
|
686
|
+
const publisherOptions = {};
|
|
687
|
+
if (publisherRoutingKey !== void 0) publisherOptions.routingKey = publisherRoutingKey;
|
|
688
|
+
return definePublisherInternal(exchange, message, publisherOptions);
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Type guard to check if a value is a CommandConsumerConfig.
|
|
692
|
+
*
|
|
693
|
+
* @param value - The value to check
|
|
694
|
+
* @returns True if the value is a CommandConsumerConfig
|
|
695
|
+
*/
|
|
696
|
+
function isCommandConsumerConfig(value) {
|
|
697
|
+
return typeof value === "object" && value !== null && "__brand" in value && value.__brand === "CommandConsumerConfig";
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
//#endregion
|
|
701
|
+
//#region src/builder/contract.ts
|
|
313
702
|
/**
|
|
314
703
|
* Define an AMQP contract.
|
|
315
704
|
*
|
|
@@ -380,138 +769,53 @@ function defineConsumer(queue, message, options) {
|
|
|
380
769
|
* ```
|
|
381
770
|
*/
|
|
382
771
|
function defineContract(definition) {
|
|
383
|
-
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
...
|
|
397
|
-
|
|
398
|
-
return {
|
|
399
|
-
...definition,
|
|
400
|
-
queues: expandedQueues,
|
|
401
|
-
bindings: mergedBindings
|
|
772
|
+
const { publishers: inputPublishers, consumers: inputConsumers, ...rest } = definition;
|
|
773
|
+
const result = rest;
|
|
774
|
+
if (definition.queues && Object.keys(definition.queues).length > 0) {
|
|
775
|
+
const expandedQueues = {};
|
|
776
|
+
const queueBindings = {};
|
|
777
|
+
for (const [name, entry] of Object.entries(definition.queues)) if (isQueueWithTtlBackoffInfrastructure(entry)) {
|
|
778
|
+
expandedQueues[name] = entry.queue;
|
|
779
|
+
expandedQueues[`${name}Wait`] = entry.waitQueue;
|
|
780
|
+
queueBindings[`${name}WaitBinding`] = entry.waitQueueBinding;
|
|
781
|
+
queueBindings[`${name}RetryBinding`] = entry.mainQueueRetryBinding;
|
|
782
|
+
} else expandedQueues[name] = entry;
|
|
783
|
+
result.queues = expandedQueues;
|
|
784
|
+
if (Object.keys(queueBindings).length > 0) result.bindings = {
|
|
785
|
+
...result.bindings,
|
|
786
|
+
...queueBindings
|
|
402
787
|
};
|
|
403
788
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
*/
|
|
413
|
-
function isQueueWithTtlBackoffInfrastructure(entry) {
|
|
414
|
-
return typeof entry === "object" && entry !== null && "__brand" in entry && entry.__brand === "QueueWithTtlBackoffInfrastructure";
|
|
415
|
-
}
|
|
416
|
-
/**
|
|
417
|
-
* Extract the plain QueueDefinition from a QueueEntry.
|
|
418
|
-
* If the entry is a QueueWithTtlBackoffInfrastructure, returns the inner queue.
|
|
419
|
-
* Otherwise, returns the entry as-is.
|
|
420
|
-
*
|
|
421
|
-
* @param entry - The queue entry (either plain QueueDefinition or QueueWithTtlBackoffInfrastructure)
|
|
422
|
-
* @returns The plain QueueDefinition
|
|
423
|
-
*
|
|
424
|
-
* @example
|
|
425
|
-
* ```typescript
|
|
426
|
-
* const queue = defineQueue('orders', { retry: { mode: 'ttl-backoff' }, deadLetter: { exchange: dlx } });
|
|
427
|
-
* const plainQueue = extractQueue(queue); // Returns the inner QueueDefinition
|
|
428
|
-
* ```
|
|
429
|
-
*/
|
|
430
|
-
function extractQueue(entry) {
|
|
431
|
-
if (isQueueWithTtlBackoffInfrastructure(entry)) return entry.queue;
|
|
432
|
-
return entry;
|
|
433
|
-
}
|
|
434
|
-
/**
|
|
435
|
-
* Helper to call definePublisher with proper type handling.
|
|
436
|
-
* Type safety is enforced by overloaded public function signatures.
|
|
437
|
-
* @internal
|
|
438
|
-
*/
|
|
439
|
-
function callDefinePublisher(exchange, message, options) {
|
|
440
|
-
if (exchange.type === "fanout") return definePublisher(exchange, message, options);
|
|
441
|
-
return definePublisher(exchange, message, options);
|
|
442
|
-
}
|
|
443
|
-
/**
|
|
444
|
-
* Helper to call defineQueueBinding with proper type handling.
|
|
445
|
-
* Type safety is enforced by overloaded public function signatures.
|
|
446
|
-
* @internal
|
|
447
|
-
*/
|
|
448
|
-
function callDefineQueueBinding(queue, exchange, options) {
|
|
449
|
-
if (exchange.type === "fanout") return defineQueueBinding(queue, exchange, options);
|
|
450
|
-
return defineQueueBinding(queue, exchange, options);
|
|
451
|
-
}
|
|
452
|
-
/**
|
|
453
|
-
* Implementation of definePublisherFirst.
|
|
454
|
-
* @internal
|
|
455
|
-
*/
|
|
456
|
-
function definePublisherFirst(exchange, message, options) {
|
|
457
|
-
const publisher = callDefinePublisher(exchange, message, options);
|
|
458
|
-
if (exchange.type === "topic") {
|
|
459
|
-
const createConsumer$1 = (queue, routingKey) => {
|
|
460
|
-
const binding = callDefineQueueBinding(queue, exchange, routingKey ? {
|
|
461
|
-
...options,
|
|
462
|
-
routingKey
|
|
463
|
-
} : options);
|
|
464
|
-
return {
|
|
465
|
-
consumer: defineConsumer(queue, message),
|
|
466
|
-
binding
|
|
467
|
-
};
|
|
468
|
-
};
|
|
469
|
-
return {
|
|
470
|
-
publisher,
|
|
471
|
-
createConsumer: createConsumer$1
|
|
472
|
-
};
|
|
789
|
+
if (inputPublishers && Object.keys(inputPublishers).length > 0) {
|
|
790
|
+
const processedPublishers = {};
|
|
791
|
+
for (const [name, entry] of Object.entries(inputPublishers)) if (isEventPublisherConfig(entry)) {
|
|
792
|
+
const publisherOptions = {};
|
|
793
|
+
if (entry.routingKey !== void 0) publisherOptions.routingKey = entry.routingKey;
|
|
794
|
+
processedPublishers[name] = definePublisherInternal(entry.exchange, entry.message, publisherOptions);
|
|
795
|
+
} else processedPublishers[name] = entry;
|
|
796
|
+
result.publishers = processedPublishers;
|
|
473
797
|
}
|
|
474
|
-
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
* @internal
|
|
489
|
-
*/
|
|
490
|
-
function defineConsumerFirst(queue, exchange, message, options) {
|
|
491
|
-
const consumer = defineConsumer(queue, message);
|
|
492
|
-
const binding = callDefineQueueBinding(queue, exchange, options);
|
|
493
|
-
if (exchange.type === "topic") {
|
|
494
|
-
const createPublisher$1 = (routingKey) => {
|
|
495
|
-
return callDefinePublisher(exchange, message, {
|
|
496
|
-
...options,
|
|
497
|
-
routingKey
|
|
498
|
-
});
|
|
499
|
-
};
|
|
500
|
-
return {
|
|
501
|
-
consumer,
|
|
502
|
-
binding,
|
|
503
|
-
createPublisher: createPublisher$1
|
|
798
|
+
if (inputConsumers && Object.keys(inputConsumers).length > 0) {
|
|
799
|
+
const processedConsumers = {};
|
|
800
|
+
const consumerBindings = {};
|
|
801
|
+
for (const [name, entry] of Object.entries(inputConsumers)) if (isEventConsumerResult(entry)) {
|
|
802
|
+
processedConsumers[name] = entry.consumer;
|
|
803
|
+
consumerBindings[`${name}Binding`] = entry.binding;
|
|
804
|
+
} else if (isCommandConsumerConfig(entry)) {
|
|
805
|
+
processedConsumers[name] = entry.consumer;
|
|
806
|
+
consumerBindings[`${name}Binding`] = entry.binding;
|
|
807
|
+
} else processedConsumers[name] = entry;
|
|
808
|
+
result.consumers = processedConsumers;
|
|
809
|
+
if (Object.keys(consumerBindings).length > 0) result.bindings = {
|
|
810
|
+
...result.bindings,
|
|
811
|
+
...consumerBindings
|
|
504
812
|
};
|
|
505
813
|
}
|
|
506
|
-
|
|
507
|
-
return callDefinePublisher(exchange, message, options);
|
|
508
|
-
};
|
|
509
|
-
return {
|
|
510
|
-
consumer,
|
|
511
|
-
binding,
|
|
512
|
-
createPublisher
|
|
513
|
-
};
|
|
814
|
+
return result;
|
|
514
815
|
}
|
|
816
|
+
|
|
817
|
+
//#endregion
|
|
818
|
+
//#region src/builder/ttl-backoff.ts
|
|
515
819
|
/**
|
|
516
820
|
* Create TTL-backoff retry infrastructure for a queue.
|
|
517
821
|
*
|
|
@@ -577,11 +881,11 @@ function defineTtlBackoffRetryInfrastructure(queueEntry, options) {
|
|
|
577
881
|
});
|
|
578
882
|
return {
|
|
579
883
|
waitQueue,
|
|
580
|
-
waitQueueBinding:
|
|
581
|
-
mainQueueRetryBinding:
|
|
884
|
+
waitQueueBinding: defineQueueBindingInternal(waitQueue, dlx, { routingKey: waitQueueName }),
|
|
885
|
+
mainQueueRetryBinding: defineQueueBindingInternal(queue, dlx, { routingKey: queue.name })
|
|
582
886
|
};
|
|
583
887
|
}
|
|
584
888
|
|
|
585
889
|
//#endregion
|
|
586
|
-
export {
|
|
890
|
+
export { defineCommandConsumer, defineCommandPublisher, defineConsumer, defineContract, defineEventConsumer, defineEventPublisher, defineExchange, defineExchangeBinding, defineMessage, definePublisher, defineQueue, defineQueueBinding, defineQuorumQueue, defineTtlBackoffQueue, defineTtlBackoffRetryInfrastructure, extractQueue, isCommandConsumerConfig, isEventConsumerResult, isEventPublisherConfig, isQueueWithTtlBackoffInfrastructure };
|
|
587
891
|
//# sourceMappingURL=index.mjs.map
|