source: frontend/node_modules/emittery/index.d.ts

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 12.0 KB
Line 
1/**
2Emittery accepts strings and symbols as event names.
3
4Symbol event names can be used to avoid name collisions when your classes are extended, especially for internal events.
5*/
6type EventName = string | symbol;
7
8// Helper type for turning the passed `EventData` type map into a list of string keys that don't require data alongside the event name when emitting. Uses the same trick that `Omit` does internally to filter keys by building a map of keys to keys we want to keep, and then accessing all the keys to return just the list of keys we want to keep.
9type DatalessEventNames<EventData> = {
10 [Key in keyof EventData]: EventData[Key] extends undefined ? Key : never;
11}[keyof EventData];
12
13declare const listenerAdded: unique symbol;
14declare const listenerRemoved: unique symbol;
15type OmnipresentEventData = {[listenerAdded]: Emittery.ListenerChangedData; [listenerRemoved]: Emittery.ListenerChangedData};
16
17/**
18Emittery is a strictly typed, fully async EventEmitter implementation. Event listeners can be registered with `on` or `once`, and events can be emitted with `emit`.
19
20`Emittery` has a generic `EventData` type that can be provided by users to strongly type the list of events and the data passed to the listeners for those events. Pass an interface of {[eventName]: undefined | <eventArg>}, with all the event names as the keys and the values as the type of the argument passed to listeners if there is one, or `undefined` if there isn't.
21
22@example
23```
24import Emittery = require('emittery');
25
26const emitter = new Emittery<
27 // Pass `{[eventName: <string | symbol>]: undefined | <eventArg>}` as the first type argument for events that pass data to their listeners.
28 // A value of `undefined` in this map means the event listeners should expect no data, and a type other than `undefined` means the listeners will receive one argument of that type.
29 {
30 open: string,
31 close: undefined
32 }
33>();
34
35// Typechecks just fine because the data type for the `open` event is `string`.
36emitter.emit('open', 'foo\n');
37
38// Typechecks just fine because `close` is present but points to undefined in the event data type map.
39emitter.emit('close');
40
41// TS compilation error because `1` isn't assignable to `string`.
42emitter.emit('open', 1);
43
44// TS compilation error because `other` isn't defined in the event data type map.
45emitter.emit('other');
46```
47*/
48declare class Emittery<
49 EventData = Record<string, any>, // When https://github.com/microsoft/TypeScript/issues/1863 ships, we can switch this to have an index signature including Symbols. If you want to use symbol keys right now, you need to pass an interface with those symbol keys explicitly listed.
50 AllEventData = EventData & OmnipresentEventData,
51 DatalessEvents = DatalessEventNames<EventData>
52> {
53 /**
54 Fires when an event listener was added.
55
56 An object with `listener` and `eventName` (if `on` or `off` was used) is provided as event data.
57
58 @example
59 ```
60 import Emittery = require('emittery');
61
62 const emitter = new Emittery();
63
64 emitter.on(Emittery.listenerAdded, ({listener, eventName}) => {
65 console.log(listener);
66 //=> data => {}
67
68 console.log(eventName);
69 //=> '🦄'
70 });
71
72 emitter.on('🦄', data => {
73 // Handle data
74 });
75 ```
76 */
77 static readonly listenerAdded: typeof listenerAdded;
78
79 /**
80 Fires when an event listener was removed.
81
82 An object with `listener` and `eventName` (if `on` or `off` was used) is provided as event data.
83
84 @example
85 ```
86 import Emittery = require('emittery');
87
88 const emitter = new Emittery();
89
90 const off = emitter.on('🦄', data => {
91 // Handle data
92 });
93
94 emitter.on(Emittery.listenerRemoved, ({listener, eventName}) => {
95 console.log(listener);
96 //=> data => {}
97
98 console.log(eventName);
99 //=> '🦄'
100 });
101
102 off();
103 ```
104 */
105 static readonly listenerRemoved: typeof listenerRemoved;
106
107 /**
108 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.
109
110 @example
111 ```
112 import Emittery = require('emittery');
113
114 @Emittery.mixin('emittery')
115 class MyClass {}
116
117 const instance = new MyClass();
118
119 instance.emit('event');
120 ```
121 */
122 static mixin(
123 emitteryPropertyName: string | symbol,
124 methodNames?: readonly string[]
125 ): <T extends { new (): any }>(klass: T) => T; // eslint-disable-line @typescript-eslint/prefer-function-type
126
127 /**
128 Subscribe to one or more events.
129
130 Using the same listener multiple times for the same event will result in only one method call per emitted event.
131
132 @returns An unsubscribe method.
133
134 @example
135 ```
136 import Emittery = require('emittery');
137
138 const emitter = new Emittery();
139
140 emitter.on('🦄', data => {
141 console.log(data);
142 });
143 emitter.on(['🦄', '🐶'], data => {
144 console.log(data);
145 });
146
147 emitter.emit('🦄', '🌈'); // log => '🌈' x2
148 emitter.emit('🐶', '🍖'); // log => '🍖'
149 ```
150 */
151 on<Name extends keyof AllEventData>(
152 eventName: Name,
153 listener: (eventData: AllEventData[Name]) => void | Promise<void>
154 ): Emittery.UnsubscribeFn;
155
156 /**
157 Get an async iterator which buffers data each time an event is emitted.
158
159 Call `return()` on the iterator to remove the subscription.
160
161 @example
162 ```
163 import Emittery = require('emittery');
164
165 const emitter = new Emittery();
166 const iterator = emitter.events('🦄');
167
168 emitter.emit('🦄', '🌈1'); // Buffered
169 emitter.emit('🦄', '🌈2'); // Buffered
170
171 iterator
172 .next()
173 .then(({value, done}) => {
174 // done === false
175 // value === '🌈1'
176 return iterator.next();
177 })
178 .then(({value, done}) => {
179 // done === false
180 // value === '🌈2'
181 // Revoke subscription
182 return iterator.return();
183 })
184 .then(({done}) => {
185 // done === true
186 });
187 ```
188
189 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.
190
191 @example
192 ```
193 import Emittery = require('emittery');
194
195 const emitter = new Emittery();
196 const iterator = emitter.events('🦄');
197
198 emitter.emit('🦄', '🌈1'); // Buffered
199 emitter.emit('🦄', '🌈2'); // Buffered
200
201 // In an async context.
202 for await (const data of iterator) {
203 if (data === '🌈2') {
204 break; // Revoke the subscription when we see the value `🌈2`.
205 }
206 }
207 ```
208
209 It accepts multiple event names.
210
211 @example
212 ```
213 import Emittery = require('emittery');
214
215 const emitter = new Emittery();
216 const iterator = emitter.events(['🦄', '🦊']);
217
218 emitter.emit('🦄', '🌈1'); // Buffered
219 emitter.emit('🦊', '🌈2'); // Buffered
220
221 iterator
222 .next()
223 .then(({value, done}) => {
224 // done === false
225 // value === '🌈1'
226 return iterator.next();
227 })
228 .then(({value, done}) => {
229 // done === false
230 // value === '🌈2'
231 // Revoke subscription
232 return iterator.return();
233 })
234 .then(({done}) => {
235 // done === true
236 });
237 ```
238 */
239 events<Name extends keyof EventData>(
240 eventName: Name | Name[]
241 ): AsyncIterableIterator<EventData[Name]>;
242
243 /**
244 Remove one or more event subscriptions.
245
246 @example
247 ```
248 import Emittery = require('emittery');
249
250 const emitter = new Emittery();
251
252 const listener = data => console.log(data);
253 (async () => {
254 emitter.on(['🦄', '🐶', '🦊'], listener);
255 await emitter.emit('🦄', 'a');
256 await emitter.emit('🐶', 'b');
257 await emitter.emit('🦊', 'c');
258 emitter.off('🦄', listener);
259 emitter.off(['🐶', '🦊'], listener);
260 await emitter.emit('🦄', 'a'); // nothing happens
261 await emitter.emit('🐶', 'b'); // nothing happens
262 await emitter.emit('🦊', 'c'); // nothing happens
263 })();
264 ```
265 */
266 off<Name extends keyof AllEventData>(
267 eventName: Name,
268 listener: (eventData: AllEventData[Name]) => void | Promise<void>
269 ): void;
270
271 /**
272 Subscribe to one or more events only once. It will be unsubscribed after the first
273 event.
274
275 @returns The event data when `eventName` is emitted.
276
277 @example
278 ```
279 import Emittery = require('emittery');
280
281 const emitter = new Emittery();
282
283 emitter.once('🦄').then(data => {
284 console.log(data);
285 //=> '🌈'
286 });
287 emitter.once(['🦄', '🐶']).then(data => {
288 console.log(data);
289 });
290
291 emitter.emit('🦄', '🌈'); // Logs `🌈` twice
292 emitter.emit('🐶', '🍖'); // Nothing happens
293 ```
294 */
295 once<Name extends keyof AllEventData>(eventName: Name): Promise<AllEventData[Name]>;
296
297 /**
298 Trigger an event asynchronously, optionally with some data. Listeners are called in the order they were added, but executed concurrently.
299
300 @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.
301 */
302 emit<Name extends DatalessEvents>(eventName: Name): Promise<void>;
303 emit<Name extends keyof EventData>(
304 eventName: Name,
305 eventData: EventData[Name]
306 ): Promise<void>;
307
308 /**
309 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.
310
311 If any of the listeners throw/reject, the returned promise will be rejected with the error and the remaining listeners will *not* be called.
312
313 @returns A promise that resolves when all the event listeners are done.
314 */
315 emitSerial<Name extends DatalessEvents>(eventName: Name): Promise<void>;
316 emitSerial<Name extends keyof EventData>(
317 eventName: Name,
318 eventData: EventData[Name]
319 ): Promise<void>;
320
321 /**
322 Subscribe to be notified about any event.
323
324 @returns A method to unsubscribe.
325 */
326 onAny(
327 listener: (
328 eventName: keyof EventData,
329 eventData: EventData[keyof EventData]
330 ) => void | Promise<void>
331 ): Emittery.UnsubscribeFn;
332
333 /**
334 Get an async iterator which buffers a tuple of an event name and data each time an event is emitted.
335
336 Call `return()` on the iterator to remove the subscription.
337
338 In the same way as for `events`, you can subscribe by using the `for await` statement.
339
340 @example
341 ```
342 import Emittery = require('emittery');
343
344 const emitter = new Emittery();
345 const iterator = emitter.anyEvent();
346
347 emitter.emit('🦄', '🌈1'); // Buffered
348 emitter.emit('🌟', '🌈2'); // Buffered
349
350 iterator.next()
351 .then(({value, done}) => {
352 // done is false
353 // value is ['🦄', '🌈1']
354 return iterator.next();
355 })
356 .then(({value, done}) => {
357 // done is false
358 // value is ['🌟', '🌈2']
359 // revoke subscription
360 return iterator.return();
361 })
362 .then(({done}) => {
363 // done is true
364 });
365 ```
366 */
367 anyEvent(): AsyncIterableIterator<
368 [keyof EventData, EventData[keyof EventData]]
369 >;
370
371 /**
372 Remove an `onAny` subscription.
373 */
374 offAny(
375 listener: (
376 eventName: keyof EventData,
377 eventData: EventData[keyof EventData]
378 ) => void | Promise<void>
379 ): void;
380
381 /**
382 Clear all event listeners on the instance.
383
384 If `eventName` is given, only the listeners for that event are cleared.
385 */
386 clearListeners(eventName?: keyof EventData): void;
387
388 /**
389 The number of listeners for the `eventName` or all events if not specified.
390 */
391 listenerCount(eventName?: keyof EventData): number;
392
393 /**
394 Bind the given `methodNames`, or all `Emittery` methods if `methodNames` is not defined, into the `target` object.
395
396 @example
397 ```
398 import Emittery = require('emittery');
399
400 const object = {};
401
402 new Emittery().bindMethods(object);
403
404 object.emit('event');
405 ```
406 */
407 bindMethods(target: Record<string, unknown>, methodNames?: readonly string[]): void;
408}
409
410declare namespace Emittery {
411 /**
412 Removes an event subscription.
413 */
414 type UnsubscribeFn = () => void;
415
416 /**
417 The data provided as `eventData` when listening for `Emittery.listenerAdded` or `Emittery.listenerRemoved`.
418 */
419 interface ListenerChangedData {
420 /**
421 The listener that was added or removed.
422 */
423 listener: (eventData?: unknown) => void | Promise<void>;
424
425 /**
426 The name of the event that was added or removed if `.on()` or `.off()` was used, or `undefined` if `.onAny()` or `.offAny()` was used.
427 */
428 eventName?: EventName;
429 }
430}
431
432export = Emittery;
Note: See TracBrowser for help on using the repository browser.