Documentation
¶
Overview ¶
Package model defines document classes: the class definition as JSON, its validation into a compiled Class, the named schemas and the predefined vocabulary, and the diagnostics a definition earns.
A Definition is the class as written (docs/architecture.md, ADR-0013, ADR-0018, ADR-0022, ADR-0023, ADR-0031 to ADR-0034). Compile checks every name, type and property, binds every formula against the class's variables with the function classes its mode allows (ADR-0015), builds the dependency graph of the computed variables and refuses a cycle, and lays the variables out as the typed columns and child tables of ADR-0014. Everything it refuses, it refuses at definition time, as a list of Diagnostics: a stable code, the JSON pointer of the element, the position inside a formula, a message and, where there is one, a fix. A caller that drives the engine without a person watching reads the code and the path; a person reads the message.
The statechart (Phase 3), rules and actions (Phase 4) and access rules and rights (Phase 5) are part of the class format already. Compile checks their structure and binds their formulas so that a definition is valid as a whole, and the engine runs them when their phase arrives.
Index ¶
- Constants
- func Compile(def *Definition, schemas *SchemaSet) (*Class, Diagnostics)
- func CompileIn(def *Definition, env Env) (*Class, Diagnostics)
- func CompileTable(def *TableDef) (*Table, Diagnostics)
- func Define(data []byte, schemas *SchemaSet) (*Class, Diagnostics)
- func DefineIn(data []byte, env Env) (*Class, Diagnostics)
- func DefineTable(data []byte) (*Table, Diagnostics)
- func Parse(data []byte) (*Definition, Diagnostics)
- func ParseSchema(data []byte) (*SchemaDef, Diagnostics)
- func ParseTable(data []byte) (*TableDef, Diagnostics)
- func VocabularyNames() []string
- type Access
- type AccessDef
- type Change
- type ChangeKind
- type ChildTable
- type Class
- type Column
- type ComputeMode
- type Definition
- type Diagnostic
- type Diagnostics
- type Env
- type Leaf
- type Presentation
- type PresentationDef
- type Right
- type RightDef
- type RightRule
- type Rule
- type RuleDef
- type Schema
- type SchemaDef
- type SchemaSet
- type States
- type StatesDef
- type Table
- type TableDef
- type Transition
- type TransitionDef
- type Trigger
- type Variable
- type VariableDef
Constants ¶
const ( // CodeBadJSON: the definition is not the JSON the class format expects. CodeBadJSON = "bad_json" // CodeMissing: a required element is absent or empty. CodeMissing = "missing" // CodeBadName: a name is not an identifier, or uses the reserved // separator or suffix. CodeBadName = "bad_name" // CodeReservedName: a name the generated tables use, or a keyword. CodeReservedName = "reserved_name" // CodeDuplicate: a name declared twice, in any case. CodeDuplicate = "duplicate" // CodeUnknownType: a type the type system does not have. CodeUnknownType = "unknown_type" // CodeUnknownSchema: an object or rows type names a schema that is not // defined. CodeUnknownSchema = "unknown_schema" // CodeSchemaCycle: a schema contains itself. CodeSchemaCycle = "schema_cycle" // CodeTooDeep: objects nest more than MaxObjectDepth deep. CodeTooDeep = "too_deep" // CodeNotAllowed: a property that this kind of variable, field or // element may not have. CodeNotAllowed = "not_allowed" // CodeBadFormula: a formula does not parse or bind; Pos says where. CodeBadFormula = "bad_formula" // CodeTypeMismatch: a formula's type is not the variable's. CodeTypeMismatch = "type_mismatch" // CodeNotACondition: a guard, rule condition or access rule is not // bool. CodeNotACondition = "not_a_condition" // CodeCycle: computed variables depend on each other in a loop. CodeCycle = "cycle" // CodeUnknownState, CodeUnknownVariable, CodeUnknownTransition: a // reference to a state, variable or transition the class lacks. CodeUnknownState = "unknown_state" CodeUnknownVariable = "unknown_variable" CodeUnknownTransition = "unknown_transition" // CodeBadTrigger: a trigger of a triggered variable is malformed. CodeBadTrigger = "bad_trigger" // CodeBadValue: an enum value, a range bound or a literal is wrong. CodeBadValue = "bad_value" // CodeTooManyColumns: a generated table would exceed MaxColumns. CodeTooManyColumns = "too_many_columns" // CodeNotSupported: a construct the format allows that the engine // does not implement yet. CodeNotSupported = "not_supported" )
The diagnostic codes. The list is a contract once the validate command ships (ADR-0025): a new code is added, never renamed.
const MaxColumns = 1000
MaxColumns is the most columns a generated table may hold (ADR-0031).
const MaxObjectDepth = 4
MaxObjectDepth is how deep objects may nest below a variable: a schema of scalars is one deep, a schema with an object field two (ADR-0031).
const PathSeparator = "__"
PathSeparator joins the parts of a field path in a column name (ADR-0031); it is reserved in every name.
Variables ¶
This section is empty.
Functions ¶
func Compile ¶
func Compile(def *Definition, schemas *SchemaSet) (*Class, Diagnostics)
Compile validates and compiles a definition against the schemas and no tables.
func CompileIn ¶
func CompileIn(def *Definition, env Env) (*Class, Diagnostics)
CompileIn validates a definition against the environment and compiles it. It reports every finding it can, not the first: a class with three wrong formulas earns three diagnostics.
func CompileTable ¶
func CompileTable(def *TableDef) (*Table, Diagnostics)
CompileTable checks a table definition and lays it out.
func Define ¶
func Define(data []byte, schemas *SchemaSet) (*Class, Diagnostics)
Define parses and compiles a class definition in one step, against the schemas and no tables.
func DefineIn ¶
func DefineIn(data []byte, env Env) (*Class, Diagnostics)
DefineIn parses and compiles a class definition against an environment.
func DefineTable ¶
func DefineTable(data []byte) (*Table, Diagnostics)
DefineTable parses and compiles a table definition in one step.
func Parse ¶
func Parse(data []byte) (*Definition, Diagnostics)
Parse decodes a class definition. Unknown properties are findings, so that a misspelt property never passes as an absent one.
func ParseSchema ¶
func ParseSchema(data []byte) (*SchemaDef, Diagnostics)
ParseSchema decodes a schema definition, keeping the field order.
func ParseTable ¶
func ParseTable(data []byte) (*TableDef, Diagnostics)
ParseTable decodes a table definition. Unknown properties are findings.
func VocabularyNames ¶
func VocabularyNames() []string
VocabularyNames lists the predefined schemas in their order.
Types ¶
type Access ¶
type Access struct {
Read, Create, Update, Delete *formula.Program
Transition map[string]*formula.Program
}
Access holds the compiled class-level access rules.
type AccessDef ¶
type AccessDef struct {
Read string `json:"read,omitempty"`
Create string `json:"create,omitempty"`
Update string `json:"update,omitempty"`
Delete string `json:"delete,omitempty"`
Transition map[string]string `json:"transition,omitempty"`
}
AccessDef holds the class-level access rules (ADR-0010).
type Change ¶
type Change struct {
Kind ChangeKind
// Name is the variable or the state the change is about, "" for the
// class as a whole.
Name string
// Path is the JSON pointer of the element in the new definition, or
// in the old one for a removal.
Path string
}
Change is one difference between two versions of a class.
type ChangeKind ¶
type ChangeKind string
ChangeKind is what a redefinition does to one element of a class (ADR-0039).
const ( // ChangeAddVariable: a variable the old version lacked. ChangeAddVariable ChangeKind = "add_variable" // ChangeRemoveVariable: a variable the new version lacks. ChangeRemoveVariable ChangeKind = "remove_variable" // ChangeRetypeVariable: the same variable with another type, scale or // shape. ChangeRetypeVariable ChangeKind = "retype_variable" // ChangeFormula: another formula, default, mode or triggers, or the // class title. ChangeFormula ChangeKind = "change_formula" // ChangeConstraints: another required, values, min, max, index or ref // class. ChangeConstraints ChangeKind = "change_constraints" // ChangeRemoveState: a state the new version lacks. ChangeRemoveState ChangeKind = "remove_state" // ChangeUnfinalState: a state that was terminal and is not. ChangeUnfinalState ChangeKind = "unfinal_state" // ChangeBehaviour: states added or made terminal, transitions, rules, // access, rights, or the header. ChangeBehaviour ChangeKind = "change_behaviour" )
The kinds of change. The store decides which are allowed against the documents it holds; the model only names them.
type ChildTable ¶
ChildTable is the per-version table of a composite variable (ADR-0014): the schema's columns, or value for an array, after doc_id, version and idx.
type Class ¶
type Class struct {
Name string
Version int
Label string
Plural string
Description string
Icon string
Color string
// Title is the compiled title formula, nil when TITLE is ID.
Title *formula.Program
// Variables in declaration order.
Variables []*Variable
// Order lists the auto computed variables, and "title" when there is
// a title formula, in an order where every one comes after what it
// reads: the full recalculation order of ADR-0015.
Order []string
// DefaultOrder lists the inputs with defaults in dependency order.
DefaultOrder []string
// Columns are the typed columns of the current and history tables
// after the system columns, in variable order; Children the child
// tables of composite variables.
Columns []Column
Children []ChildTable
// Schemas are the schemas the class uses, resolved at definition.
Schemas []*Schema
States *States
Transitions []*Transition
Rules []*Rule
Access *Access
// Rights is the rights table by state, then variable, "*" included
// (ADR-0028); nil when the class declares none.
Rights map[string]map[string]*Right
Def *Definition
// contains filtered or unexported fields
}
Class is a compiled class definition: every formula bound, every reference checked, the computed variables in evaluation order, and the variables laid out as the columns and child tables of ADR-0014.
func (*Class) ReadRule ¶ added in v0.3.0
ReadRule resolves the read right that governs a variable in a state (ADR-0028, ADR-0041): the cell of the named state and variable, then the state's "*", then the "*" state's cell of the variable, then its "*"; the first cell declaring a read rule decides. nil means the class rules alone apply and the variable is readable. A state of "" reads the "*" row alone.
type Column ¶
type Column struct {
// Name is the column name: the variable, a flattened field path, or a
// money column's currency twin.
Name string
Type formula.Type
// Variable is the variable the column belongs to; Path the dotted
// field path for an object leaf, the variable name for a scalar.
Variable string
Path string
Index bool
}
Column is one storage column of the current and history tables.
type ComputeMode ¶
type ComputeMode string
ComputeMode is how a computed variable recalculates (ADR-0015).
const ( ModeAuto ComputeMode = "auto" ModeTriggered ComputeMode = "triggered" )
The modes.
type Definition ¶
type Definition struct {
Name string `json:"name"`
Version int `json:"version,omitempty"`
Label string `json:"label,omitempty"`
Plural string `json:"plural,omitempty"`
Description string `json:"description,omitempty"`
Icon string `json:"icon,omitempty"`
Color string `json:"color,omitempty"`
// Title is a formula over pure functions and the document's own
// variables (ADR-0018); empty means TITLE equals ID.
Title string `json:"title,omitempty"`
Variables map[string]*VariableDef `json:"variables"`
States *StatesDef `json:"states,omitempty"`
Transitions []TransitionDef `json:"transitions,omitempty"`
Rules []RuleDef `json:"rules,omitempty"`
Access *AccessDef `json:"access,omitempty"`
Rights map[string]map[string]*RightDef `json:"rights,omitempty"`
// VariableOrder lists the variables in the order they were written.
VariableOrder []string `json:"-"`
// RightsOrder lists the states of the rights table, then per state its
// variables, in the order they were written.
RightsOrder map[string][]string `json:"-"`
// contains filtered or unexported fields
}
Definition is a class as written in JSON (docs/architecture.md). Maps keep JSON's lack of order, so the order of declaration, which decides column order and messages, is recorded apart in VariableOrder and RightsOrder by Parse.
type Diagnostic ¶
type Diagnostic struct {
// Code is a stable identifier of the kind of finding, one of the
// Code constants. A caller branches on it.
Code string `json:"code"`
// Path is the JSON pointer of the element the finding is about,
// such as /variables/total/formula or /transitions/1/guard.
Path string `json:"path"`
// Pos is the byte offset inside the formula at Path when the finding
// is about a place in a formula, and -1 otherwise.
Pos int `json:"pos"`
// Message says what is wrong, for a person.
Message string `json:"message"`
// Hint says what to write instead, when the engine knows.
Hint string `json:"hint,omitempty"`
}
Diagnostic is one definition-time finding.
func (Diagnostic) String ¶
func (d Diagnostic) String() string
type Diagnostics ¶
type Diagnostics []Diagnostic
Diagnostics is the list of findings of one definition. It is an error when it is not empty.
func (Diagnostics) Err ¶
func (ds Diagnostics) Err() error
Err returns the diagnostics as an error, or nil when there are none.
func (Diagnostics) Error ¶
func (ds Diagnostics) Error() string
func (Diagnostics) Has ¶
func (ds Diagnostics) Has(code string) bool
Has reports whether a finding with the code is in the list.
type Env ¶
Env is what a definition compiles against: the schemas its objects name and the explicit tables its formulas may read (ADR-0016). A nil Schemas is the vocabulary alone; nil Sources are none.
type Leaf ¶
type Leaf struct {
// Path is the dotted field path from the variable, "shipping.city",
// which is also the slot name the binder gives it.
Path string
// Column is the column name, the path joined with the separator.
Column string
Type formula.Type
}
Leaf is one scalar column an object flattens to (ADR-0031).
type Presentation ¶
Presentation is a compiled presentation block.
type PresentationDef ¶
type PresentationDef struct {
Title string `json:"title,omitempty"`
Subtitle string `json:"subtitle,omitempty"`
Avatar string `json:"avatar,omitempty"`
Icon string `json:"icon,omitempty"`
Color string `json:"color,omitempty"`
}
PresentationDef says how a frontend shows an object of the schema (ADR-0032): Title and Subtitle are formulas over the fields, pure functions only; Avatar names a text field holding an image URL or a file hash; Icon and Color are as in the class header.
type Right ¶
type Right struct {
Read, Write *RightRule
}
Right is one cell of the rights table: a formula, or a list of groups meaning INGROUP of any of them. A nil Right in a cell means the rule was not declared and the class-level rules alone apply.
type RightDef ¶
type RightDef struct {
Read json.RawMessage `json:"read,omitempty"`
Write json.RawMessage `json:"write,omitempty"`
}
RightDef is one cell of the rights table (ADR-0028): a formula as text or a list of group names, for reading and for writing.
type RightRule ¶
RightRule is a formula or a group list; Src is the rule as written, for the hint of a refusal.
type Rule ¶
type Rule struct {
On string
State string
Name string
Variables []string
If *formula.Program
Actions []json.RawMessage
}
Rule is one compiled rule; its actions are kept as written until Phase 4 gives them their meaning.
type RuleDef ¶
type RuleDef struct {
On string `json:"on"`
State string `json:"state,omitempty"`
Name string `json:"name,omitempty"`
Variables []string `json:"variables,omitempty"`
If string `json:"if,omitempty"`
Do []json.RawMessage `json:"do"`
}
RuleDef is one event-condition-action rule (ADR-0009). The actions are kept as written; Phase 4 gives them their meaning.
type Schema ¶
type Schema struct {
Name string
// Version counts the definitions of a user schema; a predefined one
// is versioned with the engine.
Version int
Predefined bool
Extends string
// Type is the object type, fields in order, base fields first.
Type formula.Type
// Depth is 1 for a schema of scalars and one more per level of
// object fields.
Depth int
Presentation *Presentation
Def *SchemaDef
}
Schema is a resolved schema: its object type with every field's type in place, how deep it nests, and its compiled presentation.
type SchemaDef ¶
type SchemaDef struct {
Name string `json:"name"`
Extends string `json:"extends,omitempty"`
Fields map[string]string `json:"fields"`
Presentation *PresentationDef `json:"presentation,omitempty"`
// FieldOrder lists the fields in the order written; ParseSchema fills
// it, and a caller building a SchemaDef in code may.
FieldOrder []string `json:"-"`
}
SchemaDef is a schema as written: a named list of fields, each a scalar type other than json or object<Name> of another schema, with an optional base to extend and a presentation block (ADR-0031, ADR-0032).
type SchemaSet ¶
type SchemaSet struct {
// contains filtered or unexported fields
}
SchemaSet holds the schemas a database knows: the vocabulary and the user's. Names are unique in any case.
func NewSchemaSet ¶
func NewSchemaSet() *SchemaSet
NewSchemaSet makes a set holding the predefined vocabulary.
func (*SchemaSet) Define ¶
func (s *SchemaSet) Define(def *SchemaDef) (*Schema, Diagnostics)
Define adds a user schema, or a new version of one. A predefined name is refused. The schema is resolved when it is defined: a later change to a schema it extends or embeds does not reach it until it is defined again (ADR-0031, ADR-0032).
type States ¶
States is the compiled states block.
type StatesDef ¶
type StatesDef struct {
Initial string `json:"initial"`
List []string `json:"list"`
Final []string `json:"final,omitempty"`
}
StatesDef is the statechart's states (ADR-0008).
type Table ¶
type Table struct {
Name string
Version int
Label string
Description string
Binding string
// Fields are the logical columns in order; Columns the storage
// columns, a money field as two.
Fields []formula.Field
Columns []Column
Key []string
Indexes [][]string
Def *TableDef
}
Table is a compiled table definition.
type TableDef ¶
type TableDef struct {
Name string `json:"name"`
Version int `json:"version,omitempty"`
Label string `json:"label,omitempty"`
Description string `json:"description,omitempty"`
// Columns maps a column name to its type: a scalar type other than
// object; money is stored as two columns.
Columns map[string]string `json:"columns"`
// Key lists the columns that identify a row and order the table; a
// LOOKUP returns the first matching row in this order (ADR-0020).
Key []string `json:"key"`
// Indexes lists further column sets to index.
Indexes [][]string `json:"indexes,omitempty"`
// Binding is sqlite (the default), duckdb or external (ADR-0016).
Binding string `json:"binding,omitempty"`
// ColumnOrder lists the columns in the order written.
ColumnOrder []string `json:"-"`
}
TableDef is an explicit table as written (ADR-0016, ADR-0037): a name, its columns by scalar type, the key columns that order it and identify a row, optional secondary indexes, and the storage binding its rows live in.
type Transition ¶
type Transition struct {
Name string
From []string
To string
Guard *formula.Program
// GuardSrc is the guard as written, for the hint of a refusal.
GuardSrc string
}
Transition is one compiled transition; Guard is nil when there is none.
type TransitionDef ¶
type TransitionDef struct {
Name string `json:"name,omitempty"`
From json.RawMessage `json:"from"`
To string `json:"to"`
Guard string `json:"guard,omitempty"`
}
TransitionDef is one transition. From is one state as text or a list of states. A transition without a name is eventless and needs a guard.
type Trigger ¶
Trigger is one trigger of a triggered variable: refresh, enter:<state>, exit:<state>, transition:<name>, table:<name> or schedule:<spec>.
type Variable ¶
type Variable struct {
Name string
// Computed is true for a variable with a formula, false for an input.
Computed bool
Type formula.Type
// RefClass is the class a ref variable points at.
RefClass string
Required bool
// Default is the compiled default of an input, nil when none.
Default *formula.Program
// Formula and Mode belong to a computed variable; Triggers to a
// triggered one.
Formula *formula.Program
Mode ComputeMode
Triggers []Trigger
// Values is the enum list of a text variable (ADR-0023).
Values []string
// Min and Max bound a numeric variable (ADR-0034); HasMin and HasMax
// say which are set.
Min, Max formula.Value
HasMin, HasMax bool
Index bool
// Deps are the variables the formula or default reads, by declared
// name, an object by its variable name whichever leaf was read.
Deps []string
// Sources are the explicit tables the formula or default reads
// through LOOKUP, by name.
Sources []string
Def *VariableDef
}
Variable is one compiled variable.
type VariableDef ¶
type VariableDef struct {
// Type is the type as written: a scalar name, int, decimal(s),
// money(s), array<scalar>, object or rows. decimal and money without
// a scale take Scale, or the default of two places.
Type string `json:"type"`
Scale *int `json:"scale,omitempty"`
// Class names the class a ref points at.
Class string `json:"class,omitempty"`
// Schema is the schema of an object or rows variable: a schema name
// as text, or for rows an inline object of column name to type.
Schema json.RawMessage `json:"schema,omitempty"`
// Input variables.
Required bool `json:"required,omitempty"`
Default string `json:"default,omitempty"`
// Computed variables (ADR-0015).
Formula string `json:"formula,omitempty"`
Mode string `json:"mode,omitempty"`
On []string `json:"on,omitempty"`
// Values makes a text variable an enum (ADR-0023).
Values []string `json:"values,omitempty"`
// Min and Max bound a numeric variable (ADR-0034), as literals of its
// type: a number, or text for an exact value.
Min json.RawMessage `json:"min,omitempty"`
Max json.RawMessage `json:"max,omitempty"`
// Index asks for a B-tree index on the column.
Index bool `json:"index,omitempty"`
// contains filtered or unexported fields
}
VariableDef is one variable as written.