@amqp-contract/contract 0.10.0 → 0.12.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/dist/index.d.cts CHANGED
@@ -12,6 +12,90 @@ import { StandardSchemaV1 } from "@standard-schema/spec";
12
12
  * @see https://github.com/standard-schema/standard-schema
13
13
  */
14
14
  type AnySchema = StandardSchemaV1;
15
+ /**
16
+ * TTL-Backoff retry options for exponential backoff with configurable delays.
17
+ *
18
+ * Uses TTL + wait queue pattern. Messages are published to a wait queue with
19
+ * per-message TTL, then dead-lettered back to the main queue after the TTL expires.
20
+ *
21
+ * **Benefits:** Configurable delays with exponential backoff and jitter.
22
+ * **Limitation:** More complex, potential head-of-queue blocking with mixed TTLs.
23
+ */
24
+ type TtlBackoffRetryOptions = {
25
+ /**
26
+ * TTL-Backoff mode uses wait queues with per-message TTL for exponential backoff.
27
+ */
28
+ mode: "ttl-backoff";
29
+ /**
30
+ * Maximum retry attempts before sending to DLQ.
31
+ * @default 3
32
+ */
33
+ maxRetries?: number;
34
+ /**
35
+ * Initial delay in ms before first retry.
36
+ * @default 1000
37
+ */
38
+ initialDelayMs?: number;
39
+ /**
40
+ * Maximum delay in ms between retries.
41
+ * @default 30000
42
+ */
43
+ maxDelayMs?: number;
44
+ /**
45
+ * Exponential backoff multiplier.
46
+ * @default 2
47
+ */
48
+ backoffMultiplier?: number;
49
+ /**
50
+ * Add jitter to prevent thundering herd.
51
+ * @default true
52
+ */
53
+ jitter?: boolean;
54
+ };
55
+ /**
56
+ * Quorum-Native retry options using RabbitMQ's native delivery limit feature.
57
+ *
58
+ * Uses quorum queue's `x-delivery-limit` feature. Messages are requeued immediately
59
+ * with `nack(requeue=true)`, and RabbitMQ tracks delivery count via `x-delivery-count`
60
+ * header. When the count exceeds the queue's `deliveryLimit`, the message is
61
+ * automatically dead-lettered.
62
+ *
63
+ * **Benefits:** Simpler architecture, no wait queues needed, no head-of-queue blocking.
64
+ * **Limitation:** Immediate retries only (no exponential backoff).
65
+ *
66
+ * @see https://www.rabbitmq.com/docs/quorum-queues#poison-message-handling
67
+ */
68
+ type QuorumNativeRetryOptions = {
69
+ /**
70
+ * Quorum-Native mode uses RabbitMQ's native delivery limit feature.
71
+ * Requires the queue to be a quorum queue with `deliveryLimit` configured.
72
+ */
73
+ mode: "quorum-native";
74
+ };
75
+ /**
76
+ * Resolved TTL-Backoff retry options with all defaults applied.
77
+ *
78
+ * This type is used internally in queue definitions after `defineQueue` has applied
79
+ * default values. All fields are required.
80
+ *
81
+ * @internal
82
+ */
83
+ type ResolvedTtlBackoffRetryOptions = {
84
+ mode: "ttl-backoff";
85
+ maxRetries: number;
86
+ initialDelayMs: number;
87
+ maxDelayMs: number;
88
+ backoffMultiplier: number;
89
+ jitter: boolean;
90
+ };
91
+ /**
92
+ * Resolved retry configuration stored in queue definitions.
93
+ *
94
+ * This is a discriminated union based on the `mode` field:
95
+ * - `ttl-backoff`: Has all TTL-backoff options with defaults applied
96
+ * - `quorum-native`: No additional options (uses RabbitMQ native retry)
97
+ */
98
+ type ResolvedRetryOptions = ResolvedTtlBackoffRetryOptions | QuorumNativeRetryOptions;
15
99
  /**
16
100
  * Supported compression algorithms for message payloads.
17
101
  *
@@ -41,6 +125,225 @@ type AnySchema = StandardSchemaV1;
41
125
  * ```
42
126
  */
43
127
  type CompressionAlgorithm = "gzip" | "deflate";
