UNPKG

pragmatic-fp-ts

Version:

Opinionated functional programming library with easy use in mind

73 lines (69 loc) 2.67 kB
import { Effect, Mappable, UnboxPromise } from "./types.ts"; export interface ErrorLog<T> { _: <U>(f: Mappable<T, U>) => ErrorLog<U>; effect: (f: Effect<T>) => ErrorLog<T>; try: <U>(f: Mappable<T, U>, alt: U) => ErrorLog<U>; getErrors: () => Error[]; getValue: () => T; getValueOr: <U>(alt: U) => NonNullable<T> | U; hasErrors: () => boolean; } function ErrorLog<T>(expr: T, errors: Array<Error> = []) { return { _: <U>(f: Mappable<T, U>) => ErrorLog(f(expr), errors), try: <U>(f: Mappable<T, U>, alt: U): ErrorLog<U> => { try { return ErrorLog(f(expr), errors); } catch (err) { return ErrorLog(alt, [...errors, err as Error]); } }, effect: (f: Effect<T>): ErrorLog<T> => { try { f(expr); return ErrorLog(expr, errors); } catch (err) { return ErrorLog(expr, [...errors, err as Error]); } }, getErrors: () => errors, getValue: () => expr, getValueOr: <U>(alt: T | U) => (expr || alt) as NonNullable<T> | U, hasErrors: () => errors.length > 0, }; } export interface FutureErrorLog<T> { _: <U>(f: Mappable<T, U>) => FutureErrorLog<U>; effect: (f: Effect<T>) => FutureErrorLog<T>; try: <U>(f: Mappable<T, U>, alt: UnboxPromise<U>) => FutureErrorLog<U>; getErrors: () => Promise<Error[]>; getValue: () => Promise<UnboxPromise<T>>; getValueOr: <U extends T>(alt: U) => Promise<NonNullable<UnboxPromise<T>>>; hasErrors: () => Promise<boolean>; } const FutureErrorLog = <T>( expr: T | Promise<T>, errors: Promise<Error[]> = Promise.resolve([]) ): FutureErrorLog<T> => { const exprP = expr instanceof Promise ? expr : Promise.resolve(expr); const tryOrAppendError = (p: Promise<any>, es: Promise<Error[]>) => p.then(() => es).catch(async (err) => [...(await errors), err]); return { _: <U>(f: Mappable<T, U>): FutureErrorLog<U> => FutureErrorLog(exprP.then(f), errors), effect: (fx: Effect<T>) => FutureErrorLog(exprP, tryOrAppendError(exprP.then(fx), errors)), try: <U>(f: Mappable<T, U>, alt: UnboxPromise<U>): FutureErrorLog<U> => { const p = exprP.then(f); return FutureErrorLog( p.catch(() => alt as any), tryOrAppendError(p, errors) ); }, getErrors: () => errors, getValue: () => exprP as unknown as Promise<UnboxPromise<T>>, getValueOr: async (alt: T | Promise<T>) => (await exprP) || ((alt instanceof Promise ? await alt : (alt as any)) as any), hasErrors: () => errors.then((e) => e.length > 0), }; }; export const errorLogged = <T>(value: T) => ErrorLog(value); export const errorLoggedFuture = <T>(value: T) => FutureErrorLog(value);