@sv443-network/coreutils
Version:
Cross-platform, general-purpose, JavaScript core library for Node, Deno and the browser. Intended to be used in conjunction with `@sv443-network/userutils` and `@sv443-network/djsutils`, but can be used independently as well.
104 lines (103 loc) • 6.21 kB
TypeScript
/**
* @module NanoEmitter
* This module contains the NanoEmitter class, which is a tiny event emitter powered by [nanoevents](https://www.npmjs.com/package/nanoevents) - [see the documentation for more info](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#nanoemitter)
*/
import { type DefaultEvents, type Emitter, type EventsMap, type Unsubscribe } from "nanoevents";
import type { Prettify } from "./types.js";
export interface NanoEmitterOptions {
/** If set to true, allows emitting events through the public method emit() */
publicEmit: boolean;
}
type NanoEmitterOnMultiTriggerOptions<TEvtMap extends EventsMap, TKey extends keyof TEvtMap = keyof TEvtMap> = {
/** Calls the callback when one of the given events is emitted */
oneOf?: TKey[];
/** Calls the callback when all of the given events are emitted */
allOf?: TKey[];
};
/** Options for the {@linkcode NanoEmitter.onMulti()} method */
export type NanoEmitterOnMultiOptions<TEvtMap extends EventsMap, TKey extends keyof TEvtMap = keyof TEvtMap> = Prettify<{
/** If true, the callback will be called only once for the first event (or set of events) that match the criteria */
once?: boolean;
/** If provided, can be used to abort the subscription if the signal is aborted */
signal?: AbortSignal;
/** The callback to call when the event with the given name is emitted */
callback: (event: TKey, ...args: Parameters<TEvtMap[TKey]>) => void;
} & NanoEmitterOnMultiTriggerOptions<TEvtMap, TKey> & (Pick<Required<NanoEmitterOnMultiTriggerOptions<TEvtMap, TKey>>, "oneOf"> | Pick<Required<NanoEmitterOnMultiTriggerOptions<TEvtMap, TKey>>, "allOf">)>;
/**
* Class that can be extended or instantiated by itself to create a lightweight event emitter with helper methods and a strongly typed event map.
* If extended from, you can use `this.events.emit()` to emit events, even if the `emit()` method doesn't work because `publicEmit` is not set to true in the constructor.
*/
export declare class NanoEmitter<TEvtMap extends EventsMap = DefaultEvents> {
protected readonly events: Emitter<TEvtMap>;
protected eventUnsubscribes: Unsubscribe[];
protected emitterOptions: NanoEmitterOptions;
/** Creates a new instance of NanoEmitter - a lightweight event emitter with helper methods and a strongly typed event map */
constructor(options?: Partial<NanoEmitterOptions>);
/**
* Subscribes to an event and calls the callback when it's emitted.
* @param event The event to subscribe to. Use `as "_"` in case your event names aren't thoroughly typed (like when using a template literal, e.g. \`event-${val}\` as "_")
* @returns Returns a function that can be called to unsubscribe the event listener
* @example ```ts
* const emitter = new NanoEmitter<{
* foo: (bar: string) => void;
* }>({
* publicEmit: true,
* });
*
* let i = 0;
* const unsub = emitter.on("foo", (bar) => {
* // unsubscribe after 10 events:
* if(++i === 10) unsub();
* console.log(bar);
* });
*
* emitter.emit("foo", "bar");
* ```
*/
on<TKey extends keyof TEvtMap>(event: TKey | "_", cb: TEvtMap[TKey]): () => void;
/**
* Subscribes to an event and calls the callback or resolves the Promise only once when it's emitted.
* @param event The event to subscribe to. Use `as "_"` in case your event names aren't thoroughly typed (like when using a template literal, e.g. \`event-${val}\` as "_")
* @param cb The callback to call when the event is emitted - if provided or not, the returned Promise will resolve with the event arguments
* @returns Returns a Promise that resolves with the event arguments when the event is emitted
* @example ```ts
* const emitter = new NanoEmitter<{
* foo: (bar: string) => void;
* }>();
*
* // Promise syntax:
* const [bar] = await emitter.once("foo");
* console.log(bar);
*
* // Callback syntax:
* emitter.once("foo", (bar) => console.log(bar));
* ```
*/
once<TKey extends keyof TEvtMap>(event: TKey | "_", cb?: TEvtMap[TKey]): Promise<Parameters<TEvtMap[TKey]>>;
/**
* Allows subscribing to multiple events and calling the callback only when one of, all of, or a subset of the events are emitted, either continuously or only once.
* @param options An object or array of objects with the following properties:
* `callback` (required) is the function that will be called when the conditions are met.
*
* Set `once` to true to call the callback only once for the first event (or set of events) that match the criteria, then stop listening.
* If `signal` is provided, the subscription will be aborted when the given signal is aborted.
*
* If `oneOf` is used, the callback will be called when any of the matching events are emitted.
* If `allOf` is used, the callback will be called after all of the matching events are emitted at least once, then any time any of them are emitted.
* You may use a combination of the above two options, but at least one of them must be provided.
*
* @returns Returns a function that can be called to unsubscribe all listeners created by this call. Alternatively, pass an `AbortSignal` to all options objects to achieve the same effect or for finer control.
*/
onMulti<TEvt extends keyof TEvtMap>(options: NanoEmitterOnMultiOptions<TEvtMap> | Array<NanoEmitterOnMultiOptions<TEvtMap>>): Unsubscribe;
/**
* Emits an event on this instance.
* - ⚠️ Needs `publicEmit` to be set to true in the NanoEmitter constructor or super() call!
* @param event The event to emit
* @param args The arguments to pass to the event listeners
* @returns Returns true if `publicEmit` is true and the event was emitted successfully
*/
emit<TKey extends keyof TEvtMap>(event: TKey, ...args: Parameters<TEvtMap[TKey]>): boolean;
/** Unsubscribes all event listeners from this instance */
unsubscribeAll(): void;
}
export {};