@amqp-contract/contract 0.1.4 → 0.2.1

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
@@ -3,198 +3,858 @@ import { StandardSchemaV1 } from "@standard-schema/spec";
3
3
  //#region src/types.d.ts
4
4
 
5
5
  /**
6
- * Any schema that conforms to Standard Schema v1
6
+ * Any schema that conforms to Standard Schema v1.
7
+ *
8
+ * This library supports any validation library that implements the Standard Schema v1 specification,
9
+ * including Zod, Valibot, and ArkType. This allows you to use your preferred validation library
10
+ * while maintaining type safety.
11
+ *
12
+ * @see https://github.com/standard-schema/standard-schema
7
13
  */
8
14
  type AnySchema = StandardSchemaV1;
9
15
  /**
10
- * Exchange types supported by AMQP
16
+ * Base definition of an AMQP exchange.
17
+ *
18
+ * An exchange receives messages from publishers and routes them to queues based on the exchange
19
+ * type and routing rules. This type contains properties common to all exchange types.
11
20
  */
12
- type ExchangeType = "direct" | "fanout" | "topic" | "headers";
13
- /**
14
- * Definition of an AMQP exchange
15
- */
16
- interface ExchangeDefinition {
21
+ type BaseExchangeDefinition = {
22
+ /**
23
+ * The name of the exchange. Must be unique within the RabbitMQ virtual host.
24
+ */
17
25
  name: string;
18
- type: ExchangeType;
26
+ /**
27
+ * If true, the exchange survives broker restarts. Durable exchanges are persisted to disk.
28
+ * @default false
29
+ */
19
30
  durable?: boolean;
31
+ /**
32
+ * If true, the exchange is deleted when all queues have finished using it.
33
+ * @default false
34
+ */
20
35
  autoDelete?: boolean;
36
+ /**
37
+ * If true, the exchange cannot be directly published to by clients.
38
+ * It can only receive messages from other exchanges via exchange-to-exchange bindings.
39
+ * @default false
40
+ */
21
41
  internal?: boolean;
42
+ /**
43
+ * Additional AMQP arguments for advanced configuration.
44
+ * Common arguments include alternate-exchange for handling unroutable messages.
45
+ */
22
46
  arguments?: Record<string, unknown>;
23
- }
24
- /**
25
- * Definition of an AMQP queue
26
- */
27
- interface QueueDefinition {
47
+ };
48
+ /**
49
+ * A fanout exchange definition.
50
+ *
51
+ * Fanout exchanges broadcast all messages to all bound queues, ignoring routing keys.
52
+ * This is the simplest exchange type for pub/sub messaging patterns.
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const logsExchange: FanoutExchangeDefinition = defineExchange('logs', 'fanout', {
57
+ * durable: true
58
+ * });
59
+ * ```
60
+ */
61
+ type FanoutExchangeDefinition = BaseExchangeDefinition & {
62
+ type: "fanout";
63
+ };
64
+ /**
65
+ * A direct exchange definition.
66
+ *
67
+ * Direct exchanges route messages to queues based on exact routing key matches.
68
+ * This is ideal for point-to-point messaging where each message should go to specific queues.
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const tasksExchange: DirectExchangeDefinition = defineExchange('tasks', 'direct', {
73
+ * durable: true
74
+ * });
75
+ * ```
76
+ */
77
+ type DirectExchangeDefinition = BaseExchangeDefinition & {
78
+ type: "direct";
79
+ };
80
+ /**
81
+ * A topic exchange definition.
82
+ *
83
+ * Topic exchanges route messages to queues based on routing key patterns with wildcards:
84
+ * - `*` (star) matches exactly one word
85
+ * - `#` (hash) matches zero or more words
86
+ *
87
+ * Words are separated by dots (e.g., `order.created.high-value`).
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * const ordersExchange: TopicExchangeDefinition = defineExchange('orders', 'topic', {
92
+ * durable: true
93
+ * });
94
+ * // Can be bound with patterns like 'order.*' or 'order.#'
95
+ * ```
96
+ */
97
+ type TopicExchangeDefinition = BaseExchangeDefinition & {
98
+ type: "topic";
99
+ };
100
+ /**
101
+ * Union type of all exchange definitions.
102
+ *
103
+ * Represents any type of AMQP exchange: fanout, direct, or topic.
104
+ */
105
+ type ExchangeDefinition = FanoutExchangeDefinition | DirectExchangeDefinition | TopicExchangeDefinition;
106
+ /**
107
+ * Definition of an AMQP queue.
108
+ *
109
+ * A queue stores messages until they are consumed by workers. Queues are bound to exchanges
110
+ * to receive messages based on routing rules.
111
+ */
112
+ type QueueDefinition = {
113
+ /**
114
+ * The name of the queue. Must be unique within the RabbitMQ virtual host.
115
+ */
28
116
  name: string;
117
+ /**
118
+ * If true, the queue survives broker restarts. Durable queues are persisted to disk.
119
+ * @default false
120
+ */
29
121
  durable?: boolean;
122
+ /**
123
+ * If true, the queue can only be used by the declaring connection and is deleted when
124
+ * that connection closes. Exclusive queues are private to the connection.
125
+ * @default false
126
+ */
30
127
  exclusive?: boolean;
128
+ /**
129
+ * If true, the queue is deleted when the last consumer unsubscribes.
130
+ * @default false
131
+ */
31
132
  autoDelete?: boolean;
133
+ /**
134
+ * Additional AMQP arguments for advanced configuration.
135
+ *
136
+ * Common arguments include:
137
+ * - `x-message-ttl`: Message time-to-live in milliseconds
138
+ * - `x-expires`: Queue expiration time in milliseconds
139
+ * - `x-max-length`: Maximum number of messages in the queue
140
+ * - `x-max-length-bytes`: Maximum size of the queue in bytes
141
+ * - `x-dead-letter-exchange`: Exchange for dead-lettered messages
142
+ * - `x-dead-letter-routing-key`: Routing key for dead-lettered messages
143
+ * - `x-max-priority`: Maximum priority level for priority queues
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * {
148
+ * 'x-message-ttl': 86400000, // 24 hours
149
+ * 'x-dead-letter-exchange': 'dlx',
150
+ * 'x-max-priority': 10
151
+ * }
152
+ * ```
153
+ */
32
154
  arguments?: Record<string, unknown>;
33
- }
34
- /**
35
- * Binding between queue and exchange
36
- */
37
- interface QueueBindingDefinition {
155
+ };
156
+ /**
157
+ * Definition of a message with typed payload and optional headers.
158
+ *
159
+ * @template TPayload - The Standard Schema v1 compatible schema for the message payload
160
+ * @template THeaders - The Standard Schema v1 compatible schema for the message headers (optional)
161
+ */
162
+ type MessageDefinition<TPayload extends AnySchema = AnySchema, THeaders extends StandardSchemaV1<Record<string, unknown>> | undefined = undefined> = {
163
+ /**
164
+ * The payload schema for validating message content.
165
+ * Must be a Standard Schema v1 compatible schema (Zod, Valibot, ArkType, etc.).
166
+ */
167
+ payload: TPayload;
168
+ /**
169
+ * Optional headers schema for validating message metadata.
170
+ * Must be a Standard Schema v1 compatible schema.
171
+ */
172
+ headers?: THeaders;
173
+ /**
174
+ * Brief description of the message for documentation purposes.
175
+ * Used in AsyncAPI specification generation.
176
+ */
177
+ summary?: string;
178
+ /**
179
+ * Detailed description of the message for documentation purposes.
180
+ * Used in AsyncAPI specification generation.
181
+ */
182
+ description?: string;
183
+ };
184
+ /**
185
+ * Binding between a queue and an exchange.
186
+ *
187
+ * Defines how messages from an exchange should be routed to a queue.
188
+ * For direct and topic exchanges, a routing key is required.
189
+ * For fanout exchanges, no routing key is needed as all messages are broadcast.
190
+ */
191
+ type QueueBindingDefinition = {
192
+ /** Discriminator indicating this is a queue-to-exchange binding */
38
193
  type: "queue";
39
- queue: string;
40
- exchange: string;
41
- routingKey?: string;
194
+ /** The queue that will receive messages */
195
+ queue: QueueDefinition;
196
+ /**
197
+ * Additional AMQP arguments for the binding.
198
+ * Can be used for advanced routing scenarios with the headers exchange type.
199
+ */
42
200
  arguments?: Record<string, unknown>;
43
- }
44
- /**
45
- * Binding between exchange and exchange
46
- */
47
- interface ExchangeBindingDefinition {
201
+ } & ({
202
+ /** Direct or topic exchange requiring a routing key */
203
+ exchange: DirectExchangeDefinition | TopicExchangeDefinition;
204
+ /**
205
+ * The routing key pattern for message routing.
206
+ * For direct exchanges: Must match exactly.
207
+ * For topic exchanges: Can use wildcards (* for one word, # for zero or more words).
208
+ */
209
+ routingKey: string;
210
+ } | {
211
+ /** Fanout exchange (no routing key needed) */
212
+ exchange: FanoutExchangeDefinition;
213
+ /** Fanout exchanges don't use routing keys */
214
+ routingKey?: never;
215
+ });
216
+ /**
217
+ * Binding between two exchanges (exchange-to-exchange routing).
218
+ *
219
+ * Defines how messages should be forwarded from a source exchange to a destination exchange.
220
+ * This allows for more complex routing topologies.
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * // Forward high-priority orders to a special processing exchange
225
+ * const binding: ExchangeBindingDefinition = {
226
+ * type: 'exchange',
227
+ * source: ordersExchange,
228
+ * destination: highPriorityExchange,
229
+ * routingKey: 'order.high-priority.*'
230
+ * };
231
+ * ```
232
+ */
233
+ type ExchangeBindingDefinition = {
234
+ /** Discriminator indicating this is an exchange-to-exchange binding */
48
235
  type: "exchange";
49
- source: string;
50
- destination: string;
51
- routingKey?: string;
236
+ /** The destination exchange that will receive forwarded messages */
237
+ destination: ExchangeDefinition;
238
+ /**
239
+ * Additional AMQP arguments for the binding.
240
+ */
52
241
  arguments?: Record<string, unknown>;
53
- }
54
- /**
55
- * Binding definition - can be either queue-to-exchange or exchange-to-exchange
242
+ } & ({
243
+ /** Direct or topic source exchange requiring a routing key */
244
+ source: DirectExchangeDefinition | TopicExchangeDefinition;
245
+ /**
246
+ * The routing key pattern for message routing.
247
+ * Messages matching this pattern will be forwarded to the destination exchange.
248
+ */
249
+ routingKey: string;
250
+ } | {
251
+ /** Fanout source exchange (no routing key needed) */
252
+ source: FanoutExchangeDefinition;
253
+ /** Fanout exchanges don't use routing keys */
254
+ routingKey?: never;
255
+ });
256
+ /**
257
+ * Union type of all binding definitions.
258
+ *
259
+ * A binding can be either:
260
+ * - Queue-to-exchange binding: Routes messages from an exchange to a queue
261
+ * - Exchange-to-exchange binding: Forwards messages from one exchange to another
56
262
  */
