BootEnv

Elixir configuration provider inspired by Haskell programming experience. Runtime configuration of Haskell programs is a bit different if we compare with other languages like Elixir. Haskell program business logic mainly contains pure functions which can call only pure functions by their nature. This means that in random place of Haskell program something like Elixir function Application.get_env/2 or System.get_env/1 can't be called at all (because these functions are not pure). As a result of this, in Haskell programs all needed runtime configurations are usually fetched, transformed and validated during initial boot process of program, and after this passed to main loop function as arguments (typed values).

Benefits

Usage

Define configuration schema in dedicated module:

defmodule MyApp.BootEnv do
  use BootEnv

  conf :my_app do
    env ecto_repos, do: is_list(ecto_repos)
    env logo_url, do: Regex.match?(~r/^https?\:\/\/.+$/, logo_url)

    env backoffice_pagination do
      is_integer(backoffice_pagination) and
        backoffice_pagination > 0
    end

    conf MyApp.Repo do
      env username, do: String.valid?(username)
      env password, do: String.valid?(password)
      env database, do: String.valid?(database)
      env hostname, do: String.valid?(hostname)
      env pool_size, do: is_integer(pool_size) and pool_size > 1
    end
  end
end

Start configuration provider as first child in supervision tree:

children =
  [
    # Start BootEnv configuration first
    MyApp.BootEnv,
    # Start the Ecto repository
    MyApp.Repo
    # ...
  ]

Fetch runtime configuration parameter with get_env/1 expression where it's needed:

require MyApp.BootEnv, as: Conf
img_tag(Conf.get_env([:my_app, :logo_url]), class: "image")
#=> <img src="https://foo.bar/img/smile.png" class="image">

Installation

The package can be installed by adding boot_env to your list of dependencies in mix.exs:

def deps do
  [
    {:boot_env, "~> 0.1.1"}
  ]
end