package errors import ( "errors" "fmt" "net/http" ) type AppError struct { Code string Message string HTTPCode int Cause error } func (e *AppError) Error() string { if e.Cause != nil { return fmt.Sprintf("[%s] %s: %v", e.Code, e.Message, e.Cause) } return fmt.Sprintf("[%s] %s", e.Code, e.Message) } func (e *AppError) Unwrap() error { return e.Cause } func New(code, message string, httpCode int) *AppError { return &AppError{Code: code, Message: message, HTTPCode: httpCode} } func Wrap(cause error, code, message string, httpCode int) *AppError { return &AppError{Code: code, Message: message, HTTPCode: httpCode, Cause: cause} } func IsAppError(err error) (*AppError, bool) { var appErr *AppError if errors.As(err, &appErr) { return appErr, true } return nil, false } var ( ErrInvalidParam = New("INVALID_PARAM", "invalid parameter", http.StatusBadRequest) ErrUnauthorized = New("UNAUTHORIZED", "unauthorized", http.StatusUnauthorized) ErrForbidden = New("FORBIDDEN", "forbidden", http.StatusForbidden) ErrNotFound = New("NOT_FOUND", "resource not found", http.StatusNotFound) ErrConflict = New("CONFLICT", "resource already exists", http.StatusConflict) ErrInternal = New("INTERNAL_ERROR", "internal server error", http.StatusInternalServerError) ErrTenantRequired = New("TENANT_REQUIRED", "tenant context required", http.StatusBadRequest) ErrTokenExpired = New("TOKEN_EXPIRED", "token expired", http.StatusUnauthorized) ErrTokenInvalid = New("TOKEN_INVALID", "invalid token", http.StatusUnauthorized) ErrPasswordWrong = New("PASSWORD_WRONG", "wrong password", http.StatusUnauthorized) ErrUserNotFound = New("USER_NOT_FOUND", "user not found", http.StatusNotFound) ErrUserExists = New("USER_EXISTS", "user already exists", http.StatusConflict) ErrRefreshToken = New("REFRESH_TOKEN_INVALID", "invalid refresh token", http.StatusUnauthorized) )