Brine is a configuration loader that addresses common problems with configuring Elixir applications so that they are consistent with 12 Factor.
- Allow loading of configuration from a variety of sources (eg Environment, File, Etcd)
- Avoid config per environment pattern
- Support loading of Elixir terms
- Be compatible with libraries not using Brine
- Support autocomplete and compile time checks when retrieving configuration variables
- Reduce temptation to hardcode variables by lowering friction of adding configuration
The package can be installed by adding brine
to your list of dependencies in mix.exs
:
def deps do
[
{:brine, "~> 0.1.0"}
]
end
Create a module to represent all configuration variables with default values
defmodule MyApp.Config do
use Brine
def config(:myapp, [
foo: "bar",
nested: %{
test: nil
}
])
end
When your application starts load the configuration via a Brine.Loader
. Example below uses the Environment Variable Loader. Then you can access the variables by calling the generated function.
MYAPP_NESTED_TEST='Hello' iex -S mix
iex(1)> :ok = MyApp.Config.load(Brine.Loader.Env)
iex(2)> MyApp.Config.myapp_nested_test()
"Hello"
This also works with external libraries.
defmodule MyApp.Config do
use Brine
def config(:ex_twilio, [
account_sid: nil,
auth_token: nil
])
end
EX_TWILIO_ACCOUNT_SID=xxxx EX_TWILIO_AUTH_TOKEN=xxxx iex -S mix
Brine supports loading Elixir terms so the following is possible
MYAPP_FOO='{:example, 5}' iex -S mix
iex(1)> MyApp.Config.myapp_foo()
{:example, 5}
If the input cannot be parsed, it will assume the input is meant to be a String
. However, Elixir by default interprets a term starting with an uppercase letter as a Module. Sometimes this isn't desired but you can coerce it into a string by wrapping it in quotes as shown below
MYAPP_FOO='Hello' iex -S mix
iex(1)> MyApp.Config.myapp_foo()
Hello
MYAPP_FOO='"Hello"' iex -S mix
iex(1)> MyApp.Config.myapp_foo()
"Hello"
Still thinking about a better way to implement this so please open an issue if you have any ideas