mutts 1.0.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/chunks/{decorator-BXsign4Z.js → decorator-8qjFb7dw.js} +2 -2
- package/dist/chunks/decorator-8qjFb7dw.js.map +1 -0
- package/dist/chunks/{decorator-CPbZNnsX.esm.js → decorator-AbRkXM5O.esm.js} +2 -2
- package/dist/chunks/decorator-AbRkXM5O.esm.js.map +1 -0
- package/dist/decorator.d.ts +1 -1
- package/dist/decorator.esm.js +1 -1
- package/dist/decorator.js +1 -1
- package/dist/destroyable.esm.js +1 -1
- package/dist/destroyable.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +2 -2
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/mutts.umd.js +1 -1
- package/dist/mutts.umd.js.map +1 -1
- package/dist/mutts.umd.min.js +1 -1
- package/dist/mutts.umd.min.js.map +1 -1
- package/dist/reactive.d.ts +4 -3
- package/dist/reactive.esm.js +61 -57
- package/dist/reactive.esm.js.map +1 -1
- package/dist/reactive.js +61 -56
- package/dist/reactive.js.map +1 -1
- package/dist/std-decorators.esm.js +1 -1
- package/dist/std-decorators.js +1 -1
- package/docs/reactive.md +616 -0
- package/package.json +1 -2
- package/dist/chunks/decorator-BXsign4Z.js.map +0 -1
- package/dist/chunks/decorator-CPbZNnsX.esm.js.map +0 -1
- package/src/decorator.test.ts +0 -495
- package/src/decorator.ts +0 -205
- package/src/destroyable.test.ts +0 -155
- package/src/destroyable.ts +0 -158
- package/src/eventful.test.ts +0 -380
- package/src/eventful.ts +0 -69
- package/src/index.ts +0 -7
- package/src/indexable.test.ts +0 -388
- package/src/indexable.ts +0 -124
- package/src/promiseChain.test.ts +0 -201
- package/src/promiseChain.ts +0 -99
- package/src/reactive/array.test.ts +0 -923
- package/src/reactive/array.ts +0 -352
- package/src/reactive/core.test.ts +0 -1663
- package/src/reactive/core.ts +0 -866
- package/src/reactive/index.ts +0 -28
- package/src/reactive/interface.test.ts +0 -1477
- package/src/reactive/interface.ts +0 -231
- package/src/reactive/map.test.ts +0 -866
- package/src/reactive/map.ts +0 -162
- package/src/reactive/set.test.ts +0 -289
- package/src/reactive/set.ts +0 -142
- package/src/std-decorators.test.ts +0 -679
- package/src/std-decorators.ts +0 -182
- package/src/utils.ts +0 -52
package/src/eventful.test.ts
DELETED
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
import { Eventful } from './eventful'
|
|
2
|
-
|
|
3
|
-
describe('Eventful', () => {
|
|
4
|
-
// Define test event types
|
|
5
|
-
interface TestEvents extends Record<string, (...args: any[]) => void> {
|
|
6
|
-
userLogin: (userId: string, timestamp: Date) => void
|
|
7
|
-
dataUpdate: (data: any[]) => void
|
|
8
|
-
error: (error: Error) => void
|
|
9
|
-
simple: () => void
|
|
10
|
-
withNumber: (value: number) => void
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
class TestEventful extends Eventful<TestEvents> {
|
|
14
|
-
// Test class that extends Eventful
|
|
15
|
-
// Just make `emit` public for testing
|
|
16
|
-
public emit<EventType extends keyof TestEvents>(
|
|
17
|
-
event: EventType,
|
|
18
|
-
...args: Parameters<TestEvents[EventType]>
|
|
19
|
-
) {
|
|
20
|
-
super.emit(event, ...args)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
describe('basic functionality', () => {
|
|
25
|
-
it('should register and emit single events', () => {
|
|
26
|
-
const eventful = new TestEventful()
|
|
27
|
-
let callCount = 0
|
|
28
|
-
let receivedUserId = ''
|
|
29
|
-
let receivedTimestamp: Date | null = null
|
|
30
|
-
|
|
31
|
-
eventful.on('userLogin', (userId, timestamp) => {
|
|
32
|
-
callCount++
|
|
33
|
-
receivedUserId = userId
|
|
34
|
-
receivedTimestamp = timestamp
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
const testDate = new Date()
|
|
38
|
-
eventful.emit('userLogin', 'user123', testDate)
|
|
39
|
-
|
|
40
|
-
expect(callCount).toBe(1)
|
|
41
|
-
expect(receivedUserId).toBe('user123')
|
|
42
|
-
expect(receivedTimestamp).toBe(testDate)
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it('should register and emit events with no parameters', () => {
|
|
46
|
-
const eventful = new TestEventful()
|
|
47
|
-
let callCount = 0
|
|
48
|
-
|
|
49
|
-
eventful.on('simple', () => {
|
|
50
|
-
callCount++
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
eventful.emit('simple')
|
|
54
|
-
|
|
55
|
-
expect(callCount).toBe(1)
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
it('should register and emit events with primitive parameters', () => {
|
|
59
|
-
const eventful = new TestEventful()
|
|
60
|
-
let receivedValue = 0
|
|
61
|
-
|
|
62
|
-
eventful.on('withNumber', (value) => {
|
|
63
|
-
receivedValue = value
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
eventful.emit('withNumber', 42)
|
|
67
|
-
|
|
68
|
-
expect(receivedValue).toBe(42)
|
|
69
|
-
})
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
describe('multiple listeners', () => {
|
|
73
|
-
it('should support multiple listeners for the same event', () => {
|
|
74
|
-
const eventful = new TestEventful()
|
|
75
|
-
let callCount1 = 0
|
|
76
|
-
let callCount2 = 0
|
|
77
|
-
|
|
78
|
-
eventful.on('simple', () => callCount1++)
|
|
79
|
-
eventful.on('simple', () => callCount2++)
|
|
80
|
-
|
|
81
|
-
eventful.emit('simple')
|
|
82
|
-
|
|
83
|
-
expect(callCount1).toBe(1)
|
|
84
|
-
expect(callCount2).toBe(1)
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
it('should call all listeners in registration order', () => {
|
|
88
|
-
const eventful = new TestEventful()
|
|
89
|
-
const callOrder: number[] = []
|
|
90
|
-
|
|
91
|
-
eventful.on('simple', () => callOrder.push(1))
|
|
92
|
-
eventful.on('simple', () => callOrder.push(2))
|
|
93
|
-
eventful.on('simple', () => callOrder.push(3))
|
|
94
|
-
|
|
95
|
-
eventful.emit('simple')
|
|
96
|
-
|
|
97
|
-
expect(callOrder).toEqual([1, 2, 3])
|
|
98
|
-
})
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
describe('unsubscribe functionality', () => {
|
|
102
|
-
it('should return unsubscribe function for single event', () => {
|
|
103
|
-
const eventful = new TestEventful()
|
|
104
|
-
let callCount = 0
|
|
105
|
-
|
|
106
|
-
const unsubscribe = eventful.on('simple', () => callCount++)
|
|
107
|
-
|
|
108
|
-
eventful.emit('simple')
|
|
109
|
-
expect(callCount).toBe(1)
|
|
110
|
-
|
|
111
|
-
unsubscribe()
|
|
112
|
-
eventful.emit('simple')
|
|
113
|
-
expect(callCount).toBe(1) // Should not increment
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
it('should unsubscribe specific callback when provided', () => {
|
|
117
|
-
const eventful = new TestEventful()
|
|
118
|
-
let callCount1 = 0
|
|
119
|
-
let callCount2 = 0
|
|
120
|
-
|
|
121
|
-
const callback1 = () => callCount1++
|
|
122
|
-
const callback2 = () => callCount2++
|
|
123
|
-
|
|
124
|
-
eventful.on('simple', callback1)
|
|
125
|
-
eventful.on('simple', callback2)
|
|
126
|
-
|
|
127
|
-
eventful.emit('simple')
|
|
128
|
-
expect(callCount1).toBe(1)
|
|
129
|
-
expect(callCount2).toBe(1)
|
|
130
|
-
|
|
131
|
-
eventful.off('simple', callback1)
|
|
132
|
-
eventful.emit('simple')
|
|
133
|
-
expect(callCount1).toBe(1) // Should not increment
|
|
134
|
-
expect(callCount2).toBe(2) // Should still increment
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
it('should remove all listeners when no callback provided to off', () => {
|
|
138
|
-
const eventful = new TestEventful()
|
|
139
|
-
let callCount1 = 0
|
|
140
|
-
let callCount2 = 0
|
|
141
|
-
|
|
142
|
-
eventful.on('simple', () => callCount1++)
|
|
143
|
-
eventful.on('simple', () => callCount2++)
|
|
144
|
-
|
|
145
|
-
eventful.emit('simple')
|
|
146
|
-
expect(callCount1).toBe(1)
|
|
147
|
-
expect(callCount2).toBe(1)
|
|
148
|
-
|
|
149
|
-
eventful.off('simple')
|
|
150
|
-
eventful.emit('simple')
|
|
151
|
-
expect(callCount1).toBe(1) // Should not increment
|
|
152
|
-
expect(callCount2).toBe(1) // Should not increment
|
|
153
|
-
})
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
describe('bulk event registration', () => {
|
|
157
|
-
it('should register multiple events at once', () => {
|
|
158
|
-
const eventful = new TestEventful()
|
|
159
|
-
let loginCount = 0
|
|
160
|
-
let dataCount = 0
|
|
161
|
-
let errorCount = 0
|
|
162
|
-
|
|
163
|
-
eventful.on({
|
|
164
|
-
userLogin: () => loginCount++,
|
|
165
|
-
dataUpdate: () => dataCount++,
|
|
166
|
-
error: () => errorCount++,
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
eventful.emit('userLogin', 'user123', new Date())
|
|
170
|
-
eventful.emit('dataUpdate', [1, 2, 3])
|
|
171
|
-
eventful.emit('error', new Error('test'))
|
|
172
|
-
|
|
173
|
-
expect(loginCount).toBe(1)
|
|
174
|
-
expect(dataCount).toBe(1)
|
|
175
|
-
expect(errorCount).toBe(1)
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
it('should unsubscribe multiple events at once', () => {
|
|
179
|
-
const eventful = new TestEventful()
|
|
180
|
-
let loginCount = 0
|
|
181
|
-
let dataCount = 0
|
|
182
|
-
|
|
183
|
-
const loginCallback = () => loginCount++
|
|
184
|
-
const dataCallback = () => dataCount++
|
|
185
|
-
|
|
186
|
-
eventful.on('userLogin', loginCallback)
|
|
187
|
-
eventful.on('dataUpdate', dataCallback)
|
|
188
|
-
|
|
189
|
-
eventful.emit('userLogin', 'user123', new Date())
|
|
190
|
-
eventful.emit('dataUpdate', [1, 2, 3])
|
|
191
|
-
expect(loginCount).toBe(1)
|
|
192
|
-
expect(dataCount).toBe(1)
|
|
193
|
-
|
|
194
|
-
eventful.off({
|
|
195
|
-
userLogin: loginCallback,
|
|
196
|
-
dataUpdate: dataCallback,
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
eventful.emit('userLogin', 'user123', new Date())
|
|
200
|
-
eventful.emit('dataUpdate', [1, 2, 3])
|
|
201
|
-
expect(loginCount).toBe(1) // Should not increment
|
|
202
|
-
expect(dataCount).toBe(1) // Should not increment
|
|
203
|
-
})
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
describe('global hooks', () => {
|
|
207
|
-
it('should call global hooks for all events', () => {
|
|
208
|
-
const eventful = new TestEventful()
|
|
209
|
-
const hookCalls: Array<{ event: string; args: any[] }> = []
|
|
210
|
-
|
|
211
|
-
eventful.hook((event, ...args) => {
|
|
212
|
-
hookCalls.push({ event: String(event), args })
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
eventful.emit('userLogin', 'user123', new Date())
|
|
216
|
-
eventful.emit('simple')
|
|
217
|
-
eventful.emit('withNumber', 42)
|
|
218
|
-
|
|
219
|
-
expect(hookCalls).toHaveLength(3)
|
|
220
|
-
expect(hookCalls[0].event).toBe('userLogin')
|
|
221
|
-
expect(hookCalls[0].args).toEqual(['user123', expect.any(Date)])
|
|
222
|
-
expect(hookCalls[1].event).toBe('simple')
|
|
223
|
-
expect(hookCalls[1].args).toEqual([])
|
|
224
|
-
expect(hookCalls[2].event).toBe('withNumber')
|
|
225
|
-
expect(hookCalls[2].args).toEqual([42])
|
|
226
|
-
})
|
|
227
|
-
|
|
228
|
-
it('should support multiple global hooks', () => {
|
|
229
|
-
const eventful = new TestEventful()
|
|
230
|
-
let hook1Count = 0
|
|
231
|
-
let hook2Count = 0
|
|
232
|
-
|
|
233
|
-
eventful.hook(() => hook1Count++)
|
|
234
|
-
eventful.hook(() => hook2Count++)
|
|
235
|
-
|
|
236
|
-
eventful.emit('simple')
|
|
237
|
-
|
|
238
|
-
expect(hook1Count).toBe(1)
|
|
239
|
-
expect(hook2Count).toBe(1)
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
it('should return unsubscribe function for hooks', () => {
|
|
243
|
-
const eventful = new TestEventful()
|
|
244
|
-
let hookCount = 0
|
|
245
|
-
|
|
246
|
-
const unsubscribe = eventful.hook(() => hookCount++)
|
|
247
|
-
|
|
248
|
-
eventful.emit('simple')
|
|
249
|
-
expect(hookCount).toBe(1)
|
|
250
|
-
|
|
251
|
-
unsubscribe()
|
|
252
|
-
eventful.emit('simple')
|
|
253
|
-
expect(hookCount).toBe(1) // Should not increment
|
|
254
|
-
})
|
|
255
|
-
|
|
256
|
-
it('should prevent duplicate hook registration', () => {
|
|
257
|
-
const eventful = new TestEventful()
|
|
258
|
-
let hookCount = 0
|
|
259
|
-
|
|
260
|
-
const hookCallback = () => hookCount++
|
|
261
|
-
|
|
262
|
-
eventful.hook(hookCallback)
|
|
263
|
-
eventful.hook(hookCallback) // Should not add duplicate
|
|
264
|
-
|
|
265
|
-
eventful.emit('simple')
|
|
266
|
-
expect(hookCount).toBe(1) // Should only be called once
|
|
267
|
-
})
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
describe('combined functionality', () => {
|
|
271
|
-
it('should call both specific listeners and global hooks', () => {
|
|
272
|
-
const eventful = new TestEventful()
|
|
273
|
-
let specificCount = 0
|
|
274
|
-
let hookCount = 0
|
|
275
|
-
|
|
276
|
-
eventful.on('simple', () => specificCount++)
|
|
277
|
-
eventful.hook(() => hookCount++)
|
|
278
|
-
|
|
279
|
-
eventful.emit('simple')
|
|
280
|
-
|
|
281
|
-
expect(specificCount).toBe(1)
|
|
282
|
-
expect(hookCount).toBe(1)
|
|
283
|
-
})
|
|
284
|
-
|
|
285
|
-
it('should handle complex event scenarios', () => {
|
|
286
|
-
const eventful = new TestEventful()
|
|
287
|
-
const events: string[] = []
|
|
288
|
-
|
|
289
|
-
// Register multiple listeners
|
|
290
|
-
eventful.on('userLogin', () => events.push('login1'))
|
|
291
|
-
eventful.on('userLogin', () => events.push('login2'))
|
|
292
|
-
eventful.on('dataUpdate', () => events.push('data1'))
|
|
293
|
-
|
|
294
|
-
// Register global hook
|
|
295
|
-
eventful.hook((event, ..._args) => {
|
|
296
|
-
events.push(`hook:${String(event)}`)
|
|
297
|
-
})
|
|
298
|
-
|
|
299
|
-
// Emit events
|
|
300
|
-
eventful.emit('userLogin', 'user123', new Date())
|
|
301
|
-
eventful.emit('dataUpdate', [1, 2, 3])
|
|
302
|
-
|
|
303
|
-
expect(events).toEqual(['login1', 'login2', 'hook:userLogin', 'data1', 'hook:dataUpdate'])
|
|
304
|
-
})
|
|
305
|
-
})
|
|
306
|
-
|
|
307
|
-
describe('edge cases', () => {
|
|
308
|
-
it('should handle emitting events with no listeners', () => {
|
|
309
|
-
const eventful = new TestEventful()
|
|
310
|
-
|
|
311
|
-
// Should not throw
|
|
312
|
-
expect(() => {
|
|
313
|
-
eventful.emit('userLogin', 'user123', new Date())
|
|
314
|
-
eventful.emit('simple')
|
|
315
|
-
}).not.toThrow()
|
|
316
|
-
})
|
|
317
|
-
|
|
318
|
-
it('should handle unsubscribing non-existent callbacks', () => {
|
|
319
|
-
const eventful = new TestEventful()
|
|
320
|
-
|
|
321
|
-
// Should not throw
|
|
322
|
-
expect(() => {
|
|
323
|
-
eventful.off('simple', () => {})
|
|
324
|
-
eventful.off('simple')
|
|
325
|
-
}).not.toThrow()
|
|
326
|
-
})
|
|
327
|
-
|
|
328
|
-
it('should handle unsubscribing from non-existent events', () => {
|
|
329
|
-
const eventful = new TestEventful()
|
|
330
|
-
|
|
331
|
-
// Should not throw
|
|
332
|
-
expect(() => {
|
|
333
|
-
eventful.off('nonExistentEvent' as any)
|
|
334
|
-
}).not.toThrow()
|
|
335
|
-
})
|
|
336
|
-
|
|
337
|
-
it('should handle multiple unsubscribes of the same callback', () => {
|
|
338
|
-
const eventful = new TestEventful()
|
|
339
|
-
let callCount = 0
|
|
340
|
-
|
|
341
|
-
const callback = () => callCount++
|
|
342
|
-
const unsubscribe = eventful.on('simple', callback)
|
|
343
|
-
|
|
344
|
-
eventful.emit('simple')
|
|
345
|
-
expect(callCount).toBe(1)
|
|
346
|
-
|
|
347
|
-
unsubscribe()
|
|
348
|
-
unsubscribe() // Should not throw
|
|
349
|
-
unsubscribe() // Should not throw
|
|
350
|
-
|
|
351
|
-
eventful.emit('simple')
|
|
352
|
-
expect(callCount).toBe(1) // Should not increment
|
|
353
|
-
})
|
|
354
|
-
})
|
|
355
|
-
|
|
356
|
-
describe('type safety', () => {
|
|
357
|
-
it('should enforce correct parameter types', () => {
|
|
358
|
-
const eventful = new TestEventful()
|
|
359
|
-
|
|
360
|
-
// These should compile without errors
|
|
361
|
-
eventful.on('userLogin', (userId: string, timestamp: Date) => {
|
|
362
|
-
expect(typeof userId).toBe('string')
|
|
363
|
-
expect(timestamp).toBeInstanceOf(Date)
|
|
364
|
-
})
|
|
365
|
-
|
|
366
|
-
eventful.on('dataUpdate', (data: any[]) => {
|
|
367
|
-
expect(Array.isArray(data)).toBe(true)
|
|
368
|
-
})
|
|
369
|
-
|
|
370
|
-
eventful.on('error', (error: Error) => {
|
|
371
|
-
expect(error).toBeInstanceOf(Error)
|
|
372
|
-
})
|
|
373
|
-
|
|
374
|
-
// Emit with correct types
|
|
375
|
-
eventful.emit('userLogin', 'user123', new Date())
|
|
376
|
-
eventful.emit('dataUpdate', [1, 2, 3])
|
|
377
|
-
eventful.emit('error', new Error('test'))
|
|
378
|
-
})
|
|
379
|
-
})
|
|
380
|
-
})
|
package/src/eventful.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
export class Eventful<Events extends Record<string, (...args: any[]) => void>> {
|
|
2
|
-
readonly #events = new Map<keyof Events, ((...args: any[]) => void)[]>()
|
|
3
|
-
readonly #hooks = [] as ((...args: any[]) => void)[]
|
|
4
|
-
|
|
5
|
-
public hook(
|
|
6
|
-
cb: <EventType extends keyof Events>(
|
|
7
|
-
event: EventType,
|
|
8
|
-
...args: Parameters<Events[EventType]>
|
|
9
|
-
) => void
|
|
10
|
-
): () => void {
|
|
11
|
-
if (!this.#hooks.includes(cb)) this.#hooks.push(cb)
|
|
12
|
-
return () => {
|
|
13
|
-
this.#hooks.splice(this.#hooks.indexOf(cb), 1)
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
public on(events: Partial<Events>): void
|
|
18
|
-
public on<EventType extends keyof Events>(event: EventType, cb: Events[EventType]): () => void
|
|
19
|
-
public on<EventType extends keyof Events>(
|
|
20
|
-
eventOrEvents: EventType | Partial<Events>,
|
|
21
|
-
cb?: Events[EventType]
|
|
22
|
-
): () => void {
|
|
23
|
-
if (typeof eventOrEvents === 'object') {
|
|
24
|
-
for (const e of Object.keys(eventOrEvents) as (keyof Events)[]) {
|
|
25
|
-
this.on(e, eventOrEvents[e]!)
|
|
26
|
-
}
|
|
27
|
-
} else if (cb !== undefined) {
|
|
28
|
-
let callbacks = this.#events.get(eventOrEvents)
|
|
29
|
-
if (!callbacks) {
|
|
30
|
-
callbacks = []
|
|
31
|
-
this.#events.set(eventOrEvents, callbacks)
|
|
32
|
-
}
|
|
33
|
-
callbacks.push(cb)
|
|
34
|
-
}
|
|
35
|
-
// @ts-expect-error Generic case leads to generic case
|
|
36
|
-
return () => this.off(eventOrEvents, cb)
|
|
37
|
-
}
|
|
38
|
-
public off(events: Partial<Events>): void
|
|
39
|
-
public off<EventType extends keyof Events>(event: EventType, cb?: Events[EventType]): void
|
|
40
|
-
public off<EventType extends keyof Events>(
|
|
41
|
-
eventOrEvents: EventType | Partial<Events>,
|
|
42
|
-
cb?: Events[EventType]
|
|
43
|
-
): void {
|
|
44
|
-
if (typeof eventOrEvents === 'object') {
|
|
45
|
-
for (const e of Object.keys(eventOrEvents) as (keyof Events)[]) {
|
|
46
|
-
this.off(e, eventOrEvents[e])
|
|
47
|
-
}
|
|
48
|
-
} else if (cb !== null && cb !== undefined) {
|
|
49
|
-
const callbacks = this.#events.get(eventOrEvents)
|
|
50
|
-
if (callbacks) {
|
|
51
|
-
this.#events.set(
|
|
52
|
-
eventOrEvents,
|
|
53
|
-
callbacks.filter((c) => c !== cb)
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
|
-
} else {
|
|
57
|
-
// Remove all listeners for this event
|
|
58
|
-
this.#events.delete(eventOrEvents)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
public emit<EventType extends keyof Events>(
|
|
62
|
-
event: EventType,
|
|
63
|
-
...args: Parameters<Events[EventType]>
|
|
64
|
-
) {
|
|
65
|
-
const callbacks = this.#events.get(event)
|
|
66
|
-
if (callbacks) for (const cb of callbacks) cb.apply(this, args)
|
|
67
|
-
for (const cb of this.#hooks) cb.call(this, event, ...args)
|
|
68
|
-
}
|
|
69
|
-
}
|