Skip to main content

src/aws@region.erl

-module(aws@region).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/aws/region.gleam").
-export([resolve_with/3, resolve/1]).
-export_type([resolve_error/0]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

?MODULEDOC(
    " Region resolution.\n"
    "\n"
    " Precedence (matches go-v2 / Rust SDK):\n"
    "\n"
    "   1. `AWS_REGION` environment variable\n"
    "   2. `AWS_DEFAULT_REGION` environment variable\n"
    "   3. `region` setting in `~/.aws/config` under the active profile\n"
    "\n"
    " Resolution from EC2 IMDS is not implemented — most workloads set\n"
    " `AWS_REGION` explicitly, and the few that rely on IMDS region\n"
    " auto-detection can call `from_imds` themselves and feed the result in.\n"
).

-type resolve_error() :: {no_region, list(binary())}.

-file("src/aws/region.gleam", 107).
-spec read_default_config() -> {ok, binary()} | {error, nil}.
read_default_config() ->
    gleam@result:'try'(
        aws_ffi:get_env(<<"HOME"/utf8>>),
        fun(Home) ->
            gleam@result:'try'(
                aws_ffi:read_file(<<Home/binary, "/.aws/config"/utf8>>),
                fun(Bits) -> _pipe = gleam@bit_array:to_string(Bits),
                    gleam@result:replace_error(_pipe, nil) end
            )
        end
    ).

-file("src/aws/region.gleam", 81).
-spec non_empty({ok, binary()} | {error, any()}) -> gleam@option:option(binary()).
non_empty(Result) ->
    case Result of
        {ok, S} ->
            case S of
                <<""/utf8>> ->
                    none;

                _ ->
                    {some, S}
            end;

        {error, _} ->
            none
    end.

-file("src/aws/region.gleam", 92).
-spec option_try(
    {ok, LWU} | {error, any()},
    fun((LWU) -> gleam@option:option(LWY))
) -> gleam@option:option(LWY).
option_try(Result, Next) ->
    case Result of
        {ok, Value} ->
            Next(Value);

        {error, _} ->
            none
    end.

-file("src/aws/region.gleam", 68).
-spec try_config(fun(() -> {ok, binary()} | {error, nil}), binary()) -> gleam@option:option(binary()).
try_config(Config_reader, Profile) ->
    option_try(
        Config_reader(),
        fun(Text) ->
            option_try(
                aws@internal@ini:parse(Text),
                fun(Parsed) ->
                    Section = case Profile of
                        <<"default"/utf8>> ->
                            <<"default"/utf8>>;

                        Other ->
                            <<"profile "/utf8, Other/binary>>
                    end,
                    non_empty(
                        aws@internal@ini:get_property(
                            Parsed,
                            Section,
                            <<"region"/utf8>>
                        )
                    )
                end
            )
        end
    ).

-file("src/aws/region.gleam", 61).
-spec try_env(fun((binary()) -> {ok, binary()} | {error, nil})) -> gleam@option:option(binary()).
try_env(Lookup) ->
    case non_empty(Lookup(<<"AWS_REGION"/utf8>>)) of
        {some, R} ->
            {some, R};

        none ->
            non_empty(Lookup(<<"AWS_DEFAULT_REGION"/utf8>>))
    end.

-file("src/aws/region.gleam", 39).
?DOC(
    " Resolve a region with injectable env and config-file access — used by\n"
    " tests, and available to callers that want to feed in their own sources.\n"
).
-spec resolve_with(
    binary(),
    fun((binary()) -> {ok, binary()} | {error, nil}),
    fun(() -> {ok, binary()} | {error, nil})
) -> {ok, binary()} | {error, resolve_error()}.
resolve_with(Profile, Env_lookup, Config_reader) ->
    case try_env(Env_lookup) of
        {some, Region} ->
            {ok, Region};

        none ->
            case try_config(Config_reader, Profile) of
                {some, Region@1} ->
                    {ok, Region@1};

                none ->
                    {error,
                        {no_region,
                            [<<"AWS_REGION"/utf8>>,
                                <<"AWS_DEFAULT_REGION"/utf8>>,
                                <<<<"~/.aws/config[profile="/utf8,
                                        Profile/binary>>/binary,
                                    "].region"/utf8>>]}}
            end
    end.

-file("src/aws/region.gleam", 29).
?DOC(
    " Resolve a region using the real OS env and `~/.aws/config`. Standard\n"
    " production wiring.\n"
).
-spec resolve(binary()) -> {ok, binary()} | {error, resolve_error()}.
resolve(Profile) ->
    resolve_with(Profile, fun aws_ffi:get_env/1, fun read_default_config/0).