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).
import * as Model from "gizdb:model";Types
Table
type Table = { name: string; }Stores the record in the table of this name (a lower-case SQL name).
name:string
Key
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
type Index = { name: string; }The field belongs to the named index, whose columns are its fields in order.
name:string
Unique
type Unique = { name: string; }The field belongs to the named unique constraint.
name:string
References
type References = { table: string; column: string; onDelete: string; }The stored field references this table and column.
table:stringcolumn:stringonDelete:string
MaxLength
type MaxLength = { value: i64; }The most Unicode characters a text may contain.
value:i64
Pattern
type Pattern = { value: string; }The whole text must match this regular expression.
value:string
Values
type Values = { list: string; }Comma-separated allowed strings. Annotation arguments are scalar literals.
list:string
Column
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
type Label = { text: string; }What people see the field as.
text:string
Min
type Min = { value: i64; }A text's fewest characters, or an integer's least value.
value:i64
Max
type Max = { value: i64; }A text's most characters, or an integer's greatest value.
value:i64
Hidden
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
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:stringmaxBytes:i64multiple:bool
Multiline
type Multiline = {}A text field written over several lines.
Opaque: create and use it through this module's functions.
Trim
type Trim = {}Leading and trailing white space is not part of the value.
Opaque: create and use it through this module's functions.
Submit
type Submit = { text: string; }The label of the record's form button.
text:string
Access
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:stringwrite:string
Read
type Read = { role: string; }On a field: the least role that sees it.
role:string
Write
type Write = { role: string; }On a field: the least role that writes it.
role:string
Within
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
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
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
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:stringcolumn:stringonDelete:string
Field
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:stringcolumn:stringcontract:M54.Contractkey:boolunique:_gizlang_sdk_core.Option<string>index:_gizlang_sdk_core.Option<string>references:_gizlang_sdk_core.Option<M48.Reference>values:Vec<string>hidden:boolmultiline:booltrim:boollabel:stringdoc:stringmin:_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:stringwriteRole:stringwithin:boolcomputed:_gizlang_sdk_core.Option<string>display:boolpath:Vec<i64>accept:_gizlang_sdk_core.Option<string>maxBytes:i64multiple:bool
Shape
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:stringtable:_gizlang_sdk_core.Option<string>doc:stringsubmit:stringhash:stringfields:Vec<M48.Field>read:stringwrite:string
Handler
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:stringid:stringdoc:stringinput:M48.Shape
Rejection
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:i64field:_gizlang_sdk_core.Option<string>message:stringproblems:Vec<M48.Problem>cause:_gizlang_sdk_core.Option<M56.Diagnostic>
Problem
type Problem = { field: string; message: string; }A problem of one field: its name and what is wrong.
field:stringmessage:string
Outcome
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).
donerejectedunknown
Action
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
type Row = Vec<Option<string>>A stored row: each column as text, none for NULL.
Fields
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
interface Failure { rejection(self: Self): Rejection; }A data failure: an SQL store's or GizDB's.
rejection
Functions
invalid
function invalid(field: string, message: string): RejectionA rejection (422) of the value of FIELD, with MESSAGE.
Effects: fail.
rejection
function rejection(status: i64, message: string): RejectionA rejection of the input as a whole.
diagnosed
function diagnosed(status: i64, d: Diagnostic): RejectionA rejection from a database failure: the field and message of diagnostic D, and D as its cause.
Effects: fail.
forbidden
function forbidden(message: string): RejectionA rejection (403): the actor may not do this.
missing
function missing(message: string): RejectionA rejection (404): the record is not there.
unauthenticated
function unauthenticated(): RejectionA rejection (401): the request has no signed-in actor.
stored
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
function noFields(): FieldsNo fields.
formFields
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
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
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
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
function values(shape: Shape, row: Row): Vec<Value>Decode stored wire cells under the same declared contracts, without form constraints.
Effects: fail.
wireValue
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
function encFlag(v: bool): Option<string>The text of a flag in a store row: "1" or "0".
decInteger
function decInteger(row: Row, i: i64): i64A scalar SQL result at the store wire boundary.
Effects: fail.
slotField
function slotField(slot: Typed.Slot): FieldA field with no declaration annotations: a query result slot, or a form or tool input that no Shape declares.
plainField
function plainField(name: string, scalar: string, nullable: bool, doc: string): FieldAn undeclared input of a Gizlang scalar type ("string", "i64", "bool", ...). An unknown scalar name is a programming error.
Effects: fail.
display
function display(field: Field, value: Value): stringExact, human-readable values. Temporal storage uses microseconds.
Effects: fail.
sqlType
function sqlType(f: Field, dialect: SqlDialect): stringThe SQL column type of F in DIALECT.
Effects: fail.
tableOf
function tableOf(shape: Shape): stringThe table of SHAPE.
Effects: fail.
columns
function columns(shape: Shape): stringThe stored columns in field order (a computed field has none).
Effects: fail.
insertRowsSql
function insertRowsSql(shape: Shape, n: i64): stringINSERT of n whole rows, parameters $1.. row by row in field order.
Effects: fail.
schema
function schema(shape: Shape, dialect: SqlDialect): Schema.TableThe 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
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
function json(shape: Shape, row: Vec<Option<string>>): bytesA 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
function tools(actions: Vec<Handler>): bytesThe 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
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
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
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
function actionId(name: string, input: Shape, output: Shape): stringThe id of the action name from the shapes of its input and output: the same while both meanings are.
Effects: fail.
valuesOf
function valuesOf<T>(shape: Shape, v: T): Vec<Value>The values of the record V, one per field of its Shape.
rowOf
function rowOf<T>(shape: Shape, v: T): RowThe record V as a stored row.
valueOf
function valueOf<T>(shape: Shape, row: Vec<Value>): TThe record of type T that values (one per field of its Shape, as read and values give them) make.
rowReader
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
function shape<T>(): ShapeThe Shape of the record type T; a declaration the Shape cannot hold is a defect of the program, reported with its message.
action
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
function handlers<C>(actions: Vec<Action<C>>): Vec<Handler>The actions as handlers: forms and agent tools.
dispatch
function dispatch<C>(actions: Vec<Action<C>>, context: C, id: string, bare: bool, fields: Fields): OutcomeRuns the action id names ("name.hash"; a bare name when bare, as an agent calls a tool) with checked inputs.
Methods
DbError.rejection
function DbError.rejection(self: DbError): RejectionThe error as a rejection: a database error is a defect (500), with its diagnostic.
Effects: fail.
Fields.get
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
function Fields.with(self: Fields, name: string, value: string): FieldsThe fields with NAME set to VALUE.
Effects: fail.
Fields.isNull
function Fields.isNull(self: Fields, name: string): boolWhether the field NAME is NULL.
Effects: fail.
Fields.present
function Fields.present(self: Fields, name: string): boolWhether the field NAME has a value or is NULL.
Effects: fail.
Field.required
function Field.required(self: Field): boolWhether a required field may be empty: only a text whose minimum is 0.