@zdavison/matador 2.0.12 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -134,6 +134,7 @@ var TransportNotConnectedError = class extends MatadorError {
134
134
  );
135
135
  this.transportName = transportName;
136
136
  }
137
+ transportName;
137
138
  description = "The transport is not connected to the message broker. ACTION: Ensure the transport is connected by calling transport.connect() or matador.start(). Check that the broker (e.g., RabbitMQ) is running and accessible. Verify connection settings (URL, credentials, network access).";
138
139
  };
139
140
  var TransportClosedError = class extends MatadorError {
@@ -143,6 +144,7 @@ var TransportClosedError = class extends MatadorError {
143
144
  );
144
145
  this.transportName = transportName;
145
146
  }
147
+ transportName;
146
148
  description = "The transport has been closed and will not accept new operations. ACTION: This typically occurs during application shutdown. If unexpected, check for early shutdown triggers. Events sent after transport closure will be lost.";
147
149
  };
148
150
  var AllTransportsFailedError = class extends MatadorError {
@@ -153,6 +155,8 @@ var AllTransportsFailedError = class extends MatadorError {
153
155
  this.queue = queue;
154
156
  this.errors = errors;
155
157
  }
158
+ queue;
159
+ errors;
156
160
  description = "All transports failed to send the message. ACTION: Check the health of all configured transports (primary and fallbacks). Review the errors array for specific failure reasons. Ensure at least one transport is properly configured and reachable. Consider adding a LocalTransport as a last-resort fallback.";
157
161
  };
158
162
  var TransportSendError = class extends MatadorError {
@@ -161,6 +165,8 @@ var TransportSendError = class extends MatadorError {
161
165
  this.queue = queue;
162
166
  this.cause = cause;
163
167
  }
168
+ queue;
169
+ cause;
164
170
  description = "Failed to send a message through the transport. ACTION: Check the underlying error for details. Common causes: (1) Transport disconnected during send, (2) Network issues between application and broker, (3) Broker rejected the message (size, permissions, queue limits). The message was NOT delivered and should be retried or logged.";
165
171
  toJSON() {
166
172
  return {
@@ -176,10 +182,11 @@ var TransportSendError = class extends MatadorError {
176
182
  var DelayedMessagesNotSupportedError = class extends MatadorError {
177
183
  constructor(transportName) {
178
184
  super(
179
- `Delayed messages require the RabbitMQ delayed message exchange plugin. Install rabbitmq_delayed_message_exchange or remove delayMs from event options.`
185
+ "Delayed messages require the RabbitMQ delayed message exchange plugin. Install rabbitmq_delayed_message_exchange or remove delayMs from event options."
180
186
  );
181
187
  this.transportName = transportName;
182
188
  }
189
+ transportName;
183
190
  description = "Delayed messages were requested but the transport does not support them. ACTION: For RabbitMQ, install the rabbitmq_delayed_message_exchange plugin. Run: rabbitmq-plugins enable rabbitmq_delayed_message_exchange Then restart RabbitMQ and reconnect. Alternatively, remove delayMs from your event options if delays are not required.";
184
191
  };
185
192
  var EventNotRegisteredError = class extends MatadorError {
@@ -189,16 +196,19 @@ var EventNotRegisteredError = class extends MatadorError {
189
196
  );
190
197
  this.eventKey = eventKey;
191
198
  }
199
+ eventKey;
192
200
  description = "The event type is not registered in the schema. ACTION: Register the event using matador.register(EventClass, subscribers) before dispatching. If this occurs during message consumption, it may indicate schema drift between services. Ensure all services have matching schema registrations for shared events.";
193
201
  };
194
202
  var SubscriberNotRegisteredError = class extends MatadorError {
195
203
  constructor(subscriberName, eventKey) {
196
204
  super(
197
- `Subscriber "${subscriberName}" is not registered` + (eventKey ? ` for event "${eventKey}"` : "") + ". Check schema registration."
205
+ `Subscriber "${subscriberName}" is not registered${eventKey ? ` for event "${eventKey}"` : ""}. Check schema registration.`
198
206
  );
199
207
  this.subscriberName = subscriberName;
200
208
  this.eventKey = eventKey;
201
209
  }
210
+ subscriberName;
211
+ eventKey;
202
212
  description = "The subscriber is not registered for this event in the schema. ACTION: Ensure the subscriber is included in the registration for this event. This may occur if: (1) The subscriber was removed from the schema but messages still exist, (2) Schema drift between producer and consumer services, (3) A deployment is in progress with different schema versions. Check the dead-letter queue for affected messages.";
203
213
  };
204
214
  var NoSubscribersExistError = class extends MatadorError {
@@ -208,13 +218,15 @@ var NoSubscribersExistError = class extends MatadorError {
208
218
  );
209
219
  this.eventKey = eventKey;
210
220
  }
221
+ eventKey;
211
222
  description = "The event has no subscribers registered. ACTION: Register at least one subscriber for this event type. If subscribers were intentionally removed, consider also removing the event dispatch. Events without subscribers are not useful and may indicate configuration issues.";
212
223
  };
213
224
  var InvalidSchemaError = class extends MatadorError {
214
225
  constructor(message, cause) {
215
- super(`Invalid schema: ${message}` + (cause ? `. Cause: ${cause}` : ""));
226
+ super(`Invalid schema: ${message}${cause ? `. Cause: ${cause}` : ""}`);
216
227
  this.cause = cause;
217
228
  }
229
+ cause;
218
230
  description = "The schema configuration is invalid. ACTION: Review the schema registration for issues. Common problems: (1) Duplicate subscriber names for the same event, (2) Missing required fields on event class (key, description), (3) Invalid alias configuration. Check the cause property for specific details.";
219
231
  };
220
232
  var SubscriberIsStubError = class extends MatadorError {
@@ -224,6 +236,7 @@ var SubscriberIsStubError = class extends MatadorError {
224
236
  );
225
237
  this.subscriberName = subscriberName;
226
238
  }
239
+ subscriberName;
227
240
  description = "A SubscriberStub was registered in a consuming schema. ACTION: SubscriberStubs should only be used in producer schemas to declare that a subscriber exists in another service. In the consumer service, provide a full Subscriber with a callback function. Remove the stub from the consumer schema and add the actual implementation.";
228
241
  };
229
242
  var LocalTransportCannotProcessStubError = class extends MatadorError {
@@ -233,6 +246,7 @@ var LocalTransportCannotProcessStubError = class extends MatadorError {
233
246
  );
234
247
  this.subscriberName = subscriberName;
235
248
  }
249
+ subscriberName;
236
250
  description = "The LocalTransport cannot process events for SubscriberStubs. ACTION: SubscriberStubs represent remote implementations that only RabbitMQ can route. If using LocalTransport for testing, provide mock implementations instead of stubs. For production fallback scenarios, be aware that stub-targeted events will be dropped.";
237
251
  };
