Elixir env config loader with typed defaults
Elixir
defmodule EnvConfig do
def load(spec, env \\ System.get_env()) do
Enum.reduce_while(spec, {:ok, %{}}, fn {key, opts}, {:ok, acc} ->
raw = Map.get(env, to_string(key), Keyword.get(opts, :default))
case cast(raw, Keyword.get(opts, :type, :string)) do
{:ok, value} -> {:cont, {:ok, Map.put(acc, key, value)}}
{:error, why} -> {:halt, {:error, "#{key} #{why}"}}
end
end)
end
defp cast(nil, _type), do: {:error, "is required"}
defp cast(raw, :string), do: {:ok, raw}
defp cast(raw, :integer) do
case Integer.parse(to_string(raw)) do
{value, ""} -> {:ok, value}
_ -> {:error, "must be an integer"}
end
end
defp cast(raw, :boolean) when raw in ["true", "1"], do: {:ok, true}
defp cast(raw, :boolean) when raw in ["false", "0"], do: {:ok, false}
defp cast(_, :boolean), do: {:error, "must be true or false"}
end