File size: 4,373 Bytes
48471f7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
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},
	}
}