@bernierllc/event-emitter 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.
@@ -0,0 +1,149 @@
1
+ TN:
2
+ SF:src/event-emitter.ts
3
+ FN:20,(anonymous_0)
4
+ FN:42,(anonymous_1)
5
+ FN:56,(anonymous_2)
6
+ FN:78,(anonymous_3)
7
+ FN:87,(anonymous_4)
8
+ FN:112,(anonymous_5)
9
+ FN:124,(anonymous_6)
10
+ FN:153,(anonymous_7)
11
+ FN:173,(anonymous_8)
12
+ FN:183,(anonymous_9)
13
+ FNF:10
14
+ FNH:10
15
+ FNDA:96,(anonymous_0)
16
+ FNDA:212,(anonymous_1)
17
+ FNDA:2,(anonymous_2)
18
+ FNDA:9,(anonymous_3)
19
+ FNDA:19,(anonymous_4)
20
+ FNDA:56,(anonymous_5)
21
+ FNDA:75,(anonymous_6)
22
+ FNDA:6,(anonymous_7)
23
+ FNDA:47,(anonymous_8)
24
+ FNDA:3,(anonymous_9)
25
+ DA:14,5
26
+ DA:21,96
27
+ DA:22,96
28
+ DA:23,96
29
+ DA:30,96
30
+ DA:32,96
31
+ DA:33,96
32
+ DA:44,212
33
+ DA:45,3
34
+ DA:46,3
35
+ DA:47,1
36
+ DA:51,211
37
+ DA:56,2
38
+ DA:59,211
39
+ DA:60,17
40
+ DA:62,194
41
+ DA:63,69
42
+ DA:65,194
43
+ DA:68,211
44
+ DA:69,10
45
+ DA:72,211
46
+ DA:79,9
47
+ DA:80,9
48
+ DA:81,9
49
+ DA:88,19
50
+ DA:89,4
51
+ DA:91,15
52
+ DA:92,15
53
+ DA:93,14
54
+ DA:95,14
55
+ DA:96,12
56
+ DA:101,19
57
+ DA:102,1
58
+ DA:113,56
59
+ DA:114,4
60
+ DA:118,56
61
+ DA:121,56
62
+ DA:124,56
63
+ DA:125,75
64
+ DA:126,75
65
+ DA:128,27
66
+ DA:129,23
67
+ DA:130,23
68
+ DA:137,4
69
+ DA:141,75
70
+ DA:142,8
71
+ DA:147,56
72
+ DA:154,6
73
+ DA:155,3
74
+ DA:156,1
75
+ DA:158,2
76
+ DA:161,3
77
+ DA:162,3
78
+ DA:165,6
79
+ DA:166,2
80
+ DA:174,47
81
+ DA:175,6
82
+ DA:177,41
83
+ DA:184,3
84
+ DA:185,3
85
+ DA:186,1
86
+ DA:188,3
87
+ LF:62
88
+ LH:62
89
+ BRDA:20,0,0,66
90
+ BRDA:24,1,0,96
91
+ BRDA:24,1,1,93
92
+ BRDA:25,2,0,96
93
+ BRDA:25,2,1,87
94
+ BRDA:44,3,0,3
95
+ BRDA:46,4,0,1
96
+ BRDA:59,5,0,17
97
+ BRDA:59,5,1,194
98
+ BRDA:62,6,0,69
99
+ BRDA:68,7,0,10
100
+ BRDA:68,8,0,211
101
+ BRDA:68,8,1,10
102
+ BRDA:88,9,0,4
103
+ BRDA:88,9,1,15
104
+ BRDA:92,10,0,14
105
+ BRDA:95,11,0,12
106
+ BRDA:101,12,0,1
107
+ BRDA:101,13,0,19
108
+ BRDA:101,13,1,1
109
+ BRDA:113,14,0,4
110
+ BRDA:113,15,0,56
111
+ BRDA:113,15,1,4
112
+ BRDA:118,16,0,56
113
+ BRDA:118,16,1,13
114
+ BRDA:128,17,0,23
115
+ BRDA:128,17,1,4
116
+ BRDA:129,18,0,23
117
+ BRDA:133,19,0,20
118
+ BRDA:133,19,1,3
119
+ BRDA:141,20,0,8
120
+ BRDA:154,21,0,3
121
+ BRDA:154,21,1,3
122
+ BRDA:155,22,0,1
123
+ BRDA:155,22,1,2
124
+ BRDA:165,23,0,2
125
+ BRDA:165,24,0,6
126
+ BRDA:165,24,1,2
127
+ BRDA:166,25,0,2
128
+ BRDA:166,25,1,1
129
+ BRDA:174,26,0,6
130
+ BRDA:177,27,0,41
131
+ BRDA:177,27,1,21
132
+ BRDA:185,28,0,1
133
+ BRF:44
134
+ BRH:44
135
+ end_of_record
136
+ TN:
137
+ SF:src/factory.ts
138
+ FN:15,createEventEmitter
139
+ FNF:1
140
+ FNH:1
141
+ FNDA:2,createEventEmitter
142
+ DA:9,5
143
+ DA:15,5
144
+ DA:16,2
145
+ LF:3
146
+ LH:3
147
+ BRF:0
148
+ BRH:0
149
+ end_of_record
@@ -0,0 +1,39 @@
1
+ import { EventHandler, EventSubscription, EventEmitterOptions } from './types';
2
+ /**
3
+ * Event bus for inter-package communication
4
+ */
5
+ export declare class EventEmitter {
6
+ private listeners;
7
+ private wildcardListeners;
8
+ private options;
9
+ private logger?;
10
+ constructor(options?: EventEmitterOptions);
11
+ /**
12
+ * Subscribe to event
13
+ */
14
+ on<T = any>(eventType: string, handler: EventHandler<T>): EventSubscription;
15
+ /**
16
+ * Subscribe to event once
17
+ */
18
+ once<T = any>(eventType: string, handler: EventHandler<T>): EventSubscription;
19
+ /**
20
+ * Unsubscribe from event
21
+ */
22
+ off(subscription: EventSubscription): void;
23
+ /**
24
+ * Publish event
25
+ */
26
+ emit<T = any>(eventType: string, data: T): Promise<void>;
27
+ /**
28
+ * Remove all listeners for event type
29
+ */
30
+ removeAllListeners(eventType?: string): void;
31
+ /**
32
+ * Get listener count for event type
33
+ */
34
+ listenerCount(eventType: string): number;
35
+ /**
36
+ * Get all event types with listeners
37
+ */
38
+ eventNames(): string[];
39
+ }
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.EventEmitter = void 0;
11
+ /**
12
+ * Event bus for inter-package communication
13
+ */
14
+ class EventEmitter {
15
+ constructor(options = {}) {
16
+ this.listeners = new Map();
17
+ this.wildcardListeners = new Set();
18
+ this.options = {
19
+ maxListeners: options.maxListeners || 0,
20
+ logEvents: options.logEvents || false,
21
+ captureErrors: options.captureErrors !== false // Default to true
22
+ };
23
+ // Try to load logger if available
24
+ try {
25
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
26
+ const { createLogger } = require('@bernierllc/logger');
27
+ this.logger = createLogger({ level: 'debug' });
28
+ }
29
+ catch {
30
+ // Logger not available, continue without it
31
+ }
32
+ }
33
+ /**
34
+ * Subscribe to event
35
+ */
36
+ on(eventType, handler) {
37
+ // Check max listeners
38
+ if (this.options.maxListeners > 0) {
39
+ const currentCount = this.listenerCount(eventType);
40
+ if (currentCount >= this.options.maxListeners) {
41
+ throw new Error(`Max listeners (${this.options.maxListeners}) exceeded for event type: ${eventType}`);
42
+ }
43
+ }
44
+ const subscription = {
45
+ id: `${eventType}-${Date.now()}-${Math.random()}`,
46
+ eventType,
47
+ handler,
48
+ once: false,
49
+ unsubscribe: () => this.off(subscription)
50
+ };
51
+ if (eventType === '*') {
52
+ this.wildcardListeners.add(subscription);
53
+ }
54
+ else {
55
+ if (!this.listeners.has(eventType)) {
56
+ this.listeners.set(eventType, new Set());
57
+ }
58
+ this.listeners.get(eventType).add(subscription);
59
+ }
60
+ if (this.options.logEvents && this.logger) {
61
+ this.logger.debug('Event listener added', { eventType, subscriptionId: subscription.id });
62
+ }
63
+ return subscription;
64
+ }
65
+ /**
66
+ * Subscribe to event once
67
+ */
68
+ once(eventType, handler) {
69
+ const subscription = this.on(eventType, handler);
70
+ subscription.once = true;
71
+ return subscription;
72
+ }
73
+ /**
74
+ * Unsubscribe from event
75
+ */
76
+ off(subscription) {
77
+ if (subscription.eventType === '*') {
78
+ this.wildcardListeners.delete(subscription);
79
+ }
80
+ else {
81
+ const listeners = this.listeners.get(subscription.eventType);
82
+ if (listeners) {
83
+ listeners.delete(subscription);
84
+ // Clean up empty sets
85
+ if (listeners.size === 0) {
86
+ this.listeners.delete(subscription.eventType);
87
+ }
88
+ }
89
+ }
90
+ if (this.options.logEvents && this.logger) {
91
+ this.logger.debug('Event listener removed', {
92
+ eventType: subscription.eventType,
93
+ subscriptionId: subscription.id
94
+ });
95
+ }
96
+ }
97
+ /**
98
+ * Publish event
99
+ */
100
+ async emit(eventType, data) {
101
+ if (this.options.logEvents && this.logger) {
102
+ this.logger.debug('Event emitted', { eventType, data });
103
+ }
104
+ // Get specific listeners
105
+ const specificListeners = this.listeners.get(eventType) || new Set();
106
+ // Combine with wildcard listeners
107
+ const allListeners = [...specificListeners, ...this.wildcardListeners];
108
+ // Execute handlers
109
+ const promises = allListeners.map(async (subscription) => {
110
+ try {
111
+ await subscription.handler(data);
112
+ }
113
+ catch (error) {
114
+ if (this.options.captureErrors) {
115
+ if (this.logger) {
116
+ this.logger.error('Event handler error', {
117
+ eventType,
118
+ subscriptionId: subscription.id,
119
+ error: error instanceof Error ? error.message : String(error)
120
+ });
121
+ }
122
+ }
123
+ else {
124
+ throw error;
125
+ }
126
+ }
127
+ finally {
128
+ // Remove if once subscription (always happens, even if error occurred)
129
+ if (subscription.once) {
130
+ this.off(subscription);
131
+ }
132
+ }
133
+ });
134
+ await Promise.all(promises);
135
+ }
136
+ /**
137
+ * Remove all listeners for event type
138
+ */
139
+ removeAllListeners(eventType) {
140
+ if (eventType) {
141
+ if (eventType === '*') {
142
+ this.wildcardListeners.clear();
143
+ }
144
+ else {
145
+ this.listeners.delete(eventType);
146
+ }
147
+ }
148
+ else {
149
+ this.listeners.clear();
150
+ this.wildcardListeners.clear();
151
+ }
152
+ if (this.options.logEvents && this.logger) {
153
+ this.logger.debug('Listeners removed', { eventType: eventType || 'all' });
154
+ }
155
+ }
156
+ /**
157
+ * Get listener count for event type
158
+ */
159
+ listenerCount(eventType) {
160
+ if (eventType === '*') {
161
+ return this.wildcardListeners.size;
162
+ }
163
+ return this.listeners.get(eventType)?.size || 0;
164
+ }
165
+ /**
166
+ * Get all event types with listeners
167
+ */
168
+ eventNames() {
169
+ const names = Array.from(this.listeners.keys());
170
+ if (this.wildcardListeners.size > 0) {
171
+ names.push('*');
172
+ }
173
+ return names;
174
+ }
175
+ }
176
+ exports.EventEmitter = EventEmitter;
@@ -0,0 +1,6 @@
1
+ import { EventEmitter } from './event-emitter';
2
+ import { EventEmitterOptions } from './types';
3
+ /**
4
+ * Factory function for creating event emitters
5
+ */
6
+ export declare function createEventEmitter(options?: EventEmitterOptions): EventEmitter;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.createEventEmitter = createEventEmitter;
11
+ const event_emitter_1 = require("./event-emitter");
12
+ /**
13
+ * Factory function for creating event emitters
14
+ */
15
+ function createEventEmitter(options) {
16
+ return new event_emitter_1.EventEmitter(options);
17
+ }
@@ -0,0 +1,3 @@
1
+ export { EventEmitter } from './event-emitter';
2
+ export { createEventEmitter } from './factory';
3
+ export type { EventHandler, EventSubscription, EventEmitterOptions } from './types';
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.createEventEmitter = exports.EventEmitter = void 0;
11
+ var event_emitter_1 = require("./event-emitter");
12
+ Object.defineProperty(exports, "EventEmitter", { enumerable: true, get: function () { return event_emitter_1.EventEmitter; } });
13
+ var factory_1 = require("./factory");
14
+ Object.defineProperty(exports, "createEventEmitter", { enumerable: true, get: function () { return factory_1.createEventEmitter; } });
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Event handler function
3
+ */
4
+ export type EventHandler<T = any> = (data: T) => void | Promise<void>;
5
+ /**
6
+ * Event subscription
7
+ */
8
+ export interface EventSubscription {
9
+ /** Unique subscription ID */
10
+ id: string;
11
+ /** Event type */
12
+ eventType: string;
13
+ /** Handler function */
14
+ handler: EventHandler;
15
+ /** Whether this is a one-time subscription */
16
+ once: boolean;
17
+ /** Unsubscribe function */
18
+ unsubscribe: () => void;
19
+ }
20
+ /**
21
+ * Event emitter options
22
+ */
23
+ export interface EventEmitterOptions {
24
+ /** Maximum listeners per event (0 = unlimited) */
25
+ maxListeners?: number;
26
+ /** Whether to log events */
27
+ logEvents?: boolean;
28
+ /** Whether to capture errors */
29
+ captureErrors?: boolean;
30
+ }
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,29 @@
1
+ /*
2
+ Copyright (c) 2025 Bernier LLC
3
+
4
+ This file is licensed to the client under a limited-use license.
5
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
6
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
7
+ */
8
+
9
+ module.exports = {
10
+ preset: 'ts-jest',
11
+ testEnvironment: 'node',
12
+ roots: ['<rootDir>/__tests__'],
13
+ testMatch: ['**/*.test.ts'],
14
+ collectCoverageFrom: [
15
+ 'src/**/*.ts',
16
+ '!src/**/*.d.ts',
17
+ '!src/index.ts'
18
+ ],
19
+ coverageThreshold: {
20
+ global: {
21
+ branches: 90,
22
+ functions: 90,
23
+ lines: 90,
24
+ statements: 90
25
+ }
26
+ },
27
+ coverageDirectory: 'coverage',
28
+ verbose: true
29
+ };
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@bernierllc/event-emitter",
3
+ "version": "1.0.1",
4
+ "description": "Type-safe event bus for inter-package communication",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "keywords": [
8
+ "event-emitter",
9
+ "event-bus",
10
+ "pubsub",
11
+ "messaging",
12
+ "events"
13
+ ],
14
+ "author": "Bernier LLC",
15
+ "license": "SEE LICENSE IN LICENSE",
16
+ "dependencies": {
17
+ "@bernierllc/logger": "^1.0.0"
18
+ },
19
+ "devDependencies": {
20
+ "@types/jest": "^29.5.0",
21
+ "@types/node": "^20.0.0",
22
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
23
+ "@typescript-eslint/parser": "^6.0.0",
24
+ "eslint": "^8.0.0",
25
+ "jest": "^29.5.0",
26
+ "ts-jest": "^29.1.0",
27
+ "typescript": "^5.0.0"
28
+ },
29
+ "bernierllc": {
30
+ "integration": {
31
+ "logger": "integrated",
32
+ "docsIntegration": "ready",
33
+ "neverhub": "optional"
34
+ }
35
+ },
36
+ "scripts": {
37
+ "build": "tsc",
38
+ "test": "jest --watch",
39
+ "test:run": "jest",
40
+ "test:coverage": "jest --coverage",
41
+ "lint": "eslint src __tests__ --ext .ts",
42
+ "clean": "rm -rf dist"
43
+ }
44
+ }