signal-controller
Version:
A lightweight event emitter with separation of concerns between emitter and listener inspired by the AbortController interface.
70 lines (69 loc) • 3.54 kB
TypeScript
declare const ONCE_SYMBOL: unique symbol;
declare const EMIT: unique symbol;
declare const CLEAR_SIGNAL: unique symbol;
declare const CLEAR_ALL_SIGNALS: unique symbol;
declare const COUNT_LISTENERS: unique symbol;
interface ListenerFunction {
(...args: any[]): unknown;
[ONCE_SYMBOL]?: boolean;
}
export interface BaseEventEmitterAPI {
[signalName: string | symbol]: ListenerFunction;
}
export interface SignalListenerOptions {
/** If true, this listener will only be called once. */
once?: boolean;
/** If provided, the listener will be removed when the abort signal is triggered. */
signal?: AbortSignal;
}
export type { SignalEmitter };
/** This class is used to listen to signals. */
declare class SignalEmitter<T extends BaseEventEmitterAPI> {
#private;
constructor({ immediate }?: {
immediate?: boolean | undefined;
});
[EMIT]<K extends keyof T>(signalName: K, ...args: Parameters<T[K]>): [boolean, unknown[]];
/** Start listening to a signal. The provided callback is called whenever the specified signal is emitted. */
on<K extends keyof T>(signalName: K, listener: T[K]): void;
on<K extends keyof T>(signalName: K, options: SignalListenerOptions, listener: T[K]): void;
/** Creates a readable stream that produces data each time the specified signal is emitted. */
createReadableStream<K extends keyof T>(signalName: K): ReadableStream<Parameters<T[K]>>;
/** Creates a Proimse that is resolved the next time the specified signal is emitted. The promise is rejected only
* if an abort signal is provided and it is aborted before the waited signal is emitted. */
once<K extends keyof T>(signalName: K, { signal }?: {
signal?: AbortSignal | undefined;
}): Promise<Parameters<T[K]>>;
/** Removes a listener. */
off(signalName: keyof T, listener: ListenerFunction): void;
[CLEAR_SIGNAL](signalName: keyof T): void;
[CLEAR_ALL_SIGNALS](): void;
[COUNT_LISTENERS](signalName: keyof T): number;
}
interface SignalControllerOptions {
/** If this option is true, the signal emitter will immediately call newly subscribed listeners with the last
* arguments emitted (if any). */
immediate?: boolean;
/** Callback called when an signal listener throws. */
onError?: (error: unknown, signalName: string, args: unknown[]) => void;
}
/** This class is used to emit signals. */
export declare class SignalController<T extends BaseEventEmitterAPI> {
private readonly options;
constructor(options?: SignalControllerOptions);
readonly emitter: SignalEmitter<T>;
onError: SignalControllerOptions['onError'];
/** Emits a signal with some payload. Returns true if the signal was handled by at least one listener. */
emit<K extends keyof T>(signalName: K, ...args: Parameters<T[K]>): boolean;
/** Removes all listeners for a specific signal. */
off(signalName: keyof T): void;
/** Removes all listeners for all signals. */
clear(): void;
/** Removes all signal listeners, stops accepting new signal listeners, and future calls to {@link emit} will only
* produce a warning message, but otherwise be ignored. */
destroy(): void;
/** Checks whether there are listeners attached for the specified signal. */
testSignal(signalName: keyof T): boolean;
/** Creates a writable stream that produces signals of the specified type for each chunk of data it receives. */
createWritableStream<K extends keyof T>(signalName: K): WritableStream<Parameters<T[K]>>;
}