package validate import ( "errors" "fmt" "strings" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" errs "gateway/internal/library/errors" "gateway/internal/library/errors/code" ) // ValidationError holds information about a single validation error. type ValidationError struct { Field string `json:"field"` Message string `json:"message"` } // ValidationErrors is a slice of ValidationError that implements the error interface. type ValidationErrors []ValidationError func (ve ValidationErrors) Error() string { if len(ve) == 0 { return "" } var sb strings.Builder sb.WriteString("validation failed:") for i, e := range ve { fmt.Fprintf(&sb, " field='%s', message='%s'", e.Field, e.Message) if i < len(ve)-1 { sb.WriteString(";") } } return sb.String() } // Is supports errors.Is when comparing against ValidationErrors. func (ValidationErrors) Is(target error) bool { _, ok := target.(ValidationErrors) return ok } // AsErrors unwraps err into ValidationErrors when present. func AsErrors(err error) (ValidationErrors, bool) { var ve ValidationErrors if errors.As(err, &ve) { return ve, true } return nil, false } // ToBusinessError maps field validation failures to InputInvalidFormat (HTTP 400). func (ve ValidationErrors) ToBusinessError(scope code.Scope) *errs.Error { return errs.For(scope).InputInvalidFormat(ve.Error()) } // translateValidationErrors converts validator.ValidationErrors to our custom ValidationErrors. func translateValidationErrors(valErrs validator.ValidationErrors, trans ut.Translator) ValidationErrors { customErrors := make(ValidationErrors, 0, len(valErrs)) for _, err := range valErrs { customErrors = append(customErrors, ValidationError{ Field: err.Field(), // Already transformed by RegisterTagNameFunc Message: err.Translate(trans), }) } return customErrors }