Repository navigation
Expand file tree
/
Copy pathllms.txt
More file actions
139 lines (111 loc) · 7.4 KB
/
Copy pathllms.txt
File metadata and controls
139 lines (111 loc) · 7.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# validator
> Go validation for structs, maps, JSON, form values and single values with a boolean rule expression DSL, atomic binding, filters and localized messages.
## Overview
validator (module `github.com/libtnb/validator`, Go 1.27, standard library only) compiles rule expressions such as `required && (email || regex:"^[a-z]+$")` and evaluates them against struct tags, maps, JSON objects, `url.Values` or one value. It reports failures per field with resolvable messages, distinguishes rule execution errors from data failures, and can bind the validated (filtered) input into a struct atomically. It is for HTTP request validation and any place typed input must be checked before use.
## Quick Start
```bash
go get github.com/libtnb/validator
```
```go
package main
import (
"context"
"fmt"
"github.com/libtnb/validator"
)
type User struct {
Email string `validate:"required && email"`
Age int `validate:"required && gte:18"`
Tags []string `validate:"dive && alpha"`
}
func main() {
vd := validator.MustStruct(User{Email: "a@b.com", Age: 17})
if err := vd.Validate(context.Background()); err != nil {
fmt.Println(err) // Age: The Age field must be greater than or equal to 18.
}
}
```
## Key Concepts
- **Validator**: immutable, concurrency-safe factory built with `New(options...)`; caches compiled expressions and struct plans. Package-level functions use `Default()`.
- **Validation**: one input plus its rules; configure with `AddRules`, `AddFilters`, `AddMessages`, then `Validate(ctx)` once (later mutations return `ErrValidated`). Not safe for concurrent use.
- **Expression DSL**: `!` > `&&` > `||`, parentheses, `rule:arg1,arg2` arguments (quotes and backslashes escape), `dive` for collection elements, `sometimes` to skip absent fields. `regex`/`not_regex` take one raw argument.
- **Empty values pass** most rules; presence is `required` (presence only, or non-zero with `WithStrictRequired`), `filled`, `notblank`.
- **Struct collections**: struct elements of slices, arrays and maps are validated against their own tags without `dive`, reported as `field[i].sub` / `field[key].sub`; nil pointer elements validate as the zero value.
- **Cross-field scoping**: a bare sibling name resolves in the same nested object first, then from the root; dotted names are absolute; inside a struct collection element the element is the root.
- **Filters**: `trim|lower|int` chains run before rules and feed `ValidateAs`; never applied to `dive` fields.
- **Errors vs failures**: `*Errors` holds field failures; `*RuleError` means a rule could not complete and is never a field failure; `*RulesError` means an expression is invalid; `*BindError` means a conversion failed.
## API Reference
### Core Functions
- `New(options ...Option) (*Validator, error)` / `MustNew` - build a Validator; errors: `ErrInvalidOption`, `ErrInvalidSignature`, `ErrDuplicateRule`, `ErrDuplicateFilter`.
- `Struct(data any) (*Validation, error)` - rules from struct tags; `ErrInvalidInput` for non-structs, `*RulesError` for bad tags.
- `Valid(ctx, data any) (bool, error)` - verdict only, stops at first failure, no filters, alloc-free for built-in rules.
- `Map(data M, rules map[string]string)` / `JSON(data, rules)` / `Values(data url.Values, rules)` / `Value(value any, rule string)` - explicit-expression inputs; `Values` maps a repeated key to `[]string`.
- `Check[T]() error` / `Validator.CheckType(reflect.Type)` - compile every tag on a struct type at start-up.
- `Describe[T]() ([]FieldRules, error)` / `Validator.DescribeType` - flattened rules per field for schema generators.
- `Rules() []Rule` / `Filters() []Filter` - copies of the built-in catalog (91 rules, 10 filters).
- `AsErrors(err error) (*Errors, bool)` - recover the failure collection from a wrapped error.
- `IsEmpty(v any) bool` / `IsEmptyValue(reflect.Value) bool` - the omitempty semantics rules share.
- Options: `WithTagName`, `WithTagNameFunc`, `WithStrictRequired`, `WithPrivateFieldValidation`, `WithoutBuiltinRules`, `WithAttributes`, `WithMessages`, `WithTranslation`, `WithTranslator`, `WithTransformFunc`, `WithParallel`, `WithRules`, `WithFallibleRules`, `WithFilters`, `WithRuleFunc`, `WithStringRule`.
### Core Types
- `Validation` - `Validate(ctx) error`, `ValidateAs[T](ctx, *T) error`, `Bind[T](*T) error`, `Errors() *Errors`, `Err() error`, `Fails() bool`, `AddRules`, `RemoveRules`, `ClearRules`, `Rules()`, `AddFilters`, `RemoveFilters`, `ClearFilters`, `Filters()`, `AddMessages`.
- `Errors` - `One()`, `OneFor(field)`, `Messages(field)`, `All()`, `Items()`, `Has(field)`, `Error()`.
- `FieldError` - `Field`, `Rule`, `Message` (template), `Params`.
- `Field` - value handed to rules: `Reflect()`, `Value[T]()`, `Attrs()`, `Name()`, `Root[T]()`, `Context()`, `SiblingValue(name)`, `Sibling[T](name)`. Pooled: never retain it.
- `Rule` - `Signature()`, `Passes(*Field) bool`, `Message()`; deterministic and concurrency-safe.
- `FallibleRule` - `Signature()`, `Validate(*Field) (bool, error)`, `Message()`; errors become `*RuleError`.
- `Filter` - `Signature()`, `Handle(val any, args ...string) (any, error)`.
- `RuleError`, `RulesError`, `BindError` - typed errors with `Field` and `Err`; `Unwrap` exposes the sentinels.
- `FieldRules`, `RuleInfo` - introspection output.
- Subpackages: `is` (format predicates), `conv` (lossless conversions), `translations` (`Es`, `Ja`, `Ko`, `Ru`, `ZhHans`, `ZhHant`).
## Common Patterns
### Validate and bind an HTTP form
```go
v := validator.MustNew(validator.WithTagNameFunc(func(f reflect.StructField) string {
name, _, _ := strings.Cut(f.Tag.Get("json"), ",")
return name
}))
vd := v.MustValues(r.Form, map[string]string{
"name": "required && alpha",
"tags": "required && dive && alpha", // tags=a&tags=b -> []string
})
var form struct {
Name string `json:"name"`
Tags []string `json:"tags"`
}
if err := vd.ValidateAs(r.Context(), &form); err != nil {
if errs, ok := validator.AsErrors(err); ok {
// 400 with errs.All()
} else {
// 500: *RuleError, *BindError, or cancellation
}
}
```
### Custom rule
```go
v := validator.MustNew(validator.WithRuleFunc("even", func(f *validator.Field) bool {
n, ok := f.Value[int]()
return ok && n%2 == 0
}, "The {field} must be even."))
```
### Fail fast on bad tags
```go
func init() {
if err := validator.Check[Signup](); err != nil {
panic(err) // joined *RulesError values
}
}
```
## Error Handling
- `ErrInvalidOption`, `ErrInvalidSignature`, `ErrDuplicateRule`, `ErrDuplicateFilter` - returned by `New`; fix the configuration.
- `ErrInvalidInput` - the constructor received a non-struct, non-map or malformed JSON input.
- `ErrInvalidRules` (via `*RulesError`) - an expression does not compile; the `Field` names the tag. Returned by constructors and `Check`.
- `ErrRuleEvaluation` / `ErrRulePanic` (via `*RuleError`) - a `FallibleRule` failed or a rule panicked; treat as an internal error, not user input.
- `ErrValidationFailed` - joined into `ValidateAs` errors caused by field failures; use `AsErrors` for details.
- `ErrBindTarget` / `ErrBindConversion` (via `*BindError`) - binding destination or conversion problem; the destination is unchanged.
- `ErrNilContext` - `Validate`, `ValidateAs` or `Valid` received a nil context.
- `ErrValidated` - a mutation was attempted after `Validate` ran.
## References
- Documentation: https://pkg.go.dev/github.com/libtnb/validator
- Repository: https://github.com/libtnb/validator
- Go Reference: https://pkg.go.dev/github.com/libtnb/validator
- Issues: https://github.com/libtnb/validator/issues