Packages

Configuration loader from system environment

Current section

Files

Jump to
config_env lib config_env.ex
Raw

lib/config_env.ex

defmodule ConfigEnv do
@moduledoc """
"""
@doc """
Hello world.
## Examples
iex> ConfigEnv.hello
:world
"""
defexception message: "invalid config"
def load_env(apps \\ []) do
apps
|> List.wrap
|> update_all_envs
end
defp update_all_envs(apps) do
apps
|> Enum.map(&{&1, Application.get_all_env(&1)})
|> Enum.map(&load_app_env/1)
|> Enum.map(&put_env/1)
raise_error()
end
defp load_app_env({app, envs}) when is_list(envs) do
{app, Enum.map(envs, &do_load_env/1)}
end
defp do_load_env({name, vals}) when is_list(vals) do
{name, Enum.map(vals, &do_load_env/1)}
end
defp do_load_env({name, val}) when is_map(val) do
{name, Enum.map(val, &do_load_env/1) |> Enum.into(%{})}
end
defp do_load_env({name, {:system, key}}) do
{name, do_load_env({:system, key, type: :string})}
end
defp do_load_env({name, {:system, key, opts}}) do
{name, do_load_env({:system, key, opts})}
end
defp do_load_env({:system, key}) do
do_load_env({:system, key, type: :string})
end
defp do_load_env({:system, key, opts}) do
key
|> System.get_env
|> do_load_env({key, opts})
end
defp do_load_env({:system, key, _opts}) do
System.get_env(key)
end
defp do_load_env(val) do
val
end
defp do_load_env(nil, {key, opts}) do
opts[:default] || put_error("ENV #{key} is missing")
end
defp do_load_env(val, {key, opts}) do
convert_type(val, key, opts[:type])
end
defp convert_type(val, _key, nil) do
val
end
defp convert_type(val, _key, :string) do
val
end
defp convert_type(val, _key, :binary) do
val
end
defp convert_type(val, _key, :atom) do
String.to_atom(val)
end
defp convert_type(val, key, :integer) do
case Integer.parse(val) do
{integer, _} -> integer
:error -> "ENV #{key} must be an integer"
end
end
defp convert_type(val, key, :float) do
case Float.parse(val) do
{float, _} -> float
:error -> "ENV #{key} must be a float"
end
end
defp convert_type(val, _key, :list) do
String.split(val, ",")
end
defp put_env({app, envs}) when is_list(envs) do
Enum.map(envs, &put_env(app, &1))
end
defp put_env(app, {key, val}) do
Application.put_env(app, key, val, persistent: true)
end
defp put_error(error) do
errors = Process.get(:errors, [])
Process.put(:errors, [error|errors])
end
defp raise_error do
case Process.get(:errors, []) do
[] -> :ok
errors -> raise __MODULE__, message: inspect(Enum.dedup(errors))
end
end
end