Type system for RPC procedure input/output specs.
Three entry points: resolve/1 normalizes a shorthand spec into the internal
IR map, validate/2 checks untrusted input against a spec, and serialize/2
prepares handler output for JSON encoding.
Atom keys in validated input
After a successful validate/2 call, object values are returned with
atom keys (e.g. %{id: "abc"}), not string keys. Handler functions
therefore receive atom-keyed maps and should pattern-match accordingly:
def get(%{id: id}, _ctx), do: ... # correct
def get(%{"id" => id}, _ctx), do: ... # wrong — key will be missing
Summary
Types
Internal IR map used throughout the type system; always has a kind string key.
Functions
Converts a shorthand spec term (atom, tagged tuple, or map) to an internal_spec IR map.
Serializes a server-produced value against spec into a JSON-encodable shape.
Validates user-supplied value against spec, returning {:ok, coerced} or {:error, tree}.
Types
Functions
@spec resolve( :string | :integer | :float | :boolean | {:optional, term()} | {:nullable, term()} | {:list, term()} | {:stream, term()} | internal_spec() | map() ) :: internal_spec()
Converts a shorthand spec term (atom, tagged tuple, or map) to an internal_spec IR map.
Serializes a server-produced value against spec into a JSON-encodable shape.
spec may be a shorthand spec term (atom, tagged tuple, or map — see resolve/1)
or an already-resolved IR map. Assumes value already conforms to spec (e.g. fresh
from a handler) and raises on contract violations such as missing required fields —
these indicate programmer error, not bad input.
Validates user-supplied value against spec, returning {:ok, coerced} or {:error, tree}.
spec may be a shorthand spec term (atom, tagged tuple, or map — see resolve/1)
or an already-resolved IR map. Intended for untrusted input (decoded JSON), so
contract violations come back as error trees rather than raises.
Object values in the returned {:ok, coerced} tuple always have atom keys; see the
module doc for details.