128
+ /**
129
+ * Supported queue types in RabbitMQ.
130
+ *
131
+ * - `quorum`: Quorum queues (default, recommended) - Provide better durability and high-availability
132
+ * using the Raft consensus algorithm. Best for most production use cases.
133
+ * - `classic`: Classic queues - The traditional RabbitMQ queue type. Use only when you need
134
+ * specific features not supported by quorum queues (e.g., non-durable queues, priority queues).
135
+ *
136
+ * Note: Quorum queues require `durable: true` and do not support `exclusive: true`.
137
+ * When using quorum queues, `durable` is automatically set to `true`.
138
+ *
139
+ * @see https://www.rabbitmq.com/docs/quorum-queues
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * // Create a quorum queue (default, recommended)
144
+ * const orderQueue = defineQueue('order-processing', {
145
+ * type: 'quorum', // This is the default
146
+ * });
147
+ *
148
+ * // Create a classic queue (for special cases)
149
+ * const tempQueue = defineQueue('temp-queue', {
150
+ * type: 'classic',
151
+ * durable: false, // Only supported with classic queues
152
+ * });
153
+ * ```
154
+ */
155
+ type QueueType = "quorum" | "classic";
156
+ /**
157
+ * Common queue options shared between quorum and classic queues.
158
+ */
159
+ type BaseQueueOptions = {
160
+ /**
161
+ * If true, the queue survives broker restarts. Durable queues are persisted to disk.
162
+ * Note: Quorum queues are always durable regardless of this setting.
163
+ * @default false (but forced to true for quorum queues during setup)
164
+ */
165
+ durable?: boolean;
166
+ /**
167
+ * If true, the queue is deleted when the last consumer unsubscribes.
168
+ * @default false
169
+ */
170
+ autoDelete?: boolean;
171
+ /**
172
+ * Dead letter configuration for handling failed or rejected messages.
173
+ */
174
+ deadLetter?: DeadLetterConfig;
175
+ /**
176
+ * Additional AMQP arguments for advanced configuration.
177
+ */
178
+ arguments?: Record<string, unknown>;
179
+ };
180
+ /**
181
+ * Options for creating a quorum queue.
182
+ *
183
+ * Quorum queues do not support:
184
+ * - `exclusive` - Use classic queues for exclusive access
185
+ * - `maxPriority` - Use classic queues for priority queues
186
+ *
187
+ * Quorum queues provide native retry support via `deliveryLimit`:
188
+ * - RabbitMQ tracks delivery count automatically via `x-delivery-count` header
189
+ * - When the limit is exceeded, messages are dead-lettered (if DLX is configured)
190
+ * - This is simpler than TTL-based retry and avoids head-of-queue blocking issues
191
+ *
192
+ * @example
193
+ * ```typescript
194
+ * const orderQueue = defineQueue('orders', {
195
+ * type: 'quorum',
196
+ * deadLetter: { exchange: dlx },
197
+ * deliveryLimit: 3, // Message dead-lettered after 3 delivery attempts
198
+ * });
199
+ * ```
200
+ */
201
+ type QuorumQueueOptions = BaseQueueOptions & {
202
+ /**
203
+ * Queue type: quorum (default, recommended)
204
+ */
205
+ type?: "quorum";
206
+ /**
207
+ * Quorum queues do not support exclusive mode.
208
+ * Use type: 'classic' if you need exclusive queues.
209
+ */
210
+ exclusive?: never;
211
+ /**
212
+ * Quorum queues do not support priority queues.
213
+ * Use type: 'classic' if you need priority queues.
214
+ */
215
+ maxPriority?: never;
216
+ /**
217
+ * Maximum number of delivery attempts before the message is dead-lettered.
218
+ *
219
+ * When a message is rejected (nacked) and requeued, RabbitMQ increments
220
+ * the `x-delivery-count` header. When this count reaches the delivery limit,
221
+ * the message is automatically dead-lettered (if DLX is configured) or dropped.
222
+ *
223
+ * This is a quorum queue-specific feature that provides native retry handling
224
+ * without the complexity of TTL-based wait queues.
225
+ *
226
+ * **Benefits over TTL-based retry:**
227
+ * - Simpler architecture (no wait queues needed)
228
+ * - No head-of-queue blocking issues (TTL only works at queue head)
229
+ * - Native RabbitMQ feature with atomic guarantees
230
+ *
231
+ * @minimum 1 - Must be a positive integer (1 or greater)
232
+ *
233
+ * @see https://www.rabbitmq.com/docs/quorum-queues#poison-message-handling
234
+ *
235
+ * @example
236
+ * ```typescript
237
+ * const orderQueue = defineQueue('order-processing', {
238
+ * type: 'quorum',
239
+ * deliveryLimit: 5, // Allow up to 5 delivery attempts
240
+ * deadLetter: {
241
+ * exchange: dlx,
242
+ * routingKey: 'order.failed',
243
+ * },
244
+ * });
245
+ * ```
246
+ */
247
+ deliveryLimit?: number;
248
+ /**
249
+ * Retry configuration for handling failed message processing.
250
+ *
251
+ * Determines how the worker handles retries for consumers using this queue:
252
+ * - `"ttl-backoff"` (default): Uses wait queues with exponential backoff
253
+ * - `"quorum-native"`: Uses RabbitMQ's native delivery limit feature
254
+ *
255
+ * When using `"ttl-backoff"` mode, the core package will automatically create
256
+ * a wait queue (`{queueName}-wait`) and the necessary bindings.
257
+ *
258
+ * @example
259
+ * ```typescript
260
+ * // TTL-backoff mode with custom options
261
+ * const orderQueue = defineQueue('order-processing', {
262
+ * type: 'quorum',
263
+ * deadLetter: { exchange: dlx },
264
+ * retry: {
265
+ * mode: 'ttl-backoff',
266
+ * maxRetries: 5,
267
+ * initialDelayMs: 1000,
268
+ * maxDelayMs: 30000,
269
+ * },
270
+ * });
271
+ *
272
+ * // Quorum-native mode
273
+ * const orderQueue = defineQueue('order-processing', {
274
+ * type: 'quorum',
275
+ * deliveryLimit: 5,
276
+ * deadLetter: { exchange: dlx },
277
+ * retry: { mode: 'quorum-native' },
278
+ * });
279
+ * ```
280
+ */
281
+ retry?: TtlBackoffRetryOptions | QuorumNativeRetryOptions;
282
+ };
283
+ /**
284
+ * Options for creating a classic queue.
285
+ *
286
+ * Classic queues support all traditional RabbitMQ features including:
287
+ * - `exclusive: true` - For connection-scoped queues
288
+ * - `maxPriority` - For priority queues
289
+ * - `durable: false` - For non-durable queues
290
+ *
291
+ * @example
292
+ * ```typescript
293
+ * const priorityQueue = defineQueue('tasks', {
294
+ * type: 'classic',
295
+ * durable: true,
296
+ * maxPriority: 10,
297
+ * });
298
+ * ```
299
+ */
300
+ type ClassicQueueOptions = BaseQueueOptions & {
301
+ /**
302
+ * Queue type: classic (for special cases)
303
+ */
304
+ type: "classic";
305
+ /**
306
+ * If true, the queue can only be used by the declaring connection and is deleted when
307
+ * that connection closes. Exclusive queues are private to the connection.
308
+ * @default false
309
+ */
310
+ exclusive?: boolean;
311
+ /**
312
+ * Maximum priority level for priority queue (1-255, recommended: 1-10).
313
+ * Sets x-max-priority argument.
314
+ * Only supported with classic queues.
315
+ */
316
+ maxPriority?: number;
317
+ /**
318
+ * Retry configuration for handling failed message processing.
319
+ *
320
+ * Classic queues only support TTL-backoff retry mode, which uses wait queues
321
+ * with exponential backoff. For quorum-native retry, use quorum queues instead.
322
+ *
323
+ * @example
324
+ * ```typescript
325
+ * const orderQueue = defineQueue('order-processing', {
326
+ * type: 'classic',
327
+ * durable: true,
328
+ * deadLetter: { exchange: dlx },
329
+ * retry: {
330
+ * maxRetries: 5,
331
+ * initialDelayMs: 1000,
332
+ * maxDelayMs: 30000,
333
+ * },
334
+ * });
335
+ * ```
336
+ */
337
+ retry?: TtlBackoffRetryOptions;
338
+ };
339
+ /**
340
+ * Options for defining a queue. Uses a discriminated union based on the `type` property
341
+ * to enforce quorum queue constraints at compile time.
342
+ *
343
+ * - Quorum queues (default): Do not support `exclusive` or `maxPriority`
344
+ * - Classic queues: Support all options including `exclusive` and `maxPriority`
345
+ */
346
+ type DefineQueueOptions = QuorumQueueOptions | ClassicQueueOptions;
44
347
  /**
45
348
  * Base definition of an AMQP exchange.
46
349
  *
@@ -152,27 +455,19 @@ type DeadLetterConfig = {
152
455
  routingKey?: string;
153
456
  };
154
457
  /**
155
- * Definition of an AMQP queue.
156
- *
157
- * A queue stores messages until they are consumed by workers. Queues are bound to exchanges
158
- * to receive messages based on routing rules.
458
+ * Common properties shared by all queue definitions.
159
459
  */
