Schema
Table of Contents
Interfaces
- DXNSchemaMaterializingProvider
- A {@see DXNSchemaProvider} that additionally supplies a materializer
-- how to turn an already-schema-validated field map into whatever
decoded shape the provider's own class prefers. Without this, a
provider's schema decodes to the default plain field array.
- DXNSchemaProvider
- Lets a class's *own* library ship a DXN schema for it -- field
names, types, required/optional, closed/forbidden, refinements --
without that library ever taking a runtime dependency on this one.
Classes
- Coercion
- Schema-driven type coercion on encode -- a capability with no Elixir
`dextrin` equivalent, ported from `node-dextrin` because the value
model's own `DXN*::fromX()`/`::from*()` conversion helpers already
make the coercion table trivial to build: every class's documented
native-type converter doubles as an encode-time coercion, with no
separate registration.
- Compiled
- The result of compiling one `%schema{}` 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.
- 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
- An optional convenience resolver ({@see Registry::putResolver()})
resolving `Namespace/Name` references to `.dxns` files on disk.
- Provider
- Compiles and registers one {@see DXNSchemaProvider} into a
{@see Registry}, in order:
- SchemaCompileError
- Thrown by {@see Compiler} for a malformed `.dxns` document.
- SchemaValidationError
- Thrown by {@see Validator}/{@see \JOetjen\Dextrin\Schema} for a value that violates its schema.
- 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.
- TypeExpr
- Internal, compiled representation of a `.dxns` type expression -- the
12-form vocabulary (`any`, `primitive`, `reference`, `list-of`,
`set-of`, `tuple-of`, `map-of`, `enum`, `one-of`, `all-of`,
`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/closed/forbidden/refine) -- 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`).
- NotCoercible
- A payload-free enum used as {@see Coercion::tryCoerce()}'s "no
applicable coercion" sentinel, comparable via `!==`/`instanceof` --
a coerced value can legitimately be `null` (a value coerced toward
a `nilable` field, say), so `null` itself can't double as "coercion
didn't apply" the way JS's own `tryCoerce` uses `undefined`.