express.js | Typescript implementation of problem details

express.js example of using rfc-7807-problem-details

Either pass the error/exception in next function or throw it using throw statement;

import express from "express";
import createError from "http-errors"; // https://www.npmjs.com/package/http-errors
import {
	problemDetailsMiddleware,
	ProblemDetailsException,
} from "rfc-7807-problem-details";

const app = express();

// Pass exception using next middleware
app.get("/example/next", (req, res, next) => {
	const canProceed = Math.random() * 10 > 1;
	if (canProceed) {
		return next(
			new ProblemDetailsException({
				type: "cannot-proceed",
				status: 400,
				title: "You cannot proceed.",
			})
		);
	}
	res.status(200).json({ text: `You've made it!` });
	next();
});

// throw exception
app.get("/example/throw", (req, res, next) => {
	const canProceed = Math.random() * 10 > 1;
	if (canProceed) {
		throw new ProblemDetailsException({
			type: "cannot-proceed",
			status: 400,
			title: "You cannot proceed.",
		});
	}
	res.status(200).json({ text: `You've made it!` });
	next();
});

// Pass custom exception using next middleware
app.get("/example/custom/next", (req, res, next) => {
	const canProceed = Math.random() * 10 > 1;
	if (canProceed) {
		return next(
			createError(400, "You cannot proceed.", {
				type: "cannot-proceed",
				detail: `some more details about the error - human friendly error`,
			})
		);
	}
	res.status(200).json({ text: `You've made it!` });
	next();
});

// Throw custom exception
app.get("/example/custom/throw", (req, res, next) => {
	const canProceed = Math.random() * 10 > 1;
	if (canProceed) {
		throw createError(400, "You cannot proceed.", {
			type: "cannot-proceed",
			detail: `some more details about the error - human friendly error`,
		});
	}
	res.status(200).json({ text: `You've made it!` });
	next();
});

// This is error handler hence, most be last
app.use(
	problemDetailsMiddleware((options) => {
		options.typePrefix = `https://example.com/probs/out-of-credit`;
		// default typePrefix is https://httpstatuses.io - make sure to use status code as type if you do not have dedicated errors page

		// createError function returns instance of HttpError hence we need to map it to problem details
		options.map(createError.HttpError, (error) => {
			return new ProblemDetails(
				error.type,
				error.message,
				error.status,
				error.detail
			);
		});
	})
);

const server = app.listen(3000);