@zdavison/matador 2.0.7 → 2.0.9

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 (200) hide show
  1. package/package.json +3 -2
  2. package/src/hooks/safe-hooks.ts +0 -16
  3. package/src/hooks/types.ts +0 -7
  4. package/src/index.ts +1 -0
  5. package/src/types/event.ts +8 -14
  6. package/src/types/index.ts +3 -2
  7. package/dist/checkpoint/context.d.ts +0 -59
  8. package/dist/checkpoint/context.d.ts.map +0 -1
  9. package/dist/checkpoint/context.js +0 -140
  10. package/dist/checkpoint/context.test.d.ts +0 -2
  11. package/dist/checkpoint/context.test.d.ts.map +0 -1
  12. package/dist/checkpoint/context.test.js +0 -424
  13. package/dist/checkpoint/index.d.ts +0 -7
  14. package/dist/checkpoint/index.d.ts.map +0 -1
  15. package/dist/checkpoint/index.js +0 -6
  16. package/dist/checkpoint/stores/memory.d.ts +0 -29
  17. package/dist/checkpoint/stores/memory.d.ts.map +0 -1
  18. package/dist/checkpoint/stores/memory.js +0 -39
  19. package/dist/checkpoint/stores/noop.d.ts +0 -14
  20. package/dist/checkpoint/stores/noop.d.ts.map +0 -1
  21. package/dist/checkpoint/stores/noop.js +0 -18
  22. package/dist/checkpoint/stores/stores.test.d.ts +0 -2
  23. package/dist/checkpoint/stores/stores.test.d.ts.map +0 -1
  24. package/dist/checkpoint/stores/stores.test.js +0 -146
  25. package/dist/checkpoint/types.d.ts +0 -119
  26. package/dist/checkpoint/types.d.ts.map +0 -1
  27. package/dist/checkpoint/types.js +0 -1
  28. package/dist/codec/codec.d.ts +0 -29
  29. package/dist/codec/codec.d.ts.map +0 -1
  30. package/dist/codec/codec.js +0 -15
  31. package/dist/codec/header-aware-codec.d.ts +0 -36
  32. package/dist/codec/header-aware-codec.d.ts.map +0 -1
  33. package/dist/codec/header-aware-codec.js +0 -1
  34. package/dist/codec/index.d.ts +0 -6
  35. package/dist/codec/index.d.ts.map +0 -1
  36. package/dist/codec/index.js +0 -3
  37. package/dist/codec/json-codec.d.ts +0 -13
  38. package/dist/codec/json-codec.d.ts.map +0 -1
  39. package/dist/codec/json-codec.js +0 -64
  40. package/dist/codec/rabbitmq-codec.d.ts +0 -28
  41. package/dist/codec/rabbitmq-codec.d.ts.map +0 -1
  42. package/dist/codec/rabbitmq-codec.js +0 -242
  43. package/dist/codec/rabbitmq-codec.test.d.ts +0 -2
  44. package/dist/codec/rabbitmq-codec.test.d.ts.map +0 -1
  45. package/dist/codec/rabbitmq-codec.test.js +0 -433
  46. package/dist/core/fanout.d.ts +0 -59
  47. package/dist/core/fanout.d.ts.map +0 -1
  48. package/dist/core/fanout.js +0 -121
  49. package/dist/core/fanout.test.d.ts +0 -2
  50. package/dist/core/fanout.test.d.ts.map +0 -1
  51. package/dist/core/fanout.test.js +0 -1054
  52. package/dist/core/index.d.ts +0 -7
  53. package/dist/core/index.d.ts.map +0 -1
  54. package/dist/core/index.js +0 -3
  55. package/dist/core/matador.d.ts +0 -133
  56. package/dist/core/matador.d.ts.map +0 -1
  57. package/dist/core/matador.js +0 -228
  58. package/dist/core/matador.test.d.ts +0 -2
  59. package/dist/core/matador.test.d.ts.map +0 -1
  60. package/dist/core/matador.test.js +0 -446
  61. package/dist/core/shutdown.d.ts +0 -78
  62. package/dist/core/shutdown.d.ts.map +0 -1
  63. package/dist/core/shutdown.js +0 -111
  64. package/dist/core/shutdown.test.d.ts +0 -2
  65. package/dist/core/shutdown.test.d.ts.map +0 -1
  66. package/dist/core/shutdown.test.js +0 -524
  67. package/dist/errors/checkpoint-errors.d.ts +0 -30
  68. package/dist/errors/checkpoint-errors.d.ts.map +0 -1
  69. package/dist/errors/checkpoint-errors.js +0 -49
  70. package/dist/errors/has-description.d.ts +0 -18
  71. package/dist/errors/has-description.d.ts.map +0 -1
  72. package/dist/errors/has-description.js +0 -9
  73. package/dist/errors/index.d.ts +0 -6
  74. package/dist/errors/index.d.ts.map +0 -1
  75. package/dist/errors/index.js +0 -22
  76. package/dist/errors/matador-errors.d.ts +0 -183
  77. package/dist/errors/matador-errors.d.ts.map +0 -1
  78. package/dist/errors/matador-errors.js +0 -376
  79. package/dist/errors/retry-errors.d.ts +0 -102
  80. package/dist/errors/retry-errors.d.ts.map +0 -1
  81. package/dist/errors/retry-errors.js +0 -155
  82. package/dist/errors/retry-errors.test.d.ts +0 -2
  83. package/dist/errors/retry-errors.test.d.ts.map +0 -1
  84. package/dist/errors/retry-errors.test.js +0 -136
  85. package/dist/hooks/index.d.ts +0 -4
  86. package/dist/hooks/index.d.ts.map +0 -1
  87. package/dist/hooks/index.js +0 -2
  88. package/dist/hooks/safe-hooks.d.ts +0 -33
  89. package/dist/hooks/safe-hooks.d.ts.map +0 -1
  90. package/dist/hooks/safe-hooks.js +0 -132
  91. package/dist/hooks/types.d.ts +0 -176
  92. package/dist/hooks/types.d.ts.map +0 -1
  93. package/dist/hooks/types.js +0 -9
  94. package/dist/index.cjs +0 -3242
  95. package/dist/index.cjs.map +0 -1
  96. package/dist/index.d.cts +0 -23
  97. package/dist/index.d.ts +0 -23
  98. package/dist/index.d.ts.map +0 -1
  99. package/dist/index.js +0 -31
  100. package/dist/index.js.map +0 -1
  101. package/dist/pipeline/index.d.ts +0 -3
  102. package/dist/pipeline/index.d.ts.map +0 -1
  103. package/dist/pipeline/index.js +0 -1
  104. package/dist/pipeline/pipeline.d.ts +0 -63
  105. package/dist/pipeline/pipeline.d.ts.map +0 -1
  106. package/dist/pipeline/pipeline.js +0 -273
  107. package/dist/pipeline/pipeline.test.d.ts +0 -2
  108. package/dist/pipeline/pipeline.test.d.ts.map +0 -1
  109. package/dist/pipeline/pipeline.test.js +0 -1112
  110. package/dist/retry/index.d.ts +0 -4
  111. package/dist/retry/index.d.ts.map +0 -1
  112. package/dist/retry/index.js +0 -1
  113. package/dist/retry/policy.d.ts +0 -43
  114. package/dist/retry/policy.d.ts.map +0 -1
  115. package/dist/retry/policy.js +0 -1
  116. package/dist/retry/standard-policy.d.ts +0 -44
  117. package/dist/retry/standard-policy.d.ts.map +0 -1
  118. package/dist/retry/standard-policy.js +0 -102
  119. package/dist/retry/standard-policy.test.d.ts +0 -2
  120. package/dist/retry/standard-policy.test.d.ts.map +0 -1
  121. package/dist/retry/standard-policy.test.js +0 -196
  122. package/dist/schema/index.d.ts +0 -4
  123. package/dist/schema/index.d.ts.map +0 -1
  124. package/dist/schema/index.js +0 -2
  125. package/dist/schema/registry.d.ts +0 -63
  126. package/dist/schema/registry.d.ts.map +0 -1
  127. package/dist/schema/registry.js +0 -174
  128. package/dist/schema/registry.test.d.ts +0 -2
  129. package/dist/schema/registry.test.d.ts.map +0 -1
  130. package/dist/schema/registry.test.js +0 -278
  131. package/dist/schema/types.d.ts +0 -158
  132. package/dist/schema/types.d.ts.map +0 -1
  133. package/dist/schema/types.js +0 -74
  134. package/dist/schema/types.test.d.ts +0 -2
  135. package/dist/schema/types.test.d.ts.map +0 -1
  136. package/dist/schema/types.test.js +0 -242
  137. package/dist/topology/builder.d.ts +0 -80
  138. package/dist/topology/builder.d.ts.map +0 -1
  139. package/dist/topology/builder.js +0 -165
  140. package/dist/topology/builder.test.d.ts +0 -2
  141. package/dist/topology/builder.test.d.ts.map +0 -1
  142. package/dist/topology/builder.test.js +0 -360
  143. package/dist/topology/index.d.ts +0 -5
  144. package/dist/topology/index.d.ts.map +0 -1
  145. package/dist/topology/index.js +0 -2
  146. package/dist/topology/types.d.ts +0 -128
  147. package/dist/topology/types.d.ts.map +0 -1
  148. package/dist/topology/types.js +0 -28
  149. package/dist/transport/capabilities.d.ts +0 -66
  150. package/dist/transport/capabilities.d.ts.map +0 -1
  151. package/dist/transport/capabilities.js +0 -18
  152. package/dist/transport/connection-manager.d.ts +0 -95
  153. package/dist/transport/connection-manager.d.ts.map +0 -1
  154. package/dist/transport/connection-manager.js +0 -144
  155. package/dist/transport/index.d.ts +0 -11
  156. package/dist/transport/index.d.ts.map +0 -1
  157. package/dist/transport/index.js +0 -5
  158. package/dist/transport/local/local-transport.d.ts +0 -62
  159. package/dist/transport/local/local-transport.d.ts.map +0 -1
  160. package/dist/transport/local/local-transport.js +0 -241
  161. package/dist/transport/local/local-transport.test.d.ts +0 -2
  162. package/dist/transport/local/local-transport.test.d.ts.map +0 -1
  163. package/dist/transport/local/local-transport.test.js +0 -192
  164. package/dist/transport/multi/multi-transport.d.ts +0 -94
  165. package/dist/transport/multi/multi-transport.d.ts.map +0 -1
  166. package/dist/transport/multi/multi-transport.js +0 -184
  167. package/dist/transport/multi/multi-transport.test.d.ts +0 -2
  168. package/dist/transport/multi/multi-transport.test.d.ts.map +0 -1
  169. package/dist/transport/multi/multi-transport.test.js +0 -236
  170. package/dist/transport/rabbitmq/rabbitmq-transport.d.ts +0 -83
  171. package/dist/transport/rabbitmq/rabbitmq-transport.d.ts.map +0 -1
  172. package/dist/transport/rabbitmq/rabbitmq-transport.js +0 -541
  173. package/dist/transport/rabbitmq/rabbitmq-transport.test.d.ts +0 -2
  174. package/dist/transport/rabbitmq/rabbitmq-transport.test.d.ts.map +0 -1
  175. package/dist/transport/rabbitmq/rabbitmq-transport.test.js +0 -100
  176. package/dist/transport/transport.d.ts +0 -152
  177. package/dist/transport/transport.d.ts.map +0 -1
  178. package/dist/transport/transport.js +0 -1
  179. package/dist/types/common.d.ts +0 -41
  180. package/dist/types/common.d.ts.map +0 -1
  181. package/dist/types/common.js +0 -12
  182. package/dist/types/dispatcher.d.ts +0 -14
  183. package/dist/types/dispatcher.d.ts.map +0 -1
  184. package/dist/types/dispatcher.js +0 -1
  185. package/dist/types/envelope.d.ts +0 -131
  186. package/dist/types/envelope.d.ts.map +0 -1
  187. package/dist/types/envelope.js +0 -99
  188. package/dist/types/event.d.ts +0 -96
  189. package/dist/types/event.d.ts.map +0 -1
  190. package/dist/types/event.js +0 -26
  191. package/dist/types/event.test.d.ts +0 -2
  192. package/dist/types/event.test.d.ts.map +0 -1
  193. package/dist/types/event.test.js +0 -130
  194. package/dist/types/index.d.ts +0 -10
  195. package/dist/types/index.d.ts.map +0 -1
  196. package/dist/types/index.js +0 -4
  197. package/dist/types/subscriber.d.ts +0 -227
  198. package/dist/types/subscriber.d.ts.map +0 -1
  199. package/dist/types/subscriber.js +0 -97
  200. package/tsconfig.tsbuildinfo +0 -1
