Packages
riptide
0.5.0-beta9
0.5.2
0.5.1
0.5.0-beta9
0.5.0-beta8
0.5.0-beta7
0.5.0-beta6
0.5.0-beta5
0.5.0-beta4
0.5.0-beta3
0.5.0-beta2
0.5.0-beta11
0.5.0-beta10
0.5.0-beta
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.3.0-bd63a38
0.2.79
0.2.78
0.2.74
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
A data first framework for building realtime applications
Current section
Files
Jump to
Current section
Files
lib/riptide/schema/schema.ex
defmodule Riptide.Schema do
defmacro schema(body) do
{schema, _} = Code.eval_quoted(body)
flattened = Dynamic.flatten(schema)
validate_steps =
Enum.map(flattened, fn {path, value} ->
{mod, opts} = mod_opts(value)
quote do
path = unquote(path)
case Dynamic.get(input, path) do
nil ->
[]
result ->
validate_child(path, result, unquote(mod), unquote(opts))
end
end
end)
getters =
schema
|> Dynamic.flatten()
|> Stream.flat_map(fn {path, _} ->
Stream.scan(path, [], fn segment, total ->
total ++ [segment]
end)
end)
|> Enum.uniq()
|> Stream.map(fn path ->
name_get =
["get" | path]
|> Enum.join("_")
|> String.to_atom()
quote do
def unquote(name_get)(input) do
Dynamic.get(input, unquote(path))
end
end
end)
|> Enum.to_list()
quote do
unquote(getters)
def schema() do
unquote(body)
end
def validate(input, _opts \\ []) do
unquote(validate_steps)
|> List.flatten()
|> case do
[] ->
:ok
result ->
{:error, result}
end
end
end
end
def validate_required(schema, input) do
schema
|> Dynamic.flatten()
|> Enum.filter(fn
{path, true} -> Dynamic.get(input, path) == nil
_ -> false
end)
|> case do
[] ->
:ok
layers ->
{:error, {:missing, Enum.map(layers, fn {path, _} -> path end)}}
end
end
def validate_child(path, value, mod, opts) do
case mod.validate(value, opts) do
:ok ->
[]
{:error, result} when is_list(result) ->
Enum.map(result, fn {sub_path, val} -> {path ++ sub_path, val} end)
{:error, result} ->
[{path, result}]
end
end
def mod_opts({mod, opts}), do: {from_alias(mod), opts}
def mod_opts(mod), do: mod_opts({mod, []})
alias Riptide.Schema.Type
def from_alias(:number), do: Type.Number
def from_alias(:string), do: Type.String
def from_alias(:list), do: Type.List
def from_alias(:map), do: Type.Map
def from_alias(:any), do: Type.Any
def from_alias(:enum), do: Type.Enum
def from_alias(:boolean), do: Type.Boolean
def from_alias(mod), do: mod
end