@thisisagile/easy-express
Version:
Straightforward library for building domain-driven microservice architectures
56 lines (52 loc) • 2.12 kB
text/typescript
import express from 'express';
import { isAuthError } from './AuthError';
import {
asString,
choose,
ctx,
HttpStatus,
isDoesNotExist,
isError,
isException,
isResponse,
isResults,
isText,
Response,
rest,
Result,
toHttpStatus,
toResult,
tryTo,
} from '@thisisagile/easy';
import { OriginatedError, toOriginatedError } from '@thisisagile/easy-service';
const toResponse = (status: HttpStatus, errors: Result[] = []): Response => ({
status,
body: rest.toError(status, errors),
});
const toBody = ({ origin, options }: OriginatedError): Response => {
return (
choose(origin)
.type(isAuthError, ae => toResponse(toHttpStatus(ae.status), [toResult(ae.message)]))
.type(isDoesNotExist, e => toResponse(options?.onNotFound ?? HttpStatus.NotFound, [toResult(e.reason ?? e.message)]))
// This service breaks with an error
.type(isError, e => toResponse(HttpStatus.InternalServerError, [toResult(e.message)]))
// This service fails
.type(isResults, r => toResponse(options?.onError ?? HttpStatus.BadRequest, r.results))
// Underlying service fails
.type(isResponse, r => toResponse(HttpStatus.InternalServerError, r.body.error?.errors))
.type(isException, e => toResponse(options?.onError ?? HttpStatus.BadRequest, [toResult(e.reason ?? e.message)]))
// This service fails with a string
.type(isText, t => toResponse(options?.onError ?? HttpStatus.BadRequest, [toResult(asString(t))]))
.else(() => toResponse(HttpStatus.InternalServerError, [toResult('Unknown error')]))
);
};
export const error = (e: Error, req: express.Request, res: express.Response, _next: express.NextFunction): void => {
let response: Response;
tryTo(() => toOriginatedError(e))
.map(oe => toBody(oe))
.accept(r => (response = r))
.accept(r => (ctx.request.lastError = r.status.isServerError ? r.body.error?.errors[0]?.message : undefined))
.accept(r => (ctx.request.lastErrorStack = r.status.isServerError ? e.stack : undefined))
.recover(() => response)
.accept(r => res.status(r.status.status).json(r.body));
};