UNPKG

evnty

Version:

0-Deps, simple, fast, for browser and node js reactive anonymous event library

1 lines 44.7 kB
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { MaybePromise, Callback, Listener, FilterFunction, Predicate, Filter, Mapper, AsyncGenerable, Reducer, Expander } from './types.js';\nimport { Callable } from './callable.js';\nimport { Sequence } from './sequence.js';\n\nexport * from './types.js';\nexport * from './callable.js';\nexport * from './signal.js';\nexport * from './sequence.js';\n\n/**\n * Removes a listener from the provided array of listeners. It searches for the listener and removes all instances of it from the array.\n * This method ensures that the listener is fully unregistered, preventing any residual calls to a potentially deprecated handler.\n *\n * @internal\n * @param {unknown[]} listeners - The array of listeners from which to remove the listener.\n * @param {unknown} listener - The listener function to remove from the list of listeners.\n * @returns {boolean} - Returns `true` if the listener was found and removed, `false` otherwise.\n *\n * @template T - The type of the event that listeners are associated with.\n * @template R - The type of the return value that listeners are expected to return.\n *\n * ```typescript\n * // Assuming an array of listeners for click events\n * const listeners = [onClickHandler1, onClickHandler2];\n * const wasRemoved = removeListener(listeners, onClickHandler1);\n * console.log(wasRemoved); // Output: true\n * ```\n */\nexport const removeListener = (listeners: unknown[], listener: unknown): boolean => {\n let index = listeners.indexOf(listener);\n const wasRemoved = index !== -1;\n while (~index) {\n listeners.splice(index, 1);\n index = listeners.indexOf(listener);\n }\n return wasRemoved;\n};\n\n/**\n * @internal\n * Creates a promise that resolves after a specified timeout. If an `AbortSignal` is provided and triggered,\n * the timeout is cleared, and the promise resolves to `false`.\n *\n * @param {number} timeout - The time in milliseconds to wait before resolving the promise.\n * @param {AbortSignal} [signal] - An optional `AbortSignal` that can abort the timeout.\n * @returns {Promise<boolean>} A promise that resolves to `true` if the timeout completed, or `false` if it was aborted.\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 500);\n * const result = await setTimeoutAsync(1000, controller.signal);\n * console.log(result); // false\n * ```\n */\nexport const setTimeoutAsync = (timeout: number, signal?: AbortSignal): Promise<boolean> =>\n new Promise<boolean>((resolve) => {\n const timerId = setTimeout(resolve, timeout, true);\n signal?.addEventListener('abort', () => {\n clearTimeout(timerId);\n resolve(false);\n });\n });\n\n/*\n * @internal\n */\nexport interface AsyncIterableCombinators<T> {\n filter<U extends T>(filter: Filter<T, U>): AsyncIterableCombinators<Awaited<U>>;\n map<U>(mapper: Mapper<T, U>): AsyncIterableCombinators<Awaited<U>>;\n reduce<U>(reducer: Reducer<T, U>): AsyncIterableCombinators<Awaited<U>>;\n expand<U>(expander: Mapper<T, U[]>): AsyncIterableCombinators<Awaited<U>>;\n pipe<U>(expander: AsyncGenerable<T, U>): AsyncIterableCombinators<Awaited<U>>;\n}\n\n/*\n * @internal\n */\nexport interface EventSource<T> extends Callable<[T], boolean>, Promise<T>, AsyncIterable<T> {\n next(): Promise<T>;\n}\n\n/**\n * @internal\n */\n\n/**\n * @internal\n */\nexport class Unsubscribe extends Callable<[], MaybePromise<void>> {\n private _done = false;\n\n constructor(callback: Callback) {\n super(async () => {\n this._done = true;\n await callback();\n });\n }\n\n get done() {\n return this._done;\n }\n\n pre(callback: Callback): Unsubscribe {\n return new Unsubscribe(async () => {\n await callback();\n await this();\n });\n }\n\n post(callback: Callback): Unsubscribe {\n return new Unsubscribe(async () => {\n await this();\n await callback();\n });\n }\n\n countdown(count: number): Unsubscribe {\n return new Unsubscribe(async () => {\n if (!--count) {\n await this();\n }\n });\n }\n}\n\nenum HookType {\n Add,\n Remove,\n}\n\n/**\n * A class representing an anonymous event that can be listened to or triggered.\n *\n * @template T - The event type.\n * @template R - The return type of the event.\n */\nexport class Event<T = unknown, R = unknown> extends Callable<[T], Promise<(void | Awaited<R>)[]>> implements AsyncIterable<T>, PromiseLike<T> {\n /**\n * The array of listeners for the event.\n */\n private listeners: Listener<T, R>[];\n\n private hooks: Array<(listener: Listener<T, R> | void, type: HookType) => void> = [];\n\n private _disposed = false;\n\n /**\n * A function that disposes of the event and its listeners.\n */\n readonly dispose: Callback;\n\n /**\n * Creates a new event.\n *\n * @param dispose - A function to call on the event disposal.\n *\n * ```typescript\n * // Create a click event.\n * const clickEvent = new Event<[x: number, y: number], void>();\n * clickEvent.on(([x, y]) => console.log(`Clicked at ${x}, ${y}`));\n * ```\n */\n constructor(dispose?: Callback) {\n const listeners: Listener<T, R>[] = [];\n // passes listeners exceptions to catch method\n super((value: T): Promise<(void | Awaited<R>)[]> => Promise.all(listeners.map(async (listener) => listener(await value))));\n\n this.listeners = listeners;\n\n this.dispose = () => {\n this._disposed = true;\n void this.clear();\n void this._error?.dispose();\n void dispose?.();\n };\n }\n\n private _error?: Event<unknown>;\n\n /**\n * Error event that emits errors.\n *\n * @returns {Event<unknown>} The error event.\n */\n get error(): Event<unknown> {\n return (this._error ??= new Event<unknown>());\n }\n\n /**\n * The number of listeners for the event.\n *\n * @readonly\n * @type {number}\n */\n get size(): number {\n return this.listeners.length;\n }\n\n /**\n * Checks if the event has been disposed.\n * @returns {boolean} `true` if the event has been disposed; otherwise, `false`.\n */\n get disposed(): boolean {\n return this._disposed;\n }\n\n /**\n * Checks if the given listener is NOT registered for this event.\n *\n * @param listener - The listener function to check against the registered listeners.\n * @returns `true` if the listener is not already registered; otherwise, `false`.\n *\n * ```typescript\n * // Check if a listener is not already added\n * if (event.lacks(myListener)) {\n * event.on(myListener);\n * }\n * ```\n */\n lacks(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) === -1;\n }\n\n /**\n * Checks if the given listener is registered for this event.\n *\n * @param listener - The listener function to check.\n * @returns `true` if the listener is currently registered; otherwise, `false`.\n *\n * ```typescript\n * // Verify if a listener is registered\n * if (event.has(myListener)) {\n * console.log('Listener is already registered');\n * }\n * ```\n */\n has(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) !== -1;\n }\n\n /**\n * Removes a specific listener from this event.\n *\n * @param listener - The listener to remove.\n * @returns The event instance, allowing for method chaining.\n *\n * ```typescript\n * // Remove a listener\n * event.off(myListener);\n * ```\n */\n off(listener: Listener<T, R>): this {\n if (removeListener(this.listeners, listener) && this.hooks.length) {\n [...this.hooks].forEach((spy) => spy(listener, HookType.Remove));\n }\n return this;\n }\n\n /**\n * Registers a listener that gets triggered whenever the event is emitted.\n * This is the primary method for adding event handlers that will react to the event being triggered.\n *\n * @param listener - The function to call when the event occurs.\n * @returns An object that can be used to unsubscribe the listener, ensuring easy cleanup.\n *\n * ```typescript\n * // Add a listener to an event\n * const unsubscribe = event.on((data) => {\n * console.log('Event data:', data);\n * });\n * ```\n */\n on(listener: Listener<T, R>): Unsubscribe {\n this.listeners.push(listener);\n if (this.hooks.length) {\n [...this.hooks].forEach((spy) => spy(listener, HookType.Add));\n }\n return new Unsubscribe(() => {\n void this.off(listener);\n });\n }\n\n /**\n * Adds a listener that will be called only once the next time the event is emitted.\n * This method is useful for one-time notifications or single-trigger scenarios.\n *\n * @param listener - The listener to trigger once.\n * @returns An object that can be used to remove the listener if the event has not yet occurred.\n *\n * ```typescript\n * // Register a one-time listener\n * const onceUnsubscribe = event.once((data) => {\n * console.log('Received data once:', data);\n * });\n * ```\n */\n once(listener: Listener<T, R>): Unsubscribe {\n const oneTimeListener = (event: T) => {\n void this.off(oneTimeListener);\n return listener(event);\n };\n return this.on(oneTimeListener);\n }\n\n /**\n * Removes all listeners from the event, effectively resetting it. This is useful when you need to\n * cleanly dispose of all event handlers to prevent memory leaks or unwanted triggers after certain conditions.\n *\n * @returns {this} The instance of the event, allowing for method chaining.\n *\n * ```typescript\n * const myEvent = new Event();\n * myEvent.on(data => console.log(data));\n * myEvent.clear(); // Clears all listeners\n * ```\n */\n clear(): this {\n this.listeners.splice(0);\n if (this.hooks.length) {\n [...this.hooks].forEach((spy) => spy(undefined, HookType.Remove));\n }\n return this;\n }\n\n /**\n * Enables the `Event` to be used in a Promise chain, resolving with the first emitted value.\n *\n * @template OK - The type of the fulfilled value returned by `onfulfilled` (defaults to the event's type).\n * @template ERR - The type of the rejected value returned by `onrejected` (defaults to `never`).\n * @param onfulfilled - A function called when the event emits its first value.\n * @param onrejected - A function called if an error occurs before the event emits.\n * @returns A Promise that resolves with the result of `onfulfilled` or `onrejected`.\n *\n * ```typescript\n * const clickEvent = new Event<[number, number]>();\n * await clickEvent;\n * ```\n */\n then<OK = T, ERR = never>(\n onfulfilled?: ((value: T) => OK | PromiseLike<OK>) | null,\n onrejected?: ((reason: unknown) => ERR | PromiseLike<ERR>) | null,\n ): Promise<OK | ERR> {\n const subscribers: Unsubscribe[] = [];\n const promise = new Promise<T>((resolve, reject) => {\n subscribers.push(this.once(resolve));\n subscribers.push(this.error.once(reject));\n });\n\n const unsubscribe = async <U>(value: U) => {\n await Promise.all(subscribers.map((u) => u()));\n return value;\n };\n\n return promise\n .then(onfulfilled, onrejected)\n .then(unsubscribe)\n .catch(async (error) => {\n throw await unsubscribe(error);\n });\n }\n\n /**\n * Waits for the event to settle, returning a `PromiseSettledResult`.\n *\n * @returns {Promise<PromiseSettledResult<T>>} A promise that resolves with the settled result.\n *\n * @example\n * ```typescript\n * const result = await event.settle();\n * if (result.status === 'fulfilled') {\n * console.log('Event fulfilled with value:', result.value);\n * } else {\n * console.error('Event rejected with reason:', result.reason);\n * }\n * ```\n */\n async settle(): Promise<PromiseSettledResult<T>> {\n return await Promise.allSettled([this.promise]).then(([settled]) => settled);\n }\n\n /**\n * A promise that resolves with the first emitted value from this event.\n *\n * @returns {Promise<T>} The promise value.\n */\n get promise(): Promise<T> {\n return this.then();\n }\n\n /**\n * Makes this event iterable using `for await...of` loops.\n *\n * @returns An async iterator that yields values as they are emitted by this event.\n *\n * ```typescript\n * // Assuming an event that emits numbers\n * const numberEvent = new Event<number>();\n * (async () => {\n * for await (const num of numberEvent) {\n * console.log('Number:', num);\n * }\n * })();\n * await numberEvent(1);\n * await numberEvent(2);\n * await numberEvent(3);\n * ```\n */\n [Symbol.asyncIterator](): AsyncIterator<T> {\n const ctrl = new AbortController();\n const sequence = new Sequence<T>(ctrl.signal);\n const emitEvent = (value: T) => {\n sequence(value);\n };\n const unsubscribe = this.on(emitEvent).pre(() => {\n ctrl.abort('done');\n });\n\n const spy: (typeof this.hooks)[number] = (target = emitEvent, action) => {\n if (target === emitEvent && action === HookType.Remove) {\n void unsubscribe();\n }\n };\n\n this.hooks.push(spy);\n return sequence[Symbol.asyncIterator]();\n }\n\n /**\n * Transforms the event's values using a generator function, creating a new `Event` that emits the transformed values.\n *\n * @template PT - The type of values emitted by the transformed `Event`.\n * @template PR - The return type of the listeners of the transformed `Event`.\n * @param generator - A function that takes the original event's value and returns a generator (sync or async) that yields the transformed values.\n * @returns A new `Event` instance that emits the transformed values.\n *\n * ```typescript\n * const numbersEvent = new Event<number>();\n * const evenNumbersEvent = numbersEvent.pipe(function*(value) {\n * if (value % 2 === 0) {\n * yield value;\n * }\n * });\n * evenNumbersEvent.on((evenNumber) => console.log(evenNumber));\n * await numbersEvent(1);\n * await numbersEvent(2);\n * await numbersEvent(3);\n * ```\n */\n pipe<PT, R>(generator: (event: T) => AsyncGenerator<PT, void, unknown> | Generator<PT, void, unknown>): Event<PT, R> {\n const emitEvent = async (value: T) => {\n try {\n for await (const generatedValue of generator(value)) {\n await result(generatedValue).catch(result.error);\n }\n } catch (e) {\n await result.error(e);\n }\n };\n\n const unsubscribe = this.on(emitEvent).pre(() => {\n removeListener(this.hooks, hook);\n });\n\n const hook: (typeof this.hooks)[number] = (target = emitEvent, action) => {\n if (target === emitEvent && action === HookType.Remove) {\n void unsubscribe();\n }\n };\n this.hooks.push(hook);\n\n const result = new Event<PT, R>(unsubscribe);\n return result;\n }\n\n /**\n * Creates an async generator that yields values as they are emitted by this event.\n *\n * @template PT - The type of values yielded by the async generator.\n * @param generator - An optional function that takes the original event's value and returns a generator (sync or async)\n * that yields values to include in the async generator.\n * @returns An async generator that yields values from this event as they occur.\n *\n * ```typescript\n * const numbersEvent = new Event<number>();\n * const evenNumbersEvent = numbersEvent.pipe(function*(value) {\n * if (value % 2 === 0) {\n * yield value;\n * }\n * });\n * evenNumbersEvent.on((evenNumber) => console.log(evenNumber));\n * await numbersEvent(1);\n * await numbersEvent(2);\n * await numbersEvent(3);\n * ```\n */\n async *generator<PT>(generator: (event: T) => AsyncGenerator<PT, void, unknown> | Generator<PT, void, unknown>): AsyncGenerator<Awaited<PT>, void, unknown> {\n for await (const value of this.pipe(generator)) {\n yield value;\n }\n }\n\n /**\n * Filters events, creating a new event that only triggers when the provided filter function returns `true`.\n * This method can be used to selectively process events that meet certain criteria.\n *\n * @param {Filter<T, P>} predicate The filter function or predicate to apply to each event.\n * @returns {Event<P, R>} A new event that only triggers for filtered events.\n *\n * ```typescript\n * const keyPressedEvent = new Event<string>();\n * const enterPressedEvent = keyPressedEvent.filter(key => key === 'Enter');\n * enterPressedEvent.on(() => console.log('Enter key was pressed.'));\n * ```\n */\n filter<P extends T>(predicate: Predicate<T, P>): Event<P, R>;\n filter<P extends T>(filter: FilterFunction<T>): Event<P, R>;\n filter<P extends T>(filter: Filter<T, P>): Event<P, R> {\n return this.pipe<P, R>(async function* (value: T) {\n if (await filter(value)) {\n yield value as P;\n }\n });\n }\n\n /**\n * Creates a new event that will only be triggered once when the provided filter function returns `true`.\n * This method is useful for handling one-time conditions in a stream of events.\n *\n * @param {Filter<T, P>} predicate - The filter function or predicate.\n * @returns {Event<P, R>} A new event that will be triggered only once when the filter condition is met.\n *\n * ```typescript\n * const sizeChangeEvent = new Event<number>();\n * const sizeReachedEvent = sizeChangeEvent.first(size => size > 1024);\n * sizeReachedEvent.on(() => console.log('Size threshold exceeded.'));\n * ```\n */\n first<P extends T>(predicate: Predicate<T, P>): Event<P, R>;\n first<P extends T>(filter: FilterFunction<T>): Event<P, R>;\n first<P extends T>(filter: Filter<T, P>): Event<P, R> {\n const filteredEvent = this.pipe<P, R>(async function* (value: T) {\n if (await filter(value)) {\n yield value as P;\n await filteredEvent.dispose();\n }\n });\n return filteredEvent;\n }\n\n /**\n * Transforms the data emitted by this event using a mapping function. Each emitted event is processed by the `mapper`\n * function, which returns a new value that is then emitted by the returned `Event` instance. This is useful for data transformation\n * or adapting the event's data structure.\n *\n * @template M The type of data that the mapper function will produce.\n * @template MR The type of data emitted by the mapped event, usually related to or the same as `M`.\n * @param {Mapper<T, M>} mapper A function that takes the original event data and returns the transformed data.\n * @returns {Event<M, MR>} A new `Event` instance that emits the mapped values.\n *\n * ```typescript\n * // Assuming an event that emits numbers, create a new event that emits their squares.\n * const numberEvent = new Event<number>();\n * const squaredEvent = numberEvent.map(num => num * num);\n * squaredEvent.on(squared => console.log('Squared number:', squared));\n * await numberEvent(5); // Logs: \"Squared number: 25\"\n * ```\n */\n map<M, MR = R>(mapper: Mapper<T, M>): Event<Awaited<M>, MR> {\n return this.pipe(async function* (value) {\n yield await mapper(value);\n });\n }\n\n /**\n * Accumulates the values emitted by this event using a reducer function, starting from an initial value. The reducer\n * function takes the accumulated value and the latest emitted event data, then returns a new accumulated value. This\n * new value is then emitted by the returned `Event` instance. This is particularly useful for accumulating state over time.\n *\n * @template A The type of the accumulator value.\n * @template AR The type of data emitted by the reduced event, usually the same as `A`.\n * @param {Reducer<T, A>} reducer A function that takes the current accumulated value and the new event data, returning the new accumulated value.\n * @param {A} init The initial value of the accumulator.\n * @returns {Event<A, AR>} A new `Event` instance that emits the reduced value.\n *\n * ```typescript\n * const sumEvent = numberEvent.reduce((a, b) => a + b, 0);\n * sumEvent.on((sum) => console.log(sum)); // 1, 3, 6\n * await sumEvent(1);\n * await sumEvent(2);\n * await sumEvent(3);\n * ```\n */\n reduce<A, AR = R>(reducer: Reducer<T, A>, init?: A): Event<Awaited<A>, AR>;\n reduce<A, AR = R>(reducer: Reducer<T, A>, ...init: unknown[]): Event<Awaited<A>, AR> {\n let hasInit = init.length === 1;\n let result = init[0] as A | undefined;\n\n return this.pipe(async function* (value) {\n if (hasInit) {\n result = await reducer(result!, value);\n yield result;\n } else {\n result = value as unknown as A;\n hasInit = true;\n }\n });\n }\n\n /**\n * Transforms each event's data into multiple events using an expander function. The expander function takes\n * the original event's data and returns an array of new data elements, each of which will be emitted individually\n * by the returned `Event` instance. This method is useful for scenarios where an event's data can naturally\n * be expanded into multiple, separate pieces of data which should each trigger further processing independently.\n *\n * @template ET - The type of data elements in the array returned by the expander function.\n * @template ER - The type of responses emitted by the expanded event, usually related to or the same as `ET`.\n * @param {Expander<T, ET[]>} expander - A function that takes the original event data and returns an array of new data elements.\n * @returns {Event<ET, ER>} - A new `Event` instance that emits each value from the array returned by the expander function.\n *\n * ```typescript\n * // Assuming an event that emits a sentence, create a new event that emits each word from the sentence separately.\n * const sentenceEvent = new Event<string>();\n * const wordEvent = sentenceEvent.expand(sentence => sentence.split(' '));\n * wordEvent.on(word => console.log('Word:', word));\n * await sentenceEvent('Hello world'); // Logs: \"Word: Hello\", \"Word: world\"\n * ```\n */\n expand<ET, ER>(expander: Expander<T, ET[]>): Event<Awaited<ET>, ER> {\n return this.pipe(async function* (value) {\n const values = await expander(value);\n for (const value of values) {\n yield value;\n }\n });\n }\n\n /**\n * Creates a new event that emits values based on a conductor event. The orchestrated event will emit the last value\n * captured from the original event each time the conductor event is triggered.\n *\n * @template T The type of data emitted by the original event.\n * @template R The type of data emitted by the orchestrated event, usually the same as `T`.\n * @param {Event<unknown, unknown>} conductor The event that triggers the emission of the last captured value.\n * @returns {Event<T, R>} A new event that emits values based on the conductor's triggers.\n *\n * ```typescript\n * const rightClickPositionEvent = mouseMoveEvent.orchestrate(mouseRightClickEvent);\n * ```\n *\n * ```typescript\n * // An event that emits whenever a \"tick\" event occurs.\n * const tickEvent = new Event<void>();\n * const dataEvent = new Event<string>();\n * const synchronizedEvent = dataEvent.orchestrate(tickEvent);\n * synchronizedEvent.on(data => console.log('Data on tick:', data));\n * await dataEvent('Hello');\n * await dataEvent('World!');\n * await tickEvent(); // Logs: \"Data on tick: World!\"\n * ```\n */\n orchestrate<CT, CR>(conductor: Event<CT, CR>): Event<T, R> {\n let initialized = false;\n let lastValue: T;\n const unsubscribe = this.on((event) => {\n initialized = true;\n lastValue = event;\n });\n const unsubscribeConductor = conductor.on(async () => {\n if (initialized) {\n await orchestratedEvent(lastValue);\n initialized = false;\n }\n });\n\n const orchestratedEvent = new Event<T, R>(unsubscribe.post(unsubscribeConductor));\n\n return orchestratedEvent;\n }\n /**\n * Creates a debounced event that delays triggering until after a specified interval has elapsed\n * following the last time it was invoked. This method is particularly useful for limiting the rate\n * at which a function is executed. Common use cases include handling rapid user inputs, window resizing,\n * or scroll events.\n *\n * @param {number} interval - The amount of time to wait (in milliseconds) before firing the debounced event.\n * @returns {Event<T, R>} An event of debounced events.\n *\n * ```typescript\n * const debouncedEvent = textInputEvent.debounce(100);\n * debouncedEvent.on((str) => console.log(str)); // only 'text' is emitted\n * await event('t');\n * await event('te');\n * await event('tex');\n * await event('text');\n * ```\n */\n debounce(interval: number): Event<Awaited<T>, unknown> {\n let controller = new AbortController();\n\n return this.pipe(async function* (value) {\n controller.abort();\n controller = new AbortController();\n const complete = await setTimeoutAsync(interval, controller.signal);\n if (complete) {\n yield value;\n }\n });\n }\n\n /**\n * Creates a throttled event that emits values at most once per specified interval.\n *\n * This is useful for controlling the rate of event emissions, especially for high-frequency events.\n * The throttled event will immediately emit the first value, and then only emit subsequent values\n * if the specified interval has passed since the last emission.\n *\n * @param interval - The time interval (in milliseconds) between allowed emissions.\n * @returns A new Event that emits throttled values.\n *\n * ```typescript\n * const scrollEvent = new Event();\n * const throttledScroll = scrollEvent.throttle(100); // Emit at most every 100ms\n * throttledScroll.on(() => console.log(\"Throttled scroll event\"));\n * ```\n */\n throttle(interval: number): Event<Awaited<T>, unknown> {\n let timeout = 0;\n let pendingValue: T;\n let hasPendingValue = false;\n\n return this.pipe(async function* (value) {\n const now = Date.now();\n if (timeout <= now) {\n timeout = now + interval;\n yield value;\n } else {\n pendingValue = value;\n if (!hasPendingValue) {\n hasPendingValue = true;\n await setTimeoutAsync(timeout - now);\n timeout = now + interval;\n hasPendingValue = false;\n yield pendingValue;\n }\n }\n });\n }\n\n /**\n * Aggregates multiple event emissions into batches and emits the batched events either at specified\n * time intervals or when the batch reaches a predefined size. This method is useful for grouping\n * a high volume of events into manageable chunks, such as logging or processing data in bulk.\n *\n * @param {number} interval - The time in milliseconds between batch emissions.\n * @param {number} [size] - Optional. The maximum size of each batch. If specified, triggers a batch emission\n * once the batch reaches this size, regardless of the interval.\n * @returns {Event<T[], R>} An event of the batched results.\n *\n * ```typescript\n * // Batch messages for bulk processing every 1 second or when 10 messages are collected\n * const messageEvent = createEvent<string, void>();\n * const batchedMessageEvent = messageEvent.batch(1000, 10);\n * batchedMessageEvent.on((messages) => console.log('Batched Messages:', messages));\n * ```\n */\n batch(interval: number, size?: number): Event<T[], R> {\n let controller = new AbortController();\n const batch: T[] = [];\n\n return this.pipe(async function* (value) {\n batch.push(value);\n if (size !== undefined && batch.length >= size) {\n controller.abort();\n yield batch.splice(0);\n }\n if (batch.length === 1) {\n controller = new AbortController();\n const complete = await setTimeoutAsync(interval, controller.signal);\n if (complete) {\n yield batch.splice(0);\n }\n }\n });\n }\n\n /**\n * Creates a queue from the event, where each emitted value is sequentially processed. The returned object allows popping elements\n * from the queue, ensuring that elements are handled one at a time. This method is ideal for scenarios where order and sequential processing are critical.\n *\n * @returns {Queue<T>} An object representing the queue. The 'pop' method retrieves the next element from the queue, while 'stop' halts further processing.\n *\n * ```typescript\n * // Queueing tasks for sequential execution\n * const taskEvent = new Event<string>();\n * const taskQueue = taskEvent.queue();\n * (async () => {\n * console.log('Processing:', await taskQueue.pop()); // Processing: Task 1\n * // Queue also can be used as a Promise\n * console.log('Processing:', await taskQueue); // Processing: Task 2\n * })();\n * await taskEvent('Task 1');\n * await taskEvent('Task 2');\n *```\n *\n *```typescript\n * // Additionally, the queue can be used as an async iterator\n * const taskEvent = new Event<string>();\n * const taskQueue = taskEvent.queue();\n * (async () => {\n * for await (const task of taskQueue) {\n * console.log('Processing:', task);\n * }\n * })();\n * await taskEvent('Task 1');\n * await taskEvent('Task 2');\n * ```\n *\n */\n queue(): Queue<T> {\n const ctrl = new AbortController();\n const sequence = new Sequence<T>(ctrl.signal);\n const onEvent = (value: T) => {\n sequence(value);\n };\n const unsubscribe = this.on(onEvent).pre(() => {\n ctrl.abort('done');\n });\n\n const pop = async () => await sequence;\n\n return {\n pop,\n stop: async () => {\n await unsubscribe();\n },\n get stopped() {\n return ctrl.signal.aborted;\n },\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n return pop().then(onfulfilled, onrejected);\n },\n [Symbol.asyncIterator]() {\n return {\n next: async () => {\n try {\n const value = await pop();\n return { value, done: false };\n } catch {\n return { value: undefined, done: true };\n }\n },\n };\n },\n };\n }\n}\n\nexport interface Queue<T> extends AsyncIterable<T>, PromiseLike<T> {\n pop(): Promise<T>;\n stop(): Promise<void>;\n stopped: boolean;\n}\n\nexport type EventParameters<T> = T extends Event<infer P, any> ? P : never;\n\nexport type EventResult<T> = T extends Event<any, infer R> ? R : never;\n\nexport type AllEventsParameters<T extends Event<any, any>[]> = { [K in keyof T]: EventParameters<T[K]> }[number];\n\nexport type AllEventsResults<T extends Event<any, any>[]> = { [K in keyof T]: EventResult<T[K]> }[number];\n\n/**\n * Merges multiple events into a single event. This function takes any number of `Event` instances\n * and returns a new `Event` that triggers whenever any of the input events trigger. The parameters\n * and results of the merged event are derived from the input events, providing a flexible way to\n * handle multiple sources of events in a unified manner.\n *\n * @template Events - An array of `Event` instances.\n * @param {...Events} events - A rest parameter that takes multiple events to be merged.\n * @returns {Event<AllEventsParameters<Events>, AllEventsResults<Events>>} - Returns a new `Event` instance\n * that triggers with the parameters and results of any of the merged input events.\n *\n * ```typescript\n * // Merging mouse and keyboard events into a single event\n * const mouseEvent = createEvent<MouseEvent>();\n * const keyboardEvent = createEvent<KeyboardEvent>();\n * const inputEvent = merge(mouseEvent, keyboardEvent);\n * inputEvent.on(event => console.log('Input event:', event));\n * ```\n */\nexport const merge = <Events extends Event<any, any>[]>(...events: Events): Event<AllEventsParameters<Events>, AllEventsResults<Events>> => {\n const mergedEvent = new Event<AllEventsParameters<Events>, AllEventsResults<Events>>();\n events.forEach((event) => event.on(mergedEvent));\n return mergedEvent;\n};\n\n/**\n * Creates a periodic event that triggers at a specified interval. The event will automatically emit\n * an incrementing counter value each time it triggers, starting from zero. This function is useful\n * for creating time-based triggers within an application, such as updating UI elements, polling,\n * or any other timed operation.\n *\n * @template R - The return type of the event handler function, defaulting to `void`.\n * @param {number} interval - The interval in milliseconds at which the event should trigger.\n * @returns {Event<number, R>} - An `Event` instance that triggers at the specified interval,\n * emitting an incrementing counter value.\n *\n * ```typescript\n * // Creating an interval event that logs a message every second\n * const tickEvent = createInterval(1000);\n * tickEvent.on(tickNumber => console.log('Tick:', tickNumber));\n * ```\n */\nexport const createInterval = <R = unknown>(interval: number): Event<number, R> => {\n let counter = 0;\n const intervalEvent = new Event<number, R>(() => clearInterval(timerId));\n const timerId: ReturnType<typeof setInterval> = setInterval(() => {\n void intervalEvent(counter++);\n }, interval);\n return intervalEvent;\n};\n\n/**\n * Creates a new instance of the `Event` class, which allows for the registration of event handlers that get called when the event is emitted.\n * This factory function simplifies the creation of events by encapsulating the instantiation logic, providing a clean and simple API for event creation.\n *\n * @typeParam T - The tuple of argument types that the event will accept.\n * @typeParam R - The return type of the event handler function, which is emitted after processing the event data.\n * @returns {Event<T, R>} - A new instance of the `Event` class, ready to have listeners added to it.\n *\n * ```typescript\n * // Create a new event that accepts a string and returns the string length\n * const myEvent = createEvent<string, number>();\n * myEvent.on((str: string) => str.length);\n * myEvent('hello').then(results => console.log(results)); // Logs: [5]\n * ```\n */\nexport const createEvent = <T = unknown, R = unknown>(): Event<T, R> => new Event<T, R>();\n\nexport default createEvent;\n\n/**\n * A type helper that extracts the event listener type\n *\n * @typeParam E - The event type.\n */\nexport type EventHandler<E> = E extends Event<infer T, infer R> ? Listener<T, R> : never;\n\n/**\n * A type helper that extracts the event filter type\n *\n * @typeParam E The event type to filter.\n */\nexport type EventFilter<E> = FilterFunction<EventParameters<E>>;\n\n/**\n * A type helper that extracts the event predicate type\n *\n * @typeParam E The event type to predicate.\n */\nexport type EventPredicate<E, P extends EventParameters<E>> = Predicate<EventParameters<E>, P>;\n\n/**\n * A type helper that extracts the event mapper type\n *\n * @typeParam E The event type to map.\n * @typeParam M The new type to map `E` to.\n */\nexport type EventMapper<E, M> = Mapper<EventParameters<E>, M>;\n\n/**\n * A type helper that extracts the event mapper type\n *\n * @typeParam E The type of event to reduce.\n * @typeParam M The type of reduced event.\n */\nexport type EventReducer<E, R> = Reducer<EventParameters<E>, R>;\n"],"names":["Event","Unsubscribe","createEvent","createInterval","merge","removeListener","setTimeoutAsync","listeners","listener","index","indexOf","wasRemoved","splice","timeout","signal","Promise","resolve","timerId","setTimeout","addEventListener","clearTimeout","Callable","_done","constructor","callback","done","pre","post","countdown","count","HookType","hooks","_disposed","dispose","value","all","map","clear","_error","error","size","length","disposed","lacks","has","off","forEach","spy","on","push","once","oneTimeListener","event","undefined","then","onfulfilled","onrejected","subscribers","promise","reject","unsubscribe","u","catch","settle","allSettled","settled","Symbol","asyncIterator","ctrl","AbortController","sequence","Sequence","emitEvent","abort","target","action","pipe","generator","generatedValue","result","e","hook","filter","first","filteredEvent","mapper","reduce","reducer","init","hasInit","expand","expander","values","orchestrate","conductor","initialized","lastValue","unsubscribeConductor","orchestratedEvent","debounce","interval","controller","complete","throttle","pendingValue","hasPendingValue","now","Date","batch","queue","onEvent","pop","stop","stopped","aborted","next","events","mergedEvent","counter","intervalEvent","clearInterval","setInterval"],"mappings":"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"}