@zdavison/matador 2.0.6 → 2.0.8

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 (38) hide show
  1. package/dist/hooks/index.d.ts +1 -1
  2. package/dist/hooks/index.d.ts.map +1 -1
  3. package/dist/hooks/safe-hooks.d.ts +1 -3
  4. package/dist/hooks/safe-hooks.d.ts.map +1 -1
  5. package/dist/hooks/safe-hooks.js +0 -15
  6. package/dist/hooks/types.d.ts +0 -17
  7. package/dist/hooks/types.d.ts.map +1 -1
  8. package/dist/index.cjs +27 -25
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +1 -1
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/transport/rabbitmq/rabbitmq-transport.d.ts +2 -0
  15. package/dist/transport/rabbitmq/rabbitmq-transport.d.ts.map +1 -1
  16. package/dist/transport/rabbitmq/rabbitmq-transport.js +4 -1
  17. package/dist/transport/rabbitmq/rabbitmq-transport.test.js +2 -0
  18. package/dist/types/envelope.d.ts +41 -4
  19. package/dist/types/envelope.d.ts.map +1 -1
  20. package/dist/types/envelope.js +51 -7
  21. package/dist/types/event.d.ts +7 -11
  22. package/dist/types/event.d.ts.map +1 -1
  23. package/dist/types/index.d.ts +3 -2
  24. package/dist/types/index.d.ts.map +1 -1
  25. package/package.json +3 -2
  26. package/src/hooks/index.ts +0 -1
  27. package/src/hooks/safe-hooks.ts +0 -23
  28. package/src/hooks/types.ts +0 -22
  29. package/src/index.ts +0 -1
  30. package/src/transport/rabbitmq/rabbitmq-transport.test.ts +2 -0
  31. package/src/transport/rabbitmq/rabbitmq-transport.ts +8 -2
  32. package/src/types/envelope.ts +79 -7
  33. package/src/types/event.ts +8 -14
  34. package/src/types/index.ts +9 -3
  35. package/test/e2e/multi-transport.e2e.test.ts +1 -0
  36. package/test/e2e/rabbitmq-transport.e2e.test.ts +4 -0
  37. package/test/e2e/transport-compliance.e2e.test.ts +1 -0
  38. package/tsconfig.tsbuildinfo +1 -1
@@ -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":"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"}
@@ -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,21 +1,17 @@
1
+ import type { Jsonifiable } from 'type-fest';
1
2
  /**
2
3
  * Unique event routing key type alias.
3
4
  */
4
5
  export type EventKey = string;
5
- /**
6
- * JSON-serializable primitive types.
7
- */
8
- export type JsonPrimitive = string | number | boolean | null;
9
- /**
10
- * JSON-serializable value (recursive type for objects and arrays).
11
- */
12
- export type JsonValue = JsonPrimitive | JsonValue[] | {
13
- [key: string]: JsonValue;
14
- };
15
6
  /**
16
7
  * JSON-serializable record type for metadata.
8
+ * Uses type-fest's Jsonifiable which accepts:
9
+ * - Primitives (string, number, boolean, null)
10
+ * - Arrays of Jsonifiable values
11
+ * - Objects with Jsonifiable values
12
+ * - Objects with a toJSON() method
17
13
  */
18
- export type JsonRecord = Record<string, JsonValue>;
14
+ export type JsonRecord = Record<string, Jsonifiable>;
19
15
  /**
20
16
  * Static properties required on Event classes for schema registration.
21
17
  */
@@ -1 +1 @@
1
- {"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../src/types/event.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,SAAS,GACjB,aAAa,GACb,SAAS,EAAE,GACX;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEjC;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,uCAAuC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,8CAA8C;IAC9C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B,yDAAyD;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAErC,yDAAyD;IACzD,KAAK,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,KAAK,CAAC,CAAC,GAAG,OAAO;IAChC,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAEjB,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEtC,yCAAyC;IACzC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE5C;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,8BAAsB,YAAY,CAAC,CAAC,GAAG,OAAO,CAAE,YAAW,KAAK,CAAC,CAAC,CAAC;IACjE,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAE5C,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAE1B,8BAA8B;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GACtE,CAAC,GACD,KAAK,CAAC;AAEV;;GAEG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,GAAG,OAAO,IAAI,WAAW,CAAC,CAAC,CAAC,GAClD,CAAC,KACC,IAAI,EAAE,CAAC,KACJ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../src/types/event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,uCAAuC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,8CAA8C;IAC9C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B,yDAAyD;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAErC,yDAAyD;IACzD,KAAK,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,KAAK,CAAC,CAAC,GAAG,OAAO;IAChC,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAEjB,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEtC,yCAAyC;IACzC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE5C;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,8BAAsB,YAAY,CAAC,CAAC,GAAG,OAAO,CAAE,YAAW,KAAK,CAAC,CAAC,CAAC;IACjE,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAE5C,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAE1B,8BAA8B;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GACtE,CAAC,GACD,KAAK,CAAC;AAEV;;GAEG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,GAAG,OAAO,IAAI,WAAW,CAAC,CAAC,CAAC,GAClD,CAAC,KACC,IAAI,EAAE,CAAC,KACJ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC"}
@@ -1,10 +1,11 @@
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
- export type { Event, EventClass, EventData, EventKey, EventOptions, EventStatic, JsonPrimitive, JsonRecord, JsonValue, } from './event.js';
6
+ export type { Event, EventClass, EventData, EventKey, EventOptions, EventStatic, JsonRecord, } from './event.js';
7
7
  export { MatadorEvent } from './event.js';
