rules

package
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 20, 2024 License: MPL-2.0 Imports: 21 Imported by: 17

Documentation

Overview

Package rules provides predefined rules for common validation scenarios.

Index

Examples

Constants

View Source
const (
	ErrorCodeRequired                  govy.ErrorCode = internal.RequiredErrorCodeString
	ErrorCodeForbidden                 govy.ErrorCode = "forbidden"
	ErrorCodeEqualTo                   govy.ErrorCode = "equal_to"
	ErrorCodeNotEqualTo                govy.ErrorCode = "not_equal_to"
	ErrorCodeGreaterThan               govy.ErrorCode = "greater_than"
	ErrorCodeGreaterThanOrEqualTo      govy.ErrorCode = "greater_than_or_equal_to"
	ErrorCodeLessThan                  govy.ErrorCode = "less_than"
	ErrorCodeLessThanOrEqualTo         govy.ErrorCode = "less_than_or_equal_to"
	ErrorCodeStringNotEmpty            govy.ErrorCode = "string_not_empty"
	ErrorCodeStringMatchRegexp         govy.ErrorCode = "string_match_regexp"
	ErrorCodeStringDenyRegexp          govy.ErrorCode = "string_deny_regexp"
	ErrorCodeStringDNSLabel            govy.ErrorCode = "string_dns_label"
	ErrorCodeStringURL                 govy.ErrorCode = "string_url"
	ErrorCodeStringMAC                 govy.ErrorCode = "string_mac"
	ErrorCodeStringIP                  govy.ErrorCode = "string_ip"
	ErrorCodeStringIPv4                govy.ErrorCode = "string_ipv4"
	ErrorCodeStringIPv6                govy.ErrorCode = "string_ipv6"
	ErrorCodeStringCIDR                govy.ErrorCode = "string_cidr"
	ErrorCodeStringCIDRv4              govy.ErrorCode = "string_cidrv4"
	ErrorCodeStringCIDRv6              govy.ErrorCode = "string_cidrv6"
	ErrorCodeStringASCII               govy.ErrorCode = "string_ascii"
	ErrorCodeStringUUID                govy.ErrorCode = "string_uuid"
	ErrorCodeStringEmail               govy.ErrorCode = "string_email"
	ErrorCodeStringJSON                govy.ErrorCode = "string_json"
	ErrorCodeStringContains            govy.ErrorCode = "string_contains"
	ErrorCodeStringExcludes            govy.ErrorCode = "string_excludes"
	ErrorCodeStringStartsWith          govy.ErrorCode = "string_starts_with"
	ErrorCodeStringEndsWith            govy.ErrorCode = "string_ends_with"
	ErrorCodeStringLength              govy.ErrorCode = "string_length"
	ErrorCodeStringMinLength           govy.ErrorCode = "string_min_length"
	ErrorCodeStringMaxLength           govy.ErrorCode = "string_max_length"
	ErrorCodeStringTitle               govy.ErrorCode = "string_title"
	ErrorCodeStringGitRef              govy.ErrorCode = "string_git_ref"
	ErrorCodeStringFileSystemPath      govy.ErrorCode = "string_file_system_path"
	ErrorCodeStringMatchFileSystemPath govy.ErrorCode = "string_match_file_system_path"
	ErrorCodeStringFilePath            govy.ErrorCode = "string_file_path"
	ErrorCodeStringDirPath             govy.ErrorCode = "string_dir_path"
	ErrorCodeStringRegexp              govy.ErrorCode = "string_regexp"
	ErrorCodeStringCrontab             govy.ErrorCode = "string_crontab"
	ErrorCodeStringDateTime            govy.ErrorCode = "string_date_time"
	ErrorCodeStringTimeZone            govy.ErrorCode = "string_time_zone"
	ErrorCodeStringAlpha               govy.ErrorCode = "string_alpha"
	ErrorCodeStringAlphanumeric        govy.ErrorCode = "string_alphanumeric"
	ErrorCodeStringAlphaUnicode        govy.ErrorCode = "string_alpha_unicode"
	ErrorCodeStringAlphanumericUnicode govy.ErrorCode = "string_alphanumeric_unicode"
	ErrorCodeSliceLength               govy.ErrorCode = "slice_length"
	ErrorCodeSliceMinLength            govy.ErrorCode = "slice_min_length"
	ErrorCodeSliceMaxLength            govy.ErrorCode = "slice_max_length"
	ErrorCodeMapLength                 govy.ErrorCode = "map_length"
	ErrorCodeMapMinLength              govy.ErrorCode = "map_min_length"
	ErrorCodeMapMaxLength              govy.ErrorCode = "map_max_length"
	ErrorCodeOneOf                     govy.ErrorCode = "one_of"
	ErrorCodeOneOfProperties           govy.ErrorCode = "one_of_properties"
	ErrorCodeMutuallyExclusive         govy.ErrorCode = "mutually_exclusive"
	ErrorCodeEqualProperties           govy.ErrorCode = "equal_properties"
	ErrorCodeSliceUnique               govy.ErrorCode = "slice_unique"
	ErrorCodeURL                       govy.ErrorCode = "url"
	ErrorCodeDurationPrecision         govy.ErrorCode = "duration_precision"
)

