mirror of
https://github.com/xodio/xod.git
synced 2026-03-03 23:44:04 +01:00
83 lines
2.5 KiB
JavaScript
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
|
|
)
|
|
);
|