@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.
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/safe-hooks.d.ts +1 -2
- package/dist/hooks/safe-hooks.d.ts.map +1 -1
- package/dist/hooks/safe-hooks.js +0 -3
- package/dist/hooks/types.d.ts +0 -13
- package/dist/hooks/types.d.ts.map +1 -1
- package/dist/index.cjs +27 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/transport/rabbitmq/rabbitmq-transport.d.ts +2 -0
- package/dist/transport/rabbitmq/rabbitmq-transport.d.ts.map +1 -1
- package/dist/transport/rabbitmq/rabbitmq-transport.js +4 -1
- package/dist/transport/rabbitmq/rabbitmq-transport.test.js +2 -0
- package/dist/types/envelope.d.ts +41 -4
- package/dist/types/envelope.d.ts.map +1 -1
- package/dist/types/envelope.js +51 -7
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/hooks/index.ts +0 -1
- package/src/hooks/safe-hooks.ts +0 -7
- package/src/hooks/types.ts +0 -15
- package/src/index.ts +0 -1
- package/src/transport/rabbitmq/rabbitmq-transport.test.ts +2 -0
- package/src/transport/rabbitmq/rabbitmq-transport.ts +8 -2
- package/src/types/envelope.ts +79 -7
- package/src/types/index.ts +6 -1
- package/test/e2e/multi-transport.e2e.test.ts +1 -0
- package/test/e2e/rabbitmq-transport.e2e.test.ts +4 -0
- package/test/e2e/transport-compliance.e2e.test.ts +1 -0
- 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":"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,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;
|
|
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,
|
package/dist/types/envelope.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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>(
|
|
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;
|
|
1
|
+
{"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../src/types/envelope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,KAAK,EAAe,MAAM,YAAY,CAAC;AAErD;;;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;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACxD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED;;GAEG;AACH,KAAK,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAcvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,WAAW,EAAE,CAAC,EACd,OAAO,CAAC,EAAE,0BAA0B,GACnC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAyB1B"}
|
package/dist/types/envelope.js
CHANGED
|
@@ -35,21 +35,65 @@ export function createEnvelope(options) {
|
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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(
|
|
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
|
|
52
|
-
|
|
53
|
-
|
|
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
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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,
|
|
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
package/src/hooks/index.ts
CHANGED
package/src/hooks/safe-hooks.ts
CHANGED
|
@@ -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),
|
package/src/hooks/types.ts
CHANGED
|
@@ -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
|
@@ -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
|
package/src/types/envelope.ts
CHANGED
|
@@ -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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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>(
|
|
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
|
|
169
|
-
|
|
170
|
-
|
|
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
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -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 {
|
|
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 {
|
|
@@ -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
|
});
|