@prodforcode/event-forge-rabbitmq 1.0.0 → 1.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/README.md +175 -0
- package/dist/delayed-publisher.d.ts +20 -0
- package/dist/delayed-publisher.d.ts.map +1 -0
- package/dist/delayed-publisher.js +97 -0
- package/dist/delayed-publisher.js.map +1 -0
- package/dist/golevelup-publisher.d.ts +10 -0
- package/dist/golevelup-publisher.d.ts.map +1 -0
- package/dist/golevelup-publisher.js +41 -0
- package/dist/golevelup-publisher.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/microservices-publisher.d.ts +11 -0
- package/dist/microservices-publisher.d.ts.map +1 -0
- package/dist/microservices-publisher.js +34 -0
- package/dist/microservices-publisher.js.map +1 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# @prodforcode/event-forge-rabbitmq
|
|
2
|
+
|
|
3
|
+
RabbitMQ publishers for the Universal Inbox-Outbox Pattern library.
|
|
4
|
+
|
|
5
|
+
## Publishers
|
|
6
|
+
|
|
7
|
+
### GolevelupPublisher
|
|
8
|
+
|
|
9
|
+
Basic RabbitMQ publisher using `@golevelup/nestjs-rabbitmq` for immediate message delivery.
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { GolevelupPublisher } from '@prodforcode/event-forge-rabbitmq';
|
|
13
|
+
|
|
14
|
+
const publisher = new GolevelupPublisher(
|
|
15
|
+
amqpConnection,
|
|
16
|
+
'events.exchange'
|
|
17
|
+
);
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### DelayedMessagePublisher
|
|
21
|
+
|
|
22
|
+
Advanced RabbitMQ publisher with support for delayed message delivery using RabbitMQ's `x-delayed-message` exchange plugin.
|
|
23
|
+
|
|
24
|
+
#### Prerequisites
|
|
25
|
+
|
|
26
|
+
The DelayedMessagePublisher requires the RabbitMQ `rabbitmq_delayed_message_exchange` plugin to be enabled on your RabbitMQ server.
|
|
27
|
+
|
|
28
|
+
**Installation:**
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Enable the plugin
|
|
32
|
+
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
|
|
33
|
+
|
|
34
|
+
# Restart RabbitMQ
|
|
35
|
+
rabbitmqctl restart
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Exchange Configuration:**
|
|
39
|
+
|
|
40
|
+
You must create a delayed exchange with type `x-delayed-message`:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Using rabbitmqadmin
|
|
44
|
+
rabbitmqadmin declare exchange name=events.delayed type=x-delayed-message arguments='{"x-delayed-type": "topic"}'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Or programmatically:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
await channel.assertExchange('events.delayed', 'x-delayed-message', {
|
|
51
|
+
durable: true,
|
|
52
|
+
arguments: {
|
|
53
|
+
'x-delayed-type': 'topic'
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
#### Usage
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { DelayedMessagePublisher } from '@prodforcode/event-forge-rabbitmq';
|
|
62
|
+
|
|
63
|
+
const publisher = new DelayedMessagePublisher(
|
|
64
|
+
amqpConnection,
|
|
65
|
+
{
|
|
66
|
+
directExchange: 'events.direct', // For immediate messages
|
|
67
|
+
delayedExchange: 'events.delayed' // For delayed messages
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// Immediate message (uses directExchange, default routing)
|
|
72
|
+
await publisher.publish(message);
|
|
73
|
+
|
|
74
|
+
// Delayed message (uses delayedExchange)
|
|
75
|
+
await publisher.publish({
|
|
76
|
+
...message,
|
|
77
|
+
metadata: {
|
|
78
|
+
delay: 5000 // Delay in milliseconds
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Custom routing key (override default {aggregateType}.{eventType})
|
|
83
|
+
await publisher.publish({
|
|
84
|
+
...message,
|
|
85
|
+
metadata: {
|
|
86
|
+
routingKey: 'sms.priority.high' // Custom routing key
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Custom exchange for immediate messages (e.g., fanout exchange)
|
|
91
|
+
await publisher.publish({
|
|
92
|
+
...message,
|
|
93
|
+
metadata: {
|
|
94
|
+
exchange: 'notifications.fanout', // Custom exchange (immediate only)
|
|
95
|
+
routingKey: '' // Empty for fanout exchanges
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### Message Routing Logic
|
|
101
|
+
|
|
102
|
+
The DelayedMessagePublisher provides flexible routing through metadata overrides:
|
|
103
|
+
|
|
104
|
+
**Routing Key:**
|
|
105
|
+
- If `metadata.routingKey` is provided: Uses the custom routing key
|
|
106
|
+
- Otherwise: Uses default format `{aggregateType}.{eventType}`
|
|
107
|
+
|
|
108
|
+
**Exchange Selection:**
|
|
109
|
+
- If `metadata.exchange` is provided (immediate messages only): Uses the custom exchange
|
|
110
|
+
- If `metadata.delay` is present: Uses `delayedExchange` with `x-delay` header
|
|
111
|
+
- Otherwise: Uses `directExchange` for immediate delivery
|
|
112
|
+
|
|
113
|
+
**Important Notes:**
|
|
114
|
+
- `metadata.exchange` only applies to immediate messages (ignored when `metadata.delay` is present)
|
|
115
|
+
- For delayed messages, the configured `delayedExchange` is always used
|
|
116
|
+
- `metadata.routingKey` works for both immediate and delayed messages
|
|
117
|
+
|
|
118
|
+
#### Metadata Delay Format
|
|
119
|
+
|
|
120
|
+
The `metadata.delay` field must be:
|
|
121
|
+
- A number (milliseconds)
|
|
122
|
+
- Greater than or equal to 0
|
|
123
|
+
- Present in the message metadata object
|
|
124
|
+
|
|
125
|
+
Example:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
const message: OutboxMessage = {
|
|
129
|
+
id: 'msg-123',
|
|
130
|
+
aggregateType: 'User',
|
|
131
|
+
aggregateId: 'user-456',
|
|
132
|
+
eventType: 'user.created',
|
|
133
|
+
payload: { name: 'John Doe' },
|
|
134
|
+
metadata: {
|
|
135
|
+
delay: 10000 // Deliver after 10 seconds
|
|
136
|
+
},
|
|
137
|
+
// ... other fields
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
await publisher.publish(message);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### Error Handling
|
|
144
|
+
|
|
145
|
+
If the RabbitMQ server does not have the delayed message plugin enabled or the delayed exchange is not properly configured, publishing delayed messages will fail with an error from RabbitMQ.
|
|
146
|
+
|
|
147
|
+
### MicroservicesPublisher
|
|
148
|
+
|
|
149
|
+
RabbitMQ publisher using `@nestjs/microservices` for NestJS microservices architecture.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import { MicroservicesPublisher } from '@prodforcode/event-forge-rabbitmq';
|
|
153
|
+
|
|
154
|
+
const publisher = new MicroservicesPublisher(clientProxy);
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Installation
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
npm install @prodforcode/event-forge-rabbitmq
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Peer dependencies (install based on your needs):
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# For GolevelupPublisher and DelayedMessagePublisher
|
|
167
|
+
npm install @golevelup/nestjs-rabbitmq @nestjs/common
|
|
168
|
+
|
|
169
|
+
# For MicroservicesPublisher
|
|
170
|
+
npm install @nestjs/microservices @nestjs/common
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## License
|
|
174
|
+
|
|
175
|
+
MIT
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { IMessagePublisher, OutboxMessage, PublishOptions } from '@prodforcode/event-forge-core';
|
|
2
|
+
import { AmqpConnection } from './types';
|
|
3
|
+
export interface DelayedPublisherConfig {
|
|
4
|
+
directExchange: string;
|
|
5
|
+
delayedExchange: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class DelayedMessagePublisher implements IMessagePublisher {
|
|
8
|
+
private readonly amqpConnection;
|
|
9
|
+
private readonly config;
|
|
10
|
+
constructor(amqpConnection: AmqpConnection, config: DelayedPublisherConfig);
|
|
11
|
+
publish(message: OutboxMessage, options?: PublishOptions): Promise<void>;
|
|
12
|
+
private getRoutingKey;
|
|
13
|
+
private buildRoutingKey;
|
|
14
|
+
private extractCustomRoutingKey;
|
|
15
|
+
private extractDelay;
|
|
16
|
+
private getExchange;
|
|
17
|
+
private selectExchange;
|
|
18
|
+
private extractCustomExchange;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=delayed-publisher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delayed-publisher.d.ts","sourceRoot":"","sources":["../src/delayed-publisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAEjG,OAAO,EAAE,cAAc,EAA0B,MAAM,SAAS,CAAC;AAKjE,MAAM,WAAW,sBAAsB;IAErC,cAAc,EAAE,MAAM,CAAC;IAEvB,eAAe,EAAE,MAAM,CAAC;CACzB;AAuCD,qBAAa,uBAAwB,YAAW,iBAAiB;IAE7D,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,sBAAsB;IAG3C,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IA0C9E,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,uBAAuB;IAkB/B,OAAO,CAAC,YAAY;IAyBpB,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,qBAAqB;CAa9B"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DelayedMessagePublisher = void 0;
|
|
4
|
+
class DelayedMessagePublisher {
|
|
5
|
+
amqpConnection;
|
|
6
|
+
config;
|
|
7
|
+
constructor(amqpConnection, config) {
|
|
8
|
+
this.amqpConnection = amqpConnection;
|
|
9
|
+
this.config = config;
|
|
10
|
+
}
|
|
11
|
+
async publish(message, options) {
|
|
12
|
+
const routingKey = this.getRoutingKey(message);
|
|
13
|
+
const delay = this.extractDelay(message);
|
|
14
|
+
const exchange = this.getExchange(message, delay);
|
|
15
|
+
const rabbitMQOptions = {
|
|
16
|
+
...options,
|
|
17
|
+
persistent: true,
|
|
18
|
+
contentType: 'application/json',
|
|
19
|
+
messageId: message.id,
|
|
20
|
+
timestamp: message.createdAt.getTime(),
|
|
21
|
+
headers: {
|
|
22
|
+
...options?.headers,
|
|
23
|
+
'x-aggregate-type': message.aggregateType,
|
|
24
|
+
'x-aggregate-id': message.aggregateId,
|
|
25
|
+
'x-event-type': message.eventType,
|
|
26
|
+
...(delay !== null && { 'x-delay': delay }),
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
await this.amqpConnection.publish(exchange, routingKey, {
|
|
30
|
+
id: message.id,
|
|
31
|
+
aggregateType: message.aggregateType,
|
|
32
|
+
aggregateId: message.aggregateId,
|
|
33
|
+
eventType: message.eventType,
|
|
34
|
+
payload: message.payload,
|
|
35
|
+
metadata: message.metadata,
|
|
36
|
+
createdAt: message.createdAt,
|
|
37
|
+
}, rabbitMQOptions);
|
|
38
|
+
}
|
|
39
|
+
getRoutingKey(message) {
|
|
40
|
+
const customRoutingKey = this.extractCustomRoutingKey(message);
|
|
41
|
+
if (customRoutingKey !== null) {
|
|
42
|
+
return customRoutingKey;
|
|
43
|
+
}
|
|
44
|
+
return this.buildRoutingKey(message);
|
|
45
|
+
}
|
|
46
|
+
buildRoutingKey(message) {
|
|
47
|
+
return `${message.aggregateType}.${message.eventType}`;
|
|
48
|
+
}
|
|
49
|
+
extractCustomRoutingKey(message) {
|
|
50
|
+
if (!message.metadata || !('routingKey' in message.metadata)) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
const routingKey = message.metadata.routingKey;
|
|
54
|
+
if (typeof routingKey !== 'string') {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
return routingKey;
|
|
58
|
+
}
|
|
59
|
+
extractDelay(message) {
|
|
60
|
+
if (!message.metadata?.delay) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const delay = message.metadata.delay;
|
|
64
|
+
if (typeof delay !== 'number') {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
if (delay < 0) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
return delay;
|
|
71
|
+
}
|
|
72
|
+
getExchange(message, delay) {
|
|
73
|
+
const customExchange = this.extractCustomExchange(message);
|
|
74
|
+
if (customExchange !== null && delay === null) {
|
|
75
|
+
return customExchange;
|
|
76
|
+
}
|
|
77
|
+
return this.selectExchange(delay);
|
|
78
|
+
}
|
|
79
|
+
selectExchange(delay) {
|
|
80
|
+
if (delay === null) {
|
|
81
|
+
return this.config.directExchange;
|
|
82
|
+
}
|
|
83
|
+
return this.config.delayedExchange;
|
|
84
|
+
}
|
|
85
|
+
extractCustomExchange(message) {
|
|
86
|
+
if (!message.metadata || !('exchange' in message.metadata)) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const exchange = message.metadata.exchange;
|
|
90
|
+
if (typeof exchange !== 'string') {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
return exchange;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.DelayedMessagePublisher = DelayedMessagePublisher;
|
|
97
|
+
//# sourceMappingURL=delayed-publisher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delayed-publisher.js","sourceRoot":"","sources":["../src/delayed-publisher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IMessagePublisher, OutboxMessage, PublishOptions } from '@prodforcode/event-forge-core';
|
|
2
|
+
import { AmqpConnection } from './types';
|
|
3
|
+
export declare class GolevelupPublisher implements IMessagePublisher {
|
|
4
|
+
private readonly amqpConnection;
|
|
5
|
+
private readonly exchange;
|
|
6
|
+
constructor(amqpConnection: AmqpConnection, exchange: string);
|
|
7
|
+
publish(message: OutboxMessage, options?: PublishOptions): Promise<void>;
|
|
8
|
+
private buildRoutingKey;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=golevelup-publisher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"golevelup-publisher.d.ts","sourceRoot":"","sources":["../src/golevelup-publisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAEjG,OAAO,EAAE,cAAc,EAA0B,MAAM,SAAS,CAAC;AAMjE,qBAAa,kBAAmB,YAAW,iBAAiB;IAExD,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBADR,cAAc,EAAE,cAAc,EAC9B,QAAQ,EAAE,MAAM;IAG7B,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAsC9E,OAAO,CAAC,eAAe;CAGxB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GolevelupPublisher = void 0;
|
|
4
|
+
class GolevelupPublisher {
|
|
5
|
+
amqpConnection;
|
|
6
|
+
exchange;
|
|
7
|
+
constructor(amqpConnection, exchange) {
|
|
8
|
+
this.amqpConnection = amqpConnection;
|
|
9
|
+
this.exchange = exchange;
|
|
10
|
+
}
|
|
11
|
+
async publish(message, options) {
|
|
12
|
+
const routingKey = this.buildRoutingKey(message);
|
|
13
|
+
const rabbitMQOptions = {
|
|
14
|
+
...options,
|
|
15
|
+
persistent: true,
|
|
16
|
+
contentType: 'application/json',
|
|
17
|
+
messageId: message.id,
|
|
18
|
+
timestamp: message.createdAt.getTime(),
|
|
19
|
+
headers: {
|
|
20
|
+
...options?.headers,
|
|
21
|
+
'x-aggregate-type': message.aggregateType,
|
|
22
|
+
'x-aggregate-id': message.aggregateId,
|
|
23
|
+
'x-event-type': message.eventType,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
await this.amqpConnection.publish(this.exchange, routingKey, {
|
|
27
|
+
id: message.id,
|
|
28
|
+
aggregateType: message.aggregateType,
|
|
29
|
+
aggregateId: message.aggregateId,
|
|
30
|
+
eventType: message.eventType,
|
|
31
|
+
payload: message.payload,
|
|
32
|
+
metadata: message.metadata,
|
|
33
|
+
createdAt: message.createdAt,
|
|
34
|
+
}, rabbitMQOptions);
|
|
35
|
+
}
|
|
36
|
+
buildRoutingKey(message) {
|
|
37
|
+
return `${message.aggregateType}.${message.eventType}`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.GolevelupPublisher = GolevelupPublisher;
|
|
41
|
+
//# sourceMappingURL=golevelup-publisher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"golevelup-publisher.js","sourceRoot":"","sources":["../src/golevelup-publisher.ts"],"names":[],"mappings":";;;AAQA,MAAa,kBAAkB;IAEV;IACA;IAFnB,YACmB,cAA8B,EAC9B,QAAgB;QADhB,mBAAc,GAAd,cAAc,CAAgB;QAC9B,aAAQ,GAAR,QAAQ,CAAQ;IAChC,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,OAAsB,EAAE,OAAwB;QAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAEjD,MAAM,eAAe,GAA2B;YAC9C,GAAG,OAAO;YACV,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE,kBAAkB;YAC/B,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE;YACtC,OAAO,EAAE;gBACP,GAAG,OAAO,EAAE,OAAO;gBACnB,kBAAkB,EAAE,OAAO,CAAC,aAAa;gBACzC,gBAAgB,EAAE,OAAO,CAAC,WAAW;gBACrC,cAAc,EAAE,OAAO,CAAC,SAAS;aAClC;SACF,CAAC;QAEF,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAC/B,IAAI,CAAC,QAAQ,EACb,UAAU,EACV;YACE,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B,EACD,eAAe,CAChB,CAAC;IACJ,CAAC;IAOO,eAAe,CAAC,OAAsB;QAC5C,OAAO,GAAG,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IACzD,CAAC;CACF;AA/CD,gDA+CC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./types"), exports);
|
|
18
|
+
__exportStar(require("./delayed-publisher"), exports);
|
|
19
|
+
__exportStar(require("./golevelup-publisher"), exports);
|
|
20
|
+
__exportStar(require("./microservices-publisher"), exports);
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,sDAAoC;AACpC,wDAAsC;AACtC,4DAA0C"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IMessagePublisher, OutboxMessage, PublishOptions } from '@prodforcode/event-forge-core';
|
|
2
|
+
export interface ClientProxy {
|
|
3
|
+
emit<TResult = unknown, TInput = unknown>(pattern: string, data: TInput): Promise<TResult> | TResult;
|
|
4
|
+
}
|
|
5
|
+
export declare class MicroservicesPublisher implements IMessagePublisher {
|
|
6
|
+
private readonly clientProxy;
|
|
7
|
+
constructor(clientProxy: ClientProxy);
|
|
8
|
+
publish(message: OutboxMessage, options?: PublishOptions): Promise<void>;
|
|
9
|
+
private buildPattern;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=microservices-publisher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"microservices-publisher.d.ts","sourceRoot":"","sources":["../src/microservices-publisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAMjG,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,EAAE,MAAM,GAAG,OAAO,EACtC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CAC/B;AAMD,qBAAa,sBAAuB,YAAW,iBAAiB;IAClD,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAAX,WAAW,EAAE,WAAW;IAE/C,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B9E,OAAO,CAAC,YAAY;CAGrB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MicroservicesPublisher = void 0;
|
|
4
|
+
class MicroservicesPublisher {
|
|
5
|
+
clientProxy;
|
|
6
|
+
constructor(clientProxy) {
|
|
7
|
+
this.clientProxy = clientProxy;
|
|
8
|
+
}
|
|
9
|
+
async publish(message, options) {
|
|
10
|
+
const pattern = this.buildPattern(message);
|
|
11
|
+
const messageData = {
|
|
12
|
+
id: message.id,
|
|
13
|
+
aggregateType: message.aggregateType,
|
|
14
|
+
aggregateId: message.aggregateId,
|
|
15
|
+
eventType: message.eventType,
|
|
16
|
+
payload: message.payload,
|
|
17
|
+
metadata: {
|
|
18
|
+
...message.metadata,
|
|
19
|
+
...options?.headers,
|
|
20
|
+
messageId: message.id,
|
|
21
|
+
timestamp: message.createdAt.getTime(),
|
|
22
|
+
persistent: true,
|
|
23
|
+
contentType: 'application/json',
|
|
24
|
+
},
|
|
25
|
+
createdAt: message.createdAt,
|
|
26
|
+
};
|
|
27
|
+
await this.clientProxy.emit(pattern, messageData);
|
|
28
|
+
}
|
|
29
|
+
buildPattern(message) {
|
|
30
|
+
return message.eventType;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.MicroservicesPublisher = MicroservicesPublisher;
|
|
34
|
+
//# sourceMappingURL=microservices-publisher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"microservices-publisher.js","sourceRoot":"","sources":["../src/microservices-publisher.ts"],"names":[],"mappings":";;;AAiBA,MAAa,sBAAsB;IACJ;IAA7B,YAA6B,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;IAAG,CAAC;IAEzD,KAAK,CAAC,OAAO,CAAC,OAAsB,EAAE,OAAwB;QAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAE3C,MAAM,WAAW,GAAG;YAClB,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE;gBACR,GAAG,OAAO,CAAC,QAAQ;gBACnB,GAAG,OAAO,EAAE,OAAO;gBACnB,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE;gBACtC,UAAU,EAAE,IAAI;gBAChB,WAAW,EAAE,kBAAkB;aAChC;YACD,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B,CAAC;QAEF,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACpD,CAAC;IASO,YAAY,CAAC,OAAsB;QACzC,OAAO,OAAO,CAAC,SAAS,CAAC;IAC3B,CAAC;CACF;AApCD,wDAoCC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PublishOptions } from '@prodforcode/event-forge-core';
|
|
2
|
+
export interface RabbitMQPublishOptions extends PublishOptions {
|
|
3
|
+
persistent?: boolean;
|
|
4
|
+
contentType?: string;
|
|
5
|
+
messageId?: string;
|
|
6
|
+
timestamp?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface AmqpConnection {
|
|
9
|
+
publish<T = unknown>(exchange: string, routingKey: string, message: T, options?: RabbitMQPublishOptions): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAK/D,MAAM,WAAW,sBAAuB,SAAQ,cAAc;IAE5D,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,CAAC,GAAG,OAAO,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,CAAC,EACV,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prodforcode/event-forge-rabbitmq",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "RabbitMQ publishers for Universal Inbox-Outbox Pattern",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"author": "Event-Forge",
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@prodforcode/event-forge-core": "1.0.
|
|
20
|
+
"@prodforcode/event-forge-core": "1.0.2"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/jest": "^29.5.11",
|