validator

package
v0.3.5 Latest Latest
Warning

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

Go to latest
Published: Feb 17, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package validator provides a rule-based data validation system with both programmatic and struct tag-based validation capabilities.

The package is built around a Rule type that encapsulates validation logic and error reporting, allowing for flexible and composable validation patterns.

Core Concepts

Rules are created by validation functions that return a Rule struct containing both the validation check and error details:

import "github.com/dmitrymomot/forge/pkg/validator"

// Create validation rules
rules := []validator.Rule{
	validator.Required("username", user.Username),
	validator.MinLen("username", user.Username, 3),
	validator.ValidEmail("email", user.Email),
}

// Apply all rules
if err := validator.Apply(rules...); err != nil {
	// Handle validation errors
	validationErrs := validator.ExtractValidationErrors(err)
	for _, verr := range validationErrs {
		fmt.Printf("Field: %s, Message: %s\n", verr.Field, verr.Message)
	}
}

String Validation

String validation functions for common requirements:

rules := []validator.Rule{
	validator.Required("name", user.Name),
	validator.MinLen("name", user.Name, 2),
	validator.MaxLen("name", user.Name, 50),
	validator.ValidEmail("email", user.Email),
	validator.ValidURL("website", user.Website),
	validator.ValidPhone("phone", user.Phone),
	validator.ValidAlphanumeric("username", user.Username),
}

Numeric Validation

Type-safe numeric validation using generics:

rules := []validator.Rule{
	validator.Min("age", user.Age, 18),
	validator.Max("age", user.Age, 120),
	validator.Min("price", product.Price, 0.01),
	validator.Max("quantity", order.Quantity, 1000),
}

Collection Validation

Validation for slices and maps:

rules := []validator.Rule{
	validator.RequiredSlice("items", order.Items),
	validator.MinLenSlice("items", order.Items, 1),
	validator.MaxLenSlice("tags", post.Tags, 10),
	validator.RequiredMap("metadata", user.Metadata),
}

Choice Validation

Validate values against allowed/forbidden lists:

validStatuses := []string{"active", "inactive", "pending"}
rules := []validator.Rule{
	validator.InList("status", user.Status, validStatuses),
}

forbiddenUsernames := []string{"admin", "root", "system"}
rules = append(rules,
	validator.NotInList("username", user.Username, forbiddenUsernames),
)

UUID Validation

UUID validation with version support:

import "github.com/google/uuid"

rules := []validator.Rule{
	validator.ValidUUID("id", user.ID),
	validator.ValidUUIDv4String("session_id", session.ID),
	validator.RequiredUUID("user_id", userUUID),
}

Format Validation

Various format validators:

rules := []validator.Rule{
	validator.ValidEmail("email", user.Email),
	validator.ValidURL("website", user.Website),
	validator.ValidURLWithScheme("api_url", config.APIURL, []string{"https"}),
	validator.ValidPhone("phone", user.Phone),
	validator.ValidIPv4("server", config.ServerIP),
	validator.ValidMAC("device_mac", device.MACAddress),
}

Financial Validation

Financial data validation:

rules := []validator.Rule{
	validator.PositiveAmount("amount", payment.Amount),
	validator.ValidCurrencyCode("currency", payment.Currency),
	validator.ValidCreditCardChecksum("card_number", payment.CardNumber),
	validator.DecimalPrecision("price", product.Price, 2),
	validator.ValidPercentage("tax_rate", order.TaxRate),
}

Pattern Validation

Regular expression and pattern matching:

rules := []validator.Rule{
	validator.MatchesRegex("sku", product.SKU, `^[A-Z]{2}\d{4}$`, "product SKU"),
	validator.NoWhitespace("api_key", config.APIKey),
	validator.PrintableChars("description", item.Description),
}

Struct Tag Validation

The package supports struct tag-based validation:

