AppSpring Docs

Types (TypeDecl)

Generated from the doc schema (CatalogDocSchema, @canonify/kernel-catalog/doc): each field’s type, default and description are the schema’s own, and each example is a bundle file that readBundle decodes. A field’s Example is its value in one of those examples.

TypeDecl

A type of record.

The types slot of the doc holds these, keyed by id. In a bundle each is one file, types/<name>.json, named by its name, which the file then leaves out.

Field Type Required Default Example Description
id TypeId yes (propose assigns it; a new declaration leaves it out) — "ty_7k2m9q4z1a" A type id (ty_…); renames keep it.
name Ident yes — "customer" The type name.
label Text yes (a draft may leave it out: propose writes a default made from the name, catalog.label_defaulted) — "Customer" The words shown for it.
idPrefix string (matching ^[a-z]{2,5}$) no — "bk" The prefix of its record ids: 2–5 lower-case letters.
class "data" | "access" | "credential" | "evidence" | "queue" no "data" "data" What the rows are: data. The other classes are the platform’s own, and a doc declaring one is refused (C34).
verbs TypeDecl.verbs no {} (see the example) Which generated verbs exist (runtime §4.4); default all.
properties PropertyDecl[] yes — (see the example) The properties, in their default field order.
keys TypeDecl.keys no — (see the example) The keys of the type.
temporal TypeDecl.temporal no — (see the example) Rows are effective-dated; compiles to a no_overlap invariant.
invariants InvariantDecl[] no — (see the example) The rules every write must keep.
owner PropId no — "pr_2d4f6h8k0m" The required cascade ref to the row this row belongs to.
title TitleDecl no — "name" A row’s title: pickers, ref display and the title search source.
measures Record<Ident, MeasureDecl> no — {"count":{"label":"Bookings","expr":"count()"}} The declared aggregates, by name (C79).
presentation TypePresentation no — (see the example) How the type is shown (pages).

types/customer.json

{
  "label": "Customer",
  "properties": [
    {
      "kind": "stored",
      "name": "name",
      "label": "Name",
      "type": { "t": "text" },
      "required": true
    }
  ],
  "title": "name"
}

types/booking.json

{
  "label": "Booking",
  "idPrefix": "bk",
  "class": "data",
  "verbs": { "delete": false, "end": true },
  "properties": [
    {
      "kind": "stored",
      "id": "pr_1c3e5g7j9m",
      "name": "room",
      "label": "Room",
      "type": { "t": "text" },
      "required": true
    },
    {
      "kind": "stored",
      "id": "pr_3a5c7e9g1j",
      "name": "starts",
      "label": "Starts",
      "type": { "t": "date" },
      "required": true
    },
    {
      "kind": "stored",
      "id": "pr_9t1v3x5z7b",
      "name": "ends",
      "label": "Ends",
      "type": { "t": "date" },
      "required": true
    },
    {
      "kind": "ref",
      "id": "pr_2d4f6h8k0m",
      "name": "customer",
      "label": "Customer",
      "target": "ty_7k2m9q4z1a",
      "required": true,
      "onDelete": "cascade"
    }
  ],
  "keys": {
    "natural": ["pr_1c3e5g7j9m"],
    "unique": [["pr_1c3e5g7j9m", "pr_3a5c7e9g1j"]]
  },
  "temporal": {
    "from": "pr_3a5c7e9g1j",
    "to": "pr_9t1v3x5z7b",
    "key": ["pr_1c3e5g7j9m"]
  },
  "invariants": [
    {
      "kind": "check",
      "holds": "ends >= starts",
      "message": { "text": "A booking cannot end before it starts." }
    }
  ],
  "owner": "pr_2d4f6h8k0m",
  "title": {
    "text": "Room {room} from {starts}",
    "params": { "room": "room", "starts": "starts" }
  },
  "measures": { "count": { "label": "Bookings", "expr": "count()" } }
}

types/audit_note.json

{
  "label": "Audit note",
  "verbs": {
    "create": true,
    "update": false,
    "delete": false,
    "set": false,
    "end": false
  },
  "properties": [
    {
      "kind": "stored",
      "name": "note",
      "label": "Note",
      "type": { "t": "text", "format": "long" },
      "required": true
    }
  ]
}

TypeDecl.verbs

Which generated verbs exist (runtime §4.4); default all.

Field Type Required Default Example Description
create boolean no true true Whether the generated create verb exists.
update boolean no true true Whether the generated update verb exists.
delete boolean no true true Whether the generated delete verb exists.
set boolean no true true Whether the generated set verb exists.
end boolean no true true Whether the generated end verb exists.

