# gizdb:model

a record type's meaning as a value (a Shape), and what is derived from it besides HTML: typed input validation, SQL wire rows, DDL for SQLite and PostgreSQL, additive migration, JSON and agent tool schemas. A Shape comes from the record type's declaration, docs and annotations at run time (`shapeOf`), so the declaration stays the one source; so do a record's rows (`rowOf`, `valueOf`) and the actions' table (`action`, `handlers`, `dispatch`).

```gizlang
import * as Model from "gizdb:model";
```

## Types

### `Table`

```gizlang
type Table = { name: string; }
```

Stores the record in the table of this name (a lower-case SQL name).

- `name`: `string`

### `Key`

```gizlang
type Key = {}
```

The field is the primary key, or part of it with the other key fields.

Opaque: create and use it through this module's functions.

### `Index`

```gizlang
type Index = { name: string; }
```

The field belongs to the named index, whose columns are its fields in order.

- `name`: `string`

### `Unique`

```gizlang
type Unique = { name: string; }
```

The field belongs to the named unique constraint.

- `name`: `string`

### `References`

```gizlang
type References = { table: string; column: string; onDelete: string; }
```

The stored field references this table and column.

- `table`: `string`
- `column`: `string`
- `onDelete`: `string`

### `MaxLength`

```gizlang
type MaxLength = { value: i64; }
```

The most Unicode characters a text may contain.

- `value`: `i64`

### `Pattern`

```gizlang
type Pattern = { value: string; }
```

The whole text must match this regular expression.

- `value`: `string`

### `Values`

```gizlang
type Values = { list: string; }
```

Comma-separated allowed strings. Annotation arguments are scalar literals.

- `list`: `string`

### `Column`

```gizlang
type Column = { name: string; }
```

The field's stored column, when it is not the field's name: renaming a
field then never renames or drops its column.

- `name`: `string`

### `Label`

```gizlang
type Label = { text: string; }
```

What people see the field as.

- `text`: `string`

### `Min`

```gizlang
type Min = { value: i64; }
```

A text's fewest characters, or an integer's least value.

- `value`: `i64`

### `Max`

```gizlang
type Max = { value: i64; }
```

A text's most characters, or an integer's greatest value.

- `value`: `i64`

### `Hidden`

```gizlang
type Hidden = {}
```

The field travels in forms without being shown (a target, a parent).

Opaque: create and use it through this module's functions.

### `File`

```gizlang
type File = { accept: string; maxBytes: i64; multiple: bool; }
```

