conduithub 0.1.0 → 1.0.1
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/core/conduit-hub/index.cjs +188 -0
- package/dist/core/conduit-hub/index.d.cts +44 -0
- package/dist/core/conduit-hub/index.d.mts +44 -0
- package/dist/core/conduit-hub/index.d.ts +44 -0
- package/dist/core/conduit-hub/index.mjs +186 -0
- package/dist/core/config-manager/index.cjs +216 -0
- package/dist/core/config-manager/index.d.cts +7 -0
- package/dist/core/config-manager/index.d.mts +7 -0
- package/dist/core/config-manager/index.d.ts +7 -0
- package/dist/core/config-manager/index.mjs +214 -0
- package/dist/core/event-bus/index.cjs +154 -53
- package/dist/core/event-bus/index.d.cts +2 -42
- package/dist/core/event-bus/index.d.mts +2 -42
- package/dist/core/event-bus/index.d.ts +2 -42
- package/dist/core/event-bus/index.mjs +153 -52
- package/dist/core/hook/index.cjs +185 -148
- package/dist/core/hook/index.d.cts +28 -16
- package/dist/core/hook/index.d.mts +28 -16
- package/dist/core/hook/index.d.ts +28 -16
- package/dist/core/hook/index.mjs +183 -146
- package/dist/core/index.cjs +17 -1
- package/dist/core/index.d.cts +184 -3
- package/dist/core/index.d.mts +184 -3
- package/dist/core/index.d.ts +184 -3
- package/dist/core/index.mjs +12 -1
- package/dist/core/plugin/index.cjs +271 -0
- package/dist/core/plugin/index.d.cts +7 -0
- package/dist/core/plugin/index.d.mts +7 -0
- package/dist/core/plugin/index.d.ts +7 -0
- package/dist/core/plugin/index.mjs +268 -0
- package/dist/core/service-container/index.cjs +306 -0
- package/dist/core/service-container/index.d.cts +51 -0
- package/dist/core/service-container/index.d.mts +51 -0
- package/dist/core/service-container/index.d.ts +51 -0
- package/dist/core/service-container/index.mjs +304 -0
- package/dist/core/state-manager/index.cjs +195 -0
- package/dist/core/state-manager/index.d.cts +39 -0
- package/dist/core/state-manager/index.d.mts +39 -0
- package/dist/core/state-manager/index.d.ts +39 -0
- package/dist/core/state-manager/index.mjs +193 -0
- package/dist/error/index.cjs +71 -0
- package/dist/error/index.d.cts +47 -0
- package/dist/error/index.d.mts +47 -0
- package/dist/error/index.d.ts +47 -0
- package/dist/error/index.mjs +65 -0
- package/dist/index.cjs +38 -5
- package/dist/index.d.cts +8 -2
- package/dist/index.d.mts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.mjs +16 -1
- package/dist/plugins/index.cjs +12 -0
- package/dist/plugins/index.d.cts +8 -0
- package/dist/plugins/index.d.mts +8 -0
- package/dist/plugins/index.d.ts +8 -0
- package/dist/plugins/index.mjs +6 -0
- package/dist/plugins/redis/index.cjs +12 -0
- package/dist/plugins/redis/index.d.cts +109 -0
- package/dist/plugins/redis/index.d.mts +109 -0
- package/dist/plugins/redis/index.d.ts +109 -0
- package/dist/plugins/redis/index.mjs +6 -0
- package/dist/shared/conduithub.-bZD30_I.mjs +769 -0
- package/dist/shared/{conduithub.CvMLTa-R.cjs → conduithub.BNQsddJO.cjs} +2 -9
- package/dist/shared/{conduithub.74V0wiLi.mjs → conduithub.BNefRQsK.mjs} +3 -9
- package/dist/shared/conduithub.BZQmkQy7.d.cts +52 -0
- package/dist/shared/conduithub.Bq_7Xj0J.cjs +18 -0
- package/dist/shared/conduithub.BzLwccre.d.mts +52 -0
- package/dist/shared/conduithub.CkOQG3cD.mjs +14 -0
- package/dist/shared/conduithub.CmZo_Vuc.cjs +38 -0
- package/dist/shared/conduithub.DQO1dRnn.cjs +33 -0
- package/dist/shared/conduithub.DQOWQ-Bx.d.ts +52 -0
- package/dist/shared/conduithub.Dlvl2xGE.cjs +76 -0
- package/dist/shared/conduithub.DsOOeNwU.cjs +269 -0
- package/dist/shared/conduithub.DyQQrHW9.mjs +267 -0
- package/dist/shared/conduithub.G7ICpZIy.mjs +36 -0
- package/dist/shared/conduithub.Up0QYVao.mjs +59 -0
- package/dist/shared/conduithub.alPiaJax.mjs +29 -0
- package/dist/shared/conduithub.cvEjE62V.cjs +775 -0
- package/dist/utils/index.cjs +19 -5
- package/dist/utils/index.d.cts +33 -2
- package/dist/utils/index.d.mts +33 -2
- package/dist/utils/index.d.ts +33 -2
- package/dist/utils/index.mjs +8 -1
- package/package.json +55 -7
|
@@ -1,17 +1,62 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const error_index = require('../../error/index.cjs');
|
|
4
|
+
const logger = require('../../shared/conduithub.BNQsddJO.cjs');
|
|
5
|
+
require('process');
|
|
6
|
+
require('readline');
|
|
7
|
+
const uuid = require('../../shared/conduithub.Bq_7Xj0J.cjs');
|
|
8
|
+
const code = require('../../shared/conduithub.CmZo_Vuc.cjs');
|
|
4
9
|
require('uuid');
|
|
5
10
|
|
|
6
11
|
class EventBus {
|
|
7
12
|
handlers = {};
|
|
13
|
+
locks = /* @__PURE__ */ new Map();
|
|
8
14
|
initialized = false;
|
|
9
15
|
logger;
|
|
16
|
+
maxHandlersPerEvent;
|
|
17
|
+
handlerTimeoutMs;
|
|
18
|
+
onError;
|
|
10
19
|
constructor(options) {
|
|
11
|
-
this.logger =
|
|
20
|
+
this.logger = logger.createLogger(options?.logger);
|
|
21
|
+
this.maxHandlersPerEvent = options?.maxHandlersPerEvent ?? 100;
|
|
22
|
+
this.handlerTimeoutMs = options?.handlerTimeoutMs ?? 5e3;
|
|
23
|
+
this.onError = options?.onError;
|
|
24
|
+
}
|
|
25
|
+
async withEventLock(type, operation) {
|
|
26
|
+
const currentLock = this.locks.get(type) ?? Promise.resolve();
|
|
27
|
+
let resolveLock;
|
|
28
|
+
const newLock = new Promise((resolve) => {
|
|
29
|
+
resolveLock = resolve;
|
|
30
|
+
});
|
|
31
|
+
this.locks.set(
|
|
32
|
+
type,
|
|
33
|
+
currentLock.then(() => newLock)
|
|
34
|
+
);
|
|
35
|
+
await currentLock;
|
|
36
|
+
try {
|
|
37
|
+
return await operation();
|
|
38
|
+
} finally {
|
|
39
|
+
resolveLock();
|
|
40
|
+
}
|
|
12
41
|
}
|
|
13
42
|
ensureInitialized() {
|
|
14
|
-
if (!this.initialized)
|
|
43
|
+
if (!this.initialized) {
|
|
44
|
+
throw new error_index.ConduithubError(code.ERROR_CODE.EVENT_BUS_NOT_INITIALIZED);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
sanitizeLog(data) {
|
|
48
|
+
if (typeof data === "string") {
|
|
49
|
+
return data.length > 100 ? `${data.substring(0, 100)}...` : data;
|
|
50
|
+
}
|
|
51
|
+
if (typeof data === "object" && data !== null) {
|
|
52
|
+
try {
|
|
53
|
+
const json = JSON.stringify(data);
|
|
54
|
+
return json.length > 100 ? `${json.substring(0, 100)}...` : json;
|
|
55
|
+
} catch {
|
|
56
|
+
return "[Unserializable Object]";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return String(data);
|
|
15
60
|
}
|
|
16
61
|
async initialize() {
|
|
17
62
|
if (this.initialized) return;
|
|
@@ -20,73 +65,125 @@ class EventBus {
|
|
|
20
65
|
}
|
|
21
66
|
async shutdown() {
|
|
22
67
|
this.ensureInitialized();
|
|
23
|
-
|
|
68
|
+
const totalHandlers = this.getTotalHandlerCount();
|
|
69
|
+
this.clearAllHandlers();
|
|
24
70
|
this.initialized = false;
|
|
25
|
-
this.logger.success(
|
|
71
|
+
this.logger.success(
|
|
72
|
+
`EventBus system shutdown completed - cleared ${totalHandlers} handlers`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
getTotalHandlerCount() {
|
|
76
|
+
return Object.values(this.handlers).reduce(
|
|
77
|
+
(sum, list) => sum + (list?.length ?? 0),
|
|
78
|
+
0
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
clearAllHandlers() {
|
|
82
|
+
for (const key in this.handlers) {
|
|
83
|
+
delete this.handlers[key];
|
|
84
|
+
}
|
|
26
85
|
}
|
|
27
|
-
on(type, handler) {
|
|
86
|
+
on(type, handler, priority = 0, customId) {
|
|
28
87
|
this.ensureInitialized();
|
|
29
|
-
|
|
30
|
-
const record = {
|
|
31
|
-
id,
|
|
32
|
-
handler,
|
|
33
|
-
once: false
|
|
34
|
-
};
|
|
35
|
-
(this.handlers[type] ??= []).push(record);
|
|
36
|
-
this.logger.debug(`Event handler registered: '${String(type)}' \u2192 ${id}`);
|
|
37
|
-
return id;
|
|
88
|
+
return this.registerHandler(type, handler, false, priority, customId);
|
|
38
89
|
}
|
|
39
|
-
once(type, handler) {
|
|
90
|
+
once(type, handler, priority = 0, customId) {
|
|
40
91
|
this.ensureInitialized();
|
|
41
|
-
|
|
92
|
+
return this.registerHandler(type, handler, true, priority, customId);
|
|
93
|
+
}
|
|
94
|
+
registerHandler(type, handler, once, priority, customId) {
|
|
95
|
+
const list = this.handlers[type] ??= [];
|
|
96
|
+
if (list.length >= this.maxHandlersPerEvent) {
|
|
97
|
+
throw new error_index.ConduithubError(
|
|
98
|
+
`${code.ERROR_CODE.EVENT_HANDLER_LIMIT_EXCEEDED} ${String(type)} (${this.maxHandlersPerEvent})`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
const id = customId ?? uuid.generateUuid();
|
|
102
|
+
if (customId && list.some((h) => h.id === customId)) {
|
|
103
|
+
throw new error_index.ConduithubError(
|
|
104
|
+
`${code.ERROR_CODE.DUPLICATE_EVENT_HANDLER_ID} ${String(type)}: ${customId}`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
42
107
|
const record = {
|
|
43
108
|
id,
|
|
44
109
|
handler,
|
|
45
|
-
once
|
|
110
|
+
once,
|
|
111
|
+
priority
|
|
46
112
|
};
|
|
47
|
-
|
|
113
|
+
list.push(record);
|
|
114
|
+
const handlerType = once ? "One-time event handler" : "Event handler";
|
|
48
115
|
this.logger.debug(
|
|
49
|
-
|
|
116
|
+
`${handlerType} registered: '${String(type)}' \u2192 ${id} (priority: ${priority})`
|
|
50
117
|
);
|
|
51
118
|
return id;
|
|
52
119
|
}
|
|
53
120
|
off(type, id) {
|
|
54
121
|
this.ensureInitialized();
|
|
55
122
|
const list = this.handlers[type];
|
|
56
|
-
if (!list)
|
|
123
|
+
if (!list) {
|
|
124
|
+
this.logger.debug(`No handlers found for event: '${String(type)}'`);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
57
127
|
if (!id) {
|
|
58
128
|
delete this.handlers[type];
|
|
59
129
|
this.logger.debug(`All event handlers removed for: '${String(type)}'`);
|
|
60
130
|
return;
|
|
61
131
|
}
|
|
62
132
|
const index = list.findIndex((h) => h.id === id);
|
|
63
|
-
if (index
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
133
|
+
if (index === -1) {
|
|
134
|
+
this.logger.warn(`Handler not found: '${String(type)}' \u2192 ${id}`);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
list.splice(index, 1);
|
|
138
|
+
this.logger.debug(`Event handler removed: '${String(type)}' \u2192 ${id}`);
|
|
139
|
+
if (list.length === 0) {
|
|
140
|
+
delete this.handlers[type];
|
|
67
141
|
}
|
|
68
142
|
}
|
|
69
|
-
async emit(type, payload, source = "event-bus") {
|
|
70
|
-
this.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
timestamp: Date.now(),
|
|
77
|
-
source
|
|
78
|
-
};
|
|
79
|
-
for (const { id, handler, once } of [...list]) {
|
|
80
|
-
try {
|
|
81
|
-
await handler(event);
|
|
82
|
-
if (once) this.off(type, id);
|
|
83
|
-
} catch (err) {
|
|
84
|
-
this.logger.error(
|
|
85
|
-
`Event handler execution failed: '${String(type)}' \u2192 ${id}`,
|
|
86
|
-
err
|
|
87
|
-
);
|
|
143
|
+
async emit(type, payload, source = "event-bus", context) {
|
|
144
|
+
await this.withEventLock(type, async () => {
|
|
145
|
+
this.ensureInitialized();
|
|
146
|
+
const list = this.handlers[type];
|
|
147
|
+
if (!list?.length) {
|
|
148
|
+
this.logger.debug(`No handlers for event: '${String(type)}'`);
|
|
149
|
+
return;
|
|
88
150
|
}
|
|
89
|
-
|
|
151
|
+
const sortedList = [...list].sort((a, b) => b.priority - a.priority);
|
|
152
|
+
const event = {
|
|
153
|
+
type,
|
|
154
|
+
payload,
|
|
155
|
+
timestamp: Date.now(),
|
|
156
|
+
source,
|
|
157
|
+
context
|
|
158
|
+
};
|
|
159
|
+
let successCount = 0;
|
|
160
|
+
let errorCount = 0;
|
|
161
|
+
for (const { id, handler, once } of sortedList) {
|
|
162
|
+
try {
|
|
163
|
+
await Promise.race([
|
|
164
|
+
Promise.resolve(handler(event, context)),
|
|
165
|
+
new Promise(
|
|
166
|
+
(_, reject) => setTimeout(
|
|
167
|
+
() => reject(new Error("Handler timeout")),
|
|
168
|
+
this.handlerTimeoutMs
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
]);
|
|
172
|
+
successCount++;
|
|
173
|
+
if (once) this.off(type, id);
|
|
174
|
+
} catch (err) {
|
|
175
|
+
errorCount++;
|
|
176
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
177
|
+
this.logger.error(
|
|
178
|
+
`Event handler execution failed: '${String(type)}' \u2192 ${id} - ${this.sanitizeLog(errorMessage)}`
|
|
179
|
+
);
|
|
180
|
+
this.onError?.(err, type);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
this.logger.debug(
|
|
184
|
+
`Event emitted: '${String(type)}' (${successCount} succeeded, ${errorCount} failed)`
|
|
185
|
+
);
|
|
186
|
+
});
|
|
90
187
|
}
|
|
91
188
|
removeAllListeners(type) {
|
|
92
189
|
this.ensureInitialized();
|
|
@@ -96,7 +193,7 @@ class EventBus {
|
|
|
96
193
|
`All listeners removed for event type: '${String(type)}'`
|
|
97
194
|
);
|
|
98
195
|
} else {
|
|
99
|
-
this.
|
|
196
|
+
this.clearAllHandlers();
|
|
100
197
|
this.logger.debug("All event listeners cleared from EventBus");
|
|
101
198
|
}
|
|
102
199
|
}
|
|
@@ -107,15 +204,19 @@ class EventBus {
|
|
|
107
204
|
return Object.keys(this.handlers);
|
|
108
205
|
}
|
|
109
206
|
getStats() {
|
|
110
|
-
const
|
|
111
|
-
const
|
|
112
|
-
|
|
207
|
+
const eventNames = this.eventNames();
|
|
208
|
+
const listenerCount = Object.fromEntries(
|
|
209
|
+
eventNames.map((name) => [name, this.listenerCount(name)])
|
|
210
|
+
);
|
|
211
|
+
const totalListeners = Object.values(listenerCount).reduce(
|
|
212
|
+
(sum, count) => sum + count,
|
|
213
|
+
0
|
|
113
214
|
);
|
|
114
215
|
return {
|
|
115
|
-
totalEvents:
|
|
116
|
-
totalListeners
|
|
117
|
-
eventNames
|
|
118
|
-
listenerCount
|
|
216
|
+
totalEvents: eventNames.length,
|
|
217
|
+
totalListeners,
|
|
218
|
+
eventNames,
|
|
219
|
+
listenerCount
|
|
119
220
|
};
|
|
120
221
|
}
|
|
121
222
|
get isInitialized() {
|
|
@@ -1,42 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
interface EventData<K extends string, P> {
|
|
4
|
-
type: K;
|
|
5
|
-
payload: P;
|
|
6
|
-
timestamp: number;
|
|
7
|
-
source: string;
|
|
8
|
-
}
|
|
9
|
-
interface EventHandlerRecord<K extends string, P> {
|
|
10
|
-
id: string;
|
|
11
|
-
once: boolean;
|
|
12
|
-
handler: (event: EventData<K, P>) => Promise<void> | void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
declare class EventBus<EM extends Record<string, unknown>> {
|
|
16
|
-
private handlers;
|
|
17
|
-
private initialized;
|
|
18
|
-
private logger;
|
|
19
|
-
constructor(options?: {
|
|
20
|
-
logger?: Logger;
|
|
21
|
-
});
|
|
22
|
-
private ensureInitialized;
|
|
23
|
-
initialize(): Promise<void>;
|
|
24
|
-
shutdown(): Promise<void>;
|
|
25
|
-
on<K extends keyof EM>(type: K, handler: (event: EventData<K & string, EM[K]>) => Promise<void> | void): string;
|
|
26
|
-
once<K extends keyof EM>(type: K, handler: (event: EventData<K & string, EM[K]>) => Promise<void> | void): string;
|
|
27
|
-
off<K extends keyof EM>(type: K, id?: string): void;
|
|
28
|
-
emit<K extends keyof EM>(type: K, payload: EM[K], source?: string): Promise<void>;
|
|
29
|
-
removeAllListeners<K extends keyof EM>(type?: K): void;
|
|
30
|
-
listenerCount<K extends keyof EM>(type: K): number;
|
|
31
|
-
eventNames(): Array<keyof EM>;
|
|
32
|
-
getStats(): {
|
|
33
|
-
totalEvents: number;
|
|
34
|
-
totalListeners: number;
|
|
35
|
-
eventNames: (keyof EM)[];
|
|
36
|
-
listenerCount: Record<keyof EM, number>;
|
|
37
|
-
};
|
|
38
|
-
get isInitialized(): boolean;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export { EventBus };
|
|
42
|
-
export type { EventData, EventHandlerRecord };
|
|
1
|
+
import '../../shared/conduithub.B7aryjPG.cjs';
|
|
2
|
+
export { E as EventBus } from '../../shared/conduithub.BZQmkQy7.cjs';
|
|
@@ -1,42 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
interface EventData<K extends string, P> {
|
|
4
|
-
type: K;
|
|
5
|
-
payload: P;
|
|
6
|
-
timestamp: number;
|
|
7
|
-
source: string;
|
|
8
|
-
}
|
|
9
|
-
interface EventHandlerRecord<K extends string, P> {
|
|
10
|
-
id: string;
|
|
11
|
-
once: boolean;
|
|
12
|
-
handler: (event: EventData<K, P>) => Promise<void> | void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
declare class EventBus<EM extends Record<string, unknown>> {
|
|
16
|
-
private handlers;
|
|
17
|
-
private initialized;
|
|
18
|
-
private logger;
|
|
19
|
-
constructor(options?: {
|
|
20
|
-
logger?: Logger;
|
|
21
|
-
});
|
|
22
|
-
private ensureInitialized;
|
|
23
|
-
initialize(): Promise<void>;
|
|
24
|
-
shutdown(): Promise<void>;
|
|
25
|
-
on<K extends keyof EM>(type: K, handler: (event: EventData<K & string, EM[K]>) => Promise<void> | void): string;
|
|
26
|
-
once<K extends keyof EM>(type: K, handler: (event: EventData<K & string, EM[K]>) => Promise<void> | void): string;
|
|
27
|
-
off<K extends keyof EM>(type: K, id?: string): void;
|
|
28
|
-
emit<K extends keyof EM>(type: K, payload: EM[K], source?: string): Promise<void>;
|
|
29
|
-
removeAllListeners<K extends keyof EM>(type?: K): void;
|
|
30
|
-
listenerCount<K extends keyof EM>(type: K): number;
|
|
31
|
-
eventNames(): Array<keyof EM>;
|
|
32
|
-
getStats(): {
|
|
33
|
-
totalEvents: number;
|
|
34
|
-
totalListeners: number;
|
|
35
|
-
eventNames: (keyof EM)[];
|
|
36
|
-
listenerCount: Record<keyof EM, number>;
|
|
37
|
-
};
|
|
38
|
-
get isInitialized(): boolean;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export { EventBus };
|
|
42
|
-
export type { EventData, EventHandlerRecord };
|
|
1
|
+
import '../../shared/conduithub.B7aryjPG.mjs';
|
|
2
|
+
export { E as EventBus } from '../../shared/conduithub.BzLwccre.mjs';
|
|
@@ -1,42 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
interface EventData<K extends string, P> {
|
|
4
|
-
type: K;
|
|
5
|
-
payload: P;
|
|
6
|
-
timestamp: number;
|
|
7
|
-
source: string;
|
|
8
|
-
}
|
|
9
|
-
interface EventHandlerRecord<K extends string, P> {
|
|
10
|
-
id: string;
|
|
11
|
-
once: boolean;
|
|
12
|
-
handler: (event: EventData<K, P>) => Promise<void> | void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
declare class EventBus<EM extends Record<string, unknown>> {
|
|
16
|
-
private handlers;
|
|
17
|
-
private initialized;
|
|
18
|
-
private logger;
|
|
19
|
-
constructor(options?: {
|
|
20
|
-
logger?: Logger;
|
|
21
|
-
});
|
|
22
|
-
private ensureInitialized;
|
|
23
|
-
initialize(): Promise<void>;
|
|
24
|
-
shutdown(): Promise<void>;
|
|
25
|
-
on<K extends keyof EM>(type: K, handler: (event: EventData<K & string, EM[K]>) => Promise<void> | void): string;
|
|
26
|
-
once<K extends keyof EM>(type: K, handler: (event: EventData<K & string, EM[K]>) => Promise<void> | void): string;
|
|
27
|
-
off<K extends keyof EM>(type: K, id?: string): void;
|
|
28
|
-
emit<K extends keyof EM>(type: K, payload: EM[K], source?: string): Promise<void>;
|
|
29
|
-
removeAllListeners<K extends keyof EM>(type?: K): void;
|
|
30
|
-
listenerCount<K extends keyof EM>(type: K): number;
|
|
31
|
-
eventNames(): Array<keyof EM>;
|
|
32
|
-
getStats(): {
|
|
33
|
-
totalEvents: number;
|
|
34
|
-
totalListeners: number;
|
|
35
|
-
eventNames: (keyof EM)[];
|
|
36
|
-
listenerCount: Record<keyof EM, number>;
|
|
37
|
-
};
|
|
38
|
-
get isInitialized(): boolean;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export { EventBus };
|
|
42
|
-
export type { EventData, EventHandlerRecord };
|
|
1
|
+
import '../../shared/conduithub.B7aryjPG.js';
|
|
2
|
+
export { E as EventBus } from '../../shared/conduithub.DQOWQ-Bx.js';
|
|
@@ -1,15 +1,60 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConduithubError } from '../../error/index.mjs';
|
|
2
|
+
import { c as createLogger } from '../../shared/conduithub.BNefRQsK.mjs';
|
|
3
|
+
import 'process';
|
|
4
|
+
import 'readline';
|
|
5
|
+
import { g as generateUuid } from '../../shared/conduithub.CkOQG3cD.mjs';
|
|
6
|
+
import { E as ERROR_CODE } from '../../shared/conduithub.G7ICpZIy.mjs';
|
|
2
7
|
import 'uuid';
|
|
3
8
|
|
|
4
9
|
class EventBus {
|
|
5
10
|
handlers = {};
|
|
11
|
+
locks = /* @__PURE__ */ new Map();
|
|
6
12
|
initialized = false;
|
|
7
13
|
logger;
|
|
14
|
+
maxHandlersPerEvent;
|
|
15
|
+
handlerTimeoutMs;
|
|
16
|
+
onError;
|
|
8
17
|
constructor(options) {
|
|
9
18
|
this.logger = createLogger(options?.logger);
|
|
19
|
+
this.maxHandlersPerEvent = options?.maxHandlersPerEvent ?? 100;
|
|
20
|
+
this.handlerTimeoutMs = options?.handlerTimeoutMs ?? 5e3;
|
|
21
|
+
this.onError = options?.onError;
|
|
22
|
+
}
|
|
23
|
+
async withEventLock(type, operation) {
|
|
24
|
+
const currentLock = this.locks.get(type) ?? Promise.resolve();
|
|
25
|
+
let resolveLock;
|
|
26
|
+
const newLock = new Promise((resolve) => {
|
|
27
|
+
resolveLock = resolve;
|
|
28
|
+
});
|
|
29
|
+
this.locks.set(
|
|
30
|
+
type,
|
|
31
|
+
currentLock.then(() => newLock)
|
|
32
|
+
);
|
|
33
|
+
await currentLock;
|
|
34
|
+
try {
|
|
35
|
+
return await operation();
|
|
36
|
+
} finally {
|
|
37
|
+
resolveLock();
|
|
38
|
+
}
|
|
10
39
|
}
|
|
11
40
|
ensureInitialized() {
|
|
12
|
-
if (!this.initialized)
|
|
41
|
+
if (!this.initialized) {
|
|
42
|
+
throw new ConduithubError(ERROR_CODE.EVENT_BUS_NOT_INITIALIZED);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
sanitizeLog(data) {
|
|
46
|
+
if (typeof data === "string") {
|
|
47
|
+
return data.length > 100 ? `${data.substring(0, 100)}...` : data;
|
|
48
|
+
}
|
|
49
|
+
if (typeof data === "object" && data !== null) {
|
|
50
|
+
try {
|
|
51
|
+
const json = JSON.stringify(data);
|
|
52
|
+
return json.length > 100 ? `${json.substring(0, 100)}...` : json;
|
|
53
|
+
} catch {
|
|
54
|
+
return "[Unserializable Object]";
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return String(data);
|
|
13
58
|
}
|
|
14
59
|
async initialize() {
|
|
15
60
|
if (this.initialized) return;
|
|
@@ -18,73 +63,125 @@ class EventBus {
|
|
|
18
63
|
}
|
|
19
64
|
async shutdown() {
|
|
20
65
|
this.ensureInitialized();
|
|
21
|
-
|
|
66
|
+
const totalHandlers = this.getTotalHandlerCount();
|
|
67
|
+
this.clearAllHandlers();
|
|
22
68
|
this.initialized = false;
|
|
23
|
-
this.logger.success(
|
|
69
|
+
this.logger.success(
|
|
70
|
+
`EventBus system shutdown completed - cleared ${totalHandlers} handlers`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
getTotalHandlerCount() {
|
|
74
|
+
return Object.values(this.handlers).reduce(
|
|
75
|
+
(sum, list) => sum + (list?.length ?? 0),
|
|
76
|
+
0
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
clearAllHandlers() {
|
|
80
|
+
for (const key in this.handlers) {
|
|
81
|
+
delete this.handlers[key];
|
|
82
|
+
}
|
|
24
83
|
}
|
|
25
|
-
on(type, handler) {
|
|
84
|
+
on(type, handler, priority = 0, customId) {
|
|
26
85
|
this.ensureInitialized();
|
|
27
|
-
|
|
28
|
-
const record = {
|
|
29
|
-
id,
|
|
30
|
-
handler,
|
|
31
|
-
once: false
|
|
32
|
-
};
|
|
33
|
-
(this.handlers[type] ??= []).push(record);
|
|
34
|
-
this.logger.debug(`Event handler registered: '${String(type)}' \u2192 ${id}`);
|
|
35
|
-
return id;
|
|
86
|
+
return this.registerHandler(type, handler, false, priority, customId);
|
|
36
87
|
}
|
|
37
|
-
once(type, handler) {
|
|
88
|
+
once(type, handler, priority = 0, customId) {
|
|
38
89
|
this.ensureInitialized();
|
|
39
|
-
|
|
90
|
+
return this.registerHandler(type, handler, true, priority, customId);
|
|
91
|
+
}
|
|
92
|
+
registerHandler(type, handler, once, priority, customId) {
|
|
93
|
+
const list = this.handlers[type] ??= [];
|
|
94
|
+
if (list.length >= this.maxHandlersPerEvent) {
|
|
95
|
+
throw new ConduithubError(
|
|
96
|
+
`${ERROR_CODE.EVENT_HANDLER_LIMIT_EXCEEDED} ${String(type)} (${this.maxHandlersPerEvent})`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
const id = customId ?? generateUuid();
|
|
100
|
+
if (customId && list.some((h) => h.id === customId)) {
|
|
101
|
+
throw new ConduithubError(
|
|
102
|
+
`${ERROR_CODE.DUPLICATE_EVENT_HANDLER_ID} ${String(type)}: ${customId}`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
40
105
|
const record = {
|
|
41
106
|
id,
|
|
42
107
|
handler,
|
|
43
|
-
once
|
|
108
|
+
once,
|
|
109
|
+
priority
|
|
44
110
|
};
|
|
45
|
-
|
|
111
|
+
list.push(record);
|
|
112
|
+
const handlerType = once ? "One-time event handler" : "Event handler";
|
|
46
113
|
this.logger.debug(
|
|
47
|
-
|
|
114
|
+
`${handlerType} registered: '${String(type)}' \u2192 ${id} (priority: ${priority})`
|
|
48
115
|
);
|
|
49
116
|
return id;
|
|
50
117
|
}
|
|
51
118
|
off(type, id) {
|
|
52
119
|
this.ensureInitialized();
|
|
53
120
|
const list = this.handlers[type];
|
|
54
|
-
if (!list)
|
|
121
|
+
if (!list) {
|
|
122
|
+
this.logger.debug(`No handlers found for event: '${String(type)}'`);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
55
125
|
if (!id) {
|
|
56
126
|
delete this.handlers[type];
|
|
57
127
|
this.logger.debug(`All event handlers removed for: '${String(type)}'`);
|
|
58
128
|
return;
|
|
59
129
|
}
|
|
60
130
|
const index = list.findIndex((h) => h.id === id);
|
|
61
|
-
if (index
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
131
|
+
if (index === -1) {
|
|
132
|
+
this.logger.warn(`Handler not found: '${String(type)}' \u2192 ${id}`);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
list.splice(index, 1);
|
|
136
|
+
this.logger.debug(`Event handler removed: '${String(type)}' \u2192 ${id}`);
|
|
137
|
+
if (list.length === 0) {
|
|
138
|
+
delete this.handlers[type];
|
|
65
139
|
}
|
|
66
140
|
}
|
|
67
|
-
async emit(type, payload, source = "event-bus") {
|
|
68
|
-
this.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
timestamp: Date.now(),
|
|
75
|
-
source
|
|
76
|
-
};
|
|
77
|
-
for (const { id, handler, once } of [...list]) {
|
|
78
|
-
try {
|
|
79
|
-
await handler(event);
|
|
80
|
-
if (once) this.off(type, id);
|
|
81
|
-
} catch (err) {
|
|
82
|
-
this.logger.error(
|
|
83
|
-
`Event handler execution failed: '${String(type)}' \u2192 ${id}`,
|
|
84
|
-
err
|
|
85
|
-
);
|
|
141
|
+
async emit(type, payload, source = "event-bus", context) {
|
|
142
|
+
await this.withEventLock(type, async () => {
|
|
143
|
+
this.ensureInitialized();
|
|
144
|
+
const list = this.handlers[type];
|
|
145
|
+
if (!list?.length) {
|
|
146
|
+
this.logger.debug(`No handlers for event: '${String(type)}'`);
|
|
147
|
+
return;
|
|
86
148
|
}
|
|
87
|
-
|
|
149
|
+
const sortedList = [...list].sort((a, b) => b.priority - a.priority);
|
|
150
|
+
const event = {
|
|
151
|
+
type,
|
|
152
|
+
payload,
|
|
153
|
+
timestamp: Date.now(),
|
|
154
|
+
source,
|
|
155
|
+
context
|
|
156
|
+
};
|
|
157
|
+
let successCount = 0;
|
|
158
|
+
let errorCount = 0;
|
|
159
|
+
for (const { id, handler, once } of sortedList) {
|
|
160
|
+
try {
|
|
161
|
+
await Promise.race([
|
|
162
|
+
Promise.resolve(handler(event, context)),
|
|
163
|
+
new Promise(
|
|
164
|
+
(_, reject) => setTimeout(
|
|
165
|
+
() => reject(new Error("Handler timeout")),
|
|
166
|
+
this.handlerTimeoutMs
|
|
167
|
+
)
|
|
168
|
+
)
|
|
169
|
+
]);
|
|
170
|
+
successCount++;
|
|
171
|
+
if (once) this.off(type, id);
|
|
172
|
+
} catch (err) {
|
|
173
|
+
errorCount++;
|
|
174
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
175
|
+
this.logger.error(
|
|
176
|
+
`Event handler execution failed: '${String(type)}' \u2192 ${id} - ${this.sanitizeLog(errorMessage)}`
|
|
177
|
+
);
|
|
178
|
+
this.onError?.(err, type);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
this.logger.debug(
|
|
182
|
+
`Event emitted: '${String(type)}' (${successCount} succeeded, ${errorCount} failed)`
|
|
183
|
+
);
|
|
184
|
+
});
|
|
88
185
|
}
|
|
89
186
|
removeAllListeners(type) {
|
|
90
187
|
this.ensureInitialized();
|
|
@@ -94,7 +191,7 @@ class EventBus {
|
|
|
94
191
|
`All listeners removed for event type: '${String(type)}'`
|
|
95
192
|
);
|
|
96
193
|
} else {
|
|
97
|
-
this.
|
|
194
|
+
this.clearAllHandlers();
|
|
98
195
|
this.logger.debug("All event listeners cleared from EventBus");
|
|
99
196
|
}
|
|
100
197
|
}
|
|
@@ -105,15 +202,19 @@ class EventBus {
|
|
|
105
202
|
return Object.keys(this.handlers);
|
|
106
203
|
}
|
|
107
204
|
getStats() {
|
|
108
|
-
const
|
|
109
|
-
const
|
|
110
|
-
|
|
205
|
+
const eventNames = this.eventNames();
|
|
206
|
+
const listenerCount = Object.fromEntries(
|
|
207
|
+
eventNames.map((name) => [name, this.listenerCount(name)])
|
|
208
|
+
);
|
|
209
|
+
const totalListeners = Object.values(listenerCount).reduce(
|
|
210
|
+
(sum, count) => sum + count,
|
|
211
|
+
0
|
|
111
212
|
);
|
|
112
213
|
return {
|
|
113
|
-
totalEvents:
|
|
114
|
-
totalListeners
|
|
115
|
-
eventNames
|
|
116
|
-
listenerCount
|
|
214
|
+
totalEvents: eventNames.length,
|
|
215
|
+
totalListeners,
|
|
216
|
+
eventNames,
|
|
217
|
+
listenerCount
|
|
117
218
|
};
|
|
118
219
|
}
|
|
119
220
|
get isInitialized() {
|