import {EventEmitter} from 'events'; import type IDisposable from './IDisposable'; import Disposable from './Disposable'; type EventListener = (...args: unknown[]) => void | Promise; export class Events { private readonly _events: EventEmitter; constructor() { this._events = new EventEmitter(); } public on(event: string, listener: EventListener): IDisposable { const wrappedListener = async (...eventArguments: unknown[]) => { try { await listener.apply(this, eventArguments); } catch (e) { console.error('Failed to process event [%s] with listener [%s]', event, listener, e); } }; this._events.on(event, wrappedListener); return new Disposable(() => { this._events.removeListener(event, wrappedListener); }); } public once(event: string, listener: EventListener): IDisposable { const wrappedListener = async (...eventArguments: unknown[]) => { try { await listener.apply(this, eventArguments); } catch (e) { console.error('Failed to process event [%s] with listener [%s]', event, listener, e); } }; this._events.once(event, wrappedListener); return new Disposable(() => { this._events.removeListener(event, wrappedListener); }); } public emit(event: string, ...eventArguments: unknown[]): boolean { return this._events.emit(event, ...eventArguments); } public listenerCount(event: string): number { return this._events.listenerCount(event); } }