@nextage/era-lib 1.0.174 → 1.0.176
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/build/events/base-event.controller.d.ts +52 -1
- package/build/events/base-event.controller.d.ts.map +1 -1
- package/build/events/base-event.controller.js +104 -10
- package/build/events/base-event.controller.js.map +1 -1
- package/build/events/base-listener.d.ts +17 -0
- package/build/events/base-listener.d.ts.map +1 -1
- package/build/events/base-listener.js +38 -3
- package/build/events/base-listener.js.map +1 -1
- package/build/events/base-nats-listener.d.ts +17 -0
- package/build/events/base-nats-listener.d.ts.map +1 -1
- package/build/events/base-nats-listener.js +40 -2
- package/build/events/base-nats-listener.js.map +1 -1
- package/build/events/base-nats-publisher.d.ts +6 -1
- package/build/events/base-nats-publisher.d.ts.map +1 -1
- package/build/events/base-nats-publisher.js +8 -9
- package/build/events/base-nats-publisher.js.map +1 -1
- package/build/events/base-publisher.d.ts +5 -1
- package/build/events/base-publisher.d.ts.map +1 -1
- package/build/events/base-publisher.js +7 -2
- package/build/events/base-publisher.js.map +1 -1
- package/build/events/cascade.d.ts +13 -0
- package/build/events/cascade.d.ts.map +1 -0
- package/build/events/cascade.js +87 -0
- package/build/events/cascade.js.map +1 -0
- package/build/events/index.d.ts +2 -0
- package/build/events/index.d.ts.map +1 -1
- package/build/events/index.js +2 -0
- package/build/events/index.js.map +1 -1
- package/build/events/interfaces.d.ts +2 -1
- package/build/events/interfaces.d.ts.map +1 -1
- package/build/events/outbox.d.ts +12 -0
- package/build/events/outbox.d.ts.map +1 -0
- package/build/events/outbox.js +17 -0
- package/build/events/outbox.js.map +1 -0
- package/build/events/types/event-envelope.constants.d.ts +2 -0
- package/build/events/types/event-envelope.constants.d.ts.map +1 -0
- package/build/events/types/event-envelope.constants.js +11 -0
- package/build/events/types/event-envelope.constants.js.map +1 -0
- package/build/events/types/event-envelope.interfaces.d.ts +23 -0
- package/build/events/types/event-envelope.interfaces.d.ts.map +1 -0
- package/build/events/types/event-envelope.interfaces.js +3 -0
- package/build/events/types/event-envelope.interfaces.js.map +1 -0
- package/build/events/types/index.d.ts +3 -0
- package/build/events/types/index.d.ts.map +1 -1
- package/build/events/types/index.js +3 -0
- package/build/events/types/index.js.map +1 -1
- package/build/events/types/outbox.interfaces.d.ts +12 -0
- package/build/events/types/outbox.interfaces.d.ts.map +1 -0
- package/build/events/types/outbox.interfaces.js +3 -0
- package/build/events/types/outbox.interfaces.js.map +1 -0
- package/package.json +2 -2
|
@@ -30,6 +30,35 @@ export declare abstract class BaseEventCtrl<TCreate extends Event, TUpdate exten
|
|
|
30
30
|
*/
|
|
31
31
|
publish(item: TAttrs, type: QueueEventType, context: NxContext): Promise<void>;
|
|
32
32
|
/**
|
|
33
|
+
* Overridable post-write / post-read enrichment of the RETURNED document (e.g.
|
|
34
|
+
* populate references, attach a joined aggregate). Runs AFTER the atomic write
|
|
35
|
+
* and event dispatch, so a subclass can shape the doc handed back to its
|
|
36
|
+
* resolvers WITHOUT overriding create / update / get — which would shadow the
|
|
37
|
+
* transactional outbox (that was the E3 regression). Default: identity.
|
|
38
|
+
*
|
|
39
|
+
* @param doc
|
|
40
|
+
* @param context
|
|
41
|
+
*/
|
|
42
|
+
protected decorateDoc(doc: TDoc, context: NxContext): Promise<TDoc>;
|
|
43
|
+
/**
|
|
44
|
+
* Read one entity and apply the subclass `decorateDoc` enrichment.
|
|
45
|
+
*
|
|
46
|
+
* @param id
|
|
47
|
+
* @param context
|
|
48
|
+
*/
|
|
49
|
+
get(id: string, context?: NxContext): Promise<TDoc | null>;
|
|
50
|
+
/**
|
|
51
|
+
*
|
|
52
|
+
* @param item
|
|
53
|
+
* @param context
|
|
54
|
+
* @returns
|
|
55
|
+
*/
|
|
56
|
+
/**
|
|
57
|
+
* Create the entity and its outbox row ATOMICALLY (same transaction when the
|
|
58
|
+
* deployment supports it), then dispatch the event and mark the row sent after
|
|
59
|
+
* commit. A broker failure leaves the row at sent:false (recoverable), never a
|
|
60
|
+
* lost event (fixes the E2 non-atomic gap; the per-controller override that used
|
|
61
|
+
* to do this 3-op dance is removed — E3).
|
|
33
62
|
*
|
|
34
63
|
* @param item
|
|
35
64
|
* @param context
|
|
@@ -38,6 +67,7 @@ export declare abstract class BaseEventCtrl<TCreate extends Event, TUpdate exten
|
|
|
38
67
|
create(item: TAttrs, context: NxContext): Promise<TDoc>;
|
|
39
68
|
/**
|
|
40
69
|
*
|
|
70
|
+
* @param id
|
|
41
71
|
* @param item
|
|
42
72
|
* @param context
|
|
43
73
|
* @returns
|
|
@@ -45,10 +75,31 @@ export declare abstract class BaseEventCtrl<TCreate extends Event, TUpdate exten
|
|
|
45
75
|
update(id: string, item: TAttrs, context: NxContext): Promise<TDoc>;
|
|
46
76
|
/**
|
|
47
77
|
*
|
|
48
|
-
* @param
|
|
78
|
+
* @param id
|
|
49
79
|
* @param context
|
|
50
80
|
* @returns
|
|
51
81
|
*/
|
|
52
82
|
remove(id: string, context: NxContext): Promise<TDoc>;
|
|
83
|
+
/**
|
|
84
|
+
* Persist an outbox row (sent:false) for `item` inside the caller's transaction.
|
|
85
|
+
* Returns the row id, or undefined when no outbox is registered (the event is
|
|
86
|
+
* then still published, just not tracked).
|
|
87
|
+
*
|
|
88
|
+
* @param item
|
|
89
|
+
* @param type
|
|
90
|
+
* @param context
|
|
91
|
+
*/
|
|
92
|
+
private enqueueOutbox;
|
|
93
|
+
/**
|
|
94
|
+
* Dispatch the event to the broker, then mark the outbox row as sent. Runs AFTER
|
|
95
|
+
* the transaction commits, so `publish` (a non-DB side effect) is never retried
|
|
96
|
+
* by `withTransaction` and a broker failure leaves a recoverable sent:false row.
|
|
97
|
+
*
|
|
98
|
+
* @param item
|
|
99
|
+
* @param type
|
|
100
|
+
* @param outboxId
|
|
101
|
+
* @param context
|
|
102
|
+
*/
|
|
103
|
+
private dispatchOutbox;
|
|
53
104
|
}
|
|
54
105
|
//# sourceMappingURL=base-event.controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-event.controller.d.ts","sourceRoot":"","sources":["../../src/events/base-event.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAc,mDAAmD,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAW,wDAAwD,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAE,MAAS,wDAAwD,CAAC;
|
|
1
|
+
{"version":3,"file":"base-event.controller.d.ts","sourceRoot":"","sources":["../../src/events/base-event.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAc,mDAAmD,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAW,wDAAwD,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAE,MAAS,wDAAwD,CAAC;AAE3F,OAAO,EAAE,SAAS,EAAE,MAAc,sBAAsB,CAAC;AAGzD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAKjD,OAAO,EAAE,cAAc,EAAE,MAAS,eAAe,CAAC;AAOlD,8BAAsB,aAAa,CAAC,OAAO,SAAS,KAAK,EAAE,OAAO,SAAS,KAAK,EAAE,OAAO,SAAS,KAAK,EAAE,MAAM,EAAE,IAAI,SAAS,YAAY,EAAE,MAAM,SAAS,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAE,SAAQ,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;IAMnO,SAAS,CAAC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAI,OAAO,CAAC,MAAM,CAAC;IAC3F,SAAS,CAAC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAI,OAAO,CAAC,MAAM,CAAC;IAC3F,SAAS,CAAC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAI,OAAO,CAAC,MAAM,CAAC;IAE3F,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;IAC1D,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;IAC1D,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;IAK1D,OAAO,CAAC,aAAa,CAAC,CAAmD;IAEzE;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAqBxB;;;;;OAKG;IAoBH;;;;;OAKG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAWpF;;;;;;;;;OASG;cACa,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzE;;;;;OAKG;IACY,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAMzE;;;;;OAKG;IACH;;;;;;;;;;OAUG;IACY,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBtE;;;;;;OAMG;IACY,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBlF;;;;;OAKG;IACY,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBpE;;;;;;;;OAQG;YACW,aAAa;IAY3B;;;;;;;;;OASG;YACW,cAAc;CAQ7B"}
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.BaseEventCtrl = void 0;
|
|
4
4
|
const base_controller_1 = require("@nextage/nx-frame-be/build/common/base/base.controller");
|
|
5
|
+
const mongo_utils_1 = require("@nextage/nx-frame-be/build/common/base/mongo-utils");
|
|
6
|
+
const outbox_1 = require("./outbox");
|
|
7
|
+
const cascade_1 = require("./cascade");
|
|
5
8
|
const enums_1 = require("./types/enums");
|
|
6
9
|
class BaseEventCtrl extends base_controller_1.BaseController {
|
|
7
10
|
/**
|
|
@@ -59,41 +62,132 @@ class BaseEventCtrl extends base_controller_1.BaseController {
|
|
|
59
62
|
if (!publishers?.length || !parser)
|
|
60
63
|
return;
|
|
61
64
|
const data = parser(item, type);
|
|
62
|
-
|
|
65
|
+
const meta = (0, cascade_1.outgoingMeta)(context?._event);
|
|
66
|
+
await Promise.all(publishers.map(pub => pub.publish(data, meta)));
|
|
63
67
|
}
|
|
64
68
|
/**
|
|
69
|
+
* Overridable post-write / post-read enrichment of the RETURNED document (e.g.
|
|
70
|
+
* populate references, attach a joined aggregate). Runs AFTER the atomic write
|
|
71
|
+
* and event dispatch, so a subclass can shape the doc handed back to its
|
|
72
|
+
* resolvers WITHOUT overriding create / update / get — which would shadow the
|
|
73
|
+
* transactional outbox (that was the E3 regression). Default: identity.
|
|
74
|
+
*
|
|
75
|
+
* @param doc
|
|
76
|
+
* @param context
|
|
77
|
+
*/
|
|
78
|
+
async decorateDoc(doc, context) {
|
|
79
|
+
return doc;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Read one entity and apply the subclass `decorateDoc` enrichment.
|
|
83
|
+
*
|
|
84
|
+
* @param id
|
|
85
|
+
* @param context
|
|
86
|
+
*/
|
|
87
|
+
async get(id, context) {
|
|
88
|
+
const doc = await super.get(id, context);
|
|
89
|
+
return doc ? this.decorateDoc(doc, context ?? {}) : doc;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
*
|
|
93
|
+
* @param item
|
|
94
|
+
* @param context
|
|
95
|
+
* @returns
|
|
96
|
+
*/
|
|
97
|
+
/**
|
|
98
|
+
* Create the entity and its outbox row ATOMICALLY (same transaction when the
|
|
99
|
+
* deployment supports it), then dispatch the event and mark the row sent after
|
|
100
|
+
* commit. A broker failure leaves the row at sent:false (recoverable), never a
|
|
101
|
+
* lost event (fixes the E2 non-atomic gap; the per-controller override that used
|
|
102
|
+
* to do this 3-op dance is removed — E3).
|
|
65
103
|
*
|
|
66
104
|
* @param item
|
|
67
105
|
* @param context
|
|
68
106
|
* @returns
|
|
69
107
|
*/
|
|
70
108
|
async create(item, context) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
109
|
+
let payload;
|
|
110
|
+
let outboxId;
|
|
111
|
+
const res = await this.withTransaction(context, async (ctx) => {
|
|
112
|
+
const created = await super.create(item, ctx);
|
|
113
|
+
payload = created.toJSON();
|
|
114
|
+
outboxId = await this.enqueueOutbox(payload, enums_1.QueueEventType.create, ctx);
|
|
115
|
+
return created;
|
|
116
|
+
});
|
|
117
|
+
await this.dispatchOutbox(payload, enums_1.QueueEventType.create, outboxId, context);
|
|
118
|
+
return this.decorateDoc(res, context);
|
|
74
119
|
}
|
|
75
120
|
/**
|
|
76
121
|
*
|
|
122
|
+
* @param id
|
|
77
123
|
* @param item
|
|
78
124
|
* @param context
|
|
79
125
|
* @returns
|
|
80
126
|
*/
|
|
81
127
|
async update(id, item, context) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
128
|
+
let payload;
|
|
129
|
+
let outboxId;
|
|
130
|
+
const res = await this.withTransaction(context, async (ctx) => {
|
|
131
|
+
const updated = await super.update(id, item, ctx);
|
|
132
|
+
payload = { id, ...updated.toObject() };
|
|
133
|
+
outboxId = await this.enqueueOutbox(payload, enums_1.QueueEventType.update, ctx);
|
|
134
|
+
return updated;
|
|
135
|
+
});
|
|
136
|
+
await this.dispatchOutbox(payload, enums_1.QueueEventType.update, outboxId, context);
|
|
137
|
+
return this.decorateDoc(res, context);
|
|
85
138
|
}
|
|
86
139
|
/**
|
|
87
140
|
*
|
|
88
|
-
* @param
|
|
141
|
+
* @param id
|
|
89
142
|
* @param context
|
|
90
143
|
* @returns
|
|
91
144
|
*/
|
|
92
145
|
async remove(id, context) {
|
|
93
|
-
|
|
94
|
-
|
|
146
|
+
let payload;
|
|
147
|
+
let outboxId;
|
|
148
|
+
const res = await this.withTransaction(context, async (ctx) => {
|
|
149
|
+
const removed = await this.model.remove(id, ctx);
|
|
150
|
+
payload = { id, ...removed.toObject() };
|
|
151
|
+
outboxId = await this.enqueueOutbox(payload, enums_1.QueueEventType.remove, ctx);
|
|
152
|
+
return removed;
|
|
153
|
+
});
|
|
154
|
+
await this.dispatchOutbox(payload, enums_1.QueueEventType.remove, outboxId, context);
|
|
95
155
|
return res;
|
|
96
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Persist an outbox row (sent:false) for `item` inside the caller's transaction.
|
|
159
|
+
* Returns the row id, or undefined when no outbox is registered (the event is
|
|
160
|
+
* then still published, just not tracked).
|
|
161
|
+
*
|
|
162
|
+
* @param item
|
|
163
|
+
* @param type
|
|
164
|
+
* @param context
|
|
165
|
+
*/
|
|
166
|
+
async enqueueOutbox(item, type, context) {
|
|
167
|
+
const outbox = (0, outbox_1.getOutbox)();
|
|
168
|
+
if (!outbox)
|
|
169
|
+
return undefined;
|
|
170
|
+
const id = (0, mongo_utils_1.genObjectId)().toString();
|
|
171
|
+
const evt = { id, type, data: item };
|
|
172
|
+
await outbox.create(evt, context);
|
|
173
|
+
return id;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Dispatch the event to the broker, then mark the outbox row as sent. Runs AFTER
|
|
177
|
+
* the transaction commits, so `publish` (a non-DB side effect) is never retried
|
|
178
|
+
* by `withTransaction` and a broker failure leaves a recoverable sent:false row.
|
|
179
|
+
*
|
|
180
|
+
* @param item
|
|
181
|
+
* @param type
|
|
182
|
+
* @param outboxId
|
|
183
|
+
* @param context
|
|
184
|
+
*/
|
|
185
|
+
async dispatchOutbox(item, type, outboxId, context) {
|
|
186
|
+
await this.publish(item, type, context);
|
|
187
|
+
const outbox = (0, outbox_1.getOutbox)();
|
|
188
|
+
if (outbox && outboxId)
|
|
189
|
+
await outbox.markSent(outboxId, context);
|
|
190
|
+
}
|
|
97
191
|
}
|
|
98
192
|
exports.BaseEventCtrl = BaseEventCtrl;
|
|
99
193
|
//# sourceMappingURL=base-event.controller.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-event.controller.js","sourceRoot":"","sources":["../../src/events/base-event.controller.ts"],"names":[],"mappings":";;;AAEA,4FAA2F;
|
|
1
|
+
{"version":3,"file":"base-event.controller.js","sourceRoot":"","sources":["../../src/events/base-event.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { NxContext } from '@nextage/nx-frame-be';
|
|
1
2
|
import { Message } from './event-message';
|
|
2
3
|
import { Event, MsgClientInterface, EventSubOptions } from './interfaces';
|
|
4
|
+
import { EventContext, IncomingEventRef } from './types/event-envelope.interfaces';
|
|
3
5
|
export declare abstract class Listener<T extends Event> {
|
|
4
6
|
abstract subject: T['subject'];
|
|
5
7
|
abstract queueGroupName: string;
|
|
@@ -8,6 +10,7 @@ export declare abstract class Listener<T extends Event> {
|
|
|
8
10
|
private subscription;
|
|
9
11
|
private messageStack;
|
|
10
12
|
private wait;
|
|
13
|
+
protected _incoming: IncomingEventRef | undefined;
|
|
11
14
|
protected ackWait: number;
|
|
12
15
|
constructor(client: MsgClientInterface);
|
|
13
16
|
subscriptionOptions(): EventSubOptions;
|
|
@@ -17,6 +20,20 @@ export declare abstract class Listener<T extends Event> {
|
|
|
17
20
|
* @returns
|
|
18
21
|
*/
|
|
19
22
|
checkMessages(): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Process a single message: unwrap the envelope, apply the cascade loop-guard,
|
|
25
|
+
* then dispatch to `onMessage`. A guard violation (runaway depth or revisited
|
|
26
|
+
* subject) is skipped — the in-memory bus has no ack/redelivery to fight — and
|
|
27
|
+
* the in-flight reference is always cleared so `nextContext` never leaks the
|
|
28
|
+
* previous event.
|
|
29
|
+
*/
|
|
30
|
+
protected handleMessage(msg: Message): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Build a child context carrying the in-flight event reference, so any event
|
|
33
|
+
* this listener republishes inherits the correlation and advances the cascade
|
|
34
|
+
* depth / visited lineage. Returns a fresh object (never mutates `base`).
|
|
35
|
+
*/
|
|
36
|
+
protected nextContext(base?: NxContext): EventContext;
|
|
20
37
|
/**
|
|
21
38
|
*
|
|
22
39
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-listener.d.ts","sourceRoot":"","sources":["../../src/events/base-listener.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"base-listener.d.ts","sourceRoot":"","sources":["../../src/events/base-listener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,SAAS,EAAE,MAAqB,sBAAsB,CAAC;AAClF,OAAO,EAAE,OAAO,EAAE,MAAyC,iBAAiB,CAAC;AAE7E,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAkB,mCAAmC,CAAC;AAG/F,8BAAsB,QAAQ,CAAC,CAAC,SAAS,KAAK;IAE5C,QAAQ,CAAC,OAAO,EAAS,CAAC,CAAC,SAAS,CAAC,CAAC;IACtC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAEhC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAEhE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,YAAY,CAAmC;IAEvD,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,IAAI,CAA+B;IAI3C,SAAS,CAAC,SAAS,EAAM,gBAAgB,GAAG,SAAS,CAAC;IAEtD,SAAS,CAAC,OAAO,EAAQ,MAAM,CAAe;gBAEjC,MAAM,EAAE,kBAAkB;IAIvC,mBAAmB,IAAI,eAAe;IAKhC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB7B;;;OAGG;IACG,aAAa;IAsBnB;;;;;;OAMG;cACa,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB1D;;;;OAIG;IACH,SAAS,CAAC,WAAW,CAAC,IAAI,GAAE,SAAc,GAAG,YAAY;IAKzD;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B;;;;OAIG;IACH,OAAO,CAAC,YAAY;CAKrB"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Listener = void 0;
|
|
4
4
|
const nx_frame_be_1 = require("@nextage/nx-frame-be");
|
|
5
|
+
const cascade_1 = require("./cascade");
|
|
5
6
|
class Listener {
|
|
6
7
|
constructor(client) {
|
|
7
8
|
this.messageStack = [];
|
|
@@ -33,11 +34,45 @@ class Listener {
|
|
|
33
34
|
if (!msg)
|
|
34
35
|
return;
|
|
35
36
|
this.wait = true;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
try {
|
|
38
|
+
await this.handleMessage(msg);
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
this.wait = false;
|
|
42
|
+
}
|
|
39
43
|
await this.checkMessages();
|
|
40
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Process a single message: unwrap the envelope, apply the cascade loop-guard,
|
|
47
|
+
* then dispatch to `onMessage`. A guard violation (runaway depth or revisited
|
|
48
|
+
* subject) is skipped — the in-memory bus has no ack/redelivery to fight — and
|
|
49
|
+
* the in-flight reference is always cleared so `nextContext` never leaks the
|
|
50
|
+
* previous event.
|
|
51
|
+
*/
|
|
52
|
+
async handleMessage(msg) {
|
|
53
|
+
try {
|
|
54
|
+
const { id, data, meta } = (0, cascade_1.unwrapEnvelope)(this.parseMessage(msg));
|
|
55
|
+
const violation = (0, cascade_1.cascadeViolation)(meta, this.subject);
|
|
56
|
+
if (violation) {
|
|
57
|
+
nx_frame_be_1.APP.logger.warn(`🔁 Cascade guard tripped on '${this.subject}': ${violation}`, (0, nx_frame_be_1.logClassCtx)(this));
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
this._incoming = { id, subject: this.subject, meta };
|
|
61
|
+
await this.onMessage(data, msg);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
this._incoming = undefined;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Build a child context carrying the in-flight event reference, so any event
|
|
70
|
+
* this listener republishes inherits the correlation and advances the cascade
|
|
71
|
+
* depth / visited lineage. Returns a fresh object (never mutates `base`).
|
|
72
|
+
*/
|
|
73
|
+
nextContext(base = {}) {
|
|
74
|
+
return this._incoming ? { ...base, _event: this._incoming } : { ...base };
|
|
75
|
+
}
|
|
41
76
|
/**
|
|
42
77
|
*
|
|
43
78
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-listener.js","sourceRoot":"","sources":["../../src/events/base-listener.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"base-listener.js","sourceRoot":"","sources":["../../src/events/base-listener.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { NxContext } from '@nextage/nx-frame-be';
|
|
1
2
|
import { Event, MsgClientInterface, EventSubOptions } from './interfaces';
|
|
3
|
+
import { EventContext, IncomingEventRef } from './types/event-envelope.interfaces';
|
|
2
4
|
import { JsMsg } from 'nats';
|
|
3
5
|
export declare abstract class NatsListener<T extends Event> {
|
|
4
6
|
private readonly client;
|
|
@@ -7,6 +9,7 @@ export declare abstract class NatsListener<T extends Event> {
|
|
|
7
9
|
abstract streamName: string;
|
|
8
10
|
private consumer?;
|
|
9
11
|
private isListening;
|
|
12
|
+
protected _incoming?: IncomingEventRef;
|
|
10
13
|
protected ackWait: number;
|
|
11
14
|
protected maxDeliver: number;
|
|
12
15
|
protected nakBackoffMs: number[];
|
|
@@ -37,6 +40,20 @@ export declare abstract class NatsListener<T extends Event> {
|
|
|
37
40
|
* than `term()`, so an unreachable DLQ never causes silent message loss.
|
|
38
41
|
*/
|
|
39
42
|
protected handleMessage(msg: JsMsg): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Park a cascade-guard violation on the DLQ and terminate it so it never
|
|
45
|
+
* re-enters the source stream. Falls back to `nak` only if the DLQ is
|
|
46
|
+
* unreachable, so a loop is never silently lost.
|
|
47
|
+
*/
|
|
48
|
+
protected dropCascadeViolation(msg: JsMsg, reason: string): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Build a child context carrying the in-flight event reference, so any event
|
|
51
|
+
* this listener republishes inherits the correlation, is marked as caused by
|
|
52
|
+
* the current event, and advances the cascade depth / visited lineage. Returns
|
|
53
|
+
* a fresh object (never mutates the shared base context). At the root — or when
|
|
54
|
+
* no event is in flight — it is just a copy of `base`.
|
|
55
|
+
*/
|
|
56
|
+
protected nextContext(base?: NxContext): EventContext;
|
|
40
57
|
/**
|
|
41
58
|
* Parks a failed message on the DLQ stream. Returns `true` on success so the
|
|
42
59
|
* caller can safely `term()` the original; returns `false` if the DLQ could
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-nats-listener.d.ts","sourceRoot":"","sources":["../../src/events/base-nats-listener.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"base-nats-listener.d.ts","sourceRoot":"","sources":["../../src/events/base-nats-listener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,SAAS,EAAE,MAAkC,sBAAsB,CAAC;AAClF,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG1E,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAkB,mCAAmC,CAAC;AAE/F,OAAO,EAAY,KAAK,EAAE,MAAiC,MAAM,CAAC;AAElE,8BAAsB,YAAY,CAAC,CAAC,SAAS,KAAK;IA2BnC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAzBpC,QAAQ,CAAC,OAAO,EAAS,CAAC,CAAC,SAAS,CAAC,CAAC;IACtC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAM,MAAM,CAAC;IAEhC,OAAO,CAAC,QAAQ,CAAC,CAAiB;IAClC,OAAO,CAAC,WAAW,CAAsB;IAMzC,SAAS,CAAC,SAAS,CAAC,EAAK,gBAAgB,CAAC;IAE1C,SAAS,CAAC,OAAO,EAAQ,MAAM,CAAuB;IACtD,SAAS,CAAC,UAAU,EAAK,MAAM,CAAK;IAMpC,SAAS,CAAC,YAAY,EAAG,MAAM,EAAE,CAAuB;IAGxD,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;gBAEhC,MAAM,EAAE,kBAAkB;IAExD;;;OAGG;IACH,mBAAmB,IAAI,eAAe;IAKtC;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB7B;;;;OAIG;YACW,eAAe;IAqB7B;;;;;;;;OAQG;cACa,aAAa,CAAC,GAAG,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAmDxD;;;;OAIG;cACa,oBAAoB,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU/E;;;;;;OAMG;IACH,SAAS,CAAC,WAAW,CAAC,IAAI,GAAE,SAAc,GAAG,YAAY;IAKzD;;;;OAIG;cACa,gBAAgB,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAyB9E;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAe3B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAKvB;;OAEG;IACH,OAAO,CAAC,UAAU;IAMlB;;;;OAIG;IACH,OAAO,CAAC,MAAM;IAKd;;;;OAIG;IACH,OAAO,CAAC,YAAY;CAYrB"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.NatsListener = void 0;
|
|
4
4
|
const nx_frame_be_1 = require("@nextage/nx-frame-be");
|
|
5
5
|
const dlq_constants_1 = require("./types/dlq.constants");
|
|
6
|
+
const cascade_1 = require("./cascade");
|
|
6
7
|
class NatsListener {
|
|
7
8
|
constructor(client) {
|
|
8
9
|
this.client = client;
|
|
@@ -75,8 +76,19 @@ class NatsListener {
|
|
|
75
76
|
async handleMessage(msg) {
|
|
76
77
|
try {
|
|
77
78
|
nx_frame_be_1.APP.logger.info(`📥 Received message on '${this.subject}'`);
|
|
78
|
-
const
|
|
79
|
-
|
|
79
|
+
const { id, data, meta } = (0, cascade_1.unwrapEnvelope)(this.parseMessage(msg));
|
|
80
|
+
// Cascade governance: a runaway depth or a revisited subject is a loop, not
|
|
81
|
+
// a transient failure — park it on the DLQ and drop it immediately (no
|
|
82
|
+
// retries, which would only replay the same loop three more times).
|
|
83
|
+
const violation = (0, cascade_1.cascadeViolation)(meta, this.subject);
|
|
84
|
+
if (violation) {
|
|
85
|
+
await this.dropCascadeViolation(msg, violation);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Expose the in-flight event so `onMessage` can thread its metadata into any
|
|
89
|
+
// republished event via `nextContext`.
|
|
90
|
+
this._incoming = { id, subject: this.subject, meta };
|
|
91
|
+
await this.onMessage(data, msg);
|
|
80
92
|
msg.ack();
|
|
81
93
|
nx_frame_be_1.APP.logger.info(`✅ Message acknowledged on '${this.subject}'`);
|
|
82
94
|
}
|
|
@@ -94,6 +106,32 @@ class NatsListener {
|
|
|
94
106
|
msg.nak(this.backoffFor(deliveries));
|
|
95
107
|
}
|
|
96
108
|
}
|
|
109
|
+
finally {
|
|
110
|
+
this._incoming = undefined;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Park a cascade-guard violation on the DLQ and terminate it so it never
|
|
115
|
+
* re-enters the source stream. Falls back to `nak` only if the DLQ is
|
|
116
|
+
* unreachable, so a loop is never silently lost.
|
|
117
|
+
*/
|
|
118
|
+
async dropCascadeViolation(msg, reason) {
|
|
119
|
+
nx_frame_be_1.APP.logger.warn(`🔁 Cascade guard tripped on '${this.subject}': ${reason}`);
|
|
120
|
+
const parked = await this.sendToDeadLetter(msg, new Error(`cascade-guard: ${reason}`));
|
|
121
|
+
if (parked)
|
|
122
|
+
msg.term();
|
|
123
|
+
else
|
|
124
|
+
msg.nak(this.backoffFor(this.deliveryAttempt(msg)));
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Build a child context carrying the in-flight event reference, so any event
|
|
128
|
+
* this listener republishes inherits the correlation, is marked as caused by
|
|
129
|
+
* the current event, and advances the cascade depth / visited lineage. Returns
|
|
130
|
+
* a fresh object (never mutates the shared base context). At the root — or when
|
|
131
|
+
* no event is in flight — it is just a copy of `base`.
|
|
132
|
+
*/
|
|
133
|
+
nextContext(base = {}) {
|
|
134
|
+
return this._incoming ? { ...base, _event: this._incoming } : { ...base };
|
|
97
135
|
}
|
|
98
136
|
/**
|
|
99
137
|
* Parks a failed message on the DLQ stream. Returns `true` on success so the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-nats-listener.js","sourceRoot":"","sources":["../../src/events/base-nats-listener.ts"],"names":[],"mappings":";;;AAAA,sDAAkF;AAElF,yDAAmF;
|
|
1
|
+
{"version":3,"file":"base-nats-listener.js","sourceRoot":"","sources":["../../src/events/base-nats-listener.ts"],"names":[],"mappings":";;;AAAA,sDAAkF;AAElF,yDAAmF;AAGnF,uCAAuE;AAGvE,MAAsB,YAAY;IA2BhC,YAA8B,MAA0B;QAA1B,WAAM,GAAN,MAAM,CAAoB;QApBhD,gBAAW,GAAgB,KAAK,CAAC;QAQ/B,YAAO,GAAiB,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC,6BAA6B;QAC1E,eAAU,GAAc,CAAC,CAAC;QAEpC,0EAA0E;QAC1E,wEAAwE;QACxE,0EAA0E;QAC1E,mBAAmB;QACT,iBAAY,GAAc,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAKI,CAAC;IAE7D;;;OAGG;IACH,mBAAmB;QAEjB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM;QAEV,IAAI,CAAC;YAEH,kDAAkD;YAClD,MAAM,IAAI,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;YACtE,IAAI,CAAC,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;YAEtG,+FAA+F;YAE/F,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;YAExB,IAAI,CAAC,eAAe,EAAE,CAAC;QAEzB,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YAEb,iBAAG,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,IAAI,CAAC,OAAO,OAAO,EAAE,KAAK,CAAC,CAAC;YAChF,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,eAAe;QAE3B,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAE3B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAE/C,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBACjC,IAAI,CAAC,IAAI,CAAC,WAAW;oBAAE,MAAM;gBAE7B,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,iBAAG,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,IAAI,CAAC,OAAO,OAAO,EAAE,KAAK,CAAC,CAAC;gBACrE,8BAA8B;gBAC9B,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,IAAI,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACO,KAAK,CAAC,aAAa,CAAC,GAAU;QAEtC,IAAI,CAAC;YAEH,iBAAG,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;YAE5D,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAA,wBAAc,EAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;YAElE,4EAA4E;YAC5E,uEAAuE;YACvE,oEAAoE;YACpE,MAAM,SAAS,GAAG,IAAA,0BAAgB,EAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACvD,IAAI,SAAS,EAAE,CAAC;gBAEd,MAAM,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;gBAChD,OAAO;YACT,CAAC;YAED,6EAA6E;YAC7E,uCAAuC;YACvC,IAAI,CAAC,SAAS,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;YAErD,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAEhC,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,iBAAG,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YAEb,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YAE7C,iBAAG,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,IAAI,CAAC,OAAO,eAAe,UAAU,IAAI,IAAI,CAAC,UAAU,OAAO,EAAE,KAAK,CAAC,CAAC;YAEhH,IAAI,UAAU,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBAElC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;gBAEvD,IAAI,MAAM;oBAAE,GAAG,CAAC,IAAI,EAAE,CAAC;;oBACX,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,qCAAqC;YACzF,CAAC;iBACI,CAAC;gBAEJ,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;gBACO,CAAC;YAEP,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC7B,CAAC;IACH,CAAC;IAED;;;;OAIG;IACO,KAAK,CAAC,oBAAoB,CAAC,GAAU,EAAE,MAAc;QAE7D,iBAAG,CAAC,MAAM,CAAC,IAAI,CAAC,gCAAgC,IAAI,CAAC,OAAO,MAAM,MAAM,EAAE,CAAC,CAAC;QAE5E,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC,kBAAkB,MAAM,EAAE,CAAC,CAAC,CAAC;QAEvF,IAAI,MAAM;YAAE,GAAG,CAAC,IAAI,EAAE,CAAC;;YACX,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAClE,CAAC;IAED;;;;;;OAMG;IACO,WAAW,CAAC,OAAkB,EAAE;QAExC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC;IAC5E,CAAC;IAED;;;;OAIG;IACO,KAAK,CAAC,gBAAgB,CAAC,GAAU,EAAE,KAAc;QAEzD,MAAM,QAAQ,GAAuB;YACnC,eAAe,EAAE,IAAI,CAAC,OAAO;YAC7B,UAAU,EAAO,IAAI,CAAC,UAAU;YAChC,cAAc,EAAG,IAAI,CAAC,cAAc;YACpC,aAAa,EAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC;YAC1C,KAAK,EAAY,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YACvE,IAAI,EAAa,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;YACjC,SAAS,EAAQ,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SAC1C,CAAC;QAEF,IAAI,CAAC;YAEH,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,kCAAkB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC5F,iBAAG,CAAC,MAAM,CAAC,IAAI,CAAC,kCAAkC,IAAI,CAAC,OAAO,WAAW,QAAQ,CAAC,aAAa,aAAa,CAAC,CAAC;YAC9G,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,QAAQ,EAAE,CAAC;YAEhB,iBAAG,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,IAAI,CAAC,OAAO,OAAO,EAAE,QAAQ,CAAC,CAAC;YACzF,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI;QAER,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QAEzB,IAAI,CAAC,IAAI,CAAC,QAAQ;YAChB,OAAO;QAET,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;YAClF,iBAAG,CAAC,MAAM,CAAC,IAAI,CAAC,oCAAoC,IAAI,CAAC,cAAc,UAAU,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QACpG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,iBAAG,CAAC,MAAM,CAAC,IAAI,CAAC,4BAA4B,IAAI,CAAC,OAAO,4CAA4C,CAAC,CAAC;QACxG,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,eAAe,CAAC,GAAU;QAEhC,OAAO,GAAG,CAAC,IAAI,EAAE,aAAa,IAAI,CAAC,CAAC;IACtC,CAAC;IAED;;OAEG;IACK,UAAU,CAAC,UAAkB;QAEnC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAChF,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED;;;;OAIG;IACK,MAAM,CAAC,GAAU;QAEvB,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACK,YAAY,CAAC,GAAU;QAE7B,IAAI,CAAC;YAEH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YAEb,iBAAG,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,IAAI,CAAC,OAAO,OAAO,EAAE,KAAK,CAAC,CAAC;YAC9E,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;CACF;AA9QD,oCA8QC"}
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { JetStreamPublishOptions } from 'nats';
|
|
2
2
|
import { Event, IPublisher, MsgClientInterface } from './interfaces';
|
|
3
|
+
import { EventMeta } from './types/event-envelope.interfaces';
|
|
3
4
|
export declare abstract class NatsPublisher<T extends Event> implements IPublisher<T, Partial<JetStreamPublishOptions>> {
|
|
4
5
|
private readonly client;
|
|
5
6
|
abstract subject: T['subject'];
|
|
6
7
|
constructor(client: MsgClientInterface);
|
|
7
8
|
/**
|
|
9
|
+
* Emit the event wrapped in the shared in-band envelope (id / subject / data /
|
|
10
|
+
* timestamp / cascade meta). The metadata rides in the payload so loop-guard and
|
|
11
|
+
* causation tracing stay transport agnostic.
|
|
8
12
|
*
|
|
9
13
|
* @param data
|
|
14
|
+
* @param meta
|
|
10
15
|
* @param options
|
|
11
16
|
*/
|
|
12
|
-
publish(data: T['data'], options?: Partial<JetStreamPublishOptions>): Promise<void>;
|
|
17
|
+
publish(data: T['data'], meta?: EventMeta, options?: Partial<JetStreamPublishOptions>): Promise<void>;
|
|
13
18
|
}
|
|
14
19
|
//# sourceMappingURL=base-nats-publisher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-nats-publisher.d.ts","sourceRoot":"","sources":["../../src/events/base-nats-publisher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"base-nats-publisher.d.ts","sourceRoot":"","sources":["../../src/events/base-nats-publisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAoB,MAAM,CAAC;AAC7D,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAkC,mCAAmC,CAAC;AAG1F,8BAAsB,aAAa,CAAC,CAAC,SAAS,KAAK,CAAE,YAAW,UAAU,CAAC,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAIjG,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;gBAEF,MAAM,EAAE,kBAAkB;IAEvD;;;;;;;;OAQG;IACG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAiB5G"}
|
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NatsPublisher = void 0;
|
|
4
|
-
const
|
|
4
|
+
const cascade_1 = require("./cascade");
|
|
5
5
|
class NatsPublisher {
|
|
6
6
|
constructor(client) {
|
|
7
7
|
this.client = client;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
+
* Emit the event wrapped in the shared in-band envelope (id / subject / data /
|
|
11
|
+
* timestamp / cascade meta). The metadata rides in the payload so loop-guard and
|
|
12
|
+
* causation tracing stay transport agnostic.
|
|
10
13
|
*
|
|
11
14
|
* @param data
|
|
15
|
+
* @param meta
|
|
12
16
|
* @param options
|
|
13
17
|
*/
|
|
14
|
-
async publish(data, options) {
|
|
18
|
+
async publish(data, meta, options) {
|
|
15
19
|
try {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
subject: this.subject,
|
|
19
|
-
data,
|
|
20
|
-
timestamp: new Date().toISOString(),
|
|
21
|
-
};
|
|
22
|
-
await this.client.publish(this.subject, JSON.stringify(message), options);
|
|
20
|
+
const envelope = (0, cascade_1.buildEnvelope)(this.subject, data, meta);
|
|
21
|
+
await this.client.publish(this.subject, JSON.stringify(envelope), options);
|
|
23
22
|
}
|
|
24
23
|
catch (error) {
|
|
25
24
|
console.error(`❌ Failed to publish to '${this.subject}':`, error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-nats-publisher.js","sourceRoot":"","sources":["../../src/events/base-nats-publisher.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"base-nats-publisher.js","sourceRoot":"","sources":["../../src/events/base-nats-publisher.ts"],"names":[],"mappings":";;;AAGA,uCAAkE;AAElE,MAAsB,aAAa;IAIjC,YAA6B,MAA0B;QAA1B,WAAM,GAAN,MAAM,CAAoB;IAAG,CAAC;IAE3D;;;;;;;;OAQG;IACH,KAAK,CAAC,OAAO,CAAC,IAAe,EAAE,IAAgB,EAAE,OAA0C;QAE1F,IAAI,CAAC;YAEF,MAAM,QAAQ,GAAG,IAAA,uBAAa,EAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAEzD,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CACvB,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EACxB,OAAO,CACR,CAAC;QAEJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,2BAA2B,IAAI,CAAC,OAAO,IAAI,EAAE,KAAK,CAAC,CAAC;YAClE,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF;AAhCD,sCAgCC"}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { Event, IPublisher, MsgClientInterface } from './interfaces';
|
|
2
|
+
import { EventMeta } from './types/event-envelope.interfaces';
|
|
2
3
|
export declare abstract class Publisher<T extends Event> implements IPublisher<T> {
|
|
3
4
|
abstract subject: T['subject'];
|
|
4
5
|
private readonly client;
|
|
5
6
|
constructor(client: MsgClientInterface);
|
|
6
7
|
/**
|
|
8
|
+
* Emit the event wrapped in the shared in-band envelope, so the msg bus carries
|
|
9
|
+
* the same cascade metadata as the NATS transport (transport-agnostic tracing).
|
|
7
10
|
*
|
|
8
11
|
* @param data
|
|
12
|
+
* @param meta
|
|
9
13
|
* @returns
|
|
10
14
|
*/
|
|
11
|
-
publish(data: T['data']): Promise<void>;
|
|
15
|
+
publish(data: T['data'], meta?: EventMeta): Promise<void>;
|
|
12
16
|
}
|
|
13
17
|
//# sourceMappingURL=base-publisher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-publisher.d.ts","sourceRoot":"","sources":["../../src/events/base-publisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"base-publisher.d.ts","sourceRoot":"","sources":["../../src/events/base-publisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAkC,mCAAmC,CAAC;AAG1F,8BAAsB,SAAS,CAAC,CAAC,SAAS,KAAK,CAAE,YAAW,UAAU,CAAC,CAAC,CAAC;IAEvE,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;IAE/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;gBAEhC,MAAM,EAAE,kBAAkB;IAKtC;;;;;;;OAOG;IACG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;CAKhE"}
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Publisher = void 0;
|
|
4
|
+
const cascade_1 = require("./cascade");
|
|
4
5
|
class Publisher {
|
|
5
6
|
constructor(client) {
|
|
6
7
|
this.client = client;
|
|
7
8
|
}
|
|
8
9
|
/**
|
|
10
|
+
* Emit the event wrapped in the shared in-band envelope, so the msg bus carries
|
|
11
|
+
* the same cascade metadata as the NATS transport (transport-agnostic tracing).
|
|
9
12
|
*
|
|
10
13
|
* @param data
|
|
14
|
+
* @param meta
|
|
11
15
|
* @returns
|
|
12
16
|
*/
|
|
13
|
-
async publish(data) {
|
|
14
|
-
|
|
17
|
+
async publish(data, meta) {
|
|
18
|
+
const envelope = (0, cascade_1.buildEnvelope)(this.subject, data, meta);
|
|
19
|
+
return await this.client.publish(this.subject, JSON.stringify(envelope));
|
|
15
20
|
}
|
|
16
21
|
}
|
|
17
22
|
exports.Publisher = Publisher;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-publisher.js","sourceRoot":"","sources":["../../src/events/base-publisher.ts"],"names":[],"mappings":";;;AAEA,MAAsB,SAAS;IAM7B,YAAY,MAA0B;QAEpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"base-publisher.js","sourceRoot":"","sources":["../../src/events/base-publisher.ts"],"names":[],"mappings":";;;AAEA,uCAAkE;AAElE,MAAsB,SAAS;IAM7B,YAAY,MAA0B;QAEpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO,CAAC,IAAe,EAAE,IAAgB;QAE7C,MAAM,QAAQ,GAAG,IAAA,uBAAa,EAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACzD,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC3E,CAAC;CACF;AAxBD,8BAwBC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EventEnvelope, EventMeta, IncomingEventRef } from './types/event-envelope.interfaces';
|
|
2
|
+
export declare function rootMeta(): EventMeta;
|
|
3
|
+
export declare function nextMeta(incoming: IncomingEventRef): EventMeta;
|
|
4
|
+
export declare function outgoingMeta(incoming?: IncomingEventRef): EventMeta;
|
|
5
|
+
export declare function normalizeMeta(meta?: Partial<EventMeta>): EventMeta;
|
|
6
|
+
export declare function unwrapEnvelope<T = any>(parsed: any): {
|
|
7
|
+
id: string;
|
|
8
|
+
data: T;
|
|
9
|
+
meta: EventMeta;
|
|
10
|
+
};
|
|
11
|
+
export declare function cascadeViolation(meta: EventMeta, subject: string): string | undefined;
|
|
12
|
+
export declare function buildEnvelope<T>(subject: string, data: T, meta?: EventMeta): EventEnvelope<T>;
|
|
13
|
+
//# sourceMappingURL=cascade.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cascade.d.ts","sourceRoot":"","sources":["../../src/events/cascade.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAY/F,wBAAgB,QAAQ,IAAI,SAAS,CAGpC;AAKD,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,GAAG,SAAS,CAQ9D;AAID,wBAAgB,YAAY,CAAC,QAAQ,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAGnE;AAID,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAWlE;AAQD,wBAAgB,cAAc,CAAC,CAAC,GAAG,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAE,CAW7F;AAMD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASrF;AAGD,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,CAS7F"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rootMeta = rootMeta;
|
|
4
|
+
exports.nextMeta = nextMeta;
|
|
5
|
+
exports.outgoingMeta = outgoingMeta;
|
|
6
|
+
exports.normalizeMeta = normalizeMeta;
|
|
7
|
+
exports.unwrapEnvelope = unwrapEnvelope;
|
|
8
|
+
exports.cascadeViolation = cascadeViolation;
|
|
9
|
+
exports.buildEnvelope = buildEnvelope;
|
|
10
|
+
const nx_frame_be_1 = require("@nextage/nx-frame-be");
|
|
11
|
+
const event_envelope_constants_1 = require("./types/event-envelope.constants");
|
|
12
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
13
|
+
// Cascade metadata helpers
|
|
14
|
+
//
|
|
15
|
+
// Pure functions that derive and validate the tracing metadata carried by every
|
|
16
|
+
// event. They are transport agnostic (no NATS / msg types) so both listener
|
|
17
|
+
// families and `BaseEventCtrl` share exactly the same rules.
|
|
18
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
19
|
+
// Metadata for a ROOT event (no parent in flight): a brand-new correlation.
|
|
20
|
+
function rootMeta() {
|
|
21
|
+
return { correlationId: (0, nx_frame_be_1.uuid)(), depth: 0, visited: [] };
|
|
22
|
+
}
|
|
23
|
+
// Metadata for an event published WHILE processing `incoming`: same correlation,
|
|
24
|
+
// caused by `incoming`, one hop deeper, with `incoming.subject` appended to the
|
|
25
|
+
// visited lineage (so a later re-touch of that subject is detectable as a cycle).
|
|
26
|
+
function nextMeta(incoming) {
|
|
27
|
+
return {
|
|
28
|
+
correlationId: incoming.meta.correlationId,
|
|
29
|
+
causationId: incoming.id,
|
|
30
|
+
depth: incoming.meta.depth + 1,
|
|
31
|
+
visited: [...incoming.meta.visited, incoming.subject],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// Outgoing metadata for a publish: `nextMeta` when a parent event is in flight
|
|
35
|
+
// (cascade), otherwise a fresh `rootMeta` (root command).
|
|
36
|
+
function outgoingMeta(incoming) {
|
|
37
|
+
return incoming ? nextMeta(incoming) : rootMeta();
|
|
38
|
+
}
|
|
39
|
+
// Normalize possibly-missing/partial metadata read off the wire into a full
|
|
40
|
+
// `EventMeta` (legacy / bare payloads have none → treated as a fresh root).
|
|
41
|
+
function normalizeMeta(meta) {
|
|
42
|
+
if (!meta || typeof meta.depth !== 'number' || !Array.isArray(meta.visited) || !meta.correlationId)
|
|
43
|
+
return rootMeta();
|
|
44
|
+
return {
|
|
45
|
+
correlationId: meta.correlationId,
|
|
46
|
+
causationId: meta.causationId,
|
|
47
|
+
depth: meta.depth,
|
|
48
|
+
visited: meta.visited,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Unwrap a parsed payload into `{ id, data, meta }`, tolerating three shapes:
|
|
52
|
+
// - full envelope { id, subject, data, timestamp, meta } (current)
|
|
53
|
+
// - NATS envelope { id, subject, data, timestamp } (pre-meta)
|
|
54
|
+
// - bare data the event data object itself (legacy msg path)
|
|
55
|
+
// The heuristic keys on `data` + (`meta` | `subject`); event data objects never
|
|
56
|
+
// carry a `subject` field, so bare payloads are never mistaken for envelopes.
|
|
57
|
+
function unwrapEnvelope(parsed) {
|
|
58
|
+
const isEnvelope = parsed
|
|
59
|
+
&& typeof parsed === 'object'
|
|
60
|
+
&& 'data' in parsed
|
|
61
|
+
&& ('meta' in parsed || 'subject' in parsed);
|
|
62
|
+
if (isEnvelope)
|
|
63
|
+
return { id: parsed.id ?? (0, nx_frame_be_1.uuid)(), data: parsed.data, meta: normalizeMeta(parsed.meta) };
|
|
64
|
+
return { id: (0, nx_frame_be_1.uuid)(), data: parsed, meta: rootMeta() };
|
|
65
|
+
}
|
|
66
|
+
// Decide whether processing `subject` at this `meta` violates cascade governance.
|
|
67
|
+
// Returns a human-readable reason (for the DLQ / logs) or `undefined` when safe:
|
|
68
|
+
// - depth ceiling reached → runaway loop
|
|
69
|
+
// - `subject` already visited in this lineage → cycle
|
|
70
|
+
function cascadeViolation(meta, subject) {
|
|
71
|
+
if (meta.depth >= event_envelope_constants_1.MAX_CASCADE_DEPTH)
|
|
72
|
+
return `cascade depth ${meta.depth} >= ${event_envelope_constants_1.MAX_CASCADE_DEPTH} (runaway loop)`;
|
|
73
|
+
if (meta.visited.includes(subject))
|
|
74
|
+
return `cascade cycle: subject '${subject}' already visited [${meta.visited.join(' -> ')}]`;
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
// Build the envelope a publisher puts on the wire.
|
|
78
|
+
function buildEnvelope(subject, data, meta) {
|
|
79
|
+
return {
|
|
80
|
+
id: (0, nx_frame_be_1.uuid)(),
|
|
81
|
+
subject,
|
|
82
|
+
data,
|
|
83
|
+
timestamp: new Date().toISOString(),
|
|
84
|
+
meta: meta ?? rootMeta(),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=cascade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cascade.js","sourceRoot":"","sources":["../../src/events/cascade.ts"],"names":[],"mappings":"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"}
|
package/build/events/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export * from './types/enums';
|
|
|
2
2
|
export * from './interfaces';
|
|
3
3
|
export * from './types';
|
|
4
4
|
export * from './base-event.controller';
|
|
5
|
+
export * from './cascade';
|
|
6
|
+
export * from './outbox';
|
|
5
7
|
export * from './msg-client-manager';
|
|
6
8
|
export * from './msg-wrapper';
|
|
7
9
|
export * from './base-listener';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/events/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AAExB,cAAc,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/events/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AAExB,cAAc,yBAAyB,CAAC;AACxC,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AAGzB,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AAGjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,QAAQ,CAAC;AAGvB,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAGhC,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AAGjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC"}
|
package/build/events/index.js
CHANGED
|
@@ -18,6 +18,8 @@ __exportStar(require("./types/enums"), exports);
|
|
|
18
18
|
__exportStar(require("./interfaces"), exports);
|
|
19
19
|
__exportStar(require("./types"), exports);
|
|
20
20
|
__exportStar(require("./base-event.controller"), exports);
|
|
21
|
+
__exportStar(require("./cascade"), exports);
|
|
22
|
+
__exportStar(require("./outbox"), exports);
|
|
21
23
|
// messages on memory
|
|
22
24
|
__exportStar(require("./msg-client-manager"), exports);
|
|
23
25
|
__exportStar(require("./msg-wrapper"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/events/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,+CAA6B;AAC7B,0CAAwB;AAExB,0DAAwC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/events/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,+CAA6B;AAC7B,0CAAwB;AAExB,0DAAwC;AACxC,4CAA0B;AAC1B,2CAAyB;AAEzB,qBAAqB;AACrB,uDAAqC;AACrC,gDAA8B;AAC9B,kDAAgC;AAChC,mDAAiC;AAEjC,mBAAmB;AACnB,wDAAsC;AACtC,iDAA+B;AAC/B,uDAAqC;AACrC,wDAAsC;AAEtC,YAAY;AACZ,iDAA+B;AAC/B,yCAAuB;AAEvB,aAAa;AACb,kDAAgC;AAChC,gDAA8B;AAC9B,6CAA2B;AAC3B,mDAAiC;AACjC,iDAA+B;AAC/B,4CAA0B;AAC1B,sDAAoC;AACpC,2CAAyB;AACzB,kDAAgC;AAEhC,cAAc;AACd,4CAA0B;AAC1B,kDAAgC;AAChC,oDAAkC;AAClC,qDAAmC;AACnC,qDAAmC;AACnC,oDAAkC;AAClC,iDAA+B;AAC/B,mDAAiC;AAEjC,oBAAoB;AACpB,kDAAgC;AAChC,+CAA6B;AAE7B,kBAAkB;AAClB,mCAAmC;AAEnC,cAAc"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Subjects } from './types/enums';
|
|
2
|
+
import { EventMeta } from './types/event-envelope.interfaces';
|
|
2
3
|
import { NxObject } from '@nextage/nx-frame-be';
|
|
3
4
|
export interface MsgClientInterface {
|
|
4
5
|
publish: (subject: string, payload: string, options?: NxObject) => Promise<any>;
|
|
@@ -15,6 +16,6 @@ export interface Event {
|
|
|
15
16
|
}
|
|
16
17
|
export interface IPublisher<T extends Event, O = undefined> {
|
|
17
18
|
subject: T['subject'];
|
|
18
|
-
publish(data: T['data'], options?: O): Promise<void>;
|
|
19
|
+
publish(data: T['data'], meta?: EventMeta, options?: O): Promise<void>;
|
|
19
20
|
}
|
|
20
21
|
//# sourceMappingURL=interfaces.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/events/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/events/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAO,eAAe,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAO,sBAAsB,CAAC;AAEjD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IACnF,SAAS,EAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;IACrC,WAAW,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;CACtC;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAK,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,EAAK,GAAG,CAAC;CACd;AAED,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,KAAK,EAAE,CAAC,GAAG,SAAS;IACxD,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;IACtB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { OutboxPort } from './types/outbox.interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* Register the process-wide outbox implementation. Called once, at service
|
|
4
|
+
* bootstrap (app-layer phase), with the service's own `event` model.
|
|
5
|
+
*/
|
|
6
|
+
export declare const registerOutbox: (port: OutboxPort) => void;
|
|
7
|
+
/**
|
|
8
|
+
* Current outbox implementation, or `undefined` when none was registered (the
|
|
9
|
+
* controller then publishes WITHOUT persisting an outbox row — graceful default).
|
|
10
|
+
*/
|
|
11
|
+
export declare const getOutbox: () => OutboxPort | undefined;
|
|
12
|
+
//# sourceMappingURL=outbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/events/outbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAIvD;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,UAAU,KAAG,IAA2B,CAAC;AAE9E;;;GAGG;AACH,eAAO,MAAM,SAAS,QAAO,UAAU,GAAG,SAAoB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getOutbox = exports.registerOutbox = void 0;
|
|
4
|
+
let _outbox;
|
|
5
|
+
/**
|
|
6
|
+
* Register the process-wide outbox implementation. Called once, at service
|
|
7
|
+
* bootstrap (app-layer phase), with the service's own `event` model.
|
|
8
|
+
*/
|
|
9
|
+
const registerOutbox = (port) => { _outbox = port; };
|
|
10
|
+
exports.registerOutbox = registerOutbox;
|
|
11
|
+
/**
|
|
12
|
+
* Current outbox implementation, or `undefined` when none was registered (the
|
|
13
|
+
* controller then publishes WITHOUT persisting an outbox row — graceful default).
|
|
14
|
+
*/
|
|
15
|
+
const getOutbox = () => _outbox;
|
|
16
|
+
exports.getOutbox = getOutbox;
|
|
17
|
+
//# sourceMappingURL=outbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../src/events/outbox.ts"],"names":[],"mappings":";;;AAEA,IAAI,OAA+B,CAAC;AAEpC;;;GAGG;AACI,MAAM,cAAc,GAAG,CAAC,IAAgB,EAAQ,EAAE,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAAjE,QAAA,cAAc,kBAAmD;AAE9E;;;GAGG;AACI,MAAM,SAAS,GAAG,GAA2B,EAAE,CAAC,OAAO,CAAC;AAAlD,QAAA,SAAS,aAAyC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-envelope.constants.d.ts","sourceRoot":"","sources":["../../../src/events/types/event-envelope.constants.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,iBAAiB,KAAK,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
3
|
+
// Cascade governance constants
|
|
4
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MAX_CASCADE_DEPTH = void 0;
|
|
7
|
+
// Maximum number of cascade hops before an event is treated as a runaway loop and
|
|
8
|
+
// dead-lettered instead of processed. The real cascades are depth <= 2; this is a
|
|
9
|
+
// wide anti-runaway ceiling, not a tuning knob.
|
|
10
|
+
exports.MAX_CASCADE_DEPTH = 10;
|
|
11
|
+
//# sourceMappingURL=event-envelope.constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-envelope.constants.js","sourceRoot":"","sources":["../../../src/events/types/event-envelope.constants.ts"],"names":[],"mappings":";AAAA,iFAAiF;AACjF,gCAAgC;AAChC,iFAAiF;;;AAEjF,kFAAkF;AAClF,kFAAkF;AAClF,gDAAgD;AACnC,QAAA,iBAAiB,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { NxContext } from '@nextage/nx-frame-be';
|
|
2
|
+
export interface EventMeta {
|
|
3
|
+
correlationId: string;
|
|
4
|
+
causationId?: string;
|
|
5
|
+
depth: number;
|
|
6
|
+
visited: string[];
|
|
7
|
+
}
|
|
8
|
+
export interface EventEnvelope<T = any> {
|
|
9
|
+
id: string;
|
|
10
|
+
subject: string;
|
|
11
|
+
data: T;
|
|
12
|
+
timestamp: string;
|
|
13
|
+
meta: EventMeta;
|
|
14
|
+
}
|
|
15
|
+
export interface IncomingEventRef {
|
|
16
|
+
id: string;
|
|
17
|
+
subject: string;
|
|
18
|
+
meta: EventMeta;
|
|
19
|
+
}
|
|
20
|
+
export interface EventContext extends NxContext {
|
|
21
|
+
_event?: IncomingEventRef;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=event-envelope.interfaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-envelope.interfaces.d.ts","sourceRoot":"","sources":["../../../src/events/types/event-envelope.interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAiBjD,MAAM,WAAW,SAAS;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAG,MAAM,CAAC;IACtB,KAAK,EAAU,MAAM,CAAC;IACtB,OAAO,EAAQ,MAAM,EAAE,CAAC;CACzB;AAGD,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,GAAG;IACpC,EAAE,EAAS,MAAM,CAAC;IAClB,OAAO,EAAI,MAAM,CAAC;IAClB,IAAI,EAAO,CAAC,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAO,SAAS,CAAC;CACtB;AAKD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAO,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAK,SAAS,CAAC;CACpB;AAGD,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-envelope.interfaces.js","sourceRoot":"","sources":["../../../src/events/types/event-envelope.interfaces.ts"],"names":[],"mappings":""}
|
|
@@ -14,10 +14,13 @@ export * from './treatment.enums';
|
|
|
14
14
|
export * from './vulnerability.enums';
|
|
15
15
|
export * from './asset.constants';
|
|
16
16
|
export * from './dlq.constants';
|
|
17
|
+
export * from './event-envelope.constants';
|
|
17
18
|
export * from './asset.interfaces';
|
|
18
19
|
export * from './control.interfaces';
|
|
19
20
|
export * from './dlq.interfaces';
|
|
21
|
+
export * from './event-envelope.interfaces';
|
|
20
22
|
export * from './events.interfaces';
|
|
23
|
+
export * from './outbox.interfaces';
|
|
21
24
|
export * from './risk-analysis.interfaces';
|
|
22
25
|
export * from './threat.interfaces';
|
|
23
26
|
export * from './vulnerability.interfaces';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/events/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AAExB,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AAEtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/events/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AAExB,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AAEtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAE3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAG3C,cAAc,kBAAkB,CAAC"}
|
|
@@ -30,10 +30,13 @@ __exportStar(require("./treatment.enums"), exports);
|
|
|
30
30
|
__exportStar(require("./vulnerability.enums"), exports);
|
|
31
31
|
__exportStar(require("./asset.constants"), exports);
|
|
32
32
|
__exportStar(require("./dlq.constants"), exports);
|
|
33
|
+
__exportStar(require("./event-envelope.constants"), exports);
|
|
33
34
|
__exportStar(require("./asset.interfaces"), exports);
|
|
34
35
|
__exportStar(require("./control.interfaces"), exports);
|
|
35
36
|
__exportStar(require("./dlq.interfaces"), exports);
|
|
37
|
+
__exportStar(require("./event-envelope.interfaces"), exports);
|
|
36
38
|
__exportStar(require("./events.interfaces"), exports);
|
|
39
|
+
__exportStar(require("./outbox.interfaces"), exports);
|
|
37
40
|
__exportStar(require("./risk-analysis.interfaces"), exports);
|
|
38
41
|
__exportStar(require("./threat.interfaces"), exports);
|
|
39
42
|
__exportStar(require("./vulnerability.interfaces"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/events/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AAExB,wDAAsC;AACtC,gDAA8B;AAC9B,sDAAoC;AACpC,wDAAsC;AACtC,uDAAqC;AACrC,kDAAgC;AAChC,4DAA0C;AAC1C,iDAA+B;AAC/B,uDAAqC;AACrC,wDAAsC;AACtC,iDAA+B;AAC/B,oDAAkC;AAClC,wDAAsC;AAEtC,oDAAkC;AAClC,kDAAgC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/events/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AAExB,wDAAsC;AACtC,gDAA8B;AAC9B,sDAAoC;AACpC,wDAAsC;AACtC,uDAAqC;AACrC,kDAAgC;AAChC,4DAA0C;AAC1C,iDAA+B;AAC/B,uDAAqC;AACrC,wDAAsC;AACtC,iDAA+B;AAC/B,oDAAkC;AAClC,wDAAsC;AAEtC,oDAAkC;AAClC,kDAAgC;AAChC,6DAA2C;AAE3C,qDAAmC;AACnC,uDAAqC;AACrC,mDAAiC;AACjC,8DAA4C;AAC5C,sDAAoC;AACpC,sDAAoC;AACpC,6DAA2C;AAC3C,sDAAoC;AACpC,6DAA2C;AAE3C,YAAY;AACZ,mDAAiC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NxContext } from '@nextage/nx-frame-be';
|
|
2
|
+
import { QueueEventType } from './enums';
|
|
3
|
+
export interface OutboxEvent {
|
|
4
|
+
id: string;
|
|
5
|
+
type: QueueEventType;
|
|
6
|
+
data: any;
|
|
7
|
+
}
|
|
8
|
+
export interface OutboxPort {
|
|
9
|
+
create(evt: OutboxEvent, context: NxContext): Promise<void>;
|
|
10
|
+
markSent(id: string, context: NxContext): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=outbox.interfaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbox.interfaces.d.ts","sourceRoot":"","sources":["../../../src/events/types/outbox.interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAW,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAKzC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAI,MAAM,CAAC;IACb,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,GAAG,CAAC;CACX;AASD,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,GAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAQ,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbox.interfaces.js","sourceRoot":"","sources":["../../../src/events/types/outbox.interfaces.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextage/era-lib",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.176",
|
|
4
4
|
"main": "./build/index.js",
|
|
5
5
|
"types": "./build/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"license": "ISC",
|
|
23
23
|
"description": "ERA shared backend library (@nextage/era-lib): events, models, services, bootstrap orchestrator and utils on top of @nextage/nx-frame-be. See README.md and CHANGELOG.md.",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@nextage/nx-frame-be": "^1.0.
|
|
25
|
+
"@nextage/nx-frame-be": "^1.0.41",
|
|
26
26
|
"@types/express-jwt": "^7.4.2",
|
|
27
27
|
"@types/express-rate-limit": "^6.0.0",
|
|
28
28
|
"@types/express-session": "^1.18.2",
|