# Schemas of schemas

> Describing data that describes data: a schema held as a value, so the interface that edits records edits their shape.

A [schema](https://ui.publictheta.com/foundations/schema.md) is data, so it has a shape of its own: a kind,
and the settings that kind takes. Describe that shape as a schema, and whatever
builds a form from a schema builds the form that edits schemas. People can then
make and change the shape of their own records — add a field, rename one, give a
number a limit — with the controls they already use for the records themselves.

## Best practices

**Describe schemas with the schema they are written in.** One description, of
which every kind is a case: its kind, then what only that kind has, then what
every kind shares. Nothing about the editor of schemas is then special; it is the
editor of records, given a different record.

**Give each setting its own kind.** A number's least and most are numbers, a
date's are dates, a text's pattern is text, whether it runs to several lines is
a yes-or-no, what it holds is a choice, a choice's options are a list of values
with labels. People set a limit with the control that reads that kind, and a
limit of the wrong kind cannot be entered.

**Let a description contain descriptions.** A record's fields and a list's items
are schemas too. The description refers to itself there, and is followed only as
far as the value in hand goes: a description of any depth is edited, and none is
drawn before it exists.

**Show a kind's settings when the kind is chosen.** Choosing among the kinds
comes first, and the settings of the chosen one follow it. Changing the kind
keeps what the two have in common — the label, the help, whether it is
optional — and starts the rest afresh.

**Keep a description that is being edited apart from the schema in use.** While
someone is half-way through a change the description may be incomplete — a field
with no key yet. What is built from the schema keeps the last description that
was whole, and says that it does; it takes up the new one as soon as that is
whole.

**Check what a description cannot state of itself.** That a least is not above
its most, that a starting value is one its own limits allow, that a pattern can
be read, that no two fields of a record share a key: these are relations between
settings, not limits on one. Check them beside the description, and report each
at the setting to change, in the same way as any other problem. A single value's
[formula](https://ui.publictheta.com/foundations/formula.md) is one of its settings, read against the other
fields of its record as it is written: a name that is no field, a kind that does
not fit, a field that depends on itself is reported at the formula, with the
part of it at fault marked.

**Never fail on a description, however odd.** Whatever a person can enter must
at worst be reported. A pattern that cannot be read matches nothing, and is
said to be at fault; it does not stop the interface that uses it.

**Fit the records to a schema that has changed.** Keep every value that is still
of its field's kind, drop what belongs to a field that is gone, and start a new
field as a new record would. A value that only breaks a new limit is kept and
reported, not thrown away: the limit may be the mistake.

**Follow a renaming.** A field given a new key is the same field, and keeps its
values; so is an option, or a kind of record, given a new value. A renaming is
told from a removal and an addition by its place: the new name stands where the
old one stood, and the old one is gone.

**Write a schema out clean.** A description holds every setting, set or not; the
schema made from it states only those that are set, so that it reads as one
written by hand, and comes back from storage as it went.

**Say that a description cannot hold a rule.** A description is data. A schema
that refers to itself through a rule in a program has no description that ends;
to describe one, what it refers to needs a name.

See also [Schemas](https://ui.publictheta.com/foundations/schema.md), the [object editor](https://ui.publictheta.com/components/object-editor.md)
and the [data grid](https://ui.publictheta.com/components/data-grid.md).

## Behaviour

Each statement is verified by a test in Chromium, Chromium (touch), Firefox, WebKit, WebKit (touch), unless it names the environments it applies to or is marked open.

### Describing a schema

- A schema's description is data: its kind, every setting of that kind, and nothing where none is stated.
- A record's description lists its fields, each a key and the description of its schema, and a list's holds its item's.
- Each setting is of its own kind: a number's limits are numbers, a date's are dates, a pattern is text, a format is a choice.
- Every kind has a label, a description, and whether it is optional or read-only; and every setting says what it is called.
- A record's fields and a list's item are the schema of schemas again, met only when a value reaches them.
- A description that breaks its schema is reported where it does, like any value.
- The type of a description is one of the kinds, told apart by `kind`.

### Turning a description into a schema

- The schema a description turns into states only what is set: nothing absent, no empty text, no flag that is off.
- A yes-or-no that starts as no keeps saying so: only a flag's no is the same as nothing.
- Every schema's description is one the schema of schemas allows, and turns back into the same schema.
- A description is plain data: it survives being written out and read back.
- A description the schema of schemas allows always turns into a schema that can be put to use, whatever its limits say.
- A reference is described as what it refers to, with what the reference states of its own.
- A schema that contains itself has no description that ends, and is refused.
- A schema that contains itself is described by giving what it refers to a name. *(open)*
- What is not a description is refused.
- The schema of a record's schema alone is the record kind's own fields.

### Checking what a description cannot state

- A lower limit above its upper one is found, at the lower.
- A default its own schema does not allow is found at the default, as the problem it is.
- A pattern that is not a regular expression is found at the pattern.
- An amount of money with no currency is found at the currency.
- A name used before is found at its later use: a record's keys, a choice's values, a variant's values.
- A formula that cannot be used is found at its field's formula, with why and the part it is about.
- A variant's field may not be called what its tag is, nor two of one variant's fields the same; two variants may share a name.
- A problem is found however deep it lies, at the path of its part in the schema's description.
- A schema that contains itself is checked once through, and the check ends.

## Reference implementation

React: `npx shadcn@latest add https://ui.publictheta.com/r/schema-schema.json`
