Nvir (Nvir v0.13.2)

View Source

This is the main API for Nvir, an environment variable loader and validator.

The most useful documentation is generally:

Summary

Functions

Returns the sources enabled by default when using dotenv/1 or dotenv_loader/0. The value changes dynamically depending on the current environment and operating system.

Loads specified dotenv files in the system environment. Intended usage is from config/runtime.exs in your project

Same as dotenv!/1 but accepts a custom configuration to load dotenv files.

Updates the given configuration with the given options.

Like dotenv_enable_sources/3 but accepts a keyword list or map of sources.

Enables or disables environment variable sources under the given tag.

Returns the default configuration for the dotenv!/2 function.

Returns a configuration for dotenv!/2 without any enabled source.

Returns the value of the given var, transformed and validated by the given caster.

Returns the value of the given var, transformed and validated by the given caster.

Types

config_opt()

@type config_opt() ::
  {:enabled_sources, %{required(atom()) => boolean()}}
  | {:parser, module()}
  | {:cd, nil | Path.t()}
  | {:before_env_set, transformer()}

source()

@type source() :: binary() | {atom(), source()} | [source()]

sources()

@type sources() :: source() | [sources()] | {atom(), sources()}

t()

@type t() :: %Nvir{
  before_env_set: term(),
  cd: nil | Path.t(),
  enabled_sources: %{required(atom()) => boolean()},
  parser: module()
}

transformer()

@type transformer() :: (var_def() -> var_def())

var_def()

@type var_def() :: {String.t(), String.t()}

Functions

default_dotenv_sources()

Returns the sources enabled by default when using dotenv/1 or dotenv_loader/0. The value changes dynamically depending on the current environment and operating system.

See the "Predefined tags" section on the dotenv!/1 documentation.

dotenv!(sources)

@spec dotenv!(sources()) :: %{required(binary()) => binary()}

Loads specified dotenv files in the system environment. Intended usage is from config/runtime.exs in your project

Variables defined in the files will not overwrite the system environment if they are already defined. To overwrite the system env, please list your files under an :overwrite key.

This function takes multiple sources and will select the sources to actually load based on system properties.

Valid sources are:

  • A string, this is an actual file that we want to load.
  • A {tag, value} tuple where the tag is an atom and the value is a source. Predefined tags are listed below. Additional tags can be defined with enable_sources/3.
  • A list of sources. So a keyword list is a valid source, i.e. a list of tagged tuples.

Files are loaded in order of appearance, in two phases:

  • First, files that are not wrapped in an :overwrite tagged tuple.
  • Then files that are wrapped in such tuples.

Files that do not exist are safely ignored.

Examples

import Config
import Nvir

# Load a single file
dotenv!(".env")

# Load multiple files
dotenv!([".env", ".env.#{config_env()}"])

# Load files depending on environment
dotenv!(
  dev: ".env.dev",
  test: ".env.test"
)

# Load files with and without overwrite
dotenv!(
  dev: ".env",
  test: [".env", ".env.test"],
  overwrite: [test: ".env.test.local"]
)

# Overwrite the system with all existing files
dotenv!(
  overwrite: [
    dev: ".env",
    test: [".env", ".env.test", ".env.test.local"]
  ]
)

# Totally useless but valid :)
dotenv!(test: [test: [test: ".env.test"]])
# Same without wrapping the tuples in lists
dotenv!({:test, {:test, {:test, ".env.test"}}})

# This will not load the file as `:test` and `:dev` will not be
# enabled at the same time
dotenv!(dev: [test: ".env.test"])

Predefined tags

Tags are enabled under different circumstances.

Mix environment

  • :dev - When Config.config_env() or Mix.env() is :dev.
  • :test - When Config.config_env() or Mix.env() is :test.

There is no predefined tag for :prod as using dotenv files in production is strongly discouraged.

