-module(kv_sessions). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([get_session/1, delete_session/1, key/2, with_codec/3, get/1, set/2, delete/2, replace_session/3, middleware/3]). -export_type([current_session/0, session_key/1]). -type current_session() :: {current_session, gleam@http@request:request(wisp:connection()), kv_sessions@session_config:config()}. -type session_key(TSG) :: {session_key, current_session(), binary(), fun((gleam@dynamic:dynamic_()) -> {ok, TSG} | {error, list(gleam@dynamic:decode_error())}), fun((TSG) -> binary())}. -spec get_session_with_cache( kv_sessions@session:session_id(), kv_sessions@session_config:config(), boolean() ) -> {ok, gleam@option:option(kv_sessions@session:session())} | {error, kv_sessions@session:session_error()}. get_session_with_cache(Session_id, Config, Cache) -> case {Cache, erlang:element(5, Config)} of {true, {some, Cache@1}} -> case (erlang:element(2, Cache@1))(Session_id) of {ok, {some, Session}} -> {ok, {some, Session}}; _ -> get_session_with_cache(Session_id, Config, false) end; {_, _} -> (erlang:element(2, erlang:element(4, Config)))(Session_id) end. -spec save_session( kv_sessions@session_config:config(), kv_sessions@session:session() ) -> {ok, kv_sessions@session:session()} | {error, kv_sessions@session:session_error()}. save_session(Config, Session) -> _pipe = erlang:element(5, Config), gleam@option:map( _pipe, fun(Cache) -> (erlang:element(3, Cache))(Session) end ), (erlang:element(3, erlang:element(4, Config)))(Session). -spec get_session(current_session()) -> {ok, kv_sessions@session:session()} | {error, kv_sessions@session:session_error()}. get_session(Current_session) -> gleam@result:'try'( kv_sessions@internal@utils:get_session_id( erlang:element(3, erlang:element(3, Current_session)), erlang:element(2, Current_session) ), fun(Session_id) -> gleam@result:'try'( get_session_with_cache( Session_id, erlang:element(3, Current_session), true ), fun(Maybe_session) -> case Maybe_session of {some, Session} -> case kv_sessions@internal@utils:is_session_expired( Session ) of true -> {error, session_expired_error}; false -> {ok, Session} end; none -> Session@1 = begin _pipe = kv_sessions@session:builder(), _pipe@1 = kv_sessions@session:with_id( _pipe, Session_id ), _pipe@2 = kv_sessions@session:with_expiry( _pipe@1, erlang:element( 2, erlang:element(3, Current_session) ) ), kv_sessions@session:build(_pipe@2) end, save_session( erlang:element(3, Current_session), Session@1 ) end end ) end ). -spec delete_session(current_session()) -> {ok, nil} | {error, kv_sessions@session:session_error()}. delete_session(Current_session) -> {current_session, Req, Config} = Current_session, gleam@result:'try'( kv_sessions@internal@utils:get_session_id( erlang:element(3, Config), Req ), fun(Session_id) -> _pipe = erlang:element(5, Config), gleam@option:map( _pipe, fun(Cache) -> (erlang:element(4, Cache))(Session_id) end ), (erlang:element(4, erlang:element(4, Config)))(Session_id) end ). -spec key(current_session(), binary()) -> session_key(binary()). key(Current_session, Key) -> {session_key, Current_session, Key, fun gleam@dynamic:string/1, fun(Str) -> _pipe = gleam@json:string(Str), gleam@json:to_string(_pipe) end}. -spec with_codec( session_key(any()), fun((gleam@dynamic:dynamic_()) -> {ok, TSO} | {error, list(gleam@dynamic:decode_error())}), fun((TSO) -> binary()) ) -> session_key(TSO). with_codec(Session_key, Decode, Encode) -> {session_key, erlang:element(2, Session_key), erlang:element(3, Session_key), Decode, Encode}. -spec get(session_key(TSR)) -> {ok, gleam@option:option(TSR)} | {error, kv_sessions@session:session_error()}. get(Entry) -> gleam@result:'try'( get_session(erlang:element(2, Entry)), fun(Session) -> case begin _pipe = gleam@dict:get( erlang:element(4, Session), erlang:element(3, Entry) ), gleam@option:from_result(_pipe) end of none -> {ok, none}; {some, Data} -> _pipe@1 = gleam@json:decode(Data, erlang:element(4, Entry)), _pipe@2 = gleam@result:replace_error(_pipe@1, decode_error), gleam@result:map(_pipe@2, fun(D) -> {some, D} end) end end ). -spec set(session_key(TSU), TSU) -> {ok, TSU} | {error, kv_sessions@session:session_error()}. set(Entry, Data) -> gleam@result:'try'( get_session(erlang:element(2, Entry)), fun(Session) -> Session@1 = begin _pipe = kv_sessions@session:builder_from(Session), _pipe@1 = kv_sessions@session:with_entry( _pipe, erlang:element(3, Entry), (erlang:element(5, Entry))(Data) ), kv_sessions@session:build(_pipe@1) end, gleam@result:map( save_session( erlang:element(3, erlang:element(2, Entry)), Session@1 ), fun(_) -> Data end ) end ). -spec delete(current_session(), binary()) -> {ok, kv_sessions@session:session()} | {error, kv_sessions@session:session_error()}. delete(Current_session, Key) -> {current_session, _, Config} = Current_session, gleam@result:'try'( get_session(Current_session), fun(Session) -> save_session( Config, erlang:setelement( 4, Session, gleam@dict:delete(erlang:element(4, Session), Key) ) ) end ). -spec replace_session( current_session(), gleam@http@response:response(wisp:body()), kv_sessions@session:session() ) -> {ok, gleam@http@response:response(wisp:body())} | {error, kv_sessions@session:session_error()}. replace_session(Current_session, Res, New_session) -> {current_session, Req, Config} = Current_session, gleam@result:'try'( delete_session(Current_session), fun(_) -> gleam@result:map( save_session(Config, New_session), fun(_) -> kv_sessions@internal@utils:set_session_cookie( erlang:element(3, Config), Res, Req, New_session ) end ) end ). -spec middleware( gleam@http@request:request(wisp:connection()), kv_sessions@session_config:config(), fun((gleam@http@request:request(wisp:connection())) -> gleam@http@response:response(wisp:body())) ) -> gleam@http@response:response(wisp:body()). middleware(Req, Config, Handle_request) -> case kv_sessions@internal@utils:get_session_id( erlang:element(3, Config), Req ) of {ok, _} -> Handle_request(Req); {error, _} -> Session = begin _pipe = kv_sessions@session:builder(), _pipe@1 = kv_sessions@session:with_expiry( _pipe, erlang:element(2, Config) ), kv_sessions@session:build(_pipe@1) end, _ = (erlang:element(3, erlang:element(4, Config)))(Session), Res = begin _pipe@2 = kv_sessions@internal@utils:inject_session_cookie( erlang:element(3, Config), Req, erlang:element(2, Session), signed ), Handle_request(_pipe@2) end, _pipe@3 = Res, _pipe@4 = gleam@http@response:get_cookies(_pipe@3), _pipe@5 = gleam@list:key_find(_pipe@4, erlang:element(3, Config)), (fun(Cookie) -> case Cookie of {ok, _} -> Res; {error, _} -> kv_sessions@internal@utils:set_session_cookie( erlang:element(3, Config), Res, Req, Session ) end end)(_pipe@5) end.