type User struct {
	Username string `validate:"required;min:3;max:20;alphanum"`
	Email    string `validate:"required;email"`
	Age      int    `validate:"min:18;max:120"`
	Status   string `validate:"in:active,inactive,pending"`
}

user := User{
	Username: "john_doe",
	Email:    "john@example.com",
	Age:      25,
	Status:   "active",
}

if err := validator.ValidateStruct(&user); err != nil {
	// Handle validation errors
	validationErrs := validator.ExtractValidationErrors(err)
	for _, verr := range validationErrs {
		fmt.Printf("%s: %s\n", verr.Field, verr.Message)
	}
}

Custom Validators

Register custom validation functions for struct tags:

validator.RegisterValidator("business_email", func(field string, value reflect.Value, params []string) validator.Rule {
	email := value.String()
	return validator.Rule{
		Check: func() bool {
			// Custom business email validation logic
			return strings.HasSuffix(email, "@company.com")
		},
		Error: validator.ValidationError{
			Field:   field,
			Message: "must be a company email address",
		},
	}
})

Error Handling

ValidationErrors provides methods for working with validation results:

if err := validator.Apply(rules...); err != nil {
	if validator.IsValidationError(err) {
		validationErrs := validator.ExtractValidationErrors(err)

		// Check for specific field errors
		if validationErrs.Has("email") {
			emailErrors := validationErrs.Get("email")
			fmt.Println("Email errors:", emailErrors)
		}

		// Get all failed fields
		failedFields := validationErrs.Fields()
		fmt.Println("Failed fields:", failedFields)
	}
}

Translation Support

ValidationError includes translation keys and values for internationalization. Use the Translate method on ValidationErrors with a TranslateFunc to translate all error messages in a single call. The i18n Translator.TranslateMessage method matches TranslateFunc directly:

if err := validator.Apply(rules...); err != nil {
	ve := validator.ExtractValidationErrors(err)
	ve.Translate(translator.TranslateMessage) // translates Message fields in-place
	for _, verr := range ve {
		fmt.Printf("%s: %s\n", verr.Field, verr.Message)
	}
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Apply

func Apply(rules ...Rule) error

Apply executes multiple validation rules and returns any validation errors.

func IsValidationError

func IsValidationError(err error) bool

func RegisterValidator

func RegisterValidator(name string, fn ValidatorFunc)

RegisterValidator adds a custom validator function to the registry

func ValidateStruct

func ValidateStruct(v any) error

ValidateStruct validates a struct based on its field tags

Types

type Numeric

type Numeric interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 |
		~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
		~float32 | ~float64
}

type PasswordStrengthConfig

type PasswordStrengthConfig struct {
	MinLength        int
	MaxLength        int
	RequireUppercase bool
	RequireLowercase bool
	RequireDigits    bool
	RequireSpecial   bool
	MinCharClasses   int // Minimum number of different character classes required
}

func DefaultPasswordStrength

func DefaultPasswordStrength() PasswordStrengthConfig

DefaultPasswordStrength returns NIST-recommended password policy: 8-128 chars, 3+ character classes.

type Rule

type Rule struct {
	Check func() bool
	Error ValidationError
}

Rule represents a single validation rule.

func ASCIIOnly

func ASCIIOnly(field, value string) Rule

ASCIIOnly validates that a string contains only ASCII characters.

func AgeBetween

func AgeBetween(field string, birthdate time.Time, minAge int, maxAge int) Rule

func AmountRange

func AmountRange[T Numeric](field string, value T, min T, max T) Rule

func BalancedParentheses

func BalancedParentheses(field, value string) Rule

BalancedParentheses validates that parentheses in a string are balanced.

func BusinessHours

func BusinessHours(field string, value time.Time, startHour int, endHour int) Rule

func ContainsDigit

func ContainsDigit(field, value string) Rule

ContainsDigit validates that a string contains at least one digit.

func ContainsLowercase

func ContainsLowercase(field, value string) Rule

ContainsLowercase validates that a string contains at least one lowercase letter.