238
252
  var QueueNotFoundError = class extends MatadorError {
@@ -242,13 +256,15 @@ var QueueNotFoundError = class extends MatadorError {
242
256
  );
243
257
  this.queueName = queueName;
244
258
  }
259
+ queueName;
245
260
  description = "The specified queue does not exist or has not been created. ACTION: Ensure the queue is defined in the topology configuration. Call transport.applyTopology() or matador.start() to create queues. Check that the queue name matches the topology definition.";
246
261
  };
247
262
  var InvalidEventError = class extends MatadorError {
248
263
  constructor(message, cause) {
249
- super(`Invalid event: ${message}` + (cause ? `. Cause: ${cause}` : ""));
264
+ super(`Invalid event: ${message}${cause ? `. Cause: ${cause}` : ""}`);
250
265
  this.cause = cause;
251
266
  }
267
+ cause;
252
268
  description = "The event is invalid or missing required fields. ACTION: Ensure the event has all required properties. Common issues: missing targetSubscriber during processing, null/undefined data when the event type requires data, malformed event structure from codec decode failure.";
253
269
  };
254
270
  var MessageMaybePoisonedError = class extends MatadorError {
@@ -260,6 +276,9 @@ var MessageMaybePoisonedError = class extends MatadorError {
260
276
  this.deliveryCount = deliveryCount;
261
277
  this.maxDeliveries = maxDeliveries;
262
278
  }
279
+ eventId;
280
+ deliveryCount;
281
+ maxDeliveries;
263
282
  description = "A message was redelivered multiple times without successful processing. This usually indicates the message causes a crash or timeout during processing. ACTION: (1) Check application logs for errors/crashes during message processing, (2) Inspect the message in the dead-letter queue for malformed data, (3) Review the subscriber code for bugs that cause crashes, (4) Consider increasing processing timeout if the operation is legitimately slow. This message will NOT be retried to prevent crash loops.";
264
283
  };
265
284
  var IdempotentMessageCannotRetryError = class extends MatadorError {
@@ -270,6 +289,8 @@ var IdempotentMessageCannotRetryError = class extends MatadorError {
270
289
  this.eventId = eventId;
271
290
  this.subscriberName = subscriberName;
272
291
  }
292
+ eventId;
293
+ subscriberName;
273
294
  description = "A non-idempotent subscriber received a redelivered message. Retrying would risk duplicate side effects (e.g., double payments, duplicate emails). ACTION: (1) Mark the subscriber as idempotent if it safely handles duplicates, (2) Implement idempotency keys in the subscriber logic, (3) Manually inspect and replay the message from the dead-letter queue after verification. The message will be sent to the dead-letter queue for manual review.";
274
295
  };
