Skip to content

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 11 Oct 09:02
· 7 commits to master since this release
4128ed3
  • Badges (stable version, downloads, build, static analysis, Psalm level,
    PHP, license) and a package description in the sibling packages' style.
  • string() rejects invalid UTF-8 up-front, before any length, format or
    pattern check — the domain is JSON strings, so the code-point length and
    the pattern engine never disagree about the input (#12).
  • A PCRE engine failure during a pattern check (e.g. backtrack limit
    exhausted) is reported as its own error — Pattern check failed (PCRE engine error: …) — never as a plain pattern mismatch (#11).
  • BC: SchemaException now extends \InvalidArgumentException
    (invalid input, semantically) instead of \RuntimeException. Code
    catching it as \RuntimeException must catch SchemaException or
    \InvalidArgumentException; everything else is unchanged (#16). Fits
    the pre-1.0 SemVer allowance.
  • IntSchema::positive() (>= 1) and nonNegative() (>= 0) — the named
    intent of ids and counters, thin wrappers over min() with identical
    parse, generator and JSON Schema export (#17).
  • Schema::float() — the number type: finite floats only (NaN/INF
    rejected), inclusive min()/max(), allowInt() widening parse to
    whole numbers (normalized to float), generator over the same range,
    export type: number with minimum/maximum (#6).
  • Schema::dateTime() — RFC 3339 string on the wire, DateTimeImmutable
    in the PHP domain, inclusive min()/max() bounds, generator over the
    same range, export type: string, format: date-time (bounds recorded
    as a NonRepresentable entry — pure draft 2020-12 has no keyword for
    them), toWire() formats back to the string (#15).
  • Format::DateTime strictness aligned with Schema::dateTime():
    rolled-over components (25:00) and trailing data are now rejected
    instead of silently rolling over (#15).
  • Schema::discriminated('kind', [...]) — a tagged union: the
    discriminator property selects the branch (checked eagerly as a
    required literal equal to the branch key, so branches are disjoint by
    construction), an unknown or missing tag is its own error at the tag's
    path, and errors inside the branch keep their full paths. Export is
    oneOf. Int and string tags both work (#9).
  • Schema::tuple([...]) — a fixed-length heterogeneous list
    (prefixItems + items: false), errors carrying their element index
    ($[1]) (#9).
  • ObjectSchema::strip() — the third unknown-key mode: drop unknown keys
    and keep the known ones (the shape for parsing external payloads you
    only trust partially). Mutually exclusive with
    additionalProperties(); the export keeps additionalProperties: true
    and records the drop as a NonRepresentable strip entry (#13).
  • Behavior change: additionalProperties() now passes unknown keys
    through into the parse result (the mode's documented purpose —
    round-tripping partially known maps); previously they were tolerated
    but silently dropped, making it indistinguishable from strip (#13).
  • Optional coerce() on Schema::int(), Schema::float() and
    Schema::bool(): canonical number/bool strings from query strings and
    forms are accepted and normalized to the typed value (bounds apply
    after the coercion; no leading zeros, no whitespace, no overflow; bool
    strings are the four unambiguous true/false/1/0). The
    generator's domain stays typed; each export keeps its canonical type
    and records a NonRepresentable coerce entry (#8).
  • UnionSchema failures now keep structured branch errors:
    ParseError->branches (list<UnionBranch> with the member index and
    the branch's own error paths) instead of a flattened first-error
    summary; SchemaException renders them indented, and parents prepend
    their segment to branch paths (#10).
  • ObjectSchema::into(Dto::class) → Combinator\IntoSchema: optional
    hydration of the parsed properties into a DTO via its named-argument
    constructor (after defaults and strip()); a throwing constructor is a
    parse error carrying class names only; the export and the wire form stay
    the object schema's own (#14).
  • StringSchema::regexUnchecked($pattern, $generator): an explicit opt-out
    for valid PCRE patterns outside the generatable subset (\z, lookaround,
    backreferences) — the caller supplies the generator, the export records a
    regexUnchecked NonRepresentable entry; the regex() rejection message
    points to it (#7).
  • Testing\RoundTrip (+ Testing\RoundTripException): framework-agnostic
    parity assertions for consumers — assertParses(), assertWireRoundTrip()
    and assertConsumerRoundTrip() for a hydrate/wire pair — so the law is
    defined once next to the schema (#18).
  • Schema::dateTime() generator emits millisecond-precision moments (the
    wire precision) inside the bounds aligned inwards; a value generated at a
    sub-millisecond bound no longer falls outside it after toWire(). Bounds
    that admit no millisecond-precision moment are rejected at construction.