defmodule Sorcery.Specs.Primative do
use Norm
def any(), do: spec(fn _ -> true end)
# Due to the difficulty of hardcoding pids in tests, we allow integers.
def pid(), do: spec(is_pid() or is_integer())
def string(), do: spec(is_binary)
def bool(), do: spec(is_boolean())
def atom(), do: spec(is_atom())
def struct(), do: spec(is_struct())
def map(), do: spec(is_map())
def list(), do: spec(is_list())
def id_int(), do: spec(is_integer() and &(&1 >= 0))
def id(), do: one_of([ spec(is_binary()), id_int() ])
def entity(), do: schema(%{id: id()})
def tk(), do: atom()
def attr(), do: atom()
@doc """
Map format for a list of entities of a given type.
%{
1 => %{id: 1, name: "asdf"},
2 => %{id: 2, name: "qwerty"},
}
"""
def tablemap(), do: spec(is_map() and fn t ->
Enum.all?(t, fn {id, %{}} ->
is_integer(id)
end)
end)
@doc """
Format for the collection of all entities
%{
user: %{
1 => %{id: 1, name: "asdf"},
2 => %{id: 2, name: "qwerty"},
},
comment: %{
1 => %{id: 1, body: "asdf"},
2 => %{id: 2, body: "qwerty"},
},
}
"""
def db(), do: spec(is_map() and fn d ->
Enum.all?(d, fn {tk, table} ->
is_atom(tk) and conform!(table, tablemap())
end)
end)
############
def src(), do: spec(is_struct(Sorcery.Src))
def msg(), do: spec(is_struct(Sorcery.Msg))
def subject(), do: spec(is_struct(Sorcery.Src.Subject))
def watch_meta(), do: schema(%{
pid: pid(),
subject: subject()
})
def presences(), do: schema(%{"src_subjects" => schema(%{metas: coll_of(watch_meta())})})
end