2023-04-27 23:18:48 +02:00
|
|
|
import pMap from 'p-map';
|
2023-06-26 15:57:46 +02:00
|
|
|
import { curry } from 'lodash/fp';
|
2023-04-27 23:18:48 +02:00
|
|
|
|
2023-06-06 10:58:36 +02:00
|
|
|
type AnyFunc = (...args: any) => any;
|
|
|
|
|
2023-06-23 10:04:03 +02:00
|
|
|
/*
|
|
|
|
NOTE: This type is here to enforce piped functions have the right input/output types
|
|
|
|
For a list of functions it will return a new list of function but will answer the return type of the previous is the arg type of the next function
|
|
|
|
*/
|
2023-06-06 10:58:36 +02:00
|
|
|
type PipeArgs<F extends AnyFunc[], PrevReturn = Parameters<F[0]>[0]> = F extends [
|
|
|
|
(arg: any) => infer B
|
|
|
|
]
|
|
|
|
? [(arg: PrevReturn) => B]
|
|
|
|
: F extends [(arg: any) => infer B, ...infer Tail]
|
|
|
|
? Tail extends AnyFunc[]
|
|
|
|
? [(arg: PrevReturn) => B, ...PipeArgs<Tail, B>]
|
|
|
|
: []
|
|
|
|
: [];
|
|
|
|
|
|
|
|
export function pipeAsync<F extends AnyFunc[], FirstFn extends F[0]>(
|
|
|
|
...fns: PipeArgs<F> extends F ? F : PipeArgs<F>
|
|
|
|
) {
|
|
|
|
type Args = Parameters<FirstFn>;
|
|
|
|
type ReturnT = F extends [...AnyFunc[], (...arg: any) => infer R]
|
2023-06-23 10:04:03 +02:00
|
|
|
? R extends Promise<infer InnerType>
|
|
|
|
? InnerType
|
2023-06-06 10:58:36 +02:00
|
|
|
: R
|
|
|
|
: never;
|
|
|
|
|
|
|
|
const [firstFn, ...fnRest] = fns;
|
|
|
|
|
|
|
|
return async (...args: Args): Promise<ReturnT> => {
|
2023-06-26 15:57:46 +02:00
|
|
|
let res: ReturnT = await firstFn.apply(firstFn, args);
|
2023-06-06 10:58:36 +02:00
|
|
|
|
|
|
|
for (let i = 0; i < fnRest.length; i += 1) {
|
|
|
|
res = await fnRest[i](res);
|
2023-04-27 23:18:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-06-06 10:58:36 +02:00
|
|
|
export const mapAsync = curry(pMap);
|
2023-04-27 23:18:48 +02:00
|
|
|
|
2023-06-06 10:58:36 +02:00
|
|
|
export const reduceAsync =
|
|
|
|
(mixedArray: any[]) =>
|
|
|
|
async <T>(iteratee: AnyFunc, initialValue?: T) => {
|
|
|
|
let acc = initialValue;
|
|
|
|
for (let i = 0; i < mixedArray.length; i += 1) {
|
|
|
|
acc = await iteratee(acc, await mixedArray[i], i);
|
|
|
|
}
|
|
|
|
return acc;
|
|
|
|
};
|
2023-04-27 23:18:48 +02:00
|
|
|
|
2023-06-06 10:58:36 +02:00
|
|
|
export const forEachAsync = async <T, R>(
|
|
|
|
array: T[],
|
|
|
|
func: pMap.Mapper<T, R>,
|
|
|
|
options: pMap.Options
|
|
|
|
) => {
|
|
|
|
await pMap(array, func, options);
|
|
|
|
};
|