Schema
Table of Contents
Interfaces
- DXNSchemaMaterializingProvider
- A {@see DXNSchemaProvider} that additionally supplies the schema's
materializer -- called for every decoded struct of the schema,
whatever its version, with the schema's name, the version the fields
were read with and the checked fields; it answers the provider's own
class at the latest version. Without this, a provider's schema decodes
to the generic {@see \JOetjen\Dextrin\Value\DXNStruct}.
- DXNSchemaProvider
- Lets a class's *own* library ship a DXN schema for it -- field
names, types, required/optional, refinements --
without that library ever taking a runtime dependency on this one.
Classes
- Absent
- What {@see Validator} answers for an optional field that was not given
and has no default: absent, which DXN tells apart from a field written
`nil`. One instance, compared by class.
- Compat
- The version discipline check (DXNS.md §8), mirroring
`Dextrin.Schema.Compat`: compares the schemas of a previous release
with the current ones.
- Compiled
- The result of compiling one `%schema(N){}` entry from a `.dxns`
document ({@see Compiler}) -- enough to both validate a decoded
value and convert it both directions between `.dxnb`'s
always-positional wire shape and a named field map.
- Compiler
- Compiles a parsed `.dxns` document (an ordinary decoded DXN value --
a `.dxns` file is valid `.dxn`, no new grammar; what makes it a
*schema* document is purely the shape of the value it parses to: a
`map` from name to type expression -- a bare PHP array in this port)
into {@see Compiled} entries.
- Context
- What a check knows besides the type and the value: the registry
(`null` when there is none -- strict is then off), and the fields of
the nearest enclosing struct or shape by name, which a `{:case}` reads
its sibling from (`null` outside any).
- Docs
- HTML documentation for a directory of `.dxns` schema documents -- the
port of `Dextrin.Schema.Docs`, writing the same site byte for byte (Jan,
2026-10-20): a sidebar tree of every namespace and definition, the index
and every namespace's page in one design, the pages a directory tree with
an `index.html` per namespace, every reference a link, every version
shown. It reads the documents' source, not their compiled schemas.
- FetchedSchema
- The result of a successful {@see Registry::fetchStructSchema()} --
the compiled schema itself, plus the (possibly-updated) registry a
lazy resolver hit should be threaded forward through, so a
resolved-on-demand schema is only ever resolved once per registry
lineage.
- Field
- One compiled field spec inside a {@see Compiled} schema. `required`
comes from the `?`-suffixed key convention (a field key ending in
`?` is optional; no separate flag exists in `.dxns` itself);
`default`/`description` only ever come from the `%field{...}` escape
hatch, since optionality is already fully covered by the key suffix.
- FileResolver
- A resolver ({@see Registry::putResolver()}) finding a struct's schema
in `.dxns` files on disk, by the convention DXNS.md §6 states for
every implementation -- so one set of schema files serves them all.
- Layout
- The names a `.dxns` file's entries have, from where the file lies under
its root (DXNS.md §6) -- one rule for every reader of a tree: the docs
generator, {@see Tree} and the file resolver; the port of
`Dextrin.Schema.Layout`.
- Particle
- One of a `{:list-items}`'s items (DXNS.md §1a): a type for exactly one
item, or a repeat of a group of them, `$max` `null` when there is no
upper bound.
- Provider
- Compiles and registers one {@see DXNSchemaProvider} into a
{@see Registry}, in order:
- Reader
- Which schema a decoded struct is read with, given the version it was
written with and the versions loaded (DXNS.md §8). Shared by the text
parser and the binary decoder, so both answer every case the same way
-- mirrors `Dextrin.Schema.Reader`:
- SchemaCompileError
- Thrown by {@see Compiler} for a malformed `.dxns` document, with the `schema/compile` category.
- SchemaValidationError
- Thrown by {@see Validator}/{@see \JOetjen\Dextrin\Schema} for a value
that violates its schema, with the violation's DXN.md §5 category
(`schema/missing-field`, ...), which every channel passes on
unchanged. Null only where a caller asked for something that is not a
DXN error at all, such as a schema that was never registered.
- Std
- This library's standard library of named types
(`priv/schema/std.dxns`, ported verbatim from `dextrin`'s own) --
common refinements like `PositiveInteger`/`NonEmptyString`, so a
schema author doesn't redefine them by hand. Built the same way any
consumer's own named types would be -- nothing about them is
special-cased in {@see Compiler}. Deliberately excludes anything
domain-specific (email, phone number, URL-shaped string): what
counts as a valid one is an application decision this library
shouldn't guess at.
- Tree
- A tree of `.dxns` files read as one (Jan, 2026-10-20), the port of
`Dextrin.Schema.Tree`: every entry named from where its file lies
(DXNS.md §6, {@see Layout}), the files compiled in the order their
references need -- so a reference to another file's named type
resolves whatever order the files sort in -- and every problem reported
with its file and line:
- TypeExpr
- Internal, compiled representation of a `.dxns` type expression -- the
vocabulary of DXNS.md §1 (`any`, `never`, `primitive`, `reference`,
`list-of`, `list-items`, `set-of`, `tuple-of`, `tuple-of-all`, `map-of`, `array-of`, `tagged`, `doc`, `if`,
`ordered-map-of`, `sorted-set-of`, `enum`, `one-of`, `any-of`,
`all-of`, `not`, `nilable`, `refine`) {@see Compiler} turns a parsed `.dxns` value
into, and what {@see self::matches()} checks a decoded/to-be-encoded
value against. (The 13th `dxn/DXN.md` §4 form, `struct`, isn't a
distinct compiled shape here either -- a `%schema{}` entry compiles
straight to {@see Compiled}, never to a `TypeExpr` a *field* could
hold; `reference` is what a field uses to point at one.)
- Validated
- Internal only -- never appears in a value handed back to
`Dextrin::decode()`/`decodeBinary()`'s caller.
- Validator
- Checks a value's fields against a {@see Compiled} schema
(required fields and their types) -- shared by decode ({@see
self::materialize()}, which also produces a materialized result) and
encode-time validation ({@see self::validateForEncode()}/{@see
self::validateTreeForEncode()}). Both directions reuse the exact
same `resolveFields()`/`TypeExpr::matches()` field-checking; encode's
own values are wrapped in the same {@see Validated} marker decode
already uses, via `wrapAndCheck()`, so there's one type-checking
implementation, not two that could drift.
Enums
- NoDefault
- A payload-free enum used purely as a unique sentinel value ({@see
Field::NO_DEFAULT}), comparable via `!==` -- PHP has no `undefined`/
`Symbol()` to reach for the way JS's own `Field.NO_DEFAULT` does,
and a plain `null` would be ambiguous with a field whose declared
default genuinely *is* `null` (DXN `nil`).
- NoMatch
- What {@see TypeExpr::conform()} answers when a value does not match:
a value of its own, since `null` and `false` are values a type takes.