@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/README.md +90 -30
- package/dist/index.cjs +231 -21
- package/dist/index.d.cts +826 -166
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +826 -166
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +230 -20
- package/dist/index.mjs.map +1 -1
- package/docs/index.md +766 -0
- package/package.json +8 -3
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/builder.ts"],"sourcesContent":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/builder.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,67 +1,211 @@
|
|
|
1
1
|
//#region src/builder.ts
|
|
2
2
|
/**
|
|
3
|
-
* Define
|
|
3
|
+
* Define an AMQP exchange.
|
|
4
|
+
*
|
|
5
|
+
* An exchange receives messages from publishers and routes them to queues based on the exchange type
|
|
6
|
+
* and routing rules. This is the implementation function - use the type-specific overloads for better
|
|
7
|
+
* type safety.
|
|
8
|
+
*
|
|
9
|
+
* @param name - The name of the exchange
|
|
10
|
+
* @param type - The type of exchange: "fanout", "direct", or "topic"
|
|
11
|
+
* @param options - Optional exchange configuration
|
|
12
|
+
* @returns An exchange definition
|
|
13
|
+
* @internal
|
|
4
14
|
*/
|
|
5
|
-
function
|
|
15
|
+
function defineExchange(name, type, options) {
|
|
6
16
|
return {
|
|
7
17
|
name,
|
|
8
|
-
|
|
9
|
-
|
|
18
|
+
type,
|
|
19
|
+
...options
|
|
10
20
|
};
|
|
11
21
|
}
|
|
12
22
|
/**
|
|
13
|
-
* Define an AMQP
|
|
23
|
+
* Define an AMQP queue.
|
|
24
|
+
*
|
|
25
|
+
* A queue stores messages until they are consumed by workers. Queues can be bound to exchanges
|
|
26
|
+
* to receive messages based on routing rules.
|
|
27
|
+
*
|
|
28
|
+
* @param name - The name of the queue
|
|
29
|
+
* @param options - Optional queue configuration
|
|
30
|
+
* @param options.durable - If true, the queue survives broker restarts (default: false)
|
|
31
|
+
* @param options.exclusive - If true, the queue can only be used by the declaring connection (default: false)
|
|
32
|
+
* @param options.autoDelete - If true, the queue is deleted when the last consumer unsubscribes (default: false)
|
|
33
|
+
* @param options.arguments - Additional AMQP arguments (e.g., x-message-ttl, x-dead-letter-exchange)
|
|
34
|
+
* @returns A queue definition
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const orderProcessingQueue = defineQueue('order-processing', {
|
|
39
|
+
* durable: true,
|
|
40
|
+
* arguments: {
|
|
41
|
+
* 'x-message-ttl': 86400000, // 24 hours
|
|
42
|
+
* 'x-dead-letter-exchange': 'orders-dlx'
|
|
43
|
+
* }
|
|
44
|
+
* });
|
|
45
|
+
* ```
|
|
14
46
|
*/
|
|
15
|
-
function
|
|
47
|
+
function defineQueue(name, options) {
|
|
16
48
|
return {
|
|
17
49
|
name,
|
|
18
|
-
type,
|
|
19
50
|
...options
|
|
20
51
|
};
|
|
21
52
|
}
|
|
22
53
|
/**
|
|
23
|
-
* Define
|
|
54
|
+
* Define a message definition with payload and optional headers/metadata.
|
|
55
|
+
*
|
|
56
|
+
* A message definition specifies the schema for message payloads and headers using
|
|
57
|
+
* Standard Schema v1 compatible libraries (Zod, Valibot, ArkType, etc.).
|
|
58
|
+
* The schemas are used for automatic validation when publishing or consuming messages.
|
|
59
|
+
*
|
|
60
|
+
* @param payload - The payload schema (must be Standard Schema v1 compatible)
|
|
61
|
+
* @param options - Optional message metadata
|
|
62
|
+
* @param options.headers - Optional header schema for message headers
|
|
63
|
+
* @param options.summary - Brief description for documentation (used in AsyncAPI generation)
|
|
64
|
+
* @param options.description - Detailed description for documentation (used in AsyncAPI generation)
|
|
65
|
+
* @returns A message definition with inferred types
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* import { z } from 'zod';
|
|
70
|
+
*
|
|
71
|
+
* const orderMessage = defineMessage(
|
|
72
|
+
* z.object({
|
|
73
|
+
* orderId: z.string().uuid(),
|
|
74
|
+
* customerId: z.string().uuid(),
|
|
75
|
+
* amount: z.number().positive(),
|
|
76
|
+
* items: z.array(z.object({
|
|
77
|
+
* productId: z.string(),
|
|
78
|
+
* quantity: z.number().int().positive(),
|
|
79
|
+
* })),
|
|
80
|
+
* }),
|
|
81
|
+
* {
|
|
82
|
+
* summary: 'Order created event',
|
|
83
|
+
* description: 'Emitted when a new order is created in the system'
|
|
84
|
+
* }
|
|
85
|
+
* );
|
|
86
|
+
* ```
|
|
24
87
|
*/
|
|
25
|
-
function
|
|
88
|
+
function defineMessage(payload, options) {
|
|
26
89
|
return {
|
|
27
|
-
|
|
90
|
+
payload,
|
|
28
91
|
...options
|
|
29
92
|
};
|
|
30
93
|
}
|
|
31
94
|
/**
|
|
32
|
-
* Define a binding between queue and exchange
|
|
95
|
+
* Define a binding between a queue and an exchange.
|
|
96
|
+
*
|
|
97
|
+
* This is the implementation function - use the type-specific overloads for better type safety.
|
|
98
|
+
*
|
|
99
|
+
* @param queue - The queue definition to bind
|
|
100
|
+
* @param exchange - The exchange definition
|
|
101
|
+
* @param options - Optional binding configuration
|
|
102
|
+
* @returns A queue binding definition
|
|
103
|
+
* @internal
|
|
33
104
|
*/
|
|
34
|
-
function
|
|
105
|
+
function defineQueueBinding(queue, exchange, options) {
|
|
106
|
+
if (exchange.type === "fanout") return {
|
|
107
|
+
type: "queue",
|
|
108
|
+
queue,
|
|
109
|
+
exchange,
|
|
110
|
+
...options?.arguments && { arguments: options.arguments }
|
|
111
|
+
};
|
|
35
112
|
return {
|
|
36
113
|
type: "queue",
|
|
37
114
|
queue,
|
|
38
115
|
exchange,
|
|
39
|
-
|
|
116
|
+
routingKey: options?.routingKey,
|
|
117
|
+
...options?.arguments && { arguments: options.arguments }
|
|
40
118
|
};
|
|
41
119
|
}
|
|
42
120
|
/**
|
|
43
|
-
* Define a binding between
|
|
121
|
+
* Define a binding between two exchanges (exchange-to-exchange routing).
|
|
122
|
+
*
|
|
123
|
+
* This is the implementation function - use the type-specific overloads for better type safety.
|
|
124
|
+
*
|
|
125
|
+
* @param destination - The destination exchange definition
|
|
126
|
+
* @param source - The source exchange definition
|
|
127
|
+
* @param options - Optional binding configuration
|
|
128
|
+
* @returns An exchange binding definition
|
|
129
|
+
* @internal
|
|
44
130
|
*/
|
|
45
131
|
function defineExchangeBinding(destination, source, options) {
|
|
132
|
+
if (source.type === "fanout") return {
|
|
133
|
+
type: "exchange",
|
|
134
|
+
source,
|
|
135
|
+
destination,
|
|
136
|
+
...options?.arguments && { arguments: options.arguments }
|
|
137
|
+
};
|
|
46
138
|
return {
|
|
47
139
|
type: "exchange",
|
|
48
140
|
source,
|
|
49
141
|
destination,
|
|
50
|
-
|
|
142
|
+
routingKey: options?.routingKey ?? "",
|
|
143
|
+
...options?.arguments && { arguments: options.arguments }
|
|
51
144
|
};
|
|
52
145
|
}
|
|
53
146
|
/**
|
|
54
|
-
* Define a message publisher
|
|
147
|
+
* Define a message publisher.
|
|
148
|
+
*
|
|
149
|
+
* This is the implementation function - use the type-specific overloads for better type safety.
|
|
150
|
+
*
|
|
151
|
+
* @param exchange - The exchange definition
|
|
152
|
+
* @param message - The message definition
|
|
153
|
+
* @param options - Optional publisher configuration
|
|
154
|
+
* @returns A publisher definition
|
|
155
|
+
* @internal
|
|
55
156
|
*/
|
|
56
157
|
function definePublisher(exchange, message, options) {
|
|
158
|
+
if (exchange.type === "fanout") return {
|
|
159
|
+
exchange,
|
|
160
|
+
message
|
|
161
|
+
};
|
|
57
162
|
return {
|
|
58
163
|
exchange,
|
|
59
164
|
message,
|
|
60
|
-
|
|
165
|
+
routingKey: options?.routingKey ?? ""
|
|
61
166
|
};
|
|
62
167
|
}
|
|
63
168
|
/**
|
|
64
|
-
* Define a message consumer
|
|
169
|
+
* Define a message consumer.
|
|
170
|
+
*
|
|
171
|
+
* A consumer receives and processes messages from a queue. The message schema is validated
|
|
172
|
+
* automatically when messages are consumed, ensuring type safety for your handlers.
|
|
173
|
+
*
|
|
174
|
+
* Consumers are associated with a specific queue and message type. When you create a worker
|
|
175
|
+
* with this consumer, it will process messages from the queue according to the schema.
|
|
176
|
+
*
|
|
177
|
+
* @param queue - The queue definition to consume from
|
|
178
|
+
* @param message - The message definition with payload schema
|
|
179
|
+
* @param options - Optional consumer configuration
|
|
180
|
+
* @returns A consumer definition with inferred message types
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* import { z } from 'zod';
|
|
185
|
+
*
|
|
186
|
+
* const orderQueue = defineQueue('order-processing', { durable: true });
|
|
187
|
+
* const orderMessage = defineMessage(
|
|
188
|
+
* z.object({
|
|
189
|
+
* orderId: z.string().uuid(),
|
|
190
|
+
* customerId: z.string().uuid(),
|
|
191
|
+
* amount: z.number().positive(),
|
|
192
|
+
* })
|
|
193
|
+
* );
|
|
194
|
+
*
|
|
195
|
+
* const processOrderConsumer = defineConsumer(orderQueue, orderMessage);
|
|
196
|
+
*
|
|
197
|
+
* // Later, when creating a worker, you'll provide a handler for this consumer:
|
|
198
|
+
* // const worker = await TypedAmqpWorker.create({
|
|
199
|
+
* // contract,
|
|
200
|
+
* // handlers: {
|
|
201
|
+
* // processOrder: async (message) => {
|
|
202
|
+
* // // message is automatically typed based on the schema
|
|
203
|
+
* // console.log(message.orderId); // string
|
|
204
|
+
* // }
|
|
205
|
+
* // },
|
|
206
|
+
* // connection
|
|
207
|
+
* // });
|
|
208
|
+
* ```
|
|
65
209
|
*/
|
|
66
210
|
function defineConsumer(queue, message, options) {
|
|
67
211
|
return {
|
|
@@ -71,12 +215,78 @@ function defineConsumer(queue, message, options) {
|
|
|
71
215
|
};
|
|
72
216
|
}
|
|
73
217
|
/**
|
|
74
|
-
* Define an AMQP contract
|
|
218
|
+
* Define an AMQP contract.
|
|
219
|
+
*
|
|
220
|
+
* A contract is the central definition of your AMQP messaging topology. It brings together
|
|
221
|
+
* all exchanges, queues, bindings, publishers, and consumers in a single, type-safe definition.
|
|
222
|
+
*
|
|
223
|
+
* The contract is used by both clients (for publishing) and workers (for consuming) to ensure
|
|
224
|
+
* type safety throughout your messaging infrastructure. TypeScript will infer all message types
|
|
225
|
+
* and publisher/consumer names from the contract.
|
|
226
|
+
*
|
|
227
|
+
* @param definition - The contract definition containing all AMQP resources
|
|
228
|
+
* @param definition.exchanges - Named exchange definitions
|
|
229
|
+
* @param definition.queues - Named queue definitions
|
|
230
|
+
* @param definition.bindings - Named binding definitions (queue-to-exchange or exchange-to-exchange)
|
|
231
|
+
* @param definition.publishers - Named publisher definitions for sending messages
|
|
232
|
+
* @param definition.consumers - Named consumer definitions for receiving messages
|
|
233
|
+
* @returns The same contract definition with full type inference
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```typescript
|
|
237
|
+
* import {
|
|
238
|
+
* defineContract,
|
|
239
|
+
* defineExchange,
|
|
240
|
+
* defineQueue,
|
|
241
|
+
* defineQueueBinding,
|
|
242
|
+
* definePublisher,
|
|
243
|
+
* defineConsumer,
|
|
244
|
+
* defineMessage,
|
|
245
|
+
* } from '@amqp-contract/contract';
|
|
246
|
+
* import { z } from 'zod';
|
|
247
|
+
*
|
|
248
|
+
* // Define resources
|
|
249
|
+
* const ordersExchange = defineExchange('orders', 'topic', { durable: true });
|
|
250
|
+
* const orderQueue = defineQueue('order-processing', { durable: true });
|
|
251
|
+
* const orderMessage = defineMessage(
|
|
252
|
+
* z.object({
|
|
253
|
+
* orderId: z.string(),
|
|
254
|
+
* amount: z.number(),
|
|
255
|
+
* })
|
|
256
|
+
* );
|
|
257
|
+
*
|
|
258
|
+
* // Compose contract
|
|
259
|
+
* export const contract = defineContract({
|
|
260
|
+
* exchanges: {
|
|
261
|
+
* orders: ordersExchange,
|
|
262
|
+
* },
|
|
263
|
+
* queues: {
|
|
264
|
+
* orderProcessing: orderQueue,
|
|
265
|
+
* },
|
|
266
|
+
* bindings: {
|
|
267
|
+
* orderBinding: defineQueueBinding(orderQueue, ordersExchange, {
|
|
268
|
+
* routingKey: 'order.created',
|
|
269
|
+
* }),
|
|
270
|
+
* },
|
|
271
|
+
* publishers: {
|
|
272
|
+
* orderCreated: definePublisher(ordersExchange, orderMessage, {
|
|
273
|
+
* routingKey: 'order.created',
|
|
274
|
+
* }),
|
|
275
|
+
* },
|
|
276
|
+
* consumers: {
|
|
277
|
+
* processOrder: defineConsumer(orderQueue, orderMessage),
|
|
278
|
+
* },
|
|
279
|
+
* });
|
|
280
|
+
*
|
|
281
|
+
* // TypeScript now knows:
|
|
282
|
+
* // - client.publish('orderCreated', { orderId: string, amount: number })
|
|
283
|
+
* // - handler: async (message: { orderId: string, amount: number }) => void
|
|
284
|
+
* ```
|
|
75
285
|
*/
|
|
76
286
|
function defineContract(definition) {
|
|
77
287
|
return definition;
|
|
78
288
|
}
|
|
79
289
|
|
|
80
290
|
//#endregion
|
|
81
|
-
export {
|
|
291
|
+
export { defineConsumer, defineContract, defineExchange, defineExchangeBinding, defineMessage, definePublisher, defineQueue, defineQueueBinding };
|
|
82
292
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/builder.ts"],"sourcesContent":["import type {\n AnySchema,\n BindingDefinition,\n QueueBindingDefinition,\n ExchangeBindingDefinition,\n ConsumerDefinition,\n ContractDefinition,\n ExchangeDefinition,\n ExchangeType,\n PublisherDefinition,\n QueueDefinition,\n} from \"./types.js\";\n\n/**\n * Message schema with metadata\n */\nexport interface MessageSchema<TSchema extends AnySchema = AnySchema> extends AnySchema {\n readonly name: string;\n readonly schema: TSchema;\n readonly \"~standard\": TSchema[\"~standard\"];\n}\n\n/**\n * Define a message schema with metadata\n */\nexport function defineMessage<TSchema extends AnySchema>(\n name: string,\n schema: TSchema,\n): MessageSchema<TSchema> {\n return {\n name,\n schema,\n \"~standard\": schema[\"~standard\"],\n };\n}\n\n/**\n * Define an AMQP exchange\n */\nexport function defineExchange(\n name: string,\n type: ExchangeType,\n options?: Omit<ExchangeDefinition, \"name\" | \"type\">,\n): ExchangeDefinition {\n return {\n name,\n type,\n ...options,\n };\n}\n\n/**\n * Define an AMQP queue\n */\nexport function defineQueue(\n name: string,\n options?: Omit<QueueDefinition, \"name\">,\n): QueueDefinition {\n return {\n name,\n ...options,\n };\n}\n\n/**\n * Define a binding between queue and exchange\n */\nexport function defineBinding(\n queue: string,\n exchange: string,\n options?: Omit<QueueBindingDefinition, \"type\" | \"queue\" | \"exchange\">,\n): QueueBindingDefinition {\n return {\n type: \"queue\",\n queue,\n exchange,\n ...options,\n };\n}\n\n/**\n * Define a binding between exchange and exchange (source -> destination)\n */\nexport function defineExchangeBinding(\n destination: string,\n source: string,\n options?: Omit<ExchangeBindingDefinition, \"type\" | \"source\" | \"destination\">,\n): ExchangeBindingDefinition {\n return {\n type: \"exchange\",\n source,\n destination,\n ...options,\n };\n}\n\n/**\n * Define a message publisher\n */\nexport function definePublisher<TMessageSchema extends AnySchema>(\n exchange: string,\n message: TMessageSchema,\n options?: Omit<PublisherDefinition<TMessageSchema>, \"exchange\" | \"message\">,\n): PublisherDefinition<TMessageSchema> {\n return {\n exchange,\n message,\n ...options,\n };\n}\n\n/**\n * Define a message consumer\n */\nexport function defineConsumer<\n TMessageSchema extends AnySchema,\n THandlerResultSchema extends AnySchema = AnySchema,\n>(\n queue: string,\n message: TMessageSchema,\n options?: Omit<ConsumerDefinition<TMessageSchema, THandlerResultSchema>, \"queue\" | \"message\">,\n): ConsumerDefinition<TMessageSchema, THandlerResultSchema> {\n return {\n queue,\n message,\n ...options,\n };\n}\n\n/**\n * Define an AMQP contract\n */\nexport function defineContract<\n TContract extends ContractDefinition<TExchanges, TQueues, TBindings, TPublishers, TConsumers>,\n TExchanges extends Record<string, ExchangeDefinition> = Record<string, ExchangeDefinition>,\n TQueues extends Record<string, QueueDefinition> = Record<string, QueueDefinition>,\n TBindings extends Record<string, BindingDefinition> = Record<string, BindingDefinition>,\n TPublishers extends Record<string, PublisherDefinition> = Record<string, PublisherDefinition>,\n TConsumers extends Record<string, ConsumerDefinition> = Record<string, ConsumerDefinition>,\n>(definition: TContract): TContract {\n return definition;\n}\n"],"mappings":";;;;AAyBA,SAAgB,cACd,MACA,QACwB;AACxB,QAAO;EACL;EACA;EACA,aAAa,OAAO;EACrB;;;;;AAMH,SAAgB,eACd,MACA,MACA,SACoB;AACpB,QAAO;EACL;EACA;EACA,GAAG;EACJ;;;;;AAMH,SAAgB,YACd,MACA,SACiB;AACjB,QAAO;EACL;EACA,GAAG;EACJ;;;;;AAMH,SAAgB,cACd,OACA,UACA,SACwB;AACxB,QAAO;EACL,MAAM;EACN;EACA;EACA,GAAG;EACJ;;;;;AAMH,SAAgB,sBACd,aACA,QACA,SAC2B;AAC3B,QAAO;EACL,MAAM;EACN;EACA;EACA,GAAG;EACJ;;;;;AAMH,SAAgB,gBACd,UACA,SACA,SACqC;AACrC,QAAO;EACL;EACA;EACA,GAAG;EACJ;;;;;AAMH,SAAgB,eAId,OACA,SACA,SAC0D;AAC1D,QAAO;EACL;EACA;EACA,GAAG;EACJ;;;;;AAMH,SAAgB,eAOd,YAAkC;AAClC,QAAO"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/builder.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type {\n QueueBindingDefinition,\n ExchangeBindingDefinition,\n ConsumerDefinition,\n ContractDefinition,\n ExchangeDefinition,\n PublisherDefinition,\n QueueDefinition,\n MessageDefinition,\n FanoutExchangeDefinition,\n TopicExchangeDefinition,\n DirectExchangeDefinition,\n BaseExchangeDefinition,\n} from \"./types.js\";\n\n/**\n * Define a fanout exchange.\n *\n * A fanout exchange routes messages to all bound queues without considering routing keys.\n * This exchange type is ideal for broadcasting messages to multiple consumers.\n *\n * @param name - The name of the exchange\n * @param type - Must be \"fanout\"\n * @param options - Optional exchange configuration\n * @param options.durable - If true, the exchange survives broker restarts (default: false)\n * @param options.autoDelete - If true, the exchange is deleted when no queues are bound (default: false)\n * @param options.internal - If true, the exchange cannot be directly published to (default: false)\n * @param options.arguments - Additional AMQP arguments for the exchange\n * @returns A fanout exchange definition\n *\n * @example\n * ```typescript\n * const logsExchange = defineExchange('logs', 'fanout', {\n * durable: true\n * });\n * ```\n */\nexport function defineExchange(\n name: string,\n type: \"fanout\",\n options?: Omit<BaseExchangeDefinition, \"name\" | \"type\">,\n): FanoutExchangeDefinition;\n\n/**\n * Define a direct exchange.\n *\n * A direct exchange routes messages to queues based on exact routing key matches.\n * This exchange type is ideal for point-to-point messaging.\n *\n * @param name - The name of the exchange\n * @param type - Must be \"direct\"\n * @param options - Optional exchange configuration\n * @param options.durable - If true, the exchange survives broker restarts (default: false)\n * @param options.autoDelete - If true, the exchange is deleted when no queues are bound (default: false)\n * @param options.internal - If true, the exchange cannot be directly published to (default: false)\n * @param options.arguments - Additional AMQP arguments for the exchange\n * @returns A direct exchange definition\n *\n * @example\n * ```typescript\n * const tasksExchange = defineExchange('tasks', 'direct', {\n * durable: true\n * });\n * ```\n */\nexport function defineExchange(\n name: string,\n type: \"direct\",\n options?: Omit<BaseExchangeDefinition, \"name\" | \"type\">,\n): DirectExchangeDefinition;\n\n/**\n * Define a topic exchange.\n *\n * A topic exchange routes messages to queues based on routing key patterns.\n * Routing keys can use wildcards: `*` matches one word, `#` matches zero or more words.\n * This exchange type is ideal for flexible message routing based on hierarchical topics.\n *\n * @param name - The name of the exchange\n * @param type - Must be \"topic\"\n * @param options - Optional exchange configuration\n * @param options.durable - If true, the exchange survives broker restarts (default: false)\n * @param options.autoDelete - If true, the exchange is deleted when no queues are bound (default: false)\n * @param options.internal - If true, the exchange cannot be directly published to (default: false)\n * @param options.arguments - Additional AMQP arguments for the exchange\n * @returns A topic exchange definition\n *\n * @example\n * ```typescript\n * const ordersExchange = defineExchange('orders', 'topic', {\n * durable: true\n * });\n * ```\n */\nexport function defineExchange(\n name: string,\n type: \"topic\",\n options?: Omit<BaseExchangeDefinition, \"name\" | \"type\">,\n): TopicExchangeDefinition;\n\n/**\n * Define an AMQP exchange.\n *\n * An exchange receives messages from publishers and routes them to queues based on the exchange type\n * and routing rules. This is the implementation function - use the type-specific overloads for better\n * type safety.\n *\n * @param name - The name of the exchange\n * @param type - The type of exchange: \"fanout\", \"direct\", or \"topic\"\n * @param options - Optional exchange configuration\n * @returns An exchange definition\n * @internal\n */\nexport function defineExchange(\n name: string,\n type: \"fanout\" | \"direct\" | \"topic\",\n options?: Omit<BaseExchangeDefinition, \"name\" | \"type\">,\n): ExchangeDefinition {\n return {\n name,\n type,\n ...options,\n };\n}\n\n/**\n * Define an AMQP queue.\n *\n * A queue stores messages until they are consumed by workers. Queues can be bound to exchanges\n * to receive messages based on routing rules.\n *\n * @param name - The name of the queue\n * @param options - Optional queue configuration\n * @param options.durable - If true, the queue survives broker restarts (default: false)\n * @param options.exclusive - If true, the queue can only be used by the declaring connection (default: false)\n * @param options.autoDelete - If true, the queue is deleted when the last consumer unsubscribes (default: false)\n * @param options.arguments - Additional AMQP arguments (e.g., x-message-ttl, x-dead-letter-exchange)\n * @returns A queue definition\n *\n * @example\n * ```typescript\n * const orderProcessingQueue = defineQueue('order-processing', {\n * durable: true,\n * arguments: {\n * 'x-message-ttl': 86400000, // 24 hours\n * 'x-dead-letter-exchange': 'orders-dlx'\n * }\n * });\n * ```\n */\nexport function defineQueue(\n name: string,\n options?: Omit<QueueDefinition, \"name\">,\n): QueueDefinition {\n return {\n name,\n ...options,\n };\n}\n\n/**\n * Define a message definition with payload and optional headers/metadata.\n *\n * A message definition specifies the schema for message payloads and headers using\n * Standard Schema v1 compatible libraries (Zod, Valibot, ArkType, etc.).\n * The schemas are used for automatic validation when publishing or consuming messages.\n *\n * @param payload - The payload schema (must be Standard Schema v1 compatible)\n * @param options - Optional message metadata\n * @param options.headers - Optional header schema for message headers\n * @param options.summary - Brief description for documentation (used in AsyncAPI generation)\n * @param options.description - Detailed description for documentation (used in AsyncAPI generation)\n * @returns A message definition with inferred types\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * const orderMessage = defineMessage(\n * z.object({\n * orderId: z.string().uuid(),\n * customerId: z.string().uuid(),\n * amount: z.number().positive(),\n * items: z.array(z.object({\n * productId: z.string(),\n * quantity: z.number().int().positive(),\n * })),\n * }),\n * {\n * summary: 'Order created event',\n * description: 'Emitted when a new order is created in the system'\n * }\n * );\n * ```\n */\nexport function defineMessage<\n TPayload extends MessageDefinition[\"payload\"],\n THeaders extends StandardSchemaV1<Record<string, unknown>> | undefined = undefined,\n>(\n payload: TPayload,\n options?: {\n headers?: THeaders;\n summary?: string;\n description?: string;\n },\n): MessageDefinition<TPayload, THeaders> {\n return {\n payload,\n ...options,\n };\n}\n\n/**\n * Define a binding between a queue and a fanout exchange.\n *\n * Binds a queue to a fanout exchange to receive all messages published to the exchange.\n * Fanout exchanges ignore routing keys, so this overload doesn't require one.\n *\n * @param queue - The queue definition to bind\n * @param exchange - The fanout exchange definition\n * @param options - Optional binding configuration\n * @param options.arguments - Additional AMQP arguments for the binding\n * @returns A queue binding definition\n *\n * @example\n * ```typescript\n * const logsQueue = defineQueue('logs-queue', { durable: true });\n * const logsExchange = defineExchange('logs', 'fanout', { durable: true });\n *\n * const binding = defineQueueBinding(logsQueue, logsExchange);\n * ```\n */\nexport function defineQueueBinding(\n queue: QueueDefinition,\n exchange: FanoutExchangeDefinition,\n options?: Omit<\n Extract<QueueBindingDefinition, { exchange: FanoutExchangeDefinition }>,\n \"type\" | \"queue\" | \"exchange\" | \"routingKey\"\n >,\n): Extract<QueueBindingDefinition, { exchange: FanoutExchangeDefinition }>;\n\n/**\n * Define a binding between a queue and a direct or topic exchange.\n *\n * Binds a queue to an exchange with a specific routing key pattern.\n * Messages are only routed to the queue if the routing key matches the pattern.\n *\n * For direct exchanges: The routing key must match exactly.\n * For topic exchanges: The routing key can include wildcards:\n * - `*` matches exactly one word\n * - `#` matches zero or more words\n *\n * @param queue - The queue definition to bind\n * @param exchange - The direct or topic exchange definition\n * @param options - Binding configuration (routingKey is required)\n * @param options.routingKey - The routing key pattern for message routing\n * @param options.arguments - Additional AMQP arguments for the binding\n * @returns A queue binding definition\n *\n * @example\n * ```typescript\n * const orderQueue = defineQueue('order-processing', { durable: true });\n * const ordersExchange = defineExchange('orders', 'topic', { durable: true });\n *\n * // Bind with exact routing key\n * const binding = defineQueueBinding(orderQueue, ordersExchange, {\n * routingKey: 'order.created'\n * });\n *\n * // Bind with wildcard pattern\n * const allOrdersBinding = defineQueueBinding(orderQueue, ordersExchange, {\n * routingKey: 'order.*' // Matches order.created, order.updated, etc.\n * });\n * ```\n */\nexport function defineQueueBinding(\n queue: QueueDefinition,\n exchange: DirectExchangeDefinition | TopicExchangeDefinition,\n options: Omit<\n Extract<\n QueueBindingDefinition,\n { exchange: DirectExchangeDefinition | TopicExchangeDefinition }\n >,\n \"type\" | \"queue\" | \"exchange\"\n >,\n): Extract<\n QueueBindingDefinition,\n { exchange: DirectExchangeDefinition | TopicExchangeDefinition }\n>;\n\n/**\n * Define a binding between a queue and an exchange.\n *\n * This is the implementation function - use the type-specific overloads for better type safety.\n *\n * @param queue - The queue definition to bind\n * @param exchange - The exchange definition\n * @param options - Optional binding configuration\n * @returns A queue binding definition\n * @internal\n */\nexport function defineQueueBinding(\n queue: QueueDefinition,\n exchange: ExchangeDefinition,\n options?: {\n routingKey?: string;\n arguments?: Record<string, unknown>;\n },\n): QueueBindingDefinition {\n if (exchange.type === \"fanout\") {\n return {\n type: \"queue\",\n queue,\n exchange,\n ...(options?.arguments && { arguments: options.arguments }),\n } as QueueBindingDefinition;\n }\n\n return {\n type: \"queue\",\n queue,\n exchange,\n routingKey: options?.routingKey,\n ...(options?.arguments && { arguments: options.arguments }),\n } as QueueBindingDefinition;\n}\n\n/**\n * Define a binding between two exchanges (exchange-to-exchange routing).\n *\n * Binds a destination exchange to a fanout source exchange.\n * Messages published to the source exchange will be forwarded to the destination exchange.\n * Fanout exchanges ignore routing keys, so this overload doesn't require one.\n *\n * @param destination - The destination exchange definition\n * @param source - The fanout source exchange definition\n * @param options - Optional binding configuration\n * @param options.arguments - Additional AMQP arguments for the binding\n * @returns An exchange binding definition\n *\n * @example\n * ```typescript\n * const sourceExchange = defineExchange('logs', 'fanout', { durable: true });\n * const destExchange = defineExchange('all-logs', 'fanout', { durable: true });\n *\n * const binding = defineExchangeBinding(destExchange, sourceExchange);\n * ```\n */\nexport function defineExchangeBinding(\n destination: ExchangeDefinition,\n source: FanoutExchangeDefinition,\n options?: Omit<\n Extract<ExchangeBindingDefinition, { source: FanoutExchangeDefinition }>,\n \"type\" | \"source\" | \"destination\" | \"routingKey\"\n >,\n): Extract<ExchangeBindingDefinition, { source: FanoutExchangeDefinition }>;\n\n/**\n * Define a binding between two exchanges (exchange-to-exchange routing).\n *\n * Binds a destination exchange to a direct or topic source exchange with a routing key pattern.\n * Messages are forwarded from source to destination only if the routing key matches the pattern.\n *\n * @param destination - The destination exchange definition\n * @param source - The direct or topic source exchange definition\n * @param options - Binding configuration (routingKey is required)\n * @param options.routingKey - The routing key pattern for message routing\n * @param options.arguments - Additional AMQP arguments for the binding\n * @returns An exchange binding definition\n *\n * @example\n * ```typescript\n * const ordersExchange = defineExchange('orders', 'topic', { durable: true });\n * const importantExchange = defineExchange('important-orders', 'topic', { durable: true });\n *\n * // Forward only high-value orders\n * const binding = defineExchangeBinding(importantExchange, ordersExchange, {\n * routingKey: 'order.high-value.*'\n * });\n * ```\n */\nexport function defineExchangeBinding(\n destination: ExchangeDefinition,\n source: DirectExchangeDefinition | TopicExchangeDefinition,\n options: Omit<\n Extract<\n ExchangeBindingDefinition,\n { source: DirectExchangeDefinition | TopicExchangeDefinition }\n >,\n \"type\" | \"source\" | \"destination\"\n >,\n): Extract<\n ExchangeBindingDefinition,\n { source: DirectExchangeDefinition | TopicExchangeDefinition }\n>;\n\n/**\n * Define a binding between two exchanges (exchange-to-exchange routing).\n *\n * This is the implementation function - use the type-specific overloads for better type safety.\n *\n * @param destination - The destination exchange definition\n * @param source - The source exchange definition\n * @param options - Optional binding configuration\n * @returns An exchange binding definition\n * @internal\n */\nexport function defineExchangeBinding(\n destination: ExchangeDefinition,\n source: ExchangeDefinition,\n options?: {\n routingKey?: string;\n arguments?: Record<string, unknown>;\n },\n): ExchangeBindingDefinition {\n if (source.type === \"fanout\") {\n return {\n type: \"exchange\",\n source,\n destination,\n ...(options?.arguments && { arguments: options.arguments }),\n } as ExchangeBindingDefinition;\n }\n\n return {\n type: \"exchange\",\n source,\n destination,\n routingKey: options?.routingKey ?? \"\",\n ...(options?.arguments && { arguments: options.arguments }),\n } as ExchangeBindingDefinition;\n}\n\n/**\n * Define a message publisher for a fanout exchange.\n *\n * A publisher sends messages to an exchange. For fanout exchanges, messages are broadcast\n * to all bound queues regardless of routing key, so no routing key is required.\n *\n * The message schema is validated when publishing to ensure type safety.\n *\n * @param exchange - The fanout exchange definition to publish to\n * @param message - The message definition with payload schema\n * @param options - Optional publisher configuration\n * @returns A publisher definition with inferred message types\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * const logsExchange = defineExchange('logs', 'fanout', { durable: true });\n * const logMessage = defineMessage(\n * z.object({\n * level: z.enum(['info', 'warn', 'error']),\n * message: z.string(),\n * timestamp: z.string().datetime(),\n * })\n * );\n *\n * const logPublisher = definePublisher(logsExchange, logMessage);\n * ```\n */\nexport function definePublisher<TMessage extends MessageDefinition>(\n exchange: FanoutExchangeDefinition,\n message: TMessage,\n options?: Omit<\n Extract<PublisherDefinition<TMessage>, { exchange: FanoutExchangeDefinition }>,\n \"exchange\" | \"message\" | \"routingKey\"\n >,\n): Extract<PublisherDefinition<TMessage>, { exchange: FanoutExchangeDefinition }>;\n\n/**\n * Define a message publisher for a direct or topic exchange.\n *\n * A publisher sends messages to an exchange with a specific routing key.\n * The routing key determines which queues receive the message.\n *\n * The message schema is validated when publishing to ensure type safety.\n *\n * @param exchange - The direct or topic exchange definition to publish to\n * @param message - The message definition with payload schema\n * @param options - Publisher configuration (routingKey is required)\n * @param options.routingKey - The routing key for message routing\n * @returns A publisher definition with inferred message types\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * const ordersExchange = defineExchange('orders', 'topic', { durable: true });\n * const orderMessage = defineMessage(\n * z.object({\n * orderId: z.string().uuid(),\n * amount: z.number().positive(),\n * }),\n * {\n * summary: 'Order created event',\n * description: 'Emitted when a new order is created'\n * }\n * );\n *\n * const orderCreatedPublisher = definePublisher(ordersExchange, orderMessage, {\n * routingKey: 'order.created'\n * });\n * ```\n */\nexport function definePublisher<TMessage extends MessageDefinition>(\n exchange: DirectExchangeDefinition | TopicExchangeDefinition,\n message: TMessage,\n options: Omit<\n Extract<\n PublisherDefinition<TMessage>,\n { exchange: DirectExchangeDefinition | TopicExchangeDefinition }\n >,\n \"exchange\" | \"message\"\n >,\n): Extract<\n PublisherDefinition<TMessage>,\n { exchange: DirectExchangeDefinition | TopicExchangeDefinition }\n>;\n\n/**\n * Define a message publisher.\n *\n * This is the implementation function - use the type-specific overloads for better type safety.\n *\n * @param exchange - The exchange definition\n * @param message - The message definition\n * @param options - Optional publisher configuration\n * @returns A publisher definition\n * @internal\n */\nexport function definePublisher<TMessage extends MessageDefinition>(\n exchange: ExchangeDefinition,\n message: TMessage,\n options?: { routingKey?: string },\n): PublisherDefinition<TMessage> {\n if (exchange.type === \"fanout\") {\n return {\n exchange,\n message,\n } as PublisherDefinition<TMessage>;\n }\n\n return {\n exchange,\n message,\n routingKey: options?.routingKey ?? \"\",\n } as PublisherDefinition<TMessage>;\n}\n\n/**\n * Define a message consumer.\n *\n * A consumer receives and processes messages from a queue. The message schema is validated\n * automatically when messages are consumed, ensuring type safety for your handlers.\n *\n * Consumers are associated with a specific queue and message type. When you create a worker\n * with this consumer, it will process messages from the queue according to the schema.\n *\n * @param queue - The queue definition to consume from\n * @param message - The message definition with payload schema\n * @param options - Optional consumer configuration\n * @returns A consumer definition with inferred message types\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * const orderQueue = defineQueue('order-processing', { durable: true });\n * const orderMessage = defineMessage(\n * z.object({\n * orderId: z.string().uuid(),\n * customerId: z.string().uuid(),\n * amount: z.number().positive(),\n * })\n * );\n *\n * const processOrderConsumer = defineConsumer(orderQueue, orderMessage);\n *\n * // Later, when creating a worker, you'll provide a handler for this consumer:\n * // const worker = await TypedAmqpWorker.create({\n * // contract,\n * // handlers: {\n * // processOrder: async (message) => {\n * // // message is automatically typed based on the schema\n * // console.log(message.orderId); // string\n * // }\n * // },\n * // connection\n * // });\n * ```\n */\nexport function defineConsumer<TMessage extends MessageDefinition>(\n queue: QueueDefinition,\n message: TMessage,\n options?: Omit<ConsumerDefinition<TMessage>, \"queue\" | \"message\">,\n): ConsumerDefinition<TMessage> {\n return {\n queue,\n message,\n ...options,\n };\n}\n\n/**\n * Define an AMQP contract.\n *\n * A contract is the central definition of your AMQP messaging topology. It brings together\n * all exchanges, queues, bindings, publishers, and consumers in a single, type-safe definition.\n *\n * The contract is used by both clients (for publishing) and workers (for consuming) to ensure\n * type safety throughout your messaging infrastructure. TypeScript will infer all message types\n * and publisher/consumer names from the contract.\n *\n * @param definition - The contract definition containing all AMQP resources\n * @param definition.exchanges - Named exchange definitions\n * @param definition.queues - Named queue definitions\n * @param definition.bindings - Named binding definitions (queue-to-exchange or exchange-to-exchange)\n * @param definition.publishers - Named publisher definitions for sending messages\n * @param definition.consumers - Named consumer definitions for receiving messages\n * @returns The same contract definition with full type inference\n *\n * @example\n * ```typescript\n * import {\n * defineContract,\n * defineExchange,\n * defineQueue,\n * defineQueueBinding,\n * definePublisher,\n * defineConsumer,\n * defineMessage,\n * } from '@amqp-contract/contract';\n * import { z } from 'zod';\n *\n * // Define resources\n * const ordersExchange = defineExchange('orders', 'topic', { durable: true });\n * const orderQueue = defineQueue('order-processing', { durable: true });\n * const orderMessage = defineMessage(\n * z.object({\n * orderId: z.string(),\n * amount: z.number(),\n * })\n * );\n *\n * // Compose contract\n * export const contract = defineContract({\n * exchanges: {\n * orders: ordersExchange,\n * },\n * queues: {\n * orderProcessing: orderQueue,\n * },\n * bindings: {\n * orderBinding: defineQueueBinding(orderQueue, ordersExchange, {\n * routingKey: 'order.created',\n * }),\n * },\n * publishers: {\n * orderCreated: definePublisher(ordersExchange, orderMessage, {\n * routingKey: 'order.created',\n * }),\n * },\n * consumers: {\n * processOrder: defineConsumer(orderQueue, orderMessage),\n * },\n * });\n *\n * // TypeScript now knows:\n * // - client.publish('orderCreated', { orderId: string, amount: number })\n * // - handler: async (message: { orderId: string, amount: number }) => void\n * ```\n */\nexport function defineContract<TContract extends ContractDefinition>(\n definition: TContract,\n): TContract {\n return definition;\n}\n"],"mappings":";;;;;;;;;;;;;;AAkHA,SAAgB,eACd,MACA,MACA,SACoB;AACpB,QAAO;EACL;EACA;EACA,GAAG;EACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BH,SAAgB,YACd,MACA,SACiB;AACjB,QAAO;EACL;EACA,GAAG;EACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCH,SAAgB,cAId,SACA,SAKuC;AACvC,QAAO;EACL;EACA,GAAG;EACJ;;;;;;;;;;;;;AA4FH,SAAgB,mBACd,OACA,UACA,SAIwB;AACxB,KAAI,SAAS,SAAS,SACpB,QAAO;EACL,MAAM;EACN;EACA;EACA,GAAI,SAAS,aAAa,EAAE,WAAW,QAAQ,WAAW;EAC3D;AAGH,QAAO;EACL,MAAM;EACN;EACA;EACA,YAAY,SAAS;EACrB,GAAI,SAAS,aAAa,EAAE,WAAW,QAAQ,WAAW;EAC3D;;;;;;;;;;;;;AAmFH,SAAgB,sBACd,aACA,QACA,SAI2B;AAC3B,KAAI,OAAO,SAAS,SAClB,QAAO;EACL,MAAM;EACN;EACA;EACA,GAAI,SAAS,aAAa,EAAE,WAAW,QAAQ,WAAW;EAC3D;AAGH,QAAO;EACL,MAAM;EACN;EACA;EACA,YAAY,SAAS,cAAc;EACnC,GAAI,SAAS,aAAa,EAAE,WAAW,QAAQ,WAAW;EAC3D;;;;;;;;;;;;;AAsGH,SAAgB,gBACd,UACA,SACA,SAC+B;AAC/B,KAAI,SAAS,SAAS,SACpB,QAAO;EACL;EACA;EACD;AAGH,QAAO;EACL;EACA;EACA,YAAY,SAAS,cAAc;EACpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CH,SAAgB,eACd,OACA,SACA,SAC8B;AAC9B,QAAO;EACL;EACA;EACA,GAAG;EACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwEH,SAAgB,eACd,YACW;AACX,QAAO"}
|