@zdavison/matador 2.0.6 → 2.0.7

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.
@@ -10,6 +10,8 @@ import type { MessageHandler, MessageReceipt, SendOptions, SubscribeOptions, Sub
10
10
  export interface RabbitMQTransportConfig {
11
11
  /** RabbitMQ connection URL */
12
12
  readonly url: string;
13
+ /** Connection name displayed in RabbitMQ management UI */
14
+ readonly connectionName: string;
13
15
  /** Connection manager configuration */
14
16
  readonly connection?: Partial<ConnectionManagerConfig> | undefined;
15
17
  /** Use quorum queues for durability (default: true) */
@@ -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":"AAOA,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAmB,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,SAAS,EACV,MAAM,iBAAiB,CAAC;AAEzB;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,8BAA8B;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAEhC,uCAAuC;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,SAAS,CAAC;IAEnE,uDAAuD;IACvD,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAE5C,wDAAwD;IACxD,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE9C,8EAA8E;IAC9E,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAErD,wDAAwD;IACxD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAmBD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED;;GAEG;AACH,qBAAa,iBAAkB,YAAW,SAAS;IACjD,QAAQ,CAAC,IAAI,cAAc;IAE3B,OAAO,CAAC,aAAa,CAQnB;IAEF,IAAI,YAAY,IAAI,qBAAqB,CAExC;IAED,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAoB;IACtD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmC;IACjE,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAE7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAIrB;IAEF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,wBAAwB,CAAS;gBAE7B,MAAM,EAAE,uBAAuB;IAkBrC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC,WAAW,IAAI,OAAO;IAIhB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA0ChD,IAAI,CACR,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IA0DvB,SAAS,CACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,YAAY,CAAC;IAwFlB,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAahD,gBAAgB,CACpB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IA6ChB;;;;;OAKG;YACW,uBAAuB;YAqCvB,SAAS;YAqCT,YAAY;YA+CZ,oBAAoB;YAwEpB,eAAe;YAgEf,gBAAgB;YAyBhB,sBAAsB;IA6BpC,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,sBAAsB;IAI9B,OAAO,CAAC,gBAAgB;IAiBxB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;CA0BzB"}
@@ -44,6 +44,7 @@ export class RabbitMQTransport {
44
44
  this.logger = config.logger ?? consoleLogger;
45
45
  this.config = {
46
46
  url: config.url,
47
+ connectionName: config.connectionName,
47
48
  connection: config.connection ?? {},
48
49
  quorumQueues: config.quorumQueues ?? true,
49
50
  defaultPrefetch: config.defaultPrefetch ?? 10,
@@ -272,7 +273,9 @@ export class RabbitMQTransport {
272
273
  }
273
274
  async doConnect() {
274
275
  this.logger.info(`[Matador] ⏳ Connecting to RabbitMQ at '${redactAmqpUrl(this.config.url)}'.`);
275
- const connection = await amqplib.connect(this.config.url);
276
+ const connection = await amqplib.connect(this.config.url, {
277
+ clientProperties: { connection_name: this.config.connectionName },
278
+ });
276
279
  this.connection = connection;
277
280
  // Handle connection errors - let ConnectionManager handle reconnection
278
281
  connection.on('error', (err) => {
@@ -54,6 +54,7 @@ describe('RabbitMQTransport', () => {
54
54
  };
55
55
  const transport = new RabbitMQTransport({
56
56
  url: 'amqp://testuser:testpass@localhost:5672',
57
+ connectionName: 'test-connection',
57
58
  logger: mockLogger,
58
59
  connection: {
59
60
  maxReconnectAttempts: 1, // Only try once to avoid long retries
@@ -80,6 +81,7 @@ describe('RabbitMQTransport', () => {
80
81
  };
81
82
  const transport = new RabbitMQTransport({
82
83
  url: 'amqp://localhost:5672',
84
+ connectionName: 'test-connection',
83
85
  logger: mockLogger,
84
86
  connection: {
85
87
  maxReconnectAttempts: 1,
@@ -1,4 +1,5 @@
1
1
  import type { Importance } from './common.js';
2
+ import type { Event } from './event.js';
2
3
  /**
3
4
  * Message envelope containing the event data and routing/observability metadata.
4
5
  * This is the transport-agnostic message format used throughout Matador.
@@ -79,16 +80,52 @@ export interface CreateEnvelopeOptions<T> extends DocketCreateFields {
79
80
  */
80
81
  export declare function createEnvelope<T>(options: CreateEnvelopeOptions<T>): Envelope<T>;
81
82
  /**
82
- * Helper to create a test envelope for a given event instance.
83
+ * Options for creating a dummy envelope.
84
+ * All fields are optional and will use sensible defaults if not provided.
85
+ */
86
+ export interface CreateDummyEnvelopeOptions {
87
+ readonly id?: string | undefined;
88
+ readonly eventKey?: string | undefined;
89
+ readonly eventDescription?: string | undefined;
90
+ readonly targetSubscriber?: string | undefined;
91
+ readonly importance?: Importance | undefined;
92
+ readonly correlationId?: string | undefined;
93
+ readonly metadata?: Record<string, unknown> | undefined;
94
+ readonly delayMs?: number | undefined;
95
+ }
96
+ /**
97
+ * Type helper to extract the data type from an Event, or return T as-is.
98
+ */
99
+ type ExtractData<T> = T extends Event<infer D> ? D : T;
100
+ /**
101
+ * Helper to create a test envelope for a given event instance or raw data.
83
102
  * Useful for unit testing subscriber callbacks directly.
84
103
  *
85
- * @example
104
+ * When passing an Event instance, the eventKey and eventDescription will be
105
+ * automatically extracted from the event class (unless overridden in options).
106
+ *
107
+ * @example With raw data
108
+ * ```typescript
109
+ * const envelope = createDummyEnvelope({ userId: '123', email: 'test@example.com' });
110
+ * ```
111
+ *
112
+ * @example With an Event instance
86
113
  * ```typescript
87
114
  * const event = new UserCreatedEvent({ userId: '123', email: 'test@example.com' });
88
115
  * const envelope = createDummyEnvelope(event);
89
- * await mySubscriber.callback(envelope, event);
116
+ * // eventKey is automatically set to UserCreatedEvent.key
117
+ * await mySubscriber.callback(envelope, event.data);
118
+ * ```
119
+ *
120
+ * @example With options
121
+ * ```typescript
122
+ * const event = new UserCreatedEvent({ userId: '123', email: 'test@example.com' });
123
+ * const envelope = createDummyEnvelope(event, {
124
+ * metadata: { traceId: 'abc-123' },
125
+ * correlationId: 'request-456',
126
+ * });
90
127
  * ```
91
128
  */
92
- export declare function createDummyEnvelope<T>(data: T): Envelope<T>;
129
+ export declare function createDummyEnvelope<T>(dataOrEvent: T, options?: CreateDummyEnvelopeOptions): Envelope<ExtractData<T>>;
93
130
  export {};
94
131
  //# sourceMappingURL=envelope.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../src/types/envelope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;;GAGG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,OAAO;IACnC,kCAAkC;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,qBAAqB;IACrB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAEjB,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IAGrB,4BAA4B;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,0EAA0E;IAC1E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE/C,6CAA6C;IAC7C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAElC,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEnC,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAIlC;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEhC,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAI/B,sCAAsC;IACtC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAEhC,yCAAyC;IACzC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE5C;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CACzD;AAED;;GAEG;AACH,KAAK,kBAAkB,GAAG,IAAI,CAC5B,MAAM,EACJ,UAAU,GACV,kBAAkB,GAClB,kBAAkB,GAClB,YAAY,GACZ,eAAe,CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,qBAAqB,CAAC,CAAC,CAAE,SAAQ,kBAAkB;IAClE,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEjC,qBAAqB;IACrB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAEjB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAExD;;;;OAIG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAEjE,iDAAiD;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,OAAO,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAChC,QAAQ,CAAC,CAAC,CAAC,CAmCb;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAO3D"}
1
+ {"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../src/types/envelope.ts"],"names":[],"mappings":"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"}
@@ -35,21 +35,65 @@ export function createEnvelope(options) {
35
35
  };
36
36
  }
37
37
  /**
38
- * Helper to create a test envelope for a given event instance.
38
+ * Checks if a value is a Matador Event (has data property and constructor with key).
39
+ */
40
+ function isEvent(value) {
41
+ return (typeof value === 'object' &&
42
+ value !== null &&
43
+ 'data' in value &&
44
+ typeof value.constructor.key === 'string');
45
+ }
46
+ /**
47
+ * Helper to create a test envelope for a given event instance or raw data.
39
48
  * Useful for unit testing subscriber callbacks directly.
40
49
  *
41
- * @example
50
+ * When passing an Event instance, the eventKey and eventDescription will be
51
+ * automatically extracted from the event class (unless overridden in options).
52
+ *
53
+ * @example With raw data
54
+ * ```typescript
55
+ * const envelope = createDummyEnvelope({ userId: '123', email: 'test@example.com' });
56
+ * ```
57
+ *
58
+ * @example With an Event instance
42
59
  * ```typescript
43
60
  * const event = new UserCreatedEvent({ userId: '123', email: 'test@example.com' });
44
61
  * const envelope = createDummyEnvelope(event);
45
- * await mySubscriber.callback(envelope, event);
62
+ * // eventKey is automatically set to UserCreatedEvent.key
63
+ * await mySubscriber.callback(envelope, event.data);
64
+ * ```
65
+ *
66
+ * @example With options
67
+ * ```typescript
68
+ * const event = new UserCreatedEvent({ userId: '123', email: 'test@example.com' });
69
+ * const envelope = createDummyEnvelope(event, {
70
+ * metadata: { traceId: 'abc-123' },
71
+ * correlationId: 'request-456',
72
+ * });
46
73
  * ```
47
74
  */
48
- export function createDummyEnvelope(data) {
75
+ export function createDummyEnvelope(dataOrEvent, options) {
76
+ let data;
77
+ let eventKey = options?.eventKey ?? 'dummy.event.key';
78
+ let eventDescription = options?.eventDescription;
79
+ if (isEvent(dataOrEvent)) {
80
+ data = dataOrEvent.data;
81
+ const eventStatic = dataOrEvent.constructor;
82
+ eventKey = options?.eventKey ?? eventStatic.key;
83
+ eventDescription = options?.eventDescription ?? eventStatic.description;
84
+ }
85
+ else {
86
+ data = dataOrEvent;
87
+ }
49
88
  return createEnvelope({
50
89
  data,
51
- eventKey: 'dummy.event.key',
52
- targetSubscriber: 'dummy-subscriber',
53
- importance: 'can-ignore',
90
+ eventKey,
91
+ eventDescription,
92
+ targetSubscriber: options?.targetSubscriber ?? 'dummy-subscriber',
93
+ importance: options?.importance ?? 'can-ignore',
94
+ id: options?.id,
95
+ correlationId: options?.correlationId,
96
+ metadata: options?.metadata,
97
+ delayMs: options?.delayMs,
54
98
  });
55
99
  }
@@ -1,7 +1,7 @@
1
1
  export type { DeliveryMode, Idempotency, Importance, ValidationError, ValidationResult, } from './common.js';
2
2
  export { invalidResult, validResult } from './common.js';
3
3
  export type { Dispatcher } from './dispatcher.js';
4
- export type { CreateEnvelopeOptions, Docket, Envelope } from './envelope.js';
4
+ export type { CreateDummyEnvelopeOptions, CreateEnvelopeOptions, Docket, Envelope, } from './envelope.js';
5
5
  export { createDummyEnvelope, createEnvelope } from './envelope.js';
6
6
  export type { Event, EventClass, EventData, EventKey, EventOptions, EventStatic, JsonPrimitive, JsonRecord, JsonValue, } from './event.js';
7
7
  export { MatadorEvent } from './event.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EACV,eAAe,EACf,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,YAAY,EAAE,qBAAqB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpE,YAAY,EACV,KAAK,EACL,UAAU,EACV,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,aAAa,EACb,UAAU,EACV,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,YAAY,EACV,aAAa,EACb,qBAAqB,EACrB,eAAe,EACf,8BAA8B,EAC9B,6BAA6B,EAC7B,qBAAqB,EACrB,UAAU,EACV,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,gBAAgB,EAChB,kBAAkB,EAClB,yBAAyB,EACzB,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,GACjB,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EACV,eAAe,EACf,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,YAAY,EACV,0BAA0B,EAC1B,qBAAqB,EACrB,MAAM,EACN,QAAQ,GACT,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpE,YAAY,EACV,KAAK,EACL,UAAU,EACV,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,aAAa,EACb,UAAU,EACV,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,YAAY,EACV,aAAa,EACb,qBAAqB,EACrB,eAAe,EACf,8BAA8B,EAC9B,6BAA6B,EAC7B,qBAAqB,EACrB,UAAU,EACV,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,gBAAgB,EAChB,kBAAkB,EAClB,yBAAyB,EACzB,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,GACjB,MAAM,iBAAiB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zdavison/matador",
3
- "version": "2.0.6",
3
+ "version": "2.0.7",
4
4
  "description": "A batteries-included event system.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -2,7 +2,6 @@ export type {
2
2
  DecodeErrorContext,
3
3
  EnqueueErrorContext,
4
4
  EnqueueSuccessContext,
5
- EnqueueWarningContext,
6
5
  Logger,
7
6
  MatadorHooks,
8
7
  TransportFallbackContext,
@@ -10,7 +10,6 @@ import {
10
10
  type DecodeErrorContext,
11
11
  type EnqueueErrorContext,
12
12
  type EnqueueSuccessContext,
13
- type EnqueueWarningContext,
14
13
  type Logger,
15
14
  type MatadorHooks,
16
15
  type WorkerErrorContext,
@@ -40,12 +39,6 @@ export class SafeHooks {
40
39
  );
41
40
  }
42
41
 
43
- async onEnqueueWarning(context: EnqueueWarningContext): Promise<void> {
44
- await this.safeCall('onEnqueueWarning', () =>
45
- this.hooks.onEnqueueWarning?.(context),
46
- );
47
- }
48
-
49
42
  async onEnqueueError(context: EnqueueErrorContext): Promise<void> {
50
43
  await this.safeCall('onEnqueueError', () =>
51
44
  this.hooks.onEnqueueError?.(context),
@@ -38,16 +38,6 @@ export interface EnqueueSuccessContext {
38
38
  readonly transport: string;
39
39
  }
40
40
 
41
- /**
42
- * Context for enqueue warning hook (fallback used).
43
- */
44
- export interface EnqueueWarningContext {
45
- readonly envelope: Envelope;
46
- readonly originalQueue: string;
47
- readonly fallbackQueue: string;
48
- readonly error: Error;
49
- }
50
-
51
41
  /**
52
42
  * Context for transport fallback hook.
53
43
  */
@@ -130,11 +120,6 @@ export interface MatadorHooks {
130
120
  */
131
121
  onEnqueueSuccess?(context: EnqueueSuccessContext): void | Promise<void>;
132
122
 
133
- /**
134
- * Called when enqueue falls back to a secondary queue.
135
- */
136
- onEnqueueWarning?(context: EnqueueWarningContext): void | Promise<void>;
137
-
138
123
  /**
139
124
  * Called when transport fallback occurs during send.
140
125
  * Only fires when using MultiTransport with fallbackEnabled=true.
package/src/index.ts CHANGED
@@ -155,7 +155,6 @@ export type {
155
155
  DecodeErrorContext,
156
156
  EnqueueErrorContext,
157
157
  EnqueueSuccessContext,
158
- EnqueueWarningContext,
159
158
  Logger,
160
159
  MatadorHooks,
161
160
  WorkerErrorContext,
@@ -66,6 +66,7 @@ describe('RabbitMQTransport', () => {
66
66
 
67
67
  const transport = new RabbitMQTransport({
68
68
  url: 'amqp://testuser:testpass@localhost:5672',
69
+ connectionName: 'test-connection',
69
70
  logger: mockLogger,
70
71
  connection: {
71
72
  maxReconnectAttempts: 1, // Only try once to avoid long retries
@@ -97,6 +98,7 @@ describe('RabbitMQTransport', () => {
97
98
 
98
99
  const transport = new RabbitMQTransport({
99
100
  url: 'amqp://localhost:5672',
101
+ connectionName: 'test-connection',
100
102
  logger: mockLogger,
101
103
  connection: {
102
104
  maxReconnectAttempts: 1,
@@ -29,6 +29,9 @@ export interface RabbitMQTransportConfig {
29
29
  /** RabbitMQ connection URL */
30
30
  readonly url: string;
31
31
 
32
+ /** Connection name displayed in RabbitMQ management UI */
33
+ readonly connectionName: string;
34
+
32
35
  /** Connection manager configuration */
33
36
  readonly connection?: Partial<ConnectionManagerConfig> | undefined;
34
37
 
@@ -104,7 +107,7 @@ export class RabbitMQTransport implements Transport {
104
107
  private readonly config: Required<
105
108
  Omit<RabbitMQTransportConfig, 'connection' | 'logger'>
106
109
  > & {
107
- connection: Partial<ConnectionManagerConfig>;
110
+ readonly connection: Partial<ConnectionManagerConfig>;
108
111
  };
109
112
 
110
113
  private readonly logger: Logger;
@@ -114,6 +117,7 @@ export class RabbitMQTransport implements Transport {
114
117
  this.logger = config.logger ?? consoleLogger;
115
118
  this.config = {
116
119
  url: config.url,
120
+ connectionName: config.connectionName,
117
121
  connection: config.connection ?? {},
118
122
  quorumQueues: config.quorumQueues ?? true,
119
123
  defaultPrefetch: config.defaultPrefetch ?? 10,
@@ -445,7 +449,9 @@ export class RabbitMQTransport implements Transport {
445
449
  this.logger.info(
446
450
  `[Matador] ⏳ Connecting to RabbitMQ at '${redactAmqpUrl(this.config.url)}'.`,
447
451
  );
448
- const connection = await amqplib.connect(this.config.url);
452
+ const connection = await amqplib.connect(this.config.url, {
453
+ clientProperties: { connection_name: this.config.connectionName },
454
+ });
449
455
  this.connection = connection;
450
456
 
451
457
  // Handle connection errors - let ConnectionManager handle reconnection
@@ -1,4 +1,5 @@
1
1
  import type { Importance } from './common.js';
2
+ import type { Event, EventStatic } from './event.js';
2
3
 
3
4
  /**
4
5
  * Message envelope containing the event data and routing/observability metadata.
@@ -152,21 +153,92 @@ export function createEnvelope<T>(
152
153
  }
153
154
 
154
155
  /**
155
- * Helper to create a test envelope for a given event instance.
156
+ * Options for creating a dummy envelope.
157
+ * All fields are optional and will use sensible defaults if not provided.
158
+ */
159
+ export interface CreateDummyEnvelopeOptions {
160
+ readonly id?: string | undefined;
161
+ readonly eventKey?: string | undefined;
162
+ readonly eventDescription?: string | undefined;
163
+ readonly targetSubscriber?: string | undefined;
164
+ readonly importance?: Importance | undefined;
165
+ readonly correlationId?: string | undefined;
166
+ readonly metadata?: Record<string, unknown> | undefined;
167
+ readonly delayMs?: number | undefined;
168
+ }
169
+
170
+ /**
171
+ * Type helper to extract the data type from an Event, or return T as-is.
172
+ */
173
+ type ExtractData<T> = T extends Event<infer D> ? D : T;
174
+
175
+ /**
176
+ * Checks if a value is a Matador Event (has data property and constructor with key).
177
+ */
178
+ function isEvent<T>(value: unknown): value is Event<T> {
179
+ return (
180
+ typeof value === 'object' &&
181
+ value !== null &&
182
+ 'data' in value &&
183
+ typeof (value.constructor as EventStatic).key === 'string'
184
+ );
185
+ }
186
+
187
+ /**
188
+ * Helper to create a test envelope for a given event instance or raw data.
156
189
  * Useful for unit testing subscriber callbacks directly.
157
190
  *
158
- * @example
191
+ * When passing an Event instance, the eventKey and eventDescription will be
192
+ * automatically extracted from the event class (unless overridden in options).
193
+ *
194
+ * @example With raw data
195
+ * ```typescript
196
+ * const envelope = createDummyEnvelope({ userId: '123', email: 'test@example.com' });
197
+ * ```
198
+ *
199
+ * @example With an Event instance
159
200
  * ```typescript
160
201
  * const event = new UserCreatedEvent({ userId: '123', email: 'test@example.com' });
161
202
  * const envelope = createDummyEnvelope(event);
162
- * await mySubscriber.callback(envelope, event);
203
+ * // eventKey is automatically set to UserCreatedEvent.key
204
+ * await mySubscriber.callback(envelope, event.data);
205
+ * ```
206
+ *
207
+ * @example With options
208
+ * ```typescript
209
+ * const event = new UserCreatedEvent({ userId: '123', email: 'test@example.com' });
210
+ * const envelope = createDummyEnvelope(event, {
211
+ * metadata: { traceId: 'abc-123' },
212
+ * correlationId: 'request-456',
213
+ * });
163
214
  * ```
164
215
  */
165
- export function createDummyEnvelope<T>(data: T): Envelope<T> {
216
+ export function createDummyEnvelope<T>(
217
+ dataOrEvent: T,
218
+ options?: CreateDummyEnvelopeOptions,
219
+ ): Envelope<ExtractData<T>> {
220
+ let data: ExtractData<T>;
221
+ let eventKey = options?.eventKey ?? 'dummy.event.key';
222
+ let eventDescription = options?.eventDescription;
223
+
224
+ if (isEvent(dataOrEvent)) {
225
+ data = dataOrEvent.data as ExtractData<T>;
226
+ const eventStatic = dataOrEvent.constructor as EventStatic;
227
+ eventKey = options?.eventKey ?? eventStatic.key;
228
+ eventDescription = options?.eventDescription ?? eventStatic.description;
229
+ } else {
230
+ data = dataOrEvent as ExtractData<T>;
231
+ }
232
+
166
233
  return createEnvelope({
167
234
  data,
168
- eventKey: 'dummy.event.key',
169
- targetSubscriber: 'dummy-subscriber',
170
- importance: 'can-ignore',
235
+ eventKey,
236
+ eventDescription,
237
+ targetSubscriber: options?.targetSubscriber ?? 'dummy-subscriber',
238
+ importance: options?.importance ?? 'can-ignore',
239
+ id: options?.id,
240
+ correlationId: options?.correlationId,
241
+ metadata: options?.metadata,
242
+ delayMs: options?.delayMs,
171
243
  });
172
244
  }
@@ -9,7 +9,12 @@ export { invalidResult, validResult } from './common.js';
9
9
 
10
10
  export type { Dispatcher } from './dispatcher.js';
11
11
 
12
- export type { CreateEnvelopeOptions, Docket, Envelope } from './envelope.js';
12
+ export type {
13
+ CreateDummyEnvelopeOptions,
14
+ CreateEnvelopeOptions,
15
+ Docket,
16
+ Envelope,
17
+ } from './envelope.js';
13
18
  export { createDummyEnvelope, createEnvelope } from './envelope.js';
14
19
 
15
20
  export type {
@@ -56,6 +56,7 @@ describe.skipIf(SKIP_E2E)('MultiTransport E2E', () => {
56
56
 
57
57
  rabbitTransport = new RabbitMQTransport({
58
58
  url: connectionUrl,
59
+ connectionName: 'matador-multi-transport-test',
59
60
  quorumQueues: false,
60
61
  });
61
62
 
@@ -49,6 +49,7 @@ describe.skipIf(SKIP_E2E)('RabbitMQ Transport E2E', () => {
49
49
  beforeEach(async () => {
50
50
  transport = new RabbitMQTransport({
51
51
  url: connectionUrl,
52
+ connectionName: 'matador-e2e-test',
52
53
  quorumQueues: false, // Use classic queues for faster tests
53
54
  defaultPrefetch: 5,
54
55
  });
@@ -202,6 +203,7 @@ describe.skipIf(SKIP_E2E)('RabbitMQ Transport E2E', () => {
202
203
  it('should handle disconnect and reconnect', async () => {
203
204
  const transport = new RabbitMQTransport({
204
205
  url: connectionUrl,
206
+ connectionName: 'matador-reconnect-test',
205
207
  connection: {
206
208
  maxReconnectAttempts: 3,
207
209
  initialReconnectDelay: 100,
@@ -229,6 +231,7 @@ describe.skipIf(SKIP_E2E)('RabbitMQ Transport E2E', () => {
229
231
  beforeEach(async () => {
230
232
  transport = new RabbitMQTransport({
231
233
  url: connectionUrl,
234
+ connectionName: 'matador-exact-queue-test',
232
235
  quorumQueues: false,
233
236
  defaultPrefetch: 5,
234
237
  });
@@ -515,6 +518,7 @@ describe.skipIf(SKIP_E2E)('RabbitMQ Transport E2E', () => {
515
518
  beforeEach(async () => {
516
519
  transport = new RabbitMQTransport({
517
520
  url: connectionUrl,
521
+ connectionName: 'matador-isolation-test',
518
522
  quorumQueues: false,
519
523
  defaultPrefetch: 2,
520
524
  });
@@ -116,6 +116,7 @@ const transportFactories: TransportFactory[] = [
116
116
  }
117
117
  return new RabbitMQTransport({
118
118
  url: rabbitConnectionUrl,
119
+ connectionName: 'matador-compliance-test',
119
120
  quorumQueues: false, // Use classic queues for faster tests
120
121
  defaultPrefetch: 10,
121
122
  });