func ContainsPattern

func ContainsPattern(field, value string, pattern string, description string) Rule

ContainsPattern validates that a string contains a specific pattern.

func ContainsUppercase

func ContainsUppercase(field, value string) Rule

ContainsUppercase validates that a string contains at least one uppercase letter.

func CurrencyPrecision

func CurrencyPrecision(field string, value float64, decimals int) Rule

CurrencyPrecision enforces currency-specific decimal rules (USD=2, JPY=0, etc.).

func DateAfter

func DateAfter(field string, value time.Time, after time.Time) Rule

func DateBefore

func DateBefore(field string, value time.Time, before time.Time) Rule

func DateBetween

func DateBetween(field string, value time.Time, start time.Time, end time.Time) Rule

func DecimalPrecision

func DecimalPrecision(field string, value float64, maxDecimals int) Rule

DecimalPrecision prevents floating-point precision issues in financial calculations.

func DoesNotMatchRegex

func DoesNotMatchRegex(field, value string, pattern string, description string) Rule

func EndsWithPattern

func EndsWithPattern(field, value string, pattern string) Rule

EndsWithPattern validates that a string ends with a specific pattern.

func FutureDate

func FutureDate(field string, value time.Time) Rule

func InList

func InList[T comparable](field string, value T, allowedValues []T) Rule

func InListCaseInsensitive

func InListCaseInsensitive(field, value string, allowedValues []string) Rule

func InListString

func InListString(field, value string, allowedValues []string) Rule

func Len

func Len(field, value string, exact int) Rule

func LenMap

func LenMap[K comparable, V any](field string, value map[K]V, exact int) Rule

func LenSlice

func LenSlice[T any](field string, value []T, exact int) Rule

func LenString

func LenString(field, value string, exact int) Rule

func LineCount

func LineCount(field, value string, min int, max int) Rule

LineCount validates that a string has a specific number of lines.

func MatchesRegex

func MatchesRegex(field, value string, pattern string, description string) Rule

MatchesRegex validates against custom patterns. Compiles regex on each call - cache externally for performance.

func Max

func Max[T Numeric](field string, value T, max T) Rule

func MaxAge

func MaxAge(field string, birthdate time.Time, maxAge int) Rule

func MaxLen

func MaxLen(field, value string, max int) Rule

func MaxLenMap

func MaxLenMap[K comparable, V any](field string, value map[K]V, max int) Rule

func MaxLenSlice

func MaxLenSlice[T any](field string, value []T, max int) Rule

func MaxLenString

func MaxLenString(field, value string, max int) Rule

func MaxNum

func MaxNum[T Numeric](field string, value T, max T) Rule

func MaximumTransaction

func MaximumTransaction[T Numeric](field string, value T, maximum T) Rule

MaximumTransaction validates that a transaction amount doesn't exceed a maximum limit.

func Min

func Min[T Numeric](field string, value T, min T) Rule

func MinAge

func MinAge(field string, birthdate time.Time, minAge int) Rule

MinAge validates minimum age by calculating years elapsed, accounting for leap years and exact dates.

func MinLen

func MinLen(field, value string, min int) Rule

func MinLenMap

func MinLenMap[K comparable, V any](field string, value map[K]V, min int) Rule

func MinLenSlice

func MinLenSlice[T any](field string, value []T, min int) Rule

func MinLenString

func MinLenString(field, value string, min int) Rule

func MinNum

func MinNum[T Numeric](field string, value T, min T) Rule

func MinimumPurchase

func MinimumPurchase[T Numeric](field string, value T, minimum T) Rule

MinimumPurchase validates that a purchase amount meets a minimum threshold.

func NoControlChars

func NoControlChars(field, value string) Rule

NoControlChars validates that a string contains no control characters.

func NoRepeatingChars

func NoRepeatingChars(field, value string, maxRepeats int) Rule

func NoSequentialChars

func NoSequentialChars(field, value string, maxSequential int) Rule

