vld

package module
v0.0.0-...-b729480 Latest Latest
Warning

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

Go to latest
Published: Apr 6, 2024 License: GPL-3.0 Imports: 8 Imported by: 0

README

VLD

A data validation library for GoLang.

Installation

Download the library

go get github.com/moeenn/vld

Why not go-playground/validator?

There is no denying that validator is an amazing package and is the ecosystem standard. However there are some issues with it

  • Struct tags are used to define field validators. Since tags are nothing more than strings, this method can be very error-prone.
  • The validation errors are structured non user-friedly way. This makes it difficult to format the validation errors in such a way that they can be displayed on the front-end clients properly.
  • The mechanism for defining custom validators is not intuitive.

vld attempts to solve these problems.

Basic usage

package main

import (
	"fmt"
	v "github.com/moeenn/vld"
)

type LoginForm struct {
	Email    string
	Password string
}

func main() {
	form := LoginForm{
		Email:    "admin-site.com",
		Password: "q1w2e3r4",
	}

	validations := []v.Validation{
		{
			Tag:   "email",
			Data:  form.Email,
			Rules: []v.Rule{v.NonEmptyString, v.Email},
		},
		{
			Tag:   "password",
			Data:  form.Password,
			Rules: []v.Rule{v.NonEmptyString, v.MinLength(8)},
		},
	}

	err := v.Validate(validations)
	if err != nil {
		validationErrors := err.(v.ValidationErrors)
		fmt.Printf("validation errors: %v\n", validationErrors.Errors)
		return
	}

	fmt.Println("validation successful")
}

Included validators

  • NonEmptyString: The input must be valid non-empty string value.
v.NonEmptyString
  • Length: The input string length must be exactly equal to the provided length.
// input string must be exactly 10 characters in length
v.Length(10)
  • MinLength: The input string length must be equal or more than the provided length.
// input string must be 5 characters or more in length
v.MinLength(5)
  • MaxLength: The input string length must be equal or less than the provided length.
// input string must be 5 characters or less in length
v.MaxLength(20)
  • MinFloat: The input floating-point number must be equal or more than the provided limit.
// input number must be at least 5.0 or more
v.MinFloat(5.0)
  • MaxFloat: The input floating-point number must be equal or less than the provided limit.
// input number must be 500.5 or less
v.MaxFloat(500.5)
  • MinInt: The input integer number must be equal or more than the provided limit.
// input number must be at least 100 or more
v.MinInt(100)
  • MaxInt: The input integer number must be equal or less than the provided limit.
// input number must be 200 or less
v.MaxInt(200)
  • LessThanFloat: The input floating-point number must be less than the provided limit.
// input number must be less than 20.0 (non-inclusive)
v.LessThanFloat(20.0)
  • GreaterThanFloat: The input floating-point number must be greater than the provided limit.
// input number must be greater than 10.5 (non-inclusive)
v.GreaterThanFloat(10.5)
  • LessThanInt: The input integer number must be less than the provided limit.
// input number must be less than 24 (non-inclusive)
v.LessThanInt(24)
  • GreaterThanInt: The input integer number must be greater than the provided limit.
// input number must be greater than 100 (non-inclusive)
v.GreaterThanInt(100)
  • Email: The input must be a valid email address.
v.Email
  • UUID: The input must be a valid UUID string
v.UUID
  • URL: The input must be a valid URL string
v.URL
  • Password: The input must be a strong password. The following rules are applied.
    • Minimum eight characters
    • At least one uppercase letter
    • At least one lowercase letter
    • At least one number
    • At least one special character
v.Password
  • JSON: Input must be a well-formed JSON string
v.JSON
  • ISODate: The input must be valid ISO timestamp according to RFC3339: Link.
// input string must conform to the format e.g 2024-03-22T12:35:05.115Z
v.ISODate
  • Date: The input must be a valid date-only string. Link.