57
263
  type BindingDefinition = QueueBindingDefinition | ExchangeBindingDefinition;
58
264
  /**
59
- * Definition of a message publisher
60
- */
61
- interface PublisherDefinition<TMessageSchema extends AnySchema = AnySchema> {
62
- exchange: string;
63
- routingKey?: string;
64
- message: TMessageSchema;
65
- }
66
- /**
67
- * Definition of a message consumer
68
- */
69
- interface ConsumerDefinition<TMessageSchema extends AnySchema = AnySchema, THandlerResultSchema extends AnySchema = AnySchema> {
70
- queue: string;
71
- message: TMessageSchema;
72
- handlerResult?: THandlerResultSchema;
73
- prefetch?: number;
74
- noAck?: boolean;
75
- }
76
- /**
77
- * Contract definition containing all AMQP resources
78
- */
79
- interface ContractDefinition<TExchanges extends Record<string, ExchangeDefinition> = Record<string, ExchangeDefinition>, TQueues extends Record<string, QueueDefinition> = Record<string, QueueDefinition>, TBindings extends Record<string, BindingDefinition> = Record<string, BindingDefinition>, TPublishers extends Record<string, PublisherDefinition> = Record<string, PublisherDefinition>, TConsumers extends Record<string, ConsumerDefinition> = Record<string, ConsumerDefinition>> {
80
- exchanges?: TExchanges;
81
- queues?: TQueues;
82
- bindings?: TBindings;
83
- publishers?: TPublishers;
84
- consumers?: TConsumers;
85
- }
86
- /**
87
- * Infer the TypeScript type from a schema
88
- */
89
- type InferSchemaInput<TSchema extends AnySchema> = TSchema extends StandardSchemaV1<infer TInput> ? TInput : never;
90
- /**
91
- * Infer the output type from a schema
92
- */
93
- type InferSchemaOutput<TSchema extends AnySchema> = TSchema extends StandardSchemaV1<unknown, infer TOutput> ? TOutput : never;
94
- /**
95
- * Infer publisher message input type
96
- */
97
- type PublisherInferInput<TPublisher extends PublisherDefinition> = InferSchemaInput<TPublisher["message"]>;
98
- /**
99
- * Infer consumer message input type
100
- */
101
- type ConsumerInferInput<TConsumer extends ConsumerDefinition> = InferSchemaInput<TConsumer["message"]>;
102
- /**
103
- * Infer consumer handler result type
104
- */
105
- type ConsumerInferHandlerResult<TConsumer extends ConsumerDefinition> = TConsumer["handlerResult"] extends AnySchema ? InferSchemaOutput<TConsumer["handlerResult"]> : void;
106
- /**
107
- * Consumer handler function type
108
- * Handlers return Promise for async handling
109
- * where HandlerResult is inferred from the consumer's handlerResult schema (defaults to void)
110
- */
111
- type ConsumerHandler<TConsumer extends ConsumerDefinition> = (message: ConsumerInferInput<TConsumer>) => Promise<ConsumerInferHandlerResult<TConsumer>>;
112
- /**
113
- * Infer all publishers from contract
114
- */
115
- type InferPublishers<TContract extends ContractDefinition> = NonNullable<TContract["publishers"]>;
116
- /**
117
- * Infer all consumers from contract
118
- */
119
- type InferConsumers<TContract extends ContractDefinition> = NonNullable<TContract["consumers"]>;
120
- /**
121
- * Infer publisher names from contract
122
- */
123
- type InferPublisherNames<TContract extends ContractDefinition> = keyof InferPublishers<TContract>;
124
- /**
125
- * Infer consumer names from contract
126
- */
127
- type InferConsumerNames<TContract extends ContractDefinition> = keyof InferConsumers<TContract>;
128
- /**
129
- * Get specific publisher definition from contract
130
- */
131
- type InferPublisher<TContract extends ContractDefinition, TName extends InferPublisherNames<TContract>> = InferPublishers<TContract>[TName];
132
- /**
133
- * Get specific consumer definition from contract
134
- */
135
- type InferConsumer<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = InferConsumers<TContract>[TName];
136
- /**
137
- * Client perspective types - for publishing messages
138
- */
139
- type ClientInferPublisherInput<TContract extends ContractDefinition, TName extends InferPublisherNames<TContract>> = PublisherInferInput<InferPublisher<TContract, TName>>;
140
- /**
141
- * Worker perspective types - for consuming messages
142
- */
143
- type WorkerInferConsumerInput<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = ConsumerInferInput<InferConsumer<TContract, TName>>;
144
- /**
145
- * Worker perspective - consumer handler result type
146
- */
147
- type WorkerInferConsumerHandlerResult<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = ConsumerInferHandlerResult<InferConsumer<TContract, TName>>;
148
- /**
149
- * Worker perspective - consumer handler type
150
- */
151
- type WorkerInferConsumerHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = ConsumerHandler<InferConsumer<TContract, TName>>;
152
- /**
153
- * Map of all consumer handlers for a contract
154
- */
155
- type WorkerInferConsumerHandlers<TContract extends ContractDefinition> = { [K in InferConsumerNames<TContract>]: WorkerInferConsumerHandler<TContract, K> };
265
+ * Definition of a message publisher.
266
+ *
267
+ * A publisher sends messages to an exchange with automatic schema validation.
268
+ * The message payload is validated against the schema before being sent to RabbitMQ.
269
+ *
270
+ * @template TMessage - The message definition with payload schema
271
+ *
272
+ * @example
273
+ * ```typescript
274
+ * const publisher: PublisherDefinition = {
275
+ * exchange: ordersExchange,
276
+ * message: orderMessage,
277
+ * routingKey: 'order.created'
278
+ * };
279
+ * ```
280
+ */
281
+ type PublisherDefinition<TMessage extends MessageDefinition = MessageDefinition> = {
282
+ /** The message definition including the payload schema */
283
+ message: TMessage;
284
+ } & ({
285
+ /** Direct or topic exchange requiring a routing key */
286
+ exchange: DirectExchangeDefinition | TopicExchangeDefinition;
287
+ /**
288
+ * The routing key for message routing.
289
+ * Determines which queues will receive the published message.
290
+ */
291
+ routingKey: string;
292
+ } | {
293
+ /** Fanout exchange (no routing key needed) */
294
+ exchange: FanoutExchangeDefinition;
295
+ /** Fanout exchanges don't use routing keys - all bound queues receive the message */
296
+ routingKey?: never;
297
+ });
298
+ /**
299
+ * Definition of a message consumer.
300
+ *
301
+ * A consumer receives and processes messages from a queue with automatic schema validation.
302
+ * The message payload is validated against the schema before being passed to your handler.
303
+ *
304
+ * @template TMessage - The message definition with payload schema
305
+ *
306
+ * @example
307
+ * ```typescript
308
+ * const consumer: ConsumerDefinition = {
309
+ * queue: orderProcessingQueue,
310
+ * message: orderMessage
311
+ * };
312
+ * ```
313
+ */
314
+ type ConsumerDefinition<TMessage extends MessageDefinition = MessageDefinition> = {
315
+ /** The queue to consume messages from */
316
+ queue: QueueDefinition;
317
+ /** The message definition including the payload schema */
318
+ message: TMessage;
319
+ };
320
+ /**
321
+ * Complete AMQP contract definition.
322
+ *
323
+ * A contract brings together all AMQP resources into a single, type-safe definition.
324
+ * It defines the complete messaging topology including exchanges, queues, bindings,
325
+ * publishers, and consumers.
326
+ *
327
+ * The contract is used by:
328
+ * - Clients (TypedAmqpClient) for type-safe message publishing
329
+ * - Workers (TypedAmqpWorker) for type-safe message consumption
330
+ * - AsyncAPI generator for documentation
331
+ *
332
+ * @example
333
+ * ```typescript
334
+ * const contract: ContractDefinition = {
335
+ * exchanges: {
336
+ * orders: ordersExchange,
337
+ * },
338
+ * queues: {
339
+ * orderProcessing: orderProcessingQueue,
340
+ * },
341
+ * bindings: {
342
+ * orderBinding: orderQueueBinding,
343
+ * },
344
+ * publishers: {
345
+ * orderCreated: orderCreatedPublisher,
346
+ * },
347
+ * consumers: {
348
+ * processOrder: processOrderConsumer,
349
+ * },
350
+ * };
351
+ * ```
352
+ */
353
+ type ContractDefinition = {
354
+ /**
355
+ * Named exchange definitions.
356
+ * Each key becomes available as a named resource in the contract.
357
+ */
358
+ exchanges?: Record<string, ExchangeDefinition>;
359
+ /**
360
+ * Named queue definitions.
361
+ * Each key becomes available as a named resource in the contract.
362
+ */
363
+ queues?: Record<string, QueueDefinition>;
364
+ /**
365
+ * Named binding definitions.
366
+ * Bindings can be queue-to-exchange or exchange-to-exchange.
367
+ */
368
+ bindings?: Record<string, BindingDefinition>;
369
+ /**
370
+ * Named publisher definitions.
371
+ * Each key becomes a method on the TypedAmqpClient for publishing messages.
372
+ * The method will be fully typed based on the message schema.
373
+ */
374
+ publishers?: Record<string, PublisherDefinition>;
375
+ /**
376
+ * Named consumer definitions.
377
+ * Each key requires a corresponding handler in the TypedAmqpWorker.
378
+ * The handler will be fully typed based on the message schema.
379
+ */
380
+ consumers?: Record<string, ConsumerDefinition>;
381
+ };
382
+ /**
383
+ * Extract publisher names from a contract.
384
+ *
385
+ * This utility type extracts the keys of all publishers defined in a contract.
386
+ * It's used internally for type inference in the TypedAmqpClient.
387
+ *
388
+ * @template TContract - The contract definition
389
+ * @returns Union of publisher names, or never if no publishers defined
390
+ *
391
+ * @example
392
+ * ```typescript
393
+ * type PublisherNames = InferPublisherNames<typeof myContract>;
394
+ * // Result: 'orderCreated' | 'orderUpdated' | 'orderCancelled'
395
+ * ```
396
+ */
397
+ type InferPublisherNames<TContract extends ContractDefinition> = TContract["publishers"] extends Record<string, unknown> ? keyof TContract["publishers"] : never;
398
+ /**
399
+ * Extract consumer names from a contract.
400
+ *
401
+ * This utility type extracts the keys of all consumers defined in a contract.
402
+ * It's used internally for type inference in the TypedAmqpWorker.
403
+ *
404
+ * @template TContract - The contract definition
405
+ * @returns Union of consumer names, or never if no consumers defined
406
+ *
407
+ * @example
408
+ * ```typescript
409
+ * type ConsumerNames = InferConsumerNames<typeof myContract>;
410
+ * // Result: 'processOrder' | 'sendNotification' | 'updateInventory'
411
+ * ```
412
+ */
413
+ type InferConsumerNames<TContract extends ContractDefinition> = TContract["consumers"] extends Record<string, unknown> ? keyof TContract["consumers"] : never;
156
414
  //#endregion
