-module(rally_runtime@effect).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/rally_runtime/effect.gleam").
-export([none/0, from/1, send_to_server/1, rpc/2, get_ws_page/0, send_to_client/1, broadcast_to_page/1, broadcast_to_app/1, send_to_client_context/1, navigate/1, set_dark_mode/1, set_lang/1, read_dark_mode/0, read_lang/0, get_ws_session/0, broadcast_to_session/1, put_ws_state/3, get_stored_server_context/0, get_ws_conn/0, drain_outgoing_frames/0, put_ws_session/1, decode_rally_push/1, decode_rally_push_json/1, put_ws_identity/1, get_ws_identity/0, put_ws_hostname/1, get_ws_hostname/0, put_ws_auth_timestamp/1, get_ws_auth_timestamp/0, clear_ws_auth_state/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(
" The API that page modules import for server communication, broadcast,\n"
" and navigation.\n"
"\n"
" This module has a split personality by design. Each function has two\n"
" implementations: the server-side version here (which queues push frames\n"
" via the process dictionary or is a no-op), and a client-side version\n"
" in the generated rally_runtime/effect.gleam shim (which calls the\n"
" browser WebSocket transport). The codegen rewrites imports so the\n"
" client package uses the shim, not this file.\n"
"\n"
" Two server communication models:\n"
"\n"
" rpc(msg, on_response:) Stateless request-response. Define a\n"
" ServerX message type and server_x handler.\n"
" Client sends, server returns a value.\n"
" Use this by default.\n"
"\n"
" send_to_server(msg) Stateful bidirectional. Define ToServer/\n"
" ToClient types and server_init/server_update.\n"
" Server keeps a ServerModel per connection\n"
" and can push ToClient messages any time.\n"
" Use when the server needs state between calls.\n"
).
-file("src/rally_runtime/effect.gleam", 30).
-spec none() -> lustre@effect:effect(any()).
none() ->
lustre@effect:none().
-file("src/rally_runtime/effect.gleam", 34).
-spec from(fun((fun((ALBJ) -> nil)) -> nil)) -> lustre@effect:effect(ALBJ).
from(F) ->
lustre@effect:from(F).
-file("src/rally_runtime/effect.gleam", 42).
?DOC(
" Send a ToServer variant to the server over WebSocket.\n"
" Part of the stateful model (ToServer/ToClient/ServerModel).\n"
" On the server this is a no-op. On the client, the generated\n"
" transport module provides the real implementation.\n"
).
-spec send_to_server(any()) -> lustre@effect:effect(any()).
send_to_server(_) ->
lustre@effect:none().
-file("src/rally_runtime/effect.gleam", 50).
?DOC(
" Call a server_* RPC handler and deliver the return value to on_response.\n"
" Part of the stateless RPC model (ServerX type + server_x function).\n"
" On the server this is a no-op. On the client, the generated transport\n"
" module encodes the message and sends it over WebSocket.\n"
).
-spec rpc(any(), fun((any()) -> ALBQ)) -> lustre@effect:effect(ALBQ).
rpc(_, _) ->
lustre@effect:none().
-file("src/rally_runtime/effect.gleam", 166).
?DOC(" Get the current page name for this WS connection.\n").
-spec get_ws_page() -> binary().
get_ws_page() ->
rally_runtime_ffi:get_ws_page().
-file("src/rally_runtime/effect.gleam", 141).
-spec do_push(any()) -> nil.
do_push(Msg) ->
Page = rally_runtime_ffi:get_ws_page(),
Frame = rally_runtime_ffi:encode_push_frame(Page, Msg),
rally_runtime_ffi:push_outgoing_frame(Frame).
-file("src/rally_runtime/effect.gleam", 57).
?DOC(
" Send a ToClient variant to the connected client.\n"
" Encodes the message as a protocol-specific push frame and queues it for\n"
" the WebSocket handler to send after the current dispatch.\n"
).
-spec send_to_client(any()) -> lustre@effect:effect(any()).
send_to_client(Msg) ->
do_push(Msg),
lustre@effect:none().
-file("src/rally_runtime/effect.gleam", 65).
?DOC(
" Broadcast a message to all connections viewing the current page.\n"
" Broadcasts via pg topics for other connections, plus push_outgoing_frame\n"
" for the sender's own connection (which isn't subscribed to its own topic).\n"
).
-spec broadcast_to_page(any()) -> lustre@effect:effect(any()).
broadcast_to_page(Msg) ->
Page = rally_runtime_ffi:get_ws_page(),
Frame = rally_runtime_ffi:encode_push_frame(Page, Msg),
rally_runtime_topics_ffi:broadcast(<<"page:"/utf8, Page/binary>>, Frame),
rally_runtime_ffi:push_outgoing_frame(Frame),
lustre@effect:none().
-file("src/rally_runtime/effect.gleam", 74).
?DOC(" Broadcast a message to every connection in the app.\n").
-spec broadcast_to_app(any()) -> lustre@effect:effect(any()).
broadcast_to_app(Msg) ->
Page = rally_runtime_ffi:get_ws_page(),
Frame = rally_runtime_ffi:encode_push_frame(Page, Msg),
rally_runtime_topics_ffi:broadcast(<<"app"/utf8>>, Frame),
rally_runtime_ffi:push_outgoing_frame(Frame),
lustre@effect:none().
-file("src/rally_runtime/effect.gleam", 85).
?DOC(
" Send a ClientContextMsg to update the client's shared context.\n"
" On the server, encodes and queues a push frame tagged \"__ClientContext__\".\n"
" On the client, the generated app dispatches it through client_context.update.\n"
).
-spec send_to_client_context(any()) -> lustre@effect:effect(any()).
send_to_client_context(Msg) ->
Frame = rally_runtime_ffi:encode_push_frame(
<<"__ClientContext__"/utf8>>,
Msg
),
rally_runtime_ffi:push_outgoing_frame(Frame),
lustre@effect:none().
-file("src/rally_runtime/effect.gleam", 102).
-spec do_navigate(binary()) -> nil.
do_navigate(_) ->
nil.
-file("src/rally_runtime/effect.gleam", 94).
?DOC(
" Navigate to a new URL path. Pushes a new history entry and triggers\n"
" a route change via modem's popstate listener.\n"
" On the server, this is a no-op.\n"
).
-spec navigate(binary()) -> lustre@effect:effect(any()).
navigate(Path) ->
lustre@effect:from(
fun(_) ->
nil = do_navigate(Path),
nil
end
).
-file("src/rally_runtime/effect.gleam", 108).
?DOC(
" Toggle dark mode. On the client, sets the cookie and toggles the class.\n"
" On the server, this is a no-op.\n"
).
-spec set_dark_mode(boolean()) -> lustre@effect:effect(any()).
set_dark_mode(_) ->
lustre@effect:none().
-file("src/rally_runtime/effect.gleam", 114).
?DOC(
" Set the language preference cookie.\n"
" On the server, this is a no-op.\n"
).
-spec set_lang(binary()) -> lustre@effect:effect(any()).
set_lang(_) ->
lustre@effect:none().
-file("src/rally_runtime/effect.gleam", 121).
?DOC(
" Read the dark mode preference from the cookie.\n"
" Falls back to prefers-color-scheme media query.\n"
" On the server, returns False.\n"
).
-spec read_dark_mode() -> boolean().
read_dark_mode() ->
false.
-file("src/rally_runtime/effect.gleam", 127).
?DOC(
" Read the language preference from the cookie.\n"
" On the server, returns \"en\".\n"
).
-spec read_lang() -> binary().
read_lang() ->
<<"en"/utf8>>.
-file("src/rally_runtime/effect.gleam", 201).
?DOC(" Get the session ID for the current WS connection.\n").
-spec get_ws_session() -> binary().
get_ws_session() ->
rally_runtime_ffi:get_ws_session().
-file("src/rally_runtime/effect.gleam", 132).
?DOC(" Broadcast a message to all connections in the current browser session.\n").
-spec broadcast_to_session(any()) -> lustre@effect:effect(any()).
broadcast_to_session(Msg) ->
Page = rally_runtime_ffi:get_ws_page(),
Session = rally_runtime_ffi:get_ws_session(),
Frame = rally_runtime_ffi:encode_push_frame(Page, Msg),
rally_runtime_topics_ffi:broadcast(
<<"session:"/utf8, Session/binary>>,
Frame
),
rally_runtime_ffi:push_outgoing_frame(Frame),
lustre@effect:none().
-file("src/rally_runtime/effect.gleam", 154).
?DOC(" Store the WS connection handle, server context, and current page name.\n").
-spec put_ws_state(any(), any(), binary()) -> nil.
put_ws_state(_conn, _server_context, _page) ->
rally_runtime_ffi:put_ws_state(_conn, _server_context, _page).
-file("src/rally_runtime/effect.gleam", 160).
?DOC(" Retrieve the server context stored on the current WS process.\n").
-spec get_stored_server_context() -> {ok, any()} | {error, nil}.
get_stored_server_context() ->
rally_runtime_ffi:get_stored_server_context().
-file("src/rally_runtime/effect.gleam", 172).
?DOC(" Get the mist connection handle for this WS process.\n").
-spec get_ws_conn() -> {ok, any()} | {error, nil}.
get_ws_conn() ->
rally_runtime_ffi:get_ws_conn().
-file("src/rally_runtime/effect.gleam", 187).
?DOC(" Drain all queued push frames. Called by the WS handler after dispatch.\n").
-spec drain_outgoing_frames() -> list(any()).
drain_outgoing_frames() ->
rally_runtime_ffi:drain_outgoing_frames().
-file("src/rally_runtime/effect.gleam", 195).
?DOC(" Store the session ID on the current WS process.\n").
-spec put_ws_session(binary()) -> nil.
put_ws_session(_session_id) ->
rally_runtime_ffi:put_ws_session(_session_id).
-file("src/rally_runtime/effect.gleam", 209).
?DOC(" Decode an inbound push frame (ETF protocol).\n").
-spec decode_rally_push(any()) -> {ok, bitstring()} | {error, nil}.
decode_rally_push(_msg) ->
rally_runtime_ffi:decode_rally_push(_msg).
-file("src/rally_runtime/effect.gleam", 215).
?DOC(" Decode an inbound push frame (JSON protocol).\n").
-spec decode_rally_push_json(any()) -> {ok, binary()} | {error, nil}.
decode_rally_push_json(_msg) ->
rally_runtime_ffi:decode_rally_push_json(_msg).
-file("src/rally_runtime/effect.gleam", 230).
?DOC(
" Store the resolved identity on the WebSocket connection process.\n"
" The identity type is opaque to Rally; it's stored as an Erlang term.\n"
).
-spec put_ws_identity(any()) -> nil.
put_ws_identity(_identity) ->
rally_runtime_ffi:put_ws_identity(_identity).
-file("src/rally_runtime/effect.gleam", 237).
?DOC(
" Retrieve the stored identity. Returns Error(Nil) when no identity\n"
" has been stored (fresh process or pre-auth connection).\n"
).
-spec get_ws_identity() -> {ok, any()} | {error, nil}.
get_ws_identity() ->
rally_runtime_ffi:get_ws_identity().
-file("src/rally_runtime/effect.gleam", 243).
?DOC(" Store the hostname extracted during WebSocket upgrade.\n").
-spec put_ws_hostname(binary()) -> nil.
put_ws_hostname(_hostname) ->
rally_runtime_ffi:put_ws_hostname(_hostname).
-file("src/rally_runtime/effect.gleam", 249).
?DOC(" Retrieve the stored hostname. Returns \"\" when not set.\n").
-spec get_ws_hostname() -> binary().
get_ws_hostname() ->
rally_runtime_ffi:get_ws_hostname().
-file("src/rally_runtime/effect.gleam", 255).
?DOC(" Store the Unix timestamp of the last successful auth check.\n").
-spec put_ws_auth_timestamp(integer()) -> nil.
put_ws_auth_timestamp(_ts) ->
rally_runtime_ffi:put_ws_auth_timestamp(_ts).
-file("src/rally_runtime/effect.gleam", 262).
?DOC(
" Retrieve the auth timestamp. Returns 0 when not set (0 = never authed,\n"
" triggers immediate reauth on first RPC).\n"
).
-spec get_ws_auth_timestamp() -> integer().
get_ws_auth_timestamp() ->
rally_runtime_ffi:get_ws_auth_timestamp().
-file("src/rally_runtime/effect.gleam", 269).
?DOC(
" Clear identity and reset timestamp to 0. Hostname is preserved\n"
" (connection-scoped, not auth-scoped). Used during reauth and in tests.\n"
).
-spec clear_ws_auth_state() -> nil.
clear_ws_auth_state() ->
rally_runtime_ffi:clear_ws_auth_state().