-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
resolver.ex
69 lines (58 loc) · 2.03 KB
/
resolver.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
defmodule Hush.Resolver do
@moduledoc """
Replace configuration sugin provider-aware resolvers.
"""
alias Hush.{Cast, Provider}
@doc """
Substitute {:hush, Hush.Provider, "key", [options]} present in the the config argument.
"""
@spec resolve(Keyword.t()) :: {:ok, Keyword.t()} | {:error, any()}
def resolve(config) do
try do
{:ok, resolve!(config)}
rescue
err -> {:error, err}
end
end
@doc """
Substitute {:hush, Hush.Provider, "key", [options]} present in the the config argument
"""
@spec resolve!(Keyword.t() | map) :: Keyword.t()
def resolve!(config) do
Enum.reduce(config, [], fn
{key, {:hush, provider, name}}, acc ->
acc ++ [{key, resolve_value!(key, provider, name, [])}]
{key, {:hush, provider, name, options}}, acc ->
acc ++ [{key, resolve_value!(key, provider, name, options)}]
{key, rest = [_ | _]}, acc ->
acc ++ [{key, rest |> resolve!()}]
{key, rest = %{}}, acc ->
acc ++ [{key, rest |> resolve!() |> Map.new()}]
other, acc ->
acc ++ [other]
end)
end
@spec resolve_value!(String.t(), module(), String.t(), Keyword.t()) :: any()
defp resolve_value!(key, provider, name, options) do
type = Keyword.get(options, :cast, :string)
with {:ok, value} <- Provider.fetch(provider, name, options),
{:ok, value} <- Cast.to(type, value) do
value
else
{:error, :required} ->
raise ArgumentError,
message:
"Could not resolve '#{key}'. I was trying to evaluate '#{name}' with #{provider}. If this is an optional key, you add `optional: true` to the options list."
{:error, :cast} ->
raise ArgumentError,
message:
"Although I was able to resolve configuration '#{key}', I wasn't able to cast it to type '#{
type
}'."
{:error, error} ->
raise RuntimeError,
message:
"An error occured while trying to resolve value in provider: #{provider}.\n#{error}"
end
end
end