package apperror import ( "api.qobiltu.id/validation" "fmt" ) // AppError is a custom error type for the application. type AppError struct { Code string // Optional: Error code for programmatic handling Message string // Human-readable error message Err error // Underlying error, if any Details map[string]any // Optional: Additional details about the error } func (e AppError) Error() string { if e.Code != "" { return fmt.Sprintf("[%s] %s", e.Code, e.Message) } return e.Message } // NewAppError creates a new AppError. func NewAppError(code, message string, err error, details map[string]any) error { return &AppError{ Code: code, Message: message, Err: err, Details: details, } } // ValidationError represents errors related to data validation. type ValidationError struct { Errors []validation.ErrorMessage // Structure to hold field and message of validation errors } func (e ValidationError) Error() string { return fmt.Sprintf("validation failed: %+v", e.Errors) } // NewValidationError creates a new ValidationError. func NewValidationError(message string, errors []validation.ErrorMessage) error { return &AppError{ Code: "VALIDATION_ERROR", Message: message, Err: ValidationError{Errors: errors}, } } // InternalError represents unexpected errors within the application. type InternalError struct { Message string Err error } func (e InternalError) Error() string { return fmt.Sprintf("internal server error: %v", e.Err) } // NewInternalError creates a new InternalError wrapped in AppError. func NewInternalError(message string, err error) error { return &AppError{ Code: "INTERNAL_ERROR", Message: message, Err: InternalError{Message: message, Err: err}, } } // ConflictError represents errors due to a conflict with the current state. type ConflictError struct { Message string Err error } func (e ConflictError) Error() string { return fmt.Sprintf("conflict: %s", e.Err) } // NewConflictError creates a new ConflictError wrapped in AppError. func NewConflictError(message string, err error) error { return &AppError{ Code: "CONFLICT_ERROR", Message: message, Err: ConflictError{Message: message, Err: err}, } } // NotFoundError represents errors when a resource is not found. type NotFoundError struct { Message string Resource string ID any } func (e NotFoundError) Error() string { return fmt.Sprintf("%s with ID '%v' not found", e.Resource, e.ID) } // NewNotFoundError creates a new NotFoundError wrapped in AppError. func NewNotFoundError(resource string, id any) error { message := fmt.Sprintf("%s not found", resource) return &AppError{ Code: "NOT_FOUND_ERROR", Message: fmt.Sprintf("%s not found", resource), Err: NotFoundError{Message: message, Resource: resource, ID: id}, Details: map[string]any{ "resource": resource, "id": id, }, } } // UnauthorizedError represents errors when access is denied due to lack of credentials. type UnauthorizedError struct { Message string Err error } func (e UnauthorizedError) Error() string { return fmt.Sprintf("unauthorized: %s", e.Err) } // NewUnauthorizedError creates a new UnauthorizedError wrapped in AppError. func NewUnauthorizedError(message string, err error) error { return &AppError{ Code: "UNAUTHORIZED_ERROR", Message: message, Err: UnauthorizedError{Message: message, Err: err}, } } // ForbiddenError represents errors when access is denied even with valid credentials. type ForbiddenError struct { Message string Err error } func (e ForbiddenError) Error() string { return fmt.Sprintf("forbidden: %s", e.Err) } // NewForbiddenError creates a new ForbiddenError wrapped in AppError. func NewForbiddenError(message string, err error) error { return &AppError{ Code: "FORBIDDEN_ERROR", Message: message, Err: ForbiddenError{Message: message, Err: err}, } } // BadRequestError represents errors due to an invalid request. type BadRequestError struct { Message string Err error } func (e BadRequestError) Error() string { return fmt.Sprintf("bad request: %s", e.Err) } func NewBadRequestError(message string, err error) error { return &AppError{ Code: "BAD_REQUEST_ERROR", Message: message, Err: BadRequestError{Message: message, Err: err}, } }