import * as E from 'fp-ts/Either'; import * as O from 'fp-ts/Option'; import * as EitherUtils from './EitherUtils'; import * as ObjUtils from './ObjUtils'; import * as Type from './Type'; type Either = E.Either; export const eitherToPromise = (e: Either): Promise => new Promise((resolve, reject) => { E.fold(reject, resolve)(e); }); export const optionToPromise = (o: O.Option, e?: unknown): Promise => new Promise((resolve, reject) => { O.fold(() => reject(e), resolve)(o); }); export const succeed = (a: A): Promise => Promise.resolve(a); export const fail = (error?: unknown): Promise => Promise.reject(errorify(error)); const errorify = (error?: unknown): unknown => Type.isString(error) ? new Error(error) : error; export const tryPromise = (p: Promise): Promise> => p.then(E.right, E.left); export const getOrElse = (p: Promise, other: A): Promise => p.then((x) => x, () => other); export const setError = (p: Promise, error: unknown): Promise => p.catch(() => fail(error)); export const parMap = (input: readonly A[], p: (a: A) => Promise): Promise => Promise.all(input.map(p)); export const parMapRecord = (input: Record, p: (value: A, key: string) => Promise): Promise> => { const keys = Object.keys(input); const mapper = (k: string) => p(input[k], k).then<[string, B]>((b) => [ k, b ]); return parMap(keys, mapper).then(ObjUtils.fromPairs); }; export const filterMap = async (input: A[], p: (a: A) => Promise): Promise => parMap(input, (a) => tryPromise(p(a))).then(EitherUtils.rights); export const poll = async (fn: () => Promise, timeout: number, delay: number): Promise => new Promise((resolve, reject) => { const start = Date.now(); const check = () => { fn().then(resolve, () => { const now = Date.now(); if (now - start > timeout) { reject(new Error('Timeout waiting for condition')); } else { setTimeout(check, delay); } }); }; check(); });