Current section
Files
Jump to
Current section
Files
lib/hellosign_ex/config.ex
# MIT License
# Copyright (c) 2024 Aqdas Malik
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
defmodule Hellosign.Config do
@moduledoc """
Reads configuration on application start, parses all environment variables (if any)
and caches the final config in memory to avoid parsing on each read afterwards.
"""
@type t :: %__MODULE__{
api_key: String.t() | nil,
client_id: String.t() | nil,
test_mode: String.t() | nil,
api_url: String.t() | nil,
default_cc: String.t() | nil
}
defstruct api_key: nil,
client_id: nil,
test_mode: nil,
api_url: nil,
default_cc: nil
use GenServer
@hellosign_url "https://api.hellosign.com/v3"
@config_keys [
:api_key,
:client_id,
:test_mode,
:default_cc
]
def start_link(opts), do: GenServer.start_link(__MODULE__, opts, name: __MODULE__)
@impl true
def init(_opts) do
config =
@config_keys
|> Enum.map(fn key -> {key, get_config_value(key)} end)
|> Map.new()
{:ok, config}
end
# API Key
def api_key, do: get_config_value(:api_key)
def client_id, do: get_config_value(:client_id)
def test_mode, do: get_config_value(:test_mode, "false")
def default_cc, do: get_config_value(:default_cc)
# API Url
def api_url, do: get_config_value(:api_url, @hellosign_url)
defp get_config_value(key, default \\ nil) do
value =
:hellosign
|> Application.get_env(key)
|> parse_config_value()
if is_nil(value), do: default, else: value
end
defp parse_config_value({:system, env_name}), do: fetch_env!(env_name)
defp parse_config_value({:system, :integer, env_name}) do
env_name
|> fetch_env!()
|> String.to_integer()
end
defp parse_config_value(value), do: value
# System.fetch_env!/1 support for older versions of Elixir
defp fetch_env!(env_name) do
case System.get_env(env_name) do
nil ->
raise ArgumentError,
message: "could not fetch environment variable \"#{env_name}\" because it is not set"
value ->
value
end
end
def get(key), do: GenServer.call(__MODULE__, {:get, key})
@impl true
def handle_call({:get, key}, _from, state) do
{:reply, Map.get(state, key), state}
end
@impl true
def handle_call({:put, key, value}, _from, state) do
{:reply, value, Map.put(state, key, value)}
end
end