@zdavison/matador 3.0.2 → 3.0.5

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.
@@ -690,7 +690,10 @@ describe('ProcessingPipeline', () => {
690
690
  const receipt = createReceipt({ sourceQueue: 'test-queue' });
691
691
  await pipeline.process(new Uint8Array(), receipt);
692
692
  const calls = sendMock.mock.calls;
693
- const sentEnvelope = calls[0][1];
693
+ const firstCall = calls[0];
694
+ if (!firstCall)
695
+ throw new Error('expected sendMock to be called');
696
+ const sentEnvelope = firstCall[1];
694
697
  expect(sentEnvelope.docket.lastError).toBe('Test error message');
695
698
  expect(sentEnvelope.docket.firstError).toBe('Test error message');
696
699
  });
@@ -803,7 +806,10 @@ describe('ProcessingPipeline', () => {
803
806
  const receipt = createReceipt({ sourceQueue: 'original-queue' });
804
807
  await pipeline.process(new Uint8Array(), receipt);
805
808
  const calls = sendToDeadLetterMock.mock.calls;
806
- const sentEnvelope = calls[0][2];
809
+ const firstCall = calls[0];
810
+ if (!firstCall)
811
+ throw new Error('expected sendToDeadLetter to be called');
812
+ const sentEnvelope = firstCall[2];
807
813
  expect(sentEnvelope.docket.originalQueue).toBe('original-queue');
808
814
  });