Variables

This section is empty.

Functions

func CompareDeepEqualFunc added in v0.11.0

func CompareDeepEqualFunc[T any](v1, v2 T) bool

CompareDeepEqualFunc compares two values of the same type using reflect.DeepEqual. It is particularly useful when comparing pointers' values.

func CompareFunc added in v0.11.0

func CompareFunc[T comparable](v1, v2 T) bool

CompareFunc compares two values of the same type. The type is constrained by the [comparable] interface.

func DurationPrecision

func DurationPrecision(precision time.Duration) govy.Rule[time.Duration]

DurationPrecision ensures the duration is defined with the specified precision.

func EQ

func EQ[T comparable](compared T) govy.Rule[T]

EQ ensures the property's value is equal to the compared value.

func EqualProperties added in v0.11.0

func EqualProperties[S, T any](compare ComparisonFunc[T], getters map[string]func(s S) T) govy.Rule[S]

EqualProperties checks if all of the specified properties are equal. It uses the provided ComparisonFunc to compare the values. The following built-in comparison functions are available:

If builtin ComparisonFunc are not enough, a custom function can be used.

Example
package main

import (
	"fmt"

	"github.com/nobl9/govy/pkg/govy"
	"github.com/nobl9/govy/pkg/rules"
)

type Teacher struct {
	Students []Student `json:"students"`
}

type Student struct {
	Index     string `json:"index,omitempty"`
	Name      string `json:"name,omitempty"`
	IndexCopy string `json:"indexCopy,omitempty"`
}

func main() {
	v := govy.New(
		govy.ForSlice(func(t Teacher) []Student { return t.Students }).
			WithName("students").
			RulesForEach(rules.EqualProperties(rules.CompareFunc, map[string]func(Student) any{
				"index":     func(s Student) any { return s.Index },
				"indexCopy": func(s Student) any { return s.IndexCopy },
			})),
	)
	teacher := Teacher{
		Students: []Student{
			{Index: "foo", IndexCopy: "foo"},
			{Index: "bar"},
			{IndexCopy: "foo"},
			{}, // Both index and indexCopy are empty strings, and thus equal.
		},
	}
	err := v.Validate(teacher)
	if err != nil {
		fmt.Println(err)
	}

}
Output:

Validation has failed for the following properties:
  - 'students[1]' with value '{"index":"bar"}':
    - all of [index, indexCopy] properties must be equal, but 'index' is not equal to 'indexCopy'
  - 'students[2]' with value '{"indexCopy":"foo"}':
    - all of [index, indexCopy] properties must be equal, but 'index' is not equal to 'indexCopy'

