evnty 4.3.16 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.cjs +33 -36
- package/build/index.cjs.map +1 -1
- package/build/index.d.ts +18 -17
- package/build/index.js +33 -36
- package/build/index.js.map +1 -1
- package/package.json +13 -15
- package/src/index.ts +51 -49
package/build/index.cjs
CHANGED
|
@@ -90,25 +90,25 @@ class Unsubscribe extends Callable {
|
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
-
var
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
93
|
+
var HookType = /*#__PURE__*/ function(HookType) {
|
|
94
|
+
HookType[HookType["Add"] = 0] = "Add";
|
|
95
|
+
HookType[HookType["Remove"] = 1] = "Remove";
|
|
96
|
+
return HookType;
|
|
97
|
+
}(HookType || {});
|
|
98
98
|
class Event extends Callable {
|
|
99
99
|
listeners;
|
|
100
|
-
|
|
100
|
+
hooks = [];
|
|
101
101
|
_disposed = false;
|
|
102
102
|
dispose;
|
|
103
103
|
constructor(dispose){
|
|
104
104
|
const listeners = [];
|
|
105
105
|
super((value)=>Promise.all(listeners.map(async (listener)=>listener(await value))));
|
|
106
106
|
this.listeners = listeners;
|
|
107
|
-
this.dispose =
|
|
107
|
+
this.dispose = ()=>{
|
|
108
108
|
this._disposed = true;
|
|
109
109
|
void this.clear();
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
void this._error?.dispose();
|
|
111
|
+
void dispose?.();
|
|
112
112
|
};
|
|
113
113
|
}
|
|
114
114
|
_error;
|
|
@@ -128,18 +128,18 @@ class Event extends Callable {
|
|
|
128
128
|
return this.listeners.indexOf(listener) !== -1;
|
|
129
129
|
}
|
|
130
130
|
off(listener) {
|
|
131
|
-
if (removeListener(this.listeners, listener) && this.
|
|
131
|
+
if (removeListener(this.listeners, listener) && this.hooks.length) {
|
|
132
132
|
[
|
|
133
|
-
...this.
|
|
133
|
+
...this.hooks
|
|
134
134
|
].forEach((spy)=>spy(listener, 1));
|
|
135
135
|
}
|
|
136
136
|
return this;
|
|
137
137
|
}
|
|
138
138
|
on(listener) {
|
|
139
139
|
this.listeners.push(listener);
|
|
140
|
-
if (this.
|
|
140
|
+
if (this.hooks.length) {
|
|
141
141
|
[
|
|
142
|
-
...this.
|
|
142
|
+
...this.hooks
|
|
143
143
|
].forEach((spy)=>spy(listener, 0));
|
|
144
144
|
}
|
|
145
145
|
return new Unsubscribe(()=>{
|
|
@@ -155,9 +155,9 @@ class Event extends Callable {
|
|
|
155
155
|
}
|
|
156
156
|
clear() {
|
|
157
157
|
this.listeners.splice(0);
|
|
158
|
-
if (this.
|
|
158
|
+
if (this.hooks.length) {
|
|
159
159
|
[
|
|
160
|
-
...this.
|
|
160
|
+
...this.hooks
|
|
161
161
|
].forEach((spy)=>spy(undefined, 1));
|
|
162
162
|
}
|
|
163
163
|
return this;
|
|
@@ -182,36 +182,33 @@ class Event extends Callable {
|
|
|
182
182
|
}
|
|
183
183
|
[Symbol.asyncIterator]() {
|
|
184
184
|
const queue = [];
|
|
185
|
-
const
|
|
185
|
+
const hasNextEvent = new Event();
|
|
186
186
|
const emitEvent = async (value)=>{
|
|
187
187
|
queue.push(value);
|
|
188
|
-
await
|
|
188
|
+
await hasNextEvent(true);
|
|
189
189
|
};
|
|
190
190
|
const unsubscribe = this.on(emitEvent).pre(async ()=>{
|
|
191
|
-
|
|
191
|
+
await hasNextEvent.dispose();
|
|
192
|
+
removeListener(this.hooks, spy);
|
|
192
193
|
queue.splice(0);
|
|
193
|
-
await doneEvent.dispose();
|
|
194
194
|
});
|
|
195
195
|
const spy = (target = emitEvent, action)=>{
|
|
196
196
|
if (target === emitEvent && action === 1) {
|
|
197
|
-
void
|
|
197
|
+
void hasNextEvent(false);
|
|
198
198
|
void unsubscribe();
|
|
199
199
|
}
|
|
200
200
|
};
|
|
201
|
-
this.
|
|
201
|
+
this.hooks.push(spy);
|
|
202
202
|
return {
|
|
203
203
|
async next () {
|
|
204
|
-
if (
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
value: queue.shift(),
|
|
213
|
-
done: false
|
|
214
|
-
};
|
|
204
|
+
if (!hasNextEvent.disposed) {
|
|
205
|
+
const next = queue.length || await hasNextEvent;
|
|
206
|
+
if (next) {
|
|
207
|
+
return {
|
|
208
|
+
value: queue.shift(),
|
|
209
|
+
done: false
|
|
210
|
+
};
|
|
211
|
+
}
|
|
215
212
|
}
|
|
216
213
|
return {
|
|
217
214
|
value: undefined,
|
|
@@ -221,8 +218,8 @@ class Event extends Callable {
|
|
|
221
218
|
async return (value) {
|
|
222
219
|
await unsubscribe();
|
|
223
220
|
return {
|
|
224
|
-
|
|
225
|
-
|
|
221
|
+
value,
|
|
222
|
+
done: true
|
|
226
223
|
};
|
|
227
224
|
}
|
|
228
225
|
};
|
|
@@ -238,14 +235,14 @@ class Event extends Callable {
|
|
|
238
235
|
}
|
|
239
236
|
};
|
|
240
237
|
const unsubscribe = this.on(emitEvent).pre(()=>{
|
|
241
|
-
removeListener(this.
|
|
238
|
+
removeListener(this.hooks, spy);
|
|
242
239
|
});
|
|
243
240
|
const spy = (target = emitEvent, action)=>{
|
|
244
241
|
if (target === emitEvent && action === 1) {
|
|
245
242
|
void unsubscribe();
|
|
246
243
|
}
|
|
247
244
|
};
|
|
248
|
-
this.
|
|
245
|
+
this.hooks.push(spy);
|
|
249
246
|
const result = new Event(unsubscribe);
|
|
250
247
|
return result;
|
|
251
248
|
}
|
package/build/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface Callback<R = void> {\n (): MaybePromise<R>;\n}\n\nexport interface Listener<T, R = unknown> {\n (event: T): MaybePromise<R | void>;\n}\n\nexport interface FilterFunction<T> {\n (event: T): MaybePromise<boolean>;\n}\n\nexport interface Predicate<T, P extends T> {\n (event: T): event is P;\n}\n\nexport type Filter<T, P extends T> = Predicate<T, P> | FilterFunction<T>;\n\nexport interface Mapper<T, R> {\n (event: T): MaybePromise<R>;\n}\n\nexport interface Reducer<T, R> {\n (result: R, event: T): MaybePromise<R>;\n}\n\nexport interface Expander<T, R> {\n (event: T): MaybePromise<R>;\n}\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 {Listener<T, R>[]} listeners - The array of listeners from which to remove the listener.\n * @param {Listener<T, R>} 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 * An abstract class that extends the built-in Function class. It allows instances of the class\n * to be called as functions. When an instance of Callable is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\nexport abstract class Callable extends Function {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n constructor(func: Function) {\n super();\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n\nexport interface Unsubscribe {\n (): MaybePromise<void>;\n}\n\n/**\n * @internal\n */\nexport class Unsubscribe extends Callable {\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\nexport interface Event<T = any, R = any> {\n (event: T): Promise<(void | Awaited<R>)[]>;\n}\n\nenum SpyType {\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, R> extends Callable implements AsyncIterable<T>, PromiseLike<T> {\n /**\n * The array of listeners for the event.\n */\n private listeners: Listener<T, R>[];\n\n private spies: Array<(listener: Listener<T, R> | void, type: SpyType) => 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 this.listeners = listeners;\n\n this.dispose = async () => {\n this._disposed = true;\n void this.clear();\n await this._error?.dispose();\n await 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.spies.length) {\n [...this.spies].forEach((spy) => spy(listener, SpyType.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.spies.length) {\n [...this.spies].forEach((spy) => spy(listener, SpyType.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 triggerings 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.spies.length) {\n [...this.spies].forEach((spy) => spy(undefined, SpyType.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 | undefined,\n onrejected?: ((reason: unknown) => ERR | PromiseLike<ERR>) | null | undefined,\n ): Promise<OK | ERR> {\n const unsubscribe: Unsubscribe[] = [];\n const promise = new Promise<T>((resolve, reject) => {\n unsubscribe.push(this.once(resolve));\n unsubscribe.push(this.error.once(reject));\n });\n\n return promise.then(onfulfilled, onrejected).finally(async () => {\n await Promise.all(unsubscribe.map((u) => u()));\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 queue: T[] = [];\n const doneEvent = new Event<boolean>();\n const emitEvent = async (value: T) => {\n queue.push(value);\n await doneEvent(false);\n };\n const unsubscribe = this.on(emitEvent).pre(async () => {\n removeListener(this.spies, spy);\n queue.splice(0);\n await doneEvent.dispose();\n });\n\n const spy: (typeof this.spies)[number] = (target = emitEvent, action) => {\n if (target === emitEvent && action === SpyType.Remove) {\n void doneEvent(true);\n void unsubscribe();\n }\n };\n\n this.spies.push(spy);\n return {\n async next() {\n if (queue.length) {\n return { value: queue.shift()!, done: false };\n }\n if (!(await doneEvent)) {\n return { value: queue.shift()!, done: false };\n }\n return { value: undefined, done: true };\n },\n async return(value: unknown) {\n await unsubscribe();\n return { done: true, value };\n },\n };\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.spies, spy);\n });\n\n const spy: (typeof this.spies)[number] = (target = emitEvent, action) => {\n if (target === emitEvent && action === SpyType.Remove) {\n void unsubscribe();\n }\n };\n this.spies.push(spy);\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(async (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 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 queue: T[] = [];\n let done = false;\n const valueEvent = new Event<void>();\n\n const unsubscribe = this.on(async (value) => {\n queue.push(value);\n await valueEvent();\n });\n\n const pop = async () => {\n if (!queue.length) {\n await valueEvent;\n }\n return queue.shift()!;\n };\n const stop = async () => {\n await unsubscribe();\n done = true;\n await valueEvent();\n };\n\n return {\n pop,\n stop,\n get stopped() {\n return done;\n },\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null | undefined,\n ): Promise<TResult1 | TResult2> {\n return this.pop().then(onfulfilled, onrejected);\n },\n [Symbol.asyncIterator]() {\n return {\n next: async () => {\n return { value: await pop(), done };\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(() => intervalEvent(counter++), 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":["Callable","Event","Unsubscribe","createEvent","createInterval","merge","removeListener","setTimeoutAsync","listeners","listener","index","indexOf","wasRemoved","splice","timeout","signal","Promise","resolve","timerId","setTimeout","addEventListener","clearTimeout","Function","constructor","func","Object","setPrototypeOf","prototype","_done","callback","done","pre","post","countdown","count","SpyType","spies","_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","unsubscribe","promise","reject","finally","u","settle","allSettled","settled","Symbol","asyncIterator","queue","doneEvent","emitEvent","target","action","next","shift","return","pipe","generator","generatedValue","result","catch","e","filter","first","filteredEvent","mapper","reduce","reducer","init","hasInit","expand","expander","values","orchestrate","conductor","initialized","lastValue","unsubscribeConductor","orchestratedEvent","debounce","interval","controller","AbortController","abort","complete","throttle","pendingValue","hasPendingValue","now","Date","batch","valueEvent","pop","stop","stopped","events","mergedEvent","counter","intervalEvent","clearInterval","setInterval"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export interface Fn<A extends unknown[], R> {\n (...args: A): R;\n}\n\nexport type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface Callback<R = void> extends Fn<[], MaybePromise<R>> {}\n\nexport interface Listener<T, R = unknown> extends Fn<[T], MaybePromise<R | void>> {}\n\nexport interface FilterFunction<T> {\n (event: T): MaybePromise<boolean>;\n}\n\nexport interface Predicate<T, P extends T> {\n (event: T): event is P;\n}\n\nexport type Filter<T, P extends T> = Predicate<T, P> | FilterFunction<T>;\n\nexport interface Mapper<T, R> {\n (event: T): MaybePromise<R>;\n}\n\nexport interface Reducer<T, R> {\n (result: R, event: T): MaybePromise<R>;\n}\n\nexport interface Expander<T, R> {\n (event: T): MaybePromise<R>;\n}\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 Callable<T extends unknown[], R> {\n (...args: T): R;\n}\n\n/**\n * An abstract class that extends the built-in Function class. It allows instances of the class\n * to be called as functions. When an instance of Callable is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport abstract class Callable<T, R> extends Function {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n constructor(func: Function) {\n super();\n return Object.setPrototypeOf(func, new.target.prototype);\n }\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 | undefined,\n onrejected?: ((reason: unknown) => ERR | PromiseLike<ERR>) | null | undefined,\n ): Promise<OK | ERR> {\n const unsubscribe: Unsubscribe[] = [];\n const promise = new Promise<T>((resolve, reject) => {\n unsubscribe.push(this.once(resolve));\n unsubscribe.push(this.error.once(reject));\n });\n\n return promise.then(onfulfilled, onrejected).finally(async () => {\n await Promise.all(unsubscribe.map((u) => u()));\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 queue: T[] = [];\n const hasNextEvent = new Event<boolean>();\n const emitEvent = async (value: T) => {\n queue.push(value);\n await hasNextEvent(true);\n };\n const unsubscribe = this.on(emitEvent).pre(async () => {\n await hasNextEvent.dispose();\n removeListener(this.hooks, spy);\n queue.splice(0);\n });\n\n const spy: (typeof this.hooks)[number] = (target = emitEvent, action) => {\n if (target === emitEvent && action === HookType.Remove) {\n void hasNextEvent(false);\n void unsubscribe();\n }\n };\n\n this.hooks.push(spy);\n return {\n async next() {\n if (!hasNextEvent.disposed) {\n const next = queue.length || (await hasNextEvent);\n if (next) {\n return { value: queue.shift()!, done: false };\n }\n }\n return { value: undefined, done: true };\n },\n async return(value: unknown) {\n await unsubscribe();\n return { value, done: true };\n },\n };\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, spy);\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 this.hooks.push(spy);\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(async (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 queue: T[] = [];\n let done = false;\n const valueEvent = new Event<void>();\n\n const unsubscribe = this.on(async (value) => {\n queue.push(value);\n await valueEvent();\n });\n\n const pop = async () => {\n if (!queue.length) {\n await valueEvent;\n }\n return queue.shift()!;\n };\n const stop = async () => {\n await unsubscribe();\n done = true;\n await valueEvent();\n };\n\n return {\n pop,\n stop,\n get stopped() {\n return done;\n },\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null | undefined,\n ): Promise<TResult1 | TResult2> {\n return this.pop().then(onfulfilled, onrejected);\n },\n [Symbol.asyncIterator]() {\n return {\n next: async () => {\n return { value: await pop(), done };\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(() => intervalEvent(counter++), 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":["Callable","Event","Unsubscribe","createEvent","createInterval","merge","removeListener","setTimeoutAsync","listeners","listener","index","indexOf","wasRemoved","splice","timeout","signal","Promise","resolve","timerId","setTimeout","addEventListener","clearTimeout","Function","constructor","func","Object","setPrototypeOf","prototype","_done","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","unsubscribe","promise","reject","finally","u","settle","allSettled","settled","Symbol","asyncIterator","queue","hasNextEvent","emitEvent","target","action","next","shift","return","pipe","generator","generatedValue","result","catch","e","filter","first","filteredEvent","mapper","reduce","reducer","init","hasInit","expand","expander","values","orchestrate","conductor","initialized","lastValue","unsubscribeConductor","orchestratedEvent","debounce","interval","controller","AbortController","abort","complete","throttle","pendingValue","hasPendingValue","now","Date","batch","valueEvent","pop","stop","stopped","events","mergedEvent","counter","intervalEvent","clearInterval","setInterval"],"mappings":"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"}
|
package/build/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
export interface Fn<A extends unknown[], R> {
|
|
2
|
+
(...args: A): R;
|
|
3
|
+
}
|
|
1
4
|
export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;
|
|
2
|
-
export interface Callback<R = void> {
|
|
3
|
-
(): MaybePromise<R>;
|
|
5
|
+
export interface Callback<R = void> extends Fn<[], MaybePromise<R>> {
|
|
4
6
|
}
|
|
5
|
-
export interface Listener<T, R = unknown> {
|
|
6
|
-
(event: T): MaybePromise<R | void>;
|
|
7
|
+
export interface Listener<T, R = unknown> extends Fn<[T], MaybePromise<R | void>> {
|
|
7
8
|
}
|
|
8
9
|
export interface FilterFunction<T> {
|
|
9
10
|
(event: T): MaybePromise<boolean>;
|
|
@@ -26,8 +27,8 @@ export interface Expander<T, R> {
|
|
|
26
27
|
* This method ensures that the listener is fully unregistered, preventing any residual calls to a potentially deprecated handler.
|
|
27
28
|
*
|
|
28
29
|
* @internal
|
|
29
|
-
* @param {
|
|
30
|
-
* @param {
|
|
30
|
+
* @param {unknown[]} listeners - The array of listeners from which to remove the listener.
|
|
31
|
+
* @param {unknown} listener - The listener function to remove from the list of listeners.
|
|
31
32
|
* @returns {boolean} - Returns `true` if the listener was found and removed, `false` otherwise.
|
|
32
33
|
*
|
|
33
34
|
* @template T - The type of the event that listeners are associated with.
|
|
@@ -59,22 +60,25 @@ export declare const removeListener: (listeners: unknown[], listener: unknown) =
|
|
|
59
60
|
* ```
|
|
60
61
|
*/
|
|
61
62
|
export declare const setTimeoutAsync: (timeout: number, signal?: AbortSignal) => Promise<boolean>;
|
|
63
|
+
/**
|
|
64
|
+
* @internal
|
|
65
|
+
*/
|
|
66
|
+
export interface Callable<T extends unknown[], R> {
|
|
67
|
+
(...args: T): R;
|
|
68
|
+
}
|
|
62
69
|
/**
|
|
63
70
|
* An abstract class that extends the built-in Function class. It allows instances of the class
|
|
64
71
|
* to be called as functions. When an instance of Callable is called as a function, it will
|
|
65
72
|
* call the function passed to its constructor with the same arguments.
|
|
66
73
|
* @internal
|
|
67
74
|
*/
|
|
68
|
-
export declare abstract class Callable extends Function {
|
|
75
|
+
export declare abstract class Callable<T, R> extends Function {
|
|
69
76
|
constructor(func: Function);
|
|
70
77
|
}
|
|
71
|
-
export interface Unsubscribe {
|
|
72
|
-
(): MaybePromise<void>;
|
|
73
|
-
}
|
|
74
78
|
/**
|
|
75
79
|
* @internal
|
|
76
80
|
*/
|
|
77
|
-
export declare class Unsubscribe extends Callable {
|
|
81
|
+
export declare class Unsubscribe extends Callable<[], MaybePromise<void>> {
|
|
78
82
|
private _done;
|
|
79
83
|
constructor(callback: Callback);
|
|
80
84
|
get done(): boolean;
|
|
@@ -82,21 +86,18 @@ export declare class Unsubscribe extends Callable {
|
|
|
82
86
|
post(callback: Callback): Unsubscribe;
|
|
83
87
|
countdown(count: number): Unsubscribe;
|
|
84
88
|
}
|
|
85
|
-
export interface Event<T = any, R = any> {
|
|
86
|
-
(event: T): Promise<(void | Awaited<R>)[]>;
|
|
87
|
-
}
|
|
88
89
|
/**
|
|
89
90
|
* A class representing an anonymous event that can be listened to or triggered.
|
|
90
91
|
*
|
|
91
92
|
* @template T - The event type.
|
|
92
93
|
* @template R - The return type of the event.
|
|
93
94
|
*/
|
|
94
|
-
export declare class Event<T, R> extends Callable implements AsyncIterable<T>, PromiseLike<T> {
|
|
95
|
+
export declare class Event<T = unknown, R = unknown> extends Callable<[T], Promise<(void | Awaited<R>)[]>> implements AsyncIterable<T>, PromiseLike<T> {
|
|
95
96
|
/**
|
|
96
97
|
* The array of listeners for the event.
|
|
97
98
|
*/
|
|
98
99
|
private listeners;
|
|
99
|
-
private
|
|
100
|
+
private hooks;
|
|
100
101
|
private _disposed;
|
|
101
102
|
/**
|
|
102
103
|
* A function that disposes of the event and its listeners.
|
|
@@ -205,7 +206,7 @@ export declare class Event<T, R> extends Callable implements AsyncIterable<T>, P
|
|
|
205
206
|
once(listener: Listener<T, R>): Unsubscribe;
|
|
206
207
|
/**
|
|
207
208
|
* Removes all listeners from the event, effectively resetting it. This is useful when you need to
|
|
208
|
-
* cleanly dispose of all event handlers to prevent memory leaks or unwanted
|
|
209
|
+
* cleanly dispose of all event handlers to prevent memory leaks or unwanted triggers after certain conditions.
|
|
209
210
|
*
|
|
210
211
|
* @returns {this} The instance of the event, allowing for method chaining.
|
|
211
212
|
*
|
package/build/index.js
CHANGED
|
@@ -51,25 +51,25 @@ export class Unsubscribe extends Callable {
|
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
var
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
54
|
+
var HookType = /*#__PURE__*/ function(HookType) {
|
|
55
|
+
HookType[HookType["Add"] = 0] = "Add";
|
|
56
|
+
HookType[HookType["Remove"] = 1] = "Remove";
|
|
57
|
+
return HookType;
|
|
58
|
+
}(HookType || {});
|
|
59
59
|
export class Event extends Callable {
|
|
60
60
|
listeners;
|
|
61
|
-
|
|
61
|
+
hooks = [];
|
|
62
62
|
_disposed = false;
|
|
63
63
|
dispose;
|
|
64
64
|
constructor(dispose){
|
|
65
65
|
const listeners = [];
|
|
66
66
|
super((value)=>Promise.all(listeners.map(async (listener)=>listener(await value))));
|
|
67
67
|
this.listeners = listeners;
|
|
68
|
-
this.dispose =
|
|
68
|
+
this.dispose = ()=>{
|
|
69
69
|
this._disposed = true;
|
|
70
70
|
void this.clear();
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
void this._error?.dispose();
|
|
72
|
+
void dispose?.();
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
75
|
_error;
|
|
@@ -89,18 +89,18 @@ export class Event extends Callable {
|
|
|
89
89
|
return this.listeners.indexOf(listener) !== -1;
|
|
90
90
|
}
|
|
91
91
|
off(listener) {
|
|
92
|
-
if (removeListener(this.listeners, listener) && this.
|
|
92
|
+
if (removeListener(this.listeners, listener) && this.hooks.length) {
|
|
93
93
|
[
|
|
94
|
-
...this.
|
|
94
|
+
...this.hooks
|
|
95
95
|
].forEach((spy)=>spy(listener, 1));
|
|
96
96
|
}
|
|
97
97
|
return this;
|
|
98
98
|
}
|
|
99
99
|
on(listener) {
|
|
100
100
|
this.listeners.push(listener);
|
|
101
|
-
if (this.
|
|
101
|
+
if (this.hooks.length) {
|
|
102
102
|
[
|
|
103
|
-
...this.
|
|
103
|
+
...this.hooks
|
|
104
104
|
].forEach((spy)=>spy(listener, 0));
|
|
105
105
|
}
|
|
106
106
|
return new Unsubscribe(()=>{
|
|
@@ -116,9 +116,9 @@ export class Event extends Callable {
|
|
|
116
116
|
}
|
|
117
117
|
clear() {
|
|
118
118
|
this.listeners.splice(0);
|
|
119
|
-
if (this.
|
|
119
|
+
if (this.hooks.length) {
|
|
120
120
|
[
|
|
121
|
-
...this.
|
|
121
|
+
...this.hooks
|
|
122
122
|
].forEach((spy)=>spy(undefined, 1));
|
|
123
123
|
}
|
|
124
124
|
return this;
|
|
@@ -143,36 +143,33 @@ export class Event extends Callable {
|
|
|
143
143
|
}
|
|
144
144
|
[Symbol.asyncIterator]() {
|
|
145
145
|
const queue = [];
|
|
146
|
-
const
|
|
146
|
+
const hasNextEvent = new Event();
|
|
147
147
|
const emitEvent = async (value)=>{
|
|
148
148
|
queue.push(value);
|
|
149
|
-
await
|
|
149
|
+
await hasNextEvent(true);
|
|
150
150
|
};
|
|
151
151
|
const unsubscribe = this.on(emitEvent).pre(async ()=>{
|
|
152
|
-
|
|
152
|
+
await hasNextEvent.dispose();
|
|
153
|
+
removeListener(this.hooks, spy);
|
|
153
154
|
queue.splice(0);
|
|
154
|
-
await doneEvent.dispose();
|
|
155
155
|
});
|
|
156
156
|
const spy = (target = emitEvent, action)=>{
|
|
157
157
|
if (target === emitEvent && action === 1) {
|
|
158
|
-
void
|
|
158
|
+
void hasNextEvent(false);
|
|
159
159
|
void unsubscribe();
|
|
160
160
|
}
|
|
161
161
|
};
|
|
162
|
-
this.
|
|
162
|
+
this.hooks.push(spy);
|
|
163
163
|
return {
|
|
164
164
|
async next () {
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
value: queue.shift(),
|
|
174
|
-
done: false
|
|
175
|
-
};
|
|
165
|
+
if (!hasNextEvent.disposed) {
|
|
166
|
+
const next = queue.length || await hasNextEvent;
|
|
167
|
+
if (next) {
|
|
168
|
+
return {
|
|
169
|
+
value: queue.shift(),
|
|
170
|
+
done: false
|
|
171
|
+
};
|
|
172
|
+
}
|
|
176
173
|
}
|
|
177
174
|
return {
|
|
178
175
|
value: undefined,
|
|
@@ -182,8 +179,8 @@ export class Event extends Callable {
|
|
|
182
179
|
async return (value) {
|
|
183
180
|
await unsubscribe();
|
|
184
181
|
return {
|
|
185
|
-
|
|
186
|
-
|
|
182
|
+
value,
|
|
183
|
+
done: true
|
|
187
184
|
};
|
|
188
185
|
}
|
|
189
186
|
};
|
|
@@ -199,14 +196,14 @@ export class Event extends Callable {
|
|
|
199
196
|
}
|
|
200
197
|
};
|
|
201
198
|
const unsubscribe = this.on(emitEvent).pre(()=>{
|
|
202
|
-
removeListener(this.
|
|
199
|
+
removeListener(this.hooks, spy);
|
|
203
200
|
});
|
|
204
201
|
const spy = (target = emitEvent, action)=>{
|
|
205
202
|
if (target === emitEvent && action === 1) {
|
|
206
203
|
void unsubscribe();
|
|
207
204
|
}
|
|
208
205
|
};
|
|
209
|
-
this.
|
|
206
|
+
this.hooks.push(spy);
|
|
210
207
|
const result = new Event(unsubscribe);
|
|
211
208
|
return result;
|
|
212
209
|
}
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface Callback<R = void> {\n (): MaybePromise<R>;\n}\n\nexport interface Listener<T, R = unknown> {\n (event: T): MaybePromise<R | void>;\n}\n\nexport interface FilterFunction<T> {\n (event: T): MaybePromise<boolean>;\n}\n\nexport interface Predicate<T, P extends T> {\n (event: T): event is P;\n}\n\nexport type Filter<T, P extends T> = Predicate<T, P> | FilterFunction<T>;\n\nexport interface Mapper<T, R> {\n (event: T): MaybePromise<R>;\n}\n\nexport interface Reducer<T, R> {\n (result: R, event: T): MaybePromise<R>;\n}\n\nexport interface Expander<T, R> {\n (event: T): MaybePromise<R>;\n}\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 {Listener<T, R>[]} listeners - The array of listeners from which to remove the listener.\n * @param {Listener<T, R>} 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 * An abstract class that extends the built-in Function class. It allows instances of the class\n * to be called as functions. When an instance of Callable is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\nexport abstract class Callable extends Function {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n constructor(func: Function) {\n super();\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n\nexport interface Unsubscribe {\n (): MaybePromise<void>;\n}\n\n/**\n * @internal\n */\nexport class Unsubscribe extends Callable {\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\nexport interface Event<T = any, R = any> {\n (event: T): Promise<(void | Awaited<R>)[]>;\n}\n\nenum SpyType {\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, R> extends Callable implements AsyncIterable<T>, PromiseLike<T> {\n /**\n * The array of listeners for the event.\n */\n private listeners: Listener<T, R>[];\n\n private spies: Array<(listener: Listener<T, R> | void, type: SpyType) => 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 this.listeners = listeners;\n\n this.dispose = async () => {\n this._disposed = true;\n void this.clear();\n await this._error?.dispose();\n await 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.spies.length) {\n [...this.spies].forEach((spy) => spy(listener, SpyType.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.spies.length) {\n [...this.spies].forEach((spy) => spy(listener, SpyType.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 triggerings 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.spies.length) {\n [...this.spies].forEach((spy) => spy(undefined, SpyType.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 | undefined,\n onrejected?: ((reason: unknown) => ERR | PromiseLike<ERR>) | null | undefined,\n ): Promise<OK | ERR> {\n const unsubscribe: Unsubscribe[] = [];\n const promise = new Promise<T>((resolve, reject) => {\n unsubscribe.push(this.once(resolve));\n unsubscribe.push(this.error.once(reject));\n });\n\n return promise.then(onfulfilled, onrejected).finally(async () => {\n await Promise.all(unsubscribe.map((u) => u()));\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 queue: T[] = [];\n const doneEvent = new Event<boolean>();\n const emitEvent = async (value: T) => {\n queue.push(value);\n await doneEvent(false);\n };\n const unsubscribe = this.on(emitEvent).pre(async () => {\n removeListener(this.spies, spy);\n queue.splice(0);\n await doneEvent.dispose();\n });\n\n const spy: (typeof this.spies)[number] = (target = emitEvent, action) => {\n if (target === emitEvent && action === SpyType.Remove) {\n void doneEvent(true);\n void unsubscribe();\n }\n };\n\n this.spies.push(spy);\n return {\n async next() {\n if (queue.length) {\n return { value: queue.shift()!, done: false };\n }\n if (!(await doneEvent)) {\n return { value: queue.shift()!, done: false };\n }\n return { value: undefined, done: true };\n },\n async return(value: unknown) {\n await unsubscribe();\n return { done: true, value };\n },\n };\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.spies, spy);\n });\n\n const spy: (typeof this.spies)[number] = (target = emitEvent, action) => {\n if (target === emitEvent && action === SpyType.Remove) {\n void unsubscribe();\n }\n };\n this.spies.push(spy);\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(async (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 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 queue: T[] = [];\n let done = false;\n const valueEvent = new Event<void>();\n\n const unsubscribe = this.on(async (value) => {\n queue.push(value);\n await valueEvent();\n });\n\n const pop = async () => {\n if (!queue.length) {\n await valueEvent;\n }\n return queue.shift()!;\n };\n const stop = async () => {\n await unsubscribe();\n done = true;\n await valueEvent();\n };\n\n return {\n pop,\n stop,\n get stopped() {\n return done;\n },\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null | undefined,\n ): Promise<TResult1 | TResult2> {\n return this.pop().then(onfulfilled, onrejected);\n },\n [Symbol.asyncIterator]() {\n return {\n next: async () => {\n return { value: await pop(), done };\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(() => intervalEvent(counter++), 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":["removeListener","listeners","listener","index","indexOf","wasRemoved","splice","setTimeoutAsync","timeout","signal","Promise","resolve","timerId","setTimeout","addEventListener","clearTimeout","Callable","Function","constructor","func","Object","setPrototypeOf","prototype","Unsubscribe","_done","callback","done","pre","post","countdown","count","SpyType","Event","spies","_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","unsubscribe","promise","reject","finally","u","settle","allSettled","settled","Symbol","asyncIterator","queue","doneEvent","emitEvent","target","action","next","shift","return","pipe","generator","generatedValue","result","catch","e","filter","first","filteredEvent","mapper","reduce","reducer","init","hasInit","expand","expander","values","orchestrate","conductor","initialized","lastValue","unsubscribeConductor","orchestratedEvent","debounce","interval","controller","AbortController","abort","complete","throttle","pendingValue","hasPendingValue","now","Date","batch","valueEvent","pop","stop","stopped","merge","events","mergedEvent","createInterval","counter","intervalEvent","clearInterval","setInterval","createEvent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export interface Fn<A extends unknown[], R> {\n (...args: A): R;\n}\n\nexport type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface Callback<R = void> extends Fn<[], MaybePromise<R>> {}\n\nexport interface Listener<T, R = unknown> extends Fn<[T], MaybePromise<R | void>> {}\n\nexport interface FilterFunction<T> {\n (event: T): MaybePromise<boolean>;\n}\n\nexport interface Predicate<T, P extends T> {\n (event: T): event is P;\n}\n\nexport type Filter<T, P extends T> = Predicate<T, P> | FilterFunction<T>;\n\nexport interface Mapper<T, R> {\n (event: T): MaybePromise<R>;\n}\n\nexport interface Reducer<T, R> {\n (result: R, event: T): MaybePromise<R>;\n}\n\nexport interface Expander<T, R> {\n (event: T): MaybePromise<R>;\n}\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 Callable<T extends unknown[], R> {\n (...args: T): R;\n}\n\n/**\n * An abstract class that extends the built-in Function class. It allows instances of the class\n * to be called as functions. When an instance of Callable is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport abstract class Callable<T, R> extends Function {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n constructor(func: Function) {\n super();\n return Object.setPrototypeOf(func, new.target.prototype);\n }\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 | undefined,\n onrejected?: ((reason: unknown) => ERR | PromiseLike<ERR>) | null | undefined,\n ): Promise<OK | ERR> {\n const unsubscribe: Unsubscribe[] = [];\n const promise = new Promise<T>((resolve, reject) => {\n unsubscribe.push(this.once(resolve));\n unsubscribe.push(this.error.once(reject));\n });\n\n return promise.then(onfulfilled, onrejected).finally(async () => {\n await Promise.all(unsubscribe.map((u) => u()));\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 queue: T[] = [];\n const hasNextEvent = new Event<boolean>();\n const emitEvent = async (value: T) => {\n queue.push(value);\n await hasNextEvent(true);\n };\n const unsubscribe = this.on(emitEvent).pre(async () => {\n await hasNextEvent.dispose();\n removeListener(this.hooks, spy);\n queue.splice(0);\n });\n\n const spy: (typeof this.hooks)[number] = (target = emitEvent, action) => {\n if (target === emitEvent && action === HookType.Remove) {\n void hasNextEvent(false);\n void unsubscribe();\n }\n };\n\n this.hooks.push(spy);\n return {\n async next() {\n if (!hasNextEvent.disposed) {\n const next = queue.length || (await hasNextEvent);\n if (next) {\n return { value: queue.shift()!, done: false };\n }\n }\n return { value: undefined, done: true };\n },\n async return(value: unknown) {\n await unsubscribe();\n return { value, done: true };\n },\n };\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, spy);\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 this.hooks.push(spy);\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(async (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 queue: T[] = [];\n let done = false;\n const valueEvent = new Event<void>();\n\n const unsubscribe = this.on(async (value) => {\n queue.push(value);\n await valueEvent();\n });\n\n const pop = async () => {\n if (!queue.length) {\n await valueEvent;\n }\n return queue.shift()!;\n };\n const stop = async () => {\n await unsubscribe();\n done = true;\n await valueEvent();\n };\n\n return {\n pop,\n stop,\n get stopped() {\n return done;\n },\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null | undefined,\n ): Promise<TResult1 | TResult2> {\n return this.pop().then(onfulfilled, onrejected);\n },\n [Symbol.asyncIterator]() {\n return {\n next: async () => {\n return { value: await pop(), done };\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(() => intervalEvent(counter++), 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":["removeListener","listeners","listener","index","indexOf","wasRemoved","splice","setTimeoutAsync","timeout","signal","Promise","resolve","timerId","setTimeout","addEventListener","clearTimeout","Callable","Function","constructor","func","Object","setPrototypeOf","prototype","Unsubscribe","_done","callback","done","pre","post","countdown","count","HookType","Event","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","unsubscribe","promise","reject","finally","u","settle","allSettled","settled","Symbol","asyncIterator","queue","hasNextEvent","emitEvent","target","action","next","shift","return","pipe","generator","generatedValue","result","catch","e","filter","first","filteredEvent","mapper","reduce","reducer","init","hasInit","expand","expander","values","orchestrate","conductor","initialized","lastValue","unsubscribeConductor","orchestratedEvent","debounce","interval","controller","AbortController","abort","complete","throttle","pendingValue","hasPendingValue","now","Date","batch","valueEvent","pop","stop","stopped","merge","events","mergedEvent","createInterval","counter","intervalEvent","clearInterval","setInterval","createEvent"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evnty",
|
|
3
3
|
"description": "0-Deps, simple, fast, for browser and node js reactive anonymous event library",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
7
7
|
"main": "build/index.cjs",
|
|
@@ -16,18 +16,6 @@
|
|
|
16
16
|
"src/__tests__/example.js"
|
|
17
17
|
],
|
|
18
18
|
"sideEffects": false,
|
|
19
|
-
"scripts": {
|
|
20
|
-
"build": "rm -rf build && inop src build -i __tests__ -i *.tmp.ts && tsc --declaration --emitDeclarationOnly",
|
|
21
|
-
"test": "jest",
|
|
22
|
-
"test:build": "node src/__tests__/index.cjs && node src/__tests__/index.mjs",
|
|
23
|
-
"lint": "eslint src",
|
|
24
|
-
"docs:build": "vuepress build docs",
|
|
25
|
-
"docs:clean-dev": "vuepress dev docs --clean-cache",
|
|
26
|
-
"docs:dev": "vuepress dev docs",
|
|
27
|
-
"docs:gen": "node --loader ts-node/esm ./scripts/docgen.ts src/index.ts",
|
|
28
|
-
"docs:update-package": "pnpm dlx vp-update",
|
|
29
|
-
"prepare": "husky"
|
|
30
|
-
},
|
|
31
19
|
"repository": {
|
|
32
20
|
"type": "git",
|
|
33
21
|
"url": "git+https://github.com/3axap4eHko/evnty.git"
|
|
@@ -85,5 +73,15 @@
|
|
|
85
73
|
"vue": "^3.5.13",
|
|
86
74
|
"vuepress": "2.0.0-rc.18"
|
|
87
75
|
},
|
|
88
|
-
"
|
|
89
|
-
|
|
76
|
+
"scripts": {
|
|
77
|
+
"build": "rm -rf build && inop src build -i __tests__ -i *.tmp.ts && tsc --declaration --emitDeclarationOnly",
|
|
78
|
+
"test": "jest",
|
|
79
|
+
"test:build": "node src/__tests__/index.cjs && node src/__tests__/index.mjs",
|
|
80
|
+
"lint": "eslint src",
|
|
81
|
+
"docs:build": "vuepress build docs",
|
|
82
|
+
"docs:clean-dev": "vuepress dev docs --clean-cache",
|
|
83
|
+
"docs:dev": "vuepress dev docs",
|
|
84
|
+
"docs:gen": "node --loader ts-node/esm ./scripts/docgen.ts src/index.ts",
|
|
85
|
+
"docs:update-package": "pnpm dlx vp-update"
|
|
86
|
+
}
|
|
87
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
export interface Fn<A extends unknown[], R> {
|
|
2
|
+
(...args: A): R;
|
|
3
|
+
}
|
|
4
|
+
|
|
1
5
|
export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;
|
|
2
6
|
|
|
3
|
-
export interface Callback<R = void> {
|
|
4
|
-
(): MaybePromise<R>;
|
|
5
|
-
}
|
|
7
|
+
export interface Callback<R = void> extends Fn<[], MaybePromise<R>> {}
|
|
6
8
|
|
|
7
|
-
export interface Listener<T, R = unknown> {
|
|
8
|
-
(event: T): MaybePromise<R | void>;
|
|
9
|
-
}
|
|
9
|
+
export interface Listener<T, R = unknown> extends Fn<[T], MaybePromise<R | void>> {}
|
|
10
10
|
|
|
11
11
|
export interface FilterFunction<T> {
|
|
12
12
|
(event: T): MaybePromise<boolean>;
|
|
@@ -35,8 +35,8 @@ export interface Expander<T, R> {
|
|
|
35
35
|
* This method ensures that the listener is fully unregistered, preventing any residual calls to a potentially deprecated handler.
|
|
36
36
|
*
|
|
37
37
|
* @internal
|
|
38
|
-
* @param {
|
|
39
|
-
* @param {
|
|
38
|
+
* @param {unknown[]} listeners - The array of listeners from which to remove the listener.
|
|
39
|
+
* @param {unknown} listener - The listener function to remove from the list of listeners.
|
|
40
40
|
* @returns {boolean} - Returns `true` if the listener was found and removed, `false` otherwise.
|
|
41
41
|
*
|
|
42
42
|
* @template T - The type of the event that listeners are associated with.
|
|
@@ -85,13 +85,21 @@ export const setTimeoutAsync = (timeout: number, signal?: AbortSignal): Promise<
|
|
|
85
85
|
});
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
+
/**
|
|
89
|
+
* @internal
|
|
90
|
+
*/
|
|
91
|
+
export interface Callable<T extends unknown[], R> {
|
|
92
|
+
(...args: T): R;
|
|
93
|
+
}
|
|
94
|
+
|
|
88
95
|
/**
|
|
89
96
|
* An abstract class that extends the built-in Function class. It allows instances of the class
|
|
90
97
|
* to be called as functions. When an instance of Callable is called as a function, it will
|
|
91
98
|
* call the function passed to its constructor with the same arguments.
|
|
92
99
|
* @internal
|
|
93
100
|
*/
|
|
94
|
-
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
102
|
+
export abstract class Callable<T, R> extends Function {
|
|
95
103
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
96
104
|
constructor(func: Function) {
|
|
97
105
|
super();
|
|
@@ -99,14 +107,10 @@ export abstract class Callable extends Function {
|
|
|
99
107
|
}
|
|
100
108
|
}
|
|
101
109
|
|
|
102
|
-
export interface Unsubscribe {
|
|
103
|
-
(): MaybePromise<void>;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
110
|
/**
|
|
107
111
|
* @internal
|
|
108
112
|
*/
|
|
109
|
-
export class Unsubscribe extends Callable {
|
|
113
|
+
export class Unsubscribe extends Callable<[], MaybePromise<void>> {
|
|
110
114
|
private _done = false;
|
|
111
115
|
|
|
112
116
|
constructor(callback: Callback) {
|
|
@@ -143,11 +147,7 @@ export class Unsubscribe extends Callable {
|
|
|
143
147
|
}
|
|
144
148
|
}
|
|
145
149
|
|
|
146
|
-
|
|
147
|
-
(event: T): Promise<(void | Awaited<R>)[]>;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
enum SpyType {
|
|
150
|
+
enum HookType {
|
|
151
151
|
Add,
|
|
152
152
|
Remove,
|
|
153
153
|
}
|
|
@@ -158,13 +158,13 @@ enum SpyType {
|
|
|
158
158
|
* @template T - The event type.
|
|
159
159
|
* @template R - The return type of the event.
|
|
160
160
|
*/
|
|
161
|
-
export class Event<T, R> extends Callable implements AsyncIterable<T>, PromiseLike<T> {
|
|
161
|
+
export class Event<T = unknown, R = unknown> extends Callable<[T], Promise<(void | Awaited<R>)[]>> implements AsyncIterable<T>, PromiseLike<T> {
|
|
162
162
|
/**
|
|
163
163
|
* The array of listeners for the event.
|
|
164
164
|
*/
|
|
165
165
|
private listeners: Listener<T, R>[];
|
|
166
166
|
|
|
167
|
-
private
|
|
167
|
+
private hooks: Array<(listener: Listener<T, R> | void, type: HookType) => void> = [];
|
|
168
168
|
|
|
169
169
|
private _disposed = false;
|
|
170
170
|
|
|
@@ -188,13 +188,14 @@ export class Event<T, R> extends Callable implements AsyncIterable<T>, PromiseLi
|
|
|
188
188
|
const listeners: Listener<T, R>[] = [];
|
|
189
189
|
// passes listeners exceptions to catch method
|
|
190
190
|
super((value: T): Promise<(void | Awaited<R>)[]> => Promise.all(listeners.map(async (listener) => listener(await value))));
|
|
191
|
+
|
|
191
192
|
this.listeners = listeners;
|
|
192
193
|
|
|
193
|
-
this.dispose =
|
|
194
|
+
this.dispose = () => {
|
|
194
195
|
this._disposed = true;
|
|
195
196
|
void this.clear();
|
|
196
|
-
|
|
197
|
-
|
|
197
|
+
void this._error?.dispose();
|
|
198
|
+
void dispose?.();
|
|
198
199
|
};
|
|
199
200
|
}
|
|
200
201
|
|
|
@@ -273,8 +274,8 @@ export class Event<T, R> extends Callable implements AsyncIterable<T>, PromiseLi
|
|
|
273
274
|
* ```
|
|
274
275
|
*/
|
|
275
276
|
off(listener: Listener<T, R>): this {
|
|
276
|
-
if (removeListener(this.listeners, listener) && this.
|
|
277
|
-
[...this.
|
|
277
|
+
if (removeListener(this.listeners, listener) && this.hooks.length) {
|
|
278
|
+
[...this.hooks].forEach((spy) => spy(listener, HookType.Remove));
|
|
278
279
|
}
|
|
279
280
|
return this;
|
|
280
281
|
}
|
|
@@ -295,8 +296,8 @@ export class Event<T, R> extends Callable implements AsyncIterable<T>, PromiseLi
|
|
|
295
296
|
*/
|
|
296
297
|
on(listener: Listener<T, R>): Unsubscribe {
|
|
297
298
|
this.listeners.push(listener);
|
|
298
|
-
if (this.
|
|
299
|
-
[...this.
|
|
299
|
+
if (this.hooks.length) {
|
|
300
|
+
[...this.hooks].forEach((spy) => spy(listener, HookType.Add));
|
|
300
301
|
}
|
|
301
302
|
return new Unsubscribe(() => {
|
|
302
303
|
void this.off(listener);
|
|
@@ -327,7 +328,7 @@ export class Event<T, R> extends Callable implements AsyncIterable<T>, PromiseLi
|
|
|
327
328
|
|
|
328
329
|
/**
|
|
329
330
|
* Removes all listeners from the event, effectively resetting it. This is useful when you need to
|
|
330
|
-
* cleanly dispose of all event handlers to prevent memory leaks or unwanted
|
|
331
|
+
* cleanly dispose of all event handlers to prevent memory leaks or unwanted triggers after certain conditions.
|
|
331
332
|
*
|
|
332
333
|
* @returns {this} The instance of the event, allowing for method chaining.
|
|
333
334
|
*
|
|
@@ -339,8 +340,8 @@ export class Event<T, R> extends Callable implements AsyncIterable<T>, PromiseLi
|
|
|
339
340
|
*/
|
|
340
341
|
clear(): this {
|
|
341
342
|
this.listeners.splice(0);
|
|
342
|
-
if (this.
|
|
343
|
-
[...this.
|
|
343
|
+
if (this.hooks.length) {
|
|
344
|
+
[...this.hooks].forEach((spy) => spy(undefined, HookType.Remove));
|
|
344
345
|
}
|
|
345
346
|
return this;
|
|
346
347
|
}
|
|
@@ -422,38 +423,38 @@ export class Event<T, R> extends Callable implements AsyncIterable<T>, PromiseLi
|
|
|
422
423
|
*/
|
|
423
424
|
[Symbol.asyncIterator](): AsyncIterator<T> {
|
|
424
425
|
const queue: T[] = [];
|
|
425
|
-
const
|
|
426
|
+
const hasNextEvent = new Event<boolean>();
|
|
426
427
|
const emitEvent = async (value: T) => {
|
|
427
428
|
queue.push(value);
|
|
428
|
-
await
|
|
429
|
+
await hasNextEvent(true);
|
|
429
430
|
};
|
|
430
431
|
const unsubscribe = this.on(emitEvent).pre(async () => {
|
|
431
|
-
|
|
432
|
+
await hasNextEvent.dispose();
|
|
433
|
+
removeListener(this.hooks, spy);
|
|
432
434
|
queue.splice(0);
|
|
433
|
-
await doneEvent.dispose();
|
|
434
435
|
});
|
|
435
436
|
|
|
436
|
-
const spy: (typeof this.
|
|
437
|
-
if (target === emitEvent && action ===
|
|
438
|
-
void
|
|
437
|
+
const spy: (typeof this.hooks)[number] = (target = emitEvent, action) => {
|
|
438
|
+
if (target === emitEvent && action === HookType.Remove) {
|
|
439
|
+
void hasNextEvent(false);
|
|
439
440
|
void unsubscribe();
|
|
440
441
|
}
|
|
441
442
|
};
|
|
442
443
|
|
|
443
|
-
this.
|
|
444
|
+
this.hooks.push(spy);
|
|
444
445
|
return {
|
|
445
446
|
async next() {
|
|
446
|
-
if (
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
447
|
+
if (!hasNextEvent.disposed) {
|
|
448
|
+
const next = queue.length || (await hasNextEvent);
|
|
449
|
+
if (next) {
|
|
450
|
+
return { value: queue.shift()!, done: false };
|
|
451
|
+
}
|
|
451
452
|
}
|
|
452
453
|
return { value: undefined, done: true };
|
|
453
454
|
},
|
|
454
455
|
async return(value: unknown) {
|
|
455
456
|
await unsubscribe();
|
|
456
|
-
return { done: true
|
|
457
|
+
return { value, done: true };
|
|
457
458
|
},
|
|
458
459
|
};
|
|
459
460
|
}
|
|
@@ -491,15 +492,15 @@ export class Event<T, R> extends Callable implements AsyncIterable<T>, PromiseLi
|
|
|
491
492
|
};
|
|
492
493
|
|
|
493
494
|
const unsubscribe = this.on(emitEvent).pre(() => {
|
|
494
|
-
removeListener(this.
|
|
495
|
+
removeListener(this.hooks, spy);
|
|
495
496
|
});
|
|
496
497
|
|
|
497
|
-
const spy: (typeof this.
|
|
498
|
-
if (target === emitEvent && action ===
|
|
498
|
+
const spy: (typeof this.hooks)[number] = (target = emitEvent, action) => {
|
|
499
|
+
if (target === emitEvent && action === HookType.Remove) {
|
|
499
500
|
void unsubscribe();
|
|
500
501
|
}
|
|
501
502
|
};
|
|
502
|
-
this.
|
|
503
|
+
this.hooks.push(spy);
|
|
503
504
|
|
|
504
505
|
const result = new Event<PT, R>(unsubscribe);
|
|
505
506
|
return result;
|
|
@@ -706,6 +707,7 @@ export class Event<T, R> extends Callable implements AsyncIterable<T>, PromiseLi
|
|
|
706
707
|
});
|
|
707
708
|
|
|
708
709
|
const orchestratedEvent = new Event<T, R>(unsubscribe.post(unsubscribeConductor));
|
|
710
|
+
|
|
709
711
|
return orchestratedEvent;
|
|
710
712
|
}
|
|
711
713
|
/**
|