160
- type QueueDefinition = {
460
+ type BaseQueueDefinition = {
161
461
  /**
162
462
  * The name of the queue. Must be unique within the RabbitMQ virtual host.
163
463
  */
164
464
  name: string;
165
465
  /**
166
466
  * If true, the queue survives broker restarts. Durable queues are persisted to disk.
167
- * @default false
467
+ * Note: Quorum queues are always durable regardless of this setting.
468
+ * @default false (but forced to true for quorum queues during setup)
168
469
  */
169
470
  durable?: boolean;
170
- /**
171
- * If true, the queue can only be used by the declaring connection and is deleted when
172
- * that connection closes. Exclusive queues are private to the connection.
173
- * @default false
174
- */
175
- exclusive?: boolean;
176
471
  /**
177
472
  * If true, the queue is deleted when the last consumer unsubscribes.
178
473
  * @default false
@@ -183,18 +478,6 @@ type QueueDefinition = {
183
478
  *
184
479
  * When configured, messages that are rejected, expire, or exceed queue limits
185
480
  * will be automatically forwarded to the specified dead letter exchange.
186
- *
187
- * @example
188
- * ```typescript
189
- * const dlx = defineExchange('orders-dlx', 'topic', { durable: true });
190
- * const queue = defineQueue('order-processing', {
191
- * durable: true,
192
- * deadLetter: {
193
- * exchange: dlx,
194
- * routingKey: 'order.failed'
195
- * }
196
- * });
197
- * ```
198
481
  */
199
482
  deadLetter?: DeadLetterConfig;
200
483
  /**
@@ -205,22 +488,146 @@ type QueueDefinition = {
205
488
  * - `x-expires`: Queue expiration time in milliseconds
206
489
  * - `x-max-length`: Maximum number of messages in the queue
207
490
  * - `x-max-length-bytes`: Maximum size of the queue in bytes
208
- * - `x-max-priority`: Maximum priority level for priority queues
491
+ */
492
+ arguments?: Record<string, unknown>;
493
+ };
494
+ /**
495
+ * Definition of a quorum queue.
496
+ *
497
+ * Quorum queues provide better durability and high-availability using the Raft consensus algorithm.
498
+ * They support native retry handling via `deliveryLimit` and both TTL-backoff and quorum-native retry modes.
499
+ */
500
+ type QuorumQueueDefinition = BaseQueueDefinition & {
501
+ /**
502
+ * Queue type discriminator: quorum queue.
503
+ */
504
+ type: "quorum";
505
+ /**
506
+ * Quorum queues do not support exclusive mode.
507
+ * Use type: 'classic' if you need exclusive queues.
508
+ */
509
+ exclusive?: never;
510
+ /**
511
+ * Quorum queues do not support priority queues.
512
+ * Use type: 'classic' if you need priority queues.
513
+ */
514
+ maxPriority?: never;
515
+ /**
516
+ * Maximum number of delivery attempts before the message is dead-lettered.
209
517
  *
210
- * Note: When using the `deadLetter` property, the `x-dead-letter-exchange` and
211
- * `x-dead-letter-routing-key` arguments are automatically set and should not be
212
- * specified in this arguments object.
518
+ * This is a quorum queue-specific feature. When a message is rejected (nacked)
519
+ * and requeued, RabbitMQ increments the `x-delivery-count` header. When this
520
+ * count reaches the delivery limit, the message is automatically dead-lettered
521
+ * (if DLX is configured) or dropped.
213
522
  *
214
- * @example
215
- * ```typescript
216
- * {
217
- * 'x-message-ttl': 86400000, // 24 hours
218
- * 'x-max-priority': 10
219
- * }
220
- * ```
523
+ * @minimum 1 - Must be a positive integer (1 or greater)
524
+ *
525
+ * @see https://www.rabbitmq.com/docs/quorum-queues#poison-message-handling
221
526
  */
222
- arguments?: Record<string, unknown>;
527
+ deliveryLimit?: number;
528
+ /**
529
+ * Retry configuration for handling failed message processing.
530
+ *
531
+ * Quorum queues support both:
532
+ * - `ttl-backoff`: Uses wait queues with exponential backoff (default)
533
+ * - `quorum-native`: Uses RabbitMQ's native delivery limit feature
534
+ *
535
+ * When the queue is created, defaults are applied for TTL-backoff options.
536
+ */
537
+ retry: ResolvedRetryOptions;
538
+ };
539
+ /**
540
+ * Definition of a classic queue.
541
+ *
542
+ * Classic queues are the traditional RabbitMQ queue type. Use them when you need
543
+ * specific features not supported by quorum queues (e.g., exclusive queues, priority queues).
544
+ */
545
+ type ClassicQueueDefinition = BaseQueueDefinition & {
546
+ /**
547
+ * Queue type discriminator: classic queue.
548
+ */
549
+ type: "classic";
550
+ /**
551
+ * Classic queues do not support delivery limits.
552
+ * Use type: 'quorum' if you need native retry with delivery limits.
553
+ */
554
+ deliveryLimit?: never;
555
+ /**
556
+ * If true, the queue can only be used by the declaring connection and is deleted when
557
+ * that connection closes. Exclusive queues are private to the connection.
558
+ * @default false
559
+ */
560
+ exclusive?: boolean;
561
+ /**
562
+ * Retry configuration for handling failed message processing.
563
+ *
564
+ * Classic queues only support TTL-backoff retry mode (default).
565
+ * When the queue is created, defaults are applied.
566
+ */
567
+ retry: ResolvedTtlBackoffRetryOptions;
568
+ };
569
+ /**
570
+ * Definition of an AMQP queue.
571
+ *
572
+ * A discriminated union based on queue type:
573
+ * - `QuorumQueueDefinition`: For quorum queues (type: "quorum")
574
+ * - `ClassicQueueDefinition`: For classic queues (type: "classic")
575
+ *
576
+ * Use `queue.type` as the discriminator to narrow the type.
577
+ */
578
+ type QueueDefinition = QuorumQueueDefinition | ClassicQueueDefinition;
579
+ /**
580
+ * A queue with automatically generated TTL-backoff retry infrastructure.
581
+ *
582
+ * This type is returned by `defineQueue` when TTL-backoff retry is configured
583
+ * with a dead letter exchange. When passed to `defineContract`, the wait queue
584
+ * and bindings are automatically added to the contract.
585
+ *
586
+ * @example
587
+ * ```typescript
588
+ * const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
589
+ * const queue = defineQueue('order-processing', {
590
+ * deadLetter: { exchange: dlx },
591
+ * retry: { mode: 'ttl-backoff', maxRetries: 5 },
592
+ * });
593
+ * // queue is QueueWithTtlBackoffInfrastructure
594
+ *
595
+ * const contract = defineContract({
596
+ * exchanges: { dlx },
597
+ * queues: { orderProcessing: queue }, // Automatically adds wait queue
598
+ * // ... bindings are automatically generated
599
+ * });
600
+ * ```
601
+ */
602
+ type QueueWithTtlBackoffInfrastructure = {
603
+ /**
604
+ * Discriminator to identify this as a queue with TTL-backoff infrastructure.
605
+ * @internal
606
+ */
607
+ __brand: "QueueWithTtlBackoffInfrastructure";
608
+ /**
609
+ * The main queue definition.
610
+ */
611
+ queue: QueueDefinition;
612
+ /**
613
+ * The wait queue for holding messages during backoff delay.
614
+ */
615
+ waitQueue: QueueDefinition;
616
+ /**
617
+ * Binding that routes failed messages to the wait queue.
618
+ */
619
+ waitQueueBinding: QueueBindingDefinition;
620
+ /**
621
+ * Binding that routes retried messages back to the main queue.
622
+ */
623
+ mainQueueRetryBinding: QueueBindingDefinition;
223
624
  };
625
+ /**
626
+ * A queue entry that can be passed to `defineContract`.
627
+ *
628
+ * Can be either a plain queue definition or a queue with TTL-backoff infrastructure.
629
+ */
630
+ type QueueEntry = QueueDefinition | QueueWithTtlBackoffInfrastructure;
224
631
  /**
225
632
  * Definition of a message with typed payload and optional headers.
226
633
  *
@@ -432,8 +839,11 @@ type ContractDefinition = {
432
839
  /**
433
840
  * Named queue definitions.
434
841
  * Each key becomes available as a named resource in the contract.
842
+ *
843
+ * When a queue has TTL-backoff retry configured, pass the `QueueWithTtlBackoffInfrastructure`
844
+ * object returned by `defineQueue`. The wait queue and bindings will be automatically added.
435
845
  */
436
- queues?: Record<string, QueueDefinition>;
846
+ queues?: Record<string, QueueEntry>;
437
847
  /**
438
848
  * Named binding definitions.
439
849
  * Bindings can be queue-to-exchange or exchange-to-exchange.
@@ -485,7 +895,7 @@ type InferPublisherNames<TContract extends ContractDefinition> = TContract["publ
485
895
  */
486
896
  type InferConsumerNames<TContract extends ContractDefinition> = TContract["consumers"] extends Record<string, unknown> ? keyof TContract["consumers"] : never;
487
897
  //#endregion
488
- //#region src/builder.d.ts
898
+ //#region src/builder/exchange.d.ts
489
899
  /**
490
900
  * Define a fanout exchange.
491
901
  *
@@ -556,52 +966,8 @@ declare function defineExchange(name: string, type: "direct", options?: Omit<Bas
556
966
  * ```
557
967
  */
558
968
  declare function defineExchange(name: string, type: "topic", options?: Omit<BaseExchangeDefinition, "name" | "type">): TopicExchangeDefinition;
559
- /**
560
- * Define an AMQP queue.
561
- *
562
- * A queue stores messages until they are consumed by workers. Queues can be bound to exchanges
563
- * to receive messages based on routing rules.
564
- *
565
- * @param name - The name of the queue
566
- * @param options - Optional queue configuration
567
- * @param options.durable - If true, the queue survives broker restarts (default: false)
568
- * @param options.exclusive - If true, the queue can only be used by the declaring connection (default: false)
569
- * @param options.autoDelete - If true, the queue is deleted when the last consumer unsubscribes (default: false)
570
- * @param options.deadLetter - Dead letter configuration for handling failed messages
571
- * @param options.maxPriority - Maximum priority level for priority queue (1-255, recommended: 1-10). Sets x-max-priority argument.
572
- * @param options.arguments - Additional AMQP arguments (e.g., x-message-ttl)
573
- * @returns A queue definition
574
- *
575
- * @example
576
- * ```typescript
577
- * // Basic queue
578
- * const orderQueue = defineQueue('order-processing', {
579
- * durable: true,
580
- * });
581
- *
582
- * // Priority queue with max priority of 10
583
- * const taskQueue = defineQueue('urgent-tasks', {
584
- * durable: true,
585
- * maxPriority: 10,
586
- * });
587
- *
588
- * // Queue with dead letter exchange
589
- * const dlx = defineExchange('orders-dlx', 'topic', { durable: true });
590
- * const orderQueueWithDLX = defineQueue('order-processing', {
591
- * durable: true,
592
- * deadLetter: {
593
- * exchange: dlx,
594
- * routingKey: 'order.failed'
595
- * },
596
- * arguments: {
597
- * 'x-message-ttl': 86400000, // 24 hours
598
- * }
599
- * });
600
- * ```
601
- */
602
- declare function defineQueue(name: string, options?: Omit<QueueDefinition, "name"> & {
603
- maxPriority?: number;
604
- }): QueueDefinition;
969
+ //#endregion
970
+ //#region src/builder/message.d.ts
605
971
  /**
606
972
  * Define a message definition with payload and optional headers/metadata.
607
973
  *
@@ -642,13 +1008,95 @@ declare function defineMessage<TPayload extends MessageDefinition["payload"], TH
642
1008
  summary?: string;
643
1009
  description?: string;
644
1010
  }): MessageDefinition<TPayload, THeaders>;
1011
+ //#endregion
1012
+ //#region src/builder/queue.d.ts
1013
+ /**
1014
+ * Extract the plain QueueDefinition from a QueueEntry.
1015
+ * If the entry is a QueueWithTtlBackoffInfrastructure, returns the inner queue.
1016
+ * Otherwise, returns the entry as-is.
1017
+ *
1018
+ * @param entry - The queue entry (either plain QueueDefinition or QueueWithTtlBackoffInfrastructure)
1019
+ * @returns The plain QueueDefinition
1020
+ *
1021
+ * @example
1022
+ * ```typescript
1023
+ * const queue = defineQueue('orders', { retry: { mode: 'ttl-backoff' }, deadLetter: { exchange: dlx } });
1024
+ * const plainQueue = extractQueue(queue); // Returns the inner QueueDefinition
1025
+ * ```
1026
+ */
1027
+ declare function extractQueue(entry: QueueEntry): QueueDefinition;
1028
+ /**
1029
+ * Define an AMQP queue.
1030
+ *
1031
+ * A queue stores messages until they are consumed by workers. Queues can be bound to exchanges
1032
+ * to receive messages based on routing rules.
1033
+ *
1034
+ * By default, queues are created as quorum queues which provide better durability and
1035
+ * high-availability. Use `type: 'classic'` for special cases like non-durable queues
1036
+ * or priority queues.
1037
+ *
1038
+ * @param name - The name of the queue
1039
+ * @param options - Optional queue configuration
1040
+ * @param options.type - Queue type: 'quorum' (default, recommended) or 'classic'
1041
+ * @param options.durable - If true, the queue survives broker restarts. Quorum queues are always durable.
1042
+ * @param options.exclusive - If true, the queue can only be used by the declaring connection. Only supported with classic queues.
1043
+ * @param options.autoDelete - If true, the queue is deleted when the last consumer unsubscribes (default: false)
1044
+ * @param options.deadLetter - Dead letter configuration for handling failed messages
1045
+ * @param options.maxPriority - Maximum priority level for priority queue (1-255, recommended: 1-10). Only supported with classic queues.
1046
+ * @param options.arguments - Additional AMQP arguments (e.g., x-message-ttl)
1047
+ * @returns A queue definition
1048
+ *
1049
+ * @example
1050
+ * ```typescript
1051
+ * // Quorum queue (default, recommended for production)
1052
+ * const orderQueue = defineQueue('order-processing');
1053
+ *
1054
+ * // Explicit quorum queue with dead letter exchange
1055
+ * const dlx = defineExchange('orders-dlx', 'topic', { durable: true });
1056
+ * const orderQueueWithDLX = defineQueue('order-processing', {
1057
+ * type: 'quorum',
1058
+ * deadLetter: {
1059
+ * exchange: dlx,
1060
+ * routingKey: 'order.failed'
1061
+ * },
1062
+ * arguments: {
1063
+ * 'x-message-ttl': 86400000, // 24 hours
1064
+ * }
1065
+ * });
1066
+ *
1067
+ * // Classic queue (for special cases)
1068
+ * const tempQueue = defineQueue('temp-queue', {
1069
+ * type: 'classic',
1070
+ * durable: false,
1071
+ * autoDelete: true,
1072
+ * });
1073
+ *
1074
+ * // Priority queue (requires classic type)
1075
+ * const taskQueue = defineQueue('urgent-tasks', {
1076
+ * type: 'classic',
1077
+ * durable: true,
1078
+ * maxPriority: 10,
1079
+ * });
1080
+ *
1081
+ * // Queue with TTL-backoff retry (returns infrastructure automatically)
1082
+ * const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
1083
+ * const orderQueue = defineQueue('order-processing', {
1084
+ * deadLetter: { exchange: dlx },
1085
+ * retry: { mode: 'ttl-backoff', maxRetries: 5 },
1086
+ * });
1087
+ * // orderQueue is QueueWithTtlBackoffInfrastructure, pass directly to defineContract
1088
+ * ```
1089
+ */
1090
+ declare function defineQueue(name: string, options?: DefineQueueOptions): QueueDefinition | QueueWithTtlBackoffInfrastructure;
1091
+ //#endregion
1092
+ //#region src/builder/binding.d.ts
645
1093
  /**
646
1094
  * Define a binding between a queue and a fanout exchange.
647
1095
  *
648
1096
  * Binds a queue to a fanout exchange to receive all messages published to the exchange.
649
1097
  * Fanout exchanges ignore routing keys, so this overload doesn't require one.
650
1098
  *
651
- * @param queue - The queue definition to bind
1099
+ * @param queue - The queue definition or queue with infrastructure to bind
652
1100
  * @param exchange - The fanout exchange definition
653
1101
  * @param options - Optional binding configuration
654
1102
  * @param options.arguments - Additional AMQP arguments for the binding
@@ -662,7 +1110,7 @@ declare function defineMessage<TPayload extends MessageDefinition["payload"], TH
662
1110
  * const binding = defineQueueBinding(logsQueue, logsExchange);
663
1111
  * ```
664
1112
  */
665
- declare function defineQueueBinding(queue: QueueDefinition, exchange: FanoutExchangeDefinition, options?: Omit<Extract<QueueBindingDefinition, {
1113
+ declare function defineQueueBinding(queue: QueueEntry, exchange: FanoutExchangeDefinition, options?: Omit<Extract<QueueBindingDefinition, {
666
1114
  exchange: FanoutExchangeDefinition;
667
1115
  }>, "type" | "queue" | "exchange" | "routingKey">): Extract<QueueBindingDefinition, {
668
1116
  exchange: FanoutExchangeDefinition;
@@ -678,7 +1126,7 @@ declare function defineQueueBinding(queue: QueueDefinition, exchange: FanoutExch
678
1126
  * - `*` matches exactly one word
679
1127
  * - `#` matches zero or more words
680
1128
  *
681
- * @param queue - The queue definition to bind
1129
+ * @param queue - The queue definition or queue with infrastructure to bind
682
1130
  * @param exchange - The direct or topic exchange definition
683
1131
  * @param options - Binding configuration (routingKey is required)
684
1132
  * @param options.routingKey - The routing key pattern for message routing
@@ -701,7 +1149,7 @@ declare function defineQueueBinding(queue: QueueDefinition, exchange: FanoutExch
701
1149
  * });
702
1150
  * ```
703
1151
  */
704
- declare function defineQueueBinding(queue: QueueDefinition, exchange: DirectExchangeDefinition | TopicExchangeDefinition, options: Omit<Extract<QueueBindingDefinition, {
1152
+ declare function defineQueueBinding(queue: QueueEntry, exchange: DirectExchangeDefinition | TopicExchangeDefinition, options: Omit<Extract<QueueBindingDefinition, {
705
1153
  exchange: DirectExchangeDefinition | TopicExchangeDefinition;
706
1154
  }>, "type" | "queue" | "exchange">): Extract<QueueBindingDefinition, {
707
1155
  exchange: DirectExchangeDefinition | TopicExchangeDefinition;
@@ -761,6 +1209,8 @@ declare function defineExchangeBinding(destination: ExchangeDefinition, source:
761
1209
  }>, "type" | "source" | "destination">): Extract<ExchangeBindingDefinition, {
762
1210
  source: DirectExchangeDefinition | TopicExchangeDefinition;
763
1211
  }>;
1212
+ //#endregion
1213
+ //#region src/builder/publisher.d.ts
764
1214
  /**
765
1215
  * Define a message publisher for a fanout exchange.
766
1216
  *
@@ -835,6 +1285,8 @@ declare function definePublisher<TMessage extends MessageDefinition>(exchange: D
835
1285
  }>, "exchange" | "message">): Extract<PublisherDefinition<TMessage>, {
836
1286
  exchange: DirectExchangeDefinition | TopicExchangeDefinition;
837
1287
  }>;
1288
+ //#endregion
1289
+ //#region src/builder/consumer.d.ts
838
1290
  /**
839
1291
  * Define a message consumer.
840
1292
  *
@@ -877,7 +1329,9 @@ declare function definePublisher<TMessage extends MessageDefinition>(exchange: D
877
1329
  * // });
878
1330
  * ```
879
1331
  */
880
- declare function defineConsumer<TMessage extends MessageDefinition>(queue: QueueDefinition, message: TMessage, options?: Omit<ConsumerDefinition<TMessage>, "queue" | "message">): ConsumerDefinition<TMessage>;
1332
+ declare function defineConsumer<TMessage extends MessageDefinition>(queue: QueueEntry, message: TMessage, options?: Omit<ConsumerDefinition<TMessage>, "queue" | "message">): ConsumerDefinition<TMessage>;
1333
+ //#endregion
1334
+ //#region src/builder/contract.d.ts
881
1335
  /**
882
1336
  * Define an AMQP contract.
883
1337
  *
@@ -948,34 +1402,8 @@ declare function defineConsumer<TMessage extends MessageDefinition>(queue: Queue
948
1402
  * ```
949
1403
  */
950
1404
  declare function defineContract<TContract extends ContractDefinition>(definition: TContract): TContract;
951
- /**
952
- * Publisher-first builder result for fanout and direct exchanges.
953
- *
954
- * This type represents a publisher and provides a method to create
955
- * a consumer that uses the same message schema with a binding to the exchange.
956
- *
957
- * This pattern is suitable for event-oriented messaging where publishers
958
- * emit events without knowing which queues will consume them.
959
- *
960
- * @template TMessage - The message definition
961
- * @template TPublisher - The publisher definition
962
- */
963
- type PublisherFirstResult<TMessage extends MessageDefinition, TPublisher extends PublisherDefinition<TMessage>> = {
964
- /** The publisher definition */
965
- publisher: TPublisher;
966
- /**
967
- * Create a consumer that receives messages from this publisher.
968
- * The consumer will automatically use the same message schema and
969
- * a binding will be created with the same routing key.
970
- *
971
- * @param queue - The queue that will consume the messages
972
- * @returns An object with the consumer definition and binding
973
- */
974
- createConsumer: (queue: QueueDefinition) => {
975
- consumer: ConsumerDefinition<TMessage>;
976
- binding: QueueBindingDefinition;
977
- };
978
- };
1405
+ //#endregion
1406
+ //#region src/builder/routing-types.d.ts
979
1407
  /**
980
1408
  * Type-safe routing key that validates basic format.
981
1409
  *
@@ -1052,6 +1480,36 @@ type MatchesPattern<Key extends string, Pattern extends string> = Pattern extend
1052
1480
  * @template Key - The routing key to validate
1053
1481
  */
1054
1482
  type MatchingRoutingKey<Pattern extends string, Key extends string> = RoutingKey<Key> extends never ? never : BindingPattern<Pattern> extends never ? never : MatchesPattern<Key, Pattern> extends true ? Key : never;
1483
+ //#endregion
1484
+ //#region src/builder/publisher-first.d.ts
1485
+ /**
1486
+ * Publisher-first builder result for fanout and direct exchanges.
1487
+ *
1488
+ * This type represents a publisher and provides a method to create
1489
+ * a consumer that uses the same message schema with a binding to the exchange.
1490
+ *
1491
+ * This pattern is suitable for event-oriented messaging where publishers
1492
+ * emit events without knowing which queues will consume them.
1493
+ *
1494
+ * @template TMessage - The message definition
1495
+ * @template TPublisher - The publisher definition
1496
+ */
1497
+ type PublisherFirstResult<TMessage extends MessageDefinition, TPublisher extends PublisherDefinition<TMessage>> = {
1498
+ /** The publisher definition */
1499
+ publisher: TPublisher;
1500
+ /**
1501
+ * Create a consumer that receives messages from this publisher.
1502
+ * The consumer will automatically use the same message schema and
1503
+ * a binding will be created with the same routing key.
1504
+ *
1505
+ * @param queue - The queue (or queue with infrastructure) that will consume the messages
1506
+ * @returns An object with the consumer definition and binding
1507
+ */
1508
+ createConsumer: (queue: QueueEntry) => {
1509
+ consumer: ConsumerDefinition<TMessage>;
1510
+ binding: QueueBindingDefinition;
1511
+ };
1512
+ };
1055
1513
  /**
1056
1514
  * Publisher-first builder result for topic exchanges.
1057
1515
  *
@@ -1069,11 +1527,11 @@ type PublisherFirstResultWithRoutingKey<TMessage extends MessageDefinition, TPub
1069
1527
  * Create a consumer that receives messages from this publisher.
1070
1528
  * For topic exchanges, the routing key pattern can be specified for the binding.
1071
1529
  *
1072
- * @param queue - The queue that will consume the messages
1530
+ * @param queue - The queue (or queue with infrastructure) that will consume the messages
1073
1531
  * @param routingKey - Optional routing key pattern for the binding (defaults to publisher's routing key)
1074
1532
  * @returns An object with the consumer definition and binding
1075
1533
  */
1076
- createConsumer: <TConsumerRoutingKey extends string = TRoutingKey>(queue: QueueDefinition, routingKey?: BindingPattern<TConsumerRoutingKey>) => {
1534
+ createConsumer: <TConsumerRoutingKey extends string = TRoutingKey>(queue: QueueEntry, routingKey?: BindingPattern<TConsumerRoutingKey>) => {
1077
1535
  consumer: ConsumerDefinition<TMessage>;
1078
1536
  binding: QueueBindingDefinition;
1079
1537
  };
@@ -1257,6 +1715,8 @@ declare function definePublisherFirst<TMessage extends MessageDefinition, TRouti
1257
1715
  }): PublisherFirstResultWithRoutingKey<TMessage, Extract<PublisherDefinition<TMessage>, {
1258
1716
  exchange: DirectExchangeDefinition | TopicExchangeDefinition;
1259
1717
  }>, TRoutingKey>;
1718
+ //#endregion
1719
+ //#region src/builder/consumer-first.d.ts
1260
1720
  /**
1261
1721
  * Consumer-first builder result for fanout and direct exchanges.
1262
1722
  *
@@ -1357,7 +1817,7 @@ type ConsumerFirstResultWithRoutingKey<TMessage extends MessageDefinition, TCons
1357
1817
  * });
1358
1818
  * ```
1359
1819
  */
1360
- declare function defineConsumerFirst<TMessage extends MessageDefinition>(queue: QueueDefinition, exchange: FanoutExchangeDefinition, message: TMessage, options?: Omit<Extract<QueueBindingDefinition, {
1820
+ declare function defineConsumerFirst<TMessage extends MessageDefinition>(queue: QueueEntry, exchange: FanoutExchangeDefinition, message: TMessage, options?: Omit<Extract<QueueBindingDefinition, {
1361
1821
  exchange: FanoutExchangeDefinition;
1362
1822
  }>, "type" | "queue" | "exchange" | "routingKey">): ConsumerFirstResult<TMessage, ConsumerDefinition<TMessage>, Extract<QueueBindingDefinition, {
1363
1823
  exchange: FanoutExchangeDefinition;
@@ -1411,7 +1871,7 @@ declare function defineConsumerFirst<TMessage extends MessageDefinition>(queue:
1411
1871
  * });
1412
1872
  * ```
1413
1873
  */
1414
- declare function defineConsumerFirst<TMessage extends MessageDefinition, TRoutingKey extends string>(queue: QueueDefinition, exchange: DirectExchangeDefinition, message: TMessage, options: {
1874
+ declare function defineConsumerFirst<TMessage extends MessageDefinition, TRoutingKey extends string>(queue: QueueEntry, exchange: DirectExchangeDefinition, message: TMessage, options: {
1415
1875
  routingKey: RoutingKey<TRoutingKey>;
1416
1876
  arguments?: Record<string, unknown>;
1417
1877
  }): ConsumerFirstResult<TMessage, ConsumerDefinition<TMessage>, Extract<QueueBindingDefinition, {
@@ -1469,12 +1929,87 @@ declare function defineConsumerFirst<TMessage extends MessageDefinition, TRoutin
1469
1929
  * });
1470
1930
  * ```
1471
1931
  */
1472
- declare function defineConsumerFirst<TMessage extends MessageDefinition, TRoutingKey extends string>(queue: QueueDefinition, exchange: TopicExchangeDefinition, message: TMessage, options: {
1932
+ declare function defineConsumerFirst<TMessage extends MessageDefinition, TRoutingKey extends string>(queue: QueueEntry, exchange: TopicExchangeDefinition, message: TMessage, options: {
1473
1933
  routingKey: BindingPattern<TRoutingKey>;
1474
1934
  arguments?: Record<string, unknown>;
1475
1935
  }): ConsumerFirstResultWithRoutingKey<TMessage, ConsumerDefinition<TMessage>, Extract<QueueBindingDefinition, {
1476
1936
  exchange: TopicExchangeDefinition;
1477
1937
  }>>;
1478
1938
  //#endregion
1479
- export { type AnySchema, type BaseExchangeDefinition, type BindingDefinition, type BindingPattern, type CompressionAlgorithm, type ConsumerDefinition, type ConsumerFirstResult, type ConsumerFirstResultWithRoutingKey, type ContractDefinition, type DeadLetterConfig, type DirectExchangeDefinition, type ExchangeBindingDefinition, type ExchangeDefinition, type FanoutExchangeDefinition, type InferConsumerNames, type InferPublisherNames, type MatchingRoutingKey, type MessageDefinition, type PublisherDefinition, type PublisherFirstResult, type PublisherFirstResultWithRoutingKey, type QueueBindingDefinition, type QueueDefinition, type RoutingKey, type TopicExchangeDefinition, defineConsumer, defineConsumerFirst, defineContract, defineExchange, defineExchangeBinding, defineMessage, definePublisher, definePublisherFirst, defineQueue, defineQueueBinding };
1939
+ //#region src/builder/ttl-backoff.d.ts
1940
+ /**
1941
+ * Result type for TTL-backoff retry infrastructure builder.
1942
+ *
1943
+ * Contains the wait queue and bindings needed for TTL-backoff retry.
1944
+ */
1945
+ type TtlBackoffRetryInfrastructure = {
1946
+ /**
1947
+ * The wait queue for holding messages during backoff delay.
1948
+ * This is a classic queue with a dead letter exchange pointing back to the main queue.
1949
+ */
1950
+ waitQueue: QueueDefinition;
1951
+ /**
1952
+ * Binding that routes failed messages to the wait queue.
1953
+ */
1954
+ waitQueueBinding: QueueBindingDefinition;
1955
+ /**
1956
+ * Binding that routes retried messages back to the main queue.
1957
+ */
1958
+ mainQueueRetryBinding: QueueBindingDefinition;
1959
+ };
1960
+ /**
1961
+ * Create TTL-backoff retry infrastructure for a queue.
1962
+ *
1963
+ * This builder helper generates the wait queue and bindings needed for TTL-backoff retry.
1964
+ * The generated infrastructure can be spread into a contract definition.
1965
+ *
1966
+ * TTL-backoff retry works by:
1967
+ * 1. Failed messages are sent to the DLX with routing key `{queueName}-wait`
1968
+ * 2. The wait queue receives these messages and holds them for a TTL period
1969
+ * 3. After TTL expires, messages are dead-lettered back to the DLX with routing key `{queueName}`
1970
+ * 4. The main queue receives the retried message via its binding to the DLX
1971
+ *
1972
+ * @param queue - The main queue definition (must have deadLetter configured)
1973
+ * @param options - Optional configuration for the wait queue
1974
+ * @param options.waitQueueDurable - Whether the wait queue should be durable (default: same as main queue)
1975
+ * @returns TTL-backoff retry infrastructure containing wait queue and bindings
1976
+ * @throws {Error} If the queue does not have a dead letter exchange configured
1977
+ *
1978
+ * @example
1979
+ * ```typescript
1980
+ * const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
1981
+ * const orderQueue = defineQueue('order-processing', {
1982
+ * type: 'quorum',
1983
+ * deadLetter: { exchange: dlx },
1984
+ * retry: {
1985
+ * mode: 'ttl-backoff',
1986
+ * maxRetries: 5,
1987
+ * initialDelayMs: 1000,
1988
+ * },
1989
+ * });
1990
+ *
1991
+ * // Generate TTL-backoff infrastructure
1992
+ * const retryInfra = defineTtlBackoffRetryInfrastructure(orderQueue);
1993
+ *
1994
+ * // Spread into contract
1995
+ * const contract = defineContract({
1996
+ * exchanges: { dlx },
1997
+ * queues: {
1998
+ * orderProcessing: orderQueue,
1999
+ * orderProcessingWait: retryInfra.waitQueue,
2000
+ * },
2001
+ * bindings: {
2002
+ * ...// your other bindings
2003
+ * orderWaitBinding: retryInfra.waitQueueBinding,
2004
+ * orderRetryBinding: retryInfra.mainQueueRetryBinding,
2005
+ * },
2006
+ * // ... publishers and consumers
2007
+ * });
2008
+ * ```
2009
+ */
2010
+ declare function defineTtlBackoffRetryInfrastructure(queueEntry: QueueEntry, options?: {
2011
+ waitQueueDurable?: boolean;
2012
+ }): TtlBackoffRetryInfrastructure;
2013
+ //#endregion
2014
+ export { type AnySchema, type BaseExchangeDefinition, type BindingDefinition, type BindingPattern, type ClassicQueueDefinition, type ClassicQueueOptions, type CompressionAlgorithm, type ConsumerDefinition, type ConsumerFirstResult, type ConsumerFirstResultWithRoutingKey, type ContractDefinition, type DeadLetterConfig, type DefineQueueOptions, type DirectExchangeDefinition, type ExchangeBindingDefinition, type ExchangeDefinition, type FanoutExchangeDefinition, type InferConsumerNames, type InferPublisherNames, type MatchingRoutingKey, type MessageDefinition, type PublisherDefinition, type PublisherFirstResult, type PublisherFirstResultWithRoutingKey, type QueueBindingDefinition, type QueueDefinition, type QueueEntry, type QueueType, type QueueWithTtlBackoffInfrastructure, type QuorumNativeRetryOptions, type QuorumQueueDefinition, type QuorumQueueOptions, type ResolvedRetryOptions, type ResolvedTtlBackoffRetryOptions, type RoutingKey, type TopicExchangeDefinition, type TtlBackoffRetryInfrastructure, type TtlBackoffRetryOptions, defineConsumer, defineConsumerFirst, defineContract, defineExchange, defineExchangeBinding, defineMessage, definePublisher, definePublisherFirst, defineQueue, defineQueueBinding, defineTtlBackoffRetryInfrastructure, extractQueue };
1480
2015
  //# sourceMappingURL=index.d.cts.map