func Forbidden

func Forbidden[T any]() govy.Rule[T]

Forbidden ensures the property's value is its type's zero value, i.e. it's empty.

func GT

func GT[T constraints.Ordered](compared T) govy.Rule[T]

GT ensures the property's value is greater than the compared value.

func GTE

func GTE[T constraints.Ordered](compared T) govy.Rule[T]

GTE ensures the property's value is greater than or equal to the compared value.

func LT

func LT[T constraints.Ordered](compared T) govy.Rule[T]

LT ensures the property's value is less than the compared value.

func LTE

func LTE[T constraints.Ordered](compared T) govy.Rule[T]

LTE ensures the property's value is less than or equal to the compared value.

func MapLength

func MapLength[M ~map[K]V, K comparable, V any](minLen, maxLen int) govy.Rule[M]

MapLength ensures the map's length is between min and max (closed interval).

func MapMaxLength

func MapMaxLength[M ~map[K]V, K comparable, V any](limit int) govy.Rule[M]

MapMaxLength ensures the map's length is less than or equal to the limit.

func MapMinLength

func MapMinLength[M ~map[K]V, K comparable, V any](limit int) govy.Rule[M]

MapMinLength ensures the map's length is greater than or equal to the limit.

func MutuallyExclusive

func MutuallyExclusive[S any](required bool, getters map[string]func(s S) any) govy.Rule[S]

MutuallyExclusive checks if properties are mutually exclusive. This means, exactly one of the properties can be set. Property is considered set if its value is not empty (non-zero). If required is true, then a single non-empty property is required.

Example
package main

import (
	"fmt"

	"github.com/nobl9/govy/pkg/govy"
	"github.com/nobl9/govy/pkg/rules"
)

type Teacher struct {
	Students []Student `json:"students"`
}

type Student struct {
	Index     string `json:"index,omitempty"`
	Name      string `json:"name,omitempty"`
	IndexCopy string `json:"indexCopy,omitempty"`
}

func main() {
	v := govy.New(
		govy.ForSlice(func(t Teacher) []Student { return t.Students }).
			WithName("students").
			RulesForEach(rules.MutuallyExclusive(true, map[string]func(Student) any{
				"index": func(s Student) any { return s.Index },
				"name":  func(s Student) any { return s.Name },
			})),
	)
	teacher := Teacher{
		Students: []Student{
			{Index: "foo"},
			{Index: "bar", Name: "John"},
			{Name: "Eve"},
			{},
		},
	}
	err := v.Validate(teacher)
	if err != nil {
		fmt.Println(err)
	}

}
Output:

Validation has failed for the following properties:
  - 'students[1]' with value '{"index":"bar","name":"John"}':
    - [index, name] properties are mutually exclusive, provide only one of them
  - 'students[3]':
    - one of [index, name] properties must be set, none was provided

func NEQ

func NEQ[T comparable](compared T) govy.Rule[T]

NEQ ensures the property's value is not equal to the compared value.

func OneOf

func OneOf[T comparable](values ...T) govy.Rule[T]

OneOf checks if the property's value matches one of the provided values. The values must be comparable.

func OneOfProperties added in v0.3.0

func OneOfProperties[S any](getters map[string]func(s S) any) govy.Rule[S]

OneOfProperties checks if at least one of the properties is set. Property is considered set if its value is not empty (non-zero).

Example
package main

import (
	"fmt"

	"github.com/nobl9/govy/pkg/govy"
	"github.com/nobl9/govy/pkg/rules"
)

type Teacher struct {
	Students []Student `json:"students"`
}

type Student struct {
	Index     string `json:"index,omitempty"`
	Name      string `json:"name,omitempty"`
	IndexCopy string `json:"indexCopy,omitempty"`
}

