UNPKG

evnty

Version:

Async-first, reactive event handling library for complex event flows in browser and Node.js

1 lines 20.3 kB
{"version":3,"sources":["../src/utils.ts"],"sourcesContent":["import { Sequence } from './sequence.js';\nimport { AnyIterator, AnyIterable, MaybePromise } from './types.js';\n\n/**\n * @internal\n */\nexport function isThenable(value: unknown): value is PromiseLike<unknown> {\n return value !== null && typeof value === 'object' && typeof (value as PromiseLike<unknown>).then === 'function';\n}\n\n/**\n * @internal\n * A no-operation function. Useful as a default callback or placeholder.\n */\nexport const noop = () => {};\n\n/**\n * @internal\n * Returns the minimum value from an iterable, or a fallback if empty.\n */\nexport function min(values: Iterable<number>, fallback: number): number {\n let result = Infinity;\n for (const value of values) {\n if (value < result) result = value;\n }\n return result === Infinity ? fallback : result;\n}\n\n/**\n * @internal\n * Indicates which iterator method triggered a mapping operation.\n */\nexport enum MapIteratorType {\n /** The next() method was called */\n NEXT,\n /** The return() method was called */\n RETURN,\n /** The throw() method was called */\n THROW,\n}\n\n/**\n * @internal\n * A mapping function for transforming iterator results.\n * @template T - The input value type\n * @template U - The output value type\n * @template TReturn - The iterator return type\n */\nexport interface MapNext<T, U, TReturn> {\n (result: MaybePromise<IteratorResult<T, TReturn>>, type: MapIteratorType): MaybePromise<IteratorResult<U, TReturn>>;\n}\n\n/**\n * @internal\n * Wraps an iterator with a mapping function applied to each result.\n * @template U - The output value type\n * @template T - The input value type\n * @template TReturn - The iterator return type\n * @template TNext - The type passed to next()\n * @param iterator - The source iterator to wrap\n * @param map - The mapping function to apply to each result\n * @returns An async iterator with mapped results\n */\nexport const mapIterator = <U, T, TReturn, TNext>(iterator: AnyIterator<T, TReturn, TNext>, map: MapNext<T, U, TReturn>): AsyncIterator<U, TReturn, TNext> => {\n const subIterator: AsyncIterator<U, TReturn, TNext> = {\n next: async (...args: [] | [TNext]) => {\n const result = await iterator.next(...args);\n return map(result, MapIteratorType.NEXT);\n },\n };\n if (iterator.return) {\n subIterator.return = async (...args: [] | [TReturn]) => {\n const result = await iterator.return!(...args);\n return map(result, MapIteratorType.RETURN);\n };\n } else {\n subIterator.return = async (value: TReturn) => {\n return map({ done: true, value }, MapIteratorType.RETURN);\n };\n }\n if (iterator.throw) {\n subIterator.throw = async (...args: [] | [unknown]) => {\n const result = await iterator.throw!(...args);\n return map(result, MapIteratorType.THROW);\n };\n }\n\n return subIterator;\n};\n\n/**\n * Wraps an async iterable with abort signal support.\n * Each iteration creates a fresh iterator with scoped abort handling.\n * Listener is added at iteration start and removed on completion/abort/return.\n *\n * @template T - The yielded value type\n * @template TReturn - The return value type\n * @template TNext - The type passed to next()\n * @param iterable - The source async iterable to wrap\n * @param signal - AbortSignal to cancel iteration\n * @returns An async iterable with abort support\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n * const source = async function*() { yield 1; yield 2; yield 3; };\n *\n * for await (const value of abortableIterable(source(), controller.signal)) {\n * console.log(value);\n * if (value === 2) controller.abort();\n * }\n * ```\n */\nexport function abortableIterable<T, TReturn, TNext>(iterable: AsyncIterable<T, TReturn, TNext>, signal: AbortSignal): AsyncIterable<T, TReturn, TNext> {\n return {\n [Symbol.asyncIterator](): AsyncIterator<T, TReturn, TNext> {\n const iterator = iterable[Symbol.asyncIterator]();\n const { promise, resolve } = Promise.withResolvers<void>();\n const onAbort = () => resolve();\n let closed = false;\n\n const finish = (value?: TReturn): Promise<IteratorResult<T, TReturn>> => {\n if (closed) {\n return Promise.resolve({ done: true, value: value as TReturn });\n }\n closed = true;\n signal.removeEventListener('abort', onAbort);\n return iterator.return?.(value) ?? Promise.resolve({ done: true, value: value as TReturn });\n };\n\n if (signal.aborted) {\n onAbort();\n } else {\n signal.addEventListener('abort', onAbort);\n }\n\n const race = [promise, undefined] as unknown as [Promise<void>, Promise<IteratorResult<T, TReturn>>];\n\n return {\n async next(...args: [] | [TNext]): Promise<IteratorResult<T, TReturn>> {\n race[1] = iterator.next(...args);\n const result = await Promise.race(race);\n if (result === undefined) {\n void finish();\n return { done: true, value: undefined as TReturn };\n }\n if (result.done) {\n closed = true;\n signal.removeEventListener('abort', onAbort);\n }\n return result;\n },\n async return(value?: TReturn): Promise<IteratorResult<T, TReturn>> {\n return finish(value);\n },\n };\n },\n };\n}\n\n/**\n * Interface for creating iterable number sequences with various parameter combinations.\n * Supports infinite sequences, counted sequences, and sequences with custom start and step values.\n */\nexport interface Iterate {\n (): Iterable<number, void, unknown>;\n (count: number): Iterable<number, void, unknown>;\n (start: number, count: number): Iterable<number, void, unknown>;\n (start: number, count: number, step: number): Iterable<number, void, unknown>;\n}\n\n/**\n * Creates an iterable sequence of numbers with flexible parameters.\n * Can generate infinite sequences, finite sequences, or sequences with custom start and step values.\n *\n * @param args Variable arguments to configure the sequence:\n * - No args: Infinite sequence starting at 0 with step 1\n * - 1 arg (count): Sequence from 0 to count-1\n * - 2 args (start, count): Sequence starting at 'start' for 'count' iterations\n * - 3 args (start, count, step): Custom start, count, and step value\n * @returns An iterable that generates numbers according to the parameters\n *\n * @example\n * ```typescript\n * // Infinite sequence: 0, 1, 2, 3, ...\n * for (const n of iterate()) { }\n *\n * // Count only: 0, 1, 2, 3, 4\n * for (const n of iterate(5)) { }\n *\n * // Start and count: 10, 11, 12, 13, 14\n * for (const n of iterate(10, 5)) { }\n *\n * // Start, count, and step: 0, 2, 4, 6, 8\n * for (const n of iterate(0, 5, 2)) { }\n * ```\n */\nexport const iterate: Iterate = (startOrCount?: number, countWhenTwoArgs?: number, step: number = 1): Iterable<number, void, unknown> => {\n const hasStartArg = countWhenTwoArgs !== undefined;\n const start = hasStartArg ? startOrCount! : 0;\n const count = startOrCount === undefined ? Infinity : hasStartArg ? countWhenTwoArgs : startOrCount;\n\n return {\n [Symbol.iterator]() {\n let idx = 0;\n let current = start;\n return {\n next() {\n if (idx < count) {\n const value = current;\n current += step;\n idx++;\n return { value, done: false };\n }\n return { value: undefined, done: true };\n },\n return(value) {\n idx = count;\n return { value, done: true };\n },\n throw(error?: unknown) {\n idx = count;\n throw error;\n },\n } satisfies Iterator<number, void, unknown>;\n },\n };\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 = async (timeout: number, signal?: AbortSignal): Promise<boolean> => {\n if (signal?.aborted) {\n return false;\n }\n const { promise, resolve } = Promise.withResolvers<boolean>();\n const timerId = setTimeout(resolve, timeout, true);\n const onAbort = () => {\n clearTimeout(timerId);\n resolve(false);\n };\n signal?.addEventListener('abort', onAbort);\n\n return promise.finally(() => signal?.removeEventListener('abort', onAbort));\n};\n\n/**\n * Converts a synchronous iterable to an asynchronous iterable.\n * Wraps the sync iterator methods to return promises, enabling uniform async handling.\n *\n * @template T The type of values yielded by the iterator\n * @template TReturn The return type of the iterator\n * @template TNext The type of value that can be passed to next()\n * @param iterable A synchronous iterable to convert\n * @returns An async iterable that yields the same values as the input\n *\n * @example\n * ```typescript\n * const syncArray = [1, 2, 3, 4, 5];\n * const asyncIterable = toAsyncIterable(syncArray);\n *\n * for await (const value of asyncIterable) {\n * console.log(value); // 1, 2, 3, 4, 5\n * }\n * ```\n */\nexport const toAsyncIterable = <T, TReturn, TNext>(iterable: Iterable<T, TReturn, TNext>): AsyncIterable<T, TReturn, TNext> => {\n return {\n [Symbol.asyncIterator]() {\n const iterator = iterable[Symbol.iterator]();\n return {\n async next(...args: [TNext] | []) {\n return iterator.next(...args);\n },\n async return(maybeValue) {\n const value = await maybeValue;\n return iterator.return?.(value) ?? ({ value, done: true } as IteratorResult<T, TReturn>);\n },\n async throw(error) {\n if (iterator.throw) {\n return iterator.throw(error);\n }\n throw error;\n },\n } satisfies AsyncIterator<T, TReturn, TNext>;\n },\n };\n};\n\n/**\n * @internal\n * Pipes values from an async iterable through a generator transformation.\n * Applies a generator function to each value, yielding all resulting values.\n * Supports cancellation via AbortSignal for early termination.\n *\n * @template T The input value type\n * @template U The output value type\n * @param iterable The source async iterable\n * @param generatorFactory A factory that returns a generator function for transforming values\n * @param signal Optional AbortSignal to cancel the operation\n * @returns An async generator yielding transformed values\n *\n * @example\n * ```typescript\n * async function* source() {\n * yield 1; yield 2; yield 3;\n * }\n *\n * const doubled = pipe(source(), () => async function*(n) {\n * yield n * 2;\n * });\n *\n * for await (const value of doubled) {\n * console.log(value); // 2, 4, 6\n * }\n * ```\n */\nconst isAsyncIterable = <T, TReturn, TNext>(value: AnyIterable<T, TReturn, TNext>): value is AsyncIterable<T, TReturn, TNext> => {\n return typeof (value as AsyncIterable<T, TReturn, TNext>)[Symbol.asyncIterator] === 'function';\n};\n\n/**\n * @internal\n */\nexport async function* pipe<T, U>(\n iterable: AsyncIterable<T>,\n generatorFactory: () => (value: T) => AnyIterable<U, void, unknown>,\n signal?: AbortSignal,\n): AsyncGenerator<Awaited<U>, void, unknown> {\n const source = signal ? abortableIterable(iterable, signal) : iterable;\n const generator = generatorFactory();\n\n for await (const value of source) {\n const produced = generator(value);\n const subIterable = isAsyncIterable(produced) ? produced : toAsyncIterable(produced);\n const abortableSub = signal ? abortableIterable(subIterable, signal) : subIterable;\n\n for await (const subValue of abortableSub) {\n yield subValue;\n }\n }\n}\n\n/**\n * @internal\n * Merges multiple async iterables into a single stream.\n * Values are yielded as they become available from any source.\n * Completes when all sources complete; aborts all on error.\n * @template T - The value type yielded by all iterables\n * @param iterables - The async iterables to merge\n * @returns A merged async iterable\n */\nexport const mergeIterables = <T>(...iterables: AsyncIterable<T, void, unknown>[]): AsyncIterable<T, void, unknown> => {\n return {\n [Symbol.asyncIterator]() {\n if (iterables.length === 0) {\n return {\n next: async () => ({ value: undefined, done: true }),\n };\n }\n\n const exit = Symbol('mergeIterables.exit');\n const ctrl = new AbortController();\n const sequence = new Sequence<T>(ctrl.signal);\n let remaining = iterables.length;\n\n const pump = async (iterable: AsyncIterable<T, void, unknown>) => {\n try {\n for await (const value of abortableIterable(iterable, ctrl.signal)) {\n if (!sequence.emit(value)) {\n break;\n }\n }\n } catch (error) {\n ctrl.abort(error);\n } finally {\n remaining -= 1;\n if (remaining === 0 && !ctrl.signal.aborted) {\n ctrl.abort(exit);\n }\n }\n };\n\n for (const iterable of iterables) {\n void pump(iterable);\n }\n\n return {\n next: async () => {\n try {\n const value = await sequence.receive();\n return { value, done: false };\n } catch {\n if (ctrl.signal.aborted && ctrl.signal.reason === exit) {\n return { value: undefined, done: true };\n }\n throw ctrl.signal.reason;\n }\n },\n return: async () => {\n ctrl.abort(exit);\n return { value: undefined, done: true };\n },\n throw: async (error?: unknown) => {\n ctrl.abort(error);\n return { value: undefined, done: true };\n },\n };\n },\n };\n};\n"],"names":["MapIteratorType","abortableIterable","isThenable","iterate","mapIterator","mergeIterables","min","noop","pipe","setTimeoutAsync","toAsyncIterable","value","then","values","fallback","result","Infinity","iterator","map","subIterator","next","args","return","done","throw","iterable","signal","Symbol","asyncIterator","promise","resolve","Promise","withResolvers","onAbort","closed","finish","removeEventListener","aborted","addEventListener","race","undefined","startOrCount","countWhenTwoArgs","step","hasStartArg","start","count","idx","current","error","timeout","timerId","setTimeout","clearTimeout","finally","maybeValue","isAsyncIterable","generatorFactory","source","generator","produced","subIterable","abortableSub","subValue","iterables","length","exit","ctrl","AbortController","sequence","Sequence","remaining","pump","emit","abort","receive","reason"],"mappings":"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"}