/dotenv_config_erlang

Erlang apps config based on environment variables and .env files

Primary LanguageErlangApache License 2.0Apache-2.0

Dotenv Config

Erlang/Elixir apps config based on environment variables and .env files

Usage

Erlang

At the start of your application, load the .env files (later files will overwrite the previous ones values). Environment variables will overwrite the .env files values.

dotenv_config:init(parser_module, ["path/to/.env"]).

Library can also load the .env files from the environment variable DOTENV_CONFIG_ENV_FILES. Hence you need to provide module name only.

dotenv_config:init(parser_module).

If .env files are not provided, the library will load the environment variables only.

parser_module is a module that implements the dotenv_config_parser behaviour. It should have a get_parser/0 function that returns a list of {ConfigItemName, ConfigItemType} tuples. See the parser_module example below.

Get the config value:

<<"some_client_id">> = dotenv_config:get(<<"CLIENT_ID">>).
{ok, <<"some_client_id">>} = dotenv_config:fetch(<<"CLIENT_ID">>).

Set the config value:

dotenv_config:set(<<"CLIENT_ID">>, <<"new_client_id">>).

Get all the config values:

dotenv_config:get_all().

parser_module example

-module(client_config_example).
-behaviour(dotenv_config_parser).

-export([get_parser/0]).

get_parser() ->
    [
        {<<"CLIENT_ID">>, str},
        {<<"PORT">>, int},
        {<<"DEBUG">>, bool},
        {<<"NAMES">>, json},
        {<<"LOG_LEVEL">>, atom},
        {<<"CALLBACK_MODULE">>, module},
        {<<"CHARLIST">>, charlist},
        {<<"SOME_LIST_MODE">>, [{exact, <<"allowlist">>}, {exact, <<"blocklist">>}]},
        {<<"SOME_CALL_TIMEOUT">>, [{exact, <<"infinity">>}, int]},
        {<<"SOME_COMPLEX_TYPE">>, fun (RawValue) -> <<RawValue/binary, "_42">> end}
    ].

json type would be parsed to list or map using jiffy:decode(RawValue, [return_maps]).

module type would be checked for existence.

Elixir

Please read Erlang section also for better understanding.

runtime.exs

import Config

files = ["config/.env.default", "config/.env"] |> Enum.filter(&File.exists?/1)
:dotenv_config.init(MyApp.Config, files)

config :ex_gram, token: :dotenv_config.get("MYAPP_BOT_TOKEN")

config :my_app, :bot_token, :dotenv_config.get("MYAPP_BOT_TOKEN")

config :my_app, :download_path, :dotenv_config.get("MYAPP_DOWNLOAD_DIR_PATH")

config :my_app,
       :max_file_size_to_send_to_telegram,
       :dotenv_config.get("MYAPP_MAX_FILE_SIZE_TO_SEND_TO_TELEGRAM")

config :my_app,
       :max_video_size_to_send_to_telegram,
       :dotenv_config.get("MYAPP_MAX_VIDEO_SIZE_TO_SEND_TO_TELEGRAM")

config :my_app,
       :max_audio_size_to_send_to_telegram,
       :dotenv_config.get("MYAPP_MAX_AUDIO_SIZE_TO_SEND_TO_TELEGRAM")

config :my_app,
       :max_file_size_to_compress,
       :dotenv_config.get("MYAPP_MAX_FILE_SIZE_TO_COMPRESS")

config :my_app,
       :max_duration_to_compress,
       :dotenv_config.get("MYAPP_MAX_DURATION_TO_COMPRESS")

config :my_app,
       :allowed_urls_regex,
       :dotenv_config.get("MYAPP_ALLOWED_URLS_REGEX")

:dotenv_config.stop()

Parser module example

defmodule MyApp.Config do
  @moduledoc """
  This module is responsible for providing configuration parser for the dotenv_config library.
  """
  @behaviour :dotenv_config_parser

  @impl true
  @spec get_parser() :: :dotenv_config.parser()
  def get_parser() do
    [
      {"MYAPP_BOT_TOKEN", :str},
      {"MYAPP_DOWNLOAD_DIR_PATH", :str},
      {"MYAPP_MAX_FILE_SIZE_TO_SEND_TO_TELEGRAM", :int},
      {"MYAPP_MAX_VIDEO_SIZE_TO_SEND_TO_TELEGRAM", :int},
      {"MYAPP_MAX_AUDIO_SIZE_TO_SEND_TO_TELEGRAM", :int},
      {"MYAPP_MAX_FILE_SIZE_TO_COMPRESS", :int},
      {"MYAPP_MAX_DURATION_TO_COMPRESS", :int},
      {"MYAPP_ALLOWED_URLS_REGEX", :str}
    ]
  end
end