// Copyright 2024 Patial Tech (Ankit Patial). // // This file is part of code.patial.tech/go/appcore, which is MIT licensed. // See http://opensource.org/licenses/MIT package validate import ( "errors" "fmt" "reflect" "strings" "github.com/go-playground/validator/v10" ) var validate *validator.Validate func init() { validate = validator.New() // register function to get tag name from json tags. validate.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) } // RegisterAlias for single/multuple tags func RegisterAlias(alias, tags string) { validate.RegisterAlias(alias, tags) } func RegisterValidation(tagName string, fn validator.Func, callValidationEvenIfNull ...bool) { validate.RegisterValidation(tagName, fn, callValidationEvenIfNull...) } // Struct validator func Struct(s any) error { err := validate.Struct(s) if IsInvalidValidationError(err) { return err } var valErrs validator.ValidationErrors if !errors.As(err, &valErrs) { return err } var sb strings.Builder for _, err := range valErrs { switch err.Tag() { case "required": sb.WriteString(fmt.Sprintf("%s: is required.\n", err.Field())) case "email": sb.WriteString(fmt.Sprintf("%s: is invalid.\n", err.Field())) default: sb.WriteString(fmt.Sprintf("%s: %q validation failed.\n", err.Field(), err.Tag())) } } return errors.New(sb.String()) } // Map validator func Map(data map[string]any, rules map[string]any) map[string]any { return validate.ValidateMap(data, rules) } func IsInvalidValidationError(err error) bool { var v *validator.InvalidValidationError return errors.As(err, &v) }