157
415
  //#region src/builder.d.ts
158
416
  /**
159
- * Message schema with metadata
160
- */
161
- interface MessageSchema<TSchema extends AnySchema = AnySchema> extends AnySchema {
162
- readonly name: string;
163
- readonly schema: TSchema;
164
- readonly "~standard": TSchema["~standard"];
165
- }
166
- /**
167
- * Define a message schema with metadata
168
- */
169
- declare function defineMessage<TSchema extends AnySchema>(name: string, schema: TSchema): MessageSchema<TSchema>;
170
- /**
171
- * Define an AMQP exchange
172
- */
173
- declare function defineExchange(name: string, type: ExchangeType, options?: Omit<ExchangeDefinition, "name" | "type">): ExchangeDefinition;
174
- /**
175
- * Define an AMQP queue
417
+ * Define a fanout exchange.
418
+ *
419
+ * A fanout exchange routes messages to all bound queues without considering routing keys.
420
+ * This exchange type is ideal for broadcasting messages to multiple consumers.
421
+ *
422
+ * @param name - The name of the exchange
423
+ * @param type - Must be "fanout"
424
+ * @param options - Optional exchange configuration
425
+ * @param options.durable - If true, the exchange survives broker restarts (default: false)
426
+ * @param options.autoDelete - If true, the exchange is deleted when no queues are bound (default: false)
427
+ * @param options.internal - If true, the exchange cannot be directly published to (default: false)
428
+ * @param options.arguments - Additional AMQP arguments for the exchange
429
+ * @returns A fanout exchange definition
430
+ *
431
+ * @example
432
+ * ```typescript
433
+ * const logsExchange = defineExchange('logs', 'fanout', {
434
+ * durable: true
435
+ * });
436
+ * ```
437
+ */
438
+ declare function defineExchange(name: string, type: "fanout", options?: Omit<BaseExchangeDefinition, "name" | "type">): FanoutExchangeDefinition;
439
+ /**
440
+ * Define a direct exchange.
441
+ *
442
+ * A direct exchange routes messages to queues based on exact routing key matches.
443
+ * This exchange type is ideal for point-to-point messaging.
444
+ *
445
+ * @param name - The name of the exchange
446
+ * @param type - Must be "direct"
447
+ * @param options - Optional exchange configuration
448
+ * @param options.durable - If true, the exchange survives broker restarts (default: false)
449
+ * @param options.autoDelete - If true, the exchange is deleted when no queues are bound (default: false)
450
+ * @param options.internal - If true, the exchange cannot be directly published to (default: false)
451
+ * @param options.arguments - Additional AMQP arguments for the exchange
452
+ * @returns A direct exchange definition
453
+ *
454
+ * @example
455
+ * ```typescript
456
+ * const tasksExchange = defineExchange('tasks', 'direct', {
457
+ * durable: true
458
+ * });
459
+ * ```
460
+ */
461
+ declare function defineExchange(name: string, type: "direct", options?: Omit<BaseExchangeDefinition, "name" | "type">): DirectExchangeDefinition;
462
+ /**
463
+ * Define a topic exchange.
464
+ *
465
+ * A topic exchange routes messages to queues based on routing key patterns.
466
+ * Routing keys can use wildcards: `*` matches one word, `#` matches zero or more words.
467
+ * This exchange type is ideal for flexible message routing based on hierarchical topics.
468
+ *
469
+ * @param name - The name of the exchange
470
+ * @param type - Must be "topic"
471
+ * @param options - Optional exchange configuration
472
+ * @param options.durable - If true, the exchange survives broker restarts (default: false)
473
+ * @param options.autoDelete - If true, the exchange is deleted when no queues are bound (default: false)
474
+ * @param options.internal - If true, the exchange cannot be directly published to (default: false)
475
+ * @param options.arguments - Additional AMQP arguments for the exchange
476
+ * @returns A topic exchange definition
477
+ *
478
+ * @example
479
+ * ```typescript
480
+ * const ordersExchange = defineExchange('orders', 'topic', {
481
+ * durable: true
482
+ * });
483
+ * ```
484
+ */
485
+ declare function defineExchange(name: string, type: "topic", options?: Omit<BaseExchangeDefinition, "name" | "type">): TopicExchangeDefinition;
486
+ /**
487
+ * Define an AMQP queue.
488
+ *
489
+ * A queue stores messages until they are consumed by workers. Queues can be bound to exchanges
490
+ * to receive messages based on routing rules.
491
+ *
492
+ * @param name - The name of the queue
493
+ * @param options - Optional queue configuration
494
+ * @param options.durable - If true, the queue survives broker restarts (default: false)
495
+ * @param options.exclusive - If true, the queue can only be used by the declaring connection (default: false)
496
+ * @param options.autoDelete - If true, the queue is deleted when the last consumer unsubscribes (default: false)
497
+ * @param options.arguments - Additional AMQP arguments (e.g., x-message-ttl, x-dead-letter-exchange)
498
+ * @returns A queue definition
499
+ *
500
+ * @example
501
+ * ```typescript
502
+ * const orderProcessingQueue = defineQueue('order-processing', {
503
+ * durable: true,
504
+ * arguments: {
505
+ * 'x-message-ttl': 86400000, // 24 hours
506
+ * 'x-dead-letter-exchange': 'orders-dlx'
507
+ * }
508
+ * });
509
+ * ```
176
510
  */
