@pulzar/core
Version:
Next-generation Node.js framework for ultra-fast web applications with zero-reflection DI, GraphQL, WebSockets, events, and edge runtime support
104 lines • 4.08 kB
JavaScript
import { logger } from "../utils/logger";
export class ApiError extends Error {
statusCode;
details;
constructor(message, statusCode = 500, details) {
super(message);
this.name = "ApiError";
this.statusCode = statusCode;
if (details !== undefined) {
this.details = details;
}
Error.captureStackTrace(this, ApiError);
}
}
export class ErrorHandler {
options;
constructor(options = {}) {
this.options = {
includeStack: process.env.NODE_ENV === "development",
customErrorCodes: {},
formatError: (error) => {
const apiError = error;
return {
error: error.name || "Error",
message: error.message,
statusCode: apiError.statusCode || 500,
...(apiError.details && { details: apiError.details }),
timestamp: new Date().toISOString(),
};
},
...options,
};
}
/**
* Express error handling middleware
*/
middleware() {
return (error, req, res, next) => {
// Skip if response already sent
if (res.headersSent) {
return next(error);
}
// Get request ID
const requestId = req.headers["x-request-id"] || "unknown";
// Log error
logger.error("Request error", {
error: error.message,
stack: error.stack,
statusCode: error.statusCode || 500,
method: req.method,
url: req.url,
userAgent: req.headers["user-agent"],
ip: req.ip,
requestId,
});
// Format error response
const errorResponse = this.options.formatError(error);
errorResponse.requestId = requestId;
// Add stack trace in development
if (this.options.includeStack && error.stack) {
errorResponse.stack =
error.stack;
}
// Determine status code
const statusCode = error.statusCode ||
this.options.customErrorCodes[error.name] ||
500;
// Send error response
res.status(statusCode).json(errorResponse);
};
}
/**
* Create formatted error response
*/
formatError(error) {
return this.options.formatError(error);
}
}
// Default error handler instance
export const errorHandler = new ErrorHandler();
// Error factory functions
export const ApiErrors = {
BadRequest: (message = "Bad Request", details) => new ApiError(message, 400, details),
Unauthorized: (message = "Unauthorized", details) => new ApiError(message, 401, details),
Forbidden: (message = "Forbidden", details) => new ApiError(message, 403, details),
NotFound: (message = "Not Found", details) => new ApiError(message, 404, details),
MethodNotAllowed: (message = "Method Not Allowed", details) => new ApiError(message, 405, details),
Conflict: (message = "Conflict", details) => new ApiError(message, 409, details),
UnprocessableEntity: (message = "Unprocessable Entity", details) => new ApiError(message, 422, details),
TooManyRequests: (message = "Too Many Requests", details) => new ApiError(message, 429, details),
InternalServerError: (message = "Internal Server Error", details) => new ApiError(message, 500, details),
NotImplemented: (message = "Not Implemented", details) => new ApiError(message, 501, details),
ServiceUnavailable: (message = "Service Unavailable", details) => new ApiError(message, 503, details),
};
// Helper functions
export function isApiError(error) {
return error instanceof ApiError;
}
export function createErrorHandler(options) {
return new ErrorHandler(options).middleware();
}
// Default middleware export
export default errorHandler.middleware();
//# sourceMappingURL=errorHandler.js.map