package errors import ( "errors" "net/http" "github.com/go-sql-driver/mysql" "gorm.io/gorm" ) // APIError defines a standard error structure for API responses. type APIError struct { HTTPStatus int Code string Message string } // Error implements the error interface. func (e *APIError) Error() string { return e.Message } // Predefined API errors var ( ErrBadRequest = &APIError{HTTPStatus: http.StatusBadRequest, Code: "BAD_REQUEST", Message: "Invalid request parameters"} ErrInvalidJSON = &APIError{HTTPStatus: http.StatusBadRequest, Code: "INVALID_JSON", Message: "Invalid JSON format"} ErrValidation = &APIError{HTTPStatus: http.StatusBadRequest, Code: "VALIDATION_FAILED", Message: "Input validation failed"} ErrDuplicateResource = &APIError{HTTPStatus: http.StatusConflict, Code: "DUPLICATE_RESOURCE", Message: "Resource already exists"} ErrResourceNotFound = &APIError{HTTPStatus: http.StatusNotFound, Code: "NOT_FOUND", Message: "Resource not found"} ErrInternalServer = &APIError{HTTPStatus: http.StatusInternalServerError, Code: "INTERNAL_SERVER_ERROR", Message: "An unexpected error occurred"} ErrDatabase = &APIError{HTTPStatus: http.StatusInternalServerError, Code: "DATABASE_ERROR", Message: "Database operation failed"} ErrUnauthorized = &APIError{HTTPStatus: http.StatusUnauthorized, Code: "UNAUTHORIZED", Message: "Authentication failed"} ErrForbidden = &APIError{HTTPStatus: http.StatusForbidden, Code: "FORBIDDEN", Message: "You do not have permission to access this resource"} ErrTaskInProgress = &APIError{HTTPStatus: http.StatusConflict, Code: "TASK_IN_PROGRESS", Message: "A task is already in progress"} ErrBadGateway = &APIError{HTTPStatus: http.StatusBadGateway, Code: "BAD_GATEWAY", Message: "Upstream service error"} ) // NewAPIError creates a new APIError with a custom message. func NewAPIError(base *APIError, message string) *APIError { return &APIError{ HTTPStatus: base.HTTPStatus, Code: base.Code, Message: message, } } // ParseDBError intelligently converts a GORM error into a standard APIError. func ParseDBError(err error) *APIError { if err == nil { return nil } // Handle record not found error if errors.Is(err, gorm.ErrRecordNotFound) { return ErrResourceNotFound } // Handle MySQL specific errors var mysqlErr *mysql.MySQLError if errors.As(err, &mysqlErr) { switch mysqlErr.Number { case 1062: // Duplicate entry for unique key return ErrDuplicateResource } } // Default to a generic database error return ErrDatabase }