UNPKG

@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
"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