@catbee/utils
Version:
A modular, production-grade utility toolkit for Node.js and TypeScript, designed for robust, scalable applications (including Express-based services). All utilities are tree-shakable and can be imported independently.
387 lines • 15.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.InsufficientStorageException = exports.PayloadTooLargeException = exports.UnsupportedMediaTypeException = exports.RequestTimeoutException = exports.NotAcceptableException = exports.MethodNotAllowedException = exports.UnprocessableEntityException = exports.GatewayTimeoutException = exports.ServiceUnavailableException = exports.TooManyRequestsException = exports.BadGatewayException = exports.ConflictException = exports.ForbiddenException = exports.NotFoundException = exports.BadRequestException = exports.UnauthorizedException = exports.InternalServerErrorException = exports.HttpError = void 0;
exports.isHttpError = isHttpError;
exports.createHttpError = createHttpError;
exports.hasErrorShape = hasErrorShape;
exports.getErrorMessage = getErrorMessage;
exports.withErrorHandling = withErrorHandling;
const http_status_codes_1 = require("./http-status-codes");
const logger_utils_1 = require("./logger.utils");
const response_utils_1 = require("./response.utils");
/**
* Generic HTTP error class used for custom exceptions with any status code.
* Inherit this when you need to throw errors dynamically at runtime.
*/
class HttpError extends response_utils_1.ErrorResponse {
/**
* Creates a new HTTP error instance.
* @param status - A valid HTTP status code (e.g., 400, 500).
* @param message - The error message to return to the client.
*/
constructor(status, message) {
super(message);
this.status = status;
}
}
exports.HttpError = HttpError;
/**
* Represents a 500 Internal Server Error.
* Use this for unexpected backend errors that are not caused by the client.
*/
class InternalServerErrorException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Internal server error".
*/
constructor(message = "Internal server error") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.INTERNAL_SERVER_ERROR;
}
}
exports.InternalServerErrorException = InternalServerErrorException;
/**
* Represents a 401 Unauthorized Error.
* Indicates that authentication is required and has failed or not been provided.
*/
class UnauthorizedException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Unauthorized".
*/
constructor(message = "Unauthorized") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.UNAUTHORIZED;
}
}
exports.UnauthorizedException = UnauthorizedException;
/**
* Represents a 400 Bad Request Error.
* Indicates that the client has sent invalid data (e.g., malformed request body).
*/
class BadRequestException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Bad request".
*/
constructor(message = "Bad request") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.BAD_REQUEST;
}
}
exports.BadRequestException = BadRequestException;
/**
* Represents a 404 Not Found Error.
* Used when a requested resource (e.g., user, file) could not be located.
*/
class NotFoundException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Resource not found".
*/
constructor(message = "Resource not found") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.NOT_FOUND;
}
}
exports.NotFoundException = NotFoundException;
/**
* Represents a 403 Forbidden Error.
* Indicates that the client is authenticated but not allowed to access the resource.
*/
class ForbiddenException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Forbidden".
*/
constructor(message = "Forbidden") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.FORBIDDEN;
}
}
exports.ForbiddenException = ForbiddenException;
/**
* Represents a 409 Conflict Error.
* Commonly used when a resource already exists or a versioning conflict occurs.
*/
class ConflictException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Conflict".
*/
constructor(message = "Conflict") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.CONFLICT;
}
}
exports.ConflictException = ConflictException;
/**
* Represents a 502 Bad Gateway Error.
* Used when the server receives an invalid response from an upstream server.
*/
class BadGatewayException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Bad Gateway".
*/
constructor(message = "Bad Gateway") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.BAD_GATEWAY;
}
}
exports.BadGatewayException = BadGatewayException;
/**
* Represents a 429 Too Many Requests Error.
* Returned when the client has hit a rate limit.
*/
class TooManyRequestsException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Too many requests".
*/
constructor(message = "Too many requests") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.TOO_MANY_REQUESTS;
}
}
exports.TooManyRequestsException = TooManyRequestsException;
/**
* Represents a 503 Service Unavailable Error.
* Indicates that the server is temporarily unavailable (e.g., for maintenance).
*/
class ServiceUnavailableException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Service Unavailable".
*/
constructor(message = "Service Unavailable") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.SERVICE_UNAVAILABLE;
}
}
exports.ServiceUnavailableException = ServiceUnavailableException;
/**
* Represents a 504 Gateway Timeout Error.
* Returned when the server acting as a gateway times out waiting for a response.
*/
class GatewayTimeoutException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Gateway Timeout".
*/
constructor(message = "Gateway Timeout") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.GATEWAY_TIMEOUT;
}
}
exports.GatewayTimeoutException = GatewayTimeoutException;
/**
* Represents a 422 Unprocessable Entity Error.
* Used when the server understands the content type but cannot process the contained instructions.
*/
class UnprocessableEntityException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Unprocessable Entity".
* @param details - Optional validation details or additional error context.
*/
constructor(message = "Unprocessable Entity", details) {
super(message);
this.details = details;
this.status = http_status_codes_1.HttpStatusCodes.UNPROCESSABLE_ENTITY;
}
}
exports.UnprocessableEntityException = UnprocessableEntityException;
/**
* Represents a 405 Method Not Allowed Error.
* Used when the request method is not supported for the requested resource.
*/
class MethodNotAllowedException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Method Not Allowed".
* @param allowedMethods - Optional array of allowed HTTP methods.
*/
constructor(message = "Method Not Allowed", allowedMethods) {
super(message);
this.allowedMethods = allowedMethods;
this.status = http_status_codes_1.HttpStatusCodes.METHOD_NOT_ALLOWED;
}
}
exports.MethodNotAllowedException = MethodNotAllowedException;
/**
* Represents a 406 Not Acceptable Error.
* Used when the server cannot produce a response matching the client's accepted content types.
*/
class NotAcceptableException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Not Acceptable".
*/
constructor(message = "Not Acceptable") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.NOT_ACCEPTABLE;
}
}
exports.NotAcceptableException = NotAcceptableException;
/**
* Represents a 408 Request Timeout Error.
* Used when the server times out waiting for the client to send a request.
*/
class RequestTimeoutException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Request Timeout".
*/
constructor(message = "Request Timeout") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.REQUEST_TIMEOUT;
}
}
exports.RequestTimeoutException = RequestTimeoutException;
/**
* Represents a 415 Unsupported Media Type Error.
* Used when the request's Content-Type is not supported.
*/
class UnsupportedMediaTypeException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Unsupported Media Type".
*/
constructor(message = "Unsupported Media Type") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.UNSUPPORTED_MEDIA_TYPE;
}
}
exports.UnsupportedMediaTypeException = UnsupportedMediaTypeException;
/**
* Represents a 413 Payload Too Large Error.
* Used when the request body exceeds server limits.
*/
class PayloadTooLargeException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Payload Too Large".
*/
constructor(message = "Payload Too Large") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.PAYLOAD_TOO_LARGE;
}
}
exports.PayloadTooLargeException = PayloadTooLargeException;
/**
* Represents a 507 Insufficient Storage Error.
* Used when the server has insufficient storage to complete the request.
*/
class InsufficientStorageException extends response_utils_1.ErrorResponse {
/**
* @param message - Optional custom message. Defaults to "Insufficient Storage".
*/
constructor(message = "Insufficient Storage") {
super(message);
this.status = http_status_codes_1.HttpStatusCodes.INSUFFICIENT_STORAGE;
}
}
exports.InsufficientStorageException = InsufficientStorageException;
/**
* Checks if an error is an instance of HttpError or its subclasses.
*
* @param error - The error to check.
* @returns True if the error is an HttpError, false otherwise.
*/
function isHttpError(error) {
return error instanceof response_utils_1.ErrorResponse;
}
/**
* Creates an HTTP error with the specified status code and message.
* Factory function for creating appropriate HTTP error instances.
*
* @param status - HTTP status code.
* @param message - Optional custom error message.
* @returns An instance of the appropriate HTTP error class.
*/
function createHttpError(status, message) {
switch (status) {
case http_status_codes_1.HttpStatusCodes.BAD_REQUEST:
return new BadRequestException(message);
case http_status_codes_1.HttpStatusCodes.UNAUTHORIZED:
return new UnauthorizedException(message);
case http_status_codes_1.HttpStatusCodes.FORBIDDEN:
return new ForbiddenException(message);
case http_status_codes_1.HttpStatusCodes.NOT_FOUND:
return new NotFoundException(message);
case http_status_codes_1.HttpStatusCodes.METHOD_NOT_ALLOWED:
return new MethodNotAllowedException(message);
case http_status_codes_1.HttpStatusCodes.NOT_ACCEPTABLE:
return new NotAcceptableException(message);
case http_status_codes_1.HttpStatusCodes.REQUEST_TIMEOUT:
return new RequestTimeoutException(message);
case http_status_codes_1.HttpStatusCodes.CONFLICT:
return new ConflictException(message);
case http_status_codes_1.HttpStatusCodes.GONE:
return new HttpError(http_status_codes_1.HttpStatusCodes.GONE, message || "Gone");
case http_status_codes_1.HttpStatusCodes.PAYLOAD_TOO_LARGE:
return new PayloadTooLargeException(message);
case http_status_codes_1.HttpStatusCodes.UNSUPPORTED_MEDIA_TYPE:
return new UnsupportedMediaTypeException(message);
case http_status_codes_1.HttpStatusCodes.UNPROCESSABLE_ENTITY:
return new UnprocessableEntityException(message);
case http_status_codes_1.HttpStatusCodes.TOO_MANY_REQUESTS:
return new TooManyRequestsException(message);
case http_status_codes_1.HttpStatusCodes.INTERNAL_SERVER_ERROR:
return new InternalServerErrorException(message);
case http_status_codes_1.HttpStatusCodes.BAD_GATEWAY:
return new BadGatewayException(message);
case http_status_codes_1.HttpStatusCodes.SERVICE_UNAVAILABLE:
return new ServiceUnavailableException(message);
case http_status_codes_1.HttpStatusCodes.GATEWAY_TIMEOUT:
return new GatewayTimeoutException(message);
case http_status_codes_1.HttpStatusCodes.INSUFFICIENT_STORAGE:
return new InsufficientStorageException(message);
default:
return new HttpError(status, message || `HTTP Error ${status}`);
}
}
/**
* Type guard to check if an object has specific error properties.
*
* @param error - The object to check.
* @returns True if object has error-like structure.
*/
function hasErrorShape(error) {
return (typeof error === "object" &&
error !== null &&
"message" in error &&
typeof error.message === "string");
}
/**
* Safely extracts message from any error type.
*
* @param error - Any error object or value.
* @returns A string error message.
*/
function getErrorMessage(error) {
if (typeof error === "string") {
return error;
}
if (error instanceof Error) {
return error.message;
}
if (hasErrorShape(error)) {
return error.message;
}
return "Unknown error occurred";
}
/**
* Wraps a function and transforms any errors into HTTP errors.
* Useful for API handlers to ensure consistent error responses.
*
* @param handler - The async function to wrap.
* @returns A function that always returns or throws an HTTP error.
*/
function withErrorHandling(handler) {
return async (...args) => {
try {
return await handler(...args);
}
catch (error) {
if (isHttpError(error)) {
throw error;
}
// Log the original error (consider using a proper logger)
(0, logger_utils_1.getLogger)().error("Caught error in handler:", error);
// Extract status code if it exists, otherwise use 500
let status = http_status_codes_1.HttpStatusCodes.INTERNAL_SERVER_ERROR;
if (hasErrorShape(error) && typeof error.status === "number") {
status = error.status;
}
// Create appropriate HTTP error
throw createHttpError(status, getErrorMessage(error));
}
};
}
//# sourceMappingURL=exception.utils.js.map