123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- package errors
- import (
- "fmt"
- "net/http"
- )
- // ErrorType represents the type of error
- type ErrorType string
- const (
- ErrorTypeValidation ErrorType = "VALIDATION_ERROR"
- ErrorTypeAuthorization ErrorType = "AUTHORIZATION_ERROR"
- ErrorTypeAuthentication ErrorType = "AUTHENTICATION_ERROR"
- ErrorTypeNotFound ErrorType = "NOT_FOUND"
- ErrorTypeConflict ErrorType = "CONFLICT"
- ErrorTypeInternal ErrorType = "INTERNAL_ERROR"
- ErrorTypeBadRequest ErrorType = "BAD_REQUEST"
- )
- // AppError represents an application error
- type AppError struct {
- Type ErrorType `json:"type"`
- Message string `json:"message"`
- Detail string `json:"detail,omitempty"`
- Field string `json:"field,omitempty"`
- Code int `json:"-"`
- Err error `json:"-"`
- }
- func (e *AppError) Error() string {
- if e.Detail != "" {
- return fmt.Sprintf("%s: %s (%s)", e.Type, e.Message, e.Detail)
- }
- return fmt.Sprintf("%s: %s", e.Type, e.Message)
- }
- func (e *AppError) Unwrap() error {
- return e.Err
- }
- // Error constructors
- func NewValidationError(message, field string) *AppError {
- return &AppError{
- Type: ErrorTypeValidation,
- Message: message,
- Field: field,
- Code: http.StatusBadRequest,
- }
- }
- func NewAuthorizationError(message string) *AppError {
- return &AppError{
- Type: ErrorTypeAuthorization,
- Message: message,
- Code: http.StatusForbidden,
- }
- }
- func NewAuthenticationError(message string) *AppError {
- return &AppError{
- Type: ErrorTypeAuthentication,
- Message: message,
- Code: http.StatusUnauthorized,
- }
- }
- func NewNotFoundError(resource, id string) *AppError {
- return &AppError{
- Type: ErrorTypeNotFound,
- Message: fmt.Sprintf("%s not found", resource),
- Detail: fmt.Sprintf("ID: %s", id),
- Code: http.StatusNotFound,
- }
- }
- func NewConflictError(message, detail string) *AppError {
- return &AppError{
- Type: ErrorTypeConflict,
- Message: message,
- Detail: detail,
- Code: http.StatusConflict,
- }
- }
- func NewInternalError(message string, err error) *AppError {
- return &AppError{
- Type: ErrorTypeInternal,
- Message: message,
- Detail: err.Error(),
- Code: http.StatusInternalServerError,
- Err: err,
- }
- }
- // Error type checks
- func IsNotFound(err error) bool {
- if err == nil {
- return false
- }
- if e, ok := err.(*AppError); ok {
- return e.Type == ErrorTypeNotFound
- }
- return false
- }
- func IsValidation(err error) bool {
- if err == nil {
- return false
- }
- if e, ok := err.(*AppError); ok {
- return e.Type == ErrorTypeValidation
- }
- return false
- }
- func IsAuthorization(err error) bool {
- if err == nil {
- return false
- }
- if e, ok := err.(*AppError); ok {
- return e.Type == ErrorTypeAuthorization || e.Type == ErrorTypeAuthentication
- }
- return false
- }
- // WithDetail adds detail to an existing error
- func WithDetail(err *AppError, detail string) *AppError {
- if err == nil {
- return nil
- }
- err.Detail = detail
- return err
- }
- // WithField adds a field name to an existing error
- func WithField(err *AppError, field string) *AppError {
- if err == nil {
- return nil
- }
- err.Field = field
- return err
- }
|