275
296
  var TimeoutError = class extends MatadorError {
@@ -278,6 +299,8 @@ var TimeoutError = class extends MatadorError {
278
299
  this.operation = operation;
279
300
  this.timeoutMs = timeoutMs;
280
301
  }
302
+ operation;
303
+ timeoutMs;
281
304
  description = "An operation timed out before completing. ACTION: (1) Increase the timeout if the operation legitimately needs more time, (2) Optimize the operation to complete faster, (3) Check for deadlocks or blocking operations, (4) Verify external service dependencies are responsive.";
282
305
  };
283
306
  function isMatadorError(error) {
@@ -311,6 +334,8 @@ var DuplicateIoKeyError = class extends MatadorError {
311
334
  this.key = key;
312
335
  this.subscriberName = subscriberName;
313
336
  }
337
+ key;
338
+ subscriberName;
314
339
  description = "The same io() key was used multiple times in a single subscriber execution. Each io() call must have a unique key to ensure correct checkpoint behavior. ACTION: Ensure all io() keys are unique within the subscriber. For dynamic operations (e.g., loops), include a unique identifier in the key (e.g., `process-item-${item.id}`).";
315
340
  };
316
341
  var CheckpointStoreError = class extends MatadorError {
@@ -322,6 +347,9 @@ var CheckpointStoreError = class extends MatadorError {
322
347
  this.envelopeId = envelopeId;
323
348
  this.cause = cause;
324
349
  }
350
+ operation;
351
+ envelopeId;
352
+ cause;
325
353
  description = "A checkpoint store operation failed. This may cause issues with resumable subscribers. ACTION: Check the underlying storage system (Redis, etc.) for connectivity issues. The subscriber may re-execute operations that were already completed.";
326
354
  };
327
355
  function isDuplicateIoKeyError(error) {
@@ -358,6 +386,7 @@ var TopologyValidationError = class extends Error {
358
386
  this.issues = issues;
359
387
  this.name = "TopologyValidationError";
360
388
  }
389
+ issues;
361
390
  description = "The topology configuration is invalid. Check the issues array for specific validation failures such as missing namespace, invalid queue names, or conflicting settings. This error occurs during Matador initialization and must be fixed in the configuration.";
362
391
  };
363
392
  var TopologyBuilder = class _TopologyBuilder {
@@ -902,6 +931,9 @@ var ShutdownManager = class {
902
931
  this.disconnectTransport = disconnectTransport;
903
932
  this.config = { ...defaultShutdownConfig, ...config };
904
933
  }
934
+ getEnqueueCount;
935
+ stopReceiving;
936
+ disconnectTransport;
905
937
  _state = "running";
906
938
  config;
907
939
  eventsBeingProcessed = 0;
@@ -1012,6 +1044,7 @@ var CodecDecodeError = class extends Error {
1012
1044
  this.cause = cause;
1013
1045
  this.name = "CodecDecodeError";
1014
1046
  }
1047
+ cause;
1015
1048
  description = "Failed to decode a message from the transport. This typically indicates corrupted data, incompatible codec versions, or messages from a different system. Check the cause property for the underlying parsing error. The message will be sent to the dead-letter queue for investigation.";
1016
1049
  };
1017
1050
 
@@ -1048,16 +1081,16 @@ var JsonCodec = class {
1048
1081
  return false;
1049
1082
  }
1050
1083
  const envelope = value;
1051
- if (typeof envelope["id"] !== "string") return false;
1084
+ if (typeof envelope.id !== "string") return false;
1052
1085
  if (!("data" in envelope)) return false;
1053
- if (typeof envelope["docket"] !== "object" || envelope["docket"] === null)
1086
+ if (typeof envelope.docket !== "object" || envelope.docket === null)
1054
1087
  return false;
1055
- const docket = envelope["docket"];
1056
- if (typeof docket["eventKey"] !== "string") return false;
1057
- if (typeof docket["targetSubscriber"] !== "string") return false;
1058
- if (typeof docket["attempts"] !== "number") return false;
1059
- if (typeof docket["createdAt"] !== "string") return false;
1060
- if (typeof docket["importance"] !== "string") return false;
1088
+ const docket = envelope.docket;
1089
+ if (typeof docket.eventKey !== "string") return false;
1090
+ if (typeof docket.targetSubscriber !== "string") return false;
1091
+ if (typeof docket.attempts !== "number") return false;
1092
+ if (typeof docket.createdAt !== "string") return false;
1093
+ if (typeof docket.importance !== "string") return false;
1061
1094
  return true;
1062
1095
  }
1063
1096
  };