Continuous integration

  • :ci - When the CI environment variable is "true".
  • :ci@github - When the GITHUB_ACTIONS environment variable is "true".
  • :ci@travis - When the TRAVIS environment variable is "true".
  • :ci@circle - When the CIRCLECI environment variable is "true".
  • :ci@gitlab - When the GITLAB_CI environment variable is "true".

Operating system

  • :linux - On Linux machines.
  • :windows - On Windows machines.
  • :darwin - On MacOS machines.

dotenv!(nvir, sources)

@spec dotenv!(t(), sources()) :: %{required(binary()) => binary()}

Same as dotenv!/1 but accepts a custom configuration to load dotenv files.

dotenv_configure(nvir, opts)

@spec dotenv_configure(t(), [config_opt()]) :: t()

Updates the given configuration with the given options.

The options are not merged.

Options

  • :enabled_sources - A map of %{atom => boolean} values to declare which source tags will be enabled when collecting sources. Defaults to the return value of default_enabled_sources/0.
  • :parser - The module to parse environment variables files. Defaults to Nvir.Parser.RDB.
  • :cd - A directory path to load relative source paths from.
  • :before_env_set - A function that accepts a {varname, value} tuple and must return a similar tuple. This gives the possibility to change or transform the parsed variables before the environment is altered. Returned varname and value must implement the String.Chars protocol. Returning nil as a value will delete the environment variable.

Example

Implement loading a custom :docs environment and load a file when running a release:

import Nvir

dotenv_loader()
|> dotenv_configure(
  enabled_sources: %{
    # Enable sources tagged with :docs depending on an environment variable
    docs: System.get_env("MIX_ENV") == "docs",

    # Enable sources tagged with :rel when running a release
    rel: env!("RELEASE_NAME", :boolean, false)
  },

  # Load dotenv files relative to this directory
  cd: "~/projects/apps/envs"
)
|> dotenv!(
  docs: ".env.docs",
  rel: "releases.env",
  dev: ".env.dev",
  test: ".env.test"
)

dotenv_enable_sources(nvir, enum)

Like dotenv_enable_sources/3 but accepts a keyword list or map of sources.

Nvir.dotenv_loader()
|> Nvir.dotenv_enable_source(
  custom: true,
  docs: config_env() == :docs
)
|> Nvir.dotenv!(["global.env", custom: "local.env", docs: "docs.env"])

dotenv_enable_sources(nvir, tag, enabled?)

Enables or disables environment variable sources under the given tag.

For instance, the following call will load both files:

Nvir.dotenv_loader()
|> Nvir.enable_sources(:custom, true)
|> Nvir.dotenv!(["global.env", custom: "local.env"])

Whereas the following call will only load files that are not wrapped in a tag.

Nvir.dotenv_loader()
|> Nvir.dotenv!(["global.env", custom: "local.env"])

It is also possible to disable some defaults by overriding them. In the following code, the .env.test file will never be loaded:

Nvir.dotenv_loader()
|> Nvir.enable_sources(:test, false)
|> Nvir.dotenv!(["global.env", dev: ".env.dev", test: ".env.test"])

dotenv_loader()

@spec dotenv_loader() :: t()

Returns the default configuration for the dotenv!/2 function.

Examples

Implement loading a custom :docs environment:

import Config
import Nvir

dotenv_loader()
|> enable_source(:docs, config_env() == :docs)
|> dotenv!(
  docs: ".env.docs",
  dev: ".env.dev",
  test: ".env.test"
)

dotenv_new()

@spec dotenv_new() :: t()

Returns a configuration for dotenv!/2 without any enabled source.

Generally this is used for custom loading strategies, see dotenv_loader/0 to use reasonable defaults.

env!(var, caster \\ :string)

Returns the value of the given var, transformed and validated by the given caster.

Raises if the variable is not defined or if the caster validation fails.

Please see the README for available casters.

env!(var, caster, default)

Returns the value of the given var, transformed and validated by the given caster.

Returns the default value if the variable is not defined.

Raises if the caster validation fails.

Please see the README for available casters.