defmodule Weave.Loaders.Environment do @moduledoc """ This loader will utilise the available environment variables to provide configuration. A prefix must be specified. ```elixir loaders: [ {Weave.Loaders.Environment, prefix: "MY_APP_"}, {Weave.Loaders.Environment, prefix: nil} # Use nil to load all environment variables ] ``` With the above configuration, any environment variables that begin with `MY_APP_` will be sent to the handler. Please note, these will be "sanitized" before being sent to the handler. This means "MY_APP_NAME" will become "name" """ use Weave.Loader require Logger @doc """ You shouldn't call this function youroself. Instead, use a Weave module. """ def load_configuration(options: [prefix: prefix], only: only, handler: handler) do Logger.debug(fn -> "Weave - Environment Loader: prefix: #{prefix}, only: #{inspect(only)}, handler: #{ inspect(handler) }" end) System.get_env() |> filter_prefix(prefix) |> filter_only(only) |> Enum.map(fn {key, value} -> apply_configuration(key, value, handler) sanitize(key) end) end @doc """ Safety net to provide debug when people don't configure their loaders correctly """ def load_configuration(options: _, only: _, handler: _) do Logger.warn(fn -> "Weave Environment Loader called, but wasn't configured with `prefix: nil | binary`" end) [] end defp filter_prefix(variables, nil), do: variables defp filter_prefix(variables, prefix) do require Logger Logger.debug(fn -> "Filtering prefix: #{prefix}" end) variables |> Enum.filter(fn {key, _value} -> String.starts_with?(key, prefix) end) |> Enum.map(fn {key, value} -> {String.trim_leading(key, prefix), value} end) end defp filter_only(variables, nil), do: variables defp filter_only(variables, only) do # Allow variables names to be passed as string # or atoms by converting everything to strings here only = Enum.map(only, fn key -> String.downcase(to_string(key)) end) Enum.filter(variables, fn {key, _} -> String.downcase(key) in only end) end end