TypeDecl.keys

The keys of the type.

Field Type Required Default Example Description
natural PropId[] no — ["pr_1c3e5g7j9m"] The natural key: required properties that name a row.
unique PropId[][] no — [["pr_1c3e5g7j9m","pr_3a5c7e9g1j"]] Each list of properties is unique together.

TypeDecl.temporal

Rows are effective-dated; compiles to a no_overlap invariant.

Field Type Required Default Example Description
from PropId yes — "pr_3a5c7e9g1j" The start of each row’s period.
to PropId yes — "pr_9t1v3x5z7b" The end of each row’s period.
key PropId[] yes — ["pr_1c3e5g7j9m"] Required properties whose rows must not overlap.

InvariantDecl

A rule every write must keep.

One of, told apart by kind:

InvariantDecl.check

A row condition.

Field Type Required Default Example Description
kind "check" yes — "check" A condition on one row.
id InvariantId yes (propose assigns it; a new declaration leaves it out) — — An invariant id (iv_…); renames keep it.
holds Expr yes — "ends >= starts" The CX condition every row must hold.
message MsgRef yes — {"text":"A booking cannot end before it starts."} What a refused write says.

An item of invariants in a type file.

{
  "kind": "check",
  "holds": "total >= 0",
  "message": { "text": "The total cannot be negative." }
}

InvariantDecl.unique

A uniqueness rule.

Field Type Required Default Example Description
kind "unique" yes — "unique" No two rows share these values.
id InvariantId yes (propose assigns it; a new declaration leaves it out) — — An invariant id (iv_…); renames keep it.
props PropId[] yes — ["pr_5w7y9a1c3e"] The properties whose values are unique together.
where Expr no — "active" Only rows where this holds count.

An item of invariants in a type file.

{ "kind": "unique", "props": ["pr_5w7y9a1c3e"], "where": "active" }

InvariantDecl.no_overlap

A no-overlap rule.

Field Type Required Default Example Description
kind "no_overlap" yes — "no_overlap" No two rows with the same key overlap in time.
id InvariantId yes (propose assigns it; a new declaration leaves it out) — — An invariant id (iv_…); renames keep it.
from PropId yes — "pr_3a5c7e9g1j" The start of each row’s period.
to PropId yes — "pr_9t1v3x5z7b" The end of each row’s period.
key PropId[] yes — ["pr_1c3e5g7j9m"] Required properties that group rows that must not overlap.

An item of invariants in a type file.

{
  "kind": "no_overlap",
  "from": "pr_3a5c7e9g1j",
  "to": "pr_9t1v3x5z7b",
  "key": ["pr_1c3e5g7j9m"]
}

InvariantDecl.bound

A bound over the type’s rows.

Field Type Required Default Example Description
kind "bound" yes — "bound" A condition over the rows of the type together.
id InvariantId yes (propose assigns it; a new declaration leaves it out) — — An invariant id (iv_…); renames keep it.
holds Expr yes — "count() <= 1000" The CX condition every row must hold.
message MsgRef yes — {"text":"At most {max} orders.","params":{"max":"1000"}} What a refused write says.

An item of invariants in a type file.

{
  "kind": "bound",
  "holds": "count() <= 1000",
  "message": { "text": "At most {max} orders.", "params": { "max": "1000" } }
}

MeasureDecl

A declared aggregate, read by data.aggregate, Aggregate/Stat, nav counts and agents.

Field Type Required Default Example Description
id MeasureId yes (propose assigns it; a new declaration leaves it out) — — A measure id (ms_…); renames keep it.
label Text yes (a draft may leave it out: propose writes a default made from the name, catalog.label_defaulted) — "Bookings" The words shown for it.
expr Expr yes — "count()" One CX aggregate over the type’s rows (use site measure, cost at most agg).
groupBy PropId[] no — ["pr_5n1v3x7c9d"] The properties a reader may group it by.
where Expr no — "status == 'placed'" Only rows where this holds are aggregated.

An entry of measures in a type file, under its name (here revenue).

{
  "label": "Revenue",
  "expr": "sum(total)",
  "groupBy": ["pr_5n1v3x7c9d"],
  "where": "status == 'placed'"
}

TitleDecl

A CX text expression, or a template with CX params that present writes in the reader’s convention.

Type: Expr | MsgRef.

SearchSpec

Makes the property a search source.

Field Type Required Default Example Description
weight "title" | "body" yes — "body" The weight class of its search column: title ranks above body.

The searchable of a property.

{ "weight": "title" }

This page as Markdown