@@ -1,360 +0,0 @@
1
- import { describe, expect, it } from 'bun:test';
2
- import { TopologyBuilder, TopologyValidationError } from './builder.js';
3
- import { resolveQueueName } from './types.js';
4
- describe('TopologyBuilder', () => {
5
- describe('withNamespace', () => {
6
- it('should set the namespace', () => {
7
- const topology = TopologyBuilder.create()
8
- .withNamespace('myapp')
9
- .addQueue('events')
10
- .build();
11
- expect(topology.namespace).toBe('myapp');
12
- });
13
- it('should reject empty namespace', () => {
14
- const builder = TopologyBuilder.create()
15
- .withNamespace('')
16
- .addQueue('events');
17
- expect(() => builder.build()).toThrow(TopologyValidationError);
18
- });
19
- it('should reject namespace starting with number', () => {
20
- const builder = TopologyBuilder.create()
21
- .withNamespace('123app')
22
- .addQueue('events');
23
- expect(() => builder.build()).toThrow(TopologyValidationError);
24
- });
25
- it('should allow hyphens and underscores in namespace', () => {
26
- const topology = TopologyBuilder.create()
27
- .withNamespace('my-app_v2')
28
- .addQueue('events')
29
- .build();
30
- expect(topology.namespace).toBe('my-app_v2');
31
- });
32
- });
33
- describe('addQueue', () => {
34
- it('should add a queue with defaults', () => {
35
- const topology = TopologyBuilder.create()
36
- .withNamespace('test')
37
- .addQueue('events')
38
- .build();
39
- expect(topology.queues).toHaveLength(1);
40
- expect(topology.queues[0]?.name).toBe('events');
41
- });
42
- it('should add queue with options', () => {
43
- const topology = TopologyBuilder.create()
44
- .withNamespace('test')
45
- .addQueue('events', {
46
- concurrency: 5,
47
- consumerTimeout: 30000,
48
- priorities: true,
49
- })
50
- .build();
51
- expect(topology.queues[0]?.concurrency).toBe(5);
52
- expect(topology.queues[0]?.consumerTimeout).toBe(30000);
53
- expect(topology.queues[0]?.priorities).toBe(true);
54
- });
55
- it('should add multiple queues', () => {
56
- const topology = TopologyBuilder.create()
57
- .withNamespace('test')
58
- .addQueue('events')
59
- .addQueue('notifications')
60
- .addQueue('analytics')
61
- .build();
62
- expect(topology.queues).toHaveLength(3);
63
- });
64
- it('should reject duplicate queue names', () => {
65
- const builder = TopologyBuilder.create()
66
- .withNamespace('test')
67
- .addQueue('events')
68
- .addQueue('events');
69
- expect(() => builder.build()).toThrow('Duplicate queue name');
70
- });
71
- it('should reject empty queue name', () => {
72
- const builder = TopologyBuilder.create()
73
- .withNamespace('test')
74
- .addQueue('');
75
- expect(() => builder.build()).toThrow('Queue name cannot be empty');
76
- });
77
- it('should reject queue names starting with number', () => {
78
- const builder = TopologyBuilder.create()
79
- .withNamespace('test')
80
- .addQueue('123queue');
81
- expect(() => builder.build()).toThrow('must start with a letter');
82
- });
83
- it('should reject invalid concurrency', () => {
84
- const builder = TopologyBuilder.create()
85
- .withNamespace('test')
86
- .addQueue('events', { concurrency: 0 });
87
- expect(() => builder.build()).toThrow('concurrency must be at least 1');
88
- });
89
- it('should reject negative consumer timeout', () => {
90
- const builder = TopologyBuilder.create()
91
- .withNamespace('test')
92
- .addQueue('events', { consumerTimeout: -1 });
93
- expect(() => builder.build()).toThrow('consumer timeout must be non-negative');
94
- });
95
- });
96
- describe('withDeadLetter', () => {
97
- it('should configure dead letter settings', () => {
98
- const topology = TopologyBuilder.create()
99
- .withNamespace('test')
100
- .addQueue('events')
101
- .withDeadLetter({
102
- unhandled: { enabled: false },
103
- undeliverable: { enabled: true },
104
- })
105
- .build();
106
- expect(topology.deadLetter.unhandled.enabled).toBe(false);
107
- expect(topology.deadLetter.undeliverable.enabled).toBe(true);
108
- });
109
- it('should merge with defaults', () => {
110
- const topology = TopologyBuilder.create()
111
- .withNamespace('test')
112
- .addQueue('events')
113
- .withDeadLetter({ unhandled: { enabled: false } })
114
- .build();
115
- // undeliverable should keep default
116
- expect(topology.deadLetter.unhandled.enabled).toBe(false);
117
- expect(topology.deadLetter.undeliverable.enabled).toBe(true);
118
- });
119
- });
120
- describe('withRetry', () => {
121
- it('should configure retry settings', () => {
122
- const topology = TopologyBuilder.create()
123
- .withNamespace('test')
124
- .addQueue('events')
125
- .withRetry({
126
- enabled: true,
127
- defaultDelayMs: 5000,
128
- maxDelayMs: 600000,
129
- })
130
- .build();
131
- expect(topology.retry.enabled).toBe(true);
132
- expect(topology.retry.defaultDelayMs).toBe(5000);
133
- expect(topology.retry.maxDelayMs).toBe(600000);
134
- });
135
- it('should reject negative default delay', () => {
136
- const builder = TopologyBuilder.create()
137
- .withNamespace('test')
138
- .addQueue('events')
139
- .withRetry({ defaultDelayMs: -1 });
140
- expect(() => builder.build()).toThrow('delay must be non-negative');
141
- });
142
- it('should reject max delay less than default', () => {
143
- const builder = TopologyBuilder.create()
144
- .withNamespace('test')
145
- .addQueue('events')
146
- .withRetry({
147
- defaultDelayMs: 10000,
148
- maxDelayMs: 5000,
149
- });
150
- expect(() => builder.build()).toThrow('Max retry delay must be greater than or equal to default');
151
- });
152
- });
153
- describe('withoutRetry', () => {
154
- it('should disable retry', () => {
155
- const topology = TopologyBuilder.create()
156
- .withNamespace('test')
157
- .addQueue('events')
158
- .withoutRetry()
159
- .build();
160
- expect(topology.retry.enabled).toBe(false);
161
- });
162
- });
163
- describe('withoutDeadLetter', () => {
164
- it('should disable dead letter queues', () => {
165
- const topology = TopologyBuilder.create()
166
- .withNamespace('test')
167
- .addQueue('events')
168
- .withoutDeadLetter()
169
- .build();
170
- expect(topology.deadLetter.unhandled.enabled).toBe(false);
171
- expect(topology.deadLetter.undeliverable.enabled).toBe(false);
172
- });
173
- });
174
- describe('validate', () => {
175
- it('should return issues without throwing', () => {
176
- const builder = TopologyBuilder.create();
177
- const issues = builder.validate();
178
- expect(issues.length).toBeGreaterThan(0);
179
- expect(issues).toContain('Namespace is required');
180
- expect(issues).toContain('At least one queue is required');
181
- });
182
- it('should return empty array for valid topology', () => {
183
- const builder = TopologyBuilder.create()
184
- .withNamespace('test')
185
- .addQueue('events');
186
- const issues = builder.validate();
187
- expect(issues).toHaveLength(0);
188
- });
189
- });
190
- describe('build', () => {
191
- it('should throw TopologyValidationError with issues', () => {
192
- const builder = TopologyBuilder.create();
193
- try {
194
- builder.build();
195
- expect(true).toBe(false); // Should not reach here
196
- }
197
- catch (error) {
198
- expect(error).toBeInstanceOf(TopologyValidationError);
199
- expect(error.issues).toContain('Namespace is required');
200
- }
201
- });
202
- it('should return immutable topology', () => {
203
- const topology = TopologyBuilder.create()
204
- .withNamespace('test')
205
- .addQueue('events')
206
- .build();
207
- // Verify structure
208
- expect(topology.namespace).toBe('test');
209
- expect(topology.queues).toHaveLength(1);
210
- expect(topology.deadLetter.unhandled.enabled).toBe(true);
211
- expect(topology.retry.enabled).toBe(true);
212
- });
213
- });
214
- describe('exact queue option', () => {
215
- it('should mark queue as exact (external)', () => {
216
- const topology = TopologyBuilder.create()
217
- .withNamespace('test')
218
- .addQueue('external-queue', { exact: true })
219
- .build();
220
- expect(topology.queues[0]?.exact).toBe(true);
221
- });
222
- it('should allow dots in queue name when exact: true', () => {
223
- const topology = TopologyBuilder.create()
224
- .withNamespace('test')
225
- .addQueue('matador.shared.id-platform', { exact: true })
226
- .build();
227
- expect(topology.queues[0]?.name).toBe('matador.shared.id-platform');
228
- expect(topology.queues[0]?.exact).toBe(true);
229
- });
230
- it('should reject dots in queue name when exact: false', () => {
231
- const builder = TopologyBuilder.create()
232
- .withNamespace('test')
233
- .addQueue('invalid.queue.name');
234
- expect(() => builder.build()).toThrow('must start with a letter');
235
- });
236
- it('should allow transport-specific RabbitMQ options with exact queue', () => {
237
- const topology = TopologyBuilder.create()
238
- .withNamespace('test')
239
- .addQueue('matador.shared.id-platform', {
240
- exact: true,
241
- transport: {
242
- rabbitmq: {
243
- options: {
244
- durable: true,
245
- deadLetterExchange: 'matador.shared.dlx-undeliverable',
246
- arguments: {
247
- 'x-queue-type': 'quorum',
248
- },
249
- },
250
- },
251
- },
252
- })
253
- .build();
254
- expect(topology.queues[0]?.name).toBe('matador.shared.id-platform');
255
- expect(topology.queues[0]?.exact).toBe(true);
256
- expect(topology.queues[0]?.transport?.rabbitmq?.options?.durable).toBe(true);
257
- expect(topology.queues[0]?.transport?.rabbitmq?.options?.deadLetterExchange).toBe('matador.shared.dlx-undeliverable');
258
- expect(topology.queues[0]?.transport?.rabbitmq?.options?.arguments?.['x-queue-type']).toBe('quorum');
259
- });
260
- });
261
- describe('addQueue with QueueDefinition object', () => {
262
- it('should accept a QueueDefinition object', () => {
263
- const queueDef = {
264
- name: 'events',
265
- concurrency: 5,
266
- consumerTimeout: 30000,
267
- };
268
- const topology = TopologyBuilder.create()
269
- .withNamespace('test')
270
- .addQueue(queueDef)
271
- .build();
272
- expect(topology.queues).toHaveLength(1);
273
- expect(topology.queues[0]?.name).toBe('events');
274
- expect(topology.queues[0]?.concurrency).toBe(5);
275
- expect(topology.queues[0]?.consumerTimeout).toBe(30000);
276
- });
277
- it('should allow reusing queue definitions across builders', () => {
278
- const sharedQueue = {
279
- name: 'shared-queue',
280
- concurrency: 10,
281
- exact: true,
282
- };
283
- const topology1 = TopologyBuilder.create()
284
- .withNamespace('app1')
285
- .addQueue(sharedQueue)
286
- .build();
287
- const topology2 = TopologyBuilder.create()
288
- .withNamespace('app2')
289
- .addQueue(sharedQueue)
290
- .build();
291
- expect(topology1.queues[0]).toEqual(sharedQueue);
292
- expect(topology2.queues[0]).toEqual(sharedQueue);
293
- });
294
- it('should work with queue() alias', () => {
295
- const queueDef = {
296
- name: 'analytics',
297
- priorities: true,
298
- };
299
- const topology = TopologyBuilder.create()
300
- .withNamespace('test')
301
- .queue(queueDef)
302
- .build();
303
- expect(topology.queues[0]?.name).toBe('analytics');
304
- expect(topology.queues[0]?.priorities).toBe(true);
305
- });
306
- it('should mix QueueDefinition objects with name+options style', () => {
307
- const reusableQueue = {
308
- name: 'shared',
309
- concurrency: 3,
310
- };
311
- const topology = TopologyBuilder.create()
312
- .withNamespace('test')
313
- .addQueue(reusableQueue)
314
- .addQueue('local', { concurrency: 1 })
315
- .build();
316
- expect(topology.queues).toHaveLength(2);
317
- expect(topology.queues[0]?.name).toBe('shared');
318
- expect(topology.queues[1]?.name).toBe('local');
319
- });
320
- it('should validate QueueDefinition objects the same way', () => {
321
- const invalidQueue = {
322
- name: '123invalid',
323
- concurrency: 5,
324
- };
325
- const builder = TopologyBuilder.create()
326
- .withNamespace('test')
327
- .addQueue(invalidQueue);
328
- expect(() => builder.build()).toThrow('must start with a letter');
329
- });
330
- });
331
- });
332
- describe('resolveQueueName', () => {
333
- it('should return namespace.name for regular queues', () => {
334
- const queueDef = { name: 'events' };
335
- expect(resolveQueueName('myapp', queueDef)).toBe('myapp.events');
336
- });
337
- it('should return name as-is when exact: true', () => {
338
- const queueDef = { name: 'matador.shared.id-platform', exact: true };
339
- expect(resolveQueueName('myapp', queueDef)).toBe('matador.shared.id-platform');
340
- });
341
- it('should return namespace.name when exact: false', () => {
342
- const queueDef = { name: 'events', exact: false };
343
- expect(resolveQueueName('myapp', queueDef)).toBe('myapp.events');
344
- });
345
- it('should work with full QueueDefinition including transport options', () => {
346
- const queueDef = {
347
- name: 'matador.shared.id-platform',
348
- exact: true,
349
- transport: {
350
- rabbitmq: {
351
- options: {
352
- durable: true,
353
- deadLetterExchange: 'matador.shared.dlx-undeliverable',
354
- },
355
- },
356
- },
357
- };
358
- expect(resolveQueueName('myapp', queueDef)).toBe('matador.shared.id-platform');
359
- });
360
- });
@@ -1,5 +0,0 @@
1
- export type { DeadLetterConfig, DeadLetterQueueConfig, QueueDefinition, RabbitMQQueueDefinition, RabbitMQQueueOptions, RetryConfig, Topology, TransportQueueOptions, } from './types.js';
2
- export { getDeadLetterQueueName, getQualifiedQueueName, getRetryQueueName, resolveQueueName, } from './types.js';
3
- export type { QueueOptions } from './builder.js';
4
- export { TopologyBuilder, TopologyValidationError } from './builder.js';
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/topology/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,uBAAuB,EACvB,oBAAoB,EACpB,WAAW,EACX,QAAQ,EACR,qBAAqB,GACtB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC"}
@@ -1,2 +0,0 @@
1
- export { getDeadLetterQueueName, getQualifiedQueueName, getRetryQueueName, resolveQueueName, } from './types.js';
2
- export { TopologyBuilder, TopologyValidationError } from './builder.js';
@@ -1,128 +0,0 @@
1
- /**
2
- * Transport-agnostic topology definition.
3
- * Matador owns the topology; transports translate and apply it.
4
- */
5
- export interface Topology {
6
- /** Namespace prefix for all queues */
7
- readonly namespace: string;
8
- /** Work queues for processing events */
9
- readonly queues: readonly QueueDefinition[];
10
- /** Dead-letter queue configuration */
11
- readonly deadLetter: DeadLetterConfig;
12
- /** Retry queue configuration */
13
- readonly retry: RetryConfig;
14
- }
15
- /**
16
- * Individual queue definition.
17
- */
18
- export interface QueueDefinition {
19
- /** Queue name (will be prefixed with namespace unless exact: true) */
20
- readonly name: string;
21
- /** Concurrency for this queue */
22
- readonly concurrency?: number | undefined;
23
- /** Consumer timeout in milliseconds */
24
- readonly consumerTimeout?: number | undefined;
25
- /** Enable priority support if transport allows */
26
- readonly priorities?: boolean | undefined;
27
- /**
28
- * When true, the queue name is used exactly as provided without any
29
- * modification. The namespace prefix will NOT be added, and no other
30
- * transformations will be applied. Use this for referencing external
31
- * queues that are not managed by Matador.
32
- */
33
- readonly exact?: boolean | undefined;
34
- /** Transport-specific queue options */
35
- readonly transport?: TransportQueueOptions | undefined;
36
- }
37
- /**
38
- * Transport-specific queue options.
39
- * Each transport can define its own options under its transport name key.
40
- */
41
- export interface TransportQueueOptions {
42
- /** RabbitMQ-specific queue options */
43
- readonly rabbitmq?: RabbitMQQueueDefinition | undefined;
44
- }
45
- /**
46
- * RabbitMQ-specific queue definition options.
47
- */
48
- export interface RabbitMQQueueDefinition {
49
- /**
50
- * Exact RabbitMQ queue assertion options.
51
- * When provided, these options completely replace all auto-computed defaults
52
- * (durable, x-queue-type, x-dead-letter-exchange, etc.).
53
- */
54
- readonly options?: RabbitMQQueueOptions | undefined;
55
- }
56
- /**
57
- * RabbitMQ queue assertion options.
58
- * Maps to amqplib's Options.AssertQueue.
59
- */
60
- export interface RabbitMQQueueOptions {
61
- /** Queue survives broker restart */
62
- readonly durable?: boolean | undefined;
63
- /** Queue is deleted when last consumer unsubscribes */
64
- readonly autoDelete?: boolean | undefined;
65
- /** Queue can only be used by the declaring connection */
66
- readonly exclusive?: boolean | undefined;
67
- /** Exchange to which dead-lettered messages are sent */
68
- readonly deadLetterExchange?: string | undefined;
69
- /** Routing key for dead-lettered messages */
70
- readonly deadLetterRoutingKey?: string | undefined;
71
- /** Message TTL in milliseconds */
72
- readonly messageTtl?: number | undefined;
73
- /** Queue expires after this many milliseconds of non-use */
74
- readonly expires?: number | undefined;
75
- /** Maximum number of messages in the queue */
76
- readonly maxLength?: number | undefined;
77
- /** Maximum priority level (0-255) */
78
- readonly maxPriority?: number | undefined;
79
- /** Additional x-* arguments for RabbitMQ */
80
- readonly arguments?: Record<string, unknown> | undefined;
81
- }
82
- /**
83
- * Dead-letter queue configuration.
84
- */
85
- export interface DeadLetterConfig {
86
- /** Unhandled events (schema mismatch) queue */
87
- readonly unhandled: DeadLetterQueueConfig;
88
- /** Undeliverable events (permanent failures) queue */
89
- readonly undeliverable: DeadLetterQueueConfig;
90
- }
91
- /**
92
- * Configuration for a specific dead-letter queue.
93
- */
94
- export interface DeadLetterQueueConfig {
95
- /** Whether this DLQ is enabled */
96
- readonly enabled: boolean;
97
- /** Maximum number of messages in the DLQ */
98
- readonly maxLength?: number | undefined;
99
- }
100
- /**
101
- * Retry queue configuration.
102
- */
103
- export interface RetryConfig {
104
- /** Enable retry queue with delay */
105
- readonly enabled: boolean;
106
- /** Default retry delay in milliseconds */
107
- readonly defaultDelayMs: number;
108
- /** Maximum retry delay in milliseconds */
109
- readonly maxDelayMs: number;
110
- }
111
- /**
112
- * Gets the fully qualified queue name with namespace prefix.
113
- */
114
- export declare function getQualifiedQueueName(namespace: string, queueName: string): string;
115
- /**
116
- * Gets the dead-letter queue name for a given queue.
117
- */
118
- export declare function getDeadLetterQueueName(namespace: string, queueName: string, dlqType: 'unhandled' | 'undeliverable'): string;
119
- /**
120
- * Gets the retry queue name for a given queue.
121
- */
122
- export declare function getRetryQueueName(namespace: string, queueName: string): string;
123
- /**
124
- * Resolves the actual queue name for a given queue definition.
125
- * When exact: true, returns name as-is. Otherwise, returns namespace.name.
126
- */
127
- export declare function resolveQueueName(namespace: string, queueDef: QueueDefinition): string;
128
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/topology/types.ts"],"names":[],"mappings":"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"}
@@ -1,28 +0,0 @@
1
- /**
2
- * Gets the fully qualified queue name with namespace prefix.
3
- */
4
- export function getQualifiedQueueName(namespace, queueName) {
5
- return `${namespace}.${queueName}`;
6
- }
7
- /**
8
- * Gets the dead-letter queue name for a given queue.
9
- */
10
- export function getDeadLetterQueueName(namespace, queueName, dlqType) {
11
- return `${namespace}.${queueName}.${dlqType}`;
12
- }
13
- /**
14
- * Gets the retry queue name for a given queue.
15
- */
16
- export function getRetryQueueName(namespace, queueName) {
17
- return `${namespace}.${queueName}.retry`;
18
- }
19
- /**
20
- * Resolves the actual queue name for a given queue definition.
21
- * When exact: true, returns name as-is. Otherwise, returns namespace.name.
22
- */
23
- export function resolveQueueName(namespace, queueDef) {
24
- if (queueDef.exact) {
25
- return queueDef.name;
26
- }
27
- return `${namespace}.${queueDef.name}`;
28
- }
@@ -1,66 +0,0 @@
1
- import type { DeliveryMode } from '../types/index.js';
2
- /**
3
- * Describes the native capabilities of a transport.
4
- * Matador adapts its behavior based on these capabilities.
5
- */
6
- export interface TransportCapabilities {
7
- /**
8
- * Delivery semantics the transport supports.
9
- * - 'at-least-once': Ack after processing (may redeliver on failure)
10
- * - 'at-most-once': Ack before processing (no redelivery, may lose messages)
11
- */
12
- readonly deliveryModes: readonly DeliveryMode[];
13
- /**
14
- * Transport can delay message delivery natively.
15
- * - true: Use transport's native delay (BullMQ, RabbitMQ with plugin)
16
- * - false: Matador handles via retry queue with TTL or external scheduler
17
- */
18
- readonly delayedMessages: boolean;
19
- /**
20
- * Transport can route failed messages to dead-letter queue natively.
21
- * - 'native': Transport handles DL routing (RabbitMQ DLX)
22
- * - 'manual': Matador must send() to DLQ then complete() original
23
- * - 'none': No DL support, Matador logs and discards
24
- */
25
- readonly deadLetterRouting: 'native' | 'manual' | 'none';
26
- /**
27
- * Transport tracks delivery/attempt count natively.
28
- * - true: Receipt includes accurate attemptNumber from transport
29
- * - false: Matador tracks attempts in envelope.docket.attempts field
30
- */
31
- readonly attemptTracking: boolean;
32
- /**
33
- * How transport handles concurrency.
34
- * - 'prefetch': Channel-based prefetch (RabbitMQ)
35
- * - 'worker': Worker concurrency setting (BullMQ)
36
- * - 'partition': Partition-based parallelism (Kafka)
37
- * - 'none': No concurrency control (Memory)
38
- */
39
- readonly concurrencyModel: 'prefetch' | 'worker' | 'partition' | 'none';
40
- /**
41
- * Message ordering guarantees.
42
- * - 'none': No ordering guarantee (most transports with multiple consumers)
43
- * - 'queue': Ordered within queue (single consumer scenarios)
44
- * - 'partition': Ordered within partition/key (Kafka)
45
- */
46
- readonly ordering: 'none' | 'queue' | 'partition';
47
- /**
48
- * Transport supports message priority.
49
- * - true: Higher priority messages processed first
50
- * - false: FIFO only
51
- */
52
- readonly priorities: boolean;
53
- }
54
- /**
55
- * Checks if the transport supports a specific delivery mode.
56
- */
57
- export declare function supportsDeliveryMode(capabilities: TransportCapabilities, mode: DeliveryMode): boolean;
58
- /**
59
- * Checks if the transport supports native delayed messages.
60
- */
61
- export declare function supportsDelayedMessages(capabilities: TransportCapabilities): boolean;
62
- /**
63
- * Checks if the transport has native dead-letter routing.
64
- */
65
- export declare function hasNativeDeadLetter(capabilities: TransportCapabilities): boolean;
66
- //# sourceMappingURL=capabilities.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/transport/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAC;IAEhD;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAElC;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IAEzD;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAElC;;;;;;OAMG;IACH,QAAQ,CAAC,gBAAgB,EAAE,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,MAAM,CAAC;IAExE;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,WAAW,CAAC;IAElD;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,qBAAqB,EACnC,IAAI,EAAE,YAAY,GACjB,OAAO,CAET;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,qBAAqB,GAClC,OAAO,CAET;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,qBAAqB,GAClC,OAAO,CAET"}
@@ -1,18 +0,0 @@
1
- /**
2
- * Checks if the transport supports a specific delivery mode.
3
- */
4
- export function supportsDeliveryMode(capabilities, mode) {
5
- return capabilities.deliveryModes.includes(mode);
6
- }
7
- /**
8
- * Checks if the transport supports native delayed messages.
9
- */
10
- export function supportsDelayedMessages(capabilities) {
11
- return capabilities.delayedMessages;
12
- }
13
- /**
14
- * Checks if the transport has native dead-letter routing.
15
- */
16
- export function hasNativeDeadLetter(capabilities) {
17
- return capabilities.deadLetterRouting === 'native';
18
- }