809
815
  it('should handle discard decision', async () => {
@@ -956,7 +962,10 @@ describe('ProcessingPipeline', () => {
956
962
  const receipt = createReceipt({ sourceQueue: 'test-queue' });
957
963
  await pipeline.process(new Uint8Array(), receipt);
958
964
  const calls = sendMock.mock.calls;
959
- const sentEnvelope = calls[0][1];
965
+ const firstCall = calls[0];
966
+ if (!firstCall)
967
+ throw new Error('expected sendMock to be called');
968
+ const sentEnvelope = firstCall[1];
960
969
  expect(sentEnvelope.docket.firstError).toBe('First failure');
961
970
  expect(sentEnvelope.docket.lastError).toBe('First failure');
962
971
  });
@@ -994,7 +1003,10 @@ describe('ProcessingPipeline', () => {
994
1003
  const receipt = createReceipt({ sourceQueue: 'test-queue' });
995
1004
  await pipeline.process(new Uint8Array(), receipt);
996
1005
  const calls = sendMock.mock.calls;
997
- const sentEnvelope = calls[0][1];
1006
+ const firstCall = calls[0];
1007
+ if (!firstCall)
1008
+ throw new Error('expected sendMock to be called');
1009
+ const sentEnvelope = firstCall[1];
998
1010
  expect(sentEnvelope.docket.firstError).toBe('Original error');
999
1011
  expect(sentEnvelope.docket.lastError).toBe('Second failure');
1000
1012
  });
@@ -76,6 +76,8 @@ describe('installPlugins', () => {
76
76
  const schema = installPlugins(baseSchema, [{ subscriber: globalSub }]);
77
77
  // Check user.created has both subscribers
78
78
  const userEntry = schema[UserCreatedEvent.key];
79
+ if (!userEntry)
80
+ throw new Error('expected user.created entry');
79
81
  expect(isSchemaEntryTuple(userEntry)).toBe(true);
80
82
  const [, userSubs] = userEntry;
81
83
  expect(userSubs).toHaveLength(2);
@@ -183,6 +185,8 @@ describe('installPlugins', () => {
183
185
  };
184
186
  const schema = installPlugins(baseSchema, [{ subscriber: globalSub }]);
185
187
  const entry = schema[UserCreatedEvent.key];
188
+ if (!entry)
189
+ throw new Error('expected user.created entry');
186
190
  expect(isSchemaEntryTuple(entry)).toBe(true);
187
191
  const [eventClass, subs] = entry;
188
192
  expect(eventClass).toBe(UserCreatedEvent);
@@ -1 +1 @@
1
- {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/topology/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,QAAQ,EACT,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;AAWzD;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,KAAM,YAAW,cAAc;aASxD,MAAM,EAAE,SAAS,MAAM,EAAE;IAR3C,QAAQ,CAAC,WAAW,SAIuC;gBAGzD,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,SAAS,MAAM,EAAE;CAK5C;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B;;OAEG;IACH,MAAM,CAAC,MAAM,IAAI,eAAe;IAIhC,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,UAAU,CAGhB;IACF,OAAO,CAAC,KAAK,CAIX;IAEF;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKtC;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAapD;;;OAGG;IACH,KAAK,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI;IACxC;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAWjD;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAQvD;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI;IAS7C;;OAEG;IACH,YAAY,IAAI,IAAI;IAKpB;;OAEG;IACH,iBAAiB,IAAI,IAAI;IAQzB;;OAEG;IACH,QAAQ,IAAI,SAAS,MAAM,EAAE;IAuD7B;;;OAGG;IACH,KAAK,IAAI,QAAQ;CAgBlB"}
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/topology/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,QAAQ,EACT,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;AAWzD;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,KAAM,YAAW,cAAc;aASxD,MAAM,EAAE,SAAS,MAAM,EAAE;IAR3C,QAAQ,CAAC,WAAW,SAIuC;gBAGzD,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,SAAS,MAAM,EAAE;CAK5C;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B;;OAEG;IACH,MAAM,CAAC,MAAM,IAAI,eAAe;IAIhC,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,UAAU,CAGhB;IACF,OAAO,CAAC,KAAK,CAIX;IAEF;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKtC;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAapD;;;OAGG;IACH,KAAK,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI;IACxC;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAWjD;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAQvD;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI;IAS7C;;OAEG;IACH,YAAY,IAAI,IAAI;IAKpB;;OAEG;IACH,iBAAiB,IAAI,IAAI;IAQzB;;OAEG;IACH,QAAQ,IAAI,SAAS,MAAM,EAAE;IAQ7B;;;OAGG;IACH,KAAK,IAAI,QAAQ;CAgBlB"}
@@ -104,47 +104,11 @@ export class TopologyBuilder {
104
104
  * Validates the topology configuration.
105
105
  */
106
106
  validate() {
107
- const issues = [];
108
- if (!this.namespace || this.namespace.trim() === '') {
109
- issues.push('Namespace is required');
110
- }
111
- else if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(this.namespace)) {
112
- issues.push('Namespace must start with a letter and contain only alphanumeric characters, underscores, and hyphens');
113
- }
114
- if (this.queues.length === 0) {
115
- issues.push('At least one queue is required');
116
- }
117
- const queueNames = new Set();
118
- for (const queue of this.queues) {
119
- if (!queue.name || queue.name.trim() === '') {
120
- issues.push('Queue name cannot be empty');
121
- }
122
- else if (!queue.exact && !/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(queue.name)) {
123
- // Skip pattern validation for exact queues (allows names like 'matador.shared.id-platform')
124
- issues.push(`Queue name "${queue.name}" must start with a letter and contain only alphanumeric characters, underscores, and hyphens`);
125
- }
126
- else if (queueNames.has(queue.name)) {
127
- issues.push(`Duplicate queue name: "${queue.name}"`);
128
- }
129
- else {
130
- queueNames.add(queue.name);
131
- }
132
- if (queue.concurrency !== undefined && queue.concurrency < 1) {
133
- issues.push(`Queue "${queue.name}" concurrency must be at least 1`);
134
- }
135
- if (queue.consumerTimeout !== undefined && queue.consumerTimeout < 0) {
136
- issues.push(`Queue "${queue.name}" consumer timeout must be non-negative`);
137
- }
138
- }
139
- if (this.retry.enabled) {
140
- if (this.retry.defaultDelayMs < 0) {
141
- issues.push('Default retry delay must be non-negative');
142
- }
143
- if (this.retry.maxDelayMs < this.retry.defaultDelayMs) {
144
- issues.push('Max retry delay must be greater than or equal to default delay');
145
- }
146
- }
147
- return issues;
107
+ return [
108
+ ...validateNamespace(this.namespace),
109
+ ...validateQueues(this.queues),
110
+ ...validateRetry(this.retry),
111
+ ];
148
112
  }
149
113
  /**
150
114
  * Builds the topology configuration.
@@ -163,3 +127,64 @@ export class TopologyBuilder {
163
127
  };
164
128
  }
165
129
  }
130
+ const IDENTIFIER_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
131
+ function validateNamespace(namespace) {
132
+ if (!namespace || namespace.trim() === '') {
133
+ return ['Namespace is required'];
134
+ }
135
+ if (!IDENTIFIER_PATTERN.test(namespace)) {
136
+ return [
137
+ 'Namespace must start with a letter and contain only alphanumeric characters, underscores, and hyphens',
138
+ ];
139
+ }
140
+ return [];
141
+ }
142
+ function validateQueueName(queue, seen) {
143
+ if (!queue.name || queue.name.trim() === '') {
144
+ return ['Queue name cannot be empty'];
145
+ }
146
+ if (!queue.exact && !IDENTIFIER_PATTERN.test(queue.name)) {
147
+ return [
148
+ `Queue name "${queue.name}" must start with a letter and contain only alphanumeric characters, underscores, and hyphens`,
149
+ ];
150
+ }
151
+ if (seen.has(queue.name)) {
152
+ return [`Duplicate queue name: "${queue.name}"`];
153
+ }
154
+ seen.add(queue.name);
155
+ return [];
156
+ }
157
+ function validateQueueLimits(queue) {
158
+ const issues = [];
159
+ if (queue.concurrency !== undefined && queue.concurrency < 1) {
160
+ issues.push(`Queue "${queue.name}" concurrency must be at least 1`);
161
+ }
162
+ if (queue.consumerTimeout !== undefined && queue.consumerTimeout < 0) {
163
+ issues.push(`Queue "${queue.name}" consumer timeout must be non-negative`);
164
+ }
165
+ return issues;
166
+ }
167
+ function validateQueues(queues) {
168
+ const issues = [];
169
+ if (queues.length === 0) {
170
+ issues.push('At least one queue is required');
171
+ }
172
+ const seen = new Set();
173
+ for (const queue of queues) {
174
+ issues.push(...validateQueueName(queue, seen));
175
+ issues.push(...validateQueueLimits(queue));
176
+ }
177
+ return issues;
178
+ }
179
+ function validateRetry(retry) {
180
+ if (!retry.enabled)
181
+ return [];
182
+ const issues = [];
183
+ if (retry.defaultDelayMs < 0) {
184
+ issues.push('Default retry delay must be non-negative');
185
+ }
186
+ if (retry.maxDelayMs < retry.defaultDelayMs) {
187
+ issues.push('Max retry delay must be greater than or equal to default delay');
188
+ }
189
+ return issues;
190
+ }
@@ -56,7 +56,8 @@ describe('LocalTransport', () => {
56
56
  const envelope = createTestEnvelope();
57
57
  await transport.send('test-queue', envelope);
58
58
  const received = await transport.receiveOne('test-queue');
59
- expect(received).not.toBeNull();
59
+ if (!received)
60
+ throw new Error('expected received message');
60
61
  await transport.complete(received.receipt);
61
62
  expect(transport.getQueueSize('test-queue')).toBe(0);
62
63
  expect(transport.getCompleted()).toHaveLength(1);
@@ -112,7 +113,8 @@ describe('LocalTransport', () => {
112
113
  const envelope = createTestEnvelope();
113
114
  await transport.send('test-queue', envelope);
114
115
  const received = await transport.receiveOne('test-queue');
115
- expect(received).not.toBeNull();
116
+ if (!received)
117
+ throw new Error('expected received message');
116
118
  await transport.sendToDeadLetter(received.receipt, 'dlq', envelope, 'test error');
117
119
  expect(transport.getQueueSize('test-queue')).toBe(0);
118
120
  expect(transport.getQueueSize('test-queue.dlq')).toBe(1);
@@ -145,6 +147,8 @@ describe('LocalTransport', () => {
145
147
  await transport.connect();
146
148
  await transport.send('test-queue', createTestEnvelope());
147
149
  const received = await transport.receiveOne('test-queue');
150
+ if (!received)
151
+ throw new Error('expected received message');
148
152
  await transport.complete(received.receipt);
149
153
  transport.clear();
150
154
  expect(transport.getQueueSize('test-queue')).toBe(0);
@@ -1 +1 @@
1
- {"version":3,"file":"multi-transport.d.ts","sourceRoot":"","sources":["../../../src/transport/multi/multi-transport.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACrE,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;AAgBzB;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAE1C;;;;;;OAMG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MACzB,MAAM,GACN,SAAS,GACT,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAEhC;;;OAGG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;CAC1E;AAmBD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,cAAe,YAAW,SAAS;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAE5B,wEAAwE;IACxE,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAE1C,2DAA2D;IAC3D,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAElC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsB;IAC5C,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,oBAAoB,EAAE,KAAK,GAAE,mBAAwB;IAcnE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC,WAAW,IAAI,OAAO;IAKhB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhD,IAAI,CACR,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAyC7B;;OAEG;YACW,eAAe;IAwB7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IASnB,SAAS,CACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,YAAY,CAAC;IA0BlB,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhD,gBAAgB,CACpB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;CAOjB"}
1
+ {"version":3,"file":"multi-transport.d.ts","sourceRoot":"","sources":["../../../src/transport/multi/multi-transport.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACrE,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;AAgBzB;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAE1C;;;;;;OAMG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MACzB,MAAM,GACN,SAAS,GACT,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAEhC;;;OAGG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;CAC1E;AAmBD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,cAAe,YAAW,SAAS;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAE5B,wEAAwE;IACxE,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAE1C,2DAA2D;IAC3D,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAElC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsB;IAC5C,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,oBAAoB,EAAE,KAAK,GAAE,mBAAwB;IAcnE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC,WAAW,IAAI,OAAO;IAKhB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhD,IAAI,CACR,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IA0C7B;;OAEG;YACW,eAAe;IAwB7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IASnB,SAAS,CACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,YAAY,CAAC;IA0BlB,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhD,gBAAgB,CACpB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;CAOjB"}
@@ -91,6 +91,8 @@ export class MultiTransport {
91
91
  const errors = [];
92
92
  for (let i = 0; i < transportOrder.length; i++) {
93
93
  const transport = transportOrder[i];
94
+ if (!transport)
95
+ continue;
94
96
  try {
95
97
  return await transport.send(queue, envelope, options);
96
98
  }
@@ -120,6 +120,8 @@ describe('MultiTransport', () => {
120
120
  await transportWithCallback.send('test-queue', envelope);
121
121
  expect(fallbackContexts).toHaveLength(1);
122
122
  const ctx = fallbackContexts[0];
123
+ if (!ctx)
124
+ throw new Error('expected fallback context');
123
125
  expect(ctx.failedTransport).toBe('local');
124
126
  expect(ctx.nextTransport).toBe('local');
125
127
  expect(ctx.queue).toBe('test-queue');
@@ -206,7 +208,8 @@ describe('MultiTransport', () => {
206
208
  it('should complete using primary transport', async () => {
207
209
  await primary.send('test-queue', createTestEnvelope());
208
210
  const received = await primary.receiveOne('test-queue');
209
- expect(received).not.toBeNull();
211
+ if (!received)
212
+ throw new Error('expected received message');
210
213
  await transport.complete(received.receipt);
211
214
  expect(primary.getCompleted()).toHaveLength(1);
212
215
  });
@@ -219,7 +222,8 @@ describe('MultiTransport', () => {
219
222
  const envelope = createTestEnvelope();
220
223
  await primary.send('test-queue', envelope);
221
224
  const received = await primary.receiveOne('test-queue');
222
- expect(received).not.toBeNull();
225
+ if (!received)
226
+ throw new Error('expected received message');
223
227
  await transport.sendToDeadLetter(received.receipt, 'dlq', envelope, 'test error');
224
228
  expect(primary.getQueueSize('test-queue')).toBe(0);
225
229
  expect(primary.getQueueSize('test-queue.dlq')).toBe(1);
@@ -66,6 +66,7 @@ export declare class RabbitMQTransport implements Transport {
66
66
  private doConnect;
67
67
  private doDisconnect;
68
68
  private setupDelayedExchange;
69
+ private buildWorkQueueOptions;
69
70
  private assertWorkQueue;
70
71
  private assertRetryQueue;
71
72
  private assertDeadLetterQueues;
@@ -1 +1 @@
1
- {"version":3,"file":"rabbitmq-transport.d.ts","sourceRoot":"","sources":["../../../src/transport/rabbitmq/rabbitmq-transport.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rabbitmq-transport.d.ts","sourceRoot":"","sources":["../../../src/transport/rabbitmq/rabbitmq-transport.ts"],"names":[],"mappings":"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"}
@@ -406,41 +406,34 @@ export class RabbitMQTransport {
406
406
  });
407
407
  });
408
408
  }
409
+ buildWorkQueueOptions(topology, queueDef) {
410
+ const queueOptions = {
411
+ durable: true,
412
+ arguments: {},
413
+ };
414
+ if (this.config.quorumQueues && !queueDef.exact) {
415
+ queueOptions.arguments['x-queue-type'] = 'quorum';
416
+ }
417
+ if (topology.deadLetter.unhandled.enabled ||
418
+ topology.deadLetter.undeliverable.enabled) {
419
+ queueOptions.arguments['x-dead-letter-exchange'] =
420
+ this.getDLXExchangeName(topology.namespace);
421
+ }
422
+ if (queueDef.priorities) {
423
+ queueOptions.arguments['x-max-priority'] = 10;
424
+ }
425
+ if (queueDef.consumerTimeout) {
426
+ queueOptions.arguments['x-consumer-timeout'] = queueDef.consumerTimeout;
427
+ }
428
+ return queueOptions;
429
+ }
409
430
  async assertWorkQueue(channel, topology, queueDef) {
410
431
  const queueName = queueDef.exact
411
432
  ? queueDef.name
412
433
  : `${topology.namespace}.${queueDef.name}`;
413
434
  const rabbitmqOptions = queueDef.transport?.rabbitmq?.options;
414
- // If user provided exact RabbitMQ options, use them directly (replaces all defaults)
415
- if (rabbitmqOptions) {
416
- await channel.assertQueue(queueName, rabbitmqOptions);
417
- }
418
- else {
419
- // Use computed defaults
420
- const queueOptions = {
421
- durable: true,
422
- arguments: {},
423
- };
424
- // Use quorum queues for durability
425
- if (this.config.quorumQueues && !queueDef.exact) {
426
- queueOptions.arguments['x-queue-type'] = 'quorum';
427
- }
428
- // Set up dead-letter exchange routing
429
- const dlxExchange = this.getDLXExchangeName(topology.namespace);
430
- if (topology.deadLetter.unhandled.enabled ||
431
- topology.deadLetter.undeliverable.enabled) {
432
- queueOptions.arguments['x-dead-letter-exchange'] = dlxExchange;
433
- }
434
- // Enable priority if requested
435
- if (queueDef.priorities) {
436
- queueOptions.arguments['x-max-priority'] = 10;
437
- }
438
- // Set consumer timeout if specified
439
- if (queueDef.consumerTimeout) {
440
- queueOptions.arguments['x-consumer-timeout'] = queueDef.consumerTimeout;
441
- }
442
- await channel.assertQueue(queueName, queueOptions);
443
- }
435
+ const queueOptions = rabbitmqOptions ?? this.buildWorkQueueOptions(topology, queueDef);
436
+ await channel.assertQueue(queueName, queueOptions);
444
437
  // Bind queue to main exchange
445
438
  const mainExchange = this.getMainExchangeName(topology.namespace);
446
439
  await channel.bindQueue(queueName, mainExchange, queueName);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zdavison/matador",
3
- "version": "3.0.2",
3
+ "version": "3.0.5",
4
4
  "description": "A batteries-included event system.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",