func main() {
	v := govy.New(
		govy.ForSlice(func(t Teacher) []Student { return t.Students }).
			WithName("students").
			RulesForEach(rules.OneOfProperties(map[string]func(Student) any{
				"index": func(s Student) any { return s.Index },
				"name":  func(s Student) any { return s.Name },
			})),
	)
	teacher := Teacher{
		Students: []Student{
			{Index: "foo"},
			{},
			{Name: "John"},
			{Index: "bar", Name: "Eve"},
		},
	}
	err := v.Validate(teacher)
	if err != nil {
		fmt.Println(err)
	}

}
Output:

Validation has failed for the following properties:
  - 'students[1]':
    - one of [index, name] properties must be set, none was provided

func Required

func Required[T any]() govy.Rule[T]

Required ensures the property's value is not empty (i.e. it's not its type's zero value).

func SliceLength

func SliceLength[S ~[]E, E any](minLen, maxLen int) govy.Rule[S]

SliceLength ensures the slice's length is between min and max (closed interval).

func SliceMaxLength

func SliceMaxLength[S ~[]E, E any](limit int) govy.Rule[S]

SliceMaxLength ensures the slice's length is less than or equal to the limit.

func SliceMinLength

func SliceMinLength[S ~[]E, E any](limit int) govy.Rule[S]

SliceMinLength ensures the slice's length is greater than or equal to the limit.

func SliceUnique

func SliceUnique[S []V, V any, H comparable](hashFunc HashFunction[V, H], constraints ...string) govy.Rule[S]

SliceUnique ensures that a slice contains unique elements based on a provided HashFunction. You can optionally specify constraints which will be included in the error message to further clarify the reason for breaking uniqueness.

Example
package main

import (
	"fmt"

	"github.com/nobl9/govy/pkg/govy"
	"github.com/nobl9/govy/pkg/rules"
)

type Teacher struct {
	Students []Student `json:"students"`
}

type Student struct {
	Index     string `json:"index,omitempty"`
	Name      string `json:"name,omitempty"`
	IndexCopy string `json:"indexCopy,omitempty"`
}

func main() {
	v := govy.New(
		govy.ForSlice(func(t Teacher) []Student { return t.Students }).
			WithName("students").
			Rules(rules.SliceUnique(func(v Student) string { return v.Index },
				"each student must have unique index")),
	)
	teacher := Teacher{
		Students: []Student{
			{Index: "foo"},
			{Index: "bar"}, // 2nd element
			{Index: "baz"},
			{Index: "bar"}, // 4th element
		},
	}
	err := v.Validate(teacher)
	if err != nil {
		fmt.Println(err)
	}

}
Output:

Validation has failed for the following properties:
  - 'students' with value '[{"index":"foo"},{"index":"bar"},{"index":"baz"},{"index":"bar"}]':
    - elements are not unique, 2nd and 4th elements collide based on constraints: each student must have unique index

func StringASCII

func StringASCII() govy.Rule[string]

StringASCII ensures property's value contains only ASCII characters.

func StringAlpha added in v0.10.0

func StringAlpha() govy.Rule[string]

StringAlpha ensures the property's value consists only of ASCII letters.

func StringAlphaUnicode added in v0.10.0

func StringAlphaUnicode() govy.Rule[string]

StringAlpha ensures the property's value consists only of Unicode letters.

func StringAlphanumeric added in v0.10.0

func StringAlphanumeric() govy.Rule[string]

StringAlpha ensures the property's value consists only of ASCII letters and numbers.

func StringAlphanumericUnicode added in v0.10.0

func StringAlphanumericUnicode() govy.Rule[string]

StringAlpha ensures the property's value consists only of Unicode letters and numbers.

func StringCIDR added in v0.2.0

func StringCIDR() govy.Rule[string]

StringCIDR ensures property's value is a valid CIDR notation IP address.

func StringCIDRv4 added in v0.2.0

func StringCIDRv4() govy.Rule[string]

StringCIDRv4 ensures property's value is a valid CIDR notation IPv4 address.

