UNPKG

fairlie-functional

Version:

A lightweight functional library in typescript that helps dealing with failures the rail way

291 lines (290 loc) 9.07 kB
/** * Return a successful response * @param value a successful value */ export const succeed = (value) => ({ status: 'success', value, }); /** * Return a failure result * @param error an error value */ export const failWith = (error) => ({ status: 'failure', error, }); /** * Return the successful value otherwise a default value * @param defaultValue the default value * @returns the successful otherwise the default value */ export const withDefault = (defaultValue) => (result) => result.status === 'success' ? result.value : defaultValue; /** * A function that connects two switch functions together, passing the success output of the first function to the input of the second function, and propagating the failure output to the error track. * @param f1 the first switch function * @param f2 the second switch function * @returns a composite switch function */ export function bindTwo(f1, f2) { return (value) => { const result1 = f1(value); if (result1.status === 'success') { const result2 = f2(result1.value); return result2; } else { return result1; } }; } /** * A function that connects two asynchronous switch functions together, passing the success output of the first function to the input of the second function, and propagating the failure output to the error track. * @param f1 the first asynchronous switch function * @param f2 the second asynchronous switch function * @returns a composite async switch function */ export function bindTwoAsync(f1, f2) { return async (value) => { const result1 = await f1(value); if (result1.status === 'success') { const result2 = await f2(result1.value); return result2; } else { return result1; } }; } /** * A function that connects three switch functions together, passing the success output of the first function to the input of the second function, and then passing the success output of the second function to the third function and propagating the failure output to the error track. * @param f1 the first switch function * @param f2 the second switch function * @param f3 the third switch function * @returns a successful result or a failure */ export function bindThree(f1, f2, f3) { return (input) => { const result1 = f1(input); if (result1.status === 'success') { const result2 = f2(result1.value); if (result2.status === 'success') { const result3 = f3(result2.value); return result3; } return result2; } else { return result1; } }; } /** * A function that connects three switch functions asynchronously together, passing the success output of the first function to the input of the second function, and then passing the success output of the second function to the third function and propagating the failure output to the error track. * @param f1 the first switch function * @param f2 the second switch function * @param f3 the third switch function * @returns a successful result or a failure */ export function bindThreeAsync(f1, f2, f3) { return async (input) => { const result1 = await f1(input); if (result1.status === 'success') { const result2 = await f2(result1.value); if (result2.status === 'success') { const result3 = await f3(result2.value); return result3; } return result2; } else { return result1; } }; } /** * A function that connects multiple switch functions together, passing the success output of the current function to the input of the next function, and propagating the failure output to the error track. * @param functions the first switch function * @returns a successful result or a failure */ export function bindSimilar(functions) { return (value) => { let valueResult = succeed(value); for (const f of functions) { if (valueResult.status === 'success') { valueResult = f(valueResult.value); } else { return valueResult; } } return valueResult; }; } /** * A function that connects multiple switch functions asynchronously together, passing the success output of the current function to the input of the next function, and propagating the failure output to the error track. * @param functions the first switch function * @returns a successful result or a failure */ export function bindSimilarAsync(functions) { return async (value) => { let valueResult = succeed(value); for (const f of functions) { if (valueResult.status === 'success') { valueResult = await f(valueResult.value); } else { return valueResult; } } return valueResult; }; } /** * The bypass function takes a switch function that expects a failure value as an input * and returns a success or failure value as an output * @param altFunc the first switch function * @returns a successful result or a failure */ export function bypass(altFunc) { return (result) => { if (result.status === 'success') { return result; } else { return altFunc(result.error); } }; } /** * The bypass function takes an asynchronous switch function that expects a failure value as an input * and returns a success or failure value as an output * @param altFunc the first switch function * @returns a successful result or a failure */ export function bypassAsync(altFunc) { return async (result) => { if (result.status === 'success') { return result; } else { return await altFunc(result.error); } }; } /** * The recover function takes a recovery function that expects a failure value as an input * and returns only a success value as an output * @param altFunc the first switch function * @returns a successful result or a failure */ export function recover(altFunc) { return (result) => { if (result.status === 'success') { return result; } else { return altFunc(result.error); } }; } /** * The recover function takes a asynchronous recovery function that expects a failure value as an input * and returns only a success value as an output * @param altFunc the first switch function * @returns a successful result or a failure */ export function recoverAsync(altFunc) { return async (result) => { if (result.status === 'success') { return result; } else { return await altFunc(result.error); } }; } /** * The fallback function takes a switch function that expects the input value as an input * and returns a success or failure value as an output. In short, it will fallback to that * function if the first fail * @param f1 the first switch function * @param fallbackF2 the fallback function * @returns a successful result or a failure */ export function orFallback(f1, fallbackF2) { return (value) => { const result1 = f1(value); if (result1.status === 'success') { return result1; } else { const resultFallback = fallbackF2(value); return resultFallback; } }; } /** * The fallback function takes an asynchronous switch function that expects the input value as an input * and returns a success or failure value as an output. In short, it will fallback to that * function if the first fail * @param f1 the first switch function * @param fallbackF2 the fallback function * @returns a successful result or a failure */ export function orFallbackAsync(f1, fallbackF2) { return async (value) => { const result1 = await f1(value); if (result1.status === 'success') { return result1; } else { const resultFallback = await fallbackF2(value); return resultFallback; } }; } /** * Take a simple transformation function which takes an input and return an output and * convert it to a switch * @param transform a transformer function * @returns a switch function */ export function transformToSwitch(transform) { return (value) => { const transformed = transform(value); return succeed(transformed); }; } /** * Take a simple transformation function which takes an input and return an output and * convert it to an asynchronous switch * @param transform a transformer function * @returns an asynchronous switch function */ export function transformToAsyncSwitch(transform) { return async (value) => { const transformed = transform(value); return succeed(transformed); }; }