Files
xod/packages/xod-func-tools/src/errors.js
2018-08-29 20:42:58 +03:00

83 lines
2.5 KiB
JavaScript

import * as R from 'ramda';
import { Either } from 'ramda-fantasy';
import { def } from './types';
import { foldMaybe, foldEither } from './monads';
export const createError = def(
'createError :: String -> Object -> Error',
(errorType, payload) => {
const err = new Error(`${errorType} ${JSON.stringify(payload)}`);
err.type = errorType;
err.payload = payload;
return err;
}
);
export const fail = def(
'fail :: String -> Object -> Either Error a',
R.compose(Either.Left, createError)
);
// :: String -> Object -> ((a, ..., z) -> Boolean) -> ((a, ..., z) -> Either Error a)
export const failOnFalse = R.curry((errorType, payload, condition) =>
R.ifElse(condition, Either.of, () => fail(errorType, payload))
);
// :: String -> Object -> Maybe a -> Either Error a
export const failOnNothing = R.curry((errorType, payload) =>
foldMaybe(fail(errorType, payload), Either.of)
);
/**
* Updates trace of the Error, produced by any of `fail` functions.
* Will be used in functions that validates something recursively.
*/
export const prependTraceToError = def(
'prependTraceToError :: String -> Either Error a -> Either Error a',
(patchPath, either) =>
foldEither(
R.when(R.is(Error), err => {
const newPayload = R.over(
R.lensProp('trace'),
R.pipe(R.defaultTo([]), R.concat([patchPath])),
R.propOr({}, 'payload', err)
);
const newErr = R.compose(
foldEither(e => {
// We have to reassign stack to the new Error object
// to keep the stack trace to place where error really occured
// eslint-disable-next-line no-param-reassign
e.stack = err.stack;
return Either.Left(e);
}, Either.of),
fail
)(err.type, newPayload);
return newErr;
}),
Either.of,
either
)
);
export const composeErrorFormatters = def(
'composeErrorFormatters :: [StrMap Error -> Stanza] -> (Error -> Stanza)',
R.compose(
errorFormatters => err => {
const formatter = errorFormatters[err.type];
if (!formatter) {
// Fallback to ugly/default error message
// if there is no messages for this type of error
// or error has no type at all
return {
title: 'Error',
note: err.message,
solution:
'The error has no formatter, which is a bug. Report the issue to XOD developers.',
};
}
return formatter(err.payload);
},
R.mergeAll
)
);