@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.
539 lines • 22.1 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
import { HttpStatusCodes } from "./http-status-codes";
import { getLogger } from "./logger.utils";
import { ErrorResponse } from "./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.
*/
var HttpError = /** @class */ (function (_super) {
__extends(HttpError, _super);
/**
* 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.
*/
function HttpError(status, message) {
var _this = _super.call(this, message) || this;
_this.status = status;
return _this;
}
return HttpError;
}(ErrorResponse));
export { HttpError };
/**
* Represents a 500 Internal Server Error.
* Use this for unexpected backend errors that are not caused by the client.
*/
var InternalServerErrorException = /** @class */ (function (_super) {
__extends(InternalServerErrorException, _super);
/**
* @param message - Optional custom message. Defaults to "Internal server error".
*/
function InternalServerErrorException(message) {
if (message === void 0) { message = "Internal server error"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.INTERNAL_SERVER_ERROR;
return _this;
}
return InternalServerErrorException;
}(ErrorResponse));
export { InternalServerErrorException };
/**
* Represents a 401 Unauthorized Error.
* Indicates that authentication is required and has failed or not been provided.
*/
var UnauthorizedException = /** @class */ (function (_super) {
__extends(UnauthorizedException, _super);
/**
* @param message - Optional custom message. Defaults to "Unauthorized".
*/
function UnauthorizedException(message) {
if (message === void 0) { message = "Unauthorized"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.UNAUTHORIZED;
return _this;
}
return UnauthorizedException;
}(ErrorResponse));
export { UnauthorizedException };
/**
* Represents a 400 Bad Request Error.
* Indicates that the client has sent invalid data (e.g., malformed request body).
*/
var BadRequestException = /** @class */ (function (_super) {
__extends(BadRequestException, _super);
/**
* @param message - Optional custom message. Defaults to "Bad request".
*/
function BadRequestException(message) {
if (message === void 0) { message = "Bad request"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.BAD_REQUEST;
return _this;
}
return BadRequestException;
}(ErrorResponse));
export { BadRequestException };
/**
* Represents a 404 Not Found Error.
* Used when a requested resource (e.g., user, file) could not be located.
*/
var NotFoundException = /** @class */ (function (_super) {
__extends(NotFoundException, _super);
/**
* @param message - Optional custom message. Defaults to "Resource not found".
*/
function NotFoundException(message) {
if (message === void 0) { message = "Resource not found"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.NOT_FOUND;
return _this;
}
return NotFoundException;
}(ErrorResponse));
export { NotFoundException };
/**
* Represents a 403 Forbidden Error.
* Indicates that the client is authenticated but not allowed to access the resource.
*/
var ForbiddenException = /** @class */ (function (_super) {
__extends(ForbiddenException, _super);
/**
* @param message - Optional custom message. Defaults to "Forbidden".
*/
function ForbiddenException(message) {
if (message === void 0) { message = "Forbidden"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.FORBIDDEN;
return _this;
}
return ForbiddenException;
}(ErrorResponse));
export { ForbiddenException };
/**
* Represents a 409 Conflict Error.
* Commonly used when a resource already exists or a versioning conflict occurs.
*/
var ConflictException = /** @class */ (function (_super) {
__extends(ConflictException, _super);
/**
* @param message - Optional custom message. Defaults to "Conflict".
*/
function ConflictException(message) {
if (message === void 0) { message = "Conflict"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.CONFLICT;
return _this;
}
return ConflictException;
}(ErrorResponse));
export { ConflictException };
/**
* Represents a 502 Bad Gateway Error.
* Used when the server receives an invalid response from an upstream server.
*/
var BadGatewayException = /** @class */ (function (_super) {
__extends(BadGatewayException, _super);
/**
* @param message - Optional custom message. Defaults to "Bad Gateway".
*/
function BadGatewayException(message) {
if (message === void 0) { message = "Bad Gateway"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.BAD_GATEWAY;
return _this;
}
return BadGatewayException;
}(ErrorResponse));
export { BadGatewayException };
/**
* Represents a 429 Too Many Requests Error.
* Returned when the client has hit a rate limit.
*/
var TooManyRequestsException = /** @class */ (function (_super) {
__extends(TooManyRequestsException, _super);
/**
* @param message - Optional custom message. Defaults to "Too many requests".
*/
function TooManyRequestsException(message) {
if (message === void 0) { message = "Too many requests"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.TOO_MANY_REQUESTS;
return _this;
}
return TooManyRequestsException;
}(ErrorResponse));
export { TooManyRequestsException };
/**
* Represents a 503 Service Unavailable Error.
* Indicates that the server is temporarily unavailable (e.g., for maintenance).
*/
var ServiceUnavailableException = /** @class */ (function (_super) {
__extends(ServiceUnavailableException, _super);
/**
* @param message - Optional custom message. Defaults to "Service Unavailable".
*/
function ServiceUnavailableException(message) {
if (message === void 0) { message = "Service Unavailable"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.SERVICE_UNAVAILABLE;
return _this;
}
return ServiceUnavailableException;
}(ErrorResponse));
export { ServiceUnavailableException };
/**
* Represents a 504 Gateway Timeout Error.
* Returned when the server acting as a gateway times out waiting for a response.
*/
var GatewayTimeoutException = /** @class */ (function (_super) {
__extends(GatewayTimeoutException, _super);
/**
* @param message - Optional custom message. Defaults to "Gateway Timeout".
*/
function GatewayTimeoutException(message) {
if (message === void 0) { message = "Gateway Timeout"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.GATEWAY_TIMEOUT;
return _this;
}
return GatewayTimeoutException;
}(ErrorResponse));
export { GatewayTimeoutException };
/**
* Represents a 422 Unprocessable Entity Error.
* Used when the server understands the content type but cannot process the contained instructions.
*/
var UnprocessableEntityException = /** @class */ (function (_super) {
__extends(UnprocessableEntityException, _super);
/**
* @param message - Optional custom message. Defaults to "Unprocessable Entity".
* @param details - Optional validation details or additional error context.
*/
function UnprocessableEntityException(message, details) {
if (message === void 0) { message = "Unprocessable Entity"; }
var _this = _super.call(this, message) || this;
_this.details = details;
_this.status = HttpStatusCodes.UNPROCESSABLE_ENTITY;
return _this;
}
return UnprocessableEntityException;
}(ErrorResponse));
export { UnprocessableEntityException };
/**
* Represents a 405 Method Not Allowed Error.
* Used when the request method is not supported for the requested resource.
*/
var MethodNotAllowedException = /** @class */ (function (_super) {
__extends(MethodNotAllowedException, _super);
/**
* @param message - Optional custom message. Defaults to "Method Not Allowed".
* @param allowedMethods - Optional array of allowed HTTP methods.
*/
function MethodNotAllowedException(message, allowedMethods) {
if (message === void 0) { message = "Method Not Allowed"; }
var _this = _super.call(this, message) || this;
_this.allowedMethods = allowedMethods;
_this.status = HttpStatusCodes.METHOD_NOT_ALLOWED;
return _this;
}
return MethodNotAllowedException;
}(ErrorResponse));
export { MethodNotAllowedException };
/**
* Represents a 406 Not Acceptable Error.
* Used when the server cannot produce a response matching the client's accepted content types.
*/
var NotAcceptableException = /** @class */ (function (_super) {
__extends(NotAcceptableException, _super);
/**
* @param message - Optional custom message. Defaults to "Not Acceptable".
*/
function NotAcceptableException(message) {
if (message === void 0) { message = "Not Acceptable"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.NOT_ACCEPTABLE;
return _this;
}
return NotAcceptableException;
}(ErrorResponse));
export { NotAcceptableException };
/**
* Represents a 408 Request Timeout Error.
* Used when the server times out waiting for the client to send a request.
*/
var RequestTimeoutException = /** @class */ (function (_super) {
__extends(RequestTimeoutException, _super);
/**
* @param message - Optional custom message. Defaults to "Request Timeout".
*/
function RequestTimeoutException(message) {
if (message === void 0) { message = "Request Timeout"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.REQUEST_TIMEOUT;
return _this;
}
return RequestTimeoutException;
}(ErrorResponse));
export { RequestTimeoutException };
/**
* Represents a 415 Unsupported Media Type Error.
* Used when the request's Content-Type is not supported.
*/
var UnsupportedMediaTypeException = /** @class */ (function (_super) {
__extends(UnsupportedMediaTypeException, _super);
/**
* @param message - Optional custom message. Defaults to "Unsupported Media Type".
*/
function UnsupportedMediaTypeException(message) {
if (message === void 0) { message = "Unsupported Media Type"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.UNSUPPORTED_MEDIA_TYPE;
return _this;
}
return UnsupportedMediaTypeException;
}(ErrorResponse));
export { UnsupportedMediaTypeException };
/**
* Represents a 413 Payload Too Large Error.
* Used when the request body exceeds server limits.
*/
var PayloadTooLargeException = /** @class */ (function (_super) {
__extends(PayloadTooLargeException, _super);
/**
* @param message - Optional custom message. Defaults to "Payload Too Large".
*/
function PayloadTooLargeException(message) {
if (message === void 0) { message = "Payload Too Large"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.PAYLOAD_TOO_LARGE;
return _this;
}
return PayloadTooLargeException;
}(ErrorResponse));
export { PayloadTooLargeException };
/**
* Represents a 507 Insufficient Storage Error.
* Used when the server has insufficient storage to complete the request.
*/
var InsufficientStorageException = /** @class */ (function (_super) {
__extends(InsufficientStorageException, _super);
/**
* @param message - Optional custom message. Defaults to "Insufficient Storage".
*/
function InsufficientStorageException(message) {
if (message === void 0) { message = "Insufficient Storage"; }
var _this = _super.call(this, message) || this;
_this.status = HttpStatusCodes.INSUFFICIENT_STORAGE;
return _this;
}
return InsufficientStorageException;
}(ErrorResponse));
export { 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.
*/
export function isHttpError(error) {
return error instanceof 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.
*/
export function createHttpError(status, message) {
switch (status) {
case HttpStatusCodes.BAD_REQUEST:
return new BadRequestException(message);
case HttpStatusCodes.UNAUTHORIZED:
return new UnauthorizedException(message);
case HttpStatusCodes.FORBIDDEN:
return new ForbiddenException(message);
case HttpStatusCodes.NOT_FOUND:
return new NotFoundException(message);
case HttpStatusCodes.METHOD_NOT_ALLOWED:
return new MethodNotAllowedException(message);
case HttpStatusCodes.NOT_ACCEPTABLE:
return new NotAcceptableException(message);
case HttpStatusCodes.REQUEST_TIMEOUT:
return new RequestTimeoutException(message);
case HttpStatusCodes.CONFLICT:
return new ConflictException(message);
case HttpStatusCodes.GONE:
return new HttpError(HttpStatusCodes.GONE, message || "Gone");
case HttpStatusCodes.PAYLOAD_TOO_LARGE:
return new PayloadTooLargeException(message);
case HttpStatusCodes.UNSUPPORTED_MEDIA_TYPE:
return new UnsupportedMediaTypeException(message);
case HttpStatusCodes.UNPROCESSABLE_ENTITY:
return new UnprocessableEntityException(message);
case HttpStatusCodes.TOO_MANY_REQUESTS:
return new TooManyRequestsException(message);
case HttpStatusCodes.INTERNAL_SERVER_ERROR:
return new InternalServerErrorException(message);
case HttpStatusCodes.BAD_GATEWAY:
return new BadGatewayException(message);
case HttpStatusCodes.SERVICE_UNAVAILABLE:
return new ServiceUnavailableException(message);
case HttpStatusCodes.GATEWAY_TIMEOUT:
return new GatewayTimeoutException(message);
case HttpStatusCodes.INSUFFICIENT_STORAGE:
return new InsufficientStorageException(message);
default:
return new HttpError(status, message || "HTTP Error ".concat(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.
*/
export 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.
*/
export 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.
*/
export function withErrorHandling(handler) {
var _this = this;
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return __awaiter(_this, void 0, void 0, function () {
var error_1, status_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, handler.apply(void 0, __spreadArray([], __read(args), false))];
case 1: return [2 /*return*/, _a.sent()];
case 2:
error_1 = _a.sent();
if (isHttpError(error_1)) {
throw error_1;
}
// Log the original error (consider using a proper logger)
getLogger().error("Caught error in handler:", error_1);
status_1 = HttpStatusCodes.INTERNAL_SERVER_ERROR;
if (hasErrorShape(error_1) && typeof error_1.status === "number") {
status_1 = error_1.status;
}
// Create appropriate HTTP error
throw createHttpError(status_1, getErrorMessage(error_1));
case 3: return [2 /*return*/];
}
});
});
};
}
//# sourceMappingURL=exception.utils.js.map