evnty
Version:
Async-first, reactive event handling library for complex event flows in browser and Node.js
1 lines • 8.42 kB
Source Map (JSON)
{"version":3,"sources":["../src/dispatch-result.ts"],"sourcesContent":["import { Fn, MaybePromise } from './types.js';\nimport { isThenable, noop } from './utils.js';\n\nconst ERR_BRAND = Symbol.for('evnty.ResultError');\n\n/**\n * @internal\n */\nexport interface ResultError<E = unknown> {\n readonly error: E;\n readonly [ERR_BRAND]: true;\n}\n\nfunction ResultError<E>(this: ResultError<E>, error: E): void {\n (this as { error: E }).error = error;\n}\n(ResultError.prototype as { [ERR_BRAND]: true })[ERR_BRAND] = true;\n\n/**\n * @internal\n */\nexport function err<E>(error: E): ResultError<E> {\n return new (ResultError as unknown as new (error: E) => ResultError<E>)(error);\n}\n\n/**\n * @internal\n */\nexport function isErr(result: unknown): result is ResultError<unknown> {\n return typeof result === 'object' && result !== null && (result as Record<symbol, boolean>)[ERR_BRAND] === true;\n}\n\n/**\n * @internal\n */\nexport function isOk(result: unknown): boolean {\n return typeof result !== 'object' || result === null || !(result as Record<symbol, boolean>)[ERR_BRAND];\n}\n\n/**\n * @internal\n */\nexport type DispatchResultItem<T> = MaybePromise<T> | ResultError;\n\n/**\n * @internal\n */\nexport function unwrap<T>(results: DispatchResultItem<T>[]): MaybePromise<T>[] {\n const len = results.length;\n const unwrapped = new Array<MaybePromise<T>>(len);\n for (let i = 0; i < len; i++) {\n const r = results[i];\n unwrapped[i] = isErr(r) ? Promise.reject(r.error) : r;\n }\n return unwrapped;\n}\n\nasync function resolveMaybePromises<T>(items: MaybePromise<T>[], asyncIndices: number[]): Promise<T[]> {\n const pending = new Array<PromiseLike<T>>(asyncIndices.length);\n for (let j = 0; j < asyncIndices.length; j++) {\n pending[j] = items[asyncIndices[j]] as PromiseLike<T>;\n }\n const resolved = await Promise.all(pending);\n for (let j = 0; j < asyncIndices.length; j++) {\n items[asyncIndices[j]] = resolved[j];\n }\n return items as T[];\n}\n\nfunction resolveAll<T>(results: DispatchResultItem<T>[]): T[] | Promise<T[]> {\n const len = results.length;\n if (len === 0) return results as T[];\n\n let firstError: unknown;\n let hasError = false;\n let asyncIndices: number[] | null = null;\n\n for (let i = 0; i < len; i++) {\n const r = results[i];\n if (isErr(r)) {\n if (!hasError) {\n hasError = true;\n firstError = r.error;\n }\n } else if (isThenable(r)) {\n (asyncIndices ??= []).push(i);\n }\n }\n\n if (hasError) {\n if (asyncIndices !== null) {\n for (let j = 0; j < asyncIndices.length; j++) {\n (results[asyncIndices[j]] as PromiseLike<T>).then(noop, noop);\n }\n }\n return Promise.reject(firstError);\n }\n if (asyncIndices === null) return results as T[];\n\n return resolveMaybePromises(results as MaybePromise<T>[], asyncIndices);\n}\n\nfunction settleAll<T>(results: DispatchResultItem<T>[]): PromiseSettledResult<T>[] | Promise<PromiseSettledResult<T>[]> {\n const len = results.length;\n if (len === 0) return [] as PromiseSettledResult<T>[];\n\n let asyncIndices: number[] | null = null;\n const settled = new Array<MaybePromise<PromiseSettledResult<T>>>(len);\n\n for (let i = 0; i < len; i++) {\n const r = results[i];\n if (isErr(r)) {\n settled[i] = { status: 'rejected', reason: r.error };\n } else if (isThenable(r)) {\n (asyncIndices ??= []).push(i);\n settled[i] = r.then(\n (value): PromiseFulfilledResult<T> => ({ status: 'fulfilled', value }),\n (reason: unknown): PromiseRejectedResult => ({ status: 'rejected', reason }),\n );\n } else {\n settled[i] = { status: 'fulfilled', value: r };\n }\n }\n\n if (asyncIndices === null) return settled as PromiseSettledResult<T>[];\n\n return resolveMaybePromises(settled, asyncIndices);\n}\n\n/**\n * Wraps an array of values or promises (typically listener results) and provides batch resolution.\n *\n * @template T\n */\nexport class DispatchResult<T> implements PromiseLike<T[]> {\n #results: DispatchResultItem<T>[];\n\n readonly [Symbol.toStringTag] = 'DispatchResult';\n\n constructor(results: DispatchResultItem<T>[]) {\n this.#results = results;\n }\n\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?: Fn<[T[]], MaybePromise<TResult1>> | null,\n onrejected?: Fn<[any], MaybePromise<TResult2>> | null,\n ): PromiseLike<TResult1 | TResult2> {\n const resolved = this.all();\n if (resolved instanceof Promise) return resolved.then(onfulfilled, onrejected);\n return Promise.resolve(resolved).then(onfulfilled, onrejected);\n }\n\n /**\n * Resolves all listener results, rejecting if any promise rejects or any ResultError exists.\n */\n all(): T[] | Promise<T[]> {\n return resolveAll(this.#results);\n }\n\n /**\n * Waits for all listener results to settle, regardless of fulfillment or rejection.\n */\n settled(): PromiseSettledResult<T>[] | Promise<PromiseSettledResult<T>[]> {\n return settleAll(this.#results);\n }\n}\n"],"names":["DispatchResult","err","isErr","isOk","unwrap","ERR_BRAND","Symbol","for","ResultError","error","prototype","result","results","len","length","unwrapped","Array","i","r","Promise","reject","resolveMaybePromises","items","asyncIndices","pending","j","resolved","all","resolveAll","firstError","hasError","isThenable","push","then","noop","settleAll","settled","status","reason","value","toStringTag","onfulfilled","onrejected","resolve"],"mappings":"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"}