func StringCIDRv6 added in v0.2.0

func StringCIDRv6() govy.Rule[string]

StringCIDRv4 ensures property's value is a valid CIDR notation IPv6 address.

func StringContains

func StringContains(substrings ...string) govy.Rule[string]

StringContains ensures the property's value contains all the provided substrings.

func StringCrontab added in v0.6.0

func StringCrontab() govy.Rule[string]

StringCrontab ensures the property's value is a valid crontab schedule expression. For more details on cron expressions read crontab manual and visit crontab.guru.

func StringDNSLabel

func StringDNSLabel() govy.Rule[string]

StringDNSLabel ensures the property's value is a valid DNS label as defined by RFC 1123.

func StringDateTime added in v0.9.0

func StringDateTime(layout string, examples ...string) govy.Rule[string]

StringDateTime ensures the property's value is a valid date and time in the specified layout.

The layout must be a valid time format string as defined by time.Parse, an example of which is time.RFC3339.

func StringDenyRegexp

func StringDenyRegexp(re *regexp.Regexp, examples ...string) govy.Rule[string]

StringDenyRegexp ensures the property's value does not match the regular expression. The error message can be enhanced with examples of invalid values.

func StringDirPath added in v0.5.0

func StringDirPath() govy.Rule[string]

StringDirPath ensures the property's value is a file system path pointing to an existing directory.

func StringEmail added in v0.2.0

func StringEmail() govy.Rule[string]

StringEmail ensures the property's value is a valid email address. It follows RFC 5322 specification which is more permissive in regards to domain names. Ref: https://www.ietf.org/rfc/rfc5322.txt

func StringEndsWith

func StringEndsWith(suffixes ...string) govy.Rule[string]

StringEndsWith ensures the property's value ends with one of the provided suffixes.

func StringExcludes added in v0.2.0

func StringExcludes(substrings ...string) govy.Rule[string]

StringExcludes ensures the property's value does not contain any of the provided substrings.

func StringFilePath added in v0.5.0

func StringFilePath() govy.Rule[string]

StringFilePath ensures the property's value is a file system path pointing to an existing file.

func StringFileSystemPath added in v0.5.0

func StringFileSystemPath() govy.Rule[string]

StringFileSystemPath ensures the property's value is an existing file system path.

func StringGitRef added in v0.5.0

func StringGitRef() govy.Rule[string]

StringGitRef ensures a git reference name follows the [git-check-ref-format] rules.

It is important to note that this function does not check if the reference exists in the repository. It only checks if the reference name is valid. This functions does not support the '--refspec-pattern', '--normalize', and '--allow-onelevel' options.

