emittery 0.4.1 → 0.7.0

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/index.d.ts ADDED
@@ -0,0 +1,414 @@
1
+ /**
2
+ Emittery accepts strings and symbols as event names.
3
+
4
+ Symbol event names can be used to avoid name collisions when your classes are extended, especially for internal events.
5
+ */
6
+ type EventName = string | symbol;
7
+
8
+ /**
9
+ Emittery also accepts an array of strings and symbols as event names.
10
+ */
11
+ type EventNames = EventName | readonly EventName[];
12
+
13
+ declare class Emittery {
14
+ /**
15
+ In TypeScript, it returns a decorator which mixins `Emittery` as property `emitteryPropertyName` and `methodNames`, or all `Emittery` methods if `methodNames` is not defined, into the target class.
16
+
17
+ @example
18
+ ```
19
+ import Emittery = require('emittery');
20
+
21
+ @Emittery.mixin('emittery')
22
+ class MyClass {}
23
+
24
+ const instance = new MyClass();
25
+
26
+ instance.emit('event');
27
+ ```
28
+ */
29
+ static mixin(emitteryPropertyName: string, methodNames?: readonly string[]): Function;
30
+
31
+ /**
32
+ Fires when an event listener was added.
33
+
34
+ An object with `listener` and `eventName` (if `on` or `off` was used) is provided as event data.
35
+
36
+ @example
37
+ ```
38
+ import Emittery = require('emittery');
39
+
40
+ const emitter = new Emittery();
41
+
42
+ emitter.on(Emittery.listenerAdded, ({listener, eventName}) => {
43
+ console.log(listener);
44
+ //=> data => {}
45
+
46
+ console.log(eventName);
47
+ //=> '🦄'
48
+ });
49
+
50
+ emitter.on('🦄', data => {
51
+ // Handle data
52
+ });
53
+ ```
54
+ */
55
+ static readonly listenerAdded: unique symbol;
56
+
57
+ /**
58
+ Fires when an event listener was removed.
59
+
60
+ An object with `listener` and `eventName` (if `on` or `off` was used) is provided as event data.
61
+
62
+ @example
63
+ ```
64
+ import Emittery = require('emittery');
65
+
66
+ const emitter = new Emittery();
67
+
68
+ const off = emitter.on('🦄', data => {
69
+ // Handle data
70
+ });
71
+
72
+ emitter.on(Emittery.listenerRemoved, ({listener, eventName}) => {
73
+ console.log(listener);
74
+ //=> data => {}
75
+
76
+ console.log(eventName);
77
+ //=> '🦄'
78
+ });
79
+
80
+ off();
81
+ ```
82
+ */
83
+ static readonly listenerRemoved: unique symbol;
84
+
85
+ /**
86
+ Subscribe to one or more events.
87
+
88
+ Using the same listener multiple times for the same event will result in only one method call per emitted event.
89
+
90
+ @returns An unsubscribe method.
91
+
92
+ @example
93
+ ```
94
+ import Emittery = require('emittery');
95
+
96
+ const emitter = new Emittery();
97
+
98
+ emitter.on('🦄', data => {
99
+ console.log(data);
100
+ });
101
+ emitter.on(['🦄', '🐶'], data => {
102
+ console.log(data);
103
+ });
104
+
105
+ emitter.emit('🦄', '🌈'); // log => '🌈' x2
106
+ emitter.emit('🐶', '🍖'); // log => '🍖'
107
+ ```
108
+ */
109
+ on(eventName: typeof Emittery.listenerAdded | typeof Emittery.listenerRemoved, listener: (eventData: Emittery.ListenerChangedData) => void): Emittery.UnsubscribeFn
110
+ on(eventName: EventNames, listener: (eventData?: unknown) => void): Emittery.UnsubscribeFn;
111
+
112
+ /**
113
+ Get an async iterator which buffers data each time an event is emitted.
114
+
115
+ Call `return()` on the iterator to remove the subscription.
116
+
117
+ @example
118
+ ```
119
+ import Emittery = require('emittery');
120
+
121
+ const emitter = new Emittery();
122
+ const iterator = emitter.events('🦄');
123
+
124
+ emitter.emit('🦄', '🌈1'); // Buffered
125
+ emitter.emit('🦄', '🌈2'); // Buffered
126
+
127
+ iterator
128
+ .next()
129
+ .then(({value, done}) => {
130
+ // done === false
131
+ // value === '🌈1'
132
+ return iterator.next();
133
+ })
134
+ .then(({value, done}) => {
135
+ // done === false
136
+ // value === '🌈2'
137
+ // Revoke subscription
138
+ return iterator.return();
139
+ })
140
+ .then(({done}) => {
141
+ // done === true
142
+ });
143
+ ```
144
+
145
+ In practice you would usually consume the events using the [for await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of) statement. In that case, to revoke the subscription simply break the loop.
146
+
147
+ @example
148
+ ```
149
+ import Emittery = require('emittery');
150
+
151
+ const emitter = new Emittery();
152
+ const iterator = emitter.events('🦄');
153
+
154
+ emitter.emit('🦄', '🌈1'); // Buffered
155
+ emitter.emit('🦄', '🌈2'); // Buffered
156
+
157
+ // In an async context.
158
+ for await (const data of iterator) {
159
+ if (data === '🌈2') {
160
+ break; // Revoke the subscription when we see the value `🌈2`.
161
+ }
162
+ }
163
+ ```
164
+
165
+ It accepts multiple event names.
166
+
167
+ @example
168
+ ```
169
+ import Emittery = require('emittery');
170
+
171
+ const emitter = new Emittery();
172
+ const iterator = emitter.events(['🦄', '🦊']);
173
+
174
+ emitter.emit('🦄', '🌈1'); // Buffered
175
+ emitter.emit('🦊', '🌈2'); // Buffered
176
+
177
+ iterator
178
+ .next()
179
+ .then(({value, done}) => {
180
+ // done === false
181
+ // value === '🌈1'
182
+ return iterator.next();
183
+ })
184
+ .then(({value, done}) => {
185
+ // done === false
186
+ // value === '🌈2'
187
+ // Revoke subscription
188
+ return iterator.return();
189
+ })
190
+ .then(({done}) => {
191
+ // done === true
192
+ });
193
+ ```
194
+ */
195
+ events(eventName: EventNames): AsyncIterableIterator<unknown>
196
+
197
+ /**
198
+ Remove one or more event subscriptions.
199
+
200
+ @example
201
+ ```
202
+ import Emittery = require('emittery');
203
+
204
+ const emitter = new Emittery();
205
+
206
+ const listener = data => console.log(data);
207
+ (async () => {
208
+ emitter.on(['🦄', '🐶', '🦊'], listener);
209
+ await emitter.emit('🦄', 'a');
210
+ await emitter.emit('🐶', 'b');
211
+ await emitter.emit('🦊', 'c');
212
+ emitter.off('🦄', listener);
213
+ emitter.off(['🐶', '🦊'], listener);
214
+ await emitter.emit('🦄', 'a'); // nothing happens
215
+ await emitter.emit('🐶', 'b'); // nothing happens
216
+ await emitter.emit('🦊', 'c'); // nothing happens
217
+ })();
218
+ ```
219
+ */
220
+ off(eventName: EventNames, listener: (eventData?: unknown) => void): void;
221
+
222
+ /**
223
+ Subscribe to one or more events only once. It will be unsubscribed after the first
224
+ event.
225
+
226
+ @returns The event data when `eventName` is emitted.
227
+
228
+ @example
229
+ ```
230
+ import Emittery = require('emittery');
231
+
232
+ const emitter = new Emittery();
233
+
234
+ emitter.once('🦄').then(data => {
235
+ console.log(data);
236
+ //=> '🌈'
237
+ });
238
+ emitter.once(['🦄', '🐶']).then(data => {
239
+ console.log(data);
240
+ });
241
+
242
+ emitter.emit('🦄', '🌈'); // Logs `🌈` twice
243
+ emitter.emit('🐶', '🍖'); // Nothing happens
244
+ ```
245
+ */
246
+ once(eventName: typeof Emittery.listenerAdded | typeof Emittery.listenerRemoved): Promise<Emittery.ListenerChangedData>
247
+ once(eventName: EventNames): Promise<unknown>;
248
+
249
+ /**
250
+ Trigger an event asynchronously, optionally with some data. Listeners are called in the order they were added, but executed concurrently.
251
+
252
+ @returns A promise that resolves when all the event listeners are done. *Done* meaning executed if synchronous or resolved when an async/promise-returning function. You usually wouldn't want to wait for this, but you could for example catch possible errors. If any of the listeners throw/reject, the returned promise will be rejected with the error, but the other listeners will not be affected.
253
+ */
254
+ emit(eventName: EventName, eventData?: unknown): Promise<void>;
255
+
256
+ /**
257
+ Same as `emit()`, but it waits for each listener to resolve before triggering the next one. This can be useful if your events depend on each other. Although ideally they should not. Prefer `emit()` whenever possible.
258
+
259
+ If any of the listeners throw/reject, the returned promise will be rejected with the error and the remaining listeners will *not* be called.
260
+
261
+ @returns A promise that resolves when all the event listeners are done.
262
+ */
263
+ emitSerial(eventName: EventName, eventData?: unknown): Promise<void>;
264
+
265
+ /**
266
+ Subscribe to be notified about any event.
267
+
268
+ @returns A method to unsubscribe.
269
+ */
270
+ onAny(listener: (eventName: EventName, eventData?: unknown) => unknown): Emittery.UnsubscribeFn;
271
+
272
+ /**
273
+ Get an async iterator which buffers a tuple of an event name and data each time an event is emitted.
274
+
275
+ Call `return()` on the iterator to remove the subscription.
276
+
277
+ In the same way as for `events`, you can subscribe by using the `for await` statement.
278
+
279
+ @example
280
+ ```
281
+ import Emittery = require('emittery');
282
+
283
+ const emitter = new Emittery();
284
+ const iterator = emitter.anyEvent();
285
+
286
+ emitter.emit('🦄', '🌈1'); // Buffered
287
+ emitter.emit('🌟', '🌈2'); // Buffered
288
+
289
+ iterator.next()
290
+ .then(({value, done}) => {
291
+ // done is false
292
+ // value is ['🦄', '🌈1']
293
+ return iterator.next();
294
+ })
295
+ .then(({value, done}) => {
296
+ // done is false
297
+ // value is ['🌟', '🌈2']
298
+ // revoke subscription
299
+ return iterator.return();
300
+ })
301
+ .then(({done}) => {
302
+ // done is true
303
+ });
304
+ ```
305
+ */
306
+ anyEvent(): AsyncIterableIterator<unknown>
307
+
308
+ /**
309
+ Remove an `onAny` subscription.
310
+ */
311
+ offAny(listener: (eventName: EventName, eventData?: unknown) => void): void;
312
+
313
+ /**
314
+ Clear all event listeners on the instance.
315
+
316
+ If `eventName` is given, only the listeners for that event are cleared.
317
+ */
318
+ clearListeners(eventName?: EventNames): void;
319
+
320
+ /**
321
+ The number of listeners for the `eventName` or all events if not specified.
322
+ */
323
+ listenerCount(eventName?: EventNames): number;
324
+
325
+ /**
326
+ Bind the given `methodNames`, or all `Emittery` methods if `methodNames` is not defined, into the `target` object.
327
+
328
+ @example
329
+ ```
330
+ import Emittery = require('emittery');
331
+
332
+ const object = {};
333
+
334
+ new Emittery().bindMethods(object);
335
+
336
+ object.emit('event');
337
+ ```
338
+ */
339
+ bindMethods(target: object, methodNames?: readonly string[]): void;
340
+ }
341
+
342
+ declare namespace Emittery {
343
+ /**
344
+ Removes an event subscription.
345
+ */
346
+ type UnsubscribeFn = () => void;
347
+ type EventNameFromDataMap<EventDataMap> = Extract<keyof EventDataMap, EventName>;
348
+
349
+ /**
350
+ Maps event names to their emitted data type.
351
+ */
352
+ interface Events {
353
+ // Blocked by https://github.com/microsoft/TypeScript/issues/1863, should be
354
+ // `[eventName: EventName]: unknown;`
355
+ }
356
+
357
+ /**
358
+ The data provided as `eventData` when listening for `Emittery.listenerAdded` or `Emittery.listenerRemoved`.
359
+ */
360
+ interface ListenerChangedData {
361
+ /**
362
+ The listener that was added or removed.
363
+ */
364
+ listener: (eventData?: unknown) => void;
365
+
366
+ /**
367
+ The name of the event that was added or removed if `.on()` or `.off()` was used, or `undefined` if `.onAny()` or `.offAny()` was used.
368
+ */
369
+ eventName?: EventName;
370
+ }
371
+
372
+ /**
373
+ Async event emitter.
374
+
375
+ You must list supported events and the data type they emit, if any.
376
+
377
+ @example
378
+ ```
379
+ import Emittery = require('emittery');
380
+
381
+ const emitter = new Emittery.Typed<{value: string}, 'open' | 'close'>();
382
+
383
+ emitter.emit('open');
384
+ emitter.emit('value', 'foo\n');
385
+ emitter.emit('value', 1); // TS compilation error
386
+ emitter.emit('end'); // TS compilation error
387
+ ```
388
+ */
389
+ class Typed<EventDataMap extends Events, EmptyEvents extends EventName = never> extends Emittery {
390
+ on<Name extends EventNameFromDataMap<EventDataMap>>(eventName: Name, listener: (eventData: EventDataMap[Name]) => void): Emittery.UnsubscribeFn;
391
+ on<Name extends EmptyEvents>(eventName: Name, listener: () => void): Emittery.UnsubscribeFn;
392
+
393
+ events<Name extends EventNameFromDataMap<EventDataMap>>(eventName: Name): AsyncIterableIterator<EventDataMap[Name]>;
394
+
395
+ once<Name extends EventNameFromDataMap<EventDataMap>>(eventName: Name): Promise<EventDataMap[Name]>;
396
+ once<Name extends EmptyEvents>(eventName: Name): Promise<void>;
397
+
398
+ off<Name extends EventNameFromDataMap<EventDataMap>>(eventName: Name, listener: (eventData: EventDataMap[Name]) => void): void;
399
+ off<Name extends EmptyEvents>(eventName: Name, listener: () => void): void;
400
+
401
+ onAny(listener: (eventName: EventNameFromDataMap<EventDataMap> | EmptyEvents, eventData?: EventDataMap[EventNameFromDataMap<EventDataMap>]) => void): Emittery.UnsubscribeFn;
402
+ anyEvent(): AsyncIterableIterator<[EventNameFromDataMap<EventDataMap>, EventDataMap[EventNameFromDataMap<EventDataMap>]]>;
403
+
404
+ offAny(listener: (eventName: EventNameFromDataMap<EventDataMap> | EmptyEvents, eventData?: EventDataMap[EventNameFromDataMap<EventDataMap>]) => void): void;
405
+
406
+ emit<Name extends EventNameFromDataMap<EventDataMap>>(eventName: Name, eventData: EventDataMap[Name]): Promise<void>;
407
+ emit<Name extends EmptyEvents>(eventName: Name): Promise<void>;
408
+
409
+ emitSerial<Name extends EventNameFromDataMap<EventDataMap>>(eventName: Name, eventData: EventDataMap[Name]): Promise<void>;
410
+ emitSerial<Name extends EmptyEvents>(eventName: Name): Promise<void>;
411
+ }
412
+ }
413
+
414
+ export = Emittery;