// input must be in format e.g. 2023-10-05
v.Date
  • Time: The input must be a valid time-only string. Link.
// input must be in 24-hours format: e.g. 10:20:00
v.Time
  • Before date: TODO

  • Before or equal to date: TODO

  • After date: TODO

  • After or equal to date: TODO

  • StartsWith: The input string must begin with the provided prefix.

v.StartsWith("data:")
  • DoesntStartWith: The input string must not start with the provided prefix.
v.DoesntStartWith("mysql")
  • EndsWith: The input string must end with the provided suffix.
v.EndsWith("example")
  • DoesntEndWith: The input string must not end with the provided prefix.
v.DoesntEndWith("sample")
  • Enum: The input string must be equal to one of the provided valid values.
// values are provided in variadic fashion
v.Enum("Value One", "Value Two", "Value Three")
  • Regexp: The input value must satisfy the provided regular expression.
v.Regexp("^hello$")
  • Same: The input value must be the same as the required input. This validator can be used to confirm passwords.
import (
	"fmt"
	v "github.com/moeenn/vld"
)

type RegisterForm struct {
	Password        string
	ConfirmPassword string
}

func main() {
	form := RegisterForm{
		Password:        "A832KCN284506b@",
		ConfirmPassword: "A832KCN284506b@",
	}

	validations := []v.Validation{
		{
			Tag:   "password",
			Data:  form.Password,
			Rules: []v.Rule{v.NonEmptyString, v.Password},
		},
		{
			Tag:   "confirm_password",
			Data:  form.ConfirmPassword,
			Rules: []v.Rule{v.Same("Password", form.Password)},
		},
	}

	err := v.Validate(validations)
	if err != nil {
		validationErrors := err.(v.ValidationErrors)
		fmt.Printf("validation errors: %v\n", validationErrors.Errors)
		return
	}

	fmt.Println("validation successful")
}
  • Array: TODO

  • MinItems: TODO

  • MaxItems: TODO

Custom validators

In vld validators are plain functions. They can be defined as follows.

type ExampleForm struct {
	Slug string
}

func Slug(input any) error {
	err := errors.New("The input must be a valid slug")
	asString, ok := input.(string)
	if !ok {
		return err
	}

	if strings.Contains(asString, "_") {
		return err
	}
	return nil
}

func main() {
	form := ExampleForm{
		Slug: "some-slug-here",
	}

	validations := []v.Validation{
		{
			Tag:   "slug",
			Data:  form.Slug,
			Rules: []v.Rule{v.NonEmptyString, Slug}, // notice the user-defined validator
		},
	}

	err := v.Validate(validations)
	if err != nil {
		validationErrors := err.(v.ValidationErrors)
		fmt.Printf("validation errors: %v\n", validationErrors.Errors)
		return
	}
	
	// the input data is valid
    ...	
}

If the custom validator function required additional arguments, they can be defined as follows.

func StartsWith(prefix string) Rule {
	return func(input any) error {
		err := fmt.Errorf("The input must start with '%s'", prefix)
		asString, ok := input.(string)
		if !ok || !strings.HasPrefix(asString, prefix) {
			return err
		}
		return nil
	}
}

Documentation

Index

Constants

View Source
const (
	PATTERN_EMAIL = `^[^@]+@[^@]+\.[^@]+$`
	PATTERN_UUID  = `^[a-f\d]{8}(-[a-f\d]{4}){4}[a-f\d]{8}$`

	// Password strength rules:
	// - Minimum eight characters
	// - At least one uppercase letter
	// - One lowercase letter
	// - One number
	// - One special character
	// **Note**: the pattern will match weak passwords instead of strong passwords
	PATTERN_PASSWORD_STRENGTH = `^(.{0,7}|[^0-9]*|[^A-Z]*|[^a-z]*|[a-zA-Z0-9]*)$`
)

Variables

This section is empty.

Functions

func Date

func Date(input any) error