Git imposes the following rules on how references are named:

  1. They can include slash '/' for hierarchical (directory) grouping, but no slash-separated component can begin with a dot '.' or end with the sequence '.lock'.
  2. They must contain at least one '/'. This enforces the presence of a category (e.g. 'heads/', 'tags/'), but the actual names are not restricted.
  3. They cannot have ASCII control characters (i.e. bytes whose values are lower than '\040', or '\177' DEL).
  4. They cannot have '?', '*', '[', ' ', '~', '^', ', '\t', '\n', '@{', '\\' and '..',
  5. They cannot begin or end with a slash '/'.
  6. They cannot end with a '.'.
  7. They cannot be the single character '@'.
  8. 'HEAD' is an allowed special name.

Slightly modified version of [go-git] implementation, kudos to the authors!

[git-check-ref-format] :https://git-scm.com/docs/git-check-ref-format [go-git]: https://github.com/go-git/go-git/blob/95afe7e1cdf71c59ee8a71971fac71880020a744/plumbing/reference.go#L167

func StringIP added in v0.2.0

func StringIP() govy.Rule[string]

StringIP ensures property's value is a valid IP address.

func StringIPv4 added in v0.2.0

func StringIPv4() govy.Rule[string]

StringIPv4 ensures property's value is a valid IPv4 address.

func StringIPv6 added in v0.2.0

func StringIPv6() govy.Rule[string]

StringIPv6 ensures property's value is a valid IPv6 address.

func StringJSON

func StringJSON() govy.Rule[string]

StringJSON ensures property's value is a valid JSON literal.

func StringLength

func StringLength(minLen, maxLen int) govy.Rule[string]

StringLength ensures the string's length is between min and max (closed interval).

func StringMAC added in v0.2.0

func StringMAC() govy.Rule[string]

StringMAC ensures property's value is a valid MAC address.

func StringMatchFileSystemPath added in v0.5.0

func StringMatchFileSystemPath(pattern string) govy.Rule[string]

StringMatchFileSystemPath ensures the property's value matches the provided file path pattern. It uses filepath.Match to match the pattern. The native function comes with some limitations, most notably it does not support '**' recursive expansion. It does not check if the file path exists on the file system.

func StringMatchRegexp

func StringMatchRegexp(re *regexp.Regexp, examples ...string) govy.Rule[string]

StringMatchRegexp ensures the property's value matches the regular expression. The error message can be enhanced with examples of valid values.

func StringMaxLength

func StringMaxLength(limit int) govy.Rule[string]

StringMaxLength ensures the string's length is less than or equal to the limit.

func StringMinLength

func StringMinLength(limit int) govy.Rule[string]

StringMinLength ensures the string's length is greater than or equal to the limit.

func StringNotEmpty

func StringNotEmpty() govy.Rule[string]

StringNotEmpty ensures the property's value is not empty. The string is considered empty if it contains only whitespace characters.

func StringRegexp added in v0.6.0

func StringRegexp() govy.Rule[string]

StringRegexp ensures the property's value is a valid regular expression. The accepted regular expression syntax must comply to RE2. It is described at https://golang.org/s/re2syntax, except for \C. For an overview of the syntax, see regexp/syntax package.

func StringStartsWith

func StringStartsWith(prefixes ...string) govy.Rule[string]

StringStartsWith ensures the property's value starts with one of the provided prefixes.

func StringTimeZone added in v0.9.0

func StringTimeZone() govy.Rule[string]

StringTimeZone ensures the property's value is a valid time zone name which uniquely identifies a time zone in the IANA Time Zone database. Example: "America/New_York", "Europe/London".

Under the hood time.LoadLocation is called to parse the zone. The native function allows empty string and 'Local' keyword to be supplied. However, these two options are explicitly forbidden by StringTimeZone.

Furthermore, the time zone data is not readily available in one predefined place. time.LoadLocation looks for the IANA Time Zone database in specific places, please refer to its documentation for more information.

func StringTitle

func StringTitle() govy.Rule[string]

StringTitle ensures each word in a string starts with a capital letter.

func StringURL

func StringURL() govy.Rule[string]

StringURL ensures property's value is a valid URL as defined by url.Parse function. Unlike URL it does not impose any additional rules upon parsed url.URL.

func StringUUID

func StringUUID() govy.Rule[string]

StringUUID ensures property's value is a valid UUID string as defined by RFC 4122. It does not enforce a specific UUID version. Ref: https://www.ietf.org/rfc/rfc4122.txt

func URL

func URL() govy.Rule[*url.URL]

URL ensures the URL is valid. The URL must have a scheme (e.g. https://) and contain either host, fragment or opaque data.

Types

type ComparisonFunc added in v0.11.0

type ComparisonFunc[T any] func(v1, v2 T) bool

ComparisonFunc defines a shape for a function that compares two values. It should return true if the values are equal, false otherwise.

type HashFunction

type HashFunction[V any, H comparable] func(v V) H

HashFunction accepts a value and returns a comparable hash.

func HashFuncSelf

func HashFuncSelf[H comparable]() HashFunction[H, H]

HashFuncSelf returns a HashFunction which returns its input value as a hash itself. The value must be comparable.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL