A structured error: where, what, and the few values the message needs.
Nothing here renders a string until you ask for one. message/1 builds the sentence from
code and meta on demand, so a run that produces no errors never builds a message, and a
run that produces a thousand pays for the ones you actually print.
path locates the offending node. What it is a path through depends on who built the
error: Rupa.Schema.validate/1 returns paths through the schema, where :of is a list's
element, an integer is a tuple position, a string is a tagged branch, and :defs leads into
the definitions. Decoding returns paths through the data.
Summary
Types
Functions
Renders the error as a sentence.
iex> [:name] |> Rupa.Error.new(:unknown_format, %{format: :ssn}) |> Rupa.Error.message()
":ssn is not one of Rupa's built-in formats"
Builds an error.
iex> Rupa.Error.new([:age], :unknown_option, %{option: :fmt})
%Rupa.Error{path: [:age], code: :unknown_option, meta: %{option: :fmt}}
The path as an RFC 6901 JSON pointer.
iex> Rupa.Error.pointer(Rupa.Error.new([:addresses, 0, :street], :min))
"/addresses/0/street"
iex> Rupa.Error.pointer(Rupa.Error.new([], :unknown_type))
""A segment is a field name, an index or a wire key. A map_of key can be any term when the map
came from Elixir rather than from JSON, so a segment with no string of its own -- a tuple, say
-- is written the way inspect/1 writes it, escaped like any other.
iex> Rupa.Error.pointer(Rupa.Error.new([:by, {1, 2}], :type))
"/by/{1, 2}"