/
binding.ex
77 lines (62 loc) · 1.57 KB
/
binding.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
defmodule Skogsra.Binding do
@moduledoc """
Variable binding behaviour.
"""
alias Skogsra.Env
alias Skogsra.Type
require Logger
@doc """
Callback for initializing binding.
"""
@callback init(env :: Env.t()) ::
{:ok, term()} | {:error, term()}
@doc """
Callback for getting an environment variable.
"""
@callback get_env(env :: Env.t(), config :: term()) ::
{:ok, term()} | {:error, term()}
@doc """
Uses the `Skogsra.Binding` behaviour.
"""
defmacro __using__(_) do
quote do
@behaviour Skogsra.Binding
@impl Skogsra.Binding
def init(_env) do
{:ok, nil}
end
defoverridable init: 1
end
end
@spec get_env(Env.binding(), env :: Env.t()) :: term()
def get_env(:system, %Env{} = env), do: get_env(Skogsra.Sys, env)
def get_env(:config, %Env{} = env), do: get_env(Skogsra.App, env)
def get_env(module, %Env{} = env) do
with {:ok, config} <- module.init(env),
{:ok, value} <- module.get_env(env, config) do
cast(module, env, value)
else
{:error, reason} ->
Logger.warning(reason)
nil
_ ->
nil
end
end
#########
# Helpers
@spec cast(module(), Env.t(), term()) :: nil | term()
defp cast(module, env, value) do
case Type.cast(env, value) do
{:ok, value} ->
value
:error ->
reason = """
Cannot cast #{inspect(value)} for environment variable #{inspect(env)}
Module: #{inspect(module)})
"""
Logger.warning(reason)
nil
end
end
end