Date check if the provided input is a valid string and a valid date-only string. Date string must be in format e.g. 2023-10-05 [Link](https://pkg.golang.ir/time#pkg-constants).

func Email

func Email(input any) error

Email check if the provide input is a valid email address.

func ISODate

func ISODate(input any) error

ISODate check if the provided input is a valid string and a valid ISO timestamp according to RFC3339: [Link](https://pkg.golang.ir/time#pkg-constants).

func JSON

func JSON(input any) error

JSON check if the provided code is a valid string and a valid json.

func NonEmptyString

func NonEmptyString(input any) error

NonEmptyString check if provided input is a non-empty string.

func Password

func Password(input any) error

Password check if the provided input is a valid string and a reasonably strong password.

func Time

func Time(input any) error

Time check if the provided input is a valid string and a valid time-only string. Time string must be in 24-hours format: e.g. 10:20:00 [Link](https://pkg.golang.ir/time#pkg-constants).

func URL

func URL(input any) error

URL check if the provided input is a valid string and a valid URL.

func UUID

func UUID(input any) error

UUID check if the provided input is a valid string and a valid UUID.

func Validate

func Validate(validations []Validation) error

Types

type Rule

type Rule func(any) error

func DoesntEndWith

func DoesntEndWith(suffix string) Rule

DoesntEndWith check if the provided input is a valid string and ends with the provided substring

func DoesntStartWith

func DoesntStartWith(prefix string) Rule

DoesntStartWith check if the provided input is a valid string and doesn't starts with the provided substring

func EndsWith

func EndsWith(suffix string) Rule

EndsWith check if the provided input is a valid string and ends with the provided substring

func Enum

func Enum(enumValues ...string) Rule

Enum check if the provided input matches any of the listed enumerations values

func GreaterThanFloat

func GreaterThanFloat(limit float64) Rule

GreaterThanFloat check if provided input is a number and its value is greater than but not equal to the provided limit.

func GreaterThanInt

func GreaterThanInt(limit int) Rule

GreaterThanInt check if provided input is a number and its value is greater than but not equal to the provided limit.

func Length

func Length(length int) Rule

Length check if the provided input is a string and its length is equal to the provided length.

func LessThanFloat

func LessThanFloat(limit float64) Rule

LessThanFloat check if provided input is a number and its value is less than but not equal to the provided limit.

func LessThanInt

func LessThanInt(limit int) Rule

LessThanInt check if provided input is a number and its value is less than but not equal to the provided limit.

func MaxFloat

func MaxFloat(limit float64) Rule

MaxFloat check if provided input is a number and its value is more than or equal to the provided limit.

func MaxInt

func MaxInt(limit int) Rule

MaxInt check if provided input is a number and its value is more than or equal to the provided limit.

func MaxLength

func MaxLength(length int) Rule

MaxLength check if provided input is a string and its length is less than or equal to the provided length.

func MinFloat

func MinFloat(limit float64) Rule

MinFloat check if provided input is a number and its value is less than or equal to the provided limit.

func MinInt

func MinInt(limit int) Rule

MinInt check if provided input is a number and its value is less than or equal to the provided limit.

func MinLength

func MinLength(length int) Rule

MinLength check if provided input is a string and its length is more than or equal to the provided length.

func Regexp

func Regexp(pattern string) Rule

Regexp check if the provided input is a valid string and matches the required regular expression.

func Same

func Same(targetName string, targetValue any) Rule

Same check if the provided input is the same as the required input.

func StartsWith

func StartsWith(prefix string) Rule

StartsWith check if the provided input is a valid string and starts with the provided substring

type Validation

type Validation struct {
	Tag   string
	Data  any
	Rules []Rule
}

type ValidationErrors

type ValidationErrors struct {
	Errors map[string]string `json:"errors"`
}

func (ValidationErrors) Error

func (v ValidationErrors) Error() string

Jump to

Keyboard shortcuts

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