A text field holds a file: its form control is a file input for the media types in `accept` (as the HTML attribute: `image/png,.pdf`; empty
for any), each file at most `maxBytes` bytes (0: the server's limit). The field's value is the file's name; the bytes come with `Web.uploads`.
With `multiple` the field takes several files and its value is the JSON list of their names.

- `accept`: `string`
- `maxBytes`: `i64`
- `multiple`: `bool`

### `Multiline`

```gizlang
type Multiline = {}
```

A text field written over several lines.

Opaque: create and use it through this module's functions.

### `Trim`

```gizlang
type Trim = {}
```

Leading and trailing white space is not part of the value.

Opaque: create and use it through this module's functions.

### `Submit`

```gizlang
type Submit = { text: string; }
```

The label of the record's form button.

- `text`: `string`

### `Access`

```gizlang
type Access = { read: string; write: string; }
```

The least role that reads the rows of the record and the least that writes them (default: viewer and editor).

- `read`: `string`
- `write`: `string`

### `Read`

```gizlang
type Read = { role: string; }
```

On a field: the least role that sees it.

- `role`: `string`

### `Write`

```gizlang
type Write = { role: string; }
```

On a field: the least role that writes it.

- `role`: `string`

### `Within`

```gizlang
type Within = {}
```

On a field that references another record: that record is the parent of this one, and grants on a parent reach it.

Opaque: create and use it through this module's functions.

### `Computed`

```gizlang
type Computed = { sql: string; }
```

On a field: the SQL expression over the record's columns that gives its value. It is read, never stored or written.

- `sql`: `string`

### `Display`

```gizlang
type Display = {}
```

On a field: the record is shown as this field in lists and in the choices of a reference.

Opaque: create and use it through this module's functions.

### `Reference`

```gizlang
type Reference = { table: string; column: string; onDelete: string; }
```

A field that refers to a record of TABLE by its COLUMN, and what a delete of that record does (ON DELETE).

- `table`: `string`
- `column`: `string`
- `onDelete`: `string`

### `Field`

```gizlang
type Field = { name: string; column: string; contract: Typed.Contract; key: bool; unique: Option<string>; index: Option<string>; references: Option<Reference>; values: Vec<string>; hidden: bool; multiline: bool; trim: bool; label: string; doc: string; min: Option<i64>; max: Option<i64>; maxLength: Option<i64>; pattern: Option<string>; was: Vec<string>; readRole: string; writeRole: string; within: bool; computed: Option<string>; display: bool; path: Vec<i64>; accept: Option<string>; maxBytes: i64; multiple: bool; }
```

One field contract owns storage, validation and presentation.

- `name`: `string`
- `column`: `string`
- `contract`: `M54.Contract`
- `key`: `bool`
- `unique`: `_gizlang_sdk_core.Option<string>`
- `index`: `_gizlang_sdk_core.Option<string>`
- `references`: `_gizlang_sdk_core.Option<M48.Reference>`
- `values`: `Vec<string>`
- `hidden`: `bool`
- `multiline`: `bool`
- `trim`: `bool`
- `label`: `string`
- `doc`: `string`
- `min`: `_gizlang_sdk_core.Option<i64>`
- `max`: `_gizlang_sdk_core.Option<i64>`
- `maxLength`: `_gizlang_sdk_core.Option<i64>`
- `pattern`: `_gizlang_sdk_core.Option<string>`
- `was`: `Vec<string>`
- `readRole`: `string`
- `writeRole`: `string`
- `within`: `bool`
- `computed`: `_gizlang_sdk_core.Option<string>`
- `display`: `bool`
- `path`: `Vec<i64>`
- `accept`: `_gizlang_sdk_core.Option<string>`
- `maxBytes`: `i64`
- `multiple`: `bool`

### `Shape`

```gizlang
type Shape = { name: string; table: Option<string>; doc: string; submit: string; hash: string; fields: Vec<Field>; read: string; write: string; }
```

A record type, stored in `table` or not stored (an action's input). `hash`
is the meaning hash of its fields, so a handler id names the input it was
rendered for. `submit` is its form's button. `read` and `write` are the least roles that read and write its rows.

- `name`: `string`
- `table`: `_gizlang_sdk_core.Option<string>`
- `doc`: `string`
- `submit`: `string`
- `hash`: `string`
- `fields`: `Vec<M48.Field>`
- `read`: `string`
- `write`: `string`

### `Handler`

```gizlang
type Handler = { name: string; id: string; doc: string; input: Shape; }
```

A function a person, a page or an agent calls by its id, "name.hash".

- `name`: `string`
- `id`: `string`
- `doc`: `string`
- `input`: `M48.Shape`

### `Rejection`

```gizlang
type Rejection = { status: i64; field: Option<string>; message: string; problems: Vec<Problem>; cause: Option<Diagnostic>; }
```

A rejection, the one error answer of GizWeb: the HTTP status it answers with, the field it is about (none for the
input as a whole), a message for the person, every field problem of the input (the first is `field` and
`message`), and for a database failure its diagnostic, the machine-readable cause.

- `status`: `i64`
- `field`: `_gizlang_sdk_core.Option<string>`
- `message`: `string`
- `problems`: `Vec<M48.Problem>`
- `cause`: `_gizlang_sdk_core.Option<M56.Diagnostic>`

### `Problem`

```gizlang
type Problem = { field: string; message: string; }
```

A problem of one field: its name and what is wrong.

- `field`: `string`
- `message`: `string`

### `Outcome`

```gizlang
type Outcome = | { kind: "done"; json: bytes; } | { kind: "rejected"; rejection: Rejection; } | { kind: "unknown"; }
```

What calling an action gave: its result as JSON, a rejection, or no action
with that id (the page was rendered by other code, so it reloads).

- `done`
- `rejected`
- `unknown`

### `Action`

```gizlang
type Action<C> = { handler: Handler; run: (context: C, values: Vec<Value>) => Outcome; }
```

An action: people (its form), pages (data-a) and agents (a tool) call it by its handler id. It takes the app's context
and one input record and gives a record or a Rejection; `run` takes the input as the values `read` checked.

Opaque: create and use it through this module's functions.

### `Row`

```gizlang
type Row = Vec<Option<string>>
```

A stored row: each column as text, none for NULL.

### `Fields`

```gizlang
type Fields = { names: Vec<string>; values: Vec<string>; nulls: Vec<string>; }
```

Named text inputs, from a form or a JSON object.

- `names`: `Vec<string>`
- `values`: `Vec<string>`
- `nulls`: `Vec<string>`

### `Failure`

```gizlang
interface Failure { rejection(self: Self): Rejection; }
```

A data failure: an SQL store's or GizDB's.

- `rejection`

## Functions

### `invalid`

```gizlang
function invalid(field: string, message: string): Rejection
```

A rejection (422) of the value of FIELD, with MESSAGE.

Effects: fail.

### `rejection`

```gizlang
function rejection(status: i64, message: string): Rejection
```

A rejection of the input as a whole.

### `diagnosed`

```gizlang
function diagnosed(status: i64, d: Diagnostic): Rejection
```

A rejection from a database failure: the field and message of diagnostic D, and D as its cause.

Effects: fail.

### `forbidden`

```gizlang
function forbidden(message: string): Rejection
```

A rejection (403): the actor may not do this.

### `missing`

```gizlang
function missing(message: string): Rejection
```

A rejection (404): the record is not there.

### `unauthenticated`

```gizlang
function unauthenticated(): Rejection
```

A rejection (401): the request has no signed-in actor.

### `stored`

```gizlang
function stored<T, E extends Failure>(result: Result<T, E>): Result<T, Rejection>
```

A data result as an action's: a store or GizDB failure is a defect (500), not the caller's mistake.

### `noFields`

```gizlang
function noFields(): Fields
```

No fields.

### `formFields`

```gizlang
function formFields(body: string): Result<Fields, Rejection>
```

A form body (application/x-www-form-urlencoded) as fields: one value per
decoded name. Malformed or excess input and duplicate names fail before any
action sees a partial input.

Effects: fail.

### `jsonFields`

```gizlang
function jsonFields(text: string): Result<Fields, Rejection>
```

JSON numbers retain their validated source token, including exact i64/u64.
Explicit NULL is separate from omission. Duplicate decoded names are rejected.

Effects: fail.

### `read`

```gizlang
function read(shape: Shape, input: Fields): Result<Vec<Value>, Rejection>
```

The input checked against the shape, as a row the shape's typed decoder
reads without failing: required values present, texts within their
character bounds, integers and numbers well formed and within range,
booleans as 1 or 0 (absent is false, as an unchecked checkbox).
A rejection lists the problem of every field that fails, in shape order.

Effects: fail.

### `readField`

```gizlang
function readField(f: Field, wire: string): Result<Value, Rejection>
```

The value of ONE field from its wire text, checked as `read` checks it (required, bounds, pattern, allowed values).

Effects: fail.

### `values`

```gizlang
function values(shape: Shape, row: Row): Vec<Value>
```

Decode stored wire cells under the same declared contracts, without form constraints.

Effects: fail.

### `wireValue`

```gizlang
function wireValue(field: Field, value: Value): Option<string>
```

A field value as a Row cell: the text a form, the JSON and the admin console carry (a blob in base64, a time in ISO 8601). A SQL store takes its parameters from sql/types textParameter.

Effects: fail.

### `encFlag`

```gizlang
function encFlag(v: bool): Option<string>
```

The text of a flag in a store row: "1" or "0".

### `decInteger`

```gizlang
function decInteger(row: Row, i: i64): i64
```

A scalar SQL result at the store wire boundary.

Effects: fail.

### `slotField`

```gizlang
function slotField(slot: Typed.Slot): Field
```

A field with no declaration annotations: a query result slot, or a
form or tool input that no Shape declares.

### `plainField`

```gizlang
function plainField(name: string, scalar: string, nullable: bool, doc: string): Field
```

An undeclared input of a Gizlang scalar type ("string", "i64", "bool", ...).
An unknown scalar name is a programming error.

Effects: fail.

### `display`

```gizlang
function display(field: Field, value: Value): string
```

Exact, human-readable values. Temporal storage uses microseconds.

Effects: fail.

### `sqlType`

```gizlang
function sqlType(f: Field, dialect: SqlDialect): string
```

The SQL column type of F in DIALECT.

Effects: fail.

### `tableOf`

```gizlang
function tableOf(shape: Shape): string
```

The table of SHAPE.

Effects: fail.

### `columns`

```gizlang
function columns(shape: Shape): string
```

The stored columns in field order (a computed field has none).

Effects: fail.

### `insertRowsSql`

```gizlang
function insertRowsSql(shape: Shape, n: i64): string
```

INSERT of `n` whole rows, parameters $1.. row by row in field order.

Effects: fail.

### `schema`

```gizlang
function schema(shape: Shape, dialect: SqlDialect): Schema.Table
```

The checked schema of a shape's table: columns in field order, the key, each
Unique group (named TABLE_NAME), each References column (TABLE_COLUMN_fkey)
and each named index. Each index ends with the key, so rows equal on the index
come in key order (ORDER BY created, id reads the index and sorts nothing).

Effects: fail.

### `ddl`

```gizlang
function ddl(shape: Shape, dialect: SqlDialect): Vec<string>
```

CREATE TABLE (with its unique and foreign keys), then CREATE INDEX for each
named index; all idempotent. A table made before a constraint was declared
keeps its columns and does not get it. A
keyed SQLite table is WITHOUT ROWID: the key is the table's one b-tree,
instead of a rowid table and a second b-tree for the key.

Effects: fail, read, write, console, io.

### `json`

```gizlang
function json(shape: Shape, row: Vec<Option<string>>): bytes
```

A row as a JSON object keyed by field name. An integer beyond 2^53 - 1 is a
string, so a browser reads it exactly; decimals are strings.

Effects: fail.

### `tools`

```gizlang
function tools(actions: Vec<Handler>): bytes
```

The actions as agent tools: name, description and a JSON Schema of the
input, from the same Shape the form and the validator use.

Effects: fail.

### `select`

```gizlang
function select<P, R>(shape: Shape, filter: string, parameters: Vec<Typed.Slot>, encode: (input: P) => Result<Vec<Value>, DbError> effects { fail }, of: (row: Vec<Value>) => R effects { fail }): Result<Query.Prepared<P, R>, DbError>
```

A typed query of a stored Shape's records, in key order: one DAL query that any data source
runs. `filter` is SQL over the columns with `$1`, `$2`... for `parameters`; `of` makes a record.

### `selectAs`

```gizlang
function selectAs<P, R>(shape: Shape, masks: Vec<string>, filter: string, tail: string, parameters: Vec<Typed.Slot>, encode: (input: P) => Result<Vec<Value>, DbError> effects { fail }, of: (row: Vec<Value>) => R effects { fail }): Result<Query.Prepared<P, R>, DbError>
```

The query of `select` over some rows and fields: the fields with a mask (a SQL condition) come as NULL where it is not true (they are nullable in the result), and `tail`
(an ORDER BY, LIMIT or OFFSET that the caller made from checked names and numbers) replaces the order by key.

### `shapeOf`

```gizlang
function shapeOf<T>(): Result<Shape, string>
```

The Shape of the record type T, from its declaration, docs and annotations: the one source of its storage, validation,
forms and tools. A declaration the Shape cannot hold gives its message. Reading the declaration takes work, so a
program makes a Shape once and keeps it.

### `actionId`

```gizlang
function actionId(name: string, input: Shape, output: Shape): string
```

The id of the action `name` from the shapes of its input and output: the same while both meanings are.

Effects: fail.

### `valuesOf`

```gizlang
function valuesOf<T>(shape: Shape, v: T): Vec<Value>
```

The values of the record V, one per field of its Shape.

### `rowOf`

```gizlang
function rowOf<T>(shape: Shape, v: T): Row
```

The record V as a stored row.

### `valueOf`

```gizlang
function valueOf<T>(shape: Shape, row: Vec<Value>): T
```

The record of type T that values (one per field of its Shape, as `read` and `values` give them) make.

### `rowReader`

```gizlang
function rowReader<T>(shape: Shape): (row: Vec<Value>) => T effects { fail }
```

`valueOf<T>` for a Shape as the row reader that Data.find, Data.one and the queries of a Shape take.

### `shape`

```gizlang
function shape<T>(): Shape
```

The Shape of the record type T; a declaration the Shape cannot hold is a defect of the program, reported with its message.

### `action`

```gizlang
function action<C, I, O>(name: string, doc: string, run: (context: C, input: I) => Result<O, Rejection>): Action<C>
```

The action `name`: a function of the app's context and an input record I that gives a record O or a Rejection.
The input arrives checked against I's Shape; the output is answered as JSON by O's Shape.

### `handlers`

```gizlang
function handlers<C>(actions: Vec<Action<C>>): Vec<Handler>
```

The actions as handlers: forms and agent tools.

### `dispatch`

```gizlang
function dispatch<C>(actions: Vec<Action<C>>, context: C, id: string, bare: bool, fields: Fields): Outcome
```

Runs the action `id` names ("name.hash"; a bare name when `bare`, as an agent calls a tool) with checked inputs.

## Methods

### `DbError.rejection`

```gizlang
function DbError.rejection(self: DbError): Rejection
```

The error as a rejection: a database error is a defect (500), with its diagnostic.

Effects: fail.

### `Fields.get`

```gizlang
function Fields.get(self: Fields, name: string): Option<string>
```

The value of the field NAME, or none when it is absent or NULL.

Effects: fail.

### `Fields.with`

```gizlang
function Fields.with(self: Fields, name: string, value: string): Fields
```

The fields with NAME set to VALUE.

Effects: fail.

### `Fields.isNull`

```gizlang
function Fields.isNull(self: Fields, name: string): bool
```

Whether the field NAME is NULL.

Effects: fail.

### `Fields.present`

```gizlang
function Fields.present(self: Fields, name: string): bool
```

Whether the field NAME has a value or is NULL.

Effects: fail.

### `Field.required`

```gizlang
function Field.required(self: Field): bool
```

Whether a required field may be empty: only a text whose minimum is 0.

