-module(openfeature). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([shutdown/0, set_provider/1, get_provider_metadata/0, set_domain_provider/2, get_domain_provider_metadata/1, get_client/0, get_domain_client/1]). -export_type([api_message/0, api/0]). -type api_message() :: shutdown | {set_provider, gleam@erlang@process:subject({ok, nil} | {error, nil}), openfeature@domain:domain(), openfeature@provider:feature_provider()} | {get_provider, gleam@erlang@process:subject(openfeature@provider:feature_provider()), openfeature@domain:domain()} | {set_context, openfeature@evaluation_context:evaluation_context()} | {add_handler, openfeature@domain:domain(), fun((openfeature@events:event_details()) -> nil)} | {remove_handler, openfeature@domain:domain(), fun((openfeature@events:event_details()) -> nil)}. -type api() :: {api, gleam@dict:dict(openfeature@domain:domain(), openfeature@provider:feature_provider()), openfeature@evaluation_context:evaluation_context(), gleam@dict:dict(openfeature@domain:domain(), list(fun((openfeature@events:event_details()) -> nil)))}. -spec set_provider_internal( api(), gleam@erlang@process:subject({ok, nil} | {error, nil}), openfeature@domain:domain(), openfeature@provider:feature_provider() ) -> api(). set_provider_internal(State, Reply_with, Domain, Provider) -> Init_result = (erlang:element(2, Provider))(erlang:element(3, State)), gleam@otp@actor:send(Reply_with, Init_result), Provider_registry = begin _pipe = erlang:element(2, State), gleam@dict:insert(_pipe, Domain, Provider) end, {api, Provider_registry, erlang:element(3, State), erlang:element(4, State)}. -spec get_provider_internal( api(), gleam@erlang@process:subject(openfeature@provider:feature_provider()), openfeature@domain:domain() ) -> api(). get_provider_internal(State, Reply_with, Domain) -> _pipe = erlang:element(2, State), _pipe@1 = gleam@dict:get(_pipe, Domain), _pipe@2 = gleam@result:unwrap( _pipe@1, openfeature@providers@no_op:provider() ), gleam@otp@actor:send(Reply_with, _pipe@2), State. -spec set_context_internal( api(), openfeature@evaluation_context:evaluation_context() ) -> api(). set_context_internal(State, Evaluation_context) -> {api, erlang:element(2, State), Evaluation_context, erlang:element(4, State)}. -spec shutdown_internal(api()) -> nil. shutdown_internal(State) -> _pipe = erlang:element(2, State), _pipe@1 = gleam@dict:values(_pipe), gleam@list:each( _pipe@1, fun(Provider) -> (erlang:element(3, Provider))() end ). -spec add_handler_internal( api(), openfeature@domain:domain(), fun((openfeature@events:event_details()) -> nil) ) -> api(). add_handler_internal(State, Domain, Callback) -> Domain_callbacks = begin _pipe = erlang:element(4, State), _pipe@1 = gleam@dict:get(_pipe, Domain), _pipe@2 = gleam@result:unwrap(_pipe@1, []), gleam@list:prepend(_pipe@2, Callback) end, _pipe@3 = erlang:element(4, State), _pipe@4 = gleam@dict:insert(_pipe@3, Domain, Domain_callbacks), {api, erlang:element(2, State), erlang:element(3, State), _pipe@4}. -spec remove_handler_internal( api(), openfeature@domain:domain(), fun((openfeature@events:event_details()) -> nil) ) -> api(). remove_handler_internal(State, Domain, Callback) -> Domain_callbacks = begin _pipe = erlang:element(4, State), _pipe@1 = gleam@dict:get(_pipe, Domain), _pipe@2 = gleam@result:unwrap(_pipe@1, []), gleam@list:drop_while(_pipe@2, fun(X) -> X =:= Callback end) end, _pipe@3 = erlang:element(4, State), _pipe@4 = gleam@dict:insert(_pipe@3, Domain, Domain_callbacks), {api, erlang:element(2, State), erlang:element(3, State), _pipe@4}. -spec init_api() -> gleam@erlang@process:subject(api_message()). init_api() -> Initial_state = {api, gleam@dict:new(), openfeature@evaluation_context:empty(), gleam@dict:new()}, _assert_subject = gleam@otp@actor:start( Initial_state, fun(Message, State) -> case Message of shutdown -> shutdown_internal(State), {stop, normal}; {set_provider, Reply_with, Domain, Provider} -> _pipe = set_provider_internal( State, Reply_with, Domain, Provider ), gleam@otp@actor:continue(_pipe); {get_provider, Reply_with@1, Domain@1} -> _pipe@1 = get_provider_internal( State, Reply_with@1, Domain@1 ), gleam@otp@actor:continue(_pipe@1); {set_context, Evaluation_context} -> _pipe@2 = set_context_internal(State, Evaluation_context), gleam@otp@actor:continue(_pipe@2); {add_handler, Domain@2, Callback} -> _pipe@3 = add_handler_internal(State, Domain@2, Callback), gleam@otp@actor:continue(_pipe@3); {remove_handler, Domain@3, Callback@1} -> _pipe@4 = remove_handler_internal( State, Domain@3, Callback@1 ), gleam@otp@actor:continue(_pipe@4) end end ), {ok, Subject} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"openfeature"/utf8>>, function => <<"init_api"/utf8>>, line => 43}) end, Subject. -spec get_api_subject() -> gleam@erlang@process:subject(api_message()). get_api_subject() -> worm_ffi:persist(fun init_api/0). -spec shutdown() -> nil. shutdown() -> gleam@otp@actor:send(get_api_subject(), shutdown). -spec set_provider(openfeature@provider:feature_provider()) -> {ok, nil} | {error, nil}. set_provider(Provider) -> _pipe = gleam@erlang@process:try_call( get_api_subject(), fun(_capture) -> {set_provider, _capture, global, Provider} end, 10000 ), _pipe@1 = gleam@result:nil_error(_pipe), gleam@result:flatten(_pipe@1). -spec get_provider() -> openfeature@provider:feature_provider(). get_provider() -> gleam@otp@actor:call( get_api_subject(), fun(_capture) -> {get_provider, _capture, global} end, 10000 ). -spec get_provider_metadata() -> openfeature@provider:metadata(). get_provider_metadata() -> (erlang:element(4, get_provider()))(). -spec set_domain_provider(binary(), openfeature@provider:feature_provider()) -> nil. set_domain_provider(Domain, Provider) -> _pipe = gleam@otp@actor:call( get_api_subject(), fun(_capture) -> {set_provider, _capture, {scoped, Domain}, Provider} end, 10000 ), gleam@result:unwrap(_pipe, nil). -spec get_domain_provider(binary()) -> openfeature@provider:feature_provider(). get_domain_provider(Domain) -> gleam@otp@actor:call( get_api_subject(), fun(_capture) -> {get_provider, _capture, {scoped, Domain}} end, 10000 ). -spec get_domain_provider_metadata(binary()) -> openfeature@provider:metadata(). get_domain_provider_metadata(Domain) -> (erlang:element(4, get_domain_provider(Domain)))(). -spec get_client() -> openfeature@client:client(). get_client() -> {client, get_provider(), {client_metadata, global}, openfeature@evaluation_context:empty()}. -spec get_domain_client(binary()) -> openfeature@client:client(). get_domain_client(Domain) -> {client, get_domain_provider(Domain), {client_metadata, {scoped, Domain}}, openfeature@evaluation_context:empty()}.