UNPKG

kequapp

Version:

A minimal, zero-magic Node web framework built on native APIs

85 lines (84 loc) 2.59 kB
/** 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; }