@@ -1147,12 +1180,12 @@ var RabbitMQCodec = class {
1147
1180
  isV1Body(value) {
1148
1181
  if (typeof value !== "object" || value === null) return false;
1149
1182
  const obj = value;
1150
- return typeof obj["key"] === "string" && typeof obj["targetSubscriber"] === "string" && "data" in obj && !("payload" in obj);
1183
+ return typeof obj.key === "string" && typeof obj.targetSubscriber === "string" && "data" in obj && !("payload" in obj);
1151
1184
  }
1152
1185
  isV2Body(value) {
1153
1186
  if (typeof value !== "object" || value === null) return false;
1154
1187
  const obj = value;
1155
- return typeof obj["id"] === "string" && "data" in obj && !("key" in obj);
1188
+ return typeof obj.id === "string" && "data" in obj && !("key" in obj);
1156
1189
  }
1157
1190
  decodeV2(body, headers) {
1158
1191
  const eventKey = this.requireStringHeader(headers, HEADERS.EVENT_KEY);
@@ -1210,7 +1243,7 @@ var RabbitMQCodec = class {
1210
1243
  Object.assign(mergedMetadata, body.metadata);
1211
1244
  }
1212
1245
  if (user_id !== void 0 && user_id !== null) {
1213
- mergedMetadata["user_id"] = user_id;
1246
+ mergedMetadata.user_id = user_id;
1214
1247
  }
1215
1248
  Object.assign(mergedMetadata, otherUniversal);
1216
1249
  const attempts = typeof headers[HEADERS.ATTEMPTS] === "number" ? headers[HEADERS.ATTEMPTS] : 1;
@@ -1774,7 +1807,7 @@ var StandardRetryPolicy = class {
1774
1807
  }
1775
1808
  getDelay(context) {
1776
1809
  const attempt = context.receipt.attemptNumber;
1777
- const delay = this.config.baseDelay * Math.pow(this.config.backoffMultiplier, attempt - 1);
1810
+ const delay = this.config.baseDelay * this.config.backoffMultiplier ** (attempt - 1);
1778
1811
  return Math.min(delay, this.config.maxDelay);
1779
1812
  }
1780
1813
  };
@@ -2111,17 +2144,16 @@ var Matador = class {
2111
2144
  }
2112
2145
  const isEventClass = typeof eventOrClass === "function" && "key" in eventOrClass;
2113
2146
  if (isEventClass) {
2114
- const eventClass = eventOrClass;
2147
+ const eventClass2 = eventOrClass;
2115
2148
  const data = dataOrOptions;
2116
- const options = maybeOptions;
2117
- const event = new eventClass(data);
2118
- return this.fanout.send(eventClass, event, options);
2119
- } else {
2120
- const event = eventOrClass;
2121
- const options = dataOrOptions;
2122
- const eventClass = event.constructor;
2123
- return this.fanout.send(eventClass, event, options);
2149
+ const options2 = maybeOptions;
2150
+ const event2 = new eventClass2(data);
2151
+ return this.fanout.send(eventClass2, event2, options2);
2124
2152
  }
2153
+ const event = eventOrClass;
2154
+ const options = dataOrOptions;
2155
+ const eventClass = event.constructor;
2156
+ return this.fanout.send(eventClass, event, options);
2125
2157
  }
2126
2158
  /**
2127
2159
  * Gets current handler state.
@@ -2215,6 +2247,8 @@ var ConnectionManager = class {
2215
2247
  this.disconnectFn = disconnectFn;
2216
2248
  this.config = { ...defaultConnectionConfig, ...config };
2217
2249
  }
2250
+ connectFn;
2251
+ disconnectFn;
2218
2252
  _state = { status: "disconnected" };
2219
2253
  listeners = /* @__PURE__ */ new Set();
2220
2254
  reconnectTimer = null;
@@ -2282,7 +2316,7 @@ var ConnectionManager = class {
2282
2316
  * Calculate delay for a given attempt using exponential backoff.
2283
2317
  */
2284
2318
  calculateDelay(attempt) {
2285
- const delay = this.config.initialReconnectDelay * Math.pow(this.config.backoffMultiplier, attempt - 1);
2319
+ const delay = this.config.initialReconnectDelay * this.config.backoffMultiplier ** (attempt - 1);
2286
2320
  return Math.min(delay, this.config.maxReconnectDelay);
2287
2321
  }
2288
2322
  setState(state) {
@@ -3093,7 +3127,7 @@ var RabbitMQTransport = class {
3093
3127
  const delayedExchange = this.getDelayedExchangeName(topology.namespace);
3094
3128
  await channel.bindQueue(queueName, delayedExchange, queueName);
3095
3129
  }
3096
- if (topology.retry.enabled) {
3130
+ if (topology.retry.enabled && !queueDef.exact) {
3097
3131
  await this.assertRetryQueue(channel, topology, queueName);
3098
3132
  }
3099
3133
  }