Documentation
¶
Overview ¶
Package condition is the Condition: the typed tree of tests on a Contact (the API contract's tree, ADR 0029, ADR 0054), its validation and its compiler to a Contact predicate. A Segment is a named Condition and a Rule holds one. A group {kind: "group", combinator: and|or, not, rules[]} whose entries are nested groups or leaves {kind: "rule", field, operator, value}, told apart by `kind`.
A leaf is built from ent's generated predicates wherever one exists: the core attributes (contact.EmailEQ …), Tags (contact.HasTagsWith) and Events (contact.HasEventsWith). The one dynamic piece is a Custom field's key inside the custom_fields JSON column, which no generated predicate covers; it is addressed with ent's JSON predicates (sqljson) after the key is checked. A leaf may only name a core attribute, a Tag, an Event action, or a Custom field of the Workspace's catalogue (ADR 0006).
Index ¶
- Variables
- func Compile(ctx context.Context, s *ent.Scoped, g Group) (predicate.Contact, error)
- func ContactPredicate(ctx context.Context, s *ent.Scoped, def string) (predicate.Contact, error)
- func Decode(def string, into json.Unmarshaler) error
- func Encode(group json.Marshaler) (string, error)
- func EncodeOptional[G any, P interface{ ... }](opt interface{ ... }) (*string, error)
- func RulePredicate(ctx context.Context, s *ent.Scoped, def string, props map[string]any) (predicate.Contact, error)
- type Group
- type Leaf
Constants ¶
This section is empty.
Variables ¶
var ErrStorage = errors.New("condition: storage")
ErrStorage marks a failure to read what compiling needs from the database, as opposed to a condition that does not compile.
Functions ¶
func Compile ¶
Compile turns a condition group into a Contact predicate. An empty rule set matches everyone (an empty negated group matches no one) — deliberate, so an empty rule is never a silent "nobody". A "trigger:" leaf is refused: only a Rule has an Event.
func ContactPredicate ¶
ContactPredicate parses a stored condition and compiles it for the Workspace of s.
func Decode ¶
func Decode(def string, into json.Unmarshaler) error
Decode loads a stored condition into an API DTO.
func Encode ¶
Encode stores a condition given as an API DTO. The API's typed tree is the stored shape: a condition is saved as its JSON, and ContactPredicate reads it back.
func EncodeOptional ¶
func EncodeOptional[G any, P interface { *G json.Marshaler }](opt interface{ Get() (G, bool) }) (*string, error)
EncodeOptional is Encode for a condition the request may leave out: nil when it is absent.
func RulePredicate ¶
func RulePredicate(ctx context.Context, s *ent.Scoped, def string, props map[string]any) (predicate.Contact, error)
RulePredicate parses a Rule's stored condition and compiles it for the Workspace of s, with "trigger:<key>" leaves allowed. They are evaluated in memory against props, the properties of the Event that fired the Rule, and folded into the tree as constants before the rest compiles to a predicate (the Event's row may not exist yet). A key the Event lacks, or a value of another type, makes the leaf false. Any key is valid, so props may be nil to only validate.
Types ¶
type Group ¶
type Group struct {
Kind string `json:"kind"`
Combinator string `json:"combinator"`
Not bool `json:"not,omitempty"`
Rules []json.RawMessage `json:"rules"`
}
Group is a group of the rule tree. Each rules[] entry is decoded lazily because it is either a nested Group or a Leaf, as its `kind` says.
func Parse ¶
Parse decodes a stored condition into a Group. A blank condition is a valid "match everyone" group.