kequapp
Version:
A minimal, zero-magic Node web framework built on native APIs
85 lines (84 loc) • 2.59 kB
JavaScript
/** biome-ignore-all lint/suspicious/noExplicitAny: too many possibilities */
import { STATUS_CODES } from 'node:http';
const Ex = {
StatusCode,
...errorHelpers(),
};
function StatusCode(statusCode, message, ...info) {
if (!STATUS_CODES[statusCode]) {
return buildException(StatusCode, 'Error', statusCode, message, ...info);
}
const key = createMethodName(statusCode);
return buildException(StatusCode, key, statusCode, message, ...info);
}
function errorHelpers() {
const errorHelpers = {};
const statusCodes = Object.keys(STATUS_CODES).map((statusCode) => parseInt(statusCode, 10));
for (const statusCode of statusCodes) {
if (statusCode < 400)
continue;
const key = createMethodName(statusCode);
errorHelpers[key] = (message, ...info) => {
return buildException(errorHelpers[key], key, statusCode, message, ...info);
};
}
return errorHelpers;
}
export default Ex;
export function unknownToEx(error) {
if (!(error instanceof Error)) {
const ex = StatusCode(500, createMessage(error));
delete ex.stack;
return ex;
}
const ex = error;
ex.statusCode = ex.statusCode ?? 500;
ex.info = ex.info ?? [];
ex.name = ex.name ?? createMethodName(ex.statusCode);
return ex;
}
function createMessage(message) {
try {
return `[Unknown Problem] ${String(message)}`;
}
catch (_error) {
return '[Unknown Problem]';
}
}
function createMethodName(statusCode) {
return (STATUS_CODES[statusCode] ?? 'Error')
.replace("'", '')
.split(/[\s-]+/)
.map(capitalize)
.join('');
}
function capitalize(word) {
return word.charAt(0).toUpperCase() + word.substring(1);
}
function buildException(parent, name, statusCode, message, ...info) {
const ex = new Error(message ?? STATUS_CODES[statusCode]);
ex.name = name;
ex.statusCode = statusCode;
ex.info = info.map(normalize);
Error.captureStackTrace(ex, parent);
return ex;
}
function normalize(value) {
if (typeof value !== 'object' || value === null)
return value;
if (value instanceof Date)
return value;
if (value instanceof Error)
return {
message: value.message,
name: value.name,
stack: value.stack?.split(/\r?\n/),
};
if (Array.isArray(value))
return value.map(normalize);
const result = {};
for (const key of Object.keys(value)) {
result[key] = normalize(value[key]);
}
return result;
}