chore(deps): bump github.com/invopop/validation from 0.3.0 to 0.8.0

Bumps [github.com/invopop/validation](https://github.com/invopop/validation) from 0.3.0 to 0.8.0.
- [Commits](https://github.com/invopop/validation/compare/v0.3.0...v0.8.0)

---
updated-dependencies:
- dependency-name: github.com/invopop/validation
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2024-08-15 11:51:16 +02:00
committed by Ralf Haferkamp
parent d97de49ace
commit eca3eadbb5
9 changed files with 87 additions and 46 deletions
+31
View File
@@ -0,0 +1,31 @@
run:
timeout: "120s"
output:
formats:
- format: "colored-line-number"
linters:
enable:
- "gocyclo"
- "unconvert"
- "goimports"
- "govet"
- "misspell"
- "nakedret"
- "revive"
- "goconst"
- "unparam"
- "gofmt"
linters-settings:
staticcheck:
# SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks
# Default: ["*"]
checks: ["all"]
goconst:
ignore-tests: true
issues:
exclude-use-default: false
+4 -4
View File
@@ -3,7 +3,7 @@
[![Lint](https://github.com/invopop/validation/actions/workflows/lint.yaml/badge.svg)](https://github.com/invopop/validation/actions/workflows/lint.yaml)
[![Test Go](https://github.com/invopop/validation/actions/workflows/test.yaml/badge.svg)](https://github.com/invopop/validation/actions/workflows/test.yaml)
[![GoDoc](https://godoc.org/github.com/invopop/validation?status.png)](http://godoc.org/github.com/invopop/validation)
[![Coverage Status](https://coveralls.io/repos/github/invopop/validation/badge.svg?branch=main)](https://coveralls.io/github/invopop/validation?branch=main)
[![Coverage Status](https://codecov.io/gh/invopop/validation/graph/badge.svg?token=Q3AEO8GZ8G)](https://codecov.io/gh/invopop/validation)
[![Go Report](https://goreportcard.com/badge/github.com/invopop/validation)](https://goreportcard.com/report/github.com/invopop/validation)
![Latest Tag](https://img.shields.io/github/v/tag/invopop/validation)
@@ -607,14 +607,14 @@ When performing context-aware validation, if a rule does not implement `validati
The following rules are provided in the `validation` package:
- `In(...interface{})`: checks if a value can be found in the given list of values.
- `NotIn(...interface{})`: checks if a value is NOT among the given list of values.
- `In[T any](values ...T)`: checks if a value can be found in the given list of values.
- `NotIn[T any](values ...T)`: checks if a value is NOT among the given list of values.
- `Length(min, max int)`: checks if the length of a value is within the specified range.
This rule should only be used for validating strings, slices, maps, and arrays.
- `RuneLength(min, max int)`: checks if the length of a string is within the specified range.
This rule is similar as `Length` except that when the value being validated is a string, it checks
its rune length instead of byte length.
- `Min(min interface{})` and `Max(max interface{})`: checks if a value is within the specified range.
- `Min(min any)` and `Max(max any)`: checks if a value is within the specified range.
These two rules should only be used for validating int, uint, float and time.Time types.
- `Match(*regexp.Regexp)`: checks if a value matches the specified regular expression.
This rule should only be used for strings and byte slices.
+4 -3
View File
@@ -25,9 +25,10 @@ type DateRule struct {
// Date returns a validation rule that checks if a string value is in a format that can be parsed into a date.
// The format of the date should be specified as the layout parameter which accepts the same value as that for time.Parse.
// For example,
// validation.Date(time.ANSIC)
// validation.Date("02 Jan 06 15:04 MST")
// validation.Date("2006-01-02")
//
// validation.Date(time.ANSIC)
// validation.Date("02 Jan 06 15:04 MST")
// validation.Date("2006-01-02")
//
// By calling Min() and/or Max(), you can let the Date rule to check if a parsed date value is within
// the specified date range.
+7 -7
View File
@@ -15,21 +15,21 @@ var ErrInInvalid = NewError("validation_in_invalid", "must be a valid value")
// reflect.DeepEqual() will be used to determine if two values are equal.
// For more details please refer to https://golang.org/pkg/reflect/#DeepEqual
// An empty value is considered valid. Use the Required rule to make sure a value is not empty.
func In(values ...interface{}) InRule {
return InRule{
func In[T any](values ...T) InRule[T] {
return InRule[T]{
elements: values,
err: ErrInInvalid,
}
}
// InRule is a validation rule that validates if a value can be found in the given list of values.
type InRule struct {
elements []interface{}
type InRule[T any] struct {
elements []T
err Error
}
// Validate checks if the given value is valid or not.
func (r InRule) Validate(value interface{}) error {
func (r InRule[T]) Validate(value interface{}) error {
value, isNil := Indirect(value)
if isNil || IsEmpty(value) {
return nil
@@ -45,13 +45,13 @@ func (r InRule) Validate(value interface{}) error {
}
// Error sets the error message for the rule.
func (r InRule) Error(message string) InRule {
func (r InRule[T]) Error(message string) InRule[T] {
r.err = r.err.SetMessage(message)
return r
}
// ErrorObject sets the error struct for the rule.
func (r InRule) ErrorObject(err Error) InRule {
func (r InRule[T]) ErrorObject(err Error) InRule[T] {
r.err = err
return r
}
+11 -9
View File
@@ -4,34 +4,36 @@
package validation
import "reflect"
// ErrNotInInvalid is the error that returns when a value is in a list.
var ErrNotInInvalid = NewError("validation_not_in_invalid", "must not be in list")
// NotIn returns a validation rule that checks if a value is absent from the given list of values.
// Note that the value being checked and the possible range of values must be of the same type.
// Like with In(), reflect.DeepEqual() will be used to determine if two values are equal.
// An empty value is considered valid. Use the Required rule to make sure a value is not empty.
func NotIn(values ...interface{}) NotInRule {
return NotInRule{
func NotIn[T any](values ...T) NotInRule[T] {
return NotInRule[T]{
elements: values,
err: ErrNotInInvalid,
}
}
// NotInRule is a validation rule that checks if a value is absent from the given list of values.
type NotInRule struct {
elements []interface{}
type NotInRule[T any] struct {
elements []T
err Error
}
// Validate checks if the given value is valid or not.
func (r NotInRule) Validate(value interface{}) error {
func (r NotInRule[T]) Validate(value interface{}) error {
value, isNil := Indirect(value)
if isNil || IsEmpty(value) {
return nil
}
for _, e := range r.elements {
if e == value {
if reflect.DeepEqual(e, value) {
return r.err
}
}
@@ -39,13 +41,13 @@ func (r NotInRule) Validate(value interface{}) error {
}
// Error sets the error message for the rule.
func (r NotInRule) Error(message string) NotInRule {
func (r NotInRule[T]) Error(message string) NotInRule[T] {
r.err = r.err.SetMessage(message)
return r
}
// ErrorObject sets the error struct for the rule.
func (r NotInRule) ErrorObject(err Error) NotInRule {
func (r NotInRule[T]) ErrorObject(err Error) NotInRule[T] {
r.err = err
return r
}
+25 -17
View File
@@ -60,11 +60,11 @@ var (
// Validate validates the given value and returns the validation error, if any.
//
// Validate performs validation using the following steps:
// 1. For each rule, call its `Validate()` to validate the value. Return if any error is found.
// 2. If the value being validated implements `Validatable`, call the value's `Validate()`.
// Return with the validation result.
// 3. If the value being validated is a map/slice/array, and the element type implements `Validatable`,
// for each element call the element value's `Validate()`. Return with the validation result.
// 1. For each rule, call its `Validate()` to validate the value. Return if any error is found.
// 2. If the value being validated implements `Validatable`, call the value's `Validate()`.
// Return with the validation result.
// 3. If the value being validated is a map/slice/array, and the element type implements `Validatable`,
// for each element call the element value's `Validate()`. Return with the validation result.
func Validate(value interface{}, rules ...Rule) error {
for _, rule := range rules {
if s, ok := rule.(skipRule); ok && s.skip {
@@ -103,16 +103,16 @@ func Validate(value interface{}, rules ...Rule) error {
// ValidateWithContext validates the given value with the given context and returns the validation error, if any.
//
// ValidateWithContext performs validation using the following steps:
// 1. For each rule, call its `ValidateWithContext()` to validate the value if the rule implements `RuleWithContext`.
// Otherwise call `Validate()` of the rule. Return if any error is found.
// 2. If the value being validated implements `ValidatableWithContext`, call the value's `ValidateWithContext()`
// and return with the validation result.
// 3. If the value being validated implements `Validatable`, call the value's `Validate()`
// and return with the validation result.
// 4. If the value being validated is a map/slice/array, and the element type implements `ValidatableWithContext`,
// for each element call the element value's `ValidateWithContext()`. Return with the validation result.
// 5. If the value being validated is a map/slice/array, and the element type implements `Validatable`,
// for each element call the element value's `Validate()`. Return with the validation result.
// 1. For each rule, call its `ValidateWithContext()` to validate the value if the rule implements `RuleWithContext`.
// Otherwise call `Validate()` of the rule. Return if any error is found.
// 2. If the value being validated implements `ValidatableWithContext`, call the value's `ValidateWithContext()`
// and return with the validation result.
// 3. If the value being validated implements `Validatable`, call the value's `Validate()`
// and return with the validation result.
// 4. If the value being validated is a map/slice/array, and the element type implements `ValidatableWithContext`,
// for each element call the element value's `ValidateWithContext()`. Return with the validation result.
// 5. If the value being validated is a map/slice/array, and the element type implements `Validatable`,
// for each element call the element value's `Validate()`. Return with the validation result.
func ValidateWithContext(ctx context.Context, value interface{}, rules ...Rule) error {
for _, rule := range rules {
if s, ok := rule.(skipRule); ok && s.skip {
@@ -199,7 +199,11 @@ func validateSlice(rv reflect.Value) error {
errs := Errors{}
l := rv.Len()
for i := 0; i < l; i++ {
if ev := rv.Index(i).Interface(); ev != nil {
v := rv.Index(i)
if v.Kind() == reflect.Ptr && v.IsNil() {
continue
}
if ev := v.Interface(); ev != nil {
if err := ev.(Validatable).Validate(); err != nil {
errs[strconv.Itoa(i)] = err
}
@@ -216,7 +220,11 @@ func validateSliceWithContext(ctx context.Context, rv reflect.Value) error {
errs := Errors{}
l := rv.Len()
for i := 0; i < l; i++ {
if ev := rv.Index(i).Interface(); ev != nil {
v := rv.Index(i)
if v.Kind() == reflect.Ptr && v.IsNil() {
continue
}
if ev := v.Interface(); ev != nil {
if err := ev.(ValidatableWithContext).ValidateWithContext(ctx); err != nil {
errs[strconv.Itoa(i)] = err
}