Documentation
¶
Index ¶
- Variables
- func All(vals ...any) bool
- func AllFunc(f func(any) bool, vals ...any) bool
- func AllUnique[T comparable](vals []T) bool
- func AnyToFloat64(value any) (float64, bool)
- func DifferenceInDays(dt1, dt2 time.Time) int
- func HasValue(val any) bool
- func HasValue__SkipNumeric(val any) bool
- func IsStrongPassword(password string) bool
- func None(vals ...any) bool
- func NoneFunc(f func(any) bool, vals ...any) bool
- func Some(vals ...any) bool
- func SomeFunc(f func(any) bool, vals ...any) bool
- type ErrorMessages
- type Field
- type Fields
- func (fields *Fields) GetField(fieldName string) *Field
- func (fields *Fields) SetField(fieldName string, newField *Field) *Fields
- func (fields *Fields) SetLanguage(lang languages.Language) *Fields
- func (fields *Fields) SetRuleOpts(fieldNames []string, opts *RuleSetOpts) *Fields
- func (fields *Fields) SetRuleOptsForAll(opts *RuleSetOpts) *Fields
- func (fields *Fields) SetRules(fieldName string, rules Rules) *Fields
- func (fields *Fields) SetValue(fieldName string, value any) *Fields
- func (fields *Fields) SetValues(values map[string]any) *Fields
- func (fields *Fields) String() string
- type RuleSet
- func After(dt time.Time) *RuleSet
- func Before(dt time.Time) *RuleSet
- func CEP() *RuleSet
- func Cnpj() *RuleSet
- func Contains(substr string) *RuleSet
- func ContainsAll(substrs ...string) *RuleSet
- func ContainsNone(substrs ...string) *RuleSet
- func ContainsSome(substrs ...string) *RuleSet
- func Cpf() *RuleSet
- func CpfCnpj() *RuleSet
- func Email() *RuleSet
- func EqualTo[T comparable](value T) *RuleSet
- func False() *RuleSet
- func GreaterThan[T int | float64 | float32](n T) *RuleSet
- func GreaterThanOrEqualTo[T int | float64 | float32](n T) *RuleSet
- func LessThan[T int | float64 | float32](n T) *RuleSet
- func LessThanOrEqualTo[T int | float64 | float32](n T) *RuleSet
- func Match(regexes ...*regexp.Regexp) *RuleSet
- func MatchList(regexes ...*regexp.Regexp) *RuleSet
- func Max(maxValue int) *RuleSet
- func MaxDaysRange(dt time.Time, maxDays int) *RuleSet
- func Min(minValue int) *RuleSet
- func NewRuleSet(ruleName string) *RuleSet
- func NoWhitespace() *RuleSet
- func NotAfter(dt time.Time) *RuleSet
- func NotBefore(dt time.Time) *RuleSet
- func NotContains(substr string) *RuleSet
- func NotEqualTo[T comparable](value T) *RuleSet
- func NotOneOf[T comparable](vals []T) *RuleSet
- func OneOf[T comparable](vals []T) *RuleSet
- func Phone() *RuleSet
- func Required() *RuleSet
- func RequiredIf(vals ...any) *RuleSet
- func RequiredUnless(vals ...any) *RuleSet
- func StopIf(cond bool) *RuleSet
- func StopIfFunc(f func(fieldValue any) bool) *RuleSet
- func StopIfNoValue() *RuleSet
- func StrongPassword() *RuleSet
- func True() *RuleSet
- func UUIDstr() *RuleSet
- func UniqueList[T comparable]() *RuleSet
- func (rs *RuleSet) HasValue() bool
- func (rs *RuleSet) String() string
- func (rs *RuleSet) WithFlowFunc(f func(*RuleSet) bool) *RuleSet
- func (rs *RuleSet) WithMessage(msg string) *RuleSet
- func (rs *RuleSet) WithMessageFunc(f func(*RuleSet) string) *RuleSet
- func (rs *RuleSet) WithOpts(opts *RuleSetOpts) *RuleSet
- func (rs *RuleSet) WithValidateFunc(f func(*RuleSet) bool) *RuleSet
- type RuleSetOpts
- type Rules
Constants ¶
This section is empty.
Variables ¶
var AddressNumberRegex = regexp.MustCompile(`^(?:s\/n|S\/n|S\/N|s\/N)|^(\d)*$`)
numbers or "S/N", "s/n", "S/n", "s/N"
var CepRegex = regexp.MustCompile(`(^\d{5})\-?(\d{3}$)`)
with or without dash (-)
var CnpjRegex = regexp.MustCompile(`^(\d{2}\.?\d{3}\.?\d{3}\/?\d{4}\-?\d{2})$`)
with or without symbols (.-/)
var CpfRegex = regexp.MustCompile(`^\d{3}\.?\d{3}\.?\d{3}\-?\d{2}$`)
with or without symbols (.-/)
var EmailRegex = regexp.MustCompile(`[^@ \t\r\n]+@[^@ \t\r\n]+\.[^@ \t\r\n]+`)
var HasDigitRegex = regexp.MustCompile(`[\d]`)
var HasLowercaseRegex = regexp.MustCompile(`[a-z]`)
var HasSpecialCharacterRegex = regexp.MustCompile(`[@#$%&*!-+&*]`)
var HasUppercaseRegex = regexp.MustCompile(`[A-Z]`)
var NoWhitespaceRegex = regexp.MustCompile(`^\S+$`)
var PhoneRegex = regexp.MustCompile(`(?:(?:\+|00)?(55)\s?)?(?:\(?([1-9][0-9])\)?\s?)(?:((?:9\d|[2-9])\d{3})\-?(\d{4}))`)
with or without symbols (+-()) and whitespaces
var UUIDRegex = regexp.MustCompile(`^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-(1|4|5|7)[a-fA-F0-9]{3}-[89abAB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$`)
var WhateverRegex = regexp.MustCompile(`.*`)
literally accept anything
Functions ¶
func All ¶
A helper function. All provided arguments must have a valid value (meaning no zero values).
Example usage:
fields := Fields{ { Name: "Ie", Value: e.Ie, Rules: safe.Rules( safe.Match(safe.IEMGRegex), safe.RequiredUnless(safe.All(e.PostalCode, e.Neighborhood, e.StreetType, e.StreetName, e.Number)), ), }, }
In the example above, Ie is required, unless all address info is provided.
To achieve this, the safe.All helper function is used to return a boolean, indicating if all those values are valid non-zero values or not.
Note that this is needed because safe.RequiredUnless satisfies its condition when at least one of its arguments have a value.
On the other hand, with the use of safe.All, we ensure that all those address infos have a non-zero value.
func AllUnique ¶
func AllUnique[T comparable](vals []T) bool
Given a list of values, all of them should be unique.
func AnyToFloat64 ¶ added in v1.3.0
A helper function to convert a value of type any to a float64
This can be used in validation functions to easily validate number fields
func DifferenceInDays ¶ added in v1.1.0
A helper function to calculate the difference in days of two datetime values.
Please note that this function will completely ignore the hours, minutes, seconds and so on. It will purely considerer the days.
The order of the arguments does not matter, and which one comes first or last in time does not matter as well.
func HasValue ¶
In safe, the concept of "having a value" is described as follows:
bool: it must be true. string: it must have more than one rune (or character, if you will). int, float64, float32: it must not be zero. time.Time: it must not be the zero time instant, as prescribed by time.Time.IsZero. struct{}: empty structs are not considered as "having a value" anything else: is not nil
func HasValue__SkipNumeric ¶ added in v1.4.0
Exactly the same as safe.HasValue, but skip numeric values.
This means that zero is a valid number
func IsStrongPassword ¶
A helper function to determine if a password is considered strong.
This means 8+ characters, with lowercase and uppercase letters, numbers and special characters.
func None ¶ added in v1.3.0
A helper function. None of the provided arguments should have a valid value (meaning they should all be zero values).
Exactly the opposite of safe.All.
Here is an example of how it might be used:
fields := Fields{ { Name: "Ie", Value: e.Ie, Rules: safe.Rules( safe.Match(safe.IEMGRegex), safe.RequiredIf(safe.None(e.PostalCode, e.Neighborhood, e.StreetType, e.StreetName, e.Number)), ), }, }
In the example above, Ie is required only when none of the address fields have a value.
In essence, we are achieving the same behavior of the example in the safe.All docs.
func NoneFunc ¶ added in v1.4.0
A helper function. None of the provided arguments should satisfy f(val).
Types ¶
type ErrorMessages ¶
safe.Validate returns (safe.ErrorMessages, bool).
safe.ErrorMessages is a map of field names, each associated with a message.
Example:
fields := safe.Fields{ {...} } errors, ok := Validate(fields) if !ok { fmt.Println("why is username not valid?", errors["Username"]) fmt.Println("why is email not valid?", errors["Email"]) }
func Validate ¶
func Validate(fields Fields) (ErrorMessages, bool)
Expects Fields, which is just a []*Field. Each Field has a slice of Rules. All of them are evalueted sequentially.
When a Field is not valid, no more validations are performed for that specific field, so we proceed to the next one.
Validate returns two values:
1) ErrorMessages, a map in which the keys correspond to the Field.Name property, and the values are string error messages according to the broken rule.
2) A bool, indicating if all fields are valid or not. In case this is true, ErrorMessages is nil.
Example usage:
fields := safe.Fields{ {...} } errors, ok := Validate(fields) fmt.Println("are all fields valid?", ok) fmt.Println("is there any error message?", errors)
func (*ErrorMessages) Error ¶
func (errors *ErrorMessages) Error() string
Implements the error interface. Calls the JSON method and converts it to string.
func (*ErrorMessages) JSON ¶
func (errors *ErrorMessages) JSON() []byte
Returns the JSON version of ErrorMessages
In case of error, returns an empty []byte
type Field ¶
type Field struct { // Name is used as a key in the ErrorMessages map when the field is not valid Name string Value any Rules Rules }
An individual Field to be validated.
It is highly advisable to use safe.Fields instead, since safe.Validate expects safe.Fields as argument.
func (*Field) SetLanguage ¶ added in v1.4.0
Set language for all rules in the field.
func (*Field) SetRuleOpts ¶ added in v1.4.0
func (f *Field) SetRuleOpts(opts *RuleSetOpts) *Field
Set rule opts for all rules in the field.
type Fields ¶
type Fields []*Field
A slice of fields to be validated. Each Field has a name, a value and a set of rules.
Example usage:
fields := safe.Fields{ { Name: "Email", Value: user.Email, Rules: safe.Rules{safe.Requiredi(), safe.Email(), safe.Max(128)}, }, { Name: "Password", Value: user.Password, Rules: safe.Rules{safe.Required(), safe.Max(128), safe.StrongPassword()}, }, }
func (*Fields) SetLanguage ¶ added in v1.1.0
Sets the language for all field rules
If no language is set, it defaults to messages.DefaultLang
func (*Fields) SetRuleOpts ¶ added in v1.4.0
func (fields *Fields) SetRuleOpts(fieldNames []string, opts *RuleSetOpts) *Fields
Sets rule set options to the fields matching fieldNames
func (*Fields) SetRuleOptsForAll ¶ added in v1.4.0
func (fields *Fields) SetRuleOptsForAll(opts *RuleSetOpts) *Fields
Sets rule set options to all fields
func (*Fields) SetRules ¶
Set rules for a specific field. This will overwrite the existing rules in the field.
func (*Fields) SetValue ¶
Set a value for a specific field. This will overwrite the existing value in the field.
func (*Fields) SetValues ¶ added in v1.2.0
Set values for multiple fields. This will overwrite the existing values in the fields.
The key is the field.Name and the value is the new value to be assigned. Example usage:
fields := safe.Fields{ { Name: "field_1", Value: "field_1_value", Rules: safe.Rules{...}, }, { Name: "field_2", Value: "field_2_value", Rules: safe.Rules{...}, }, { Name: "field_3", Value: "field_3_value", Rules: safe.Rules{...}, }, } fields.SetValues(map[string]any{ "field_1": "another_value_for_field_1", "field_2": "another_value_for_field_2", "field_3": "another_value_for_field_3", })
type RuleSet ¶
type RuleSet struct { RuleName string FieldValue any MessageFunc func(*RuleSet) string ValidateFunc func(*RuleSet) bool // returns true if is valid, false otherwise FlowFunc func(*RuleSet) bool // returns true if should proceed, false otherwise Language languages.Language Opts *RuleSetOpts }
A safe.RuleSet is what actually validates a value agains a validate func (a "rule" if you will).
It is also responsible for providing error messages thourgh a message func.
An interesting feature of safe.RuleSet is its FlowFunc. It allows for a rule set to control the flow of validations. If the flow func returns true, then proceed with next validations, otherwise stop.
Usualy, safe.RuleSet is not used directly.
This library exposes functions that return a *safe.RuleSet. You can also make your own!
func After ¶
The field must be of type time.Time, and it's value should be after the provided datetime.
func Before ¶
The field must be of type time.Time, and it's value should be before the provided datetime.
func Cnpj ¶
func Cnpj() *RuleSet
The field must be a string with a valid cnpj format
It may or may not include symbols
func Contains ¶ added in v1.3.0
The field value must be of type string
The value of the field must contain substr
func ContainsAll ¶ added in v1.3.0
The field value must be of type string
The value of the field must contain all substrs.
Note that this is different from strings.ContainsAny, because we compare substrings, not unicode code points
func ContainsNone ¶ added in v1.3.0
The field value must be of type string
None of the substrs should be found in the field value
func ContainsSome ¶ added in v1.3.0
The field value must be of type string
The value of the field must contain at least one of substrs
func Cpf ¶
func Cpf() *RuleSet
The field must be a string with a valid cpf format
It may or may not include symbols
func CpfCnpj ¶
func CpfCnpj() *RuleSet
The field must be a string with a valid cpf or cnpj format
It may or may not include symbols
func EqualTo ¶ added in v1.1.0
func EqualTo[T comparable](value T) *RuleSet
The field value must implement the comparable interface.
The value of the field should be equal to the provided value.
This rule behaves exactly like safe.OneOf, but with only one value to compare
func GreaterThan ¶ added in v1.3.0
The field value must be like T, either an int, a float64 or a float32
The value of the field must be greater than n
func GreaterThanOrEqualTo ¶ added in v1.3.0
The field value must be like T, either an int, a float64 or a float32
The value of the field must be greater than or equal to n
func LessThan ¶ added in v1.3.0
The field value must be like T, either an int, a float64 or a float32
The value of the field must be less than n
func LessThanOrEqualTo ¶ added in v1.3.0
The field value must be like T, either an int, a float64 or a float32
The value of the field must be greater than or equal to n
func MatchList ¶
The field must be a slice of string, in which all strings match all the given regexes.
func Max ¶
The field must be an int, float64, float32 or string.
In case it is a numeric value, it must not greater then maxValue.
As for strings, they must not have more then maxValue number of characters.
func MaxDaysRange ¶
The field must be of type time.Time.
The days range between the value of the field and the provided datetime should not be greater than maxDays.
func Min ¶
The field must be an int, float64, float32 or string.
In case it is a numeric value, it must not be less then minValue.
As for strings, they must not have less then minValue number of characters.
func NewRuleSet ¶ added in v1.4.0
func NoWhitespace ¶ added in v1.0.3
func NoWhitespace() *RuleSet
The field must be a string with no whitespaces
This includes characters like \n (linebreaks) and \t (tabs)
func NotAfter ¶
The field must be of type time.Time, and it's value should not be after the provided datetime.
func NotBefore ¶
The field must be of type time.Time, and it's value should not be before the provided datetime.
func NotContains ¶ added in v1.3.0
The field value must be of type string
The value of the field must not contain substr
func NotEqualTo ¶ added in v1.1.0
func NotEqualTo[T comparable](value T) *RuleSet
Exactly the opposite of safe.EqualTo.
func OneOf ¶
func OneOf[T comparable](vals []T) *RuleSet
The field value must implement the comparable interface.
The value of the field should be equal to at least one of the provided values.
Example usage:
EntityUserTypes := [6]string{"q", "w", "e", "r", "t", "y"} e := &Entity{UserType: "default", SomeOtherOptionField: 4} fields := safe.Fields{ { Name: "UserType", Value: e.UserType, Rules: safe.Rules{safe.Required(), safe.OneOf(EntityUserTypes[:])}, }, { Name: "SomeOtherOptionField", Value: e.SomeOtherOptionField, Rules: safe.Rules{safe.Required(), safe.OneOf([]int{1, 2, 3})}, }, }
func Phone ¶
func Phone() *RuleSet
The field must be a string with a valid phone format.
It may or may not include symbols (like +, - and ()) or whitespaces
func Required ¶
func Required() *RuleSet
The field must have a value. Zero values are not allowed, except for boolean fields.
Supported field types: bool, string, int, float64, float32, time.Time
Example:
u := &User{Username: "", BooleanField: false} fields := safe.Fields{ { Name: "Username", Value: u.Username, Rules: safe.Rules{safe.Required().WithOpts(&safe.RuleSetOpts{ AcceptNumberZero: true, })}, }, { Name: "BooleanField", Value: u.BooleanField, Rules: safe.Rules{safe.Required()}, }, } errors, ok := safe.Validate(fields)
In the example above, username field will not be valid, but the boolean field is valid, because it has a value. In essence, safe.Required bypasses boolean fields.
To validate boolean fields more specificaly, use safe.True and safe.False.
func RequiredIf ¶ added in v1.3.0
The field is not required by default.
However, if any of the provided vals are valid (meaning, if at least of one them have no zero value), then the field becomes required.
Example usage:
fields := safe.Fields{ { Name: "Email", Value: user.Email, Rules: safe.Rules{safe.Email(), safe.Max(128), safe.RequiredIf(user.Username)}, }, { Name: "Username", Value: user.Username, Rules: safe.Rules{safe.Max(128), safe.Min(3)}, }, }
In the example above, email is required only when username is provided.
func RequiredUnless ¶
The field is required, just like safe.Required.
However, if any of the provided vals are valid (meaning, if at least of one them have no zero value), then pass.
Example usage:
fields := safe.Fields{ { Name: "Email", Value: user.Email, Rules: safe.Rules{safe.Email(), safe.Max(128), safe.RequiredUnless(user.Username)}, }, { Name: "Username", Value: user.Username, Rules: safe.Rules{safe.Required(), safe.Max(128), safe.Min(3)}, }, }
In the example above, email is required, unless username is provided.
func StopIf ¶ added in v1.4.0
A flow rule.
Stop validation for the field if the provided condition is met.
func StopIfFunc ¶ added in v1.4.0
A flow rule.
Stop validation for the field if the provided func returns true.
func StopIfNoValue ¶ added in v1.4.0
func StopIfNoValue() *RuleSet
A flow rule.
Stop validation for the field if the field has no value.
Example usage:
fields := safe.Fields{ { Name: "limit", Value: filters.Limit, Rules: safe.Rules{safe.StopIfNoValue(), safe.GreaterThanOrEqualTo(10), safe.RequiredIf(filters.Offset)}, }, { Name: "offset", Value: filters.Offset, Rules: safe.Rules{safe.StopIfNoValue(), safe.GreaterThanOrEqualTo(0), safe.RequiredIf(filters.Limit)}, }, { Name: "order_by", Value: filters.OrderBy, Rules: safe.Rules{safe.OneOf([]string{"created_at"})}, }, { Name: "search", Value: filters.Search, Rules: safe.Rules{safe.Max(128)}, }, } fields.SetRuleOptsForAll(&safe.RuleSetOpts{ AcceptNumberZero: true, })
In the example above, email is required only when username is provided.
func StrongPassword ¶
func StrongPassword() *RuleSet
The field must be a string with a strong password pattern.
This means 8+ characters, with lowercase and uppercase letters, numbers and special characters.
func UUIDstr ¶
func UUIDstr() *RuleSet
The field must be a string with a valid format for a uuid v1, v4, v5 or v7.
In case you are using a uuid package like google's, you will likely not need this, because you will already have a uuid validation method.
Besides that, most of the time the database itself will generate the uuids.
func UniqueList ¶
func UniqueList[T comparable]() *RuleSet
The field must be a slice of values, each of them implementing the comparable interface. All values in the list should be unique.
Must provide type inference.
Example usage:
someList := [6]string{"q", "w", "e", "q", "t", "y"} fields := safe.Fields{ { Name: "fieldName", Value: someList, Rules: safe.Rules{safe.Required(), safe.UniqueList[string]()}, }, }
IMPORTANT!
Please note that if you pass "any" as type parameter to safe.UniqueList, it will work **only** with explicit []any types. If you pass another type, there will be runtime errors.
func (*RuleSet) WithFlowFunc ¶ added in v1.4.0
func (*RuleSet) WithMessage ¶
Modifies a default message from a RuleSet, effectively letting you provide your own custom error messages.
Example usage:
fields := safe.Fields{ { Name: "Username", Value: u.Username, Rules: safe.Rules{safe.Required().WithMessage("Why did you leave it blank?")}, }, }
func (*RuleSet) WithMessageFunc ¶ added in v1.4.0
func (*RuleSet) WithOpts ¶ added in v1.4.0
func (rs *RuleSet) WithOpts(opts *RuleSetOpts) *RuleSet
type RuleSetOpts ¶ added in v1.4.0
type RuleSetOpts struct {
AcceptNumberZero bool
}