import pMap from 'p-map'; import { curry, curryN } from 'lodash/fp'; import type { CurriedFunction3 } from 'lodash'; interface MapOptions { concurrency?: number; } type MapFunc = (element: T, index: number) => R | Promise; export type ReduceAsync = CurriedFunction3< T[], (accumulator: V | R, current: Awaited, index: number) => R | Promise, V, Promise >; type CurriedMapAsync = CurriedFunction3< T[], MapFunc, MapOptions, Promise >; interface Method { (...args: any[]): any; } function pipeAsync(...methods: Method[]) { return async (data: unknown) => { let res = data; for (let i = 0; i < methods.length; i += 1) { res = await methods[i](res); } return res; }; } const mapAsync: CurriedMapAsync = curry(pMap); const reduceAsync: ReduceAsync = curryN(2, async (mixedArray, iteratee, initialValue) => { let acc = initialValue; for (let i = 0; i < mixedArray.length; i += 1) { acc = await iteratee(acc, await mixedArray[i], i); } return acc; }); const forEachAsync = curry( async (array: T[], func: MapFunc, options: MapOptions) => { await mapAsync(array, func, options); } ); export { mapAsync, reduceAsync, forEachAsync, pipeAsync };