@zdavison/matador 2.0.9 → 2.0.11

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.
Files changed (259) hide show
  1. package/dist/checkpoint/context.d.ts +59 -0
  2. package/dist/checkpoint/context.d.ts.map +1 -0
  3. package/dist/checkpoint/context.js +140 -0
  4. package/dist/checkpoint/context.test.d.ts +2 -0
  5. package/dist/checkpoint/context.test.d.ts.map +1 -0
  6. package/dist/checkpoint/context.test.js +424 -0
  7. package/dist/checkpoint/index.d.ts +7 -0
  8. package/dist/checkpoint/index.d.ts.map +1 -0
  9. package/dist/checkpoint/index.js +6 -0
  10. package/dist/checkpoint/stores/memory.d.ts +29 -0
  11. package/dist/checkpoint/stores/memory.d.ts.map +1 -0
  12. package/dist/checkpoint/stores/memory.js +39 -0
  13. package/{src/checkpoint/stores/noop.ts → dist/checkpoint/stores/noop.d.ts} +5 -13
  14. package/dist/checkpoint/stores/noop.d.ts.map +1 -0
  15. package/dist/checkpoint/stores/noop.js +18 -0
  16. package/dist/checkpoint/stores/stores.test.d.ts +2 -0
  17. package/dist/checkpoint/stores/stores.test.d.ts.map +1 -0
  18. package/dist/checkpoint/stores/stores.test.js +146 -0
  19. package/dist/checkpoint/types.d.ts +119 -0
  20. package/dist/checkpoint/types.d.ts.map +1 -0
  21. package/dist/checkpoint/types.js +1 -0
  22. package/dist/codec/codec.d.ts +29 -0
  23. package/dist/codec/codec.d.ts.map +1 -0
  24. package/dist/codec/codec.js +15 -0
  25. package/dist/codec/header-aware-codec.d.ts +36 -0
  26. package/dist/codec/header-aware-codec.d.ts.map +1 -0
  27. package/dist/codec/header-aware-codec.js +1 -0
  28. package/{src/codec/index.ts → dist/codec/index.d.ts} +2 -7
  29. package/dist/codec/index.d.ts.map +1 -0
  30. package/dist/codec/index.js +3 -0
  31. package/dist/codec/json-codec.d.ts +13 -0
  32. package/dist/codec/json-codec.d.ts.map +1 -0
  33. package/dist/codec/json-codec.js +64 -0
  34. package/dist/codec/rabbitmq-codec.d.ts +28 -0
  35. package/dist/codec/rabbitmq-codec.d.ts.map +1 -0
  36. package/dist/codec/rabbitmq-codec.js +242 -0
  37. package/dist/codec/rabbitmq-codec.test.d.ts +2 -0
  38. package/dist/codec/rabbitmq-codec.test.d.ts.map +1 -0
  39. package/dist/codec/rabbitmq-codec.test.js +433 -0
  40. package/dist/core/fanout.d.ts +59 -0
  41. package/dist/core/fanout.d.ts.map +1 -0
  42. package/dist/core/fanout.js +121 -0
  43. package/dist/core/fanout.test.d.ts +2 -0
  44. package/dist/core/fanout.test.d.ts.map +1 -0
  45. package/dist/core/fanout.test.js +1054 -0
  46. package/{src/core/index.ts → dist/core/index.d.ts} +2 -7
  47. package/dist/core/index.d.ts.map +1 -0
  48. package/dist/core/index.js +3 -0
  49. package/dist/core/matador.d.ts +133 -0
  50. package/dist/core/matador.d.ts.map +1 -0
  51. package/dist/core/matador.js +228 -0
  52. package/dist/core/matador.test.d.ts +2 -0
  53. package/dist/core/matador.test.d.ts.map +1 -0
  54. package/dist/core/matador.test.js +446 -0
  55. package/dist/core/shutdown.d.ts +78 -0
  56. package/dist/core/shutdown.d.ts.map +1 -0
  57. package/dist/core/shutdown.js +111 -0
  58. package/dist/core/shutdown.test.d.ts +2 -0
  59. package/dist/core/shutdown.test.d.ts.map +1 -0
  60. package/dist/core/shutdown.test.js +524 -0
  61. package/dist/errors/checkpoint-errors.d.ts +30 -0
  62. package/dist/errors/checkpoint-errors.d.ts.map +1 -0
  63. package/dist/errors/checkpoint-errors.js +49 -0
  64. package/dist/errors/has-description.d.ts +18 -0
  65. package/dist/errors/has-description.d.ts.map +1 -0
  66. package/dist/errors/has-description.js +9 -0
  67. package/dist/errors/index.d.ts +6 -0
  68. package/dist/errors/index.d.ts.map +1 -0
  69. package/dist/errors/index.js +22 -0
  70. package/dist/errors/matador-errors.d.ts +183 -0
  71. package/dist/errors/matador-errors.d.ts.map +1 -0
  72. package/dist/errors/matador-errors.js +376 -0
  73. package/dist/errors/retry-errors.d.ts +102 -0
  74. package/dist/errors/retry-errors.d.ts.map +1 -0
  75. package/dist/errors/retry-errors.js +155 -0
  76. package/dist/errors/retry-errors.test.d.ts +2 -0
  77. package/dist/errors/retry-errors.test.d.ts.map +1 -0
  78. package/dist/errors/retry-errors.test.js +136 -0
  79. package/dist/hooks/index.d.ts +4 -0
  80. package/dist/hooks/index.d.ts.map +1 -0
  81. package/dist/hooks/index.js +2 -0
  82. package/dist/hooks/safe-hooks.d.ts +32 -0
  83. package/dist/hooks/safe-hooks.d.ts.map +1 -0
  84. package/dist/hooks/safe-hooks.js +120 -0
  85. package/dist/hooks/types.d.ts +172 -0
  86. package/dist/hooks/types.d.ts.map +1 -0
  87. package/dist/hooks/types.js +9 -0
  88. package/dist/index.cjs +3228 -0
  89. package/dist/index.cjs.map +1 -0
  90. package/dist/index.d.cts +23 -0
  91. package/dist/index.d.ts +23 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +31 -0
  94. package/dist/index.js.map +1 -0
  95. package/{src/pipeline/index.ts → dist/pipeline/index.d.ts} +1 -0
  96. package/dist/pipeline/index.d.ts.map +1 -0
  97. package/dist/pipeline/index.js +1 -0
  98. package/dist/pipeline/pipeline.d.ts +63 -0
  99. package/dist/pipeline/pipeline.d.ts.map +1 -0
  100. package/dist/pipeline/pipeline.js +273 -0
  101. package/dist/pipeline/pipeline.test.d.ts +2 -0
  102. package/dist/pipeline/pipeline.test.d.ts.map +1 -0
  103. package/dist/pipeline/pipeline.test.js +1112 -0
  104. package/{src/retry/index.ts → dist/retry/index.d.ts} +1 -1
  105. package/dist/retry/index.d.ts.map +1 -0
  106. package/dist/retry/index.js +1 -0
  107. package/dist/retry/policy.d.ts +43 -0
  108. package/dist/retry/policy.d.ts.map +1 -0
  109. package/dist/retry/policy.js +1 -0
  110. package/dist/retry/standard-policy.d.ts +44 -0
  111. package/dist/retry/standard-policy.d.ts.map +1 -0
  112. package/dist/retry/standard-policy.js +102 -0
  113. package/dist/retry/standard-policy.test.d.ts +2 -0
  114. package/dist/retry/standard-policy.test.d.ts.map +1 -0
  115. package/dist/retry/standard-policy.test.js +196 -0
  116. package/dist/schema/index.d.ts +4 -0
  117. package/dist/schema/index.d.ts.map +1 -0
  118. package/dist/schema/index.js +2 -0
  119. package/dist/schema/registry.d.ts +63 -0
  120. package/dist/schema/registry.d.ts.map +1 -0
  121. package/dist/schema/registry.js +174 -0
  122. package/dist/schema/registry.test.d.ts +2 -0
  123. package/dist/schema/registry.test.d.ts.map +1 -0
  124. package/dist/schema/registry.test.js +278 -0
  125. package/{src/schema/types.ts → dist/schema/types.d.ts} +29 -88
  126. package/dist/schema/types.d.ts.map +1 -0
  127. package/dist/schema/types.js +74 -0
  128. package/dist/schema/types.test.d.ts +2 -0
  129. package/dist/schema/types.test.d.ts.map +1 -0
  130. package/dist/schema/types.test.js +242 -0
  131. package/dist/topology/builder.d.ts +80 -0
  132. package/dist/topology/builder.d.ts.map +1 -0
  133. package/dist/topology/builder.js +165 -0
  134. package/dist/topology/builder.test.d.ts +2 -0
  135. package/dist/topology/builder.test.d.ts.map +1 -0
  136. package/dist/topology/builder.test.js +360 -0
  137. package/dist/topology/index.d.ts +5 -0
  138. package/dist/topology/index.d.ts.map +1 -0
  139. package/dist/topology/index.js +2 -0
  140. package/dist/topology/types.d.ts +128 -0
  141. package/dist/topology/types.d.ts.map +1 -0
  142. package/dist/topology/types.js +28 -0
  143. package/dist/transport/capabilities.d.ts +66 -0
  144. package/dist/transport/capabilities.d.ts.map +1 -0
  145. package/dist/transport/capabilities.js +18 -0
  146. package/dist/transport/connection-manager.d.ts +95 -0
  147. package/dist/transport/connection-manager.d.ts.map +1 -0
  148. package/dist/transport/connection-manager.js +144 -0
  149. package/dist/transport/index.d.ts +11 -0
  150. package/dist/transport/index.d.ts.map +1 -0
  151. package/dist/transport/index.js +5 -0
  152. package/dist/transport/local/local-transport.d.ts +62 -0
  153. package/dist/transport/local/local-transport.d.ts.map +1 -0
  154. package/dist/transport/local/local-transport.js +241 -0
  155. package/dist/transport/local/local-transport.test.d.ts +2 -0
  156. package/dist/transport/local/local-transport.test.d.ts.map +1 -0
  157. package/dist/transport/local/local-transport.test.js +192 -0
  158. package/dist/transport/multi/multi-transport.d.ts +94 -0
  159. package/dist/transport/multi/multi-transport.d.ts.map +1 -0
  160. package/dist/transport/multi/multi-transport.js +184 -0
  161. package/dist/transport/multi/multi-transport.test.d.ts +2 -0
  162. package/dist/transport/multi/multi-transport.test.d.ts.map +1 -0
  163. package/dist/transport/multi/multi-transport.test.js +236 -0
  164. package/dist/transport/rabbitmq/rabbitmq-transport.d.ts +83 -0
  165. package/dist/transport/rabbitmq/rabbitmq-transport.d.ts.map +1 -0
  166. package/dist/transport/rabbitmq/rabbitmq-transport.js +541 -0
  167. package/dist/transport/rabbitmq/rabbitmq-transport.test.d.ts +2 -0
  168. package/dist/transport/rabbitmq/rabbitmq-transport.test.d.ts.map +1 -0
  169. package/dist/transport/rabbitmq/rabbitmq-transport.test.js +100 -0
  170. package/dist/transport/transport.d.ts +152 -0
  171. package/dist/transport/transport.d.ts.map +1 -0
  172. package/dist/transport/transport.js +1 -0
  173. package/{src/types/common.ts → dist/types/common.d.ts} +8 -20
  174. package/dist/types/common.d.ts.map +1 -0
  175. package/dist/types/common.js +12 -0
  176. package/dist/types/dispatcher.d.ts +14 -0
  177. package/dist/types/dispatcher.d.ts.map +1 -0
  178. package/dist/types/dispatcher.js +1 -0
  179. package/dist/types/envelope.d.ts +131 -0
  180. package/dist/types/envelope.d.ts.map +1 -0
  181. package/dist/types/envelope.js +99 -0
  182. package/dist/types/event.d.ts +92 -0
  183. package/dist/types/event.d.ts.map +1 -0
  184. package/dist/types/event.js +26 -0
  185. package/dist/types/event.test.d.ts +2 -0
  186. package/dist/types/event.test.d.ts.map +1 -0
  187. package/dist/types/event.test.js +130 -0
  188. package/dist/types/index.d.ts +11 -0
  189. package/dist/types/index.d.ts.map +1 -0
  190. package/dist/types/index.js +4 -0
  191. package/dist/types/subscriber.d.ts +227 -0
  192. package/dist/types/subscriber.d.ts.map +1 -0
  193. package/dist/types/subscriber.js +97 -0
  194. package/package.json +6 -2
  195. package/examples/config.ts +0 -126
  196. package/examples/event.ts +0 -26
  197. package/examples/order-event.json +0 -19
  198. package/src/checkpoint/context.test.ts +0 -510
  199. package/src/checkpoint/context.ts +0 -213
  200. package/src/checkpoint/index.ts +0 -30
  201. package/src/checkpoint/stores/memory.ts +0 -47
  202. package/src/checkpoint/stores/stores.test.ts +0 -177
  203. package/src/checkpoint/types.ts +0 -147
  204. package/src/codec/codec.ts +0 -42
  205. package/src/codec/header-aware-codec.ts +0 -41
  206. package/src/codec/json-codec.ts +0 -69
  207. package/src/codec/rabbitmq-codec.test.ts +0 -516
  208. package/src/codec/rabbitmq-codec.ts +0 -336
  209. package/src/core/fanout.test.ts +0 -1350
  210. package/src/core/fanout.ts +0 -184
  211. package/src/core/matador.test.ts +0 -575
  212. package/src/core/matador.ts +0 -357
  213. package/src/core/shutdown.test.ts +0 -853
  214. package/src/core/shutdown.ts +0 -165
  215. package/src/errors/checkpoint-errors.ts +0 -62
  216. package/src/errors/has-description.ts +0 -25
  217. package/src/errors/index.ts +0 -58
  218. package/src/errors/matador-errors.ts +0 -477
  219. package/src/errors/retry-errors.test.ts +0 -175
  220. package/src/errors/retry-errors.ts +0 -188
  221. package/src/hooks/index.ts +0 -14
  222. package/src/hooks/safe-hooks.ts +0 -200
  223. package/src/hooks/types.ts +0 -226
  224. package/src/index.ts +0 -242
  225. package/src/pipeline/pipeline.test.ts +0 -1377
  226. package/src/pipeline/pipeline.ts +0 -393
  227. package/src/retry/policy.ts +0 -46
  228. package/src/retry/standard-policy.test.ts +0 -290
  229. package/src/retry/standard-policy.ts +0 -156
  230. package/src/schema/index.ts +0 -16
  231. package/src/schema/registry.test.ts +0 -339
  232. package/src/schema/registry.ts +0 -229
  233. package/src/schema/types.test.ts +0 -280
  234. package/src/topology/builder.test.ts +0 -451
  235. package/src/topology/builder.ts +0 -238
  236. package/src/topology/index.ts +0 -19
  237. package/src/topology/types.ts +0 -183
  238. package/src/transport/capabilities.ts +0 -88
  239. package/src/transport/connection-manager.ts +0 -218
  240. package/src/transport/index.ts +0 -42
  241. package/src/transport/local/local-transport.test.ts +0 -262
  242. package/src/transport/local/local-transport.ts +0 -330
  243. package/src/transport/multi/multi-transport.test.ts +0 -320
  244. package/src/transport/multi/multi-transport.ts +0 -294
  245. package/src/transport/rabbitmq/rabbitmq-transport.test.ts +0 -120
  246. package/src/transport/rabbitmq/rabbitmq-transport.ts +0 -782
  247. package/src/transport/transport.ts +0 -200
  248. package/src/types/dispatcher.ts +0 -18
  249. package/src/types/envelope.ts +0 -244
  250. package/src/types/event.test.ts +0 -157
  251. package/src/types/event.ts +0 -112
  252. package/src/types/index.ts +0 -62
  253. package/src/types/subscriber.ts +0 -333
  254. package/test/e2e/multi-transport.e2e.test.ts +0 -237
  255. package/test/e2e/rabbitmq-transport.e2e.test.ts +0 -618
  256. package/test/e2e/transport-compliance.e2e.test.ts +0 -506
  257. package/test/integration/matador.integration.test.ts +0 -634
  258. package/tsconfig.json +0 -29
  259. package/tsup.config.ts +0 -13
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Connection state machine states.
3
+ */
4
+ export type ConnectionState = {
5
+ readonly status: 'disconnected';
6
+ } | {
7
+ readonly status: 'connecting';
8
+ readonly attempt: number;
9
+ } | {
10
+ readonly status: 'connected';
11
+ } | {
12
+ readonly status: 'reconnecting';
13
+ readonly attempt: number;
14
+ readonly lastError: Error;
15
+ } | {
16
+ readonly status: 'failed';
17
+ readonly error: Error;
18
+ };
19
+ /**
20
+ * Configuration for the connection manager.
21
+ */
22
+ export interface ConnectionManagerConfig {
23
+ /** Maximum reconnection attempts before giving up (0 = infinite) */
24
+ readonly maxReconnectAttempts: number;
25
+ /** Initial delay between reconnection attempts (ms) */
26
+ readonly initialReconnectDelay: number;
27
+ /** Maximum delay between reconnection attempts (ms) */
28
+ readonly maxReconnectDelay: number;
29
+ /** Backoff multiplier for reconnection delay */
30
+ readonly backoffMultiplier: number;
31
+ /** Heartbeat interval for connection health (ms), optional */
32
+ readonly heartbeatInterval?: number;
33
+ }
34
+ /**
35
+ * Default configuration values.
36
+ */
37
+ export declare const defaultConnectionConfig: ConnectionManagerConfig;
38
+ /**
39
+ * Callback for state change notifications.
40
+ */
41
+ export type StateChangeCallback = (state: ConnectionState) => void;
42
+ /**
43
+ * Function that performs the actual connection.
44
+ */
45
+ export type ConnectFn = () => Promise<void>;
46
+ /**
47
+ * Function that performs disconnection.
48
+ */
49
+ export type DisconnectFn = () => Promise<void>;
50
+ /**
51
+ * Manages connection lifecycle with automatic reconnection.
52
+ */
53
+ export declare class ConnectionManager {
54
+ private readonly connectFn;
55
+ private readonly disconnectFn;
56
+ private _state;
57
+ private readonly listeners;
58
+ private reconnectTimer;
59
+ private readonly config;
60
+ constructor(connectFn: ConnectFn, disconnectFn: DisconnectFn, config?: Partial<ConnectionManagerConfig>);
61
+ /**
62
+ * Current connection state.
63
+ */
64
+ get state(): ConnectionState;
65
+ /**
66
+ * Whether currently connected.
67
+ */
68
+ isConnected(): boolean;
69
+ /**
70
+ * Register a callback for connection state changes.
71
+ */
72
+ onStateChange(callback: StateChangeCallback): () => void;
73
+ /**
74
+ * Attempt to establish connection.
75
+ */
76
+ connect(): Promise<void>;
77
+ /**
78
+ * Gracefully disconnect.
79
+ */
80
+ disconnect(): Promise<void>;
81
+ /**
82
+ * Called by transport when connection is lost unexpectedly.
83
+ */
84
+ handleConnectionLost(error: Error): Promise<void>;
85
+ /**
86
+ * Calculate delay for a given attempt using exponential backoff.
87
+ */
88
+ calculateDelay(attempt: number): number;
89
+ private setState;
90
+ private handleConnectionFailure;
91
+ private shouldGiveUp;
92
+ private attemptReconnect;
93
+ private clearReconnectTimer;
94
+ }
95
+ //# sourceMappingURL=connection-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../src/transport/connection-manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;CAAE,GACnC;IAAE,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAChC;IACE,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;CAC3B,GACD;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IAEtC,uDAAuD;IACvD,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IAEvC,uDAAuD;IACvD,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IAEnC,gDAAgD;IAChD,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IAEnC,8DAA8D;IAC9D,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,uBAKrC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;AAE5C;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;AAE/C;;GAEG;AACH,qBAAa,iBAAiB;IAO1B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAP/B,OAAO,CAAC,MAAM,CAA+C;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;gBAG9B,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,YAAY,EAC3C,MAAM,GAAE,OAAO,CAAC,uBAAuB,CAAM;IAK/C;;OAEG;IACH,IAAI,KAAK,IAAI,eAAe,CAE3B;IAED;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,IAAI;IAKxD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB9B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAcjC;;OAEG;IACG,oBAAoB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IASvD;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAOvC,OAAO,CAAC,QAAQ;YAWF,uBAAuB;IAiBrC,OAAO,CAAC,YAAY;YAON,gBAAgB;IAoB9B,OAAO,CAAC,mBAAmB;CAM5B"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Default configuration values.
3
+ */
4
+ export const defaultConnectionConfig = {
5
+ maxReconnectAttempts: 0, // Infinite
6
+ initialReconnectDelay: 1000,
7
+ maxReconnectDelay: 30000,
8
+ backoffMultiplier: 2,
9
+ };
10
+ /**
11
+ * Manages connection lifecycle with automatic reconnection.
12
+ */
13
+ export class ConnectionManager {
14
+ connectFn;
15
+ disconnectFn;
16
+ _state = { status: 'disconnected' };
17
+ listeners = new Set();
18
+ reconnectTimer = null;
19
+ config;
20
+ constructor(connectFn, disconnectFn, config = {}) {
21
+ this.connectFn = connectFn;
22
+ this.disconnectFn = disconnectFn;
23
+ this.config = { ...defaultConnectionConfig, ...config };
24
+ }
25
+ /**
26
+ * Current connection state.
27
+ */
28
+ get state() {
29
+ return this._state;
30
+ }
31
+ /**
32
+ * Whether currently connected.
33
+ */
34
+ isConnected() {
35
+ return this._state.status === 'connected';
36
+ }
37
+ /**
38
+ * Register a callback for connection state changes.
39
+ */
40
+ onStateChange(callback) {
41
+ this.listeners.add(callback);
42
+ return () => this.listeners.delete(callback);
43
+ }
44
+ /**
45
+ * Attempt to establish connection.
46
+ */
47
+ async connect() {
48
+ if (this._state.status === 'connected') {
49
+ return;
50
+ }
51
+ this.setState({ status: 'connecting', attempt: 1 });
52
+ try {
53
+ await this.connectFn();
54
+ this.setState({ status: 'connected' });
55
+ }
56
+ catch (error) {
57
+ const err = error instanceof Error ? error : new Error(String(error));
58
+ await this.handleConnectionFailure(err, 1);
59
+ }
60
+ }
61
+ /**
62
+ * Gracefully disconnect.
63
+ */
64
+ async disconnect() {
65
+ this.clearReconnectTimer();
66
+ if (this._state.status === 'disconnected') {
67
+ return;
68
+ }
69
+ try {
70
+ await this.disconnectFn();
71
+ }
72
+ finally {
73
+ this.setState({ status: 'disconnected' });
74
+ }
75
+ }
76
+ /**
77
+ * Called by transport when connection is lost unexpectedly.
78
+ */
79
+ async handleConnectionLost(error) {
80
+ if (this._state.status === 'disconnected') {
81
+ return;
82
+ }
83
+ this.setState({ status: 'reconnecting', attempt: 1, lastError: error });
84
+ await this.attemptReconnect(1);
85
+ }
86
+ /**
87
+ * Calculate delay for a given attempt using exponential backoff.
88
+ */
89
+ calculateDelay(attempt) {
90
+ const delay = this.config.initialReconnectDelay *
91
+ Math.pow(this.config.backoffMultiplier, attempt - 1);
92
+ return Math.min(delay, this.config.maxReconnectDelay);
93
+ }
94
+ setState(state) {
95
+ this._state = state;
96
+ for (const listener of this.listeners) {
97
+ try {
98
+ listener(state);
99
+ }
100
+ catch {
101
+ // Ignore listener errors
102
+ }
103
+ }
104
+ }
105
+ async handleConnectionFailure(error, attempt) {
106
+ if (this.shouldGiveUp(attempt)) {
107
+ this.setState({ status: 'failed', error });
108
+ throw error;
109
+ }
110
+ this.setState({
111
+ status: 'reconnecting',
112
+ attempt: attempt + 1,
113
+ lastError: error,
114
+ });
115
+ await this.attemptReconnect(attempt + 1);
116
+ }
117
+ shouldGiveUp(attempt) {
118
+ return (this.config.maxReconnectAttempts > 0 &&
119
+ attempt >= this.config.maxReconnectAttempts);
120
+ }
121
+ async attemptReconnect(attempt) {
122
+ const delay = this.calculateDelay(attempt);
123
+ await new Promise((resolve) => {
124
+ this.reconnectTimer = setTimeout(resolve, delay);
125
+ });
126
+ if (this._state.status === 'disconnected') {
127
+ return;
128
+ }
129
+ try {
130
+ await this.connectFn();
131
+ this.setState({ status: 'connected' });
132
+ }
133
+ catch (error) {
134
+ const err = error instanceof Error ? error : new Error(String(error));
135
+ await this.handleConnectionFailure(err, attempt);
136
+ }
137
+ }
138
+ clearReconnectTimer() {
139
+ if (this.reconnectTimer !== null) {
140
+ clearTimeout(this.reconnectTimer);
141
+ this.reconnectTimer = null;
142
+ }
143
+ }
144
+ }
@@ -0,0 +1,11 @@
1
+ export type { TransportCapabilities } from './capabilities.js';
2
+ export { hasNativeDeadLetter, supportsDeliveryMode, supportsDelayedMessages, } from './capabilities.js';
3
+ export type { MessageHandler, MessageReceipt, RabbitMQSendOptions, RabbitMQSubscribeOptions, SendOptions, SubscribeOptions, Subscription, Transport, TransportSendOptions, TransportSubscribeOptions, } from './transport.js';
4
+ export type { ConnectFn, ConnectionManagerConfig, ConnectionState, DisconnectFn, StateChangeCallback, } from './connection-manager.js';
5
+ export { ConnectionManager, defaultConnectionConfig, } from './connection-manager.js';
6
+ export { LocalTransport } from './local/local-transport.js';
7
+ export type { MultiTransportConfig, MultiTransportHooks, } from './multi/multi-transport.js';
8
+ export { MultiTransport } from './multi/multi-transport.js';
9
+ export type { RabbitMQTransportConfig } from './rabbitmq/rabbitmq-transport.js';
10
+ export { RabbitMQTransport } from './rabbitmq/rabbitmq-transport.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,SAAS,EACT,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,SAAS,EACT,uBAAuB,EACvB,eAAe,EACf,YAAY,EACZ,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,YAAY,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,YAAY,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { hasNativeDeadLetter, supportsDeliveryMode, supportsDelayedMessages, } from './capabilities.js';
2
+ export { ConnectionManager, defaultConnectionConfig, } from './connection-manager.js';
3
+ export { LocalTransport } from './local/local-transport.js';
4
+ export { MultiTransport } from './multi/multi-transport.js';
5
+ export { RabbitMQTransport } from './rabbitmq/rabbitmq-transport.js';
@@ -0,0 +1,62 @@
1
+ import { type Logger } from '../../hooks/index.js';
2
+ import type { Topology } from '../../topology/types.js';
3
+ import type { Envelope } from '../../types/index.js';
4
+ import type { TransportCapabilities } from '../capabilities.js';
5
+ import type { MessageHandler, MessageReceipt, SendOptions, SubscribeOptions, Subscription, Transport } from '../transport.js';
6
+ /**
7
+ * Local in-memory transport for testing and fallback.
8
+ * Messages are stored in memory and delivered synchronously.
9
+ */
10
+ export declare class LocalTransport implements Transport {
11
+ readonly name = "local";
12
+ readonly capabilities: TransportCapabilities;
13
+ private connected;
14
+ private readonly queues;
15
+ private readonly subscriptions;
16
+ private readonly completedMessages;
17
+ private readonly delayedTimers;
18
+ private messageIdCounter;
19
+ private readonly logger;
20
+ constructor(logger?: Logger);
21
+ connect(): Promise<void>;
22
+ disconnect(): Promise<void>;
23
+ isConnected(): boolean;
24
+ applyTopology(topology: Topology): Promise<void>;
25
+ send(queue: string, envelope: Envelope, options?: SendOptions): Promise<Transport['name']>;
26
+ /**
27
+ * Schedules a message for delayed delivery.
28
+ * Returns immediately (non-blocking) to match real transport behavior.
29
+ */
30
+ private scheduleDelayedMessage;
31
+ private enqueue;
32
+ private deliverToSubscribers;
33
+ subscribe(queue: string, handler: MessageHandler, options?: SubscribeOptions): Promise<Subscription>;
34
+ complete(receipt: MessageReceipt): Promise<void>;
35
+ sendToDeadLetter(receipt: MessageReceipt, dlqName: string, envelope: Envelope, _reason: string): Promise<void>;
36
+ /**
37
+ * Gets the current size of a queue.
38
+ */
39
+ getQueueSize(queue: string): number;
40
+ /**
41
+ * Gets all completed message receipts.
42
+ */
43
+ getCompleted(): readonly MessageReceipt[];
44
+ /**
45
+ * Gets pending (uncompleted) messages from a queue.
46
+ */
47
+ getPendingMessages(queue: string): readonly Envelope[];
48
+ /**
49
+ * Clears all state (for test isolation).
50
+ */
51
+ clear(): void;
52
+ /**
53
+ * Receives one message from the queue without a subscription.
54
+ * Useful for testing.
55
+ */
56
+ receiveOne(queue: string): Promise<{
57
+ envelope: Envelope;
58
+ receipt: MessageReceipt;
59
+ } | null>;
60
+ private getOrCreateQueue;
61
+ }
62
+ //# sourceMappingURL=local-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-transport.d.ts","sourceRoot":"","sources":["../../../src/transport/local/local-transport.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,SAAS,EACV,MAAM,iBAAiB,CAAC;AAiCzB;;;GAGG;AACH,qBAAa,cAAe,YAAW,SAAS;IAC9C,QAAQ,CAAC,IAAI,WAAW;IACxB,QAAQ,CAAC,YAAY,wBAAqB;IAE1C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsC;IAC7D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA2C;IACzE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAwB;IAC1D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4C;IAC1E,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,MAAM,CAAC,EAAE,MAAM;IAIrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBjC,WAAW,IAAI,OAAO;IAIhB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBhD,IAAI,CACR,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAe7B;;;OAGG;IACH,OAAO,CAAC,sBAAsB;YAkBhB,OAAO;YAgBP,oBAAoB;IA+B5B,SAAS,CACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,YAAY,CAAC;IAsClB,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhD,gBAAgB,CACpB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC;IAQhB;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAMnC;;OAEG;IACH,YAAY,IAAI,SAAS,cAAc,EAAE;IAIzC;;OAEG;IACH,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,QAAQ,EAAE;IAMtD;;OAEG;IACH,KAAK,IAAI,IAAI;IAYb;;;OAGG;IACG,UAAU,CACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,OAAO,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI,CAAC;IAmBlE,OAAO,CAAC,gBAAgB;CAQzB"}
@@ -0,0 +1,241 @@
1
+ import { TransportNotConnectedError } from '../../errors/index.js';
2
+ import { consoleLogger } from '../../hooks/index.js';
3
+ /**
4
+ * Capabilities of the LocalTransport.
5
+ */
6
+ const localCapabilities = {
7
+ deliveryModes: ['at-least-once', 'at-most-once'],
8
+ delayedMessages: true, // Implemented with setTimeout
9
+ deadLetterRouting: 'manual',
10
+ attemptTracking: false,
11
+ concurrencyModel: 'none',
12
+ ordering: 'queue',
13
+ priorities: false,
14
+ };
15
+ /**
16
+ * Local in-memory transport for testing and fallback.
17
+ * Messages are stored in memory and delivered synchronously.
18
+ */
19
+ export class LocalTransport {
20
+ name = 'local';
21
+ capabilities = localCapabilities;
22
+ connected = false;
23
+ queues = new Map();
24
+ subscriptions = new Map();
25
+ completedMessages = [];
26
+ delayedTimers = new Set();
27
+ messageIdCounter = 0;
28
+ logger;
29
+ constructor(logger) {
30
+ this.logger = logger ?? consoleLogger;
31
+ }
32
+ async connect() {
33
+ this.connected = true;
34
+ }
35
+ async disconnect() {
36
+ // Cancel all delayed message timers
37
+ for (const timer of this.delayedTimers) {
38
+ clearTimeout(timer);
39
+ }
40
+ this.delayedTimers.clear();
41
+ // Deactivate all subscriptions
42
+ for (const subs of this.subscriptions.values()) {
43
+ for (const sub of subs) {
44
+ sub.active = false;
45
+ }
46
+ }
47
+ this.connected = false;
48
+ }
49
+ isConnected() {
50
+ return this.connected;
51
+ }
52
+ async applyTopology(topology) {
53
+ if (!this.connected) {
54
+ throw new TransportNotConnectedError(this.name, 'applyTopology');
55
+ }
56
+ // Initialize queues for the topology.
57
+ // Note: Retry queues are not pre-created here because LocalTransport handles
58
+ // retries by re-enqueueing messages with a delay to the original queue, matching
59
+ // how the pipeline schedules retries via transport.send() with a delay option.
60
+ for (const queueDef of topology.queues) {
61
+ const queueName = `${topology.namespace}.${queueDef.name}`;
62
+ if (!this.queues.has(queueName)) {
63
+ this.queues.set(queueName, []);
64
+ }
65
+ }
66
+ }
67
+ async send(queue, envelope, options) {
68
+ if (!this.connected) {
69
+ throw new TransportNotConnectedError(this.name, 'send');
70
+ }
71
+ // Handle delayed messages (non-blocking, like real transports)
72
+ if (options?.delay !== undefined && options.delay > 0) {
73
+ this.scheduleDelayedMessage(queue, envelope, options.delay);
74
+ return this.name;
75
+ }
76
+ await this.enqueue(queue, envelope);
77
+ return this.name;
78
+ }
79
+ /**
80
+ * Schedules a message for delayed delivery.
81
+ * Returns immediately (non-blocking) to match real transport behavior.
82
+ */
83
+ scheduleDelayedMessage(queue, envelope, delayMs) {
84
+ const timer = setTimeout(() => {
85
+ this.delayedTimers.delete(timer);
86
+ // Fire and forget - errors are logged in enqueue/deliverToSubscribers
87
+ this.enqueue(queue, envelope).catch((error) => {
88
+ this.logger.error('[Matador] 🔴 Failed to enqueue delayed message', error);
89
+ });
90
+ }, delayMs);
91
+ this.delayedTimers.add(timer);
92
+ }
93
+ async enqueue(queue, envelope) {
94
+ const messages = this.getOrCreateQueue(queue);
95
+ const messageId = `${++this.messageIdCounter}`;
96
+ const queuedMessage = {
97
+ envelope,
98
+ id: messageId,
99
+ completed: false,
100
+ };
101
+ messages.push(queuedMessage);
102
+ // Deliver to any active subscriptions
103
+ await this.deliverToSubscribers(queue, queuedMessage);
104
+ }
105
+ async deliverToSubscribers(queue, message) {
106
+ const subs = this.subscriptions.get(queue);
107
+ if (!subs)
108
+ return;
109
+ for (const sub of subs) {
110
+ if (!sub.active || message.completed)
111
+ continue;
112
+ const receipt = {
113
+ handle: message,
114
+ redelivered: false,
115
+ attemptNumber: message.envelope.docket.attempts,
116
+ deliveryCount: message.envelope.docket.attempts,
117
+ sourceQueue: queue,
118
+ sourceTransport: this.name,
119
+ };
120
+ try {
121
+ await sub.handler(message.envelope, receipt);
122
+ }
123
+ catch (error) {
124
+ // Handler errors should be caught in the pipeline
125
+ this.logger.error('[Matador] 🔴 Handler error in message processing', error);
126
+ }
127
+ }
128
+ }
129
+ async subscribe(queue, handler, options = {}) {
130
+ if (!this.connected) {
131
+ throw new TransportNotConnectedError(this.name, 'subscribe');
132
+ }
133
+ const subscription = {
134
+ handler,
135
+ options,
136
+ active: true,
137
+ };
138
+ const subs = this.subscriptions.get(queue) ?? [];
139
+ subs.push(subscription);
140
+ this.subscriptions.set(queue, subs);
141
+ // Deliver any pending messages
142
+ const messages = this.queues.get(queue) ?? [];
143
+ for (const message of messages) {
144
+ if (message.completed)
145
+ continue;
146
+ await this.deliverToSubscribers(queue, message);
147
+ }
148
+ return {
149
+ unsubscribe: async () => {
150
+ subscription.active = false;
151
+ const remaining = subs.filter((s) => s !== subscription);
152
+ if (remaining.length > 0) {
153
+ this.subscriptions.set(queue, remaining);
154
+ }
155
+ else {
156
+ this.subscriptions.delete(queue);
157
+ }
158
+ },
159
+ get isActive() {
160
+ return subscription.active;
161
+ },
162
+ };
163
+ }
164
+ async complete(receipt) {
165
+ const message = receipt.handle;
166
+ message.completed = true;
167
+ this.completedMessages.push(receipt);
168
+ }
169
+ async sendToDeadLetter(receipt, dlqName, envelope, _reason) {
170
+ const dlqQueueName = `${receipt.sourceQueue}.${dlqName}`;
171
+ await this.enqueue(dlqQueueName, envelope);
172
+ await this.complete(receipt);
173
+ }
174
+ // Test helpers
175
+ /**
176
+ * Gets the current size of a queue.
177
+ */
178
+ getQueueSize(queue) {
179
+ const messages = this.queues.get(queue);
180
+ if (!messages)
181
+ return 0;
182
+ return messages.filter((m) => !m.completed).length;
183
+ }
184
+ /**
185
+ * Gets all completed message receipts.
186
+ */
187
+ getCompleted() {
188
+ return this.completedMessages;
189
+ }
190
+ /**
191
+ * Gets pending (uncompleted) messages from a queue.
192
+ */
193
+ getPendingMessages(queue) {
194
+ const messages = this.queues.get(queue);
195
+ if (!messages)
196
+ return [];
197
+ return messages.filter((m) => !m.completed).map((m) => m.envelope);
198
+ }
199
+ /**
200
+ * Clears all state (for test isolation).
201
+ */
202
+ clear() {
203
+ this.queues.clear();
204
+ this.subscriptions.clear();
205
+ this.completedMessages.length = 0;
206
+ this.messageIdCounter = 0;
207
+ for (const timer of this.delayedTimers) {
208
+ clearTimeout(timer);
209
+ }
210
+ this.delayedTimers.clear();
211
+ }
212
+ /**
213
+ * Receives one message from the queue without a subscription.
214
+ * Useful for testing.
215
+ */
216
+ async receiveOne(queue) {
217
+ const messages = this.queues.get(queue);
218
+ if (!messages)
219
+ return null;
220
+ const pending = messages.find((m) => !m.completed);
221
+ if (!pending)
222
+ return null;
223
+ const receipt = {
224
+ handle: pending,
225
+ redelivered: false,
226
+ attemptNumber: pending.envelope.docket.attempts,
227
+ deliveryCount: pending.envelope.docket.attempts,
228
+ sourceQueue: queue,
229
+ sourceTransport: this.name,
230
+ };
231
+ return { envelope: pending.envelope, receipt };
232
+ }
233
+ getOrCreateQueue(queue) {
234
+ let messages = this.queues.get(queue);
235
+ if (!messages) {
236
+ messages = [];
237
+ this.queues.set(queue, messages);
238
+ }
239
+ return messages;
240
+ }
241
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=local-transport.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-transport.test.d.ts","sourceRoot":"","sources":["../../../src/transport/local/local-transport.test.ts"],"names":[],"mappings":""}