refactored for maintainability
This commit is contained in:
106
internal/validation/stringfield.go
Normal file
106
internal/validation/stringfield.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type StringField struct {
|
||||
Field
|
||||
Value string
|
||||
}
|
||||
|
||||
func newStringField(key string, g Getter) *StringField {
|
||||
return &StringField{
|
||||
Value: g.Get(key),
|
||||
Field: newField(key, g),
|
||||
}
|
||||
}
|
||||
|
||||
// Required enforces a non empty string
|
||||
func (s *StringField) Required() *StringField {
|
||||
if s.Value == "" {
|
||||
s.getter.AddCheck(newFailedCheck(
|
||||
"Field not provided",
|
||||
fmt.Sprintf("%s is required", s.Key),
|
||||
))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Optional will skip all validations if value is empty
|
||||
func (s *StringField) Optional() *StringField {
|
||||
if s.Value == "" {
|
||||
s.optional = true
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// MaxLength enforces a maximum string length
|
||||
func (s *StringField) MaxLength(length int) *StringField {
|
||||
if len(s.Value) > length && !s.optional {
|
||||
s.getter.AddCheck(newFailedCheck(
|
||||
"Input too long",
|
||||
fmt.Sprintf("%s is too long, max %v chars", s.Key, length),
|
||||
))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// MinLength enforces a minimum string length
|
||||
func (s *StringField) MinLength(length int) *StringField {
|
||||
if len(s.Value) < length && !s.optional {
|
||||
s.getter.AddCheck(newFailedCheck(
|
||||
"Input too short",
|
||||
fmt.Sprintf("%s is too short, min %v chars", s.Key, length),
|
||||
))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// AlphaNumeric enforces the string contains only letters and numbers
|
||||
func (s *StringField) AlphaNumeric() *StringField {
|
||||
if s.optional {
|
||||
return s
|
||||
}
|
||||
for _, r := range s.Value {
|
||||
if !unicode.IsLetter(r) && !unicode.IsDigit(r) {
|
||||
s.getter.AddCheck(newFailedCheck(
|
||||
"Invalid characters",
|
||||
fmt.Sprintf("%s must contain only letters and numbers.", s.Key),
|
||||
))
|
||||
return s
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *StringField) AllowedValues(allowed []string) *StringField {
|
||||
if !slices.Contains(allowed, s.Value) && !s.optional {
|
||||
s.getter.AddCheck(newFailedCheck(
|
||||
"Value not allowed",
|
||||
fmt.Sprintf("%s must be one of: %s", s.Key, strings.Join(allowed, ",")),
|
||||
))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// ToUpper transforms the string to uppercase
|
||||
func (s *StringField) ToUpper() *StringField {
|
||||
s.Value = strings.ToUpper(s.Value)
|
||||
return s
|
||||
}
|
||||
|
||||
// ToLower transforms the string to lowercase
|
||||
func (s *StringField) ToLower() *StringField {
|
||||
s.Value = strings.ToLower(s.Value)
|
||||
return s
|
||||
}
|
||||
|
||||
// TrimSpace removes leading and trailing whitespace
|
||||
func (s *StringField) TrimSpace() *StringField {
|
||||
s.Value = strings.TrimSpace(s.Value)
|
||||
return s
|
||||
}
|
||||
Reference in New Issue
Block a user