Current section

Files

Jump to
libero src libero@rpc.erl
Raw

src/libero@rpc.erl

-module(libero@rpc).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/libero/rpc.gleam").
-export([send/4, on_push/2, on_connect/1, on_disconnect/1]).
-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(
" Client-side send machinery.\n"
"\n"
" `send` is the entry point used by libero-generated client stubs.\n"
" It takes the WebSocket URL, the module name, the typed `ClientMsg`\n"
" variant, and a callback to wrap the server's response into a\n"
" Lustre Msg.\n"
"\n"
" The JS FFI (rpc_ffi.mjs) opens the WebSocket lazily on first call\n"
" and caches the connection. Sends issued before the socket is open\n"
" are queued and flushed on the open event. Responses are matched\n"
" to sends by request ID.\n"
"\n"
" Developers don't usually call this module directly. They import\n"
" the per-module stubs the libero generator writes into their\n"
" client package, and those stubs delegate here.\n"
).
-file("src/libero/rpc.gleam", 74).
-spec unreachable_on_erlang() -> any().
unreachable_on_erlang() ->
erlang:error(#{gleam_error => panic,
message => <<"libero/rpc is a JavaScript-only module, unreachable on Erlang target"/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"libero/rpc"/utf8>>,
function => <<"unreachable_on_erlang"/utf8>>,
line => 75}).
-file("src/libero/rpc.gleam", 105).
-spec ffi_send(
binary(),
binary(),
any(),
fun((gleam@dynamic:dynamic_()) -> nil)
) -> nil.
ffi_send(Url, Module, Msg, On_response) ->
_ = Url,
_ = Module,
_ = Msg,
_ = On_response,
unreachable_on_erlang().
-file("src/libero/rpc.gleam", 26).
?DOC(
" Send a typed `ClientMsg` value to the server via WebSocket and\n"
" deliver the server's response back to the Lustre update loop.\n"
"\n"
" The `on_response` callback wraps the decoded response (a Dynamic\n"
" value reconstructed from ETF) into a Lustre Msg so it can be\n"
" dispatched through `update`.\n"
).
-spec send(binary(), binary(), any(), fun((gleam@dynamic:dynamic_()) -> AFIA)) -> lustre@effect:effect(AFIA).
send(Url, Module, Msg, On_response) ->
lustre@effect:from(
fun(Dispatch) ->
ffi_send(
Url,
Module,
Msg,
fun(Raw) -> Dispatch(On_response(Raw)) end
)
end
).
-file("src/libero/rpc.gleam", 94).
-spec ffi_register_push(binary(), fun((gleam@dynamic:dynamic_()) -> nil)) -> nil.
ffi_register_push(Module, Callback) ->
_ = Module,
_ = Callback,
unreachable_on_erlang().
-file("src/libero/rpc.gleam", 42).
?DOC(
" Handle server-initiated push messages on a module.\n"
" When the server pushes a typed message without a prior request,\n"
" the callback wraps it into a Lustre Msg for dispatch.\n"
).
-spec on_push(binary(), fun((gleam@dynamic:dynamic_()) -> AFIC)) -> lustre@effect:effect(AFIC).
on_push(Module, Handler) ->
lustre@effect:from(
fun(Dispatch) ->
ffi_register_push(Module, fun(Raw) -> Dispatch(Handler(Raw)) end)
end
).
-file("src/libero/rpc.gleam", 80).
-spec ffi_register_on_connect(fun(() -> nil)) -> nil.
ffi_register_on_connect(Callback) ->
_ = Callback,
unreachable_on_erlang().
-file("src/libero/rpc.gleam", 55).
?DOC(
" Register a callback that fires whenever the WebSocket connects:\n"
" the initial connection and every successful reconnect. Use this\n"
" to load (or reload) state without a separate code path for the\n"
" first connection. Register early in your app's `init`.\n"
).
-spec on_connect(fun(() -> AFIE)) -> lustre@effect:effect(AFIE).
on_connect(Handler) ->
lustre@effect:from(
fun(Dispatch) ->
ffi_register_on_connect(fun() -> Dispatch(Handler()) end)
end
).
-file("src/libero/rpc.gleam", 87).
-spec ffi_register_on_disconnect(fun((binary()) -> nil)) -> nil.
ffi_register_on_disconnect(Callback) ->
_ = Callback,
unreachable_on_erlang().
-file("src/libero/rpc.gleam", 65).
?DOC(
" Register a callback that fires when the WebSocket disconnects.\n"
" The reason is a human-readable string suitable for display.\n"
" Auto-reconnect kicks in after the disconnect with exponential\n"
" backoff, so a paired `on_connect` will fire when service resumes.\n"
).
-spec on_disconnect(fun((binary()) -> AFIG)) -> lustre@effect:effect(AFIG).
on_disconnect(Handler) ->
lustre@effect:from(
fun(Dispatch) ->
ffi_register_on_disconnect(
fun(Reason) -> Dispatch(Handler(Reason)) end
)
end
).