Packages

A type-safe configuration loader for Gleam that supports JSON, YAML, and TOML with automatic format detection, environment variable resolution, and profile-based configuration.

Current section

Files

Jump to
yodel src yodel@resolver.erl
Raw

src/yodel@resolver.erl

-module(yodel@resolver).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([resolve_placeholders/2]).
-export_type([placeholder/0]).
-type placeholder() :: {placeholder,
binary(),
binary(),
gleam@option:option(binary())}.
-file("src/yodel/resolver.gleam", 65).
-spec find_next_placeholder(binary(), gleam@regexp:regexp()) -> gleam@option:option(placeholder()).
find_next_placeholder(Value, Pattern) ->
case gleam@regexp:scan(Pattern, Value) of
[] ->
none;
[Match | _] ->
case erlang:element(3, Match) of
[{some, Env_var}, Default] ->
{some,
{placeholder,
erlang:element(2, Match),
Env_var,
Default}};
[{some, Env_var@1}] ->
{some,
{placeholder, erlang:element(2, Match), Env_var@1, none}};
_ ->
none
end
end.
-file("src/yodel/resolver.gleam", 79).
-spec resolve_placeholder(placeholder(), yodel@options:resolve_mode()) -> {ok,
binary()} |
{error, yodel@errors:config_error()}.
resolve_placeholder(Placeholder, Mode) ->
case envoy_ffi:get(erlang:element(3, Placeholder)) of
{ok, Value} ->
{ok, Value};
{error, _} ->
case {erlang:element(4, Placeholder), Mode} of
{{some, Default_value}, _} ->
{ok, Default_value};
{none, lenient} ->
{ok, erlang:element(2, Placeholder)};
{none, strict} ->
{error,
{resolver_error,
{unresolved_placeholder,
erlang:element(3, Placeholder),
erlang:element(2, Placeholder)}}}
end
end.
-file("src/yodel/resolver.gleam", 31).
-spec resolve_value(
binary(),
gleam@regexp:regexp(),
yodel@options:resolve_mode(),
list(binary())
) -> {ok, binary()} | {error, yodel@errors:config_error()}.
resolve_value(Value, Pattern, Mode, Attempted) ->
case find_next_placeholder(Value, Pattern) of
none ->
{ok, Value};
{some, Placeholder} ->
case gleam@list:contains(Attempted, erlang:element(3, Placeholder)) of
true ->
case Mode of
lenient ->
{ok, Value};
strict ->
{error,
{resolver_error,
{unresolved_placeholder,
erlang:element(3, Placeholder),
erlang:element(2, Placeholder)}}}
end;
false ->
gleam@result:'try'(
resolve_placeholder(Placeholder, Mode),
fun(Resolved) ->
Updated = gleam@string:replace(
Value,
erlang:element(2, Placeholder),
Resolved
),
resolve_value(
Updated,
Pattern,
Mode,
[erlang:element(3, Placeholder) | Attempted]
)
end
)
end
end.
-file("src/yodel/resolver.gleam", 104).
-spec map_compile_error(gleam@regexp:compile_error()) -> yodel@errors:config_error().
map_compile_error(Error) ->
{resolver_error,
{regex_error,
<<<<(erlang:element(2, Error))/binary, " at "/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(3, Error)))/binary>>}}.
-file("src/yodel/resolver.gleam", 100).
-spec compile_placeholder_regex() -> {ok, gleam@regexp:regexp()} |
{error, yodel@errors:config_error()}.
compile_placeholder_regex() ->
_pipe = gleam@regexp:from_string(
<<"\\$\\{([^:}]+)(?::((?:[^${}]+|\\$\\{(?:[^{}]*\\{[^{}]*\\})*[^{}]*\\})*))?\\}"/utf8>>
),
gleam@result:map_error(_pipe, fun map_compile_error/1).
-file("src/yodel/resolver.gleam", 19).
-spec resolve_placeholders(binary(), yodel@options:options()) -> {ok, binary()} |
{error, yodel@errors:config_error()}.
resolve_placeholders(Input, Options) ->
gleam@result:'try'(
compile_placeholder_regex(),
fun(Pattern) ->
case resolve_value(
Input,
Pattern,
yodel@options:get_resolve_mode(Options),
[]
) of
{ok, Resolved_value} ->
{ok, Resolved_value};
{error, E} ->
{error, E}
end
end
).