NoSequentialChars prevents patterns like "abc" or "123" that reduce effective entropy.

func NoSpecialChars

func NoSpecialChars(field, value string) Rule

NoSpecialChars validates that a string contains no special characters (only letters, numbers, and spaces).

func NoWhitespace

func NoWhitespace(field, value string) Rule

NoWhitespace validates that a string contains no whitespace characters.

func NonNegativeAmount

func NonNegativeAmount[T Numeric](field string, value T) Rule

func NonNilUUID

func NonNilUUID(field string, value uuid.UUID) Rule

func NonNilUUIDString

func NonNilUUIDString(field, value string) Rule

func NoneOf

func NoneOf[T comparable](field string, value T, options []T) Rule

func NoneOfString

func NoneOfString(field, value string, options []string) Rule

func NotCommonPassword

func NotCommonPassword(field, value string) Rule

func NotInList

func NotInList[T comparable](field string, value T, forbiddenValues []T) Rule

func NotInListCaseInsensitive

func NotInListCaseInsensitive(field, value string, forbiddenValues []string) Rule

func NotInListString

func NotInListString(field, value string, forbiddenValues []string) Rule

func OneOf

func OneOf[T comparable](field string, value T, options []T) Rule

func OneOfString

func OneOfString(field, value string, options []string) Rule

func OnlyWhitespace

func OnlyWhitespace(field, value string) Rule

OnlyWhitespace validates that a string contains only whitespace characters.

func PasswordDigit

func PasswordDigit(field, value string) Rule

func PasswordEntropy

func PasswordEntropy(field, value string, minEntropy float64) Rule

PasswordEntropy validates password randomness using Shannon entropy. 50+ bits indicates strong randomness, 40-49 is moderate, <40 is weak.

func PasswordLowercase

func PasswordLowercase(field, value string) Rule

func PasswordSpecialChar

func PasswordSpecialChar(field, value string) Rule

func PasswordUppercase

func PasswordUppercase(field, value string) Rule

func PastDate

func PastDate(field string, value time.Time) Rule

func PositiveAmount

func PositiveAmount[T Numeric](field string, value T) Rule

func PrintableChars

func PrintableChars(field, value string) Rule

PrintableChars validates that a string contains only printable characters.

func Required

func Required(field, value string) Rule

func RequiredComparable

func RequiredComparable[T comparable](field string, value T) Rule

func RequiredMap

func RequiredMap[K comparable, V any](field string, value map[K]V) Rule

func RequiredNum

func RequiredNum[T Numeric](field string, value T) Rule

func RequiredSlice

func RequiredSlice[T any](field string, value []T) Rule

func RequiredString

func RequiredString(field, value string) Rule

RequiredString validates that a string is not empty after trimming whitespace.

func RequiredUUID

func RequiredUUID(field string, value uuid.UUID) Rule

func RequiredUUIDString

func RequiredUUIDString(field, value string) Rule

func StartsWithPattern

func StartsWithPattern(field, value string, pattern string) Rule

StartsWithPattern validates that a string starts with a specific pattern.

func StrongPassword

func StrongPassword(field, value string, config PasswordStrengthConfig) Rule

func TimeAfter

func TimeAfter(field string, value time.Time, after time.Time) Rule

TimeAfter compares time-of-day only, ignoring date component.

func TimeBefore

func TimeBefore(field string, value time.Time, before time.Time) Rule

func TimeBetween

func TimeBetween(field string, value time.Time, start time.Time, end time.Time) Rule

func ValidAPIKey

func ValidAPIKey(field, value string, minLength int, maxLength int) Rule

ValidAPIKey validates that a string looks like a valid API key.

func ValidAccountNumber

func ValidAccountNumber(field, value string) Rule

ValidAccountNumber validates that a bank account number is in a reasonable format. This is a basic validation - real implementations should use country-specific rules.

func ValidAlpha

func ValidAlpha(field, value string) Rule

func ValidAlphanumeric

