Documentation
¶
Overview ¶
Package rules provides a framework for defining and applying validation rules to data structures in order to provide consistent error codes and messages from GOBL.
Index ¶
- func Indirect(value interface{}) (interface{}, bool)
- func IsEmpty(value interface{}) bool
- func LengthOfValue(value interface{}) (int, error)
- func Register(pkg string, code Code, sets ...*Set)
- func RegisterWithGuard(pkg string, code Code, guard Test, sets ...*Set)
- func StringOrBytes(value interface{}) (isString bool, str string, isBytes bool, bs []byte)
- type Assertion
- type Code
- type Context
- type ContextAdder
- type ContextKey
- type ContextKeyable
- type ContextualTest
- type Def
- type Embeddable
- type Fault
- type Faults
- type Set
- type Test
- type WithContext
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Indirect ¶
func Indirect(value interface{}) (interface{}, bool)
Indirect returns the value that the given interface or pointer references to. If the value implements driver.Valuer, it will deal with the value returned by the Value() method instead. A boolean value is also returned to indicate if the value is nil or not (only applicable to interface, pointer, map, and slice). If the value is neither an interface nor a pointer, it will be returned back.
func IsEmpty ¶
func IsEmpty(value interface{}) bool
IsEmpty checks if a value is empty or not. A value is considered empty if - integer, float: zero - bool: false - string, array: len() == 0 - slice, map: nil or len() == 0 - interface, pointer: nil or the referenced value is empty
func LengthOfValue ¶
LengthOfValue returns the length of a value that is a string, slice, map, or array. An error is returned for all other types.
func RegisterWithGuard ¶
RegisterWithGuard is used to register a set of rules for a given namespace with an optional guard condition that determines when the rules should be applied.
Types ¶
type Assertion ¶
type Assertion struct {
// ID defines a globally unique code for this assertion.
ID Code `json:"id"`
// Desc is the human-readable message to include in faults when this assertion fails.
Desc string `json:"desc,omitempty"`
// Tests is a list of tests to evaluate for this assertion. A false result indicates a failure.
Tests []Test `json:"tests"`
}
Assertion represents a single validation rule definition.
func (Assertion) MarshalJSON ¶
MarshalJSON serializes Assertion to JSON, converting Tests to a comma-joined string.
type Code ¶
type Code string
Code defines a unique code to use for rules.
const GOBL Code = "GOBL"
GOBL for GOBL rules.
type Context ¶
type Context struct {
// contains filtered or unexported fields
}
Context holds key-value pairs accumulated during a rules.Validate call and is passed to ByContext test functions. Use Set to store values and Value to retrieve them.
func (Context) Each ¶
Each iterates over all values in the context, calling fn for each. Returns true as soon as fn returns true (short-circuit), false otherwise.
func (Context) Keys ¶
func (c Context) Keys() []ContextKey
Keys returns the set of distinct keys present in the context.
func (*Context) Set ¶
func (c *Context) Set(key ContextKey, value any)
Set appends a key-value pair to the validation context, preserving insertion order.
func (Context) Value ¶
func (c Context) Value(key ContextKey) any
Value returns the stored value for key, or nil if absent. Callers do a type assertion: v, ok := ctx.Value(key).(MyType)
type ContextAdder ¶
type ContextAdder interface {
RulesContext() WithContext
}
ContextAdder is implemented by objects that want to automatically inject values into the validation context when encountered by the rules engine.
type ContextKeyable ¶
type ContextKeyable interface {
ContextKeys() []ContextKey
}
ContextKeyable is optionally implemented by guard tests that can report which context keys they depend on. This enables the engine to skip guard evaluation entirely when none of the required keys are present in the validation context.
type ContextualTest ¶
ContextualTest is implemented by tests that need access to the validation context. The engine checks for this interface before falling back to the standard Test.Check method.
type Def ¶
type Def func(s *Set)
Def is a function that modifies a Set during construction. Assert, Field, Each, Object, and When all return Def values that compose as arguments to For.
func Assert ¶
Assert returns a Def that adds a single assertion to the parent set. The assertion is evaluated against the parent object (or extracted field value when used inside Field or Each).
func AssertIfPresent ¶
AssertIfPresent returns a Def that adds an assertion that is only evaluated when the current scoped value is non-nil and non-empty. Use this for optional fields that have format or content constraints.
func Each ¶
Each returns a Def that iterates over the elements of the current context, which must be a slice or array. It is intended to be used inside a Field that targets a slice field. All assertions and subsets inside Each are applied to each element individually.
Usage:
rules.Field("lines",
rules.Assert("01", "no duplicates", checkNoDups), // whole-slice assertion
rules.Each(
rules.Assert("02", "line required", is.Present), // per-element
),
)
Each panics at initialisation time if the parent context is not a slice or array.
func Field ¶
Field returns a Def that creates a field-scoped subset. name must be the JSON tag name of a field in the parent struct. All assertions and subsets inside Field receive the extracted field value when validating.
type Embeddable ¶
type Embeddable interface {
Embedded() any
}
Embeddable is implemented by types that wrap a private payload whose rules should be validated as if the payload were at the same JSON level as the wrapper. When the rules traversal encounters a struct that implements Embeddable, it calls Embedded() and recurses into the result without adding any path prefix.
type Fault ¶
type Fault struct {
// contains filtered or unexported fields
}
Fault represents a single rule assertion failure identified by a code and one or more paths. When multiple paths share the same code and message, they are merged into a single Fault. Fault is *not* designed to be instantiated directly, and will be created as part of the validation processes from defined rules.
func (*Fault) MarshalJSON ¶
MarshalJSON encodes the fault as a JSON object with paths, code, and message fields.
type Faults ¶
type Faults interface {
error
HasPath(path string) bool
HasCode(code Code) bool
// Len returns the number of faults in the collection.
Len() int
// First returns the first fault in the collection.
First() *Fault
// Last returns the last fault in the collection.
Last() *Fault
// At returns the fault at position i.
At(i int) *Fault
// List returns the underlying slice of faults.
List() []*Fault
}
Faults is the interface for a collection of validation faults. A nil value indicates no faults were found.
func Validate ¶
func Validate(obj any, opts ...WithContext) Faults
Validate uses the global registry of rule sets to validate the provided object. Each registered namespace set is applied in order; the Set.Validate method is responsible for matching the object type, evaluating guard conditions, running assertions, and recursively iterating exported struct fields. Returns nil when no faults are found.
Optional WithContext values inject additional context into the validation session. Context is also collected automatically from the root object's exported fields that implement ContextAdder (e.g. tax.Regime, tax.Addons).
type Set ¶
type Set struct {
// ID is the namespace for this set of rules, typically a package-level code like "GOBL" or "GOBL-ORG".
ID Code `json:"id,omitempty"`
// Package is the short package name used by Register to identify the rule set for generation purposes. It is only set by Register and RegisterWithGuard.
Package string `json:"package,omitempty"`
// Object is the fully-qualified Go type name (e.g. "bill.Invoice") that this set of rules applies to. It is set by For and is used for informational purposes.
Object string `json:"object,omitempty"`
// FieldName is the JSON tag name of the field this subset is scoped to. When non-empty, Validate extracts this field from the parent object and delegates to it.
FieldName string `json:"field,omitempty"`
// Each when true causes Validate to iterate over the slice elements of the field named by FieldName.
Each bool `json:"each,omitempty"`
// Guard is an optional expression that determines when this set of rules should be applied. If provided, the set will only be applied when the expression evaluates to true. The expression can reference any exported field from the struct associated with this set of rules.
Guard Test `json:"guard,omitempty"`
// Assert is a list of assertions to evaluate directly on the struct associated with this set of rules.
Assert []*Assertion `json:"assert,omitempty"`
// Subsets are additional sets of rules to apply recursively to the struct associated with this set of rules. They will be applied in order, and their assertions will be evaluated after the assertions in this set. Subsets can also have their own Test conditions, which will be evaluated independently.
Subsets []*Set `json:"subsets,omitempty"`
// contains filtered or unexported fields
}
Set represents a collection of rules grouped by a namespace an associated with a specific struct.
func AllSets ¶
func AllSets() []*Set
AllSets returns all rule sets registered in the global registry.
func For ¶
For creates a new set of rules for the provided object (struct or value type). Each Def is applied in order to build up the set's assertions and subsets. Assert, Field, Each, Object, and When all return Def values that can be passed here.
We let the compiler know that this function should not be "inlined" so that the package the caller is in can be detected reliably at runtime.
func NewSet ¶
NewSet creates a standalone namespace set from the given type-bound subsets. It prepends the namespace code to all assertion and set IDs and builds the type index for efficient lookup during validation.
Unlike Register, the returned set is NOT added to the global registry. Use Set.Validate to validate objects against it directly.
The input sets are cloned internally, so the same output of For can safely be passed to multiple NewSet or Register calls.
func (Set) MarshalJSON ¶
MarshalJSON serializes Set to JSON, converting the Test field to its string representation.
func (*Set) Validate ¶
func (s *Set) Validate(obj any, opts ...WithContext) Faults
Validate validates an object against the set's rules. If the set has a test condition (from When), it is evaluated first and the set is skipped when false. Returns nil when no faults are found.
Optional WithContext values inject additional context into the validation session. Context is also collected automatically from the root object's exported fields that implement ContextAdder (e.g. tax.Regime, tax.Addons).
type WithContext ¶
type WithContext func(*Context)
WithContext is a functional option for rules.Validate that injects values into the validation context before validation begins.