8
+ export type { Jsonifiable } from 'type-fest';
8
9
  export type { AnySubscriber, BaseSubscriberOptions, CallbackContext, CreateResumableSubscriberInput, CreateStandardSubscriberInput, CreateSubscriberInput, EnvelopeOf, ResumableCallback, ResumableCallbackContext, ResumableSubscriber, ResumableSubscriberOptions, StandardCallback, StandardSubscriber, StandardSubscriberOptions, Subscriber, SubscriberCallback, SubscriberDefinition, SubscriberOptions, SubscriberStub, } from './subscriber.js';
9
10
  export { createSubscriber, createSubscriberStub, isResumableSubscriber, isStandardSubscriber, isSubscriber, isSubscriberStub, } from './subscriber.js';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -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,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,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.8",
4
4
  "description": "A batteries-included event system.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -34,7 +34,8 @@
34
34
  "send-test-event": "bun ./cli.ts ./examples/config.ts ./examples/event.ts"
35
35
  },
36
36
  "dependencies": {
37
- "amqplib": "^0.10.4"
37
+ "amqplib": "^0.10.4",
38
+ "type-fest": "^5.3.1"
38
39
  },
39
40
  "devDependencies": {
40
41
  "@testcontainers/rabbitmq": "^10.16.0",
@@ -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),
@@ -123,22 +116,6 @@ export class SafeHooks {
123
116
  }
124
117
  }
125
118
 
126
- async getQueueConcurrency(queueName: string): Promise<number | undefined> {
127
- if (!this.hooks.getQueueConcurrency) {
128
- return undefined;
129
- }
130
-
131
- try {
132
- return await this.hooks.getQueueConcurrency(queueName);
133
- } catch (error) {
134
- this.logger.warn(
135
- '[Matador] 🟡 Hook getQueueConcurrency threw an error',
136
- error,
137
- );
138
- return undefined;
139
- }
140
- }
141
-
142
119
  async getRetryDelay(
143
120
  envelope: Envelope,
144
121
  attemptNumber: number,
@@ -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.
@@ -191,13 +176,6 @@ export interface MatadorHooks {
191
176
  | Record<string, unknown>
192
177
  | Promise<Record<string, unknown>>;
193
178
 
194
- /**
195
- * Dynamic queue concurrency lookup.
196
- */
197
- getQueueConcurrency?(
198
- queueName: string,
199
- ): number | undefined | Promise<number | undefined>;
200
-
201
179
  /**
202
180
  * Dynamic retry delay lookup.
203
181
  */
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
  }
@@ -1,25 +1,19 @@
1
+ import type { Jsonifiable } from 'type-fest';
2
+
1
3
  /**
2
4
  * Unique event routing key type alias.
3
5
  */
4
6
  export type EventKey = string;
5
7
 
6
- /**
7
- * JSON-serializable primitive types.
8
- */
9
- export type JsonPrimitive = string | number | boolean | null;
10
-
11
- /**
12
- * JSON-serializable value (recursive type for objects and arrays).
13
- */
14
- export type JsonValue =
15
- | JsonPrimitive
16
- | JsonValue[]
17
- | { [key: string]: JsonValue };
18
-
19
8
  /**
20
9
  * JSON-serializable record type for metadata.
10
+ * Uses type-fest's Jsonifiable which accepts:
11
+ * - Primitives (string, number, boolean, null)
12
+ * - Arrays of Jsonifiable values
13
+ * - Objects with Jsonifiable values
14
+ * - Objects with a toJSON() method
21
15
  */
22
- export type JsonRecord = Record<string, JsonValue>;
16
+ export type JsonRecord = Record<string, Jsonifiable>;
23
17
 
24
18
  /**
25
19
  * Static properties required on Event classes for schema registration.
@@ -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 {
@@ -19,12 +24,13 @@ export type {
19
24
  EventKey,
20
25
  EventOptions,
21
26
  EventStatic,
22
- JsonPrimitive,
23
27
  JsonRecord,
24
- JsonValue,
25
28
  } from './event.js';
26
29
  export { MatadorEvent } from './event.js';
27
30
 
31
+ // Re-export Jsonifiable from type-fest for convenience
32
+ export type { Jsonifiable } from 'type-fest';
33
+
28
34
  export type {
29
35
  AnySubscriber,
30
36
  BaseSubscriberOptions,
@@ -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