func ValidAlphanumeric(field, value string) Rule

func ValidBase64

func ValidBase64(field, value string) Rule

ValidBase64 validates that a string is valid base64 encoding.

func ValidBirthdate

func ValidBirthdate(field string, value time.Time) Rule

ValidBirthdate ensures reasonable birthdate constraints: not future, not older than 150 years.

func ValidCategory

func ValidCategory(field, value string, allowedCategories []string) Rule

func ValidCreditCardChecksum

func ValidCreditCardChecksum(field, value string) Rule

ValidCreditCardChecksum validates a credit card number using the Luhn algorithm.

func ValidCurrencyCode

func ValidCurrencyCode(field, value string) Rule

ValidCurrencyCode validates that a string is a valid ISO 4217 currency code.

func ValidCustomID

func ValidCustomID(field, value string, pattern string, description string) Rule

ValidCustomID validates that a string matches a custom identifier pattern.

func ValidDiscount

func ValidDiscount(field string, value float64) Rule

ValidDiscount validates that a discount percentage is reasonable (0-100%).

func ValidDomainName

func ValidDomainName(field, value string) Rule

ValidDomainName validates that a string is a valid domain name.

func ValidEmail

func ValidEmail(field, value string) Rule

ValidEmail validates email addresses using RFC 5322 with additional web-friendly constraints. Rejects edge cases like quoted local parts and comments that are valid per RFC but problematic for web apps.

func ValidEnum

func ValidEnum(field, value string, enumValues []string) Rule

func ValidEnumCaseInsensitive

func ValidEnumCaseInsensitive(field, value string, enumValues []string) Rule

func ValidHandle

func ValidHandle(field, value string, minLen int, maxLen int) Rule

ValidHandle validates that a string is a valid handle (starts with letter, then letters/numbers/underscore/hyphen).

func ValidHexString

func ValidHexString(field, value string, exactLength int) Rule

ValidHexString validates that a string contains only hexadecimal characters.

func ValidIP

func ValidIP(field, value string) Rule

func ValidIPv4

func ValidIPv4(field, value string) Rule

func ValidIPv6

func ValidIPv6(field, value string) Rule

func ValidInterestRate

func ValidInterestRate(field string, value float64, maxRate float64) Rule

ValidInterestRate validates that an interest rate is reasonable.

func ValidMAC

func ValidMAC(field, value string) Rule

func ValidNumericString

func ValidNumericString(field, value string) Rule

func ValidOTP

func ValidOTP(field, value string, length int) Rule

ValidOTP validates that a string is a valid OTP code with the specified length. The OTP must contain exactly the specified number of digits (0-9 only).

func ValidPercentage

func ValidPercentage(field string, value float64) Rule

ValidPercentage validates that a value is a valid percentage (0-100).

func ValidPermission

func ValidPermission(field, value string, allowedPermissions []string) Rule

func ValidPhone

func ValidPhone(field, value string) Rule

ValidPhone validates international phone numbers in E.164 format. Allows common formatting chars (spaces, dashes) but requires 7-15 digits total.

func ValidProductCode

func ValidProductCode(field, value string, pattern string) Rule

ValidProductCode validates that a string is a valid product code.

func ValidRole

func ValidRole(field, value string, allowedRoles []string) Rule

func ValidRoutingNumber

func ValidRoutingNumber(field, value string) Rule

ValidRoutingNumber validates that a routing number is in the correct format (US).

func ValidSKU

func ValidSKU(field, value string) Rule

ValidSKU validates that a string is a valid SKU (Stock Keeping Unit).

func ValidSlug

func ValidSlug(field, value string) Rule

ValidSlug validates URL-safe slugs, preventing edge cases like leading/trailing hyphens.

func ValidSlugNotReserved

func ValidSlugNotReserved(field, value string, reserved ...string) Rule

ValidSlugNotReserved validates URL-safe slugs and ensures they are not in the reserved list. The reserved slug check is case-insensitive.

