UNPKG

@jsoldi/hkt

Version:

Higher kinded types for typescript and a few utility monads.

80 lines 2.98 kB
import { monad } from "../classes/monad.js"; import { pipe } from "../core/utils.js"; /** An error thrown when a task is aborted. */ export class AbortError extends Error { constructor(msg) { super(msg ?? 'Task was aborted'); this.name = 'AbortError'; } } /** The task module, providing functions to work with `Task` instances, which are promise-returning functions. */ export const task = (() => { return pipe((() => { const fun = (asyncLike) => (...args) => { const promiseFun = (asyncLike) => (...args) => { return typeof asyncLike === 'function' ? promiseFun(asyncLike(...args))() : asyncLike; }; return () => promiseFun(asyncLike)(...args); }; const unit = (a) => () => Promise.resolve(a); const bind = (fa, f) => () => fa().then(a => fun(f)(a)()); const flatMap = (f) => (fa) => bind(fa, f); const map = (fa, f) => () => fa().then(f); return { ...monad({ unit, bind, flatMap, map }), fun }; })(), base => { const delay = (ms) => () => new Promise(resolve => setTimeout(resolve, ms)); const promises = (fa) => fa.map(t => t()); const all = (fa) => () => Promise.all(promises(fa)); const race = (fa) => () => Promise.race(promises(fa)); const any = (fa) => () => Promise.any(promises(fa)); const run = (fa) => fa(); const runFree = (t) => async () => { while (t.right) t = await t.value(); return t.value; }; const memo = (f) => { let memo = undefined; return () => { if (memo === undefined) memo = f(); return memo; }; }; const abortable = (signal) => (fa) => () => new Promise((resolve, reject) => { const doAbort = () => reject(new AbortError()); if (signal.aborted) return doAbort(); signal.addEventListener('abort', doAbort); fa().then(resolve, reject).finally(() => signal.removeEventListener('abort', doAbort)); }); const expirable = (ms) => (ta) => { return () => { const controller = new AbortController(); const id = setTimeout(() => controller.abort(), ms); return abortable(controller.signal)(ta)().finally(() => clearTimeout(id)); }; }; const _catch = (f) => (fa) => () => fa().catch(e => f(e)()); const _finally = (f) => (fa) => () => fa().finally(f); return { ...base, run, runFree, delay, promises, all, race, any, memo, abortable, expirable, catch: _catch, finally: _finally, }; }); })(); //# sourceMappingURL=task.js.map