@amqp-contract/contract 0.20.0 → 0.21.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
@@ -27,6 +27,7 @@ type TtlBackoffRetryOptions = {
27
27
  mode: "ttl-backoff";
28
28
  /**
29
29
  * Maximum retry attempts before sending to DLQ.
30
+ * @minimum 1 - Must be a positive integer (1 or greater)
30
31
  * @default 3
31
32
  */
32
33
  maxRetries?: number;
@@ -50,27 +51,66 @@ type TtlBackoffRetryOptions = {
50
51
  * @default true
51
52
  */
52
53
  jitter?: boolean;
54
+ /**
55
+ * Name of the wait queue.
56
+ * @default '{queueName}-wait'
57
+ */
58
+ waitQueueName?: string;
59
+ /**
60
+ * Name of the wait exchange.
61
+ * @default 'wait-exchange'
62
+ */
63
+ waitExchangeName?: string;
64
+ /**
65
+ * Name of the retry exchange.
66
+ * @default 'retry-exchange'
67
+ */
68
+ retryExchangeName?: string;
53
69
  };
54
70
  /**
55
- * Quorum-Native retry options using RabbitMQ's native delivery limit feature.
71
+ * Immediate-Requeue retry options.
56
72
  *
57
- * Uses quorum queue's `x-delivery-limit` feature. Messages are requeued immediately
58
- * with `nack(requeue=true)`, and RabbitMQ tracks delivery count via `x-delivery-count`
59
- * header. When the count exceeds the queue's `deliveryLimit`, the message is
60
- * automatically dead-lettered.
73
+ * Failed messages are requeued immediately.
74
+ * For quorum queues, messages are requeued with `nack(requeue=true)`, and the worker tracks delivery count via the native RabbitMQ `x-delivery-count` header.
75
+ * For classic queues, messages are re-published on the same queue, and the worker tracks delivery count via a custom `x-retry-count` header.
76
+ * When the count exceeds `maxRetries`, the message is automatically dead-lettered (if DLX is configured) or dropped.
61
77
  *
62
78
  * **Benefits:** Simpler architecture, no wait queues needed, no head-of-queue blocking.
63
79
  * **Limitation:** Immediate retries only (no exponential backoff).
64
80
  *
65
81
  * @see https://www.rabbitmq.com/docs/quorum-queues#poison-message-handling
66
82
  */
67
- type QuorumNativeRetryOptions = {
83
+ type ImmediateRequeueRetryOptions = {
84
+ /**
85
+ * Immediate-Requeue mode.
86
+ */
87
+ mode: "immediate-requeue";
88
+ /**
89
+ * Maximum retry attempts before sending to DLQ.
90
+ * @minimum 1 - Must be a positive integer (1 or greater)
91
+ * @default 3
92
+ */
93
+ maxRetries?: number;
94
+ };
95
+ /**
96
+ * No retry mode. Failed messages are not retried and are sent
97
+ * directly to DLQ (if configured) or rejected.
98
+ */
99
+ type NoneRetryOptions = {
68
100
  /**
69
- * Quorum-Native mode uses RabbitMQ's native delivery limit feature.
70
- * Requires the queue to be a quorum queue with `deliveryLimit` configured.
101
+ * None mode disables retry attempts entirely.
71
102
  */
72
- mode: "quorum-native";
103
+ mode: "none";
73
104
  };
105
+ /**
106
+ * Retry configuration options.
107
+ *
108
+ * This is a discriminated union based on the `mode` field:
109
+ * - `none` (default): No retry attempts are made; failed messages are handled by DLQ/reject
110
+ * - `immediate-requeue`: Requeues failed messages immediately
111
+ * - `ttl-backoff`: Uses wait queues with exponential backoff
112
+ */
113
+ type RetryOptions = NoneRetryOptions | ImmediateRequeueRetryOptions | TtlBackoffRetryOptions;
74
114
  /**
75
115
  * Resolved TTL-Backoff retry options with all defaults applied.
76
116
  *
@@ -86,15 +126,34 @@ type ResolvedTtlBackoffRetryOptions = {
86
126
  maxDelayMs: number;
87
127
  backoffMultiplier: number;
88
128
  jitter: boolean;
129
+ waitQueueName: string;
130
+ waitExchangeName: string;
131
+ retryExchangeName: string;
132
+ };
133
+ /**
134
+ * Resolved Immediate-Requeue retry options with all defaults applied.
135
+ *
136
+ * This type is used internally in queue definitions after `defineQueue` has applied
137
+ * default values. All fields are required.
138
+ *
139
+ * @internal
140
+ */
141
+ type ResolvedImmediateRequeueRetryOptions = {
142
+ mode: "immediate-requeue";
143
+ maxRetries: number;
89
144
  };
90
145
  /**
91
146
  * Resolved retry configuration stored in queue definitions.
92
147
  *
93
148
  * This is a discriminated union based on the `mode` field:
94
- * - `ttl-backoff`: Has all TTL-backoff options with defaults applied
95
- * - `quorum-native`: No additional options (uses RabbitMQ native retry)
149
+ * - `none`: No retry attempts are made; failed messages are handled by DLQ/reject
150
+ * - `immediate-requeue`: Has all immediate-requeue retry options with default applied
151
+ * - `ttl-backoff`: Has all TTL-backoff retry options with defaults applied
152
+ *
153
+ * When using `ttl-backoff` mode, the core package will automatically create
154
+ * a wait queue and the necessary exchanges and bindings.
96
155
  */
97
- type ResolvedRetryOptions = ResolvedTtlBackoffRetryOptions | QuorumNativeRetryOptions;
156
+ type ResolvedRetryOptions = NoneRetryOptions | ResolvedImmediateRequeueRetryOptions | ResolvedTtlBackoffRetryOptions;
98
157
  /**
99
158
  * Supported compression algorithms for message payloads.
100
159
  *
@@ -132,8 +191,7 @@ type CompressionAlgorithm = "gzip" | "deflate";
132
191
  * - `classic`: Classic queues - The traditional RabbitMQ queue type. Use only when you need
133
192
  * specific features not supported by quorum queues (e.g., non-durable queues, priority queues).
134
193
  *
135
- * Note: Quorum queues require `durable: true` and do not support `exclusive: true`.
136
- * When using quorum queues, `durable` is automatically set to `true`.
194
+ * Note: Quorum queues only support durable queues, and do not support exclusive, auto-deleting, or priority queues.
137
195
  *
138
196
  * @see https://www.rabbitmq.com/docs/quorum-queues
139
197
  *
@@ -156,21 +214,37 @@ type QueueType = "quorum" | "classic";
156
214
  * Common queue options shared between quorum and classic queues.
157
215
  */
158
216
  type BaseQueueOptions = {
159
- /**
160
- * If true, the queue survives broker restarts. Durable queues are persisted to disk.
161
- * Note: Quorum queues are always durable regardless of this setting.
162
- * @default false (but forced to true for quorum queues during setup)
163
- */
164
- durable?: boolean;
165
- /**
166
- * If true, the queue is deleted when the last consumer unsubscribes.
167
- * @default false
168
- */
169
- autoDelete?: boolean;
170
217
  /**
171
218
  * Dead letter configuration for handling failed or rejected messages.
172
219
  */
173
220
  deadLetter?: DeadLetterConfig;
221
+ /**
222
+ * Retry configuration for handling failed message processing.
223
+ *
224
+ * @example
225
+ * ```typescript
226
+ * // No retry
227
+ * const orderQueue = defineQueue('order-processing', {
228
+ * retry: { mode: 'none' },
229
+ * });
230
+ *
231
+ * // Immediate-requeue mode
232
+ * const orderQueue = defineQueue('order-processing', {
233
+ * retry: { mode: 'immediate-requeue', maxRetries: 5 },
234
+ * });
235
+ *
236
+ * // TTL-backoff mode with custom options
237
+ * const orderQueue = defineQueue('order-processing', {
238
+ * retry: {
239
+ * mode: 'ttl-backoff',
240
+ * maxRetries: 5,
241
+ * initialDelayMs: 1000,
242
+ * maxDelayMs: 30000,
243
+ * },
244
+ * });
245
+ * ```
246
+ */
247
+ retry?: RetryOptions;
174
248
  /**
175
249
  * Additional AMQP arguments for advanced configuration.
176
250
  */
@@ -180,12 +254,14 @@ type BaseQueueOptions = {
180
254
  * Options for creating a quorum queue.
181
255
  *
182
256
  * Quorum queues do not support:
183
- * - `exclusive` - Use classic queues for exclusive access
257
+ * - `exclusive` - Use classic queues for connection-scoped queues
258
+ * - `autoDelete` - Use classic queues for auto-deleting queues when consumers disconnect
184
259
  * - `maxPriority` - Use classic queues for priority queues
260
+ * - `durable: false` - Use classic queues for non-durable queues
185
261
  *
186
- * Quorum queues provide native retry support via `deliveryLimit`:
262
+ * Quorum queues provide native retry support for immediate-requeue retry mode:
187
263
  * - RabbitMQ tracks delivery count automatically via `x-delivery-count` header
188
- * - When the limit is exceeded, messages are dead-lettered (if DLX is configured)
264
+ * - When the limit is exceeded, messages are dead-lettered (if DLX is configured) or dropped
189
265
  * - This is simpler than TTL-based retry and avoids head-of-queue blocking issues
190
266
  *
191
267
  * @example
@@ -193,7 +269,7 @@ type BaseQueueOptions = {
193
269
  * const orderQueue = defineQueue('orders', {
194
270
  * type: 'quorum',
195
271
  * deadLetter: { exchange: dlx },
196
- * deliveryLimit: 3, // Message dead-lettered after 3 delivery attempts
272
+ * retry: { mode: 'immediate-requeue', maxRetries: 3 } // Message dead-lettered after 3 retry attempts
197
273
  * });
198
274
  * ```
199
275
  */
@@ -202,88 +278,32 @@ type QuorumQueueOptions = BaseQueueOptions & {
202
278
  * Queue type: quorum (default, recommended)
203
279
  */
204
280
  type?: "quorum";
281
+ /**
282
+ * Quorum queues only support durable queues.
283
+ */
284
+ durable?: true;
205
285
  /**
206
286
  * Quorum queues do not support exclusive mode.
207
287
  * Use type: 'classic' if you need exclusive queues.
208
288
  */
209
289
  exclusive?: never;
290
+ /**
291
+ * Quorum queues do not support auto-delete mode.
292
+ * Use type: 'classic' if you need auto-deleting queues.
293
+ */
294
+ autoDelete?: never;
210
295
  /**
211
296
  * Quorum queues do not support priority queues.
212
297
  * Use type: 'classic' if you need priority queues.
213
298
  */
214
299
  maxPriority?: never;
215
- /**
216
- * Maximum number of delivery attempts before the message is dead-lettered.
217
- *
218
- * When a message is rejected (nacked) and requeued, RabbitMQ increments
219
- * the `x-delivery-count` header. When this count reaches the delivery limit,
220
- * the message is automatically dead-lettered (if DLX is configured) or dropped.
221
- *
222
- * This is a quorum queue-specific feature that provides native retry handling
223
- * without the complexity of TTL-based wait queues.
224
- *
225
- * **Benefits over TTL-based retry:**
226
- * - Simpler architecture (no wait queues needed)
227
- * - No head-of-queue blocking issues (TTL only works at queue head)
228
- * - Native RabbitMQ feature with atomic guarantees
229
- *
230
- * @minimum 1 - Must be a positive integer (1 or greater)
231
- *
232
- * @see https://www.rabbitmq.com/docs/quorum-queues#poison-message-handling
233
- *
234
- * @example
235
- * ```typescript
236
- * const orderQueue = defineQueue('order-processing', {
237
- * type: 'quorum',
238
- * deliveryLimit: 5, // Allow up to 5 delivery attempts
239
- * deadLetter: {
240
- * exchange: dlx,
241
- * routingKey: 'order.failed',
242
- * },
243
- * });
244
- * ```
245
- */
246
- deliveryLimit?: number;
247
- /**
248
- * Retry configuration for handling failed message processing.
249
- *
250
- * Determines how the worker handles retries for consumers using this queue:
251
- * - `"ttl-backoff"` (default): Uses wait queues with exponential backoff
252
- * - `"quorum-native"`: Uses RabbitMQ's native delivery limit feature
253
- *
254
- * When using `"ttl-backoff"` mode, the core package will automatically create
255
- * a wait queue (`{queueName}-wait`) and the necessary bindings.
256
- *
257
- * @example
258
- * ```typescript
259
- * // TTL-backoff mode with custom options
260
- * const orderQueue = defineQueue('order-processing', {
261
- * type: 'quorum',
262
- * deadLetter: { exchange: dlx },
263
- * retry: {
264
- * mode: 'ttl-backoff',
265
- * maxRetries: 5,
266
- * initialDelayMs: 1000,
267
- * maxDelayMs: 30000,
268
- * },
269
- * });
270
- *
271
- * // Quorum-native mode
272
- * const orderQueue = defineQueue('order-processing', {
273
- * type: 'quorum',
274
- * deliveryLimit: 5,
275
- * deadLetter: { exchange: dlx },
276
- * retry: { mode: 'quorum-native' },
277
- * });
278
- * ```
279
- */
280
- retry?: TtlBackoffRetryOptions | QuorumNativeRetryOptions;
281
300
  };
282
301
  /**
283
302
  * Options for creating a classic queue.
284
303
  *
285
304
  * Classic queues support all traditional RabbitMQ features including:
286
- * - `exclusive: true` - For connection-scoped queues
305
+ * - `exclusive` - For connection-scoped queues
306
+ * - `autoDelete` - For auto-deleting queues when consumers disconnect
287
307
  * - `maxPriority` - For priority queues
288
308
  * - `durable: false` - For non-durable queues
289
309
  *
@@ -291,7 +311,6 @@ type QuorumQueueOptions = BaseQueueOptions & {
291
311
  * ```typescript
292
312
  * const priorityQueue = defineQueue('tasks', {
293
313
  * type: 'classic',
294
- * durable: true,
295
314
  * maxPriority: 10,
296
315
  * });
297
316
  * ```
@@ -301,48 +320,42 @@ type ClassicQueueOptions = BaseQueueOptions & {
301
320
  * Queue type: classic (for special cases)
302
321
  */
303
322
  type: "classic";
323
+ /**
324
+ * If true, the queue survives broker restarts. Durable queues are persisted to disk.
325
+ * @default true
326
+ */
327
+ durable?: boolean;
304
328
  /**
305
329
  * If true, the queue can only be used by the declaring connection and is deleted when
306
330
  * that connection closes. Exclusive queues are private to the connection.
307
- * @default false
308
331
  */
309
332
  exclusive?: boolean;
333
+ /**
334
+ * If true, the queue is deleted when the last consumer unsubscribes.
335
+ */
336
+ autoDelete?: boolean;
310
337
  /**
311
338
  * Maximum priority level for priority queue (1-255, recommended: 1-10).
312
339
  * Sets x-max-priority argument.
313
- * Only supported with classic queues.
314
340
  */
315
341
  maxPriority?: number;
316
- /**
317
- * Retry configuration for handling failed message processing.
318
- *
319
- * Classic queues only support TTL-backoff retry mode, which uses wait queues
320
- * with exponential backoff. For quorum-native retry, use quorum queues instead.
321
- *
322
- * @example
323
- * ```typescript
324
- * const orderQueue = defineQueue('order-processing', {
325
- * type: 'classic',
326
- * durable: true,
327
- * deadLetter: { exchange: dlx },
328
- * retry: {
329
- * maxRetries: 5,
330
- * initialDelayMs: 1000,
331
- * maxDelayMs: 30000,
332
- * },
333
- * });
334
- * ```
335
- */
336
- retry?: TtlBackoffRetryOptions;
337
342
  };
338
343
  /**
339
344
  * Options for defining a queue. Uses a discriminated union based on the `type` property
340
345
  * to enforce quorum queue constraints at compile time.
341
346
  *
342
- * - Quorum queues (default): Do not support `exclusive` or `maxPriority`
343
- * - Classic queues: Support all options including `exclusive` and `maxPriority`
347
+ * - Quorum queues (default): Do not support `exclusive`, `autoDelete`, or `maxPriority`
348
+ * - Classic queues: Support all options including `exclusive`, `autoDelete`, and `maxPriority`
344
349
  */
345
350
  type DefineQueueOptions = QuorumQueueOptions | ClassicQueueOptions;
351
+ /**
352
+ * Options for defining a queue with a dead letter exchange.
353
+ */
354
+ type DefineQueueOptionsWithDeadLetterExchange<TDlx extends ExchangeDefinition = ExchangeDefinition> = DefineQueueOptions & {
355
+ deadLetter: {
356
+ exchange: TDlx;
357
+ };
358
+ };
346
359
  /**
347
360
  * Base definition of an AMQP exchange.
348
361
  *
@@ -356,18 +369,16 @@ type BaseExchangeDefinition<TName extends string = string> = {
356
369
  name: TName;
357
370
  /**
358
371
  * If true, the exchange survives broker restarts. Durable exchanges are persisted to disk.
359
- * @default false
372
+ * @default true
360
373
  */
361
374
  durable?: boolean;
362
375
  /**
363
376
  * If true, the exchange is deleted when all queues have finished using it.
364
- * @default false
365
377
  */
366
378
  autoDelete?: boolean;
367
379
  /**
368
380
  * If true, the exchange cannot be directly published to by clients.
369
381
  * It can only receive messages from other exchanges via exchange-to-exchange bindings.
370
- * @default false
371
382
  */
372
383
  internal?: boolean;
373
384
  /**
@@ -377,20 +388,24 @@ type BaseExchangeDefinition<TName extends string = string> = {
377
388
  arguments?: Record<string, unknown>;
378
389
  };
379
390
  /**
380
- * A fanout exchange definition.
391
+ * A topic exchange definition.
381
392
  *
382
- * Fanout exchanges broadcast all messages to all bound queues, ignoring routing keys.
383
- * This is the simplest exchange type for pub/sub messaging patterns.
393
+ * Topic exchanges route messages to queues based on routing key patterns with wildcards:
394
+ * - `*` (star) matches exactly one word
395
+ * - `#` (hash) matches zero or more words
396
+ *
397
+ * Words are separated by dots (e.g., `order.created.high-value`).
384
398
  *
385
399
  * @example
386
400
  * ```typescript
387
- * const logsExchange: FanoutExchangeDefinition = defineExchange('logs', 'fanout', {
388
- * durable: true
401
+ * const ordersExchange: TopicExchangeDefinition = defineExchange('orders', {
402
+ * type: 'topic', // This is the default type, so it can be omitted
389
403
  * });
404
+ * // Can be bound with patterns like 'order.*' or 'order.#'
390
405
  * ```
391
406
  */
392
- type FanoutExchangeDefinition<TName extends string = string> = BaseExchangeDefinition<TName> & {
393
- type: "fanout";
407
+ type TopicExchangeDefinition<TName extends string = string> = BaseExchangeDefinition<TName> & {
408
+ type: "topic";
394
409
  };
395
410
  /**
396
411
  * A direct exchange definition.
@@ -400,8 +415,8 @@ type FanoutExchangeDefinition<TName extends string = string> = BaseExchangeDefin
400
415
  *
401
416
  * @example
402
417
  * ```typescript
403
- * const tasksExchange: DirectExchangeDefinition = defineExchange('tasks', 'direct', {
404
- * durable: true
418
+ * const tasksExchange: DirectExchangeDefinition = defineExchange('tasks', {
419
+ * type: 'direct',
405
420
  * });
406
421
  * ```
407
422
  */
@@ -409,31 +424,43 @@ type DirectExchangeDefinition<TName extends string = string> = BaseExchangeDefin
409
424
  type: "direct";
410
425
  };
411
426
  /**
412
- * A topic exchange definition.
427
+ * A fanout exchange definition.
413
428
  *
414
- * Topic exchanges route messages to queues based on routing key patterns with wildcards:
415
- * - `*` (star) matches exactly one word
416
- * - `#` (hash) matches zero or more words
429
+ * Fanout exchanges broadcast all messages to all bound queues, ignoring routing keys.
430
+ * This is the simplest exchange type for pub/sub messaging patterns.
417
431
  *
418
- * Words are separated by dots (e.g., `order.created.high-value`).
432
+ * @example
433
+ * ```typescript
434
+ * const logsExchange: FanoutExchangeDefinition = defineExchange('logs', {
435
+ * type: 'fanout',
436
+ * });
437
+ * ```
438
+ */
439
+ type FanoutExchangeDefinition<TName extends string = string> = BaseExchangeDefinition<TName> & {
440
+ type: "fanout";
441
+ };
442
+ /**
443
+ * A headers exchange definition.
444
+ *
445
+ * Headers exchanges route messages based on header values rather than routing keys.
446
+ * This is useful for more complex routing scenarios where metadata is important.
419
447
  *
420
448
  * @example
421
449
  * ```typescript
422
- * const ordersExchange: TopicExchangeDefinition = defineExchange('orders', 'topic', {
423
- * durable: true
450
+ * const routesExchange: HeadersExchangeDefinition = defineExchange('routes', {
451
+ * type: 'headers',
424
452
  * });
425
- * // Can be bound with patterns like 'order.*' or 'order.#'
426
453
  * ```
427
454
  */
428
- type TopicExchangeDefinition<TName extends string = string> = BaseExchangeDefinition<TName> & {
429
- type: "topic";
455
+ type HeadersExchangeDefinition<TName extends string = string> = BaseExchangeDefinition<TName> & {
456
+ type: "headers";
430
457
  };
431
458
  /**
432
459
  * Union type of all exchange definitions.
433
460
  *
434
- * Represents any type of AMQP exchange: fanout, direct, or topic.
461
+ * Represents any type of AMQP exchange: topic, direct, fanout, headers.
435
462
  */
436
- type ExchangeDefinition<TName extends string = string> = FanoutExchangeDefinition<TName> | DirectExchangeDefinition<TName> | TopicExchangeDefinition<TName>;
463
+ type ExchangeDefinition<TName extends string = string> = TopicExchangeDefinition<TName> | DirectExchangeDefinition<TName> | FanoutExchangeDefinition<TName> | HeadersExchangeDefinition<TName>;
437
464
  /**
438
465
  * Configuration for dead letter exchange (DLX) on a queue.
439
466
  *
@@ -461,17 +488,6 @@ type BaseQueueDefinition<TName extends string = string> = {
461
488
  * The name of the queue. Must be unique within the RabbitMQ virtual host.
462
489
  */
463
490
  name: TName;
464
- /**
465
- * If true, the queue survives broker restarts. Durable queues are persisted to disk.
466
- * Note: Quorum queues are always durable regardless of this setting.
467
- * @default false (but forced to true for quorum queues during setup)
468
- */
469
- durable?: boolean;
470
- /**
471
- * If true, the queue is deleted when the last consumer unsubscribes.
472
- * @default false
473
- */
474
- autoDelete?: boolean;
475
491
  /**
476
492
  * Dead letter configuration for handling failed or rejected messages.
477
493
  *
@@ -479,6 +495,11 @@ type BaseQueueDefinition<TName extends string = string> = {
479
495
  * will be automatically forwarded to the specified dead letter exchange.
480
496
  */
481
497
  deadLetter?: DeadLetterConfig;
498
+ /**
499
+ * Retry configuration for handling failed message processing.
500
+ * When the queue is created, defaults are applied.
501
+ */
502
+ retry: ResolvedRetryOptions;
482
503
  /**
483
504
  * Additional AMQP arguments for advanced configuration.
484
505
  *
@@ -494,52 +515,37 @@ type BaseQueueDefinition<TName extends string = string> = {
494
515
  * Definition of a quorum queue.
495
516
  *
496
517
  * Quorum queues provide better durability and high-availability using the Raft consensus algorithm.
497
- * They support native retry handling via `deliveryLimit` and both TTL-backoff and quorum-native retry modes.
498
518
  */
499
519
  type QuorumQueueDefinition<TName extends string = string> = BaseQueueDefinition<TName> & {
500
520
  /**
501
521
  * Queue type discriminator: quorum queue.
502
522
  */
503
523
  type: "quorum";
524
+ /**
525
+ * Quorum queues only support durable queues.
526
+ */
527
+ durable: true;
504
528
  /**
505
529
  * Quorum queues do not support exclusive mode.
506
530
  * Use type: 'classic' if you need exclusive queues.
507
531
  */
508
532
  exclusive?: never;
533
+ /**
534
+ * Quorum queues do not support auto-delete mode.
535
+ * Use type: 'classic' if you need auto-deleting queues.
536
+ */
537
+ autoDelete?: never;
509
538
  /**
510
539
  * Quorum queues do not support priority queues.
511
540
  * Use type: 'classic' if you need priority queues.
512
541
  */
513
542
  maxPriority?: never;
514
- /**
515
- * Maximum number of delivery attempts before the message is dead-lettered.
516
- *
517
- * This is a quorum queue-specific feature. When a message is rejected (nacked)
518
- * and requeued, RabbitMQ increments the `x-delivery-count` header. When this
519
- * count reaches the delivery limit, the message is automatically dead-lettered
520
- * (if DLX is configured) or dropped.
521
- *
522
- * @minimum 1 - Must be a positive integer (1 or greater)
523
- *
524
- * @see https://www.rabbitmq.com/docs/quorum-queues#poison-message-handling
525
- */
526
- deliveryLimit?: number;
527
- /**
528
- * Retry configuration for handling failed message processing.
529
- *
530
- * Quorum queues support both:
531
- * - `ttl-backoff`: Uses wait queues with exponential backoff (default)
532
- * - `quorum-native`: Uses RabbitMQ's native delivery limit feature
533
- *
534
- * When the queue is created, defaults are applied for TTL-backoff options.
535
- */
536
- retry: ResolvedRetryOptions;
537
543
  };
538
544
  /**
539
545
  * Definition of a classic queue.
540
546
  *
541
547
  * Classic queues are the traditional RabbitMQ queue type. Use them when you need
542
- * specific features not supported by quorum queues (e.g., exclusive queues, priority queues).
548
+ * specific features not supported by quorum queues (e.g., exclusive queues, auto-deleting queues, priority queues).
543
549
  */
544
550
  type ClassicQueueDefinition<TName extends string = string> = BaseQueueDefinition<TName> & {
545
551
  /**
@@ -547,23 +553,23 @@ type ClassicQueueDefinition<TName extends string = string> = BaseQueueDefinition
547
553
  */
548
554
  type: "classic";
549
555
  /**
550
- * Classic queues do not support delivery limits.
551
- * Use type: 'quorum' if you need native retry with delivery limits.
556
+ * If true, the queue survives broker restarts. Durable queues are persisted to disk.
552
557
  */
553
- deliveryLimit?: never;
558
+ durable: boolean;
554
559
  /**
555
560
  * If true, the queue can only be used by the declaring connection and is deleted when
556
561
  * that connection closes. Exclusive queues are private to the connection.
557
- * @default false
558
562
  */
559
563
  exclusive?: boolean;
560
564
  /**
561
- * Retry configuration for handling failed message processing.
562
- *
563
- * Classic queues only support TTL-backoff retry mode (default).
564
- * When the queue is created, defaults are applied.
565
+ * If true, the queue is deleted when the last consumer unsubscribes.
566
+ */
567
+ autoDelete?: boolean;
568
+ /**
569
+ * Maximum priority level for priority queue (1-255, recommended: 1-10).
570
+ * Sets x-max-priority argument.
565
571
  */
566
- retry: ResolvedTtlBackoffRetryOptions;
572
+ maxPriority?: number;
567
573
  };
568
574
  /**
569
575
  * Definition of an AMQP queue.
@@ -578,26 +584,24 @@ type QueueDefinition<TName extends string = string> = QuorumQueueDefinition<TNam
578
584
  /**
579
585
  * A queue with automatically generated TTL-backoff retry infrastructure.
580
586
  *
581
- * This type is returned by `defineQueue` when TTL-backoff retry is configured
582
- * with a dead letter exchange. When passed to `defineContract`, the wait queue
583
- * and bindings are automatically added to the contract.
587
+ * This type is returned by `defineQueue` when TTL-backoff retry is configured.
588
+ * When passed to `defineContract`, the wait queue, exchanges, and bindings are
589
+ * automatically added to the contract.
584
590
  *
585
591
  * @example
586
592
  * ```typescript
587
- * const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
588
- * const exchange = defineExchange('orders', 'topic', { durable: true });
593
+ * const exchange = defineExchange('orders');
589
594
  * const queue = defineQueue('order-processing', {
590
- * deadLetter: { exchange: dlx },
591
595
  * retry: { mode: 'ttl-backoff', maxRetries: 5 },
592
596
  * });
593
597
  * // queue is QueueWithTtlBackoffInfrastructure
594
598
  * const message = defineMessage(z.object({ orderId: z.string() }));
595
599
  * const orderCreated = defineEventPublisher(exchange, message, { routingKey: 'order.created' });
596
600
  *
597
- * // Wait queue, bindings, and DLX exchange are automatically extracted
601
+ * // Wait queue, exchanges, and bindings are automatically extracted
598
602
  * const contract = defineContract({
599
603
  * publishers: { orderCreated },
600
- * consumers: { processOrder: defineEventConsumer(orderCreated, extractQueue(queue)) },
604
+ * consumers: { processOrder: defineEventConsumer(orderCreated, queue) },
601
605
  * });
602
606
  * ```
603
607
  */
@@ -611,23 +615,26 @@ type QueueWithTtlBackoffInfrastructure<TName extends string = string> = {
611
615
  * The main queue definition.
612
616
  */
613
617
  queue: QueueDefinition<TName>;
614
- /**
615
- * Dead letter configuration from the main queue.
616
- * Always present since TTL-backoff infrastructure requires a dead letter exchange.
617
- */
618
- deadLetter: DeadLetterConfig;
619
618
  /**
620
619
  * The wait queue for holding messages during backoff delay.
621
620
  */
622
621
  waitQueue: QueueDefinition;
622
+ /**
623
+ * Wait exchange used to route failed messages to the wait queue.
624
+ */
625
+ waitExchange: HeadersExchangeDefinition;
626
+ /**
627
+ * Retry exchange used to route messages to retry back to the main queue.
628
+ */
629
+ retryExchange: HeadersExchangeDefinition;
623
630
  /**
624
631
  * Binding that routes failed messages to the wait queue.
625
632
  */
626
633
  waitQueueBinding: QueueBindingDefinition;
627
634
  /**
628
- * Binding that routes retried messages back to the main queue.
635
+ * Binding that routes messages to retry back to the main queue.
629
636
  */
630
- mainQueueRetryBinding: QueueBindingDefinition;
637
+ retryQueueBinding: QueueBindingDefinition;
631
638
  };
632
639
  /**
633
640
  * A queue entry that can be passed to `defineContract`.
@@ -635,6 +642,14 @@ type QueueWithTtlBackoffInfrastructure<TName extends string = string> = {
635
642
  * Can be either a plain queue definition or a queue with TTL-backoff infrastructure.
636
643
  */
637
644
  type QueueEntry<TName extends string = string> = QueueDefinition<TName> | QueueWithTtlBackoffInfrastructure<TName>;
645
+ /**
646
+ * A queue entry with a dead letter exchange.
647
+ */
648
+ type QueueEntryWithDeadLetterExchange<TName extends string = string, TDlx extends ExchangeDefinition = ExchangeDefinition> = QueueEntry<TName> & {
649
+ deadLetter: {
650
+ exchange: TDlx;
651
+ };
652
+ };
638
653
  /**
639
654
  * Definition of a message with typed payload and optional headers.
640
655
  *
@@ -668,7 +683,7 @@ type MessageDefinition<TPayload extends AnySchema = AnySchema, THeaders extends
668
683
  *
669
684
  * Defines how messages from an exchange should be routed to a queue.
670
685
  * For direct and topic exchanges, a routing key is required.
671
- * For fanout exchanges, no routing key is needed as all messages are broadcast.
686
+ * For fanout and headers exchanges, no routing key is needed.
672
687
  */
673
688
  type QueueBindingDefinition = {
674
689
  /** Discriminator indicating this is a queue-to-exchange binding */type: "queue"; /** The queue that will receive messages */
@@ -687,7 +702,7 @@ type QueueBindingDefinition = {
687
702
  */
688
703
  routingKey: string;
689
704
  } | {
690
- /** Fanout exchange (no routing key needed) */exchange: FanoutExchangeDefinition; /** Fanout exchanges don't use routing keys */
705
+ /** Fanout or headers exchange (no routing key needed) */exchange: FanoutExchangeDefinition | HeadersExchangeDefinition; /** Fanout and headers exchanges don't use routing keys */
691
706
  routingKey?: never;
692
707
  });
693
708
  /**
@@ -722,7 +737,7 @@ type ExchangeBindingDefinition = {
722
737
  */
723
738
  routingKey: string;
724
739
  } | {
725
- /** Fanout source exchange (no routing key needed) */source: FanoutExchangeDefinition; /** Fanout exchanges don't use routing keys */
740
+ /** Fanout or headers source exchange (no routing key needed) */source: FanoutExchangeDefinition | HeadersExchangeDefinition; /** Fanout and headers exchanges don't use routing keys */
726
741
  routingKey?: never;
727
742
  });
728
743
  /**
@@ -763,7 +778,7 @@ type PublisherDefinition<TMessage extends MessageDefinition = MessageDefinition>
763
778
  */
764
779
  routingKey: string;
765
780
  } | {
766
- /** Fanout exchange (no routing key needed) */exchange: FanoutExchangeDefinition; /** Fanout exchanges don't use routing keys - all bound queues receive the message */
781
+ /** Fanout or headers exchange (no routing key needed) */exchange: FanoutExchangeDefinition | HeadersExchangeDefinition; /** Fanout and headers exchanges don't use routing keys */
767
782
  routingKey?: never;
768
783
  });
769
784
  /**
@@ -785,7 +800,7 @@ type PublisherDefinition<TMessage extends MessageDefinition = MessageDefinition>
785
800
  * ```
786
801
  */
787
802
  type ConsumerDefinition<TMessage extends MessageDefinition = MessageDefinition> = {
788
- /** The queue to consume messages from */queue: QueueDefinition; /** The message definition including the payload schema */
803
+ /** The queue to consume messages from */queue: QueueEntry; /** The message definition including the payload schema */
789
804
  message: TMessage;
790
805
  };
791
806
  /**
@@ -816,8 +831,7 @@ type CommandConsumerConfigBase = {
816
831
  consumer: ConsumerDefinition;
817
832
  binding: QueueBindingDefinition;
818
833
  exchange: ExchangeDefinition;
819
- queue: QueueDefinition;
820
- deadLetterExchange: ExchangeDefinition | undefined;
834
+ queue: QueueEntry;
821
835
  message: MessageDefinition;
822
836
  routingKey: string | undefined;
823
837
  };
@@ -834,8 +848,7 @@ type EventConsumerResultBase = {
834
848
  consumer: ConsumerDefinition;
835
849
  binding: QueueBindingDefinition;
836
850
  exchange: ExchangeDefinition;
837
- queue: QueueDefinition;
838
- deadLetterExchange: ExchangeDefinition | undefined;
851
+ queue: QueueEntry;
839
852
  exchangeBinding: ExchangeBindingDefinition | undefined;
840
853
  bridgeExchange: ExchangeDefinition | undefined;
841
854
  };
@@ -898,7 +911,7 @@ type ContractDefinition = {
898
911
  * Each key becomes available as a named resource in the contract.
899
912
  *
900
913
  * When a queue has TTL-backoff retry configured, pass the `QueueWithTtlBackoffInfrastructure`
901
- * object returned by `defineQueue`. The wait queue and bindings will be automatically added.
914
+ * object returned by `defineQueue`. The wait queue, exchanges, and bindings will be automatically added.
902
915
  */
903
916
  queues?: Record<string, QueueEntry>;
904
917
  /**
@@ -925,6 +938,7 @@ type ContractDefinition = {
925
938
  * Can be either:
926
939
  * - A plain PublisherDefinition from definePublisher
927
940
  * - An EventPublisherConfig from defineEventPublisher (auto-extracted to publisher)
941
+ * - An BridgedPublisherConfig from defineCommandPublisher (auto-extracted to publisher)
928
942
  */
929
943
  type PublisherEntry = PublisherDefinition | EventPublisherConfigBase | BridgedPublisherConfigBase;
930
944
  /**
@@ -1005,7 +1019,7 @@ type ExtractDlxFromEntry<T extends QueueEntry> = T extends {
1005
1019
  deadLetter: {
1006
1020
  exchange: infer E extends ExchangeDefinition;
1007
1021
  };
1008
- } ? E : undefined : undefined;
1022
+ } ? E : never : never;
1009
1023
  /**
1010
1024
  * Extract the queue from a consumer entry.
1011
1025
  * @internal
@@ -1040,11 +1054,7 @@ type ExtractExchangesFromConsumers<TConsumers extends Record<string, ConsumerEnt
1040
1054
  * Extract the dead letter exchange from a consumer entry.
1041
1055
  * @internal
1042
1056
  */
1043
- type ExtractDeadLetterExchange<T extends ConsumerEntry> = T extends EventConsumerResultBase | CommandConsumerConfigBase ? T["deadLetterExchange"] extends ExchangeDefinition ? T["deadLetterExchange"] : never : T extends ConsumerDefinition ? T["queue"] extends {
1044
- deadLetter: {
1045
- exchange: infer E extends ExchangeDefinition;
1046
- };
1047
- } ? E : never : never;
1057
+ type ExtractDeadLetterExchange<T extends ConsumerEntry> = ExtractDlxFromEntry<T["queue"]>;
1048
1058
  /**
1049
1059
  * Extract dead letter exchanges from all consumers in a contract.
1050
1060
  * @internal
@@ -1054,7 +1064,7 @@ type ExtractDeadLetterExchangesFromConsumers<TConsumers extends Record<string, C
1054
1064
  * Extract queues from all consumers in a contract.
1055
1065
  * @internal
1056
1066
  */
1057
- type ExtractQueuesFromConsumers<TConsumers extends Record<string, ConsumerEntry>> = { [K in keyof TConsumers as ExtractConsumerQueue<TConsumers[K]>["name"]]: ExtractConsumerQueue<TConsumers[K]> };
1067
+ type ExtractQueuesFromConsumers<TConsumers extends Record<string, ConsumerEntry>> = { [K in keyof TConsumers as ExtractQueueFromEntry<ExtractConsumerQueue<TConsumers[K]>>["name"]]: ExtractConsumerQueue<TConsumers[K]> };
1058
1068
  /**
1059
1069
  * Extract bindings from all consumers in a contract.
1060
1070
  * @internal
@@ -1074,12 +1084,12 @@ type ExtractConsumerDefinitions<TConsumers extends Record<string, ConsumerEntry>
1074
1084
  * Extract the publisher definition from a publisher entry.
1075
1085
  * @internal
1076
1086
  */
1077
- type ExtractPublisherDefinition<T extends PublisherEntry> = T extends BridgedPublisherConfigBase ? T["publisher"] : T extends EventPublisherConfigBase ? PublisherDefinition<T["message"]> & (T["exchange"] extends FanoutExchangeDefinition ? {
1087
+ type ExtractPublisherDefinition<T extends PublisherEntry> = T extends BridgedPublisherConfigBase ? T["publisher"] : T extends EventPublisherConfigBase ? PublisherDefinition<T["message"]> & (T["exchange"] extends DirectExchangeDefinition | TopicExchangeDefinition ? {
1078
1088
  exchange: T["exchange"];
1079
- routingKey?: never;
1089
+ routingKey: T["routingKey"] & string;
1080
1090
  } : {
1081
1091
  exchange: T["exchange"];
1082
- routingKey: T["routingKey"] & string;
1092
+ routingKey?: never;
1083
1093
  }) : T extends PublisherDefinition ? T : never;
1084
1094
  /**
1085
1095
  * Extract publisher definitions from all publishers in a contract.
@@ -1188,28 +1198,32 @@ type InferConsumerNames<TContract extends ContractDefinition> = TContract["consu
1188
1198
  //#endregion
1189
1199
  //#region src/builder/exchange.d.ts
1190
1200
  /**
1191
- * Define a fanout exchange.
1201
+ * Define a topic exchange.
1192
1202
  *
1193
- * A fanout exchange routes messages to all bound queues without considering routing keys.
1194
- * This exchange type is ideal for broadcasting messages to multiple consumers.
1203
+ * A topic exchange routes messages to queues based on routing key patterns.
1204
+ * Routing keys can use wildcards: `*` matches one word, `#` matches zero or more words.
1205
+ * This exchange type is ideal for flexible message routing based on hierarchical topics.
1195
1206
  *
1196
1207
  * @param name - The name of the exchange
1197
- * @param type - Must be "fanout"
1198
1208
  * @param options - Optional exchange configuration
1199
- * @param options.durable - If true, the exchange survives broker restarts (default: false)
1200
- * @param options.autoDelete - If true, the exchange is deleted when no queues are bound (default: false)
1201
- * @param options.internal - If true, the exchange cannot be directly published to (default: false)
1209
+ * @param options.type - Exchange type (must be "topic", or omitted for default topic exchange)
1210
+ * @param options.durable - If true, the exchange survives broker restarts (default: true)
1211
+ * @param options.autoDelete - If true, the exchange is deleted when no queues are bound
1212
+ * @param options.internal - If true, the exchange cannot be directly published to
1202
1213
  * @param options.arguments - Additional AMQP arguments for the exchange
1203
- * @returns A fanout exchange definition
1214
+ * @returns A topic exchange definition
1204
1215
  *
1205
1216
  * @example
1206
1217
  * ```typescript
1207
- * const logsExchange = defineExchange('logs', 'fanout', {
1208
- * durable: true
1209
- * });
1218
+ * const ordersExchange = defineExchange('orders', { type: 'topic' });
1219
+ *
1220
+ * // Or omit type for default topic exchange
1221
+ * const ordersExchange = defineExchange('orders');
1210
1222
  * ```
1211
1223
  */
1212
- declare function defineExchange<TName extends string>(name: TName, type: "fanout", options?: Omit<BaseExchangeDefinition, "name" | "type">): FanoutExchangeDefinition<TName>;
1224
+ declare function defineExchange<TName extends string>(name: TName, options?: {
1225
+ type?: "topic";
1226
+ } & Omit<BaseExchangeDefinition, "name" | "type">): TopicExchangeDefinition<TName>;
1213
1227
  /**
1214
1228
  * Define a direct exchange.
1215
1229
  *
@@ -1217,46 +1231,68 @@ declare function defineExchange<TName extends string>(name: TName, type: "fanout
1217
1231
  * This exchange type is ideal for point-to-point messaging.
1218
1232
  *
1219
1233
  * @param name - The name of the exchange
1220
- * @param type - Must be "direct"
1221
- * @param options - Optional exchange configuration
1222
- * @param options.durable - If true, the exchange survives broker restarts (default: false)
1223
- * @param options.autoDelete - If true, the exchange is deleted when no queues are bound (default: false)
1224
- * @param options.internal - If true, the exchange cannot be directly published to (default: false)
1234
+ * @param options - Exchange configuration
1235
+ * @param options.type - Exchange type (must be "direct")
1236
+ * @param options.durable - If true, the exchange survives broker restarts (default: true)
1237
+ * @param options.autoDelete - If true, the exchange is deleted when no queues are bound
1238
+ * @param options.internal - If true, the exchange cannot be directly published to
1225
1239
  * @param options.arguments - Additional AMQP arguments for the exchange
1226
1240
  * @returns A direct exchange definition
1227
1241
  *
1228
1242
  * @example
1229
1243
  * ```typescript
1230
- * const tasksExchange = defineExchange('tasks', 'direct', {
1231
- * durable: true
1232
- * });
1244
+ * const tasksExchange = defineExchange('tasks', { type: 'direct' });
1233
1245
  * ```
1234
1246
  */
1235
- declare function defineExchange<TName extends string>(name: TName, type: "direct", options?: Omit<BaseExchangeDefinition, "name" | "type">): DirectExchangeDefinition<TName>;
1247
+ declare function defineExchange<TName extends string>(name: TName, options: {
1248
+ type: "direct";
1249
+ } & Omit<BaseExchangeDefinition, "name" | "type">): DirectExchangeDefinition<TName>;
1236
1250
  /**
1237
- * Define a topic exchange.
1251
+ * Define a fanout exchange.
1238
1252
  *
1239
- * A topic exchange routes messages to queues based on routing key patterns.
1240
- * Routing keys can use wildcards: `*` matches one word, `#` matches zero or more words.
1241
- * This exchange type is ideal for flexible message routing based on hierarchical topics.
1253
+ * A fanout exchange routes messages to all bound queues without considering routing keys.
1254
+ * This exchange type is ideal for broadcasting messages to multiple consumers.
1242
1255
  *
1243
1256
  * @param name - The name of the exchange
1244
- * @param type - Must be "topic"
1245
- * @param options - Optional exchange configuration
1246
- * @param options.durable - If true, the exchange survives broker restarts (default: false)
1247
- * @param options.autoDelete - If true, the exchange is deleted when no queues are bound (default: false)
1248
- * @param options.internal - If true, the exchange cannot be directly published to (default: false)
1257
+ * @param options - Exchange configuration
1258
+ * @param options.type - Exchange type (must be "fanout")
1259
+ * @param options.durable - If true, the exchange survives broker restarts (default: true)
1260
+ * @param options.autoDelete - If true, the exchange is deleted when no queues are bound
1261
+ * @param options.internal - If true, the exchange cannot be directly published to
1249
1262
  * @param options.arguments - Additional AMQP arguments for the exchange
1250
- * @returns A topic exchange definition
1263
+ * @returns A fanout exchange definition
1251
1264
  *
1252
1265
  * @example
1253
1266
  * ```typescript
1254
- * const ordersExchange = defineExchange('orders', 'topic', {
1255
- * durable: true
1256
- * });
1267
+ * const logsExchange = defineExchange('logs', { type: 'fanout' });
1268
+ * ```
1269
+ */
1270
+ declare function defineExchange<TName extends string>(name: TName, options: {
1271
+ type: "fanout";
1272
+ } & Omit<BaseExchangeDefinition, "name" | "type">): FanoutExchangeDefinition<TName>;
1273
+ /**
1274
+ * Define a headers exchange.
1275
+ *
1276
+ * A headers exchange routes messages to all bound queues based on header matching.
1277
+ * This exchange type is ideal for complex routing scenarios.
1278
+ *
1279
+ * @param name - The name of the exchange
1280
+ * @param options - Exchange configuration
1281
+ * @param options.type - Exchange type (must be "headers")
1282
+ * @param options.durable - If true, the exchange survives broker restarts (default: true)
1283
+ * @param options.autoDelete - If true, the exchange is deleted when no queues are bound
1284
+ * @param options.internal - If true, the exchange cannot be directly published to
1285
+ * @param options.arguments - Additional AMQP arguments for the exchange
1286
+ * @returns A headers exchange definition
1287
+ *
1288
+ * @example
1289
+ * ```typescript
1290
+ * const routesExchange = defineExchange('routes', { type: 'headers' });
1257
1291
  * ```
1258
1292
  */
1259
- declare function defineExchange<TName extends string>(name: TName, type: "topic", options?: Omit<BaseExchangeDefinition, "name" | "type">): TopicExchangeDefinition<TName>;
1293
+ declare function defineExchange<TName extends string>(name: TName, options: {
1294
+ type: "headers";
1295
+ } & Omit<BaseExchangeDefinition, "name" | "type">): HeadersExchangeDefinition<TName>;
1260
1296
  //#endregion
1261
1297
  //#region src/builder/message.d.ts
1262
1298
  /**
@@ -1301,89 +1337,6 @@ declare function defineMessage<TPayload extends MessageDefinition["payload"], TH
1301
1337
  }): MessageDefinition<TPayload, THeaders>;
1302
1338
  //#endregion
1303
1339
  //#region src/builder/queue.d.ts
1304
- /**
1305
- * Type guard to check if a queue entry is a QueueWithTtlBackoffInfrastructure.
1306
- *
1307
- * When you configure a queue with TTL-backoff retry and a dead letter exchange,
1308
- * `defineQueue` returns a `QueueWithTtlBackoffInfrastructure` instead of a plain
1309
- * `QueueDefinition`. This type guard helps you distinguish between the two.
1310
- *
1311
- * **When to use:**
1312
- * - When you need to check the type of a queue entry at runtime
1313
- * - When writing generic code that handles both plain queues and infrastructure wrappers
1314
- *
1315
- * **Related functions:**
1316
- * - `extractQueue()` - Use this to get the underlying queue definition from either type
1317
- *
1318
- * @param entry - The queue entry to check
1319
- * @returns True if the entry is a QueueWithTtlBackoffInfrastructure, false otherwise
1320
- *
1321
- * @example
1322
- * ```typescript
1323
- * const queue = defineQueue('orders', {
1324
- * deadLetter: { exchange: dlx },
1325
- * retry: { mode: 'ttl-backoff' },
1326
- * });
1327
- *
1328
- * if (isQueueWithTtlBackoffInfrastructure(queue)) {
1329
- * // queue has .queue, .waitQueue, .waitQueueBinding, .mainQueueRetryBinding
1330
- * console.log('Wait queue:', queue.waitQueue.name);
1331
- * } else {
1332
- * // queue is a plain QueueDefinition
1333
- * console.log('Queue:', queue.name);
1334
- * }
1335
- * ```
1336
- */
1337
- declare function isQueueWithTtlBackoffInfrastructure(entry: QueueEntry): entry is QueueWithTtlBackoffInfrastructure;
1338
- /**
1339
- * Extract the plain QueueDefinition from a QueueEntry.
1340
- *
1341
- * **Why this function exists:**
1342
- * When you configure a queue with TTL-backoff retry and a dead letter exchange,
1343
- * `defineQueue` (or `defineTtlBackoffQueue`) returns a wrapper object that includes
1344
- * the main queue, wait queue, and bindings. This function extracts the underlying
1345
- * queue definition so you can access properties like `name`, `type`, etc.
1346
- *
1347
- * **When to use:**
1348
- * - When you need to access queue properties (name, type, deadLetter, etc.)
1349
- * - When passing a queue to functions that expect a plain QueueDefinition
1350
- * - Works safely on both plain queues and infrastructure wrappers
1351
- *
1352
- * **How it works:**
1353
- * - If the entry is a `QueueWithTtlBackoffInfrastructure`, returns `entry.queue`
1354
- * - Otherwise, returns the entry as-is (it's already a plain QueueDefinition)
1355
- *
1356
- * @param entry - The queue entry (either plain QueueDefinition or QueueWithTtlBackoffInfrastructure)
1357
- * @returns The plain QueueDefinition
1358
- *
1359
- * @example
1360
- * ```typescript
1361
- * import { defineQueue, defineTtlBackoffQueue, extractQueue } from '@amqp-contract/contract';
1362
- *
1363
- * // TTL-backoff queue returns a wrapper
1364
- * const orderQueue = defineTtlBackoffQueue('orders', {
1365
- * deadLetter: { exchange: dlx },
1366
- * maxRetries: 3,
1367
- * });
1368
- *
1369
- * // Use extractQueue to access the queue name
1370
- * const queueName = extractQueue(orderQueue).name; // 'orders'
1371
- *
1372
- * // Also works safely on plain queues
1373
- * const plainQueue = defineQueue('simple', { type: 'quorum', retry: { mode: 'quorum-native' } });
1374
- * const plainName = extractQueue(plainQueue).name; // 'simple'
1375
- *
1376
- * // Access other properties
1377
- * const queueDef = extractQueue(orderQueue);
1378
- * console.log(queueDef.name); // 'orders'
1379
- * console.log(queueDef.type); // 'quorum'
1380
- * console.log(queueDef.deadLetter); // { exchange: dlx, ... }
1381
- * ```
1382
- *
1383
- * @see isQueueWithTtlBackoffInfrastructure - Type guard to check if extraction is needed
1384
- * @see defineTtlBackoffQueue - Creates queues with TTL-backoff infrastructure
1385
- */
1386
- declare function extractQueue<T extends QueueEntry>(entry: T): ExtractQueueFromEntry<T>;
1387
1340
  /**
1388
1341
  * Define an AMQP queue.
1389
1342
  *
@@ -1397,11 +1350,12 @@ declare function extractQueue<T extends QueueEntry>(entry: T): ExtractQueueFromE
1397
1350
  * @param name - The name of the queue
1398
1351
  * @param options - Optional queue configuration
1399
1352
  * @param options.type - Queue type: 'quorum' (default, recommended) or 'classic'
1400
- * @param options.durable - If true, the queue survives broker restarts. Quorum queues are always durable.
1401
- * @param options.exclusive - If true, the queue can only be used by the declaring connection. Only supported with classic queues.
1402
- * @param options.autoDelete - If true, the queue is deleted when the last consumer unsubscribes (default: false)
1403
- * @param options.deadLetter - Dead letter configuration for handling failed messages
1353
+ * @param options.durable - If true, the queue survives broker restarts. Quorum queues only support durable queues (default: true)
1354
+ * @param options.exclusive - If true, the queue can only be used by the declaring connection and is deleted when that connection closes. Only supported with classic queues.
1355
+ * @param options.autoDelete - If true, the queue is deleted when the last consumer unsubscribes. Only supported with classic queues.
1404
1356
  * @param options.maxPriority - Maximum priority level for priority queue (1-255, recommended: 1-10). Only supported with classic queues.
1357
+ * @param options.deadLetter - Dead letter configuration for handling failed messages
1358
+ * @param options.retry - Retry configuration for handling failed message processing
1405
1359
  * @param options.arguments - Additional AMQP arguments (e.g., x-message-ttl)
1406
1360
  * @returns A queue definition
1407
1361
  *
@@ -1411,7 +1365,7 @@ declare function extractQueue<T extends QueueEntry>(entry: T): ExtractQueueFromE
1411
1365
  * const orderQueue = defineQueue('order-processing');
1412
1366
  *
1413
1367
  * // Explicit quorum queue with dead letter exchange
1414
- * const dlx = defineExchange('orders-dlx', 'topic', { durable: true });
1368
+ * const dlx = defineExchange('orders-dlx');
1415
1369
  * const orderQueueWithDLX = defineQueue('order-processing', {
1416
1370
  * type: 'quorum',
1417
1371
  * deadLetter: {
@@ -1433,12 +1387,11 @@ declare function extractQueue<T extends QueueEntry>(entry: T): ExtractQueueFromE
1433
1387
  * // Priority queue (requires classic type)
1434
1388
  * const taskQueue = defineQueue('urgent-tasks', {
1435
1389
  * type: 'classic',
1436
- * durable: true,
1437
1390
  * maxPriority: 10,
1438
1391
  * });
1439
1392
  *
1440
1393
  * // Queue with TTL-backoff retry (returns infrastructure automatically)
1441
- * const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
1394
+ * const dlx = defineExchange('orders-dlx', { type: 'direct' });
1442
1395
  * const orderQueue = defineQueue('order-processing', {
1443
1396
  * deadLetter: { exchange: dlx },
1444
1397
  * retry: { mode: 'ttl-backoff', maxRetries: 5 },
@@ -1446,204 +1399,82 @@ declare function extractQueue<T extends QueueEntry>(entry: T): ExtractQueueFromE
1446
1399
  * // orderQueue is QueueWithTtlBackoffInfrastructure, pass directly to defineContract
1447
1400
  * ```
1448
1401
  */
1449
- declare function defineQueue<TName extends string, TDlx extends ExchangeDefinition>(name: TName, options: DefineQueueOptions & {
1450
- deadLetter: {
1451
- exchange: TDlx;
1452
- };
1453
- }): (QueueDefinition<TName> | QueueWithTtlBackoffInfrastructure<TName>) & {
1454
- deadLetter: {
1455
- exchange: TDlx;
1456
- };
1457
- };
1458
- declare function defineQueue<TName extends string>(name: TName, options?: DefineQueueOptions): QueueDefinition<TName> | QueueWithTtlBackoffInfrastructure<TName>;
1459
- /**
1460
- * Options for creating a quorum queue with quorum-native retry.
1461
- *
1462
- * This simplified helper enforces the required configuration for quorum-native retry:
1463
- * - Dead letter exchange is required (for failed messages)
1464
- * - Delivery limit is required (for retry count)
1465
- */
1466
- type DefineQuorumQueueOptions = {
1467
- /**
1468
- * Dead letter configuration - required for retry support.
1469
- * Failed messages will be sent to this exchange.
1470
- */
1471
- deadLetter: DeadLetterConfig;
1472
- /**
1473
- * Maximum number of delivery attempts before dead-lettering.
1474
- * @minimum 1
1475
- */
1476
- deliveryLimit: number;
1477
- /**
1478
- * If true, the queue is deleted when the last consumer unsubscribes.
1479
- * @default false
1480
- */
1481
- autoDelete?: boolean;
1482
- /**
1483
- * Additional AMQP arguments for advanced configuration.
1484
- */
1485
- arguments?: Record<string, unknown>;
1486
- };
1487
- /**
1488
- * Create a quorum queue with quorum-native retry.
1489
- *
1490
- * This is a simplified helper that enforces best practices:
1491
- * - Uses quorum queues (recommended for most use cases)
1492
- * - Requires dead letter exchange for failed message handling
1493
- * - Uses quorum-native retry mode (simpler than TTL-backoff)
1494
- *
1495
- * **When to use:**
1496
- * - You want simple, immediate retries without exponential backoff
1497
- * - You don't need configurable delays between retries
1498
- * - You want the simplest retry configuration
1499
- *
1500
- * @param name - The queue name
1501
- * @param options - Configuration options
1502
- * @returns A quorum queue definition with quorum-native retry
1503
- *
1504
- * @example
1505
- * ```typescript
1506
- * const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
1507
- *
1508
- * const orderQueue = defineQuorumQueue('order-processing', {
1509
- * deadLetter: { exchange: dlx },
1510
- * deliveryLimit: 3, // Retry up to 3 times
1511
- * });
1512
- *
1513
- * // Use in a contract — exchanges, queues, and bindings are auto-extracted
1514
- * const contract = defineContract({
1515
- * publishers: { ... },
1516
- * consumers: { processOrder: defineEventConsumer(event, orderQueue) },
1517
- * });
1518
- * ```
1519
- *
1520
- * @see defineQueue - For full queue configuration options
1521
- * @see defineTtlBackoffQueue - For queues with exponential backoff retry
1522
- */
1523
- declare function defineQuorumQueue<TName extends string>(name: TName, options: DefineQuorumQueueOptions): QuorumQueueDefinition<TName>;
1524
- /**
1525
- * Options for creating a queue with TTL-backoff retry.
1526
- *
1527
- * This simplified helper enforces the required configuration for TTL-backoff retry:
1528
- * - Dead letter exchange is required (used for retry routing)
1529
- * - Returns infrastructure that includes wait queue and bindings
1530
- */
1531
- type DefineTtlBackoffQueueOptions = {
1532
- /**
1533
- * Dead letter configuration - required for TTL-backoff retry.
1534
- * Used for routing messages to the wait queue and back.
1535
- */
1536
- deadLetter: DeadLetterConfig;
1537
- /**
1538
- * Maximum retry attempts before sending to DLQ.
1539
- * @default 3
1540
- */
1541
- maxRetries?: number;
1542
- /**
1543
- * Initial delay in ms before first retry.
1544
- * @default 1000
1545
- */
1546
- initialDelayMs?: number;
1547
- /**
1548
- * Maximum delay in ms between retries.
1549
- * @default 30000
1550
- */
1551
- maxDelayMs?: number;
1552
- /**
1553
- * Exponential backoff multiplier.
1554
- * @default 2
1555
- */
1556
- backoffMultiplier?: number;
1557
- /**
1558
- * Add jitter to prevent thundering herd.
1559
- * @default true
1560
- */
1561
- jitter?: boolean;
1562
- /**
1563
- * If true, the queue is deleted when the last consumer unsubscribes.
1564
- * @default false
1565
- */
1566
- autoDelete?: boolean;
1567
- /**
1568
- * Additional AMQP arguments for advanced configuration.
1569
- */
1570
- arguments?: Record<string, unknown>;
1571
- };
1402
+ declare function defineQueue<TName extends string, TDlx extends ExchangeDefinition>(name: TName, options: DefineQueueOptionsWithDeadLetterExchange<TDlx>): QueueEntryWithDeadLetterExchange<TName, TDlx>;
1403
+ declare function defineQueue<TName extends string>(name: TName, options?: DefineQueueOptions): QueueEntry<TName>;
1404
+ //#endregion
1405
+ //#region src/builder/queue-utils.d.ts
1572
1406
  /**
1573
- * Create a queue with TTL-backoff retry (exponential backoff).
1407
+ * Extract the plain QueueDefinition from a QueueEntry.
1574
1408
  *
1575
- * This is a simplified helper that enforces best practices:
1576
- * - Uses quorum queues (recommended for most use cases)
1577
- * - Requires dead letter exchange for retry routing
1578
- * - Uses TTL-backoff retry mode with configurable delays
1579
- * - Automatically generates wait queue and bindings
1409
+ * **Why this function exists:**
1410
+ * When you configure a queue with TTL-backoff retry,
1411
+ * `defineQueue` returns a wrapper object that includes
1412
+ * the main queue, wait queue, headers exchanges, and bindings. This function extracts the underlying
1413
+ * queue definition so you can access properties like `name`, `type`, etc.
1580
1414
  *
1581
1415
  * **When to use:**
1582
- * - You need exponential backoff between retries
1583
- * - You want configurable delays (initial delay, max delay, jitter)
1584
- * - You're processing messages that may need time before retry
1416
+ * - When you need to access queue properties (name, type, etc.)
1417
+ * - When passing a queue to functions that expect a plain QueueDefinition
1418
+ * - Works safely on both plain queues and infrastructure wrappers
1585
1419
  *
1586
- * **Returns:** A `QueueWithTtlBackoffInfrastructure` object that includes the
1587
- * main queue, wait queue, and bindings. Pass this directly to `defineContract`
1588
- * and it will be expanded automatically.
1420
+ * **How it works:**
1421
+ * - If the entry is a `QueueWithTtlBackoffInfrastructure`, returns `entry.queue`
1422
+ * - Otherwise, returns the entry as-is (it's already a plain QueueDefinition)
1589
1423
  *
1590
- * @param name - The queue name
1591
- * @param options - Configuration options
1592
- * @returns A queue with TTL-backoff infrastructure
1424
+ * @param entry - The queue entry (either plain QueueDefinition or QueueWithTtlBackoffInfrastructure)
1425
+ * @returns The plain QueueDefinition
1593
1426
  *
1594
1427
  * @example
1595
1428
  * ```typescript
1596
- * const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
1429
+ * import { defineQueue, extractQueue } from '@amqp-contract/contract';
1597
1430
  *
1598
- * const orderQueue = defineTtlBackoffQueue('order-processing', {
1599
- * deadLetter: { exchange: dlx },
1600
- * maxRetries: 5,
1601
- * initialDelayMs: 1000, // Start with 1s delay
1602
- * maxDelayMs: 30000, // Cap at 30s
1431
+ * // TTL-backoff queue returns a wrapper
1432
+ * const orderQueue = defineQueue('orders', {
1433
+ * retry: { mode: 'ttl-backoff', maxRetries: 3 },
1603
1434
  * });
1604
1435
  *
1605
- * // Use in a contract wait queue, bindings, and DLX are auto-extracted
1606
- * const contract = defineContract({
1607
- * publishers: { ... },
1608
- * consumers: { processOrder: defineEventConsumer(event, extractQueue(orderQueue)) },
1609
- * });
1436
+ * // Use extractQueue to access the queue name
1437
+ * const queueName = extractQueue(orderQueue).name; // 'orders'
1610
1438
  *
1611
- * // To access the underlying queue definition (e.g., for the queue name):
1612
- * import { extractQueue } from '@amqp-contract/contract';
1613
- * const queueName = extractQueue(orderQueue).name;
1439
+ * // Also works safely on plain queues
1440
+ * const plainQueue = defineQueue('simple', { type: 'quorum', retry: { mode: 'immediate-requeue' } });
1441
+ * const plainName = extractQueue(plainQueue).name; // 'simple'
1442
+ *
1443
+ * // Access other properties
1444
+ * const queueDef = extractQueue(orderQueue);
1445
+ * console.log(queueDef.name); // 'orders'
1446
+ * console.log(queueDef.type); // 'quorum'
1614
1447
  * ```
1615
1448
  *
1616
- * @see defineQueue - For full queue configuration options
1617
- * @see defineQuorumQueue - For queues with quorum-native retry (simpler, immediate retries)
1618
- * @see extractQueue - To access the underlying queue definition
1449
+ * @see isQueueWithTtlBackoffInfrastructure - Type guard to check if extraction is needed
1619
1450
  */
1620
- declare function defineTtlBackoffQueue<TName extends string>(name: TName, options: DefineTtlBackoffQueueOptions): QueueWithTtlBackoffInfrastructure<TName>;
1451
+ declare function extractQueue<T extends QueueEntry>(entry: T): ExtractQueueFromEntry<T>;
1621
1452
  //#endregion
1622
1453
  //#region src/builder/binding.d.ts
1623
1454
  /**
1624
- * Define a binding between a queue and a fanout exchange.
1455
+ * Define a binding between a queue and a fanout or headers exchange.
1625
1456
  *
1626
- * Binds a queue to a fanout exchange to receive all messages published to the exchange.
1627
- * Fanout exchanges ignore routing keys, so this overload doesn't require one.
1457
+ * Binds a queue to a fanout or headers exchange (no routing key needed).
1458
+ * Fanout and headers exchanges ignore routing keys, so this overload doesn't require one.
1628
1459
  *
1629
1460
  * @param queue - The queue definition or queue with infrastructure to bind
1630
- * @param exchange - The fanout exchange definition
1461
+ * @param exchange - The fanout or headers exchange definition
1631
1462
  * @param options - Optional binding configuration
1632
1463
  * @param options.arguments - Additional AMQP arguments for the binding
1633
1464
  * @returns A queue binding definition
1634
1465
  *
1635
1466
  * @example
1636
1467
  * ```typescript
1637
- * const logsQueue = defineQueue('logs-queue', { durable: true });
1638
- * const logsExchange = defineExchange('logs', 'fanout', { durable: true });
1468
+ * const logsQueue = defineQueue('logs-queue');
1469
+ * const logsExchange = defineExchange('logs', { type: 'fanout' });
1639
1470
  *
1640
1471
  * const binding = defineQueueBinding(logsQueue, logsExchange);
1641
1472
  * ```
1642
1473
  */
1643
- declare function defineQueueBinding(queue: QueueEntry, exchange: FanoutExchangeDefinition, options?: Omit<Extract<QueueBindingDefinition, {
1644
- exchange: FanoutExchangeDefinition;
1474
+ declare function defineQueueBinding(queue: QueueEntry, exchange: FanoutExchangeDefinition | HeadersExchangeDefinition, options?: Omit<Extract<QueueBindingDefinition, {
1475
+ exchange: FanoutExchangeDefinition | HeadersExchangeDefinition;
1645
1476
  }>, "type" | "queue" | "exchange" | "routingKey">): Extract<QueueBindingDefinition, {
1646
- exchange: FanoutExchangeDefinition;
1477
+ exchange: FanoutExchangeDefinition | HeadersExchangeDefinition;
1647
1478
  }>;
1648
1479
  /**
1649
1480
  * Define a binding between a queue and a direct or topic exchange.
@@ -1665,8 +1496,8 @@ declare function defineQueueBinding(queue: QueueEntry, exchange: FanoutExchangeD
1665
1496
  *
1666
1497
  * @example
1667
1498
  * ```typescript
1668
- * const orderQueue = defineQueue('order-processing', { durable: true });
1669
- * const ordersExchange = defineExchange('orders', 'topic', { durable: true });
1499
+ * const orderQueue = defineQueue('order-processing');
1500
+ * const ordersExchange = defineExchange('orders');
1670
1501
  *
1671
1502
  * // Bind with exact routing key
1672
1503
  * const binding = defineQueueBinding(orderQueue, ordersExchange, {
@@ -1687,28 +1518,28 @@ declare function defineQueueBinding(queue: QueueEntry, exchange: DirectExchangeD
1687
1518
  /**
1688
1519
  * Define a binding between two exchanges (exchange-to-exchange routing).
1689
1520
  *
1690
- * Binds a destination exchange to a fanout source exchange.
1521
+ * Binds a destination exchange to a fanout or headers source exchange.
1691
1522
  * Messages published to the source exchange will be forwarded to the destination exchange.
1692
- * Fanout exchanges ignore routing keys, so this overload doesn't require one.
1523
+ * Fanout and headers exchanges ignore routing keys, so this overload doesn't require one.
1693
1524
  *
1694
1525
  * @param destination - The destination exchange definition
1695
- * @param source - The fanout source exchange definition
1526
+ * @param source - The fanout or headers source exchange definition
1696
1527
  * @param options - Optional binding configuration
1697
1528
  * @param options.arguments - Additional AMQP arguments for the binding
1698
1529
  * @returns An exchange binding definition
1699
1530
  *
1700
1531
  * @example
1701
1532
  * ```typescript
1702
- * const sourceExchange = defineExchange('logs', 'fanout', { durable: true });
1703
- * const destExchange = defineExchange('all-logs', 'fanout', { durable: true });
1533
+ * const sourceExchange = defineExchange('logs', { type: 'fanout' });
1534
+ * const destExchange = defineExchange('all-logs', { type: 'fanout' });
1704
1535
  *
1705
1536
  * const binding = defineExchangeBinding(destExchange, sourceExchange);
1706
1537
  * ```
1707
1538
  */
1708
- declare function defineExchangeBinding(destination: ExchangeDefinition, source: FanoutExchangeDefinition, options?: Omit<Extract<ExchangeBindingDefinition, {
1709
- source: FanoutExchangeDefinition;
1539
+ declare function defineExchangeBinding(destination: ExchangeDefinition, source: FanoutExchangeDefinition | HeadersExchangeDefinition, options?: Omit<Extract<ExchangeBindingDefinition, {
1540
+ source: FanoutExchangeDefinition | HeadersExchangeDefinition;
1710
1541
  }>, "type" | "source" | "destination" | "routingKey">): Extract<ExchangeBindingDefinition, {
1711
- source: FanoutExchangeDefinition;
1542
+ source: FanoutExchangeDefinition | HeadersExchangeDefinition;
1712
1543
  }>;
1713
1544
  /**
1714
1545
  * Define a binding between two exchanges (exchange-to-exchange routing).
@@ -1725,8 +1556,8 @@ declare function defineExchangeBinding(destination: ExchangeDefinition, source:
1725
1556
  *
1726
1557
  * @example
1727
1558
  * ```typescript
1728
- * const ordersExchange = defineExchange('orders', 'topic', { durable: true });
1729
- * const importantExchange = defineExchange('important-orders', 'topic', { durable: true });
1559
+ * const ordersExchange = defineExchange('orders');
1560
+ * const importantExchange = defineExchange('important-orders');
1730
1561
  *
1731
1562
  * // Forward only high-value orders
1732
1563
  * const binding = defineExchangeBinding(importantExchange, ordersExchange, {
@@ -1742,10 +1573,11 @@ declare function defineExchangeBinding(destination: ExchangeDefinition, source:
1742
1573
  //#endregion
1743
1574
  //#region src/builder/publisher.d.ts
1744
1575
  /**
1745
- * Define a message publisher for a fanout exchange.
1576
+ * Define a message publisher for a fanout or headers exchange.
1746
1577
  *
1747
1578
  * A publisher sends messages to an exchange. For fanout exchanges, messages are broadcast
1748
- * to all bound queues regardless of routing key, so no routing key is required.
1579
+ * to all bound queues regardless of routing key, so no routing key is required. For headers exchanges,
1580
+ * routing is based on message headers rather than routing keys, so no routing key is required either.
1749
1581
  *
1750
1582
  * The message schema is validated when publishing to ensure type safety.
1751
1583
  *
@@ -1762,7 +1594,7 @@ declare function defineExchangeBinding(destination: ExchangeDefinition, source:
1762
1594
  * - You want automatic schema consistency between publisher and consumers
1763
1595
  * - You're building event-driven architectures
1764
1596
  *
1765
- * @param exchange - The fanout exchange definition to publish to
1597
+ * @param exchange - The fanout or headers exchange definition to publish to
1766
1598
  * @param message - The message definition with payload schema
1767
1599
  * @param options - Optional publisher configuration
1768
1600
  * @returns A publisher definition with inferred message types
@@ -1771,7 +1603,7 @@ declare function defineExchangeBinding(destination: ExchangeDefinition, source:
1771
1603
  * ```typescript
1772
1604
  * import { z } from 'zod';
1773
1605
  *
1774
- * const logsExchange = defineExchange('logs', 'fanout', { durable: true });
1606
+ * const logsExchange = defineExchange('logs', { type: 'fanout' });
1775
1607
  * const logMessage = defineMessage(
1776
1608
  * z.object({
1777
1609
  * level: z.enum(['info', 'warn', 'error']),
@@ -1786,10 +1618,10 @@ declare function defineExchangeBinding(destination: ExchangeDefinition, source:
1786
1618
  * @see defineEventPublisher - For event-driven patterns with automatic schema consistency
1787
1619
  * @see defineCommandConsumer - For task queue patterns with automatic schema consistency
1788
1620
  */
1789
- declare function definePublisher<TMessage extends MessageDefinition>(exchange: FanoutExchangeDefinition, message: TMessage, options?: Omit<Extract<PublisherDefinition<TMessage>, {
1790
- exchange: FanoutExchangeDefinition;
1621
+ declare function definePublisher<TMessage extends MessageDefinition>(exchange: FanoutExchangeDefinition | HeadersExchangeDefinition, message: TMessage, options?: Omit<Extract<PublisherDefinition<TMessage>, {
1622
+ exchange: FanoutExchangeDefinition | HeadersExchangeDefinition;
1791
1623
  }>, "exchange" | "message" | "routingKey">): Extract<PublisherDefinition<TMessage>, {
1792
- exchange: FanoutExchangeDefinition;
1624
+ exchange: FanoutExchangeDefinition | HeadersExchangeDefinition;
1793
1625
  }>;
1794
1626
  /**
1795
1627
  * Define a message publisher for a direct or topic exchange.
@@ -1822,7 +1654,7 @@ declare function definePublisher<TMessage extends MessageDefinition>(exchange: F
1822
1654
  * ```typescript
1823
1655
  * import { z } from 'zod';
1824
1656
  *
1825
- * const ordersExchange = defineExchange('orders', 'topic', { durable: true });
1657
+ * const ordersExchange = defineExchange('orders');
1826
1658
  * const orderMessage = defineMessage(
1827
1659
  * z.object({
1828
1660
  * orderId: z.string().uuid(),
@@ -1911,7 +1743,7 @@ declare function extractConsumer(entry: ConsumerEntry): ConsumerDefinition;
1911
1743
  * ```typescript
1912
1744
  * import { z } from 'zod';
1913
1745
  *
1914
- * const orderQueue = defineQueue('order-processing', { durable: true });
1746
+ * const orderQueue = defineQueue('order-processing');
1915
1747
  * const orderMessage = defineMessage(
1916
1748
  * z.object({
1917
1749
  * orderId: z.string().uuid(),
@@ -1970,12 +1802,11 @@ declare function defineConsumer<TMessage extends MessageDefinition>(queue: Queue
1970
1802
  * import { z } from 'zod';
1971
1803
  *
1972
1804
  * // Define resources
1973
- * const ordersExchange = defineExchange('orders', 'topic', { durable: true });
1974
- * const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
1805
+ * const ordersExchange = defineExchange('orders');
1806
+ * const dlx = defineExchange('orders-dlx', { type: 'direct' });
1975
1807
  * const orderQueue = defineQueue('order-processing', {
1976
1808
  * deadLetter: { exchange: dlx },
1977
- * retry: { mode: 'quorum-native' },
1978
- * deliveryLimit: 3,
1809
+ * retry: { mode: 'immediate-requeue', maxRetries: 3 },
1979
1810
  * });
1980
1811
  * const orderMessage = defineMessage(
1981
1812
  * z.object({
@@ -2097,7 +1928,7 @@ type MatchingRoutingKey<Pattern extends string, Key extends string> = RoutingKey
2097
1928
  *
2098
1929
  * @template TMessage - The message definition
2099
1930
  * @template TExchange - The exchange definition
2100
- * @template TRoutingKey - The routing key type (undefined for fanout)
1931
+ * @template TRoutingKey - The routing key type (undefined for fanout and headers exchanges)
2101
1932
  */
2102
1933
  type EventPublisherConfig<TMessage extends MessageDefinition, TExchange extends ExchangeDefinition, TRoutingKey extends string | undefined = undefined> = {
2103
1934
  /** Discriminator to identify this as an event publisher config */__brand: "EventPublisherConfig"; /** The exchange to publish to */
@@ -2115,13 +1946,12 @@ type EventPublisherConfig<TMessage extends MessageDefinition, TExchange extends
2115
1946
  *
2116
1947
  * @template TMessage - The message definition
2117
1948
  */
2118
- type EventConsumerResult<TMessage extends MessageDefinition, TExchange extends ExchangeDefinition = ExchangeDefinition, TQueue extends QueueDefinition = QueueDefinition, TDlxExchange extends ExchangeDefinition | undefined = ExchangeDefinition | undefined, TExchangeBinding extends ExchangeBindingDefinition | undefined = ExchangeBindingDefinition | undefined, TBridgeExchange extends ExchangeDefinition | undefined = ExchangeDefinition | undefined> = {
1949
+ type EventConsumerResult<TMessage extends MessageDefinition, TExchange extends ExchangeDefinition = ExchangeDefinition, TQueue extends QueueEntry = QueueEntry, TExchangeBinding extends ExchangeBindingDefinition | undefined = ExchangeBindingDefinition | undefined, TBridgeExchange extends ExchangeDefinition | undefined = ExchangeDefinition | undefined> = {
2119
1950
  /** Discriminator to identify this as an event consumer result */__brand: "EventConsumerResult"; /** The consumer definition for processing messages */
2120
1951
  consumer: ConsumerDefinition<TMessage>; /** The binding connecting the queue to the exchange */
2121
1952
  binding: QueueBindingDefinition; /** The source exchange this consumer subscribes to */
2122
1953
  exchange: TExchange; /** The queue this consumer reads from */
2123
- queue: TQueue; /** The dead letter exchange from the queue, if configured */
2124
- deadLetterExchange: TDlxExchange; /** The exchange-to-exchange binding when bridging, if configured */
1954
+ queue: TQueue; /** The exchange-to-exchange binding when bridging, if configured */
2125
1955
  exchangeBinding: TExchangeBinding; /** The bridge (local domain) exchange when bridging, if configured */
2126
1956
  bridgeExchange: TBridgeExchange;
2127
1957
  };
@@ -2133,11 +1963,13 @@ type EventConsumerResult<TMessage extends MessageDefinition, TExchange extends E
2133
1963
  *
2134
1964
  * @param exchange - The fanout exchange to publish to
2135
1965
  * @param message - The message definition (schema and metadata)
1966
+ * @param options - Optional binding configuration
1967
+ * @param options.arguments - Additional AMQP arguments
2136
1968
  * @returns An event publisher configuration
2137
1969
  *
2138
1970
  * @example
2139
1971
  * ```typescript
2140
- * const logsExchange = defineExchange('logs', 'fanout', { durable: true });
1972
+ * const logsExchange = defineExchange('logs', { type: 'fanout' });
2141
1973
  * const logMessage = defineMessage(z.object({
2142
1974
  * level: z.enum(['info', 'warn', 'error']),
2143
1975
  * message: z.string(),
@@ -2153,7 +1985,42 @@ type EventConsumerResult<TMessage extends MessageDefinition, TExchange extends E
2153
1985
  * defineEventConsumer(logEvent, alertsQueue);
2154
1986
  * ```
2155
1987
  */
2156
- declare function defineEventPublisher<TMessage extends MessageDefinition, TExchange extends FanoutExchangeDefinition>(exchange: TExchange, message: TMessage): EventPublisherConfig<TMessage, TExchange, undefined>;
1988
+ declare function defineEventPublisher<TMessage extends MessageDefinition, TExchange extends FanoutExchangeDefinition>(exchange: TExchange, message: TMessage, options?: {
1989
+ arguments?: Record<string, unknown>;
1990
+ }): EventPublisherConfig<TMessage, TExchange, undefined>;
1991
+ /**
1992
+ * Define an event publisher for broadcasting messages via headers exchange.
1993
+ *
1994
+ * Events are published without knowing who consumes them. Multiple consumers
1995
+ * can subscribe to the same event using `defineEventConsumer`.
1996
+ *
1997
+ * @param exchange - The headers exchange to publish to
1998
+ * @param message - The message definition (schema and metadata)
1999
+ * @param options - Optional binding configuration
2000
+ * @param options.arguments - Additional AMQP arguments
2001
+ * @returns An event publisher configuration
2002
+ *
2003
+ * @example
2004
+ * ```typescript
2005
+ * const logsExchange = defineExchange('logs', { type: 'headers' });
2006
+ * const logMessage = defineMessage(z.object({
2007
+ * level: z.enum(['info', 'warn', 'error']),
2008
+ * message: z.string(),
2009
+ * }));
2010
+ *
2011
+ * // Create event publisher
2012
+ * const logEvent = defineEventPublisher(logsExchange, logMessage);
2013
+ *
2014
+ * // Multiple consumers can subscribe
2015
+ * const { consumer: fileConsumer, binding: fileBinding } =
2016
+ * defineEventConsumer(logEvent, fileLogsQueue);
2017
+ * const { consumer: alertConsumer, binding: alertBinding } =
2018
+ * defineEventConsumer(logEvent, alertsQueue);
2019
+ * ```
2020
+ */
2021
+ declare function defineEventPublisher<TMessage extends MessageDefinition, TExchange extends HeadersExchangeDefinition>(exchange: TExchange, message: TMessage, options?: {
2022
+ arguments?: Record<string, unknown>;
2023
+ }): EventPublisherConfig<TMessage, TExchange, undefined>;
2157
2024
  /**
2158
2025
  * Define an event publisher for broadcasting messages via direct exchange.
2159
2026
  *
@@ -2169,7 +2036,7 @@ declare function defineEventPublisher<TMessage extends MessageDefinition, TExcha
2169
2036
  *
2170
2037
  * @example
2171
2038
  * ```typescript
2172
- * const tasksExchange = defineExchange('tasks', 'direct', { durable: true });
2039
+ * const tasksExchange = defineExchange('tasks', { type: 'direct' });
2173
2040
  * const taskMessage = defineMessage(z.object({ taskId: z.string() }));
2174
2041
  *
2175
2042
  * const taskEvent = defineEventPublisher(tasksExchange, taskMessage, {
@@ -2196,7 +2063,7 @@ declare function defineEventPublisher<TMessage extends MessageDefinition, TRouti
2196
2063
  *
2197
2064
  * @example
2198
2065
  * ```typescript
2199
- * const ordersExchange = defineExchange('orders', 'topic', { durable: true });
2066
+ * const ordersExchange = defineExchange('orders', { type: 'topic' });
2200
2067
  * const orderMessage = defineMessage(z.object({
2201
2068
  * orderId: z.string(),
2202
2069
  * amount: z.number(),
@@ -2229,12 +2096,30 @@ declare function defineEventPublisher<TMessage extends MessageDefinition, TRouti
2229
2096
  * @param queue - The queue that will receive messages
2230
2097
  * @param options - Binding configuration with required bridgeExchange
2231
2098
  * @param options.bridgeExchange - The fanout bridge exchange (must be fanout to match source)
2099
+ * @param options.arguments - Additional AMQP arguments
2232
2100
  * @returns An object with the consumer definition, queue binding, and exchange binding
2233
2101
  */
2234
2102
  declare function defineEventConsumer<TMessage extends MessageDefinition, TExchange extends FanoutExchangeDefinition, TQueueEntry extends QueueEntry, TBridgeExchange extends FanoutExchangeDefinition>(eventPublisher: EventPublisherConfig<TMessage, TExchange, undefined>, queue: TQueueEntry, options: {
2235
2103
  bridgeExchange: TBridgeExchange;
2236
2104
  arguments?: Record<string, unknown>;
2237
- }): EventConsumerResult<TMessage, TExchange, ExtractQueueFromEntry<TQueueEntry>, ExtractDlxFromEntry<TQueueEntry>, ExchangeBindingDefinition, TBridgeExchange>;
2105
+ }): EventConsumerResult<TMessage, TExchange, TQueueEntry, ExchangeBindingDefinition, TBridgeExchange>;
2106
+ /**
2107
+ * Create a consumer that subscribes to an event from a headers exchange via a bridge exchange.
2108
+ *
2109
+ * When `bridgeExchange` is provided, the queue binds to the bridge exchange instead of the
2110
+ * source exchange, and an exchange-to-exchange binding is created from the source to the bridge.
2111
+ *
2112
+ * @param eventPublisher - The event publisher configuration
2113
+ * @param queue - The queue that will receive messages
2114
+ * @param options - Binding configuration with required bridgeExchange
2115
+ * @param options.bridgeExchange - The headers bridge exchange (must be headers to match source)
2116
+ * @param options.arguments - Additional AMQP arguments
2117
+ * @returns An object with the consumer definition, queue binding, and exchange binding
2118
+ */
2119
+ declare function defineEventConsumer<TMessage extends MessageDefinition, TExchange extends HeadersExchangeDefinition, TQueueEntry extends QueueEntry, TBridgeExchange extends HeadersExchangeDefinition>(eventPublisher: EventPublisherConfig<TMessage, TExchange, undefined>, queue: TQueueEntry, options: {
2120
+ bridgeExchange: TBridgeExchange;
2121
+ arguments?: Record<string, unknown>;
2122
+ }): EventConsumerResult<TMessage, TExchange, TQueueEntry, ExchangeBindingDefinition, TBridgeExchange>;
2238
2123
  /**
2239
2124
  * Create a consumer that subscribes to an event from a direct exchange via a bridge exchange.
2240
2125
  *
@@ -2242,12 +2127,13 @@ declare function defineEventConsumer<TMessage extends MessageDefinition, TExchan
2242
2127
  * @param queue - The queue that will receive messages
2243
2128
  * @param options - Binding configuration with required bridgeExchange
2244
2129
  * @param options.bridgeExchange - The bridge exchange (must be direct or topic to preserve routing keys)
2130
+ * @param options.arguments - Additional AMQP arguments
2245
2131
  * @returns An object with the consumer definition, queue binding, and exchange binding
2246
2132
  */
2247
2133
  declare function defineEventConsumer<TMessage extends MessageDefinition, TRoutingKey extends string, TExchange extends DirectExchangeDefinition, TQueueEntry extends QueueEntry, TBridgeExchange extends DirectExchangeDefinition | TopicExchangeDefinition>(eventPublisher: EventPublisherConfig<TMessage, TExchange, TRoutingKey>, queue: TQueueEntry, options: {
2248
2134
  bridgeExchange: TBridgeExchange;
2249
2135
  arguments?: Record<string, unknown>;
2250
- }): EventConsumerResult<TMessage, TExchange, ExtractQueueFromEntry<TQueueEntry>, ExtractDlxFromEntry<TQueueEntry>, ExchangeBindingDefinition, TBridgeExchange>;
2136
+ }): EventConsumerResult<TMessage, TExchange, TQueueEntry, ExchangeBindingDefinition, TBridgeExchange>;
2251
2137
  /**
2252
2138
  * Create a consumer that subscribes to an event from a topic exchange via a bridge exchange.
2253
2139
  *
@@ -2256,19 +2142,21 @@ declare function defineEventConsumer<TMessage extends MessageDefinition, TRoutin
2256
2142
  * @param options - Binding configuration with required bridgeExchange
2257
2143
  * @param options.bridgeExchange - The bridge exchange (must be direct or topic to preserve routing keys)
2258
2144
  * @param options.routingKey - Override routing key with pattern (defaults to publisher's key)
2145
+ * @param options.arguments - Additional AMQP arguments
2259
2146
  * @returns An object with the consumer definition, queue binding, and exchange binding
2260
2147
  */
2261
2148
  declare function defineEventConsumer<TMessage extends MessageDefinition, TRoutingKey extends string, TExchange extends TopicExchangeDefinition, TQueueEntry extends QueueEntry, TBridgeExchange extends DirectExchangeDefinition | TopicExchangeDefinition, TConsumerRoutingKey extends string = TRoutingKey>(eventPublisher: EventPublisherConfig<TMessage, TExchange, TRoutingKey>, queue: TQueueEntry, options: {
2262
2149
  bridgeExchange: TBridgeExchange;
2263
2150
  routingKey?: BindingPattern<TConsumerRoutingKey>;
2264
2151
  arguments?: Record<string, unknown>;
2265
- }): EventConsumerResult<TMessage, TExchange, ExtractQueueFromEntry<TQueueEntry>, ExtractDlxFromEntry<TQueueEntry>, ExchangeBindingDefinition, TBridgeExchange>;
2152
+ }): EventConsumerResult<TMessage, TExchange, TQueueEntry, ExchangeBindingDefinition, TBridgeExchange>;
2266
2153
  /**
2267
2154
  * Create a consumer that subscribes to an event from a fanout exchange.
2268
2155
  *
2269
2156
  * @param eventPublisher - The event publisher configuration
2270
2157
  * @param queue - The queue that will receive messages
2271
2158
  * @param options - Optional binding configuration
2159
+ * @param options.arguments - Additional AMQP arguments
2272
2160
  * @returns An object with the consumer definition and binding
2273
2161
  *
2274
2162
  * @example
@@ -2279,18 +2167,37 @@ declare function defineEventConsumer<TMessage extends MessageDefinition, TRoutin
2279
2167
  */
2280
2168
  declare function defineEventConsumer<TMessage extends MessageDefinition, TExchange extends FanoutExchangeDefinition, TQueueEntry extends QueueEntry>(eventPublisher: EventPublisherConfig<TMessage, TExchange, undefined>, queue: TQueueEntry, options?: {
2281
2169
  arguments?: Record<string, unknown>;
2282
- }): EventConsumerResult<TMessage, TExchange, ExtractQueueFromEntry<TQueueEntry>, ExtractDlxFromEntry<TQueueEntry>>;
2170
+ }): EventConsumerResult<TMessage, TExchange, TQueueEntry>;
2171
+ /**
2172
+ * Create a consumer that subscribes to an event from a headers exchange.
2173
+ *
2174
+ * @param eventPublisher - The event publisher configuration
2175
+ * @param queue - The queue that will receive messages
2176
+ * @param options - Optional binding configuration
2177
+ * @param options.arguments - Additional AMQP arguments
2178
+ * @returns An object with the consumer definition and binding
2179
+ *
2180
+ * @example
2181
+ * ```typescript
2182
+ * const logEvent = defineEventPublisher(logsExchange, logMessage);
2183
+ * const { consumer, binding } = defineEventConsumer(logEvent, logsQueue);
2184
+ * ```
2185
+ */
2186
+ declare function defineEventConsumer<TMessage extends MessageDefinition, TExchange extends HeadersExchangeDefinition, TQueueEntry extends QueueEntry>(eventPublisher: EventPublisherConfig<TMessage, TExchange, undefined>, queue: TQueueEntry, options?: {
2187
+ arguments?: Record<string, unknown>;
2188
+ }): EventConsumerResult<TMessage, TExchange, TQueueEntry>;
2283
2189
  /**
2284
2190
  * Create a consumer that subscribes to an event from a direct exchange.
2285
2191
  *
2286
2192
  * @param eventPublisher - The event publisher configuration
2287
2193
  * @param queue - The queue that will receive messages
2288
2194
  * @param options - Optional binding configuration
2195
+ * @param options.arguments - Additional AMQP arguments
2289
2196
  * @returns An object with the consumer definition and binding
2290
2197
  */
2291
2198
  declare function defineEventConsumer<TMessage extends MessageDefinition, TRoutingKey extends string, TExchange extends DirectExchangeDefinition, TQueueEntry extends QueueEntry>(eventPublisher: EventPublisherConfig<TMessage, TExchange, TRoutingKey>, queue: TQueueEntry, options?: {
2292
2199
  arguments?: Record<string, unknown>;
2293
- }): EventConsumerResult<TMessage, TExchange, ExtractQueueFromEntry<TQueueEntry>, ExtractDlxFromEntry<TQueueEntry>>;
2200
+ }): EventConsumerResult<TMessage, TExchange, TQueueEntry>;
2294
2201
  /**
2295
2202
  * Create a consumer that subscribes to an event from a topic exchange.
2296
2203
  *
@@ -2301,6 +2208,7 @@ declare function defineEventConsumer<TMessage extends MessageDefinition, TRoutin
2301
2208
  * @param queue - The queue that will receive messages
2302
2209
  * @param options - Optional binding configuration
2303
2210
  * @param options.routingKey - Override routing key with pattern (defaults to publisher's key)
2211
+ * @param options.arguments - Additional AMQP arguments
2304
2212
  * @returns An object with the consumer definition and binding
2305
2213
  *
2306
2214
  * @example
@@ -2321,7 +2229,7 @@ declare function defineEventConsumer<TMessage extends MessageDefinition, TRoutin
2321
2229
  declare function defineEventConsumer<TMessage extends MessageDefinition, TRoutingKey extends string, TExchange extends TopicExchangeDefinition, TQueueEntry extends QueueEntry, TConsumerRoutingKey extends string = TRoutingKey>(eventPublisher: EventPublisherConfig<TMessage, TExchange, TRoutingKey>, queue: TQueueEntry, options?: {
2322
2230
  routingKey?: BindingPattern<TConsumerRoutingKey>;
2323
2231
  arguments?: Record<string, unknown>;
2324
- }): EventConsumerResult<TMessage, TExchange, ExtractQueueFromEntry<TQueueEntry>, ExtractDlxFromEntry<TQueueEntry>>;
2232
+ }): EventConsumerResult<TMessage, TExchange, TQueueEntry>;
2325
2233
  /**
2326
2234
  * Type guard to check if a value is an EventPublisherConfig.
2327
2235
  *
@@ -2346,15 +2254,14 @@ declare function isEventConsumerResult(value: unknown): value is EventConsumerRe
2346
2254
  *
2347
2255
  * @template TMessage - The message definition
2348
2256
  * @template TExchange - The exchange definition
2349
- * @template TRoutingKey - The routing key type (undefined for fanout)
2257
+ * @template TRoutingKey - The routing key type (undefined for fanout and headers exchanges)
2350
2258
  */
2351
- type CommandConsumerConfig<TMessage extends MessageDefinition, TExchange extends ExchangeDefinition, TRoutingKey extends string | undefined = undefined, TQueue extends QueueDefinition = QueueDefinition, TDlxExchange extends ExchangeDefinition | undefined = ExchangeDefinition | undefined> = {
2259
+ type CommandConsumerConfig<TMessage extends MessageDefinition, TExchange extends ExchangeDefinition, TRoutingKey extends string | undefined = undefined, TQueue extends QueueEntry = QueueEntry> = {
2352
2260
  /** Discriminator to identify this as a command consumer config */__brand: "CommandConsumerConfig"; /** The consumer definition for processing commands */
2353
2261
  consumer: ConsumerDefinition<TMessage>; /** The binding connecting the queue to the exchange */
2354
2262
  binding: QueueBindingDefinition; /** The exchange that receives commands */
2355
2263
  exchange: TExchange; /** The queue this consumer reads from */
2356
- queue: TQueue; /** The dead letter exchange from the queue, if configured */
2357
- deadLetterExchange: TDlxExchange; /** The message definition */
2264
+ queue: TQueue; /** The message definition */
2358
2265
  message: TMessage; /** The routing key pattern for the binding */
2359
2266
  routingKey: TRoutingKey;
2360
2267
  };
@@ -2384,11 +2291,41 @@ type BridgedPublisherConfig<TMessage extends MessageDefinition, TBridgeExchange
2384
2291
  * @param queue - The queue that will receive commands
2385
2292
  * @param exchange - The fanout exchange that routes commands
2386
2293
  * @param message - The message definition (schema and metadata)
2294
+ * @param options - Optional binding configuration
2295
+ * @param options.arguments - Additional AMQP arguments
2296
+ * @returns A command consumer configuration
2297
+ *
2298
+ * @example
2299
+ * ```typescript
2300
+ * const tasksExchange = defineExchange('tasks', { type: 'fanout' });
2301
+ * const taskMessage = defineMessage(z.object({ taskId: z.string() }));
2302
+ *
2303
+ * // Consumer owns the queue
2304
+ * const executeTask = defineCommandConsumer(taskQueue, tasksExchange, taskMessage);
2305
+ *
2306
+ * // Publishers send commands to it
2307
+ * const sendTask = defineCommandPublisher(executeTask);
2308
+ * ```
2309
+ */
2310
+ declare function defineCommandConsumer<TMessage extends MessageDefinition, TQueueEntry extends QueueEntry, TExchange extends FanoutExchangeDefinition>(queue: TQueueEntry, exchange: TExchange, message: TMessage, options?: {
2311
+ arguments?: Record<string, unknown>;
2312
+ }): CommandConsumerConfig<TMessage, TExchange, undefined, TQueueEntry>;
2313
+ /**
2314
+ * Define a command consumer for receiving commands via headers exchange.
2315
+ *
2316
+ * Commands are sent by publishers to a specific queue. The consumer "owns" the
2317
+ * queue and defines what commands it accepts.
2318
+ *
2319
+ * @param queue - The queue that will receive commands
2320
+ * @param exchange - The headers exchange that routes commands
2321
+ * @param message - The message definition (schema and metadata)
2322
+ * @param options - Optional binding configuration
2323
+ * @param options.arguments - Additional AMQP arguments
2387
2324
  * @returns A command consumer configuration
2388
2325
  *
2389
2326
  * @example
2390
2327
  * ```typescript
2391
- * const tasksExchange = defineExchange('tasks', 'fanout', { durable: true });
2328
+ * const tasksExchange = defineExchange('tasks', { type: 'headers' });
2392
2329
  * const taskMessage = defineMessage(z.object({ taskId: z.string() }));
2393
2330
  *
2394
2331
  * // Consumer owns the queue
@@ -2398,7 +2335,9 @@ type BridgedPublisherConfig<TMessage extends MessageDefinition, TBridgeExchange
2398
2335
  * const sendTask = defineCommandPublisher(executeTask);
2399
2336
  * ```
2400
2337
  */
2401
- declare function defineCommandConsumer<TMessage extends MessageDefinition, TQueueEntry extends QueueEntry, TExchange extends FanoutExchangeDefinition>(queue: TQueueEntry, exchange: TExchange, message: TMessage): CommandConsumerConfig<TMessage, TExchange, undefined, ExtractQueueFromEntry<TQueueEntry>, ExtractDlxFromEntry<TQueueEntry>>;
2338
+ declare function defineCommandConsumer<TMessage extends MessageDefinition, TQueueEntry extends QueueEntry, TExchange extends HeadersExchangeDefinition>(queue: TQueueEntry, exchange: TExchange, message: TMessage, options?: {
2339
+ arguments?: Record<string, unknown>;
2340
+ }): CommandConsumerConfig<TMessage, TExchange, undefined, TQueueEntry>;
2402
2341
  /**
2403
2342
  * Define a command consumer for receiving commands via direct exchange.
2404
2343
  *
@@ -2415,7 +2354,7 @@ declare function defineCommandConsumer<TMessage extends MessageDefinition, TQueu
2415
2354
  *
2416
2355
  * @example
2417
2356
  * ```typescript
2418
- * const tasksExchange = defineExchange('tasks', 'direct', { durable: true });
2357
+ * const tasksExchange = defineExchange('tasks', { type: 'direct' });
2419
2358
  * const taskMessage = defineMessage(z.object({ taskId: z.string() }));
2420
2359
  *
2421
2360
  * const executeTask = defineCommandConsumer(taskQueue, tasksExchange, taskMessage, {
@@ -2428,7 +2367,7 @@ declare function defineCommandConsumer<TMessage extends MessageDefinition, TQueu
2428
2367
  declare function defineCommandConsumer<TMessage extends MessageDefinition, TRoutingKey extends string, TQueueEntry extends QueueEntry, TExchange extends DirectExchangeDefinition>(queue: TQueueEntry, exchange: TExchange, message: TMessage, options: {
2429
2368
  routingKey: RoutingKey<TRoutingKey>;
2430
2369
  arguments?: Record<string, unknown>;
2431
- }): CommandConsumerConfig<TMessage, TExchange, TRoutingKey, ExtractQueueFromEntry<TQueueEntry>, ExtractDlxFromEntry<TQueueEntry>>;
2370
+ }): CommandConsumerConfig<TMessage, TExchange, TRoutingKey, TQueueEntry>;
2432
2371
  /**
2433
2372
  * Define a command consumer for receiving commands via topic exchange.
2434
2373
  *
@@ -2445,7 +2384,7 @@ declare function defineCommandConsumer<TMessage extends MessageDefinition, TRout
2445
2384
  *
2446
2385
  * @example
2447
2386
  * ```typescript
2448
- * const ordersExchange = defineExchange('orders', 'topic', { durable: true });
2387
+ * const ordersExchange = defineExchange('orders', { type: 'topic' });
2449
2388
  * const orderMessage = defineMessage(z.object({ orderId: z.string() }));
2450
2389
  *
2451
2390
  * // Consumer uses pattern to receive multiple command types
@@ -2465,18 +2404,29 @@ declare function defineCommandConsumer<TMessage extends MessageDefinition, TRout
2465
2404
  declare function defineCommandConsumer<TMessage extends MessageDefinition, TRoutingKey extends string, TQueueEntry extends QueueEntry, TExchange extends TopicExchangeDefinition>(queue: TQueueEntry, exchange: TExchange, message: TMessage, options: {
2466
2405
  routingKey: BindingPattern<TRoutingKey>;
2467
2406
  arguments?: Record<string, unknown>;
2468
- }): CommandConsumerConfig<TMessage, TExchange, TRoutingKey, ExtractQueueFromEntry<TQueueEntry>, ExtractDlxFromEntry<TQueueEntry>>;
2407
+ }): CommandConsumerConfig<TMessage, TExchange, TRoutingKey, TQueueEntry>;
2469
2408
  /**
2470
2409
  * Create a bridged publisher that sends commands to a fanout exchange consumer via a bridge exchange.
2471
2410
  *
2472
2411
  * @param commandConsumer - The command consumer configuration
2473
2412
  * @param options - Configuration with required bridgeExchange
2474
- * @param options.bridgeExchange - The local domain exchange to bridge through
2413
+ * @param options.bridgeExchange - The local domain exchange to bridge through (must be fanout to match target)
2475
2414
  * @returns A bridged publisher configuration
2476
2415
  */
2477
2416
  declare function defineCommandPublisher<TMessage extends MessageDefinition, TExchange extends FanoutExchangeDefinition, TBridgeExchange extends FanoutExchangeDefinition>(commandConsumer: CommandConsumerConfig<TMessage, TExchange, undefined>, options: {
2478
2417
  bridgeExchange: TBridgeExchange;
2479
2418
  }): BridgedPublisherConfig<TMessage, TBridgeExchange, TExchange>;
2419
+ /**
2420
+ * Create a bridged publisher that sends commands to a headers exchange consumer via a bridge exchange.
2421
+ *
2422
+ * @param commandConsumer - The command consumer configuration
2423
+ * @param options - Configuration with required bridgeExchange
2424
+ * @param options.bridgeExchange - The local domain exchange to bridge through (must be headers to match target)
2425
+ * @returns A bridged publisher configuration
2426
+ */
2427
+ declare function defineCommandPublisher<TMessage extends MessageDefinition, TExchange extends HeadersExchangeDefinition, TBridgeExchange extends HeadersExchangeDefinition>(commandConsumer: CommandConsumerConfig<TMessage, TExchange, undefined>, options: {
2428
+ bridgeExchange: TBridgeExchange;
2429
+ }): BridgedPublisherConfig<TMessage, TBridgeExchange, TExchange>;
2480
2430
  /**
2481
2431
  * Create a bridged publisher that sends commands to a direct exchange consumer via a bridge exchange.
2482
2432
  *
@@ -2517,6 +2467,22 @@ declare function defineCommandPublisher<TMessage extends MessageDefinition>(comm
2517
2467
  message: TMessage;
2518
2468
  exchange: FanoutExchangeDefinition;
2519
2469
  };
2470
+ /**
2471
+ * Create a publisher that sends commands to a headers exchange consumer.
2472
+ *
2473
+ * @param commandConsumer - The command consumer configuration
2474
+ * @returns A publisher definition
2475
+ *
2476
+ * @example
2477
+ * ```typescript
2478
+ * const executeTask = defineCommandConsumer(taskQueue, headersExchange, taskMessage);
2479
+ * const sendTask = defineCommandPublisher(executeTask);
2480
+ * ```
2481
+ */
2482
+ declare function defineCommandPublisher<TMessage extends MessageDefinition>(commandConsumer: CommandConsumerConfig<TMessage, HeadersExchangeDefinition, undefined>): {
2483
+ message: TMessage;
2484
+ exchange: HeadersExchangeDefinition;
2485
+ };
2520
2486
  /**
2521
2487
  * Create a publisher that sends commands to a direct exchange consumer.
2522
2488
  *
@@ -2535,7 +2501,7 @@ declare function defineCommandPublisher<TMessage extends MessageDefinition, TRou
2535
2501
  * optionally specify a concrete routing key that matches the pattern.
2536
2502
  *
2537
2503
  * @param commandConsumer - The command consumer configuration
2538
- * @param options - Optional publisher configuration
2504
+ * @param options - Optional binding configuration
2539
2505
  * @param options.routingKey - Override routing key (must match consumer's pattern)
2540
2506
  * @returns A publisher definition
2541
2507
  *
@@ -2576,70 +2542,38 @@ declare function isBridgedPublisherConfig(value: unknown): value is BridgedPubli
2576
2542
  //#endregion
2577
2543
  //#region src/builder/ttl-backoff.d.ts
2578
2544
  /**
2579
- * Result type for TTL-backoff retry infrastructure builder.
2545
+ * Type guard to check if a queue entry is a QueueWithTtlBackoffInfrastructure.
2580
2546
  *
2581
- * Contains the wait queue and bindings needed for TTL-backoff retry.
2582
- */
2583
- type TtlBackoffRetryInfrastructure = {
2584
- /**
2585
- * The wait queue for holding messages during backoff delay.
2586
- * This is a classic queue with a dead letter exchange pointing back to the main queue.
2587
- */
2588
- waitQueue: QueueDefinition;
2589
- /**
2590
- * Binding that routes failed messages to the wait queue.
2591
- */
2592
- waitQueueBinding: QueueBindingDefinition;
2593
- /**
2594
- * Binding that routes retried messages back to the main queue.
2595
- */
2596
- mainQueueRetryBinding: QueueBindingDefinition;
2597
- };
2598
- /**
2599
- * Create TTL-backoff retry infrastructure for a queue.
2547
+ * When you configure a queue with TTL-backoff retry,
2548
+ * `defineQueue` returns a `QueueWithTtlBackoffInfrastructure` instead of a plain
2549
+ * `QueueDefinition`. This type guard helps you distinguish between the two.
2600
2550
  *
2601
- * This builder helper generates the wait queue and bindings needed for TTL-backoff retry.
2602
- * The generated infrastructure can be spread into a contract definition.
2551
+ * **When to use:**
2552
+ * - When you need to check the type of a queue entry at runtime
2553
+ * - When writing generic code that handles both plain queues and infrastructure wrappers
2603
2554
  *
2604
- * TTL-backoff retry works by:
2605
- * 1. Failed messages are sent to the DLX with routing key `{queueName}-wait`
2606
- * 2. The wait queue receives these messages and holds them for a TTL period
2607
- * 3. After TTL expires, messages are dead-lettered back to the DLX with routing key `{queueName}`
2608
- * 4. The main queue receives the retried message via its binding to the DLX
2555
+ * **Related functions:**
2556
+ * - `extractQueue()` - Use this to get the underlying queue definition from either type
2609
2557
  *
2610
- * @param queue - The main queue definition (must have deadLetter configured)
2611
- * @param options - Optional configuration for the wait queue
2612
- * @param options.waitQueueDurable - Whether the wait queue should be durable (default: same as main queue)
2613
- * @returns TTL-backoff retry infrastructure containing wait queue and bindings
2614
- * @throws {Error} If the queue does not have a dead letter exchange configured
2558
+ * @param entry - The queue entry to check
2559
+ * @returns True if the entry is a QueueWithTtlBackoffInfrastructure, false otherwise
2615
2560
  *
2616
2561
  * @example
2617
2562
  * ```typescript
2618
- * const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
2619
- * const orderQueue = defineQueue('order-processing', {
2620
- * type: 'quorum',
2621
- * deadLetter: { exchange: dlx },
2622
- * retry: {
2623
- * mode: 'ttl-backoff',
2624
- * maxRetries: 5,
2625
- * initialDelayMs: 1000,
2626
- * },
2627
- * });
2628
- *
2629
- * // Infrastructure is auto-extracted when using defineContract:
2630
- * const contract = defineContract({
2631
- * publishers: { ... },
2632
- * consumers: { processOrder: defineEventConsumer(event, extractQueue(orderQueue)) },
2563
+ * const queue = defineQueue('orders', {
2564
+ * retry: { mode: 'ttl-backoff' },
2633
2565
  * });
2634
- * // contract.queues includes the wait queue, contract.bindings includes retry bindings
2635
2566
  *
2636
- * // Or generate manually for advanced use cases:
2637
- * const retryInfra = defineTtlBackoffRetryInfrastructure(orderQueue);
2567
+ * if (isQueueWithTtlBackoffInfrastructure(queue)) {
2568
+ * // queue has .queue, .waitQueue, .waitQueueBinding, .retryQueueBinding, .waitExchange, .retryExchange
2569
+ * console.log('Wait queue:', queue.waitQueue.name);
2570
+ * } else {
2571
+ * // queue is a plain QueueDefinition
2572
+ * console.log('Queue:', queue.name);
2573
+ * }
2638
2574
  * ```
2639
2575
  */
2640
- declare function defineTtlBackoffRetryInfrastructure(queueEntry: QueueEntry, options?: {
2641
- waitQueueDurable?: boolean;
2642
- }): TtlBackoffRetryInfrastructure;
2576
+ declare function isQueueWithTtlBackoffInfrastructure(entry: QueueEntry): entry is QueueWithTtlBackoffInfrastructure;
2643
2577
  //#endregion
2644
- export { type AnySchema, type BaseExchangeDefinition, type BindingDefinition, type BindingPattern, type BridgedPublisherConfig, type BridgedPublisherConfigBase, type ClassicQueueDefinition, type ClassicQueueOptions, type CommandConsumerConfig, type CommandConsumerConfigBase, type CompressionAlgorithm, type ConsumerDefinition, type ConsumerEntry, type ContractDefinition, type ContractDefinitionInput, type ContractOutput, type DeadLetterConfig, type DefineQueueOptions, type DefineQuorumQueueOptions, type DefineTtlBackoffQueueOptions, type DirectExchangeDefinition, type EventConsumerResult, type EventConsumerResultBase, type EventPublisherConfig, type EventPublisherConfigBase, type ExchangeBindingDefinition, type ExchangeDefinition, type FanoutExchangeDefinition, type InferConsumerNames, type InferPublisherNames, type MatchingRoutingKey, type MessageDefinition, type PublisherDefinition, type PublisherEntry, 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, defineCommandConsumer, defineCommandPublisher, defineConsumer, defineContract, defineEventConsumer, defineEventPublisher, defineExchange, defineExchangeBinding, defineMessage, definePublisher, defineQueue, defineQueueBinding, defineQuorumQueue, defineTtlBackoffQueue, defineTtlBackoffRetryInfrastructure, extractConsumer, extractQueue, isBridgedPublisherConfig, isCommandConsumerConfig, isEventConsumerResult, isEventPublisherConfig, isQueueWithTtlBackoffInfrastructure };
2578
+ export { type AnySchema, type BaseExchangeDefinition, type BindingDefinition, type BindingPattern, type BridgedPublisherConfig, type BridgedPublisherConfigBase, type ClassicQueueDefinition, type ClassicQueueOptions, type CommandConsumerConfig, type CommandConsumerConfigBase, type CompressionAlgorithm, type ConsumerDefinition, type ConsumerEntry, type ContractDefinition, type ContractDefinitionInput, type ContractOutput, type DeadLetterConfig, type DefineQueueOptions, type DirectExchangeDefinition, type EventConsumerResult, type EventConsumerResultBase, type EventPublisherConfig, type EventPublisherConfigBase, type ExchangeBindingDefinition, type ExchangeDefinition, type FanoutExchangeDefinition, type HeadersExchangeDefinition, type ImmediateRequeueRetryOptions, type InferConsumerNames, type InferPublisherNames, type MatchingRoutingKey, type MessageDefinition, type PublisherDefinition, type PublisherEntry, type QueueBindingDefinition, type QueueDefinition, type QueueEntry, type QueueType, type QueueWithTtlBackoffInfrastructure, type QuorumQueueDefinition, type QuorumQueueOptions, type ResolvedImmediateRequeueRetryOptions, type ResolvedRetryOptions, type ResolvedTtlBackoffRetryOptions, type RoutingKey, type TopicExchangeDefinition, type TtlBackoffRetryOptions, defineCommandConsumer, defineCommandPublisher, defineConsumer, defineContract, defineEventConsumer, defineEventPublisher, defineExchange, defineExchangeBinding, defineMessage, definePublisher, defineQueue, defineQueueBinding, extractConsumer, extractQueue, isBridgedPublisherConfig, isCommandConsumerConfig, isEventConsumerResult, isEventPublisherConfig, isQueueWithTtlBackoffInfrastructure };
2645
2579
  //# sourceMappingURL=index.d.cts.map