@amqp-contract/contract 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -14
- package/dist/index.cjs +550 -238
- package/dist/index.d.cts +787 -405
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +787 -405
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +540 -236
- package/dist/index.mjs.map +1 -1
- package/docs/index.md +738 -216
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -72,6 +72,30 @@ type QuorumNativeRetryOptions = {
|
|
|
72
72
|
*/
|
|
73
73
|
mode: "quorum-native";
|
|
74
74
|
};
|
|
75
|
+
/**
|
|
76
|
+
* Resolved TTL-Backoff retry options with all defaults applied.
|
|
77
|
+
*
|
|
78
|
+
* This type is used internally in queue definitions after `defineQueue` has applied
|
|
79
|
+
* default values. All fields are required.
|
|
80
|
+
*
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
type ResolvedTtlBackoffRetryOptions = {
|
|
84
|
+
mode: "ttl-backoff";
|
|
85
|
+
maxRetries: number;
|
|
86
|
+
initialDelayMs: number;
|
|
87
|
+
maxDelayMs: number;
|
|
88
|
+
backoffMultiplier: number;
|
|
89
|
+
jitter: boolean;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Resolved retry configuration stored in queue definitions.
|
|
93
|
+
*
|
|
94
|
+
* This is a discriminated union based on the `mode` field:
|
|
95
|
+
* - `ttl-backoff`: Has all TTL-backoff options with defaults applied
|
|
96
|
+
* - `quorum-native`: No additional options (uses RabbitMQ native retry)
|
|
97
|
+
*/
|
|
98
|
+
type ResolvedRetryOptions = ResolvedTtlBackoffRetryOptions | QuorumNativeRetryOptions;
|
|
75
99
|
/**
|
|
76
100
|
* Supported compression algorithms for message payloads.
|
|
77
101
|
*
|
|
@@ -505,10 +529,12 @@ type QuorumQueueDefinition = BaseQueueDefinition & {
|
|
|
505
529
|
* Retry configuration for handling failed message processing.
|
|
506
530
|
*
|
|
507
531
|
* Quorum queues support both:
|
|
508
|
-
* - `ttl-backoff`: Uses wait queues with exponential backoff
|
|
532
|
+
* - `ttl-backoff`: Uses wait queues with exponential backoff (default)
|
|
509
533
|
* - `quorum-native`: Uses RabbitMQ's native delivery limit feature
|
|
534
|
+
*
|
|
535
|
+
* When the queue is created, defaults are applied for TTL-backoff options.
|
|
510
536
|
*/
|
|
511
|
-
retry
|
|
537
|
+
retry: ResolvedRetryOptions;
|
|
512
538
|
};
|
|
513
539
|
/**
|
|
514
540
|
* Definition of a classic queue.
|
|
@@ -535,9 +561,10 @@ type ClassicQueueDefinition = BaseQueueDefinition & {
|
|
|
535
561
|
/**
|
|
536
562
|
* Retry configuration for handling failed message processing.
|
|
537
563
|
*
|
|
538
|
-
* Classic queues only support TTL-backoff retry mode.
|
|
564
|
+
* Classic queues only support TTL-backoff retry mode (default).
|
|
565
|
+
* When the queue is created, defaults are applied.
|
|
539
566
|
*/
|
|
540
|
-
retry
|
|
567
|
+
retry: ResolvedTtlBackoffRetryOptions;
|
|
541
568
|
};
|
|
542
569
|
/**
|
|
543
570
|
* Definition of an AMQP queue.
|
|
@@ -771,7 +798,51 @@ type ConsumerDefinition<TMessage extends MessageDefinition = MessageDefinition>
|
|
|
771
798
|
message: TMessage;
|
|
772
799
|
};
|
|
773
800
|
/**
|
|
774
|
-
*
|
|
801
|
+
* Base type for event publisher configuration.
|
|
802
|
+
*
|
|
803
|
+
* This is a simplified type used in ContractDefinition. The full generic type
|
|
804
|
+
* is defined in the builder module.
|
|
805
|
+
*
|
|
806
|
+
* @see defineEventPublisher for creating event publishers
|
|
807
|
+
*/
|
|
808
|
+
type EventPublisherConfigBase = {
|
|
809
|
+
__brand: "EventPublisherConfig";
|
|
810
|
+
exchange: ExchangeDefinition;
|
|
811
|
+
message: MessageDefinition;
|
|
812
|
+
routingKey: string | undefined;
|
|
813
|
+
arguments?: Record<string, unknown>;
|
|
814
|
+
};
|
|
815
|
+
/**
|
|
816
|
+
* Base type for command consumer configuration.
|
|
817
|
+
*
|
|
818
|
+
* This is a simplified type used in ContractDefinition. The full generic type
|
|
819
|
+
* is defined in the builder module.
|
|
820
|
+
*
|
|
821
|
+
* @see defineCommandConsumer for creating command consumers
|
|
822
|
+
*/
|
|
823
|
+
type CommandConsumerConfigBase = {
|
|
824
|
+
__brand: "CommandConsumerConfig";
|
|
825
|
+
consumer: ConsumerDefinition;
|
|
826
|
+
binding: QueueBindingDefinition;
|
|
827
|
+
exchange: ExchangeDefinition;
|
|
828
|
+
message: MessageDefinition;
|
|
829
|
+
routingKey: string | undefined;
|
|
830
|
+
};
|
|
831
|
+
/**
|
|
832
|
+
* Base type for event consumer result.
|
|
833
|
+
*
|
|
834
|
+
* This is a simplified type used in ContractDefinitionInput. The full generic type
|
|
835
|
+
* is defined in the builder module.
|
|
836
|
+
*
|
|
837
|
+
* @see defineEventConsumer for creating event consumers
|
|
838
|
+
*/
|
|
839
|
+
type EventConsumerResultBase = {
|
|
840
|
+
__brand: "EventConsumerResult";
|
|
841
|
+
consumer: ConsumerDefinition;
|
|
842
|
+
binding: QueueBindingDefinition;
|
|
843
|
+
};
|
|
844
|
+
/**
|
|
845
|
+
* Complete AMQP contract definition (output type).
|
|
775
846
|
*
|
|
776
847
|
* A contract brings together all AMQP resources into a single, type-safe definition.
|
|
777
848
|
* It defines the complete messaging topology including exchanges, queues, bindings,
|
|
@@ -835,6 +906,69 @@ type ContractDefinition = {
|
|
|
835
906
|
*/
|
|
836
907
|
consumers?: Record<string, ConsumerDefinition>;
|
|
837
908
|
};
|
|
909
|
+
/**
|
|
910
|
+
* Publisher entry that can be passed to defineContract's publishers section.
|
|
911
|
+
*
|
|
912
|
+
* Can be either:
|
|
913
|
+
* - A plain PublisherDefinition from definePublisher
|
|
914
|
+
* - An EventPublisherConfig from defineEventPublisher (auto-extracted to publisher)
|
|
915
|
+
*/
|
|
916
|
+
type PublisherEntry = PublisherDefinition | EventPublisherConfigBase;
|
|
917
|
+
/**
|
|
918
|
+
* Consumer entry that can be passed to defineContract's consumers section.
|
|
919
|
+
*
|
|
920
|
+
* Can be either:
|
|
921
|
+
* - A plain ConsumerDefinition from defineConsumer
|
|
922
|
+
* - An EventConsumerResult from defineEventConsumer (binding auto-extracted)
|
|
923
|
+
* - A CommandConsumerConfig from defineCommandConsumer (binding auto-extracted)
|
|
924
|
+
*/
|
|
925
|
+
type ConsumerEntry = ConsumerDefinition | EventConsumerResultBase | CommandConsumerConfigBase;
|
|
926
|
+
/**
|
|
927
|
+
* Contract definition input type with automatic extraction of event/command patterns.
|
|
928
|
+
*
|
|
929
|
+
* This type allows passing event and command configs directly to the publishers
|
|
930
|
+
* and consumers sections. `defineContract` will automatically extract the appropriate
|
|
931
|
+
* definitions and generate bindings.
|
|
932
|
+
*
|
|
933
|
+
* @example
|
|
934
|
+
* ```typescript
|
|
935
|
+
* const contract = defineContract({
|
|
936
|
+
* exchanges: { orders: ordersExchange },
|
|
937
|
+
* queues: { processing: processingQueue },
|
|
938
|
+
* publishers: {
|
|
939
|
+
* // EventPublisherConfig → auto-extracted to publisher
|
|
940
|
+
* orderCreated: defineEventPublisher(ordersExchange, orderMessage, { routingKey: "order.created" }),
|
|
941
|
+
* },
|
|
942
|
+
* consumers: {
|
|
943
|
+
* // CommandConsumerConfig → auto-extracted to consumer + binding
|
|
944
|
+
* processOrder: defineCommandConsumer(orderQueue, ordersExchange, orderMessage, { routingKey: "order.process" }),
|
|
945
|
+
* // EventConsumerResult → auto-extracted to consumer + binding
|
|
946
|
+
* notify: defineEventConsumer(orderCreatedEvent, notificationQueue),
|
|
947
|
+
* },
|
|
948
|
+
* });
|
|
949
|
+
* ```
|
|
950
|
+
*
|
|
951
|
+
* @see defineContract - Processes this input and returns a ContractDefinition
|
|
952
|
+
*/
|
|
953
|
+
type ContractDefinitionInput = Omit<ContractDefinition, "publishers" | "consumers"> & {
|
|
954
|
+
/**
|
|
955
|
+
* Named publisher definitions.
|
|
956
|
+
*
|
|
957
|
+
* Can accept:
|
|
958
|
+
* - PublisherDefinition from definePublisher
|
|
959
|
+
* - EventPublisherConfig from defineEventPublisher (auto-extracted to publisher)
|
|
960
|
+
*/
|
|
961
|
+
publishers?: Record<string, PublisherEntry>;
|
|
962
|
+
/**
|
|
963
|
+
* Named consumer definitions.
|
|
964
|
+
*
|
|
965
|
+
* Can accept:
|
|
966
|
+
* - ConsumerDefinition from defineConsumer
|
|
967
|
+
* - EventConsumerResult from defineEventConsumer (binding auto-extracted)
|
|
968
|
+
* - CommandConsumerConfig from defineCommandConsumer (binding auto-extracted)
|
|
969
|
+
*/
|
|
970
|
+
consumers?: Record<string, ConsumerEntry>;
|
|
971
|
+
};
|
|
838
972
|
/**
|
|
839
973
|
* Extract publisher names from a contract.
|
|
840
974
|
*
|
|
@@ -868,7 +1002,7 @@ type InferPublisherNames<TContract extends ContractDefinition> = TContract["publ
|
|
|
868
1002
|
*/
|
|
869
1003
|
type InferConsumerNames<TContract extends ContractDefinition> = TContract["consumers"] extends Record<string, unknown> ? keyof TContract["consumers"] : never;
|
|
870
1004
|
//#endregion
|
|
871
|
-
//#region src/builder.d.ts
|
|
1005
|
+
//#region src/builder/exchange.d.ts
|
|
872
1006
|
/**
|
|
873
1007
|
* Define a fanout exchange.
|
|
874
1008
|
*
|
|
@@ -939,6 +1073,133 @@ declare function defineExchange(name: string, type: "direct", options?: Omit<Bas
|
|
|
939
1073
|
* ```
|
|
940
1074
|
*/
|
|
941
1075
|
declare function defineExchange(name: string, type: "topic", options?: Omit<BaseExchangeDefinition, "name" | "type">): TopicExchangeDefinition;
|
|
1076
|
+
//#endregion
|
|
1077
|
+
//#region src/builder/message.d.ts
|
|
1078
|
+
/**
|
|
1079
|
+
* Define a message definition with payload and optional headers/metadata.
|
|
1080
|
+
*
|
|
1081
|
+
* A message definition specifies the schema for message payloads and headers using
|
|
1082
|
+
* Standard Schema v1 compatible libraries (Zod, Valibot, ArkType, etc.).
|
|
1083
|
+
* The schemas are used for automatic validation when publishing or consuming messages.
|
|
1084
|
+
*
|
|
1085
|
+
* @param payload - The payload schema (must be Standard Schema v1 compatible)
|
|
1086
|
+
* @param options - Optional message metadata
|
|
1087
|
+
* @param options.headers - Optional header schema for message headers
|
|
1088
|
+
* @param options.summary - Brief description for documentation (used in AsyncAPI generation)
|
|
1089
|
+
* @param options.description - Detailed description for documentation (used in AsyncAPI generation)
|
|
1090
|
+
* @returns A message definition with inferred types
|
|
1091
|
+
*
|
|
1092
|
+
* @example
|
|
1093
|
+
* ```typescript
|
|
1094
|
+
* import { z } from 'zod';
|
|
1095
|
+
*
|
|
1096
|
+
* const orderMessage = defineMessage(
|
|
1097
|
+
* z.object({
|
|
1098
|
+
* orderId: z.string().uuid(),
|
|
1099
|
+
* customerId: z.string().uuid(),
|
|
1100
|
+
* amount: z.number().positive(),
|
|
1101
|
+
* items: z.array(z.object({
|
|
1102
|
+
* productId: z.string(),
|
|
1103
|
+
* quantity: z.number().int().positive(),
|
|
1104
|
+
* })),
|
|
1105
|
+
* }),
|
|
1106
|
+
* {
|
|
1107
|
+
* summary: 'Order created event',
|
|
1108
|
+
* description: 'Emitted when a new order is created in the system'
|
|
1109
|
+
* }
|
|
1110
|
+
* );
|
|
1111
|
+
* ```
|
|
1112
|
+
*/
|
|
1113
|
+
declare function defineMessage<TPayload extends MessageDefinition["payload"], THeaders extends StandardSchemaV1<Record<string, unknown>> | undefined = undefined>(payload: TPayload, options?: {
|
|
1114
|
+
headers?: THeaders;
|
|
1115
|
+
summary?: string;
|
|
1116
|
+
description?: string;
|
|
1117
|
+
}): MessageDefinition<TPayload, THeaders>;
|
|
1118
|
+
//#endregion
|
|
1119
|
+
//#region src/builder/queue.d.ts
|
|
1120
|
+
/**
|
|
1121
|
+
* Type guard to check if a queue entry is a QueueWithTtlBackoffInfrastructure.
|
|
1122
|
+
*
|
|
1123
|
+
* When you configure a queue with TTL-backoff retry and a dead letter exchange,
|
|
1124
|
+
* `defineQueue` returns a `QueueWithTtlBackoffInfrastructure` instead of a plain
|
|
1125
|
+
* `QueueDefinition`. This type guard helps you distinguish between the two.
|
|
1126
|
+
*
|
|
1127
|
+
* **When to use:**
|
|
1128
|
+
* - When you need to check the type of a queue entry at runtime
|
|
1129
|
+
* - When writing generic code that handles both plain queues and infrastructure wrappers
|
|
1130
|
+
*
|
|
1131
|
+
* **Related functions:**
|
|
1132
|
+
* - `extractQueue()` - Use this to get the underlying queue definition from either type
|
|
1133
|
+
*
|
|
1134
|
+
* @param entry - The queue entry to check
|
|
1135
|
+
* @returns True if the entry is a QueueWithTtlBackoffInfrastructure, false otherwise
|
|
1136
|
+
*
|
|
1137
|
+
* @example
|
|
1138
|
+
* ```typescript
|
|
1139
|
+
* const queue = defineQueue('orders', {
|
|
1140
|
+
* deadLetter: { exchange: dlx },
|
|
1141
|
+
* retry: { mode: 'ttl-backoff' },
|
|
1142
|
+
* });
|
|
1143
|
+
*
|
|
1144
|
+
* if (isQueueWithTtlBackoffInfrastructure(queue)) {
|
|
1145
|
+
* // queue has .queue, .waitQueue, .waitQueueBinding, .mainQueueRetryBinding
|
|
1146
|
+
* console.log('Wait queue:', queue.waitQueue.name);
|
|
1147
|
+
* } else {
|
|
1148
|
+
* // queue is a plain QueueDefinition
|
|
1149
|
+
* console.log('Queue:', queue.name);
|
|
1150
|
+
* }
|
|
1151
|
+
* ```
|
|
1152
|
+
*/
|
|
1153
|
+
declare function isQueueWithTtlBackoffInfrastructure(entry: QueueEntry): entry is QueueWithTtlBackoffInfrastructure;
|
|
1154
|
+
/**
|
|
1155
|
+
* Extract the plain QueueDefinition from a QueueEntry.
|
|
1156
|
+
*
|
|
1157
|
+
* **Why this function exists:**
|
|
1158
|
+
* When you configure a queue with TTL-backoff retry and a dead letter exchange,
|
|
1159
|
+
* `defineQueue` (or `defineTtlBackoffQueue`) returns a wrapper object that includes
|
|
1160
|
+
* the main queue, wait queue, and bindings. This function extracts the underlying
|
|
1161
|
+
* queue definition so you can access properties like `name`, `type`, etc.
|
|
1162
|
+
*
|
|
1163
|
+
* **When to use:**
|
|
1164
|
+
* - When you need to access queue properties (name, type, deadLetter, etc.)
|
|
1165
|
+
* - When passing a queue to functions that expect a plain QueueDefinition
|
|
1166
|
+
* - Works safely on both plain queues and infrastructure wrappers
|
|
1167
|
+
*
|
|
1168
|
+
* **How it works:**
|
|
1169
|
+
* - If the entry is a `QueueWithTtlBackoffInfrastructure`, returns `entry.queue`
|
|
1170
|
+
* - Otherwise, returns the entry as-is (it's already a plain QueueDefinition)
|
|
1171
|
+
*
|
|
1172
|
+
* @param entry - The queue entry (either plain QueueDefinition or QueueWithTtlBackoffInfrastructure)
|
|
1173
|
+
* @returns The plain QueueDefinition
|
|
1174
|
+
*
|
|
1175
|
+
* @example
|
|
1176
|
+
* ```typescript
|
|
1177
|
+
* import { defineQueue, defineTtlBackoffQueue, extractQueue } from '@amqp-contract/contract';
|
|
1178
|
+
*
|
|
1179
|
+
* // TTL-backoff queue returns a wrapper
|
|
1180
|
+
* const orderQueue = defineTtlBackoffQueue('orders', {
|
|
1181
|
+
* deadLetterExchange: dlx,
|
|
1182
|
+
* maxRetries: 3,
|
|
1183
|
+
* });
|
|
1184
|
+
*
|
|
1185
|
+
* // Use extractQueue to access the queue name
|
|
1186
|
+
* const queueName = extractQueue(orderQueue).name; // 'orders'
|
|
1187
|
+
*
|
|
1188
|
+
* // Also works safely on plain queues
|
|
1189
|
+
* const plainQueue = defineQueue('simple', { type: 'quorum', retry: { mode: 'quorum-native' } });
|
|
1190
|
+
* const plainName = extractQueue(plainQueue).name; // 'simple'
|
|
1191
|
+
*
|
|
1192
|
+
* // Access other properties
|
|
1193
|
+
* const queueDef = extractQueue(orderQueue);
|
|
1194
|
+
* console.log(queueDef.name); // 'orders'
|
|
1195
|
+
* console.log(queueDef.type); // 'quorum'
|
|
1196
|
+
* console.log(queueDef.deadLetter); // { exchange: dlx, ... }
|
|
1197
|
+
* ```
|
|
1198
|
+
*
|
|
1199
|
+
* @see isQueueWithTtlBackoffInfrastructure - Type guard to check if extraction is needed
|
|
1200
|
+
* @see defineTtlBackoffQueue - Creates queues with TTL-backoff infrastructure
|
|
1201
|
+
*/
|
|
1202
|
+
declare function extractQueue(entry: QueueEntry): QueueDefinition;
|
|
942
1203
|
/**
|
|
943
1204
|
* Define an AMQP queue.
|
|
944
1205
|
*
|
|
@@ -1003,45 +1264,177 @@ declare function defineExchange(name: string, type: "topic", options?: Omit<Base
|
|
|
1003
1264
|
*/
|
|
1004
1265
|
declare function defineQueue(name: string, options?: DefineQueueOptions): QueueDefinition | QueueWithTtlBackoffInfrastructure;
|
|
1005
1266
|
/**
|
|
1006
|
-
*
|
|
1267
|
+
* Options for creating a quorum queue with quorum-native retry.
|
|
1007
1268
|
*
|
|
1008
|
-
*
|
|
1009
|
-
*
|
|
1010
|
-
*
|
|
1269
|
+
* This simplified helper enforces the required configuration for quorum-native retry:
|
|
1270
|
+
* - Dead letter exchange is required (for failed messages)
|
|
1271
|
+
* - Delivery limit is required (for retry count)
|
|
1272
|
+
*/
|
|
1273
|
+
type DefineQuorumQueueOptions = {
|
|
1274
|
+
/**
|
|
1275
|
+
* Dead letter configuration - required for retry support.
|
|
1276
|
+
* Failed messages will be sent to this exchange.
|
|
1277
|
+
*/
|
|
1278
|
+
deadLetterExchange: ExchangeDefinition;
|
|
1279
|
+
/**
|
|
1280
|
+
* Optional routing key for dead-lettered messages.
|
|
1281
|
+
*/
|
|
1282
|
+
deadLetterRoutingKey?: string;
|
|
1283
|
+
/**
|
|
1284
|
+
* Maximum number of delivery attempts before dead-lettering.
|
|
1285
|
+
* @minimum 1
|
|
1286
|
+
*/
|
|
1287
|
+
deliveryLimit: number;
|
|
1288
|
+
/**
|
|
1289
|
+
* If true, the queue is deleted when the last consumer unsubscribes.
|
|
1290
|
+
* @default false
|
|
1291
|
+
*/
|
|
1292
|
+
autoDelete?: boolean;
|
|
1293
|
+
/**
|
|
1294
|
+
* Additional AMQP arguments for advanced configuration.
|
|
1295
|
+
*/
|
|
1296
|
+
arguments?: Record<string, unknown>;
|
|
1297
|
+
};
|
|
1298
|
+
/**
|
|
1299
|
+
* Create a quorum queue with quorum-native retry.
|
|
1011
1300
|
*
|
|
1012
|
-
*
|
|
1013
|
-
*
|
|
1014
|
-
*
|
|
1015
|
-
*
|
|
1016
|
-
*
|
|
1017
|
-
*
|
|
1301
|
+
* This is a simplified helper that enforces best practices:
|
|
1302
|
+
* - Uses quorum queues (recommended for most use cases)
|
|
1303
|
+
* - Requires dead letter exchange for failed message handling
|
|
1304
|
+
* - Uses quorum-native retry mode (simpler than TTL-backoff)
|
|
1305
|
+
*
|
|
1306
|
+
* **When to use:**
|
|
1307
|
+
* - You want simple, immediate retries without exponential backoff
|
|
1308
|
+
* - You don't need configurable delays between retries
|
|
1309
|
+
* - You want the simplest retry configuration
|
|
1310
|
+
*
|
|
1311
|
+
* @param name - The queue name
|
|
1312
|
+
* @param options - Configuration options
|
|
1313
|
+
* @returns A quorum queue definition with quorum-native retry
|
|
1018
1314
|
*
|
|
1019
1315
|
* @example
|
|
1020
1316
|
* ```typescript
|
|
1021
|
-
*
|
|
1317
|
+
* const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
|
|
1022
1318
|
*
|
|
1023
|
-
* const
|
|
1024
|
-
*
|
|
1025
|
-
*
|
|
1026
|
-
*
|
|
1027
|
-
*
|
|
1028
|
-
*
|
|
1029
|
-
*
|
|
1030
|
-
*
|
|
1031
|
-
*
|
|
1032
|
-
*
|
|
1033
|
-
* {
|
|
1034
|
-
* summary: 'Order created event',
|
|
1035
|
-
* description: 'Emitted when a new order is created in the system'
|
|
1036
|
-
* }
|
|
1037
|
-
* );
|
|
1319
|
+
* const orderQueue = defineQuorumQueue('order-processing', {
|
|
1320
|
+
* deadLetterExchange: dlx,
|
|
1321
|
+
* deliveryLimit: 3, // Retry up to 3 times
|
|
1322
|
+
* });
|
|
1323
|
+
*
|
|
1324
|
+
* const contract = defineContract({
|
|
1325
|
+
* exchanges: { dlx },
|
|
1326
|
+
* queues: { orderProcessing: orderQueue },
|
|
1327
|
+
* // ...
|
|
1328
|
+
* });
|
|
1038
1329
|
* ```
|
|
1330
|
+
*
|
|
1331
|
+
* @see defineQueue - For full queue configuration options
|
|
1332
|
+
* @see defineTtlBackoffQueue - For queues with exponential backoff retry
|
|
1039
1333
|
*/
|
|
1040
|
-
declare function
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1334
|
+
declare function defineQuorumQueue(name: string, options: DefineQuorumQueueOptions): QuorumQueueDefinition;
|
|
1335
|
+
/**
|
|
1336
|
+
* Options for creating a queue with TTL-backoff retry.
|
|
1337
|
+
*
|
|
1338
|
+
* This simplified helper enforces the required configuration for TTL-backoff retry:
|
|
1339
|
+
* - Dead letter exchange is required (used for retry routing)
|
|
1340
|
+
* - Returns infrastructure that includes wait queue and bindings
|
|
1341
|
+
*/
|
|
1342
|
+
type DefineTtlBackoffQueueOptions = {
|
|
1343
|
+
/**
|
|
1344
|
+
* Dead letter exchange - required for TTL-backoff retry.
|
|
1345
|
+
* Used for routing messages to the wait queue and back.
|
|
1346
|
+
*/
|
|
1347
|
+
deadLetterExchange: ExchangeDefinition;
|
|
1348
|
+
/**
|
|
1349
|
+
* Optional routing key for dead-lettered messages.
|
|
1350
|
+
*/
|
|
1351
|
+
deadLetterRoutingKey?: string;
|
|
1352
|
+
/**
|
|
1353
|
+
* Maximum retry attempts before sending to DLQ.
|
|
1354
|
+
* @default 3
|
|
1355
|
+
*/
|
|
1356
|
+
maxRetries?: number;
|
|
1357
|
+
/**
|
|
1358
|
+
* Initial delay in ms before first retry.
|
|
1359
|
+
* @default 1000
|
|
1360
|
+
*/
|
|
1361
|
+
initialDelayMs?: number;
|
|
1362
|
+
/**
|
|
1363
|
+
* Maximum delay in ms between retries.
|
|
1364
|
+
* @default 30000
|
|
1365
|
+
*/
|
|
1366
|
+
maxDelayMs?: number;
|
|
1367
|
+
/**
|
|
1368
|
+
* Exponential backoff multiplier.
|
|
1369
|
+
* @default 2
|
|
1370
|
+
*/
|
|
1371
|
+
backoffMultiplier?: number;
|
|
1372
|
+
/**
|
|
1373
|
+
* Add jitter to prevent thundering herd.
|
|
1374
|
+
* @default true
|
|
1375
|
+
*/
|
|
1376
|
+
jitter?: boolean;
|
|
1377
|
+
/**
|
|
1378
|
+
* If true, the queue is deleted when the last consumer unsubscribes.
|
|
1379
|
+
* @default false
|
|
1380
|
+
*/
|
|
1381
|
+
autoDelete?: boolean;
|
|
1382
|
+
/**
|
|
1383
|
+
* Additional AMQP arguments for advanced configuration.
|
|
1384
|
+
*/
|
|
1385
|
+
arguments?: Record<string, unknown>;
|
|
1386
|
+
};
|
|
1387
|
+
/**
|
|
1388
|
+
* Create a queue with TTL-backoff retry (exponential backoff).
|
|
1389
|
+
*
|
|
1390
|
+
* This is a simplified helper that enforces best practices:
|
|
1391
|
+
* - Uses quorum queues (recommended for most use cases)
|
|
1392
|
+
* - Requires dead letter exchange for retry routing
|
|
1393
|
+
* - Uses TTL-backoff retry mode with configurable delays
|
|
1394
|
+
* - Automatically generates wait queue and bindings
|
|
1395
|
+
*
|
|
1396
|
+
* **When to use:**
|
|
1397
|
+
* - You need exponential backoff between retries
|
|
1398
|
+
* - You want configurable delays (initial delay, max delay, jitter)
|
|
1399
|
+
* - You're processing messages that may need time before retry
|
|
1400
|
+
*
|
|
1401
|
+
* **Returns:** A `QueueWithTtlBackoffInfrastructure` object that includes the
|
|
1402
|
+
* main queue, wait queue, and bindings. Pass this directly to `defineContract`
|
|
1403
|
+
* and it will be expanded automatically.
|
|
1404
|
+
*
|
|
1405
|
+
* @param name - The queue name
|
|
1406
|
+
* @param options - Configuration options
|
|
1407
|
+
* @returns A queue with TTL-backoff infrastructure
|
|
1408
|
+
*
|
|
1409
|
+
* @example
|
|
1410
|
+
* ```typescript
|
|
1411
|
+
* const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
|
|
1412
|
+
*
|
|
1413
|
+
* const orderQueue = defineTtlBackoffQueue('order-processing', {
|
|
1414
|
+
* deadLetterExchange: dlx,
|
|
1415
|
+
* maxRetries: 5,
|
|
1416
|
+
* initialDelayMs: 1000, // Start with 1s delay
|
|
1417
|
+
* maxDelayMs: 30000, // Cap at 30s
|
|
1418
|
+
* });
|
|
1419
|
+
*
|
|
1420
|
+
* const contract = defineContract({
|
|
1421
|
+
* exchanges: { dlx },
|
|
1422
|
+
* queues: { orderProcessing: orderQueue }, // Wait queue auto-added
|
|
1423
|
+
* // ... bindings auto-generated
|
|
1424
|
+
* });
|
|
1425
|
+
*
|
|
1426
|
+
* // To access the underlying queue definition (e.g., for the queue name):
|
|
1427
|
+
* import { extractQueue } from '@amqp-contract/contract';
|
|
1428
|
+
* const queueName = extractQueue(orderQueue).name;
|
|
1429
|
+
* ```
|
|
1430
|
+
*
|
|
1431
|
+
* @see defineQueue - For full queue configuration options
|
|
1432
|
+
* @see defineQuorumQueue - For queues with quorum-native retry (simpler, immediate retries)
|
|
1433
|
+
* @see extractQueue - To access the underlying queue definition
|
|
1434
|
+
*/
|
|
1435
|
+
declare function defineTtlBackoffQueue(name: string, options: DefineTtlBackoffQueueOptions): QueueWithTtlBackoffInfrastructure;
|
|
1436
|
+
//#endregion
|
|
1437
|
+
//#region src/builder/binding.d.ts
|
|
1045
1438
|
/**
|
|
1046
1439
|
* Define a binding between a queue and a fanout exchange.
|
|
1047
1440
|
*
|
|
@@ -1161,6 +1554,8 @@ declare function defineExchangeBinding(destination: ExchangeDefinition, source:
|
|
|
1161
1554
|
}>, "type" | "source" | "destination">): Extract<ExchangeBindingDefinition, {
|
|
1162
1555
|
source: DirectExchangeDefinition | TopicExchangeDefinition;
|
|
1163
1556
|
}>;
|
|
1557
|
+
//#endregion
|
|
1558
|
+
//#region src/builder/publisher.d.ts
|
|
1164
1559
|
/**
|
|
1165
1560
|
* Define a message publisher for a fanout exchange.
|
|
1166
1561
|
*
|
|
@@ -1169,6 +1564,19 @@ declare function defineExchangeBinding(destination: ExchangeDefinition, source:
|
|
|
1169
1564
|
*
|
|
1170
1565
|
* The message schema is validated when publishing to ensure type safety.
|
|
1171
1566
|
*
|
|
1567
|
+
* **Which pattern to use:**
|
|
1568
|
+
*
|
|
1569
|
+
* | Pattern | Best for | Description |
|
|
1570
|
+
* |---------|----------|-------------|
|
|
1571
|
+
* | `definePublisher` + `defineConsumer` | Independent definition | Define publishers and consumers separately with manual schema consistency |
|
|
1572
|
+
* | `defineEventPublisher` + `defineEventConsumer` | Event broadcasting | Define event publisher first, create consumers that subscribe to it |
|
|
1573
|
+
* | `defineCommandConsumer` + `defineCommandPublisher` | Task queues | Define command consumer first, create publishers that send commands to it |
|
|
1574
|
+
*
|
|
1575
|
+
* Use `defineEventPublisher` when:
|
|
1576
|
+
* - One publisher feeds multiple consumers
|
|
1577
|
+
* - You want automatic schema consistency between publisher and consumers
|
|
1578
|
+
* - You're building event-driven architectures
|
|
1579
|
+
*
|
|
1172
1580
|
* @param exchange - The fanout exchange definition to publish to
|
|
1173
1581
|
* @param message - The message definition with payload schema
|
|
1174
1582
|
* @param options - Optional publisher configuration
|
|
@@ -1189,6 +1597,9 @@ declare function defineExchangeBinding(destination: ExchangeDefinition, source:
|
|
|
1189
1597
|
*
|
|
1190
1598
|
* const logPublisher = definePublisher(logsExchange, logMessage);
|
|
1191
1599
|
* ```
|
|
1600
|
+
*
|
|
1601
|
+
* @see defineEventPublisher - For event-driven patterns with automatic schema consistency
|
|
1602
|
+
* @see defineCommandConsumer - For task queue patterns with automatic schema consistency
|
|
1192
1603
|
*/
|
|
1193
1604
|
declare function definePublisher<TMessage extends MessageDefinition>(exchange: FanoutExchangeDefinition, message: TMessage, options?: Omit<Extract<PublisherDefinition<TMessage>, {
|
|
1194
1605
|
exchange: FanoutExchangeDefinition;
|
|
@@ -1203,6 +1614,19 @@ declare function definePublisher<TMessage extends MessageDefinition>(exchange: F
|
|
|
1203
1614
|
*
|
|
1204
1615
|
* The message schema is validated when publishing to ensure type safety.
|
|
1205
1616
|
*
|
|
1617
|
+
* **Which pattern to use:**
|
|
1618
|
+
*
|
|
1619
|
+
* | Pattern | Best for | Description |
|
|
1620
|
+
* |---------|----------|-------------|
|
|
1621
|
+
* | `definePublisher` + `defineConsumer` | Independent definition | Define publishers and consumers separately with manual schema consistency |
|
|
1622
|
+
* | `defineEventPublisher` + `defineEventConsumer` | Event broadcasting | Define event publisher first, create consumers that subscribe to it |
|
|
1623
|
+
* | `defineCommandConsumer` + `defineCommandPublisher` | Task queues | Define command consumer first, create publishers that send commands to it |
|
|
1624
|
+
*
|
|
1625
|
+
* Use `defineEventPublisher` when:
|
|
1626
|
+
* - One publisher feeds multiple consumers
|
|
1627
|
+
* - You want automatic schema consistency between publisher and consumers
|
|
1628
|
+
* - You're building event-driven architectures
|
|
1629
|
+
*
|
|
1206
1630
|
* @param exchange - The direct or topic exchange definition to publish to
|
|
1207
1631
|
* @param message - The message definition with payload schema
|
|
1208
1632
|
* @param options - Publisher configuration (routingKey is required)
|
|
@@ -1229,12 +1653,17 @@ declare function definePublisher<TMessage extends MessageDefinition>(exchange: F
|
|
|
1229
1653
|
* routingKey: 'order.created'
|
|
1230
1654
|
* });
|
|
1231
1655
|
* ```
|
|
1656
|
+
*
|
|
1657
|
+
* @see defineEventPublisher - For event-driven patterns with automatic schema consistency
|
|
1658
|
+
* @see defineCommandConsumer - For task queue patterns with automatic schema consistency
|
|
1232
1659
|
*/
|
|
1233
1660
|
declare function definePublisher<TMessage extends MessageDefinition>(exchange: DirectExchangeDefinition | TopicExchangeDefinition, message: TMessage, options: Omit<Extract<PublisherDefinition<TMessage>, {
|
|
1234
1661
|
exchange: DirectExchangeDefinition | TopicExchangeDefinition;
|
|
1235
1662
|
}>, "exchange" | "message">): Extract<PublisherDefinition<TMessage>, {
|
|
1236
1663
|
exchange: DirectExchangeDefinition | TopicExchangeDefinition;
|
|
1237
1664
|
}>;
|
|
1665
|
+
//#endregion
|
|
1666
|
+
//#region src/builder/consumer.d.ts
|
|
1238
1667
|
/**
|
|
1239
1668
|
* Define a message consumer.
|
|
1240
1669
|
*
|
|
@@ -1244,6 +1673,19 @@ declare function definePublisher<TMessage extends MessageDefinition>(exchange: D
|
|
|
1244
1673
|
* Consumers are associated with a specific queue and message type. When you create a worker
|
|
1245
1674
|
* with this consumer, it will process messages from the queue according to the schema.
|
|
1246
1675
|
*
|
|
1676
|
+
* **Which pattern to use:**
|
|
1677
|
+
*
|
|
1678
|
+
* | Pattern | Best for | Description |
|
|
1679
|
+
* |---------|----------|-------------|
|
|
1680
|
+
* | `definePublisher` + `defineConsumer` | Independent definition | Define publishers and consumers separately with manual schema consistency |
|
|
1681
|
+
* | `defineEventPublisher` + `defineEventConsumer` | Event broadcasting | Define event publisher first, create consumers that subscribe to it |
|
|
1682
|
+
* | `defineCommandConsumer` + `defineCommandPublisher` | Task queues | Define command consumer first, create publishers that send commands to it |
|
|
1683
|
+
*
|
|
1684
|
+
* Use `defineCommandConsumer` when:
|
|
1685
|
+
* - One consumer receives from multiple publishers
|
|
1686
|
+
* - You want automatic schema consistency between consumer and publishers
|
|
1687
|
+
* - You're building task queue or command patterns
|
|
1688
|
+
*
|
|
1247
1689
|
* @param queue - The queue definition to consume from
|
|
1248
1690
|
* @param message - The message definition with payload schema
|
|
1249
1691
|
* @param options - Optional consumer configuration
|
|
@@ -1276,8 +1718,19 @@ declare function definePublisher<TMessage extends MessageDefinition>(exchange: D
|
|
|
1276
1718
|
* // connection
|
|
1277
1719
|
* // });
|
|
1278
1720
|
* ```
|
|
1721
|
+
*
|
|
1722
|
+
* @see defineCommandConsumer - For task queue patterns with automatic schema consistency
|
|
1723
|
+
* @see defineEventPublisher - For event-driven patterns with automatic schema consistency
|
|
1279
1724
|
*/
|
|
1280
1725
|
declare function defineConsumer<TMessage extends MessageDefinition>(queue: QueueEntry, message: TMessage, options?: Omit<ConsumerDefinition<TMessage>, "queue" | "message">): ConsumerDefinition<TMessage>;
|
|
1726
|
+
//#endregion
|
|
1727
|
+
//#region src/builder/contract.d.ts
|
|
1728
|
+
/**
|
|
1729
|
+
* Type utility to produce the output contract type from the input.
|
|
1730
|
+
* The output has the same structure but with all entries normalized to
|
|
1731
|
+
* their base definition types (PublisherDefinition, ConsumerDefinition).
|
|
1732
|
+
*/
|
|
1733
|
+
type ContractOutput<TContract extends ContractDefinitionInput> = TContract;
|
|
1281
1734
|
/**
|
|
1282
1735
|
* Define an AMQP contract.
|
|
1283
1736
|
*
|
|
@@ -1347,50 +1800,9 @@ declare function defineConsumer<TMessage extends MessageDefinition>(queue: Queue
|
|
|
1347
1800
|
* // - handler: async (message: { orderId: string, amount: number }) => void
|
|
1348
1801
|
* ```
|
|
1349
1802
|
*/
|
|
1350
|
-
declare function defineContract<TContract extends
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
* If the entry is a QueueWithTtlBackoffInfrastructure, returns the inner queue.
|
|
1354
|
-
* Otherwise, returns the entry as-is.
|
|
1355
|
-
*
|
|
1356
|
-
* @param entry - The queue entry (either plain QueueDefinition or QueueWithTtlBackoffInfrastructure)
|
|
1357
|
-
* @returns The plain QueueDefinition
|
|
1358
|
-
*
|
|
1359
|
-
* @example
|
|
1360
|
-
* ```typescript
|
|
1361
|
-
* const queue = defineQueue('orders', { retry: { mode: 'ttl-backoff' }, deadLetter: { exchange: dlx } });
|
|
1362
|
-
* const plainQueue = extractQueue(queue); // Returns the inner QueueDefinition
|
|
1363
|
-
* ```
|
|
1364
|
-
*/
|
|
1365
|
-
declare function extractQueue(entry: QueueEntry): QueueDefinition;
|
|
1366
|
-
/**
|
|
1367
|
-
* Publisher-first builder result for fanout and direct exchanges.
|
|
1368
|
-
*
|
|
1369
|
-
* This type represents a publisher and provides a method to create
|
|
1370
|
-
* a consumer that uses the same message schema with a binding to the exchange.
|
|
1371
|
-
*
|
|
1372
|
-
* This pattern is suitable for event-oriented messaging where publishers
|
|
1373
|
-
* emit events without knowing which queues will consume them.
|
|
1374
|
-
*
|
|
1375
|
-
* @template TMessage - The message definition
|
|
1376
|
-
* @template TPublisher - The publisher definition
|
|
1377
|
-
*/
|
|
1378
|
-
type PublisherFirstResult<TMessage extends MessageDefinition, TPublisher extends PublisherDefinition<TMessage>> = {
|
|
1379
|
-
/** The publisher definition */
|
|
1380
|
-
publisher: TPublisher;
|
|
1381
|
-
/**
|
|
1382
|
-
* Create a consumer that receives messages from this publisher.
|
|
1383
|
-
* The consumer will automatically use the same message schema and
|
|
1384
|
-
* a binding will be created with the same routing key.
|
|
1385
|
-
*
|
|
1386
|
-
* @param queue - The queue (or queue with infrastructure) that will consume the messages
|
|
1387
|
-
* @returns An object with the consumer definition and binding
|
|
1388
|
-
*/
|
|
1389
|
-
createConsumer: (queue: QueueEntry) => {
|
|
1390
|
-
consumer: ConsumerDefinition<TMessage>;
|
|
1391
|
-
binding: QueueBindingDefinition;
|
|
1392
|
-
};
|
|
1393
|
-
};
|
|
1803
|
+
declare function defineContract<TContract extends ContractDefinitionInput>(definition: TContract): ContractOutput<TContract>;
|
|
1804
|
+
//#endregion
|
|
1805
|
+
//#region src/builder/routing-types.d.ts
|
|
1394
1806
|
/**
|
|
1395
1807
|
* Type-safe routing key that validates basic format.
|
|
1396
1808
|
*
|
|
@@ -1467,429 +1879,399 @@ type MatchesPattern<Key extends string, Pattern extends string> = Pattern extend
|
|
|
1467
1879
|
* @template Key - The routing key to validate
|
|
1468
1880
|
*/
|
|
1469
1881
|
type MatchingRoutingKey<Pattern extends string, Key extends string> = RoutingKey<Key> extends never ? never : BindingPattern<Pattern> extends never ? never : MatchesPattern<Key, Pattern> extends true ? Key : never;
|
|
1882
|
+
//#endregion
|
|
1883
|
+
//#region src/builder/event.d.ts
|
|
1470
1884
|
/**
|
|
1471
|
-
*
|
|
1885
|
+
* Configuration for an event publisher.
|
|
1472
1886
|
*
|
|
1473
|
-
*
|
|
1474
|
-
*
|
|
1887
|
+
* Events are published without knowing who consumes them. Multiple consumers
|
|
1888
|
+
* can subscribe to the same event. This follows the pub/sub pattern where
|
|
1889
|
+
* publishers broadcast events and consumers subscribe to receive them.
|
|
1475
1890
|
*
|
|
1476
1891
|
* @template TMessage - The message definition
|
|
1477
|
-
* @template
|
|
1478
|
-
* @template TRoutingKey - The
|
|
1892
|
+
* @template TExchange - The exchange definition
|
|
1893
|
+
* @template TRoutingKey - The routing key type (undefined for fanout)
|
|
1479
1894
|
*/
|
|
1480
|
-
type
|
|
1481
|
-
/**
|
|
1482
|
-
|
|
1483
|
-
/**
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
createConsumer: <TConsumerRoutingKey extends string = TRoutingKey>(queue: QueueEntry, routingKey?: BindingPattern<TConsumerRoutingKey>) => {
|
|
1492
|
-
consumer: ConsumerDefinition<TMessage>;
|
|
1493
|
-
binding: QueueBindingDefinition;
|
|
1494
|
-
};
|
|
1895
|
+
type EventPublisherConfig<TMessage extends MessageDefinition, TExchange extends ExchangeDefinition, TRoutingKey extends string | undefined = undefined> = {
|
|
1896
|
+
/** Discriminator to identify this as an event publisher config */
|
|
1897
|
+
__brand: "EventPublisherConfig";
|
|
1898
|
+
/** The exchange to publish to */
|
|
1899
|
+
exchange: TExchange;
|
|
1900
|
+
/** The message definition */
|
|
1901
|
+
message: TMessage;
|
|
1902
|
+
/** The routing key for direct/topic exchanges */
|
|
1903
|
+
routingKey: TRoutingKey;
|
|
1904
|
+
/** Additional AMQP arguments */
|
|
1905
|
+
arguments?: Record<string, unknown>;
|
|
1495
1906
|
};
|
|
1496
1907
|
/**
|
|
1497
|
-
*
|
|
1908
|
+
* Result from defineEventConsumer.
|
|
1498
1909
|
*
|
|
1499
|
-
*
|
|
1500
|
-
*
|
|
1501
|
-
*
|
|
1910
|
+
* Contains the consumer definition and binding needed to subscribe to an event.
|
|
1911
|
+
* Can be used directly in defineContract's consumers section - the binding
|
|
1912
|
+
* will be automatically extracted.
|
|
1913
|
+
*
|
|
1914
|
+
* @template TMessage - The message definition
|
|
1915
|
+
*/
|
|
1916
|
+
type EventConsumerResult<TMessage extends MessageDefinition> = {
|
|
1917
|
+
/** Discriminator to identify this as an event consumer result */
|
|
1918
|
+
__brand: "EventConsumerResult";
|
|
1919
|
+
/** The consumer definition for processing messages */
|
|
1920
|
+
consumer: ConsumerDefinition<TMessage>;
|
|
1921
|
+
/** The binding connecting the queue to the exchange */
|
|
1922
|
+
binding: QueueBindingDefinition;
|
|
1923
|
+
};
|
|
1924
|
+
/**
|
|
1925
|
+
* Define an event publisher for broadcasting messages via fanout exchange.
|
|
1502
1926
|
*
|
|
1503
|
-
*
|
|
1504
|
-
*
|
|
1927
|
+
* Events are published without knowing who consumes them. Multiple consumers
|
|
1928
|
+
* can subscribe to the same event using `defineEventConsumer`.
|
|
1505
1929
|
*
|
|
1506
|
-
* @param exchange - The exchange to publish to
|
|
1930
|
+
* @param exchange - The fanout exchange to publish to
|
|
1507
1931
|
* @param message - The message definition (schema and metadata)
|
|
1508
|
-
* @
|
|
1509
|
-
* @returns A publisher-first result with publisher and consumer factory
|
|
1932
|
+
* @returns An event publisher configuration
|
|
1510
1933
|
*
|
|
1511
1934
|
* @example
|
|
1512
1935
|
* ```typescript
|
|
1513
|
-
* import { z } from 'zod';
|
|
1514
|
-
*
|
|
1515
1936
|
* const logsExchange = defineExchange('logs', 'fanout', { durable: true });
|
|
1516
|
-
* const logMessage = defineMessage(
|
|
1517
|
-
* z.
|
|
1518
|
-
*
|
|
1519
|
-
*
|
|
1520
|
-
*
|
|
1521
|
-
*
|
|
1522
|
-
*
|
|
1523
|
-
*
|
|
1524
|
-
*
|
|
1525
|
-
*
|
|
1526
|
-
*
|
|
1527
|
-
* const
|
|
1528
|
-
*
|
|
1529
|
-
*
|
|
1530
|
-
* // Use in contract
|
|
1531
|
-
* const { consumer: consumer1, binding: binding1 } = createLogConsumer(logsQueue1);
|
|
1532
|
-
* const { consumer: consumer2, binding: binding2 } = createLogConsumer(logsQueue2);
|
|
1533
|
-
*
|
|
1534
|
-
* const contract = defineContract({
|
|
1535
|
-
* exchanges: { logs: logsExchange },
|
|
1536
|
-
* queues: { logsQueue1, logsQueue2 },
|
|
1537
|
-
* bindings: {
|
|
1538
|
-
* logBinding1: binding1,
|
|
1539
|
-
* logBinding2: binding2,
|
|
1540
|
-
* },
|
|
1541
|
-
* publishers: { publishLog },
|
|
1542
|
-
* consumers: {
|
|
1543
|
-
* consumeLog1: consumer1,
|
|
1544
|
-
* consumeLog2: consumer2,
|
|
1545
|
-
* },
|
|
1546
|
-
* });
|
|
1937
|
+
* const logMessage = defineMessage(z.object({
|
|
1938
|
+
* level: z.enum(['info', 'warn', 'error']),
|
|
1939
|
+
* message: z.string(),
|
|
1940
|
+
* }));
|
|
1941
|
+
*
|
|
1942
|
+
* // Create event publisher
|
|
1943
|
+
* const logEvent = defineEventPublisher(logsExchange, logMessage);
|
|
1944
|
+
*
|
|
1945
|
+
* // Multiple consumers can subscribe
|
|
1946
|
+
* const { consumer: fileConsumer, binding: fileBinding } =
|
|
1947
|
+
* defineEventConsumer(logEvent, fileLogsQueue);
|
|
1948
|
+
* const { consumer: alertConsumer, binding: alertBinding } =
|
|
1949
|
+
* defineEventConsumer(logEvent, alertsQueue);
|
|
1547
1950
|
* ```
|
|
1548
1951
|
*/
|
|
1549
|
-
declare function
|
|
1550
|
-
exchange: FanoutExchangeDefinition;
|
|
1551
|
-
}>, "type" | "queue" | "exchange" | "routingKey">): PublisherFirstResult<TMessage, Extract<PublisherDefinition<TMessage>, {
|
|
1552
|
-
exchange: FanoutExchangeDefinition;
|
|
1553
|
-
}>>;
|
|
1952
|
+
declare function defineEventPublisher<TMessage extends MessageDefinition>(exchange: FanoutExchangeDefinition, message: TMessage): EventPublisherConfig<TMessage, FanoutExchangeDefinition, undefined>;
|
|
1554
1953
|
/**
|
|
1555
|
-
* Define
|
|
1556
|
-
*
|
|
1557
|
-
* This builder enforces consistency by:
|
|
1558
|
-
* 1. Ensuring the publisher and consumer use the same message schema
|
|
1559
|
-
* 2. Linking the routing key from the publisher to the binding
|
|
1954
|
+
* Define an event publisher for broadcasting messages via direct exchange.
|
|
1560
1955
|
*
|
|
1561
|
-
*
|
|
1562
|
-
*
|
|
1956
|
+
* Events are published with a specific routing key. Consumers will receive
|
|
1957
|
+
* messages that match the routing key exactly.
|
|
1563
1958
|
*
|
|
1564
|
-
* @param exchange - The exchange to publish to
|
|
1959
|
+
* @param exchange - The direct exchange to publish to
|
|
1565
1960
|
* @param message - The message definition (schema and metadata)
|
|
1566
|
-
* @param options -
|
|
1961
|
+
* @param options - Configuration with required routing key
|
|
1567
1962
|
* @param options.routingKey - The routing key for message routing
|
|
1568
|
-
* @
|
|
1963
|
+
* @param options.arguments - Additional AMQP arguments
|
|
1964
|
+
* @returns An event publisher configuration
|
|
1569
1965
|
*
|
|
1570
1966
|
* @example
|
|
1571
1967
|
* ```typescript
|
|
1572
|
-
* import { z } from 'zod';
|
|
1573
|
-
*
|
|
1574
1968
|
* const tasksExchange = defineExchange('tasks', 'direct', { durable: true });
|
|
1575
|
-
* const taskMessage = defineMessage(
|
|
1576
|
-
* z.object({
|
|
1577
|
-
* taskId: z.string(),
|
|
1578
|
-
* payload: z.record(z.unknown()),
|
|
1579
|
-
* })
|
|
1580
|
-
* );
|
|
1581
|
-
*
|
|
1582
|
-
* // Create publisher-first relationship with routing key
|
|
1583
|
-
* const { publisher: executeTaskPublisher, createConsumer: createTaskConsumer } = definePublisherFirst(
|
|
1584
|
-
* tasksExchange,
|
|
1585
|
-
* taskMessage,
|
|
1586
|
-
* { routingKey: 'task.execute' }
|
|
1587
|
-
* );
|
|
1588
|
-
*
|
|
1589
|
-
* // Use in contract - routing key is consistent across publisher and bindings
|
|
1590
|
-
* const taskQueue = defineQueue('task-queue', { durable: true });
|
|
1591
|
-
* const { consumer, binding } = createTaskConsumer(taskQueue);
|
|
1969
|
+
* const taskMessage = defineMessage(z.object({ taskId: z.string() }));
|
|
1592
1970
|
*
|
|
1593
|
-
* const
|
|
1594
|
-
*
|
|
1595
|
-
* queues: { taskQueue },
|
|
1596
|
-
* bindings: { taskBinding: binding },
|
|
1597
|
-
* publishers: { executeTask: executeTaskPublisher },
|
|
1598
|
-
* consumers: { processTask: consumer },
|
|
1971
|
+
* const taskEvent = defineEventPublisher(tasksExchange, taskMessage, {
|
|
1972
|
+
* routingKey: 'task.execute',
|
|
1599
1973
|
* });
|
|
1600
1974
|
* ```
|
|
1601
1975
|
*/
|
|
1602
|
-
declare function
|
|
1976
|
+
declare function defineEventPublisher<TMessage extends MessageDefinition, TRoutingKey extends string>(exchange: DirectExchangeDefinition, message: TMessage, options: {
|
|
1603
1977
|
routingKey: RoutingKey<TRoutingKey>;
|
|
1604
1978
|
arguments?: Record<string, unknown>;
|
|
1605
|
-
}):
|
|
1606
|
-
exchange: DirectExchangeDefinition | TopicExchangeDefinition;
|
|
1607
|
-
}>>;
|
|
1979
|
+
}): EventPublisherConfig<TMessage, DirectExchangeDefinition, TRoutingKey>;
|
|
1608
1980
|
/**
|
|
1609
|
-
* Define
|
|
1981
|
+
* Define an event publisher for broadcasting messages via topic exchange.
|
|
1610
1982
|
*
|
|
1611
|
-
*
|
|
1612
|
-
*
|
|
1613
|
-
* 2. The publisher uses a concrete routing key (e.g., 'order.created')
|
|
1614
|
-
* 3. Consumers can optionally specify routing key patterns (e.g., 'order.*') or use the default
|
|
1983
|
+
* Events are published with a concrete routing key. Consumers can subscribe
|
|
1984
|
+
* using patterns (with * and # wildcards) to receive matching messages.
|
|
1615
1985
|
*
|
|
1616
|
-
*
|
|
1617
|
-
* and consumers can subscribe with patterns. This is less common than the consumer-first pattern.
|
|
1618
|
-
*
|
|
1619
|
-
* @param exchange - The exchange to publish to (topic type)
|
|
1986
|
+
* @param exchange - The topic exchange to publish to
|
|
1620
1987
|
* @param message - The message definition (schema and metadata)
|
|
1621
|
-
* @param options -
|
|
1622
|
-
* @param options.routingKey - The concrete routing key
|
|
1623
|
-
* @
|
|
1988
|
+
* @param options - Configuration with required routing key
|
|
1989
|
+
* @param options.routingKey - The concrete routing key (no wildcards)
|
|
1990
|
+
* @param options.arguments - Additional AMQP arguments
|
|
1991
|
+
* @returns An event publisher configuration
|
|
1624
1992
|
*
|
|
1625
1993
|
* @example
|
|
1626
1994
|
* ```typescript
|
|
1627
|
-
* import { z } from 'zod';
|
|
1628
|
-
*
|
|
1629
1995
|
* const ordersExchange = defineExchange('orders', 'topic', { durable: true });
|
|
1630
|
-
* const orderMessage = defineMessage(
|
|
1631
|
-
* z.
|
|
1632
|
-
*
|
|
1633
|
-
*
|
|
1634
|
-
*
|
|
1635
|
-
*
|
|
1996
|
+
* const orderMessage = defineMessage(z.object({
|
|
1997
|
+
* orderId: z.string(),
|
|
1998
|
+
* amount: z.number(),
|
|
1999
|
+
* }));
|
|
2000
|
+
*
|
|
2001
|
+
* // Publisher uses concrete routing key
|
|
2002
|
+
* const orderCreatedEvent = defineEventPublisher(ordersExchange, orderMessage, {
|
|
2003
|
+
* routingKey: 'order.created',
|
|
2004
|
+
* });
|
|
1636
2005
|
*
|
|
1637
|
-
* //
|
|
1638
|
-
* const {
|
|
1639
|
-
*
|
|
1640
|
-
*
|
|
1641
|
-
* { routingKey: 'order
|
|
2006
|
+
* // Consumer can use pattern
|
|
2007
|
+
* const { consumer, binding } = defineEventConsumer(
|
|
2008
|
+
* orderCreatedEvent,
|
|
2009
|
+
* allOrdersQueue,
|
|
2010
|
+
* { routingKey: 'order.*' },
|
|
1642
2011
|
* );
|
|
2012
|
+
* ```
|
|
2013
|
+
*/
|
|
2014
|
+
declare function defineEventPublisher<TMessage extends MessageDefinition, TRoutingKey extends string>(exchange: TopicExchangeDefinition, message: TMessage, options: {
|
|
2015
|
+
routingKey: RoutingKey<TRoutingKey>;
|
|
2016
|
+
arguments?: Record<string, unknown>;
|
|
2017
|
+
}): EventPublisherConfig<TMessage, TopicExchangeDefinition, TRoutingKey>;
|
|
2018
|
+
/**
|
|
2019
|
+
* Create a consumer that subscribes to an event from a fanout exchange.
|
|
1643
2020
|
*
|
|
1644
|
-
*
|
|
1645
|
-
*
|
|
1646
|
-
*
|
|
2021
|
+
* @param eventPublisher - The event publisher configuration
|
|
2022
|
+
* @param queue - The queue that will receive messages
|
|
2023
|
+
* @param options - Optional binding configuration
|
|
2024
|
+
* @returns An object with the consumer definition and binding
|
|
1647
2025
|
*
|
|
1648
|
-
*
|
|
1649
|
-
*
|
|
1650
|
-
*
|
|
1651
|
-
* const { consumer
|
|
1652
|
-
*
|
|
2026
|
+
* @example
|
|
2027
|
+
* ```typescript
|
|
2028
|
+
* const logEvent = defineEventPublisher(logsExchange, logMessage);
|
|
2029
|
+
* const { consumer, binding } = defineEventConsumer(logEvent, logsQueue);
|
|
2030
|
+
* ```
|
|
2031
|
+
*/
|
|
2032
|
+
declare function defineEventConsumer<TMessage extends MessageDefinition>(eventPublisher: EventPublisherConfig<TMessage, FanoutExchangeDefinition, undefined>, queue: QueueEntry, options?: {
|
|
2033
|
+
arguments?: Record<string, unknown>;
|
|
2034
|
+
}): EventConsumerResult<TMessage>;
|
|
2035
|
+
/**
|
|
2036
|
+
* Create a consumer that subscribes to an event from a direct exchange.
|
|
1653
2037
|
*
|
|
1654
|
-
*
|
|
1655
|
-
*
|
|
1656
|
-
*
|
|
1657
|
-
*
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
*
|
|
1664
|
-
*
|
|
1665
|
-
*
|
|
2038
|
+
* @param eventPublisher - The event publisher configuration
|
|
2039
|
+
* @param queue - The queue that will receive messages
|
|
2040
|
+
* @param options - Optional binding configuration
|
|
2041
|
+
* @returns An object with the consumer definition and binding
|
|
2042
|
+
*/
|
|
2043
|
+
declare function defineEventConsumer<TMessage extends MessageDefinition, TRoutingKey extends string>(eventPublisher: EventPublisherConfig<TMessage, DirectExchangeDefinition, TRoutingKey>, queue: QueueEntry, options?: {
|
|
2044
|
+
arguments?: Record<string, unknown>;
|
|
2045
|
+
}): EventConsumerResult<TMessage>;
|
|
2046
|
+
/**
|
|
2047
|
+
* Create a consumer that subscribes to an event from a topic exchange.
|
|
2048
|
+
*
|
|
2049
|
+
* For topic exchanges, the consumer can optionally override the routing key
|
|
2050
|
+
* with a pattern to subscribe to multiple events.
|
|
2051
|
+
*
|
|
2052
|
+
* @param eventPublisher - The event publisher configuration
|
|
2053
|
+
* @param queue - The queue that will receive messages
|
|
2054
|
+
* @param options - Optional binding configuration
|
|
2055
|
+
* @param options.routingKey - Override routing key with pattern (defaults to publisher's key)
|
|
2056
|
+
* @returns An object with the consumer definition and binding
|
|
2057
|
+
*
|
|
2058
|
+
* @example
|
|
2059
|
+
* ```typescript
|
|
2060
|
+
* const orderCreatedEvent = defineEventPublisher(ordersExchange, orderMessage, {
|
|
2061
|
+
* routingKey: 'order.created',
|
|
2062
|
+
* });
|
|
2063
|
+
*
|
|
2064
|
+
* // Use exact routing key from publisher
|
|
2065
|
+
* const { consumer: exactConsumer } = defineEventConsumer(orderCreatedEvent, exactQueue);
|
|
2066
|
+
*
|
|
2067
|
+
* // Override with pattern to receive all order events
|
|
2068
|
+
* const { consumer: allConsumer } = defineEventConsumer(orderCreatedEvent, allQueue, {
|
|
2069
|
+
* routingKey: 'order.*',
|
|
1666
2070
|
* });
|
|
1667
2071
|
* ```
|
|
1668
2072
|
*/
|
|
1669
|
-
declare function
|
|
1670
|
-
routingKey
|
|
2073
|
+
declare function defineEventConsumer<TMessage extends MessageDefinition, TRoutingKey extends string, TConsumerRoutingKey extends string = TRoutingKey>(eventPublisher: EventPublisherConfig<TMessage, TopicExchangeDefinition, TRoutingKey>, queue: QueueEntry, options?: {
|
|
2074
|
+
routingKey?: BindingPattern<TConsumerRoutingKey>;
|
|
1671
2075
|
arguments?: Record<string, unknown>;
|
|
1672
|
-
}):
|
|
1673
|
-
exchange: DirectExchangeDefinition | TopicExchangeDefinition;
|
|
1674
|
-
}>, TRoutingKey>;
|
|
2076
|
+
}): EventConsumerResult<TMessage>;
|
|
1675
2077
|
/**
|
|
1676
|
-
*
|
|
2078
|
+
* Type guard to check if a value is an EventPublisherConfig.
|
|
1677
2079
|
*
|
|
1678
|
-
*
|
|
1679
|
-
*
|
|
2080
|
+
* @param value - The value to check
|
|
2081
|
+
* @returns True if the value is an EventPublisherConfig
|
|
2082
|
+
*/
|
|
2083
|
+
declare function isEventPublisherConfig(value: unknown): value is EventPublisherConfig<MessageDefinition, ExchangeDefinition, string | undefined>;
|
|
2084
|
+
/**
|
|
2085
|
+
* Type guard to check if a value is an EventConsumerResult.
|
|
1680
2086
|
*
|
|
1681
|
-
* @
|
|
1682
|
-
* @
|
|
1683
|
-
* @template TBinding - The queue binding definition
|
|
2087
|
+
* @param value - The value to check
|
|
2088
|
+
* @returns True if the value is an EventConsumerResult
|
|
1684
2089
|
*/
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
/** The binding definition connecting the exchange to the queue */
|
|
1689
|
-
binding: TBinding;
|
|
1690
|
-
/**
|
|
1691
|
-
* Create a publisher that sends messages to this consumer.
|
|
1692
|
-
* The publisher will automatically use the same message schema and routing key.
|
|
1693
|
-
*
|
|
1694
|
-
* @returns A publisher definition with the same message type and routing key
|
|
1695
|
-
*/
|
|
1696
|
-
createPublisher: () => TBinding["exchange"] extends FanoutExchangeDefinition ? Extract<PublisherDefinition<TMessage>, {
|
|
1697
|
-
exchange: FanoutExchangeDefinition;
|
|
1698
|
-
}> : Extract<PublisherDefinition<TMessage>, {
|
|
1699
|
-
exchange: DirectExchangeDefinition | TopicExchangeDefinition;
|
|
1700
|
-
}>;
|
|
1701
|
-
};
|
|
2090
|
+
declare function isEventConsumerResult(value: unknown): value is EventConsumerResult<MessageDefinition>;
|
|
2091
|
+
//#endregion
|
|
2092
|
+
//#region src/builder/command.d.ts
|
|
1702
2093
|
/**
|
|
1703
|
-
*
|
|
2094
|
+
* Configuration for a command consumer.
|
|
1704
2095
|
*
|
|
1705
|
-
*
|
|
1706
|
-
*
|
|
2096
|
+
* Commands are sent by one or more publishers to a single consumer (task queue pattern).
|
|
2097
|
+
* The consumer "owns" the queue, and publishers send commands to it.
|
|
1707
2098
|
*
|
|
1708
2099
|
* @template TMessage - The message definition
|
|
1709
|
-
* @template
|
|
1710
|
-
* @template
|
|
2100
|
+
* @template TExchange - The exchange definition
|
|
2101
|
+
* @template TRoutingKey - The routing key type (undefined for fanout)
|
|
1711
2102
|
*/
|
|
1712
|
-
type
|
|
1713
|
-
/**
|
|
1714
|
-
|
|
1715
|
-
/** The
|
|
1716
|
-
|
|
1717
|
-
/**
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
exchange: DirectExchangeDefinition | TopicExchangeDefinition;
|
|
1726
|
-
}>;
|
|
2103
|
+
type CommandConsumerConfig<TMessage extends MessageDefinition, TExchange extends ExchangeDefinition, TRoutingKey extends string | undefined = undefined> = {
|
|
2104
|
+
/** Discriminator to identify this as a command consumer config */
|
|
2105
|
+
__brand: "CommandConsumerConfig";
|
|
2106
|
+
/** The consumer definition for processing commands */
|
|
2107
|
+
consumer: ConsumerDefinition<TMessage>;
|
|
2108
|
+
/** The binding connecting the queue to the exchange */
|
|
2109
|
+
binding: QueueBindingDefinition;
|
|
2110
|
+
/** The exchange that receives commands */
|
|
2111
|
+
exchange: TExchange;
|
|
2112
|
+
/** The message definition */
|
|
2113
|
+
message: TMessage;
|
|
2114
|
+
/** The routing key pattern for the binding */
|
|
2115
|
+
routingKey: TRoutingKey;
|
|
1727
2116
|
};
|
|
1728
2117
|
/**
|
|
1729
|
-
* Define a consumer
|
|
2118
|
+
* Define a command consumer for receiving commands via fanout exchange.
|
|
1730
2119
|
*
|
|
1731
|
-
*
|
|
1732
|
-
*
|
|
1733
|
-
* 2. Linking the routing key from the binding to the publisher
|
|
1734
|
-
* 3. Creating a binding that connects the exchange to the queue
|
|
2120
|
+
* Commands are sent by publishers to a specific queue. The consumer "owns" the
|
|
2121
|
+
* queue and defines what commands it accepts.
|
|
1735
2122
|
*
|
|
1736
|
-
*
|
|
1737
|
-
*
|
|
1738
|
-
*
|
|
1739
|
-
* @param queue - The queue to consume from
|
|
1740
|
-
* @param exchange - The exchange that routes to the queue (fanout type)
|
|
2123
|
+
* @param queue - The queue that will receive commands
|
|
2124
|
+
* @param exchange - The fanout exchange that routes commands
|
|
1741
2125
|
* @param message - The message definition (schema and metadata)
|
|
1742
|
-
* @
|
|
1743
|
-
* @returns A consumer-first result with consumer, binding, and publisher factory
|
|
2126
|
+
* @returns A command consumer configuration
|
|
1744
2127
|
*
|
|
1745
2128
|
* @example
|
|
1746
2129
|
* ```typescript
|
|
1747
|
-
*
|
|
2130
|
+
* const tasksExchange = defineExchange('tasks', 'fanout', { durable: true });
|
|
2131
|
+
* const taskMessage = defineMessage(z.object({ taskId: z.string() }));
|
|
1748
2132
|
*
|
|
1749
|
-
*
|
|
1750
|
-
* const
|
|
1751
|
-
* const notificationMessage = defineMessage(
|
|
1752
|
-
* z.object({
|
|
1753
|
-
* userId: z.string(),
|
|
1754
|
-
* message: z.string(),
|
|
1755
|
-
* })
|
|
1756
|
-
* );
|
|
2133
|
+
* // Consumer owns the queue
|
|
2134
|
+
* const executeTask = defineCommandConsumer(taskQueue, tasksExchange, taskMessage);
|
|
1757
2135
|
*
|
|
1758
|
-
* //
|
|
1759
|
-
* const
|
|
1760
|
-
* notificationsQueue,
|
|
1761
|
-
* notificationsExchange,
|
|
1762
|
-
* notificationMessage
|
|
1763
|
-
* );
|
|
1764
|
-
*
|
|
1765
|
-
* // Use in contract
|
|
1766
|
-
* const contract = defineContract({
|
|
1767
|
-
* exchanges: { notifications: notificationsExchange },
|
|
1768
|
-
* queues: { notificationsQueue },
|
|
1769
|
-
* bindings: { notificationBinding },
|
|
1770
|
-
* publishers: { sendNotification: createNotificationPublisher() },
|
|
1771
|
-
* consumers: { processNotification: processNotificationConsumer },
|
|
1772
|
-
* });
|
|
2136
|
+
* // Publishers send commands to it
|
|
2137
|
+
* const sendTask = defineCommandPublisher(executeTask);
|
|
1773
2138
|
* ```
|
|
1774
2139
|
*/
|
|
1775
|
-
declare function
|
|
1776
|
-
exchange: FanoutExchangeDefinition;
|
|
1777
|
-
}>, "type" | "queue" | "exchange" | "routingKey">): ConsumerFirstResult<TMessage, ConsumerDefinition<TMessage>, Extract<QueueBindingDefinition, {
|
|
1778
|
-
exchange: FanoutExchangeDefinition;
|
|
1779
|
-
}>>;
|
|
2140
|
+
declare function defineCommandConsumer<TMessage extends MessageDefinition>(queue: QueueEntry, exchange: FanoutExchangeDefinition, message: TMessage): CommandConsumerConfig<TMessage, FanoutExchangeDefinition, undefined>;
|
|
1780
2141
|
/**
|
|
1781
|
-
* Define a consumer
|
|
1782
|
-
*
|
|
1783
|
-
* This builder enforces consistency by:
|
|
1784
|
-
* 1. Ensuring the consumer and publisher use the same message schema
|
|
1785
|
-
* 2. Linking the routing key from the binding to the publisher
|
|
1786
|
-
* 3. Creating a binding that connects the exchange to the queue
|
|
2142
|
+
* Define a command consumer for receiving commands via direct exchange.
|
|
1787
2143
|
*
|
|
1788
|
-
*
|
|
1789
|
-
*
|
|
2144
|
+
* Commands are sent by publishers with a specific routing key that matches
|
|
2145
|
+
* the binding pattern.
|
|
1790
2146
|
*
|
|
1791
|
-
* @param queue - The queue
|
|
1792
|
-
* @param exchange - The exchange that routes
|
|
2147
|
+
* @param queue - The queue that will receive commands
|
|
2148
|
+
* @param exchange - The direct exchange that routes commands
|
|
1793
2149
|
* @param message - The message definition (schema and metadata)
|
|
1794
|
-
* @param options -
|
|
1795
|
-
* @param options.routingKey - The routing key for
|
|
1796
|
-
* @
|
|
2150
|
+
* @param options - Configuration with required routing key
|
|
2151
|
+
* @param options.routingKey - The routing key for the binding
|
|
2152
|
+
* @param options.arguments - Additional AMQP arguments
|
|
2153
|
+
* @returns A command consumer configuration
|
|
1797
2154
|
*
|
|
1798
2155
|
* @example
|
|
1799
2156
|
* ```typescript
|
|
1800
|
-
* import { z } from 'zod';
|
|
1801
|
-
*
|
|
1802
|
-
* const taskQueue = defineQueue('tasks', { durable: true });
|
|
1803
2157
|
* const tasksExchange = defineExchange('tasks', 'direct', { durable: true });
|
|
1804
|
-
* const taskMessage = defineMessage(
|
|
1805
|
-
* z.object({
|
|
1806
|
-
* taskId: z.string(),
|
|
1807
|
-
* payload: z.record(z.unknown()),
|
|
1808
|
-
* })
|
|
1809
|
-
* );
|
|
2158
|
+
* const taskMessage = defineMessage(z.object({ taskId: z.string() }));
|
|
1810
2159
|
*
|
|
1811
|
-
*
|
|
1812
|
-
*
|
|
1813
|
-
* taskQueue,
|
|
1814
|
-
* tasksExchange,
|
|
1815
|
-
* taskMessage,
|
|
1816
|
-
* { routingKey: 'task.execute' }
|
|
1817
|
-
* );
|
|
1818
|
-
*
|
|
1819
|
-
* // Use in contract - routing key is consistent across consumer and publisher
|
|
1820
|
-
* const contract = defineContract({
|
|
1821
|
-
* exchanges: { tasks: tasksExchange },
|
|
1822
|
-
* queues: { taskQueue },
|
|
1823
|
-
* bindings: { taskBinding },
|
|
1824
|
-
* publishers: { executeTask: createTaskPublisher() },
|
|
1825
|
-
* consumers: { processTask: processTaskConsumer },
|
|
2160
|
+
* const executeTask = defineCommandConsumer(taskQueue, tasksExchange, taskMessage, {
|
|
2161
|
+
* routingKey: 'task.execute',
|
|
1826
2162
|
* });
|
|
2163
|
+
*
|
|
2164
|
+
* const sendTask = defineCommandPublisher(executeTask);
|
|
1827
2165
|
* ```
|
|
1828
2166
|
*/
|
|
1829
|
-
declare function
|
|
2167
|
+
declare function defineCommandConsumer<TMessage extends MessageDefinition, TRoutingKey extends string>(queue: QueueEntry, exchange: DirectExchangeDefinition, message: TMessage, options: {
|
|
1830
2168
|
routingKey: RoutingKey<TRoutingKey>;
|
|
1831
2169
|
arguments?: Record<string, unknown>;
|
|
1832
|
-
}):
|
|
1833
|
-
exchange: DirectExchangeDefinition;
|
|
1834
|
-
}>>;
|
|
2170
|
+
}): CommandConsumerConfig<TMessage, DirectExchangeDefinition, TRoutingKey>;
|
|
1835
2171
|
/**
|
|
1836
|
-
* Define a consumer
|
|
1837
|
-
*
|
|
1838
|
-
* This builder enforces consistency by:
|
|
1839
|
-
* 1. Ensuring the consumer and publisher use the same message schema
|
|
1840
|
-
* 2. The binding uses a routing key pattern (e.g., 'order.*')
|
|
1841
|
-
* 3. The publisher factory accepts a concrete routing key that matches the pattern (e.g., 'order.created')
|
|
2172
|
+
* Define a command consumer for receiving commands via topic exchange.
|
|
1842
2173
|
*
|
|
1843
|
-
*
|
|
1844
|
-
*
|
|
2174
|
+
* The consumer binds with a routing key pattern (can use * and # wildcards).
|
|
2175
|
+
* Publishers then send commands with concrete routing keys that match the pattern.
|
|
1845
2176
|
*
|
|
1846
|
-
* @param queue - The queue
|
|
1847
|
-
* @param exchange - The exchange that routes
|
|
2177
|
+
* @param queue - The queue that will receive commands
|
|
2178
|
+
* @param exchange - The topic exchange that routes commands
|
|
1848
2179
|
* @param message - The message definition (schema and metadata)
|
|
1849
|
-
* @param options -
|
|
1850
|
-
* @param options.routingKey - The routing key pattern for the binding
|
|
1851
|
-
* @
|
|
2180
|
+
* @param options - Configuration with required routing key pattern
|
|
2181
|
+
* @param options.routingKey - The routing key pattern for the binding
|
|
2182
|
+
* @param options.arguments - Additional AMQP arguments
|
|
2183
|
+
* @returns A command consumer configuration
|
|
1852
2184
|
*
|
|
1853
2185
|
* @example
|
|
1854
2186
|
* ```typescript
|
|
1855
|
-
* import { z } from 'zod';
|
|
1856
|
-
*
|
|
1857
|
-
* const orderQueue = defineQueue('order-processing', { durable: true });
|
|
1858
2187
|
* const ordersExchange = defineExchange('orders', 'topic', { durable: true });
|
|
1859
|
-
* const orderMessage = defineMessage(
|
|
1860
|
-
* z.object({
|
|
1861
|
-
* orderId: z.string(),
|
|
1862
|
-
* amount: z.number(),
|
|
1863
|
-
* })
|
|
1864
|
-
* );
|
|
2188
|
+
* const orderMessage = defineMessage(z.object({ orderId: z.string() }));
|
|
1865
2189
|
*
|
|
1866
|
-
* //
|
|
1867
|
-
* const
|
|
1868
|
-
*
|
|
1869
|
-
*
|
|
1870
|
-
* orderMessage,
|
|
1871
|
-
* { routingKey: 'order.*' } // Pattern in binding
|
|
1872
|
-
* );
|
|
2190
|
+
* // Consumer uses pattern to receive multiple command types
|
|
2191
|
+
* const processOrder = defineCommandConsumer(orderQueue, ordersExchange, orderMessage, {
|
|
2192
|
+
* routingKey: 'order.*',
|
|
2193
|
+
* });
|
|
1873
2194
|
*
|
|
1874
|
-
* //
|
|
1875
|
-
* const
|
|
1876
|
-
*
|
|
1877
|
-
*
|
|
1878
|
-
*
|
|
1879
|
-
*
|
|
1880
|
-
* orderCreated: createOrderPublisher('order.created'), // Concrete key
|
|
1881
|
-
* orderUpdated: createOrderPublisher('order.updated'), // Concrete key
|
|
1882
|
-
* },
|
|
1883
|
-
* consumers: { processOrder: processOrderConsumer },
|
|
2195
|
+
* // Publishers send with concrete keys
|
|
2196
|
+
* const createOrder = defineCommandPublisher(processOrder, {
|
|
2197
|
+
* routingKey: 'order.create',
|
|
2198
|
+
* });
|
|
2199
|
+
* const updateOrder = defineCommandPublisher(processOrder, {
|
|
2200
|
+
* routingKey: 'order.update',
|
|
1884
2201
|
* });
|
|
1885
2202
|
* ```
|
|
1886
2203
|
*/
|
|
1887
|
-
declare function
|
|
2204
|
+
declare function defineCommandConsumer<TMessage extends MessageDefinition, TRoutingKey extends string>(queue: QueueEntry, exchange: TopicExchangeDefinition, message: TMessage, options: {
|
|
1888
2205
|
routingKey: BindingPattern<TRoutingKey>;
|
|
1889
2206
|
arguments?: Record<string, unknown>;
|
|
1890
|
-
}):
|
|
2207
|
+
}): CommandConsumerConfig<TMessage, TopicExchangeDefinition, TRoutingKey>;
|
|
2208
|
+
/**
|
|
2209
|
+
* Create a publisher that sends commands to a fanout exchange consumer.
|
|
2210
|
+
*
|
|
2211
|
+
* @param commandConsumer - The command consumer configuration
|
|
2212
|
+
* @returns A publisher definition
|
|
2213
|
+
*
|
|
2214
|
+
* @example
|
|
2215
|
+
* ```typescript
|
|
2216
|
+
* const executeTask = defineCommandConsumer(taskQueue, fanoutExchange, taskMessage);
|
|
2217
|
+
* const sendTask = defineCommandPublisher(executeTask);
|
|
2218
|
+
* ```
|
|
2219
|
+
*/
|
|
2220
|
+
declare function defineCommandPublisher<TMessage extends MessageDefinition>(commandConsumer: CommandConsumerConfig<TMessage, FanoutExchangeDefinition, undefined>): {
|
|
2221
|
+
message: TMessage;
|
|
2222
|
+
exchange: FanoutExchangeDefinition;
|
|
2223
|
+
};
|
|
2224
|
+
/**
|
|
2225
|
+
* Create a publisher that sends commands to a direct exchange consumer.
|
|
2226
|
+
*
|
|
2227
|
+
* @param commandConsumer - The command consumer configuration
|
|
2228
|
+
* @returns A publisher definition
|
|
2229
|
+
*/
|
|
2230
|
+
declare function defineCommandPublisher<TMessage extends MessageDefinition, TRoutingKey extends string>(commandConsumer: CommandConsumerConfig<TMessage, DirectExchangeDefinition, TRoutingKey>): {
|
|
2231
|
+
message: TMessage;
|
|
2232
|
+
exchange: DirectExchangeDefinition;
|
|
2233
|
+
routingKey: string;
|
|
2234
|
+
};
|
|
2235
|
+
/**
|
|
2236
|
+
* Create a publisher that sends commands to a topic exchange consumer.
|
|
2237
|
+
*
|
|
2238
|
+
* For topic exchanges where the consumer uses a pattern, the publisher can
|
|
2239
|
+
* optionally specify a concrete routing key that matches the pattern.
|
|
2240
|
+
*
|
|
2241
|
+
* @param commandConsumer - The command consumer configuration
|
|
2242
|
+
* @param options - Optional publisher configuration
|
|
2243
|
+
* @param options.routingKey - Override routing key (must match consumer's pattern)
|
|
2244
|
+
* @returns A publisher definition
|
|
2245
|
+
*
|
|
2246
|
+
* @example
|
|
2247
|
+
* ```typescript
|
|
2248
|
+
* // Consumer binds with pattern
|
|
2249
|
+
* const processOrder = defineCommandConsumer(orderQueue, topicExchange, orderMessage, {
|
|
2250
|
+
* routingKey: 'order.*',
|
|
2251
|
+
* });
|
|
2252
|
+
*
|
|
2253
|
+
* // Publisher uses concrete key matching the pattern
|
|
2254
|
+
* const createOrder = defineCommandPublisher(processOrder, {
|
|
2255
|
+
* routingKey: 'order.create',
|
|
2256
|
+
* });
|
|
2257
|
+
* ```
|
|
2258
|
+
*/
|
|
2259
|
+
declare function defineCommandPublisher<TMessage extends MessageDefinition, TRoutingKey extends string, TPublisherRoutingKey extends string = TRoutingKey>(commandConsumer: CommandConsumerConfig<TMessage, TopicExchangeDefinition, TRoutingKey>, options?: {
|
|
2260
|
+
routingKey?: RoutingKey<TPublisherRoutingKey>;
|
|
2261
|
+
}): {
|
|
2262
|
+
message: TMessage;
|
|
1891
2263
|
exchange: TopicExchangeDefinition;
|
|
1892
|
-
|
|
2264
|
+
routingKey: string;
|
|
2265
|
+
};
|
|
2266
|
+
/**
|
|
2267
|
+
* Type guard to check if a value is a CommandConsumerConfig.
|
|
2268
|
+
*
|
|
2269
|
+
* @param value - The value to check
|
|
2270
|
+
* @returns True if the value is a CommandConsumerConfig
|
|
2271
|
+
*/
|
|
2272
|
+
declare function isCommandConsumerConfig(value: unknown): value is CommandConsumerConfig<MessageDefinition, ExchangeDefinition, string | undefined>;
|
|
2273
|
+
//#endregion
|
|
2274
|
+
//#region src/builder/ttl-backoff.d.ts
|
|
1893
2275
|
/**
|
|
1894
2276
|
* Result type for TTL-backoff retry infrastructure builder.
|
|
1895
2277
|
*
|
|
@@ -1964,5 +2346,5 @@ declare function defineTtlBackoffRetryInfrastructure(queueEntry: QueueEntry, opt
|
|
|
1964
2346
|
waitQueueDurable?: boolean;
|
|
1965
2347
|
}): TtlBackoffRetryInfrastructure;
|
|
1966
2348
|
//#endregion
|
|
1967
|
-
export { type AnySchema, type BaseExchangeDefinition, type BindingDefinition, type BindingPattern, type ClassicQueueDefinition, type ClassicQueueOptions, type CompressionAlgorithm, type ConsumerDefinition, type
|
|
2349
|
+
export { type AnySchema, type BaseExchangeDefinition, type BindingDefinition, type BindingPattern, type ClassicQueueDefinition, type ClassicQueueOptions, type CommandConsumerConfig, type CommandConsumerConfigBase, type CompressionAlgorithm, type ConsumerDefinition, type ConsumerEntry, type ContractDefinition, type ContractDefinitionInput, 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, extractQueue, isCommandConsumerConfig, isEventConsumerResult, isEventPublisherConfig, isQueueWithTtlBackoffInfrastructure };
|
|
1968
2350
|
//# sourceMappingURL=index.d.cts.map
|