🔧 Add utilitary Failure type

This commit is contained in:
Hugo Saracino 2020-07-06 15:18:39 +02:00
parent 63f1f160ab
commit 8e466d82f3
3 changed files with 96 additions and 1 deletions

View file

@ -15,6 +15,7 @@
"test": "jest --runInBand"
},
"dependencies": {
"decod": "^6.1.6",
"fp-ts": "^2.6.7",
"tslib": "^2.0.0"
},
@ -27,4 +28,4 @@
"ts-jest": "^26.1.1",
"typescript": "^3.9.6"
}
}
}

89
src/Failure.ts Normal file
View file

@ -0,0 +1,89 @@
import * as decod from 'decod';
import * as Either from 'fp-ts/lib/Either';
import * as TaskEither from 'fp-ts/lib/TaskEither';
import * as Task from 'fp-ts/lib/Task';
import { pipe } from 'fp-ts/lib/pipeable';
const decodeErrorMessage = decod.at('message', decod.string);
export enum FailureType {
Unexpected = 'FailureType_Unexpected',
}
export type UnexpectedFailure = Failure<FailureType.Unexpected>;
export class Failure<T extends string = FailureType> {
constructor({
reason,
type,
originalError,
}: {
reason: string;
type: T;
originalError?: Error | unknown;
}) {
this.reason = reason;
this.type = type;
if (originalError instanceof Error) {
this.originalError = originalError;
}
}
reason: string;
type: T;
originalError?: Error;
toError(): Error {
if (this.originalError) return this.originalError;
return new Error(this.reason);
}
static builder<T extends string>(type: T) {
return (reason: string, originalError?: Error | unknown) =>
new Failure<T>({
reason,
type,
originalError,
});
}
static unexpected = Failure.builder(FailureType.Unexpected);
static fromUnknownError(originalError: unknown | Error): UnexpectedFailure {
return Failure.unexpected(decodeErrorMessage(originalError), originalError);
}
static toType<T extends string>(type: T): (failure: Failure) => Failure<T> {
return (failure: Failure) =>
new Failure({
reason: failure.reason,
type,
originalError: failure.originalError,
});
}
static toUnexpected = Failure.toType(FailureType.Unexpected);
private static throw = (failure: Failure) => {
throw failure.toError();
};
static eitherUnsafeGet = <A>(either: Either.Either<Failure, A>): A =>
pipe(either, Either.getOrElseW(Failure.throw));
static taskEitherUnsafeGet = <A>(
taskEither: TaskEither.TaskEither<Failure, A>,
): Task.Task<A> =>
pipe(
taskEither,
TaskEither.getOrElseW((failure) => async () => Failure.throw(failure)),
);
}
export type FailureTypes<F extends Record<string, string>> = F[keyof F];
export interface FailureTypings<F extends Record<string, string>> {
types: FailureTypes<F>;
failure: Failure<FailureTypes<F>>;
}

View file

@ -1159,6 +1159,11 @@ decimal.js@^10.2.0:
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231"
integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw==
decod@^6.1.6:
version "6.1.6"
resolved "https://registry.yarnpkg.com/decod/-/decod-6.1.6.tgz#de2b7d2c96fc16e7b429bacfc80dc71dc4191967"
integrity sha512-0NccOCIlq/serE+b38GayxgAiUUjpoC7jNt9PH5Ak7QTOo5GhN1owtqkfNMd3RqhNb61lg/i5BqKSF/5Hb1z3A==
decode-uri-component@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"