func ValidStatus

func ValidStatus(field, value string, allowedStatuses []string) Rule

func ValidSubdomain

func ValidSubdomain(field, value string) Rule

ValidSubdomain validates that a string is a valid subdomain.

func ValidTaxRate

func ValidTaxRate(field string, value float64) Rule

ValidTaxRate validates that a tax rate is reasonable (0-100%).

func ValidTicketNumber

func ValidTicketNumber(field, value string, prefix string) Rule

ValidTicketNumber validates that a string is a valid ticket/reference number.

func ValidURL

func ValidURL(field, value string) Rule

func ValidURLWithScheme

func ValidURLWithScheme(field, value string, schemes []string) Rule

func ValidUUID

func ValidUUID(field, value string) Rule

ValidUUID validates standard UUID format with pre-validation to avoid expensive parsing.

func ValidUUIDVersion

func ValidUUIDVersion(field string, value uuid.UUID, version int) Rule

func ValidUUIDVersionString

func ValidUUIDVersionString(field, value string, version int) Rule

func ValidUUIDv1

func ValidUUIDv1(field string, value uuid.UUID) Rule

func ValidUUIDv1String

func ValidUUIDv1String(field, value string) Rule

func ValidUUIDv3

func ValidUUIDv3(field string, value uuid.UUID) Rule

func ValidUUIDv3String

func ValidUUIDv3String(field, value string) Rule

func ValidUUIDv4

func ValidUUIDv4(field string, value uuid.UUID) Rule

func ValidUUIDv4String

func ValidUUIDv4String(field, value string) Rule

func ValidUUIDv5

func ValidUUIDv5(field string, value uuid.UUID) Rule

func ValidUUIDv5String

func ValidUUIDv5String(field, value string) Rule

func ValidUsername

func ValidUsername(field, value string, minLen int, maxLen int) Rule

func ValidVersion

func ValidVersion(field, value string) Rule

ValidVersion validates that a string is a valid semantic version.

func Weekend

func Weekend(field string, value time.Time) Rule

func WordCount

func WordCount(field, value string, min int, max int) Rule

WordCount validates that a string has a specific number of words.

func WorkingDay

func WorkingDay(field string, value time.Time) Rule

type TranslateFunc

type TranslateFunc func(key string, values map[string]any) string

TranslateFunc translates a message key with the given values into a localized string.

type ValidationError

type ValidationError struct {
	TranslationValues map[string]any
	Field             string
	Message           string
	TranslationKey    string
}

ValidationError represents a single validation error with translation support.

type ValidationErrors

type ValidationErrors []ValidationError

ValidationErrors represents a collection of validation errors.

func ExtractValidationErrors

func ExtractValidationErrors(err error) ValidationErrors

ExtractValidationErrors extracts ValidationErrors from an error.

func (*ValidationErrors) Add

func (ve *ValidationErrors) Add(err ValidationError)

func (ValidationErrors) Error

func (ve ValidationErrors) Error() string

func (ValidationErrors) Fields

func (ve ValidationErrors) Fields() []string

func (ValidationErrors) Get

func (ve ValidationErrors) Get(field string) []string

func (ValidationErrors) GetErrors

func (ve ValidationErrors) GetErrors(field string) []ValidationError

func (ValidationErrors) Has

func (ve ValidationErrors) Has(field string) bool

func (ValidationErrors) IsEmpty

func (ve ValidationErrors) IsEmpty() bool

func (ValidationErrors) Translate

func (ve ValidationErrors) Translate(fn TranslateFunc)

Translate replaces the Message field of each ValidationError in-place using the provided translation function. Errors with an empty TranslationKey are skipped. It is a no-op if fn is nil or the slice is empty.

type ValidatorFunc

type ValidatorFunc func(field string, value reflect.Value, params []string) Rule

ValidatorFunc is a function that validates a value and returns a Rule

Jump to

Keyboard shortcuts

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