Current section
Files
Jump to
Current section
Files
lib/nexus/command/validation.ex
defmodule Nexus.Command.Validation do
@moduledoc """
Defines validations for a `Nexus.Command` struct
"""
alias Nexus.Command.MissingType
alias Nexus.Command.NotSupportedType
@spec validate_required(map, atom, (any -> boolean)) :: map
def validate_required(%{name: name} = attrs, field, valid_type?) do
value = Map.get(attrs, field)
if value && valid_type?.(value) do
attrs
else
raise ArgumentError, "Missing or invalid value for #{field} field in command #{name}"
end
end
@supported_types Application.compile_env!(:nexus, :supported_types)
@spec validate_type(map) :: map
def validate_type(%{type: {:enum, values}} = attrs) do
string = Enum.all?(values, &is_same_type(&1, :string))
atom = Enum.all?(values, &is_same_type(&1, :atom))
if string or atom do
attrs
else
raise ArgumentError, "Enum values must be all strings or all atoms"
end
end
def validate_type(%{type: type} = attrs) do
if type in @supported_types do
attrs
else
raise NotSupportedType, type
end
end
def validate_type(_), do: raise(MissingType)
@spec validate_name(map) :: map
def validate_name(%{name: name} = attrs) do
if is_atom(name) do
attrs
else
raise ArgumentError, "Command name must be an atom"
end
end
@spec validate_default(map) :: map
def validate_default(%{required: false, type: {:enum, values}, name: name} = attrs) do
string = Enum.all?(values, &is_same_type(&1, :string))
atom = Enum.all?(values, &is_same_type(&1, :atom))
type = (string && "string") || (atom && "atom") || "enum"
default = Map.get(attrs, :default)
valid_default? = is_valid_default_type?(default, string, atom)
cond do
!default -> raise ArgumentError, "Non required commands must have a default value"
!valid_default? -> raise ArgumentError, "Default value for #{name} must be of type #{type}"
true -> attrs
end
end
def validate_default(%{required: false, type: type, name: name} = attrs) do
default = Map.get(attrs, :default)
cond do
!default and type != :null ->
raise ArgumentError, "Non required commands must have a default value"
!is_same_type(default, type) ->
raise ArgumentError, "Default value for #{name} must be of type #{type}"
true ->
attrs
end
end
def validate_default(attrs), do: attrs
defp is_valid_default_type?(default, string, atom) do
cond do
string -> is_binary(default)
atom -> is_atom(default)
true -> is_same_type(default, :string)
end
end
defp is_same_type(value, :string), do: is_binary(value)
defp is_same_type(value, :integer), do: is_integer(value)
defp is_same_type(value, :float), do: is_float(value)
defp is_same_type(value, :atom), do: is_atom(value)
defp is_same_type(_, :null), do: true
end