/** * @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.ts"; export interface NanoEmitterOptions { /** If set to true, allows emitting events through the public method emit() */ publicEmit: boolean; /** * When provided, the emitter will remember the last arguments of each listed event. * Any listener attached via `on()` or `once()` after the event has already fired will * be immediately called / resolved with the cached arguments (catch-up behaviour). * Only works for emissions that go through the public `emit()` or the protected `emitEvent()` method. */ catchUpEvents?: PropertyKey[]; } type NanoEmitterOnMultiTriggerOptions = { /** Calls the callback when one of the given events is emitted. Either one of or both of `oneOf` and `allOf` need to be set. If both are set, they behave like an "AND" condition. */ oneOf?: TKey[]; /** Calls the callback when all of the given events are emitted. Either one of or both of `oneOf` and `allOf` need to be set. If both are set, they behave like an "AND" condition. */ allOf?: TKey[]; }; /** Options for the {@linkcode NanoEmitter.onMulti()} method */ export type NanoEmitterOnMultiOptions = 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 cancel 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) => void; } & NanoEmitterOnMultiTriggerOptions & (Pick>, "oneOf"> | Pick>, "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, prefer using `this.emitEvent()` over `this.events.emit()` — it updates the catch-up memory for any events listed in `catchUpEvents`. */ export declare class NanoEmitter { protected readonly events: Emitter; protected eventUnsubscribes: Unsubscribe[]; protected emitterOptions: NanoEmitterOptions; /** Stores the last arguments for each event listed in `catchUpEvents` */ protected catchUpMemory: Map; /** Creates a new instance of NanoEmitter - a lightweight event emitter with helper methods and a strongly typed event map */ constructor(options?: Partial); /** * Emits an event on this instance, bypassing the `publicEmit` guard. * Prefer this over `this.events.emit()` in subclasses — it updates catch-up memory * for any event listed in `catchUpEvents` so late listeners can still receive the last value. */ protected emitEvent(event: TKey, ...args: Parameters): void; /** * 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(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(event: TKey | "_", cb?: TEvtMap[TKey]): Promise>; /** * 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 canceled 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. * If both `oneOf` and `allOf` are used together, the callback will be called when any of the `oneOf` events are emitted AND all of the `allOf` events have been emitted at least once. * At least one of `oneOf` or `allOf` 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(options: NanoEmitterOnMultiOptions | Array>): 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(event: TKey, ...args: Parameters): boolean; /** Unsubscribes all event listeners from this instance */ unsubscribeAll(): void; } export {};