@amqp-contract/contract 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -67,10 +67,9 @@ function defineMessage(payload, options) {
67
67
  }
68
68
 
69
69
  //#endregion
70
- //#region src/builder/binding.ts
70
+ //#region src/builder/queue-utils.ts
71
71
  /**
72
72
  * Type guard to check if a queue entry is a QueueWithTtlBackoffInfrastructure.
73
- * Duplicated here to avoid circular dependency with queue.ts.
74
73
  * @internal
75
74
  */
76
75
  function isQueueWithTtlBackoffInfrastructure$1(entry) {
@@ -78,13 +77,15 @@ function isQueueWithTtlBackoffInfrastructure$1(entry) {
78
77
  }
79
78
  /**
80
79
  * Extract the plain QueueDefinition from a QueueEntry.
81
- * Duplicated here to avoid circular dependency with queue.ts.
82
80
  * @internal
83
81
  */
84
- function extractQueueInternal(entry) {
82
+ function extractQueueFromEntry(entry) {
85
83
  if (isQueueWithTtlBackoffInfrastructure$1(entry)) return entry.queue;
86
84
  return entry;
87
85
  }
86
+
87
+ //#endregion
88
+ //#region src/builder/binding.ts
88
89
  /**
89
90
  * Define a binding between a queue and an exchange.
90
91
  *
@@ -97,7 +98,7 @@ function extractQueueInternal(entry) {
97
98
  * @internal
98
99
  */
99
100
  function defineQueueBinding(queue, exchange, options) {
100
- const queueDef = extractQueueInternal(queue);
101
+ const queueDef = extractQueueFromEntry(queue);
101
102
  if (exchange.type === "fanout") return {
102
103
  type: "queue",
103
104
  queue: queueDef,
@@ -198,7 +199,7 @@ function resolveTtlBackoffOptions(options) {
198
199
  * ```
199
200
  */
200
201
  function isQueueWithTtlBackoffInfrastructure(entry) {
201
- return typeof entry === "object" && entry !== null && "__brand" in entry && entry.__brand === "QueueWithTtlBackoffInfrastructure";
202
+ return isQueueWithTtlBackoffInfrastructure$1(entry);
202
203
  }
203
204
  /**
204
205
  * Extract the plain QueueDefinition from a QueueEntry.
@@ -249,14 +250,13 @@ function isQueueWithTtlBackoffInfrastructure(entry) {
249
250
  * @see defineTtlBackoffQueue - Creates queues with TTL-backoff infrastructure
250
251
  */
251
252
  function extractQueue(entry) {
252
- if (isQueueWithTtlBackoffInfrastructure(entry)) return entry.queue;
253
- return entry;
253
+ return extractQueueFromEntry(entry);
254
254
  }
255
255
  /**
256
- * Wrap a queue definition with TTL-backoff retry infrastructure.
256
+ * Create TTL-backoff retry infrastructure (wait queue + bindings) for a queue.
257
257
  * @internal
258
258
  */
259
- function wrapWithTtlBackoffInfrastructure(queue) {
259
+ function createTtlBackoffInfrastructure(queue) {
260
260
  if (!queue.deadLetter) throw new Error(`Queue "${queue.name}" does not have a dead letter exchange configured. TTL-backoff retry requires deadLetter to be set on the queue.`);
261
261
  const dlx = queue.deadLetter.exchange;
262
262
  const waitQueueName = `${queue.name}-wait`;
@@ -270,15 +270,23 @@ function wrapWithTtlBackoffInfrastructure(queue) {
270
270
  },
271
271
  retry: resolveTtlBackoffOptions(void 0)
272
272
  };
273
- const waitQueueBinding = defineQueueBindingInternal(waitQueue, dlx, { routingKey: waitQueueName });
274
- const mainQueueRetryBinding = defineQueueBindingInternal(queue, dlx, { routingKey: queue.name });
273
+ return {
274
+ waitQueue,
275
+ waitQueueBinding: defineQueueBindingInternal(waitQueue, dlx, { routingKey: waitQueueName }),
276
+ mainQueueRetryBinding: defineQueueBindingInternal(queue, dlx, { routingKey: queue.name })
277
+ };
278
+ }
279
+ /**
280
+ * Wrap a queue definition with TTL-backoff retry infrastructure.
281
+ * @internal
282
+ */
283
+ function wrapWithTtlBackoffInfrastructure(queue) {
284
+ const infra = createTtlBackoffInfrastructure(queue);
275
285
  return {
276
286
  __brand: "QueueWithTtlBackoffInfrastructure",
277
287
  queue,
278
288
  deadLetter: queue.deadLetter,
279
- waitQueue,
280
- waitQueueBinding,
281
- mainQueueRetryBinding
289
+ ...infra
282
290
  };
283
291
  }
284
292
  function defineQueue(name, options) {
@@ -610,21 +618,41 @@ function defineEventPublisher(exchange, message, options) {
610
618
  * @internal
611
619
  */
612
620
  function defineEventConsumer(eventPublisher, queue, options) {
613
- const { exchange, message, routingKey: publisherRoutingKey } = eventPublisher;
621
+ const { exchange: sourceExchange, message, routingKey: publisherRoutingKey } = eventPublisher;
614
622
  const bindingRoutingKey = options?.routingKey ?? publisherRoutingKey;
615
623
  const bindingOptions = {};
616
624
  if (bindingRoutingKey !== void 0) bindingOptions.routingKey = bindingRoutingKey;
617
625
  const bindingArguments = options?.arguments ?? eventPublisher.arguments;
618
626
  if (bindingArguments !== void 0) bindingOptions.arguments = bindingArguments;
619
- const binding = defineQueueBindingInternal(queue, exchange, bindingOptions);
627
+ const bridgeExchange = options?.bridgeExchange;
628
+ if (bridgeExchange) {
629
+ const binding = defineQueueBindingInternal(queue, bridgeExchange, bindingOptions);
630
+ const consumer = defineConsumer(queue, message);
631
+ const exchangeBindingOptions = {};
632
+ if (bindingRoutingKey !== void 0) exchangeBindingOptions.routingKey = bindingRoutingKey;
633
+ const e2eBinding = sourceExchange.type === "fanout" ? defineExchangeBinding(bridgeExchange, sourceExchange) : defineExchangeBinding(bridgeExchange, sourceExchange, exchangeBindingOptions);
634
+ return {
635
+ __brand: "EventConsumerResult",
636
+ consumer,
637
+ binding,
638
+ exchange: sourceExchange,
639
+ queue: consumer.queue,
640
+ deadLetterExchange: consumer.queue.deadLetter?.exchange,
641
+ exchangeBinding: e2eBinding,
642
+ bridgeExchange
643
+ };
644
+ }
645
+ const binding = defineQueueBindingInternal(queue, sourceExchange, bindingOptions);
620
646
  const consumer = defineConsumer(queue, message);
621
647
  return {
622
648
  __brand: "EventConsumerResult",
623
649
  consumer,
624
650
  binding,
625
- exchange,
651
+ exchange: sourceExchange,
626
652
  queue: consumer.queue,
627
- deadLetterExchange: consumer.queue.deadLetter?.exchange
653
+ deadLetterExchange: consumer.queue.deadLetter?.exchange,
654
+ exchangeBinding: void 0,
655
+ bridgeExchange: void 0
628
656
  };
629
657
  }
630
658
  /**
@@ -670,11 +698,26 @@ function defineCommandConsumer(queue, exchange, message, options) {
670
698
  * @internal
671
699
  */
672
700
  function defineCommandPublisher(commandConsumer, options) {
673
- const { exchange, message, routingKey: consumerRoutingKey } = commandConsumer;
701
+ const { exchange: targetExchange, message, routingKey: consumerRoutingKey } = commandConsumer;
674
702
  const publisherRoutingKey = options?.routingKey ?? consumerRoutingKey;
703
+ const bridgeExchange = options?.bridgeExchange;
704
+ if (bridgeExchange) {
705
+ const publisherOptions = {};
706
+ if (publisherRoutingKey !== void 0) publisherOptions.routingKey = publisherRoutingKey;
707
+ const publisher = definePublisherInternal(bridgeExchange, message, publisherOptions);
708
+ const e2eBindingOptions = {};
709
+ if (publisherRoutingKey !== void 0) e2eBindingOptions.routingKey = publisherRoutingKey;
710
+ return {
711
+ __brand: "BridgedPublisherConfig",
712
+ publisher,
713
+ exchangeBinding: bridgeExchange.type === "fanout" ? defineExchangeBinding(targetExchange, bridgeExchange) : defineExchangeBinding(targetExchange, bridgeExchange, e2eBindingOptions),
714
+ bridgeExchange,
715
+ targetExchange
716
+ };
717
+ }
675
718
  const publisherOptions = {};
676
719
  if (publisherRoutingKey !== void 0) publisherOptions.routingKey = publisherRoutingKey;
677
- return definePublisherInternal(exchange, message, publisherOptions);
720
+ return definePublisherInternal(targetExchange, message, publisherOptions);
678
721
  }
679
722
  /**
680
723
  * Type guard to check if a value is a CommandConsumerConfig.
@@ -685,6 +728,15 @@ function defineCommandPublisher(commandConsumer, options) {
685
728
  function isCommandConsumerConfig(value) {
686
729
  return typeof value === "object" && value !== null && "__brand" in value && value.__brand === "CommandConsumerConfig";
687
730
  }
731
+ /**
732
+ * Type guard to check if a value is a BridgedPublisherConfig.
733
+ *
734
+ * @param value - The value to check
735
+ * @returns True if the value is a BridgedPublisherConfig
736
+ */
737
+ function isBridgedPublisherConfig(value) {
738
+ return typeof value === "object" && value !== null && "__brand" in value && value.__brand === "BridgedPublisherConfig";
739
+ }
688
740
 
689
741
  //#endregion
690
742
  //#region src/builder/contract.ts
@@ -766,7 +818,13 @@ function defineContract(definition) {
766
818
  if (inputPublishers && Object.keys(inputPublishers).length > 0) {
767
819
  const processedPublishers = {};
768
820
  const exchanges = {};
769
- for (const [name, entry] of Object.entries(inputPublishers)) if (isEventPublisherConfig(entry)) {
821
+ const publisherBindings = {};
822
+ for (const [name, entry] of Object.entries(inputPublishers)) if (isBridgedPublisherConfig(entry)) {
823
+ exchanges[entry.bridgeExchange.name] = entry.bridgeExchange;
824
+ exchanges[entry.targetExchange.name] = entry.targetExchange;
825
+ publisherBindings[`${name}ExchangeBinding`] = entry.exchangeBinding;
826
+ processedPublishers[name] = entry.publisher;
827
+ } else if (isEventPublisherConfig(entry)) {
770
828
  exchanges[entry.exchange.name] = entry.exchange;
771
829
  const publisherOptions = {};
772
830
  if (entry.routingKey !== void 0) publisherOptions.routingKey = entry.routingKey;
@@ -781,6 +839,10 @@ function defineContract(definition) {
781
839
  ...result.exchanges,
782
840
  ...exchanges
783
841
  };
842
+ result.bindings = {
843
+ ...result.bindings,
844
+ ...publisherBindings
845
+ };
784
846
  }
785
847
  if (inputConsumers && Object.keys(inputConsumers).length > 0) {
786
848
  const processedConsumers = {};
@@ -794,6 +856,9 @@ function defineContract(definition) {
794
856
  queues[queueEntry.name] = queueEntry;
795
857
  exchanges[entry.binding.exchange.name] = entry.binding.exchange;
796
858
  if (queueEntry.deadLetter?.exchange) exchanges[queueEntry.deadLetter.exchange.name] = queueEntry.deadLetter.exchange;
859
+ if (entry.exchangeBinding) consumerBindings[`${name}ExchangeBinding`] = entry.exchangeBinding;
860
+ if (entry.bridgeExchange) exchanges[entry.bridgeExchange.name] = entry.bridgeExchange;
861
+ if (entry.exchange) exchanges[entry.exchange.name] = entry.exchange;
797
862
  } else if (isCommandConsumerConfig(entry)) {
798
863
  processedConsumers[name] = entry.consumer;
799
864
  consumerBindings[`${name}Binding`] = entry.binding;
@@ -809,22 +874,11 @@ function defineContract(definition) {
809
874
  if (queueEntry.deadLetter?.exchange) exchanges[queueEntry.deadLetter.exchange.name] = queueEntry.deadLetter.exchange;
810
875
  }
811
876
  for (const queue of Object.values(queues)) if (queue.retry?.mode === "ttl-backoff" && queue.deadLetter) {
812
- const dlx = queue.deadLetter.exchange;
813
- const waitQueueName = `${queue.name}-wait`;
814
- const waitQueue = {
815
- name: waitQueueName,
816
- type: "quorum",
817
- durable: queue.durable ?? true,
818
- deadLetter: {
819
- exchange: dlx,
820
- routingKey: queue.name
821
- },
822
- retry: resolveTtlBackoffOptions(void 0)
823
- };
824
- queues[waitQueueName] = waitQueue;
825
- consumerBindings[`${queue.name}WaitBinding`] = defineQueueBindingInternal(waitQueue, dlx, { routingKey: waitQueueName });
826
- consumerBindings[`${queue.name}RetryBinding`] = defineQueueBindingInternal(queue, dlx, { routingKey: queue.name });
827
- exchanges[dlx.name] = dlx;
877
+ const infra = createTtlBackoffInfrastructure(queue);
878
+ queues[infra.waitQueue.name] = infra.waitQueue;
879
+ consumerBindings[`${queue.name}WaitBinding`] = infra.waitQueueBinding;
880
+ consumerBindings[`${queue.name}RetryBinding`] = infra.mainQueueRetryBinding;
881
+ exchanges[queue.deadLetter.exchange.name] = queue.deadLetter.exchange;
828
882
  }
829
883
  result.consumers = processedConsumers;
830
884
  result.bindings = {
@@ -888,23 +942,9 @@ function defineContract(definition) {
888
942
  * ```
889
943
  */
890
944
  function defineTtlBackoffRetryInfrastructure(queueEntry, options) {
891
- const queue = extractQueue(queueEntry);
892
- if (!queue.deadLetter) throw new Error(`Queue "${queue.name}" does not have a dead letter exchange configured. TTL-backoff retry requires deadLetter to be set on the queue.`);
893
- const dlx = queue.deadLetter.exchange;
894
- const waitQueueName = `${queue.name}-wait`;
895
- const waitQueue = defineQueue(waitQueueName, {
896
- type: "quorum",
897
- durable: options?.waitQueueDurable ?? queue.durable ?? true,
898
- deadLetter: {
899
- exchange: dlx,
900
- routingKey: queue.name
901
- }
902
- });
903
- return {
904
- waitQueue,
905
- waitQueueBinding: defineQueueBindingInternal(waitQueue, dlx, { routingKey: waitQueueName }),
906
- mainQueueRetryBinding: defineQueueBindingInternal(queue, dlx, { routingKey: queue.name })
907
- };
945
+ const infra = createTtlBackoffInfrastructure(extractQueue(queueEntry));
946
+ if (options?.waitQueueDurable !== void 0) infra.waitQueue.durable = options.waitQueueDurable;
947
+ return infra;
908
948
  }
909
949
 
910
950
  //#endregion
@@ -925,6 +965,7 @@ exports.defineTtlBackoffQueue = defineTtlBackoffQueue;
925
965
  exports.defineTtlBackoffRetryInfrastructure = defineTtlBackoffRetryInfrastructure;
926
966
  exports.extractConsumer = extractConsumer;
927
967
  exports.extractQueue = extractQueue;
968
+ exports.isBridgedPublisherConfig = isBridgedPublisherConfig;
928
969
  exports.isCommandConsumerConfig = isCommandConsumerConfig;
929
970
  exports.isEventConsumerResult = isEventConsumerResult;
930
971
  exports.isEventPublisherConfig = isEventPublisherConfig;
package/dist/index.d.cts CHANGED
@@ -641,7 +641,7 @@ type QueueEntry<TName extends string = string> = QueueDefinition<TName> | QueueW
641
641
  * @template TPayload - The Standard Schema v1 compatible schema for the message payload
642
642
  * @template THeaders - The Standard Schema v1 compatible schema for the message headers (optional)
643
643
  */
644
- type MessageDefinition<TPayload extends AnySchema = AnySchema, THeaders extends StandardSchemaV1<Record<string, unknown>> | undefined = undefined> = {
644
+ type MessageDefinition<TPayload extends AnySchema = AnySchema, THeaders extends StandardSchemaV1<Record<string, unknown>> | undefined = StandardSchemaV1<Record<string, unknown>> | undefined> = {
645
645
  /**
646
646
  * The payload schema for validating message content.
647
647
  * Must be a Standard Schema v1 compatible schema (Zod, Valibot, ArkType, etc.).
@@ -836,6 +836,23 @@ type EventConsumerResultBase = {
836
836
  exchange: ExchangeDefinition;
837
837
  queue: QueueDefinition;
838
838
  deadLetterExchange: ExchangeDefinition | undefined;
839
+ exchangeBinding: ExchangeBindingDefinition | undefined;
840
+ bridgeExchange: ExchangeDefinition | undefined;
841
+ };
842
+ /**
843
+ * Base type for bridged publisher configuration.
844
+ *
845
+ * A bridged publisher publishes to a bridge exchange, which forwards messages
846
+ * to the target exchange via an exchange-to-exchange binding.
847
+ *
848
+ * @see defineCommandPublisher with bridgeExchange option
849
+ */
850
+ type BridgedPublisherConfigBase = {
851
+ __brand: "BridgedPublisherConfig";
852
+ publisher: PublisherDefinition;
853
+ exchangeBinding: ExchangeBindingDefinition;
854
+ bridgeExchange: ExchangeDefinition;
855
+ targetExchange: ExchangeDefinition;
839
856
  };
840
857
  /**
841
858
  * Complete AMQP contract definition (output type).
@@ -909,7 +926,7 @@ type ContractDefinition = {
909
926
  * - A plain PublisherDefinition from definePublisher
910
927
  * - An EventPublisherConfig from defineEventPublisher (auto-extracted to publisher)
911
928
  */
912
- type PublisherEntry = PublisherDefinition | EventPublisherConfigBase;
929
+ type PublisherEntry = PublisherDefinition | EventPublisherConfigBase | BridgedPublisherConfigBase;
913
930
  /**
914
931
  * Consumer entry that can be passed to defineContract's consumers section.
915
932
  *
@@ -966,7 +983,7 @@ type ContractDefinitionInput = {
966
983
  * Extract the exchange from a publisher entry.
967
984
  * @internal
968
985
  */
969
- type ExtractPublisherExchange<T extends PublisherEntry> = T extends EventPublisherConfigBase ? T["exchange"] : T extends PublisherDefinition ? T["exchange"] : never;
986
+ type ExtractPublisherExchange<T extends PublisherEntry> = T extends BridgedPublisherConfigBase ? T["bridgeExchange"] : T extends EventPublisherConfigBase ? T["exchange"] : T extends PublisherDefinition ? T["exchange"] : never;
970
987
  /**
971
988
  * Extract the QueueDefinition from a QueueEntry type.
972
989
  * For QueueWithTtlBackoffInfrastructure, returns the inner queue definition.
@@ -1057,7 +1074,7 @@ type ExtractConsumerDefinitions<TConsumers extends Record<string, ConsumerEntry>
1057
1074
  * Extract the publisher definition from a publisher entry.
1058
1075
  * @internal
1059
1076
  */
1060
- type ExtractPublisherDefinition<T extends PublisherEntry> = T extends EventPublisherConfigBase ? PublisherDefinition<T["message"]> & (T["exchange"] extends FanoutExchangeDefinition ? {
1077
+ type ExtractPublisherDefinition<T extends PublisherEntry> = T extends BridgedPublisherConfigBase ? T["publisher"] : T extends EventPublisherConfigBase ? PublisherDefinition<T["message"]> & (T["exchange"] extends FanoutExchangeDefinition ? {
1061
1078
  exchange: T["exchange"];
1062
1079
  routingKey?: never;
1063
1080
  } : {
@@ -1069,6 +1086,56 @@ type ExtractPublisherDefinition<T extends PublisherEntry> = T extends EventPubli
1069
1086
  * @internal
1070
1087
  */
1071
1088
  type ExtractPublisherDefinitions<TPublishers extends Record<string, PublisherEntry>> = { [K in keyof TPublishers]: ExtractPublisherDefinition<TPublishers[K]> };
1089
+ /**
1090
+ * Extract the bridge exchange from a consumer entry (when bridgeExchange is set).
1091
+ * @internal
1092
+ */
1093
+ type ExtractBridgeExchangeFromConsumer<T extends ConsumerEntry> = T extends EventConsumerResultBase ? T["bridgeExchange"] extends ExchangeDefinition ? T["bridgeExchange"] : never : never;
1094
+ /**
1095
+ * Extract bridge exchanges from all consumers in a contract.
1096
+ * @internal
1097
+ */
1098
+ type ExtractBridgeExchangesFromConsumers<TConsumers extends Record<string, ConsumerEntry>> = { [K in keyof TConsumers as ExtractBridgeExchangeFromConsumer<TConsumers[K]> extends never ? never : ExtractBridgeExchangeFromConsumer<TConsumers[K]>["name"]]: ExtractBridgeExchangeFromConsumer<TConsumers[K]> };
1099
+ /**
1100
+ * Extract the target exchange from a bridged publisher entry.
1101
+ * @internal
1102
+ */
1103
+ type ExtractTargetExchangeFromPublisher<T extends PublisherEntry> = T extends BridgedPublisherConfigBase ? T["targetExchange"] : never;
1104
+ /**
1105
+ * Extract target exchanges from all publishers in a contract.
1106
+ * @internal
1107
+ */
1108
+ type ExtractTargetExchangesFromPublishers<TPublishers extends Record<string, PublisherEntry>> = { [K in keyof TPublishers as ExtractTargetExchangeFromPublisher<TPublishers[K]> extends never ? never : ExtractTargetExchangeFromPublisher<TPublishers[K]>["name"]]: ExtractTargetExchangeFromPublisher<TPublishers[K]> };
1109
+ /**
1110
+ * Check if a consumer entry has an exchange binding (e2e).
1111
+ * @internal
1112
+ */
1113
+ type HasConsumerExchangeBinding<T extends ConsumerEntry> = T extends EventConsumerResultBase ? T["exchangeBinding"] extends ExchangeBindingDefinition ? true : false : false;
1114
+ /**
1115
+ * Extract the exchange binding from a consumer entry.
1116
+ * @internal
1117
+ */
1118
+ type ExtractConsumerExchangeBinding<T extends ConsumerEntry> = T extends EventConsumerResultBase ? T["exchangeBinding"] extends ExchangeBindingDefinition ? T["exchangeBinding"] : never : never;
1119
+ /**
1120
+ * Extract exchange bindings from all consumers in a contract.
1121
+ * @internal
1122
+ */
1123
+ type ExtractExchangeBindingsFromConsumers<TConsumers extends Record<string, ConsumerEntry>> = { [K in keyof TConsumers as HasConsumerExchangeBinding<TConsumers[K]> extends true ? `${K & string}ExchangeBinding` : never]: ExtractConsumerExchangeBinding<TConsumers[K]> };
1124
+ /**
1125
+ * Check if a publisher entry has an exchange binding (bridged).
1126
+ * @internal
1127
+ */
1128
+ type HasPublisherExchangeBinding<T extends PublisherEntry> = T extends BridgedPublisherConfigBase ? true : false;
1129
+ /**
1130
+ * Extract the exchange binding from a bridged publisher entry.
1131
+ * @internal
1132
+ */
1133
+ type ExtractPublisherExchangeBinding<T extends PublisherEntry> = T extends BridgedPublisherConfigBase ? T["exchangeBinding"] : never;
1134
+ /**
1135
+ * Extract exchange bindings from all publishers in a contract.
1136
+ * @internal
1137
+ */
1138
+ type ExtractExchangeBindingsFromPublishers<TPublishers extends Record<string, PublisherEntry>> = { [K in keyof TPublishers as HasPublisherExchangeBinding<TPublishers[K]> extends true ? `${K & string}ExchangeBinding` : never]: ExtractPublisherExchangeBinding<TPublishers[K]> };
1072
1139
  /**
1073
1140
  * Contract output type with all resources extracted and properly typed.
1074
1141
  *
@@ -1080,9 +1147,9 @@ type ExtractPublisherDefinitions<TPublishers extends Record<string, PublisherEnt
1080
1147
  * - consumers: Normalized consumer definitions
1081
1148
  */
1082
1149
  type ContractOutput<TContract extends ContractDefinitionInput> = {
1083
- exchanges: (TContract["publishers"] extends Record<string, PublisherEntry> ? ExtractExchangesFromPublishers<TContract["publishers"]> : {}) & (TContract["consumers"] extends Record<string, ConsumerEntry> ? ExtractExchangesFromConsumers<TContract["consumers"]> : {}) & (TContract["consumers"] extends Record<string, ConsumerEntry> ? ExtractDeadLetterExchangesFromConsumers<TContract["consumers"]> : {});
1150
+ exchanges: (TContract["publishers"] extends Record<string, PublisherEntry> ? ExtractExchangesFromPublishers<TContract["publishers"]> : {}) & (TContract["consumers"] extends Record<string, ConsumerEntry> ? ExtractExchangesFromConsumers<TContract["consumers"]> : {}) & (TContract["consumers"] extends Record<string, ConsumerEntry> ? ExtractDeadLetterExchangesFromConsumers<TContract["consumers"]> : {}) & (TContract["consumers"] extends Record<string, ConsumerEntry> ? ExtractBridgeExchangesFromConsumers<TContract["consumers"]> : {}) & (TContract["publishers"] extends Record<string, PublisherEntry> ? ExtractTargetExchangesFromPublishers<TContract["publishers"]> : {});
1084
1151
  queues: TContract["consumers"] extends Record<string, ConsumerEntry> ? ExtractQueuesFromConsumers<TContract["consumers"]> : {};
1085
- bindings: TContract["consumers"] extends Record<string, ConsumerEntry> ? ExtractBindingsFromConsumers<TContract["consumers"]> : {};
1152
+ bindings: (TContract["consumers"] extends Record<string, ConsumerEntry> ? ExtractBindingsFromConsumers<TContract["consumers"]> : {}) & (TContract["consumers"] extends Record<string, ConsumerEntry> ? ExtractExchangeBindingsFromConsumers<TContract["consumers"]> : {}) & (TContract["publishers"] extends Record<string, PublisherEntry> ? ExtractExchangeBindingsFromPublishers<TContract["publishers"]> : {});
1086
1153
  publishers: TContract["publishers"] extends Record<string, PublisherEntry> ? ExtractPublisherDefinitions<TContract["publishers"]> : {};
1087
1154
  consumers: TContract["consumers"] extends Record<string, ConsumerEntry> ? ExtractConsumerDefinitions<TContract["consumers"]> : {};
1088
1155
  };
@@ -2048,13 +2115,15 @@ type EventPublisherConfig<TMessage extends MessageDefinition, TExchange extends
2048
2115
  *
2049
2116
  * @template TMessage - The message definition
2050
2117
  */
2051
- type EventConsumerResult<TMessage extends MessageDefinition, TExchange extends ExchangeDefinition = ExchangeDefinition, TQueue extends QueueDefinition = QueueDefinition, TDlxExchange extends ExchangeDefinition | undefined = ExchangeDefinition | undefined> = {
2118
+ type EventConsumerResult<TMessage extends MessageDefinition, TExchange extends ExchangeDefinition = ExchangeDefinition, TQueue extends QueueDefinition = QueueDefinition, TDlxExchange extends ExchangeDefinition | undefined = ExchangeDefinition | undefined, TExchangeBinding extends ExchangeBindingDefinition | undefined = ExchangeBindingDefinition | undefined, TBridgeExchange extends ExchangeDefinition | undefined = ExchangeDefinition | undefined> = {
2052
2119
  /** Discriminator to identify this as an event consumer result */__brand: "EventConsumerResult"; /** The consumer definition for processing messages */
2053
2120
  consumer: ConsumerDefinition<TMessage>; /** The binding connecting the queue to the exchange */
2054
- binding: QueueBindingDefinition; /** The exchange this consumer subscribes to */
2121
+ binding: QueueBindingDefinition; /** The source exchange this consumer subscribes to */
2055
2122
  exchange: TExchange; /** The queue this consumer reads from */
2056
2123
  queue: TQueue; /** The dead letter exchange from the queue, if configured */
2057
- deadLetterExchange: TDlxExchange;
2124
+ deadLetterExchange: TDlxExchange; /** The exchange-to-exchange binding when bridging, if configured */
2125
+ exchangeBinding: TExchangeBinding; /** The bridge (local domain) exchange when bridging, if configured */
2126
+ bridgeExchange: TBridgeExchange;
2058
2127
  };
2059
2128
  /**
2060
2129
  * Define an event publisher for broadcasting messages via fanout exchange.
@@ -2150,6 +2219,50 @@ declare function defineEventPublisher<TMessage extends MessageDefinition, TRouti
2150
2219
  routingKey: RoutingKey<TRoutingKey>;
2151
2220
  arguments?: Record<string, unknown>;
2152
2221
  }): EventPublisherConfig<TMessage, TExchange, TRoutingKey>;
2222
+ /**
2223
+ * Create a consumer that subscribes to an event from a fanout exchange via a bridge exchange.
2224
+ *
2225
+ * When `bridgeExchange` is provided, the queue binds to the bridge exchange instead of the
2226
+ * source exchange, and an exchange-to-exchange binding is created from the source to the bridge.
2227
+ *
2228
+ * @param eventPublisher - The event publisher configuration
2229
+ * @param queue - The queue that will receive messages
2230
+ * @param options - Binding configuration with required bridgeExchange
2231
+ * @param options.bridgeExchange - The fanout bridge exchange (must be fanout to match source)
2232
+ * @returns An object with the consumer definition, queue binding, and exchange binding
2233
+ */
2234
+ declare function defineEventConsumer<TMessage extends MessageDefinition, TExchange extends FanoutExchangeDefinition, TQueueEntry extends QueueEntry, TBridgeExchange extends FanoutExchangeDefinition>(eventPublisher: EventPublisherConfig<TMessage, TExchange, undefined>, queue: TQueueEntry, options: {
2235
+ bridgeExchange: TBridgeExchange;
2236
+ arguments?: Record<string, unknown>;
2237
+ }): EventConsumerResult<TMessage, TExchange, ExtractQueueFromEntry<TQueueEntry>, ExtractDlxFromEntry<TQueueEntry>, ExchangeBindingDefinition, TBridgeExchange>;
2238
+ /**
2239
+ * Create a consumer that subscribes to an event from a direct exchange via a bridge exchange.
2240
+ *
2241
+ * @param eventPublisher - The event publisher configuration
2242
+ * @param queue - The queue that will receive messages
2243
+ * @param options - Binding configuration with required bridgeExchange
2244
+ * @param options.bridgeExchange - The bridge exchange (must be direct or topic to preserve routing keys)
2245
+ * @returns An object with the consumer definition, queue binding, and exchange binding
2246
+ */
2247
+ declare function defineEventConsumer<TMessage extends MessageDefinition, TRoutingKey extends string, TExchange extends DirectExchangeDefinition, TQueueEntry extends QueueEntry, TBridgeExchange extends DirectExchangeDefinition | TopicExchangeDefinition>(eventPublisher: EventPublisherConfig<TMessage, TExchange, TRoutingKey>, queue: TQueueEntry, options: {
2248
+ bridgeExchange: TBridgeExchange;
2249
+ arguments?: Record<string, unknown>;
2250
+ }): EventConsumerResult<TMessage, TExchange, ExtractQueueFromEntry<TQueueEntry>, ExtractDlxFromEntry<TQueueEntry>, ExchangeBindingDefinition, TBridgeExchange>;
2251
+ /**
2252
+ * Create a consumer that subscribes to an event from a topic exchange via a bridge exchange.
2253
+ *
2254
+ * @param eventPublisher - The event publisher configuration
2255
+ * @param queue - The queue that will receive messages
2256
+ * @param options - Binding configuration with required bridgeExchange
2257
+ * @param options.bridgeExchange - The bridge exchange (must be direct or topic to preserve routing keys)
2258
+ * @param options.routingKey - Override routing key with pattern (defaults to publisher's key)
2259
+ * @returns An object with the consumer definition, queue binding, and exchange binding
2260
+ */
2261
+ declare function defineEventConsumer<TMessage extends MessageDefinition, TRoutingKey extends string, TExchange extends TopicExchangeDefinition, TQueueEntry extends QueueEntry, TBridgeExchange extends DirectExchangeDefinition | TopicExchangeDefinition, TConsumerRoutingKey extends string = TRoutingKey>(eventPublisher: EventPublisherConfig<TMessage, TExchange, TRoutingKey>, queue: TQueueEntry, options: {
2262
+ bridgeExchange: TBridgeExchange;
2263
+ routingKey?: BindingPattern<TConsumerRoutingKey>;
2264
+ arguments?: Record<string, unknown>;
2265
+ }): EventConsumerResult<TMessage, TExchange, ExtractQueueFromEntry<TQueueEntry>, ExtractDlxFromEntry<TQueueEntry>, ExchangeBindingDefinition, TBridgeExchange>;
2153
2266
  /**
2154
2267
  * Create a consumer that subscribes to an event from a fanout exchange.
2155
2268
  *
@@ -2245,6 +2358,23 @@ type CommandConsumerConfig<TMessage extends MessageDefinition, TExchange extends
2245
2358
  message: TMessage; /** The routing key pattern for the binding */
2246
2359
  routingKey: TRoutingKey;
2247
2360
  };
2361
+ /**
2362
+ * Configuration for a bridged command publisher.
2363
+ *
2364
+ * A bridged publisher publishes to a bridge exchange (local domain), which forwards
2365
+ * messages to the target exchange (remote domain) via an exchange-to-exchange binding.
2366
+ *
2367
+ * @template TMessage - The message definition
2368
+ * @template TBridgeExchange - The bridge (local domain) exchange definition
2369
+ * @template TTargetExchange - The target (remote domain) exchange definition
2370
+ */
2371
+ type BridgedPublisherConfig<TMessage extends MessageDefinition, TBridgeExchange extends ExchangeDefinition, TTargetExchange extends ExchangeDefinition> = {
2372
+ /** Discriminator to identify this as a bridged publisher config */__brand: "BridgedPublisherConfig"; /** The publisher definition (publishes to bridge exchange) */
2373
+ publisher: PublisherDefinition<TMessage>; /** The exchange-to-exchange binding (bridge → target) */
2374
+ exchangeBinding: ExchangeBindingDefinition; /** The bridge (local domain) exchange */
2375
+ bridgeExchange: TBridgeExchange; /** The target (remote domain) exchange */
2376
+ targetExchange: TTargetExchange;
2377
+ };
2248
2378
  /**
2249
2379
  * Define a command consumer for receiving commands via fanout exchange.
2250
2380
  *
@@ -2336,6 +2466,41 @@ declare function defineCommandConsumer<TMessage extends MessageDefinition, TRout
2336
2466
  routingKey: BindingPattern<TRoutingKey>;
2337
2467
  arguments?: Record<string, unknown>;
2338
2468
  }): CommandConsumerConfig<TMessage, TExchange, TRoutingKey, ExtractQueueFromEntry<TQueueEntry>, ExtractDlxFromEntry<TQueueEntry>>;
2469
+ /**
2470
+ * Create a bridged publisher that sends commands to a fanout exchange consumer via a bridge exchange.
2471
+ *
2472
+ * @param commandConsumer - The command consumer configuration
2473
+ * @param options - Configuration with required bridgeExchange
2474
+ * @param options.bridgeExchange - The local domain exchange to bridge through
2475
+ * @returns A bridged publisher configuration
2476
+ */
2477
+ declare function defineCommandPublisher<TMessage extends MessageDefinition, TExchange extends FanoutExchangeDefinition, TBridgeExchange extends FanoutExchangeDefinition>(commandConsumer: CommandConsumerConfig<TMessage, TExchange, undefined>, options: {
2478
+ bridgeExchange: TBridgeExchange;
2479
+ }): BridgedPublisherConfig<TMessage, TBridgeExchange, TExchange>;
2480
+ /**
2481
+ * Create a bridged publisher that sends commands to a direct exchange consumer via a bridge exchange.
2482
+ *
2483
+ * @param commandConsumer - The command consumer configuration
2484
+ * @param options - Configuration with required bridgeExchange
2485
+ * @param options.bridgeExchange - The bridge exchange (must be direct or topic to preserve routing keys)
2486
+ * @returns A bridged publisher configuration
2487
+ */
2488
+ declare function defineCommandPublisher<TMessage extends MessageDefinition, TRoutingKey extends string, TExchange extends DirectExchangeDefinition, TBridgeExchange extends DirectExchangeDefinition | TopicExchangeDefinition>(commandConsumer: CommandConsumerConfig<TMessage, TExchange, TRoutingKey>, options: {
2489
+ bridgeExchange: TBridgeExchange;
2490
+ }): BridgedPublisherConfig<TMessage, TBridgeExchange, TExchange>;
2491
+ /**
2492
+ * Create a bridged publisher that sends commands to a topic exchange consumer via a bridge exchange.
2493
+ *
2494
+ * @param commandConsumer - The command consumer configuration
2495
+ * @param options - Configuration with required bridgeExchange and optional routingKey override
2496
+ * @param options.bridgeExchange - The bridge exchange (must be direct or topic to preserve routing keys)
2497
+ * @param options.routingKey - Override routing key (must match consumer's pattern)
2498
+ * @returns A bridged publisher configuration
2499
+ */
2500
+ declare function defineCommandPublisher<TMessage extends MessageDefinition, TRoutingKey extends string, TExchange extends TopicExchangeDefinition, TBridgeExchange extends DirectExchangeDefinition | TopicExchangeDefinition, TPublisherRoutingKey extends string = TRoutingKey>(commandConsumer: CommandConsumerConfig<TMessage, TExchange, TRoutingKey>, options: {
2501
+ bridgeExchange: TBridgeExchange;
2502
+ routingKey?: RoutingKey<TPublisherRoutingKey>;
2503
+ }): BridgedPublisherConfig<TMessage, TBridgeExchange, TExchange>;
2339
2504
  /**
2340
2505
  * Create a publisher that sends commands to a fanout exchange consumer.
2341
2506
  *
@@ -2401,6 +2566,13 @@ declare function defineCommandPublisher<TMessage extends MessageDefinition, TRou
2401
2566
  * @returns True if the value is a CommandConsumerConfig
2402
2567
  */
2403
2568
  declare function isCommandConsumerConfig(value: unknown): value is CommandConsumerConfig<MessageDefinition, ExchangeDefinition, string | undefined>;
2569
+ /**
2570
+ * Type guard to check if a value is a BridgedPublisherConfig.
2571
+ *
2572
+ * @param value - The value to check
2573
+ * @returns True if the value is a BridgedPublisherConfig
2574
+ */
2575
+ declare function isBridgedPublisherConfig(value: unknown): value is BridgedPublisherConfig<MessageDefinition, ExchangeDefinition, ExchangeDefinition>;
2404
2576
  //#endregion
2405
2577
  //#region src/builder/ttl-backoff.d.ts
2406
2578
  /**
@@ -2469,5 +2641,5 @@ declare function defineTtlBackoffRetryInfrastructure(queueEntry: QueueEntry, opt
2469
2641
  waitQueueDurable?: boolean;
2470
2642
  }): TtlBackoffRetryInfrastructure;
2471
2643
  //#endregion
2472
- 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 ContractOutput, type DeadLetterConfig, type DefineQueueOptions, type DefineQuorumQueueOptions, type DefineTtlBackoffQueueOptions, type DirectExchangeDefinition, type EventConsumerResult, type EventConsumerResultBase, type EventPublisherConfig, type EventPublisherConfigBase, type ExchangeBindingDefinition, type ExchangeDefinition, type FanoutExchangeDefinition, type InferConsumerNames, type InferPublisherNames, type MatchingRoutingKey, type MessageDefinition, type PublisherDefinition, type PublisherEntry, type QueueBindingDefinition, type QueueDefinition, type QueueEntry, type QueueType, type QueueWithTtlBackoffInfrastructure, type QuorumNativeRetryOptions, type QuorumQueueDefinition, type QuorumQueueOptions, type ResolvedRetryOptions, type ResolvedTtlBackoffRetryOptions, type RoutingKey, type TopicExchangeDefinition, type TtlBackoffRetryInfrastructure, type TtlBackoffRetryOptions, defineCommandConsumer, defineCommandPublisher, defineConsumer, defineContract, defineEventConsumer, defineEventPublisher, defineExchange, defineExchangeBinding, defineMessage, definePublisher, defineQueue, defineQueueBinding, defineQuorumQueue, defineTtlBackoffQueue, defineTtlBackoffRetryInfrastructure, extractConsumer, extractQueue, isCommandConsumerConfig, isEventConsumerResult, isEventPublisherConfig, isQueueWithTtlBackoffInfrastructure };
2644
+ export { type AnySchema, type BaseExchangeDefinition, type BindingDefinition, type BindingPattern, type BridgedPublisherConfig, type BridgedPublisherConfigBase, type ClassicQueueDefinition, type ClassicQueueOptions, type CommandConsumerConfig, type CommandConsumerConfigBase, type CompressionAlgorithm, type ConsumerDefinition, type ConsumerEntry, type ContractDefinition, type ContractDefinitionInput, type ContractOutput, type DeadLetterConfig, type DefineQueueOptions, type DefineQuorumQueueOptions, type DefineTtlBackoffQueueOptions, type DirectExchangeDefinition, type EventConsumerResult, type EventConsumerResultBase, type EventPublisherConfig, type EventPublisherConfigBase, type ExchangeBindingDefinition, type ExchangeDefinition, type FanoutExchangeDefinition, type InferConsumerNames, type InferPublisherNames, type MatchingRoutingKey, type MessageDefinition, type PublisherDefinition, type PublisherEntry, type QueueBindingDefinition, type QueueDefinition, type QueueEntry, type QueueType, type QueueWithTtlBackoffInfrastructure, type QuorumNativeRetryOptions, type QuorumQueueDefinition, type QuorumQueueOptions, type ResolvedRetryOptions, type ResolvedTtlBackoffRetryOptions, type RoutingKey, type TopicExchangeDefinition, type TtlBackoffRetryInfrastructure, type TtlBackoffRetryOptions, defineCommandConsumer, defineCommandPublisher, defineConsumer, defineContract, defineEventConsumer, defineEventPublisher, defineExchange, defineExchangeBinding, defineMessage, definePublisher, defineQueue, defineQueueBinding, defineQuorumQueue, defineTtlBackoffQueue, defineTtlBackoffRetryInfrastructure, extractConsumer, extractQueue, isBridgedPublisherConfig, isCommandConsumerConfig, isEventConsumerResult, isEventPublisherConfig, isQueueWithTtlBackoffInfrastructure };
2473
2645
  //# sourceMappingURL=index.d.cts.map