sehawq.db 4.0.3 → 4.0.5

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.
@@ -1,286 +1,286 @@
1
- /**
2
- * Event System - Makes everything reactive ⚡
3
- *
4
- * Listen to database changes, system events, anything!
5
- * Because sometimes you need to know when stuff happens
6
- */
7
-
8
- class Events {
9
- constructor() {
10
- this.events = new Map();
11
- this.maxListeners = 100;
12
- this.stats = {
13
- eventsEmitted: 0,
14
- listenersCalled: 0,
15
- errors: 0
16
- };
17
- }
18
-
19
- /**
20
- * Add event listener
21
- */
22
- on(event, listener, options = {}) {
23
- if (typeof listener !== 'function') {
24
- throw new Error('Listener must be a function');
25
- }
26
-
27
- if (!this.events.has(event)) {
28
- this.events.set(event, []);
29
- }
30
-
31
- const listeners = this.events.get(event);
32
-
33
- // Check max listeners
34
- if (listeners.length >= this.maxListeners) {
35
- console.warn(`⚠️ Event '${event}' has ${listeners.length} listeners, possible memory leak`);
36
- }
37
-
38
- // Add listener with options
39
- listeners.push({
40
- fn: listener,
41
- once: options.once || false,
42
- async: options.async || false,
43
- id: options.id || this._generateId()
44
- });
45
-
46
- return this;
47
- }
48
-
49
- /**
50
- * Add one-time event listener
51
- */
52
- once(event, listener, options = {}) {
53
- return this.on(event, listener, { ...options, once: true });
54
- }
55
-
56
- /**
57
- * Remove event listener
58
- */
59
- off(event, listener) {
60
- if (!this.events.has(event)) {
61
- return this;
62
- }
63
-
64
- const listeners = this.events.get(event);
65
-
66
- if (listener) {
67
- // Remove specific listener
68
- const index = listeners.findIndex(l => l.fn === listener);
69
- if (index > -1) {
70
- listeners.splice(index, 1);
71
- }
72
- } else {
73
- // Remove all listeners for event
74
- this.events.delete(event);
75
- }
76
-
77
- return this;
78
- }
79
-
80
- /**
81
- * Emit event
82
- */
83
- emit(event, ...args) {
84
- this.stats.eventsEmitted++;
85
-
86
- if (!this.events.has(event)) {
87
- return false;
88
- }
89
-
90
- const listeners = this.events.get(event).slice(); // Copy array
91
- let hasListeners = false;
92
-
93
- for (const listener of listeners) {
94
- hasListeners = true;
95
-
96
- // Remove one-time listeners
97
- if (listener.once) {
98
- this.off(event, listener.fn);
99
- }
100
-
101
- // Call listener
102
- this._callListener(listener, event, args);
103
- }
104
-
105
- return hasListeners;
106
- }
107
-
108
- /**
109
- * Call listener with error handling
110
- */
111
- _callListener(listener, event, args) {
112
- const callListener = () => {
113
- try {
114
- listener.fn.apply(this, args);
115
- this.stats.listenersCalled++;
116
- } catch (error) {
117
- this.stats.errors++;
118
- console.error(`🚨 Event listener error for '${event}':`, error);
119
-
120
- // Emit error event
121
- if (this.events.has('error')) {
122
- this.emit('error', error, event, listener);
123
- }
124
- }
125
- };
126
-
127
- if (listener.async) {
128
- setImmediate(callListener);
129
- } else {
130
- callListener();
131
- }
132
- }
133
-
134
- /**
135
- * Get all event names
136
- */
137
- eventNames() {
138
- return Array.from(this.events.keys());
139
- }
140
-
141
- /**
142
- * Get listeners for event
143
- */
144
- listeners(event) {
145
- return this.events.has(event)
146
- ? this.events.get(event).map(l => l.fn)
147
- : [];
148
- }
149
-
150
- /**
151
- * Get listener count for event
152
- */
153
- listenerCount(event) {
154
- return this.events.has(event) ? this.events.get(event).length : 0;
155
- }
156
-
157
- /**
158
- * Remove all listeners
159
- */
160
- removeAllListeners(event = null) {
161
- if (event) {
162
- this.events.delete(event);
163
- } else {
164
- this.events.clear();
165
- }
166
- return this;
167
- }
168
-
169
- /**
170
- * Set max listeners
171
- */
172
- setMaxListeners(n) {
173
- this.maxListeners = n;
174
- return this;
175
- }
176
-
177
- /**
178
- * Get max listeners
179
- */
180
- getMaxListeners() {
181
- return this.maxListeners;
182
- }
183
-
184
- /**
185
- * Generate unique ID for listener
186
- */
187
- _generateId() {
188
- return `listener_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
189
- }
190
-
191
- /**
192
- * Wait for event (Promise-based)
193
- */
194
- waitFor(event, timeout = 0) {
195
- return new Promise((resolve, reject) => {
196
- let timeoutId;
197
-
198
- const listener = (...args) => {
199
- if (timeoutId) clearTimeout(timeoutId);
200
- resolve(args);
201
- };
202
-
203
- this.once(event, listener);
204
-
205
- if (timeout > 0) {
206
- timeoutId = setTimeout(() => {
207
- this.off(event, listener);
208
- reject(new Error(`Event '${event}' timeout after ${timeout}ms`));
209
- }, timeout);
210
- }
211
- });
212
- }
213
-
214
- /**
215
- * Pipe events to another emitter
216
- */
217
- pipe(event, targetEmitter, targetEvent = null) {
218
- const targetEventName = targetEvent || event;
219
-
220
- return this.on(event, (...args) => {
221
- targetEmitter.emit(targetEventName, ...args);
222
- });
223
- }
224
-
225
- /**
226
- * Create namespaced event emitter
227
- */
228
- namespace(namespace) {
229
- const namespaced = new Events();
230
-
231
- // Pipe all events with namespace prefix
232
- this.on('*', (event, ...args) => {
233
- namespaced.emit(event, ...args);
234
- });
235
-
236
- // Pipe namespaced events back to parent
237
- namespaced.on('*', (event, ...args) => {
238
- this.emit(`${namespace}.${event}`, ...args);
239
- });
240
-
241
- return namespaced;
242
- }
243
-
244
- /**
245
- * Get event statistics
246
- */
247
- getStats() {
248
- const events = {};
249
-
250
- for (const [event, listeners] of this.events) {
251
- events[event] = {
252
- listeners: listeners.length,
253
- once: listeners.filter(l => l.once).length,
254
- async: listeners.filter(l => l.async).length
255
- };
256
- }
257
-
258
- return {
259
- ...this.stats,
260
- totalEvents: this.events.size,
261
- totalListeners: Array.from(this.events.values()).reduce((sum, listeners) => sum + listeners.length, 0),
262
- events
263
- };
264
- }
265
-
266
- /**
267
- * Debug: log all events
268
- */
269
- debug(enable = true) {
270
- if (enable) {
271
- this.on('*', (event, ...args) => {
272
- console.log(`🎯 Event: ${event}`, args);
273
- });
274
- } else {
275
- this.off('*');
276
- }
277
- return this;
278
- }
279
- }
280
-
281
- // Wildcard event support
282
- Events.prototype.on('*', function(event, ...args) {
283
- // This will be called for every event
284
- });
285
-
1
+ /**
2
+ * Event System - Makes everything reactive ⚡
3
+ *
4
+ * Listen to database changes, system events, anything!
5
+ * Because sometimes you need to know when stuff happens
6
+ */
7
+
8
+ class Events {
9
+ constructor() {
10
+ this.events = new Map();
11
+ this.maxListeners = 100;
12
+ this.stats = {
13
+ eventsEmitted: 0,
14
+ listenersCalled: 0,
15
+ errors: 0
16
+ };
17
+ }
18
+
19
+ /**
20
+ * Add event listener
21
+ */
22
+ on(event, listener, options = {}) {
23
+ if (typeof listener !== 'function') {
24
+ throw new Error('Listener must be a function');
25
+ }
26
+
27
+ if (!this.events.has(event)) {
28
+ this.events.set(event, []);
29
+ }
30
+
31
+ const listeners = this.events.get(event);
32
+
33
+ // Check max listeners
34
+ if (listeners.length >= this.maxListeners) {
35
+ console.warn(`⚠️ Event '${event}' has ${listeners.length} listeners, possible memory leak`);
36
+ }
37
+
38
+ // Add listener with options
39
+ listeners.push({
40
+ fn: listener,
41
+ once: options.once || false,
42
+ async: options.async || false,
43
+ id: options.id || this._generateId()
44
+ });
45
+
46
+ return this;
47
+ }
48
+
49
+ /**
50
+ * Add one-time event listener
51
+ */
52
+ once(event, listener, options = {}) {
53
+ return this.on(event, listener, { ...options, once: true });
54
+ }
55
+
56
+ /**
57
+ * Remove event listener
58
+ */
59
+ off(event, listener) {
60
+ if (!this.events.has(event)) {
61
+ return this;
62
+ }
63
+
64
+ const listeners = this.events.get(event);
65
+
66
+ if (listener) {
67
+ // Remove specific listener
68
+ const index = listeners.findIndex(l => l.fn === listener);
69
+ if (index > -1) {
70
+ listeners.splice(index, 1);
71
+ }
72
+ } else {
73
+ // Remove all listeners for event
74
+ this.events.delete(event);
75
+ }
76
+
77
+ return this;
78
+ }
79
+
80
+ /**
81
+ * Emit event
82
+ */
83
+ emit(event, ...args) {
84
+ this.stats.eventsEmitted++;
85
+
86
+ if (!this.events.has(event)) {
87
+ return false;
88
+ }
89
+
90
+ const listeners = this.events.get(event).slice(); // Copy array
91
+ let hasListeners = false;
92
+
93
+ for (const listener of listeners) {
94
+ hasListeners = true;
95
+
96
+ // Remove one-time listeners
97
+ if (listener.once) {
98
+ this.off(event, listener.fn);
99
+ }
100
+
101
+ // Call listener
102
+ this._callListener(listener, event, args);
103
+ }
104
+
105
+ return hasListeners;
106
+ }
107
+
108
+ /**
109
+ * Call listener with error handling
110
+ */
111
+ _callListener(listener, event, args) {
112
+ const callListener = () => {
113
+ try {
114
+ listener.fn.apply(this, args);
115
+ this.stats.listenersCalled++;
116
+ } catch (error) {
117
+ this.stats.errors++;
118
+ console.error(`🚨 Event listener error for '${event}':`, error);
119
+
120
+ // Emit error event
121
+ if (this.events.has('error')) {
122
+ this.emit('error', error, event, listener);
123
+ }
124
+ }
125
+ };
126
+
127
+ if (listener.async) {
128
+ setImmediate(callListener);
129
+ } else {
130
+ callListener();
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Get all event names
136
+ */
137
+ eventNames() {
138
+ return Array.from(this.events.keys());
139
+ }
140
+
141
+ /**
142
+ * Get listeners for event
143
+ */
144
+ listeners(event) {
145
+ return this.events.has(event)
146
+ ? this.events.get(event).map(l => l.fn)
147
+ : [];
148
+ }
149
+
150
+ /**
151
+ * Get listener count for event
152
+ */
153
+ listenerCount(event) {
154
+ return this.events.has(event) ? this.events.get(event).length : 0;
155
+ }
156
+
157
+ /**
158
+ * Remove all listeners
159
+ */
160
+ removeAllListeners(event = null) {
161
+ if (event) {
162
+ this.events.delete(event);
163
+ } else {
164
+ this.events.clear();
165
+ }
166
+ return this;
167
+ }
168
+
169
+ /**
170
+ * Set max listeners
171
+ */
172
+ setMaxListeners(n) {
173
+ this.maxListeners = n;
174
+ return this;
175
+ }
176
+
177
+ /**
178
+ * Get max listeners
179
+ */
180
+ getMaxListeners() {
181
+ return this.maxListeners;
182
+ }
183
+
184
+ /**
185
+ * Generate unique ID for listener
186
+ */
187
+ _generateId() {
188
+ return `listener_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
189
+ }
190
+
191
+ /**
192
+ * Wait for event (Promise-based)
193
+ */
194
+ waitFor(event, timeout = 0) {
195
+ return new Promise((resolve, reject) => {
196
+ let timeoutId;
197
+
198
+ const listener = (...args) => {
199
+ if (timeoutId) clearTimeout(timeoutId);
200
+ resolve(args);
201
+ };
202
+
203
+ this.once(event, listener);
204
+
205
+ if (timeout > 0) {
206
+ timeoutId = setTimeout(() => {
207
+ this.off(event, listener);
208
+ reject(new Error(`Event '${event}' timeout after ${timeout}ms`));
209
+ }, timeout);
210
+ }
211
+ });
212
+ }
213
+
214
+ /**
215
+ * Pipe events to another emitter
216
+ */
217
+ pipe(event, targetEmitter, targetEvent = null) {
218
+ const targetEventName = targetEvent || event;
219
+
220
+ return this.on(event, (...args) => {
221
+ targetEmitter.emit(targetEventName, ...args);
222
+ });
223
+ }
224
+
225
+ /**
226
+ * Create namespaced event emitter
227
+ */
228
+ namespace(namespace) {
229
+ const namespaced = new Events();
230
+
231
+ // Pipe all events with namespace prefix
232
+ this.on('*', (event, ...args) => {
233
+ namespaced.emit(event, ...args);
234
+ });
235
+
236
+ // Pipe namespaced events back to parent
237
+ namespaced.on('*', (event, ...args) => {
238
+ this.emit(`${namespace}.${event}`, ...args);
239
+ });
240
+
241
+ return namespaced;
242
+ }
243
+
244
+ /**
245
+ * Get event statistics
246
+ */
247
+ getStats() {
248
+ const events = {};
249
+
250
+ for (const [event, listeners] of this.events) {
251
+ events[event] = {
252
+ listeners: listeners.length,
253
+ once: listeners.filter(l => l.once).length,
254
+ async: listeners.filter(l => l.async).length
255
+ };
256
+ }
257
+
258
+ return {
259
+ ...this.stats,
260
+ totalEvents: this.events.size,
261
+ totalListeners: Array.from(this.events.values()).reduce((sum, listeners) => sum + listeners.length, 0),
262
+ events
263
+ };
264
+ }
265
+
266
+ /**
267
+ * Debug: log all events
268
+ */
269
+ debug(enable = true) {
270
+ if (enable) {
271
+ this.on('*', (event, ...args) => {
272
+ console.log(`🎯 Event: ${event}`, args);
273
+ });
274
+ } else {
275
+ this.off('*');
276
+ }
277
+ return this;
278
+ }
279
+ }
280
+
281
+ // Wildcard event support
282
+ Events.prototype.on('*', function(event, ...args) {
283
+ // This will be called for every event
284
+ });
285
+
286
286
  module.exports = Events;