177
511
  declare function defineQueue(name: string, options?: Omit<QueueDefinition, "name">): QueueDefinition;
178
512
  /**
179
- * Define a binding between queue and exchange
180
- */
181
- declare function defineBinding(queue: string, exchange: string, options?: Omit<QueueBindingDefinition, "type" | "queue" | "exchange">): QueueBindingDefinition;
182
- /**
183
- * Define a binding between exchange and exchange (source -> destination)
184
- */
185
- declare function defineExchangeBinding(destination: string, source: string, options?: Omit<ExchangeBindingDefinition, "type" | "source" | "destination">): ExchangeBindingDefinition;
186
- /**
187
- * Define a message publisher
188
- */
189
- declare function definePublisher<TMessageSchema extends AnySchema>(exchange: string, message: TMessageSchema, options?: Omit<PublisherDefinition<TMessageSchema>, "exchange" | "message">): PublisherDefinition<TMessageSchema>;
190
- /**
191
- * Define a message consumer
192
- */
193
- declare function defineConsumer<TMessageSchema extends AnySchema, THandlerResultSchema extends AnySchema = AnySchema>(queue: string, message: TMessageSchema, options?: Omit<ConsumerDefinition<TMessageSchema, THandlerResultSchema>, "queue" | "message">): ConsumerDefinition<TMessageSchema, THandlerResultSchema>;
194
- /**
195
- * Define an AMQP contract
196
- */
197
- declare function defineContract<TContract extends ContractDefinition<TExchanges, TQueues, TBindings, TPublishers, TConsumers>, TExchanges extends Record<string, ExchangeDefinition> = Record<string, ExchangeDefinition>, TQueues extends Record<string, QueueDefinition> = Record<string, QueueDefinition>, TBindings extends Record<string, BindingDefinition> = Record<string, BindingDefinition>, TPublishers extends Record<string, PublisherDefinition> = Record<string, PublisherDefinition>, TConsumers extends Record<string, ConsumerDefinition> = Record<string, ConsumerDefinition>>(definition: TContract): TContract;
513
+ * Define a message definition with payload and optional headers/metadata.
514
+ *
515
+ * A message definition specifies the schema for message payloads and headers using
516
+ * Standard Schema v1 compatible libraries (Zod, Valibot, ArkType, etc.).
517
+ * The schemas are used for automatic validation when publishing or consuming messages.
518
+ *
519
+ * @param payload - The payload schema (must be Standard Schema v1 compatible)
520
+ * @param options - Optional message metadata
521
+ * @param options.headers - Optional header schema for message headers
522
+ * @param options.summary - Brief description for documentation (used in AsyncAPI generation)
523
+ * @param options.description - Detailed description for documentation (used in AsyncAPI generation)
524
+ * @returns A message definition with inferred types
525
+ *
526
+ * @example
527
+ * ```typescript
528
+ * import { z } from 'zod';
529
+ *
530
+ * const orderMessage = defineMessage(
531
+ * z.object({
532
+ * orderId: z.string().uuid(),
533
+ * customerId: z.string().uuid(),
534
+ * amount: z.number().positive(),
535
+ * items: z.array(z.object({
536
+ * productId: z.string(),
537
+ * quantity: z.number().int().positive(),
538
+ * })),
539
+ * }),
540
+ * {
541
+ * summary: 'Order created event',
542
+ * description: 'Emitted when a new order is created in the system'
543
+ * }
544
+ * );
545
+ * ```
546
+ */
547
+ declare function defineMessage<TPayload extends MessageDefinition["payload"], THeaders extends StandardSchemaV1<Record<string, unknown>> | undefined = undefined>(payload: TPayload, options?: {
548
+ headers?: THeaders;
549
+ summary?: string;
550
+ description?: string;
551
+ }): MessageDefinition<TPayload, THeaders>;
552
+ /**
553
+ * Define a binding between a queue and a fanout exchange.
554
+ *
555
+ * Binds a queue to a fanout exchange to receive all messages published to the exchange.
556
+ * Fanout exchanges ignore routing keys, so this overload doesn't require one.
557
+ *
558
+ * @param queue - The queue definition to bind
559
+ * @param exchange - The fanout exchange definition
560
+ * @param options - Optional binding configuration
561
+ * @param options.arguments - Additional AMQP arguments for the binding
562
+ * @returns A queue binding definition
563
+ *
564
+ * @example
565
+ * ```typescript
566
+ * const logsQueue = defineQueue('logs-queue', { durable: true });
567
+ * const logsExchange = defineExchange('logs', 'fanout', { durable: true });
568
+ *
569
+ * const binding = defineQueueBinding(logsQueue, logsExchange);
570
+ * ```
571
+ */
572
+ declare function defineQueueBinding(queue: QueueDefinition, exchange: FanoutExchangeDefinition, options?: Omit<Extract<QueueBindingDefinition, {
573
+ exchange: FanoutExchangeDefinition;
574
+ }>, "type" | "queue" | "exchange" | "routingKey">): Extract<QueueBindingDefinition, {
575
+ exchange: FanoutExchangeDefinition;
576
+ }>;
577
+ /**
578
+ * Define a binding between a queue and a direct or topic exchange.
579
+ *
580
+ * Binds a queue to an exchange with a specific routing key pattern.
581
+ * Messages are only routed to the queue if the routing key matches the pattern.
582
+ *
583
+ * For direct exchanges: The routing key must match exactly.
584
+ * For topic exchanges: The routing key can include wildcards:
585
+ * - `*` matches exactly one word
586
+ * - `#` matches zero or more words
587
+ *
588
+ * @param queue - The queue definition to bind
589
+ * @param exchange - The direct or topic exchange definition
590
+ * @param options - Binding configuration (routingKey is required)
591
+ * @param options.routingKey - The routing key pattern for message routing
592
+ * @param options.arguments - Additional AMQP arguments for the binding
593
+ * @returns A queue binding definition
594
+ *
595
+ * @example
596
+ * ```typescript
597
+ * const orderQueue = defineQueue('order-processing', { durable: true });
598
+ * const ordersExchange = defineExchange('orders', 'topic', { durable: true });
599
+ *
600
+ * // Bind with exact routing key
601
+ * const binding = defineQueueBinding(orderQueue, ordersExchange, {
602
+ * routingKey: 'order.created'
603
+ * });
604
+ *
605
+ * // Bind with wildcard pattern
606
+ * const allOrdersBinding = defineQueueBinding(orderQueue, ordersExchange, {
607
+ * routingKey: 'order.*' // Matches order.created, order.updated, etc.
608
+ * });
609
+ * ```
610
+ */
611
+ declare function defineQueueBinding(queue: QueueDefinition, exchange: DirectExchangeDefinition | TopicExchangeDefinition, options: Omit<Extract<QueueBindingDefinition, {
612
+ exchange: DirectExchangeDefinition | TopicExchangeDefinition;
613
+ }>, "type" | "queue" | "exchange">): Extract<QueueBindingDefinition, {
614
+ exchange: DirectExchangeDefinition | TopicExchangeDefinition;
615
+ }>;
616
+ /**
617
+ * Define a binding between two exchanges (exchange-to-exchange routing).
618
+ *
619
+ * Binds a destination exchange to a fanout source exchange.
620
+ * Messages published to the source exchange will be forwarded to the destination exchange.
621
+ * Fanout exchanges ignore routing keys, so this overload doesn't require one.
622
+ *
623
+ * @param destination - The destination exchange definition
624
+ * @param source - The fanout source exchange definition
625
+ * @param options - Optional binding configuration
626
+ * @param options.arguments - Additional AMQP arguments for the binding
627
+ * @returns An exchange binding definition
628
+ *
629
+ * @example
630
+ * ```typescript
631
+ * const sourceExchange = defineExchange('logs', 'fanout', { durable: true });
632
+ * const destExchange = defineExchange('all-logs', 'fanout', { durable: true });
633
+ *
634
+ * const binding = defineExchangeBinding(destExchange, sourceExchange);
635
+ * ```
636
+ */
637
+ declare function defineExchangeBinding(destination: ExchangeDefinition, source: FanoutExchangeDefinition, options?: Omit<Extract<ExchangeBindingDefinition, {
638
+ source: FanoutExchangeDefinition;
639
+ }>, "type" | "source" | "destination" | "routingKey">): Extract<ExchangeBindingDefinition, {
640
+ source: FanoutExchangeDefinition;
641
+ }>;
642
+ /**
643
+ * Define a binding between two exchanges (exchange-to-exchange routing).
644
+ *
645
+ * Binds a destination exchange to a direct or topic source exchange with a routing key pattern.
646
+ * Messages are forwarded from source to destination only if the routing key matches the pattern.
647
+ *
648
+ * @param destination - The destination exchange definition
649
+ * @param source - The direct or topic source exchange definition
650
+ * @param options - Binding configuration (routingKey is required)
651
+ * @param options.routingKey - The routing key pattern for message routing
652
+ * @param options.arguments - Additional AMQP arguments for the binding
653
+ * @returns An exchange binding definition
654
+ *
655
+ * @example
656
+ * ```typescript
657
+ * const ordersExchange = defineExchange('orders', 'topic', { durable: true });
658
+ * const importantExchange = defineExchange('important-orders', 'topic', { durable: true });
659
+ *
660
+ * // Forward only high-value orders
661
+ * const binding = defineExchangeBinding(importantExchange, ordersExchange, {
662
+ * routingKey: 'order.high-value.*'
663
+ * });
664
+ * ```
665
+ */
666
+ declare function defineExchangeBinding(destination: ExchangeDefinition, source: DirectExchangeDefinition | TopicExchangeDefinition, options: Omit<Extract<ExchangeBindingDefinition, {
667
+ source: DirectExchangeDefinition | TopicExchangeDefinition;
668
+ }>, "type" | "source" | "destination">): Extract<ExchangeBindingDefinition, {
669
+ source: DirectExchangeDefinition | TopicExchangeDefinition;
670
+ }>;
671
+ /**
672
+ * Define a message publisher for a fanout exchange.
673
+ *
674
+ * A publisher sends messages to an exchange. For fanout exchanges, messages are broadcast
675
+ * to all bound queues regardless of routing key, so no routing key is required.
676
+ *
677
+ * The message schema is validated when publishing to ensure type safety.
678
+ *
679
+ * @param exchange - The fanout exchange definition to publish to
680
+ * @param message - The message definition with payload schema
681
+ * @param options - Optional publisher configuration
682
+ * @returns A publisher definition with inferred message types
683
+ *
684
+ * @example
685
+ * ```typescript
686
+ * import { z } from 'zod';
687
+ *
688
+ * const logsExchange = defineExchange('logs', 'fanout', { durable: true });
689
+ * const logMessage = defineMessage(
690
+ * z.object({
691
+ * level: z.enum(['info', 'warn', 'error']),
692
+ * message: z.string(),
693
+ * timestamp: z.string().datetime(),
694
+ * })
695
+ * );
696
+ *
697
+ * const logPublisher = definePublisher(logsExchange, logMessage);
698
+ * ```
699
+ */
700
+ declare function definePublisher<TMessage extends MessageDefinition>(exchange: FanoutExchangeDefinition, message: TMessage, options?: Omit<Extract<PublisherDefinition<TMessage>, {
701
+ exchange: FanoutExchangeDefinition;
702
+ }>, "exchange" | "message" | "routingKey">): Extract<PublisherDefinition<TMessage>, {
703
+ exchange: FanoutExchangeDefinition;
704
+ }>;
705
+ /**
706
+ * Define a message publisher for a direct or topic exchange.
707
+ *
708
+ * A publisher sends messages to an exchange with a specific routing key.
709
+ * The routing key determines which queues receive the message.
710
+ *
711
+ * The message schema is validated when publishing to ensure type safety.
712
+ *
713
+ * @param exchange - The direct or topic exchange definition to publish to
714
+ * @param message - The message definition with payload schema
715
+ * @param options - Publisher configuration (routingKey is required)
716
+ * @param options.routingKey - The routing key for message routing
717
+ * @returns A publisher definition with inferred message types
718
+ *
719
+ * @example
720
+ * ```typescript
721
+ * import { z } from 'zod';
722
+ *
723
+ * const ordersExchange = defineExchange('orders', 'topic', { durable: true });
724
+ * const orderMessage = defineMessage(
725
+ * z.object({
726
+ * orderId: z.string().uuid(),
727
+ * amount: z.number().positive(),
728
+ * }),
729
+ * {
730
+ * summary: 'Order created event',
731
+ * description: 'Emitted when a new order is created'
732
+ * }
733
+ * );
734
+ *
735
+ * const orderCreatedPublisher = definePublisher(ordersExchange, orderMessage, {
736
+ * routingKey: 'order.created'
737
+ * });
738
+ * ```
739
+ */
740
+ declare function definePublisher<TMessage extends MessageDefinition>(exchange: DirectExchangeDefinition | TopicExchangeDefinition, message: TMessage, options: Omit<Extract<PublisherDefinition<TMessage>, {
741
+ exchange: DirectExchangeDefinition | TopicExchangeDefinition;
742
+ }>, "exchange" | "message">): Extract<PublisherDefinition<TMessage>, {
743
+ exchange: DirectExchangeDefinition | TopicExchangeDefinition;
744
+ }>;
745
+ /**
746
+ * Define a message consumer.
747
+ *
748
+ * A consumer receives and processes messages from a queue. The message schema is validated
749
+ * automatically when messages are consumed, ensuring type safety for your handlers.
750
+ *
751
+ * Consumers are associated with a specific queue and message type. When you create a worker
752
+ * with this consumer, it will process messages from the queue according to the schema.
753
+ *
754
+ * @param queue - The queue definition to consume from
755
+ * @param message - The message definition with payload schema
756
+ * @param options - Optional consumer configuration
757
+ * @returns A consumer definition with inferred message types
758
+ *
759
+ * @example
760
+ * ```typescript
761
+ * import { z } from 'zod';
762
+ *
763
+ * const orderQueue = defineQueue('order-processing', { durable: true });
764
+ * const orderMessage = defineMessage(
765
+ * z.object({
766
+ * orderId: z.string().uuid(),
767
+ * customerId: z.string().uuid(),
768
+ * amount: z.number().positive(),
769
+ * })
770
+ * );
771
+ *
772
+ * const processOrderConsumer = defineConsumer(orderQueue, orderMessage);
773
+ *
774
+ * // Later, when creating a worker, you'll provide a handler for this consumer:
775
+ * // const worker = await TypedAmqpWorker.create({
776
+ * // contract,
777
+ * // handlers: {
778
+ * // processOrder: async (message) => {
779
+ * // // message is automatically typed based on the schema
780
+ * // console.log(message.orderId); // string
781
+ * // }
782
+ * // },
783
+ * // connection
784
+ * // });
785
+ * ```
786
+ */
787
+ declare function defineConsumer<TMessage extends MessageDefinition>(queue: QueueDefinition, message: TMessage, options?: Omit<ConsumerDefinition<TMessage>, "queue" | "message">): ConsumerDefinition<TMessage>;
788
+ /**
789
+ * Define an AMQP contract.
790
+ *
791
+ * A contract is the central definition of your AMQP messaging topology. It brings together
792
+ * all exchanges, queues, bindings, publishers, and consumers in a single, type-safe definition.
793
+ *
794
+ * The contract is used by both clients (for publishing) and workers (for consuming) to ensure
795
+ * type safety throughout your messaging infrastructure. TypeScript will infer all message types
796
+ * and publisher/consumer names from the contract.
797
+ *
798
+ * @param definition - The contract definition containing all AMQP resources
799
+ * @param definition.exchanges - Named exchange definitions
800
+ * @param definition.queues - Named queue definitions
801
+ * @param definition.bindings - Named binding definitions (queue-to-exchange or exchange-to-exchange)
802
+ * @param definition.publishers - Named publisher definitions for sending messages
803
+ * @param definition.consumers - Named consumer definitions for receiving messages
804
+ * @returns The same contract definition with full type inference
805
+ *
806
+ * @example
807
+ * ```typescript
808
+ * import {
809
+ * defineContract,
810
+ * defineExchange,
811
+ * defineQueue,
812
+ * defineQueueBinding,
813
+ * definePublisher,
814
+ * defineConsumer,
815
+ * defineMessage,
816
+ * } from '@amqp-contract/contract';
817
+ * import { z } from 'zod';
818
+ *
819
+ * // Define resources
820
+ * const ordersExchange = defineExchange('orders', 'topic', { durable: true });
821
+ * const orderQueue = defineQueue('order-processing', { durable: true });
822
+ * const orderMessage = defineMessage(
823
+ * z.object({
824
+ * orderId: z.string(),
825
+ * amount: z.number(),
826
+ * })
827
+ * );
828
+ *
829
+ * // Compose contract
830
+ * export const contract = defineContract({
831
+ * exchanges: {
832
+ * orders: ordersExchange,
833
+ * },
834
+ * queues: {
835
+ * orderProcessing: orderQueue,
836
+ * },
837
+ * bindings: {
838
+ * orderBinding: defineQueueBinding(orderQueue, ordersExchange, {
839
+ * routingKey: 'order.created',
840
+ * }),
841
+ * },
842
+ * publishers: {
843
+ * orderCreated: definePublisher(ordersExchange, orderMessage, {
844
+ * routingKey: 'order.created',
845
+ * }),
846
+ * },
847
+ * consumers: {
848
+ * processOrder: defineConsumer(orderQueue, orderMessage),
849
+ * },
850
+ * });
851
+ *
852
+ * // TypeScript now knows:
853
+ * // - client.publish('orderCreated', { orderId: string, amount: number })
854
+ * // - handler: async (message: { orderId: string, amount: number }) => void
855
+ * ```
856
+ */
857
+ declare function defineContract<TContract extends ContractDefinition>(definition: TContract): TContract;
198
858
  //#endregion
