Current section
Files
Jump to
Current section
Files
lib/blunt/message/metadata.ex
defmodule Blunt.Message.Metadata do
defmacro register(opts) do
quote bind_quoted: [opts: opts] do
Module.register_attribute(__MODULE__, :metadata, accumulate: true, persist: true)
@metadata message_type: Keyword.get(opts, :message_type, :message)
end
end
def record(name, value) do
quote do
@metadata {unquote(name), unquote(value)}
end
end
def generate do
quote do
@metadata message_type: Module.delete_attribute(__MODULE__, :message_type)
@metadata schema_fields: Module.delete_attribute(__MODULE__, :schema_fields)
@metadata primary_key: Module.delete_attribute(__MODULE__, :primary_key_type)
end
end
def docs(module) do
case Code.fetch_docs(module) do
{:docs_v1, _anno, _lang, _format, %{"en" => docs}, _meta, _inner_docs} -> docs
_ -> nil
end
end
def message_type(module),
do: fetch!(module, :message_type)
def is_message_type?(module, type) when is_atom(module) and is_atom(type),
do: message_type(module) == type
def is_query?(module),
do: is_message_type?(module, :query)
def is_command?(module),
do: is_message_type?(module, :command)
def dispatchable?(module),
do: fetch!(module, :dispatchable?)
def options(module) do
module
|> fetch!(:options)
|> Enum.into(%{}, fn {name, type, config} ->
{name, Keyword.put(config, :type, type)}
end)
end
def primary_key(module) do
case fetch!(module, :primary_key) do
{name, type, opts} -> {name, type, Keyword.put(opts, :required, true)}
pk -> pk
end
end
def has_field?(module, field_name) do
names = field_names(module)
Enum.member?(names, field_name)
end
def fields(module) do
fetch!(module, :schema_fields)
end
def field_names(module) do
module
|> fields()
|> Enum.map(&elem(&1, 0))
end
def autogenerated_fields(module) do
module
|> fields()
|> Enum.filter(fn {_name, _type, opts} ->
case Keyword.get(opts, :autogenerate) do
{_m, _f} -> true
{_m, _f, _a} -> true
_ -> false
end
end)
|> Enum.map(fn {name, _type, opts} ->
{name, Keyword.fetch!(opts, :autogenerate)}
end)
end
def required_fields(module) do
module
|> fields()
|> Enum.filter(fn {_name, _type, opts} -> Keyword.fetch!(opts, :required) end)
|> Enum.map(&elem(&1, 0))
end
def fetch!(module, key) do
module
|> get_all()
|> Keyword.fetch!(key)
end
def get_all(module) do
:attributes
|> module.__info__()
|> Keyword.get_values(:metadata)
|> List.flatten()
end
def get(module, key, default \\ nil) do
module
|> get_all()
|> Keyword.get(key, default)
end
def get_values(module, key) do
module
|> get_all()
|> Keyword.get_values(key)
end
end