UNPKG

typescript-functional-extensions

Version:

A TypeScript implementation of synchronous and asynchronous Maybe and Result monads

175 lines (174 loc) 5.97 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MaybeAsync = void 0; const maybe_js_1 = require("./maybe.js"); const resultAsync_js_1 = require("./resultAsync.js"); const unit_js_1 = require("./unit.js"); const utilities_js_1 = require("./utilities.js"); /** * Represents an asynchronous value that might or might not exist */ class MaybeAsync { static from(valueOrPromiseOrMaybePromise) { if ((0, utilities_js_1.isPromise)(valueOrPromiseOrMaybePromise)) { return new MaybeAsync(valueOrPromiseOrMaybePromise.then((v) => v instanceof maybe_js_1.Maybe ? v : maybe_js_1.Maybe.from(v))); } else if (valueOrPromiseOrMaybePromise instanceof maybe_js_1.Maybe) { return new MaybeAsync(Promise.resolve(valueOrPromiseOrMaybePromise)); } throw new Error('Value must be a Promise or Maybe'); } /** * Creates a new MaybeAsync from the given value * @param value * @returns */ static some(value) { return new MaybeAsync(Promise.resolve(maybe_js_1.Maybe.some(value))); } /** * Creates a new MaybeAsync with no value * @returns */ static none() { return new MaybeAsync(Promise.resolve(maybe_js_1.Maybe.none())); } get hasValue() { return this.value.then((m) => m.hasValue); } get hasNoValue() { return this.value.then((m) => m.hasNoValue); } value; constructor(value) { this.value = value; } getValueOrDefault(defaultValueOrFactory) { if ((0, utilities_js_1.isDefined)(this.value)) { return this.value.then((m) => { if ((0, utilities_js_1.isFunction)(defaultValueOrFactory)) { return m.getValueOrDefault(defaultValueOrFactory()); } else { return m.getValueOrDefault(defaultValueOrFactory); } }); } if ((0, utilities_js_1.isFunction)(defaultValueOrFactory)) { return Promise.resolve(defaultValueOrFactory()); } return Promise.resolve(defaultValueOrFactory); } /** * Returns the value of the MaybeAsync and throws * and returns a rejected Promise is there is none * @returns */ getValueOrThrow() { if ((0, utilities_js_1.isDefined)(this.value)) { return this.value.then((m) => { return m.getValueOrThrow(); }); } return Promise.reject('No value'); } /** * Executes the given operator functions, creating a custom pipeline * @param operations MaybeAsync operation functions * @returns */ pipe(...operations) { return (0, utilities_js_1.pipeFromArray)(operations)(this); } map(projection) { return MaybeAsync.from(this.value.then(async (m) => { if (m.hasNoValue) { return maybe_js_1.Maybe.none(); } const result = projection(m.getValueOrThrow()); if ((0, utilities_js_1.isPromise)(result)) { return result.then((r) => maybe_js_1.Maybe.some(r)); } return maybe_js_1.Maybe.some(result); })); } tap(action) { return new MaybeAsync(this.value.then(async (m) => { if (m.hasNoValue) { return m; } const result = action(m.getValueOrThrow()); if ((0, utilities_js_1.isPromise)(result)) { await result; } return m; })); } bind(projection) { return new MaybeAsync(this.value.then((m) => { if (m.hasNoValue) { return maybe_js_1.Maybe.none(); } const result = projection(m.getValueOrThrow()); if (result instanceof maybe_js_1.Maybe) { return result; } return result.toPromise(); })); } match(matcher) { return this.value.then((m) => m.match(matcher)); } execute(func) { return this.value.then((m) => { if (m.hasNoValue) { return unit_js_1.Unit.Instance; } const result = func(m.getValueOrThrow()); return (0, utilities_js_1.isPromise)(result) ? result.then(() => unit_js_1.Unit.Instance) : unit_js_1.Unit.Instance; }); } or(fallback) { return new MaybeAsync(this.value.then((m) => { if (fallback instanceof MaybeAsync) { return m.orAsync(fallback).toPromise(); } else { if (m.hasValue) { return m; } if (!(0, utilities_js_1.isFunction)(fallback)) { if (fallback instanceof maybe_js_1.Maybe) { return m.or(fallback); } return m.or(fallback); } const result = fallback(); if (result instanceof MaybeAsync) { return m.orAsync(result).toPromise(); } if (result instanceof maybe_js_1.Maybe) { return m.or(result); } return m.or(result); } })); } toResult(error) { return resultAsync_js_1.ResultAsync.from(this.value.then((m) => m.toResult(error))); } /** * Returns the inner Promise, wrapping Maybe.none if handleError is true * for a rejected Promise, otherwise rejected Promise handling is left up to the caller. * @param handleError * @returns */ toPromise(handleError = false) { return (0, utilities_js_1.isDefined)(handleError) && handleError ? this.value.catch((_) => maybe_js_1.Maybe.none()) : this.value; } } exports.MaybeAsync = MaybeAsync;