GizStack
View .mdOpen in ChatGPTOpen in Claude

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.