Packages
zoi
0.2.0
0.18.6
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.1
0.16.0
0.15.0
0.14.1
0.14.0
0.13.1
0.13.0
0.12.1
0.12.0
0.11.1
0.11.0
0.10.7
0.10.6
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.1
0.9.0
0.9.0-rc.1
0.9.0-rc.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.0
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
Zoi is a schema validation library for Elixir, designed to provide a simple and flexible way to define and validate data.
Current section
Files
Jump to
Current section
Files
lib/zoi/types/meta.ex
defmodule Zoi.Types.Meta do
@moduledoc false
@type refinement ::
{module(), atom(), [any()]} | (Zoi.Type.t(), Zoi.input() -> :ok | {:error, binary()})
@type transform ::
{module(), atom(), [any()]}
| (Zoi.Type.t(), Zoi.input() -> {:ok, Zoi.input()} | {:error, binary()} | Zoi.input())
@type t :: %__MODULE__{
refinements: [refinement()],
transforms: [transform()],
error: nil | binary()
}
@struct_fields [refinements: [], transforms: [], error: nil]
@struct_keys Keyword.keys(@struct_fields)
defstruct @struct_fields
@spec create_meta(keyword()) :: {t(), keyword()}
def create_meta(opts) do
{meta_opts, rest_opts} = split_keyword(opts)
{struct!(__MODULE__, meta_opts), rest_opts}
end
defp split_keyword(opts) when is_list(opts) do
Enum.reduce(opts, {[], []}, fn {k, v}, {meta_opts, rest_opts} ->
if k in @struct_keys do
{Keyword.put(meta_opts, k, v), rest_opts}
else
{meta_opts, Keyword.put(rest_opts, k, v)}
end
end)
end
@spec run_refinements(schema :: Zoi.Type.t(), input :: Zoi.input()) ::
{:ok, Zoi.input()} | {:error, binary()}
def run_refinements(schema, input) do
schema.meta.refinements
|> Enum.reduce({{:ok, input}, []}, fn
{mod, func, args}, {{:ok, input}, errors} ->
case apply(mod, func, [schema, input] ++ args) do
:ok ->
{{:ok, input}, errors}
{:error, err} ->
{{:ok, input}, Zoi.Errors.add_error(errors, err)}
end
refine_func, {{:ok, input}, error} ->
case refine_func.(schema, input) do
:ok ->
{{:ok, input}, error}
{:error, err} ->
{{:ok, input}, Zoi.Errors.add_error(error, err)}
end
end)
|> then(fn {{:ok, value}, errors} ->
if Enum.empty?(errors) do
{:ok, value}
else
{:error, errors}
end
end)
end
@spec run_transforms(schema :: Zoi.Type.t(), input :: Zoi.input()) ::
{:ok, Zoi.input()} | {:error, binary()}
def run_transforms(schema, input) do
schema.meta.transforms
|> Enum.reduce({{:ok, input}, []}, fn
{mod, func, args}, {{:ok, input}, error} ->
case apply(mod, func, [schema, input] ++ args) do
{:ok, value} ->
{{:ok, value}, error}
{:error, err} ->
{{:ok, input}, Zoi.Errors.add_error(error, err)}
value ->
{{:ok, value}, error}
end
transform_func, {{:ok, input}, error} ->
case transform_func.(schema, input) do
{:ok, value} ->
{{:ok, value}, error}
{:error, err} ->
{{:ok, input}, Zoi.Errors.add_error(error, err)}
value ->
{{:ok, value}, error}
end
end)
|> then(fn {{:ok, value}, errors} ->
if Enum.empty?(errors) do
{:ok, value}
else
{:error, errors}
end
end)
end
end