README.md

# Enviable

[![Hex.pm][shield-hex]][hexpm] [![Hex Docs][shield-docs]][docs]
[![Apache 2.0][shield-licence]][licence] ![Coveralls][shield-coveralls]

- code :: <https://github.com/halostatue/enviable>
- issues :: <https://github.com/halostatue/enviable/issues>

Enviable is a small collection of functions to improve Elixir project
configuration via environment variables as proposed under the [12-factor][12f]
application model. It works well with configuration environment loaders like
[Dotenvy][dotenvy], [Nvir][nvir], or [Envious][envious] and provides robust
value conversion like [jetenv][jetenv].

Enviable 2.0 removes deprecated functions and changes defaults as previously
documented. Elixir 1.17 or later is required.

## Usage

Enviable will typically be imported in `config/runtime.exs` after `Config`, but
may be used anywhere that environment variables are read.

### Enviable with [Nvir][nvir]

```elixir
import Nvir
import Enviable

client = fetch_env!("CLIENT")
dotenv!([".env", ".env.#{client}"])

config :my_app,
  key: fetch_env!("SECRET_KEY"),
  port: fetch_env_as_integer!("PORT"),
  ssl: get_env_as_boolean("SSL_ENABLED")
```

### Enviable with [Dotenvy][dotenvy]

```elixir
# config/runtime.exs
import Config
import Enviable

client = fetch_env!("CLIENT")
Dotenvy.source([".env", ".env.#{client}", get_env()], side_effect: &put_env/1)

config :my_app,
  key: fetch_env!("SECRET_KEY"),
  port: fetch_env_as_integer!("PORT"),
  ssl: get_env_as_boolean("SSL_ENABLED")
```

> #### Info {: .info}
>
> When using Dotenvy, the use of a `side_effect` that calls `System.put_env/1`
> is **required**, as Enviable works with the system environment variable table.
> Future versions of Enviable may offer ways to work with the default Dotenvy
> behaviour.

### Enviable with [Envious][envious]

```elixir
# config/runtime.exs
import Config
import Enviable

client = fetch_env!("CLIENT")

env_files = [".env", ".env.#{client}"]

loaded_env =
  Enum.reduce(env_files, %{}, fn file, acc ->
    with {:ok, contents} <- File.read(file),
         {:ok, env} <- Envious.parse(contents) do
      Map.merge(acc, env)
    else
      _ -> acc
    end
  end)

for {key, value} <- loaded_env, do: put_env_new(key, value)

config :my_app,
  key: fetch_env!("SECRET_KEY"),
  port: fetch_env_as_integer!("PORT"),
  ssl: get_env_as_boolean("SSL_ENABLED")
```

## Installation

Enviable can be installed by adding `enviable` to your list of dependencies in
`mix.exs`:

```elixir
def deps do
  [
    {:enviable, "~> 2.1"},
    # Optional, required for decimal conversion
    {:decimal, "~> 2.3"},
    # Optional, required only if :json or JSON aren't available or another
    # JSON engine is not configured
    {:jason, "~> 1.4"},
    # Optional, if using the Enviable credo checks
    {:credo, "~> 1.7", only: [:dev, :test], runtime: false}
  ]
end
```

Documentation is found on [HexDocs][docs].

## Semantic Versioning

`Enviable` follows [Semantic Versioning 2.0][semver].

[12f]: https://12factor.net/
[docs]: https://hexdocs.pm/enviable
[dotenvy]: https://hexdocs.pm/dotenvy/readme.html
[envious]: https://github.com/jax-ex/envious
[hexpm]: https://hex.pm/package/enviable
[jetenv]: https://hexdocs.pm/jetenv/readme.html
[licence]: https://github.com/halostatue/prosody/blob/main/LICENCE.md
[nvir]: https://hexdocs.pm/nvir/readme.html
[semver]: https://semver.org/
[shield-coveralls]: https://img.shields.io/coverallsCoverage/github/halostatue/enviable?style=for-the-badge
[shield-docs]: https://img.shields.io/badge/hex-docs-lightgreen.svg?style=for-the-badge "Hex Docs"
[shield-hex]: https://img.shields.io/hexpm/v/enviable?style=for-the-badge "Hex Version"
[shield-licence]: https://img.shields.io/hexpm/l/enviable?style=for-the-badge&label=licence "Apache 2.0"