199
- export { type AnySchema, type BindingDefinition, type ClientInferPublisherInput, type ConsumerDefinition, type ConsumerHandler, type ConsumerInferHandlerResult, type ConsumerInferInput, type ContractDefinition, type ExchangeBindingDefinition, type ExchangeDefinition, type ExchangeType, type InferConsumer, type InferConsumerNames, type InferConsumers, type InferPublisher, type InferPublisherNames, type InferPublishers, type InferSchemaInput, type InferSchemaOutput, type MessageSchema, type PublisherDefinition, type PublisherInferInput, type QueueBindingDefinition, type QueueDefinition, type WorkerInferConsumerHandler, type WorkerInferConsumerHandlerResult, type WorkerInferConsumerHandlers, type WorkerInferConsumerInput, defineBinding, defineConsumer, defineContract, defineExchange, defineExchangeBinding, defineMessage, definePublisher, defineQueue };
859
+ export { type AnySchema, type BaseExchangeDefinition, type BindingDefinition, type ConsumerDefinition, type ContractDefinition, type DirectExchangeDefinition, type ExchangeBindingDefinition, type ExchangeDefinition, type FanoutExchangeDefinition, type InferConsumerNames, type InferPublisherNames, type MessageDefinition, type PublisherDefinition, type QueueBindingDefinition, type QueueDefinition, type TopicExchangeDefinition, defineConsumer, defineContract, defineExchange, defineExchangeBinding, defineMessage, definePublisher, defineQueue, defineQueueBinding };
200
860
  //# sourceMappingURL=index.d.cts.map