@boo-dreamer/event-bus 0.0.3

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/index.cjs ADDED
@@ -0,0 +1,659 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
6
+ class WildcardMatcher {
7
+ /**
8
+ * 测试事件名称是否匹配模式
9
+ * @param pattern 模式(如 "user:*"、"**:*:error")
10
+ * @param event 事件名称(如 "user:login")
11
+ */
12
+ test(pattern, event) {
13
+ if (pattern === event) {
14
+ return true;
15
+ }
16
+ if (!pattern.includes("*")) {
17
+ return false;
18
+ }
19
+ const patternParts = pattern.split(":");
20
+ const eventParts = event.split(":");
21
+ return this.matchParts(patternParts, eventParts);
22
+ }
23
+ /**
24
+ * 递归匹配各部分
25
+ */
26
+ matchParts(patternParts, eventParts) {
27
+ let pIndex = 0;
28
+ let eIndex = 0;
29
+ while (pIndex < patternParts.length && eIndex < eventParts.length) {
30
+ const patternPart = patternParts[pIndex];
31
+ const eventPart = eventParts[eIndex];
32
+ if (patternPart === "**") {
33
+ if (pIndex === patternParts.length - 1) {
34
+ return true;
35
+ }
36
+ const remainingPattern = patternParts.slice(pIndex + 1);
37
+ for (let i = eIndex; i < eventParts.length; i++) {
38
+ if (this.matchParts(remainingPattern, eventParts.slice(i))) {
39
+ return true;
40
+ }
41
+ }
42
+ return false;
43
+ } else if (patternPart === "*") {
44
+ pIndex++;
45
+ eIndex++;
46
+ } else if (patternPart === eventPart) {
47
+ pIndex++;
48
+ eIndex++;
49
+ } else {
50
+ return false;
51
+ }
52
+ }
53
+ if (pIndex < patternParts.length) {
54
+ return patternParts.slice(pIndex).every((p) => p === "**");
55
+ }
56
+ return eIndex === eventParts.length;
57
+ }
58
+ /**
59
+ * 提取命名空间
60
+ * @param event 事件名称(如 "user:login:success")
61
+ * @returns 命名空间(如 "user")
62
+ */
63
+ getNamespace(event) {
64
+ const parts = event.split(":");
65
+ return parts[0] ?? "";
66
+ }
67
+ /**
68
+ * 提取事件名(不含命名空间)
69
+ * @param event 事件名称(如 "user:login:success")
70
+ * @returns 事件名(如 "login:success")
71
+ */
72
+ getEventName(event) {
73
+ const parts = event.split(":");
74
+ return parts.slice(1).join(":");
75
+ }
76
+ /**
77
+ * 检查是否为通配符模式
78
+ */
79
+ isWildcard(pattern) {
80
+ return pattern.includes("*");
81
+ }
82
+ /**
83
+ * 获取模式匹配的所有可能事件(有限集)
84
+ * 用于优化订阅查找
85
+ */
86
+ getPossibleEvents(pattern, knownEvents) {
87
+ if (!this.isWildcard(pattern)) {
88
+ return [pattern];
89
+ }
90
+ return knownEvents.filter((event) => this.test(pattern, event));
91
+ }
92
+ }
93
+ function createMatcher() {
94
+ return new WildcardMatcher();
95
+ }
96
+ const defaultMatcher = new WildcardMatcher();
97
+ class HistoryManager {
98
+ constructor(maxSize = 100, enabled = true) {
99
+ __publicField(this, "history", []);
100
+ __publicField(this, "maxSize");
101
+ __publicField(this, "enabled");
102
+ this.maxSize = maxSize;
103
+ this.enabled = enabled;
104
+ }
105
+ /**
106
+ * 添加历史记录
107
+ */
108
+ add(event, data) {
109
+ if (!this.enabled) {
110
+ return;
111
+ }
112
+ const entry = {
113
+ event,
114
+ data,
115
+ timestamp: Date.now()
116
+ };
117
+ this.history.push(entry);
118
+ if (this.history.length > this.maxSize) {
119
+ this.history.shift();
120
+ }
121
+ }
122
+ /**
123
+ * 获取历史记录
124
+ * @param event 事件名称(可选,不传则返回所有)
125
+ * @param count 数量限制
126
+ */
127
+ get(event, count) {
128
+ let result = [...this.history];
129
+ if (event) {
130
+ result = result.filter((entry) => entry.event === event);
131
+ }
132
+ if (count && count > 0) {
133
+ result = result.slice(-count);
134
+ }
135
+ return result;
136
+ }
137
+ /**
138
+ * 获取匹配通配符模式的历史记录
139
+ */
140
+ getByPattern(pattern, matcher, count) {
141
+ let result = this.history.filter((entry) => matcher(pattern, entry.event));
142
+ if (count && count > 0) {
143
+ result = result.slice(-count);
144
+ }
145
+ return result;
146
+ }
147
+ /**
148
+ * 清空历史
149
+ */
150
+ clear() {
151
+ this.history = [];
152
+ }
153
+ /**
154
+ * 获取历史记录数量
155
+ */
156
+ size() {
157
+ return this.history.length;
158
+ }
159
+ /**
160
+ * 获取特定事件的历史记录数量
161
+ */
162
+ sizeOf(event) {
163
+ return this.history.filter((entry) => entry.event === event).length;
164
+ }
165
+ /**
166
+ * 设置最大容量
167
+ */
168
+ setMaxSize(size) {
169
+ this.maxSize = size;
170
+ if (this.history.length > size) {
171
+ this.history = this.history.slice(-size);
172
+ }
173
+ }
174
+ /**
175
+ * 获取最大容量
176
+ */
177
+ getMaxSize() {
178
+ return this.maxSize;
179
+ }
180
+ /**
181
+ * 启用/禁用历史记录
182
+ */
183
+ setEnabled(enabled) {
184
+ this.enabled = enabled;
185
+ if (!enabled) {
186
+ this.clear();
187
+ }
188
+ }
189
+ /**
190
+ * 是否启用
191
+ */
192
+ isEnabled() {
193
+ return this.enabled;
194
+ }
195
+ /**
196
+ * 获取所有事件名称(去重)
197
+ */
198
+ getEventNames() {
199
+ return [...new Set(this.history.map((entry) => entry.event))];
200
+ }
201
+ /**
202
+ * 获取时间范围内的历史记录
203
+ */
204
+ getByTimeRange(startTime, endTime, event) {
205
+ let result = this.history.filter(
206
+ (entry) => entry.timestamp >= startTime && entry.timestamp <= endTime
207
+ );
208
+ if (event) {
209
+ result = result.filter((entry) => entry.event === event);
210
+ }
211
+ return result;
212
+ }
213
+ }
214
+ function createHistoryManager(maxSize, enabled) {
215
+ return new HistoryManager(maxSize, enabled);
216
+ }
217
+ class MiddlewareManager {
218
+ constructor() {
219
+ __publicField(this, "middlewares", []);
220
+ }
221
+ /**
222
+ * 注册中间件
223
+ */
224
+ use(middleware) {
225
+ this.middlewares.push(middleware);
226
+ }
227
+ /**
228
+ * 执行中间件链
229
+ */
230
+ async execute(ctx, finalHandler) {
231
+ let index = 0;
232
+ const next = async () => {
233
+ if (ctx.stopped) {
234
+ return;
235
+ }
236
+ if (index < this.middlewares.length) {
237
+ const middleware = this.middlewares[index++];
238
+ await middleware(ctx, next);
239
+ } else {
240
+ await finalHandler();
241
+ }
242
+ };
243
+ await next();
244
+ }
245
+ /**
246
+ * 获取中间件数量
247
+ */
248
+ count() {
249
+ return this.middlewares.length;
250
+ }
251
+ /**
252
+ * 清空所有中间件
253
+ */
254
+ clear() {
255
+ this.middlewares = [];
256
+ }
257
+ /**
258
+ * 移除特定中间件
259
+ */
260
+ remove(middleware) {
261
+ const index = this.middlewares.indexOf(middleware);
262
+ if (index > -1) {
263
+ this.middlewares.splice(index, 1);
264
+ return true;
265
+ }
266
+ return false;
267
+ }
268
+ }
269
+ function createEventContext(event, data) {
270
+ return {
271
+ event,
272
+ data,
273
+ stopped: false,
274
+ stopPropagation() {
275
+ this.stopped = true;
276
+ }
277
+ };
278
+ }
279
+ function createLoggerMiddleware(logger) {
280
+ return async (ctx, next) => {
281
+ const startTime = Date.now();
282
+ if (logger) {
283
+ logger(ctx.event, ctx.data);
284
+ } else {
285
+ console.log(`[EventBus] Event: ${ctx.event}`, ctx.data);
286
+ }
287
+ await next();
288
+ const duration = Date.now() - startTime;
289
+ console.log(`[EventBus] Event: ${ctx.event} processed in ${duration}ms`);
290
+ };
291
+ }
292
+ function createErrorMiddleware(onError) {
293
+ return async (ctx, next) => {
294
+ try {
295
+ await next();
296
+ } catch (error) {
297
+ const err = error instanceof Error ? error : new Error(String(error));
298
+ if (onError) {
299
+ onError(err, ctx.event, ctx.data);
300
+ } else {
301
+ console.error(`[EventBus] Error in event ${ctx.event}:`, err);
302
+ }
303
+ throw err;
304
+ }
305
+ };
306
+ }
307
+ function createPerformanceMiddleware(threshold = 100, onSlow) {
308
+ return async (ctx, next) => {
309
+ const startTime = performance.now();
310
+ await next();
311
+ const duration = performance.now() - startTime;
312
+ if (duration > threshold) {
313
+ if (onSlow) {
314
+ onSlow(ctx.event, duration, ctx.data);
315
+ } else {
316
+ console.warn(`[EventBus] Slow event: ${ctx.event} took ${duration.toFixed(2)}ms`);
317
+ }
318
+ }
319
+ };
320
+ }
321
+ function createValidationMiddleware(validator, onInvalid) {
322
+ return async (ctx, next) => {
323
+ const result = validator(ctx.data);
324
+ if (result === false || typeof result === "string") {
325
+ const reason = typeof result === "string" ? result : "Validation failed";
326
+ if (onInvalid) {
327
+ onInvalid(ctx.event, ctx.data, reason);
328
+ } else {
329
+ console.warn(`[EventBus] Validation failed for ${ctx.event}: ${reason}`);
330
+ }
331
+ ctx.stopPropagation();
332
+ return;
333
+ }
334
+ await next();
335
+ };
336
+ }
337
+ function createMiddlewareManager() {
338
+ return new MiddlewareManager();
339
+ }
340
+ class EventBus {
341
+ constructor(options = {}) {
342
+ __publicField(this, "subscribers", /* @__PURE__ */ new Map());
343
+ __publicField(this, "wildcardSubscribers", /* @__PURE__ */ new Map());
344
+ __publicField(this, "matcher");
345
+ __publicField(this, "history");
346
+ __publicField(this, "middleware");
347
+ __publicField(this, "options");
348
+ /**
349
+ * 默认错误处理器
350
+ */
351
+ __publicField(this, "defaultErrorHandler", (error, event, data) => {
352
+ console.error(`[EventBus] Error in event "${event}":`, error, data);
353
+ });
354
+ this.options = {
355
+ historySize: options.historySize ?? 100,
356
+ enableHistory: options.enableHistory ?? true,
357
+ onError: options.onError ?? this.defaultErrorHandler,
358
+ asyncHandlers: options.asyncHandlers ?? true
359
+ };
360
+ this.matcher = new WildcardMatcher();
361
+ this.history = new HistoryManager(this.options.historySize, this.options.enableHistory);
362
+ this.middleware = new MiddlewareManager();
363
+ }
364
+ /**
365
+ * 订阅事件
366
+ */
367
+ on(event, handler, options = {}) {
368
+ const eventName = String(event);
369
+ const subscriber = {
370
+ handler,
371
+ once: false,
372
+ priority: options.priority ?? 0
373
+ };
374
+ if (this.matcher.isWildcard(eventName)) {
375
+ this.addWildcardSubscriber(eventName, subscriber);
376
+ } else {
377
+ this.addSubscriber(eventName, subscriber);
378
+ }
379
+ if (options.replay) {
380
+ void this.replay(event, options.replayCount);
381
+ }
382
+ return () => {
383
+ this.off(event, handler);
384
+ };
385
+ }
386
+ /**
387
+ * 一次性订阅
388
+ */
389
+ once(event, handler, options = {}) {
390
+ const eventName = String(event);
391
+ const subscriber = {
392
+ handler,
393
+ once: true,
394
+ priority: options.priority ?? 0
395
+ };
396
+ if (this.matcher.isWildcard(eventName)) {
397
+ this.addWildcardSubscriber(eventName, subscriber);
398
+ } else {
399
+ this.addSubscriber(eventName, subscriber);
400
+ }
401
+ if (options.replay) {
402
+ void this.replay(event, options.replayCount);
403
+ }
404
+ return () => {
405
+ this.off(event, handler);
406
+ };
407
+ }
408
+ /**
409
+ * 取消订阅
410
+ */
411
+ off(event, handler) {
412
+ const eventName = String(event);
413
+ if (this.matcher.isWildcard(eventName)) {
414
+ this.removeWildcardSubscriber(eventName, handler);
415
+ } else {
416
+ this.removeSubscriber(eventName, handler);
417
+ }
418
+ }
419
+ /**
420
+ * 添加订阅者
421
+ */
422
+ addSubscriber(event, subscriber) {
423
+ if (!this.subscribers.has(event)) {
424
+ this.subscribers.set(event, /* @__PURE__ */ new Set());
425
+ }
426
+ this.subscribers.get(event).add(subscriber);
427
+ }
428
+ /**
429
+ * 移除订阅者
430
+ */
431
+ removeSubscriber(event, handler) {
432
+ const subs = this.subscribers.get(event);
433
+ if (!subs) return;
434
+ if (handler) {
435
+ for (const sub of subs) {
436
+ if (sub.handler === handler) {
437
+ subs.delete(sub);
438
+ break;
439
+ }
440
+ }
441
+ } else {
442
+ subs.clear();
443
+ }
444
+ if (subs.size === 0) {
445
+ this.subscribers.delete(event);
446
+ }
447
+ }
448
+ /**
449
+ * 添加通配符订阅者
450
+ */
451
+ addWildcardSubscriber(pattern, subscriber) {
452
+ if (!this.wildcardSubscribers.has(pattern)) {
453
+ this.wildcardSubscribers.set(pattern, /* @__PURE__ */ new Set());
454
+ }
455
+ this.wildcardSubscribers.get(pattern).add(subscriber);
456
+ }
457
+ /**
458
+ * 移除通配符订阅者
459
+ */
460
+ removeWildcardSubscriber(pattern, handler) {
461
+ const subs = this.wildcardSubscribers.get(pattern);
462
+ if (!subs) return;
463
+ if (handler) {
464
+ for (const sub of subs) {
465
+ if (sub.handler === handler) {
466
+ subs.delete(sub);
467
+ break;
468
+ }
469
+ }
470
+ } else {
471
+ subs.clear();
472
+ }
473
+ if (subs.size === 0) {
474
+ this.wildcardSubscribers.delete(pattern);
475
+ }
476
+ }
477
+ /**
478
+ * 获取匹配的订阅者(包括通配符)
479
+ */
480
+ getMatchingSubscribers(event) {
481
+ const result = [];
482
+ const exactSubs = this.subscribers.get(event);
483
+ if (exactSubs) {
484
+ result.push(...exactSubs);
485
+ }
486
+ for (const [pattern, subs] of this.wildcardSubscribers) {
487
+ if (this.matcher.test(pattern, event)) {
488
+ result.push(...subs);
489
+ }
490
+ }
491
+ return result.sort((a, b) => a.priority - b.priority);
492
+ }
493
+ /**
494
+ * 发射事件(同步返回 Promise 数组)
495
+ */
496
+ async emit(event, data) {
497
+ const eventName = String(event);
498
+ this.history.add(eventName, data);
499
+ const subscribers = this.getMatchingSubscribers(eventName);
500
+ const result = {
501
+ executedCount: 0,
502
+ failedCount: 0,
503
+ errors: []
504
+ };
505
+ if (subscribers.length === 0) {
506
+ return result;
507
+ }
508
+ const ctx = createEventContext(eventName, data);
509
+ await this.middleware.execute(ctx, async () => {
510
+ if (ctx.stopped) {
511
+ return;
512
+ }
513
+ const promises = subscribers.map(async (sub) => {
514
+ try {
515
+ await sub.handler(data);
516
+ result.executedCount++;
517
+ if (sub.once) {
518
+ this.off(event, sub.handler);
519
+ }
520
+ } catch (error) {
521
+ result.failedCount++;
522
+ const err = error instanceof Error ? error : new Error(String(error));
523
+ result.errors.push(err);
524
+ this.options.onError(err, eventName, data);
525
+ }
526
+ });
527
+ if (this.options.asyncHandlers) {
528
+ await Promise.all(promises);
529
+ } else {
530
+ for (const promise of promises) {
531
+ await promise;
532
+ }
533
+ }
534
+ });
535
+ return result;
536
+ }
537
+ /**
538
+ * 发射事件(异步等待所有 handler 完成)
539
+ */
540
+ async emitAsync(event, data) {
541
+ return this.emit(event, data);
542
+ }
543
+ /**
544
+ * 注册中间件
545
+ */
546
+ use(middleware) {
547
+ this.middleware.use(middleware);
548
+ }
549
+ /**
550
+ * 重放历史事件
551
+ */
552
+ async replay(event, count) {
553
+ const eventName = String(event);
554
+ const history = this.history.get(eventName, count);
555
+ const result = {
556
+ executedCount: 0,
557
+ failedCount: 0,
558
+ errors: []
559
+ };
560
+ for (const entry of history) {
561
+ try {
562
+ const subResult = await this.emit(event, entry.data);
563
+ result.executedCount += subResult.executedCount;
564
+ result.failedCount += subResult.failedCount;
565
+ result.errors.push(...subResult.errors);
566
+ } catch (error) {
567
+ result.failedCount++;
568
+ const err = error instanceof Error ? error : new Error(String(error));
569
+ result.errors.push(err);
570
+ }
571
+ }
572
+ return result;
573
+ }
574
+ /**
575
+ * 清空历史
576
+ */
577
+ clearHistory() {
578
+ this.history.clear();
579
+ }
580
+ /**
581
+ * 获取订阅数量
582
+ */
583
+ listenerCount(event) {
584
+ var _a;
585
+ if (event) {
586
+ const eventName = String(event);
587
+ const exactCount = ((_a = this.subscribers.get(eventName)) == null ? void 0 : _a.size) ?? 0;
588
+ let wildcardCount = 0;
589
+ for (const [pattern, subs] of this.wildcardSubscribers) {
590
+ if (this.matcher.test(pattern, eventName)) {
591
+ wildcardCount += subs.size;
592
+ }
593
+ }
594
+ return exactCount + wildcardCount;
595
+ }
596
+ let total = 0;
597
+ for (const subs of this.subscribers.values()) {
598
+ total += subs.size;
599
+ }
600
+ for (const subs of this.wildcardSubscribers.values()) {
601
+ total += subs.size;
602
+ }
603
+ return total;
604
+ }
605
+ /**
606
+ * 获取所有事件名称
607
+ */
608
+ eventNames() {
609
+ const names = /* @__PURE__ */ new Set();
610
+ for (const event of this.subscribers.keys()) {
611
+ names.add(event);
612
+ }
613
+ for (const event of this.history.getEventNames()) {
614
+ names.add(event);
615
+ }
616
+ return Array.from(names);
617
+ }
618
+ /**
619
+ * 销毁
620
+ */
621
+ destroy() {
622
+ this.subscribers.clear();
623
+ this.wildcardSubscribers.clear();
624
+ this.history.clear();
625
+ this.middleware.clear();
626
+ }
627
+ /**
628
+ * 获取历史管理器
629
+ */
630
+ getHistory() {
631
+ return this.history;
632
+ }
633
+ /**
634
+ * 获取中间件管理器
635
+ */
636
+ getMiddleware() {
637
+ return this.middleware;
638
+ }
639
+ }
640
+ function createEventBus(options) {
641
+ return new EventBus(options);
642
+ }
643
+ const eventBus = new EventBus();
644
+ exports.EventBus = EventBus;
645
+ exports.HistoryManager = HistoryManager;
646
+ exports.MiddlewareManager = MiddlewareManager;
647
+ exports.WildcardMatcher = WildcardMatcher;
648
+ exports.createErrorMiddleware = createErrorMiddleware;
649
+ exports.createEventBus = createEventBus;
650
+ exports.createEventContext = createEventContext;
651
+ exports.createHistoryManager = createHistoryManager;
652
+ exports.createLoggerMiddleware = createLoggerMiddleware;
653
+ exports.createMatcher = createMatcher;
654
+ exports.createMiddlewareManager = createMiddlewareManager;
655
+ exports.createPerformanceMiddleware = createPerformanceMiddleware;
656
+ exports.createValidationMiddleware = createValidationMiddleware;
657
+ exports.defaultMatcher = defaultMatcher;
658
+ exports.eventBus = eventBus;
659
+ //# sourceMappingURL=index.cjs.map