Packages
lustre
5.5.2
5.7.1
5.7.0
5.6.0
5.5.2
5.5.1
5.5.0
5.4.0
5.3.5
5.3.4
5.3.3
5.3.2
5.3.1
5.3.0
5.2.1
5.2.0
5.1.1
5.1.0
5.0.3
5.0.2
5.0.1
5.0.0
4.6.4
4.6.3
4.6.2
4.6.1
4.6.0
4.5.1
4.5.0
4.4.4
4.4.3
4.4.1
4.4.0
4.3.6
4.3.5
4.3.4
4.3.3
4.3.2
4.3.1
4.3.0
4.2.6
4.2.5
4.2.4
4.2.3
4.2.2
4.2.1
4.2.0
4.1.8
4.1.7
4.1.6
4.1.5
4.1.4
4.1.3
4.1.2
4.1.1
4.1.0
4.0.0
4.0.0-rc1
4.0.0-rc.2
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.12
3.0.11
3.0.10
3.0.9
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
3.0.0-rc.8
3.0.0-rc.7
3.0.0-rc.6
3.0.0-rc.5
3.0.0-rc.4
3.0.0-rc.3
3.0.0-rc.2
3.0.0-rc.1
2.0.1
2.0.0
1.3.0
1.2.0
1.1.0
1.0.0
Create HTML templates, single page applications, Web Components, and real-time server components in Gleam!
Current section
Files
Jump to
Current section
Files
src/lustre@runtime@server@runtime.erl
-module(lustre@runtime@server@runtime).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/lustre/runtime/server/runtime.gleam").
-export([start/5]).
-export_type([state/2, config/1, message/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(false).
-type state(UKD, UKE) :: {state,
gleam@erlang@process:subject(message(UKE)),
gleam@erlang@process:selector(message(UKE)),
gleam@erlang@process:selector(message(UKE)),
UKD,
fun((UKD, UKE) -> {UKD, lustre@effect:effect(UKE)}),
fun((UKD) -> lustre@vdom@vnode:element(UKE)),
config(UKE),
lustre@vdom@vnode:element(UKE),
lustre@vdom@cache:cache(UKE),
gleam@dict:dict(binary(), gleam@json:json()),
gleam@dict:dict(gleam@erlang@process:subject(lustre@runtime@transport:client_message(UKE)), gleam@erlang@process:monitor()),
gleam@set:set(fun((lustre@runtime@transport:client_message(UKE)) -> nil))}.
-type config(UKF) :: {config,
boolean(),
boolean(),
gleam@dict:dict(binary(), fun((binary()) -> {ok, UKF} | {error, nil})),
gleam@dict:dict(binary(), gleam@dynamic@decode:decoder(UKF)),
gleam@dict:dict(binary(), gleam@dynamic@decode:decoder(UKF))}.
-type message(UKG) :: {client_dispatched_message,
lustre@runtime@transport:server_message()} |
{client_registered_subject,
gleam@erlang@process:subject(lustre@runtime@transport:client_message(UKG))} |
{client_deregistered_subject,
gleam@erlang@process:subject(lustre@runtime@transport:client_message(UKG))} |
{client_registered_callback,
fun((lustre@runtime@transport:client_message(UKG)) -> nil)} |
{client_deregistered_callback,
fun((lustre@runtime@transport:client_message(UKG)) -> nil)} |
{effect_added_selector, gleam@erlang@process:selector(message(UKG))} |
{effect_dispatched_message, UKG} |
{effect_emit_event, binary(), gleam@json:json()} |
{effect_provided_value, binary(), gleam@json:json()} |
{monitor_reported_down, gleam@erlang@process:monitor()} |
system_requested_shutdown.
-file("src/lustre/runtime/server/runtime.gleam", 372).
?DOC(false).
-spec handle_attribute_change(
gleam@dict:dict(binary(), fun((binary()) -> {ok, ULO} | {error, nil})),
binary(),
binary()
) -> {ok, ULO} | {error, nil}.
handle_attribute_change(Attributes, Name, Value) ->
case gleam_stdlib:map_get(Attributes, Name) of
{error, _} ->
{error, nil};
{ok, Handler} ->
Handler(Value)
end.
-file("src/lustre/runtime/server/runtime.gleam", 384).
?DOC(false).
-spec handle_property_change(
gleam@dict:dict(binary(), gleam@dynamic@decode:decoder(ULV)),
binary(),
gleam@dynamic:dynamic_()
) -> {ok, ULV} | {error, nil}.
handle_property_change(Properties, Name, Value) ->
case gleam_stdlib:map_get(Properties, Name) of
{error, _} ->
{error, nil};
{ok, Decoder} ->
_pipe = gleam@dynamic@decode:run(Value, Decoder),
gleam@result:replace_error(_pipe, nil)
end.
-file("src/lustre/runtime/server/runtime.gleam", 396).
?DOC(false).
-spec handle_effect(
gleam@erlang@process:subject(message(UMB)),
lustre@effect:effect(UMB)
) -> nil.
handle_effect(Self, Effect) ->
Send = fun(_capture) -> gleam@erlang@process:send(Self, _capture) end,
Dispatch = fun(Message) -> Send({effect_dispatched_message, Message}) end,
Emit = fun(Name, Data) -> Send({effect_emit_event, Name, Data}) end,
Provide = fun(Key, Value) -> Send({effect_provided_value, Key, Value}) end,
Select = fun(Selector) -> _pipe = Selector,
_pipe@1 = gleam_erlang_ffi:map_selector(
_pipe,
fun(Field@0) -> {effect_dispatched_message, Field@0} end
),
_pipe@2 = {effect_added_selector, _pipe@1},
Send(_pipe@2) end,
Internals = fun() -> gleam@dynamic:nil() end,
lustre@effect:perform(Effect, Dispatch, Emit, Select, Internals, Provide).
-file("src/lustre/runtime/server/runtime.gleam", 303).
?DOC(false).
-spec handle_client_message(
state(ULI, ULJ),
lustre@runtime@transport:server_message()
) -> state(ULI, ULJ).
handle_client_message(State, Message) ->
case Message of
{batch, _, Messages} ->
gleam@list:fold(Messages, State, fun handle_client_message/2);
{attribute_changed, _, Name, Value} ->
case handle_attribute_change(
erlang:element(4, erlang:element(8, State)),
Name,
Value
) of
{error, _} ->
State;
{ok, Msg} ->
{Model, Effect} = (erlang:element(6, State))(
erlang:element(5, State),
Msg
),
Vdom = (erlang:element(7, State))(Model),
handle_effect(erlang:element(2, State), Effect),
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
Model,
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
Vdom,
erlang:element(10, State),
erlang:element(11, State),
erlang:element(12, State),
erlang:element(13, State)}
end;
{property_changed, _, Name@1, Value@1} ->
case handle_property_change(
erlang:element(5, erlang:element(8, State)),
Name@1,
Value@1
) of
{error, _} ->
State;
{ok, Msg@1} ->
{Model@1, Effect@1} = (erlang:element(6, State))(
erlang:element(5, State),
Msg@1
),
Vdom@1 = (erlang:element(7, State))(Model@1),
handle_effect(erlang:element(2, State), Effect@1),
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
Model@1,
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
Vdom@1,
erlang:element(10, State),
erlang:element(11, State),
erlang:element(12, State),
erlang:element(13, State)}
end;
{event_fired, _, Path, Name@2, Event} ->
case lustre@vdom@cache:handle(
erlang:element(10, State),
Path,
Name@2,
Event
) of
{Cache, {error, _}} ->
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
erlang:element(5, State),
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
erlang:element(9, State),
Cache,
erlang:element(11, State),
erlang:element(12, State),
erlang:element(13, State)};
{Cache@1, {ok, Handler}} ->
{Model@2, Effect@2} = (erlang:element(6, State))(
erlang:element(5, State),
erlang:element(4, Handler)
),
Vdom@2 = (erlang:element(7, State))(Model@2),
handle_effect(erlang:element(2, State), Effect@2),
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
Model@2,
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
Vdom@2,
Cache@1,
erlang:element(11, State),
erlang:element(12, State),
erlang:element(13, State)}
end;
{context_provided, _, Key, Value@2} ->
case gleam_stdlib:map_get(
erlang:element(6, erlang:element(8, State)),
Key
) of
{error, _} ->
State;
{ok, Decoder} ->
case gleam@dynamic@decode:run(Value@2, Decoder) of
{error, _} ->
State;
{ok, Context} ->
{Model@3, Effect@3} = (erlang:element(6, State))(
erlang:element(5, State),
Context
),
Vdom@3 = (erlang:element(7, State))(Model@3),
handle_effect(erlang:element(2, State), Effect@3),
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
Model@3,
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
Vdom@3,
erlang:element(10, State),
erlang:element(11, State),
erlang:element(12, State),
erlang:element(13, State)}
end
end
end.
-file("src/lustre/runtime/server/runtime.gleam", 415).
?DOC(false).
-spec broadcast(
gleam@dict:dict(gleam@erlang@process:subject(lustre@runtime@transport:client_message(UMF)), gleam@erlang@process:monitor()),
gleam@set:set(fun((lustre@runtime@transport:client_message(UMF)) -> nil)),
lustre@runtime@transport:client_message(UMF)
) -> nil.
broadcast(Clients, Callbacks, Message) ->
_ = gleam@dict:each(
Clients,
fun(Client, _) -> gleam@erlang@process:send(Client, Message) end
),
_ = gleam@set:each(Callbacks, fun(Callback) -> Callback(Message) end),
nil.
-file("src/lustre/runtime/server/runtime.gleam", 150).
?DOC(false).
-spec loop(state(UKY, UKZ), message(UKZ)) -> gleam@otp@actor:next(state(UKY, UKZ), message(UKZ)).
loop(State, Message) ->
case Message of
{client_dispatched_message, Message@1} ->
Next = handle_client_message(State, Message@1),
Diff = lustre@vdom@diff:diff(
erlang:element(10, State),
erlang:element(9, State),
erlang:element(9, Next)
),
Msg = lustre@runtime@transport:reconcile(
erlang:element(2, Diff),
lustre@vdom@cache:memos(erlang:element(3, Diff))
),
_ = broadcast(
erlang:element(12, State),
erlang:element(13, State),
Msg
),
gleam@otp@actor:continue(
{state,
erlang:element(2, Next),
erlang:element(3, Next),
erlang:element(4, Next),
erlang:element(5, Next),
erlang:element(6, Next),
erlang:element(7, Next),
erlang:element(8, Next),
erlang:element(9, Next),
erlang:element(3, Diff),
erlang:element(11, Next),
erlang:element(12, Next),
erlang:element(13, Next)}
);
{client_registered_subject, Client} ->
case gleam@dict:has_key(erlang:element(12, State), Client) of
true ->
gleam@otp@actor:continue(State);
false ->
case gleam@erlang@process:subject_owner(Client) of
{error, _} ->
gleam@otp@actor:continue(State);
{ok, Pid} ->
Monitor = gleam@erlang@process:monitor(Pid),
Subscribers = gleam@dict:insert(
erlang:element(12, State),
Client,
Monitor
),
gleam@erlang@process:send(
Client,
lustre@runtime@transport:mount(
erlang:element(2, erlang:element(8, State)),
erlang:element(3, erlang:element(8, State)),
maps:keys(
erlang:element(
4,
erlang:element(8, State)
)
),
maps:keys(
erlang:element(
5,
erlang:element(8, State)
)
),
maps:keys(
erlang:element(
6,
erlang:element(8, State)
)
),
erlang:element(11, State),
erlang:element(9, State),
lustre@vdom@cache:memos(
erlang:element(10, State)
)
)
),
gleam@otp@actor:continue(
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
erlang:element(5, State),
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
erlang:element(9, State),
erlang:element(10, State),
erlang:element(11, State),
Subscribers,
erlang:element(13, State)}
)
end
end;
{client_deregistered_subject, Client@1} ->
Subscribers@1 = gleam@dict:delete(
erlang:element(12, State),
Client@1
),
gleam@otp@actor:continue(
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
erlang:element(5, State),
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
erlang:element(9, State),
erlang:element(10, State),
erlang:element(11, State),
Subscribers@1,
erlang:element(13, State)}
);
{client_registered_callback, Callback} ->
case gleam@set:contains(erlang:element(13, State), Callback) of
true ->
gleam@otp@actor:continue(State);
false ->
Callbacks = gleam@set:insert(
erlang:element(13, State),
Callback
),
Callback(
lustre@runtime@transport:mount(
erlang:element(2, erlang:element(8, State)),
erlang:element(3, erlang:element(8, State)),
maps:keys(
erlang:element(4, erlang:element(8, State))
),
maps:keys(
erlang:element(5, erlang:element(8, State))
),
maps:keys(
erlang:element(6, erlang:element(8, State))
),
erlang:element(11, State),
erlang:element(9, State),
lustre@vdom@cache:memos(erlang:element(10, State))
)
),
gleam@otp@actor:continue(
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
erlang:element(5, State),
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
erlang:element(9, State),
erlang:element(10, State),
erlang:element(11, State),
erlang:element(12, State),
Callbacks}
)
end;
{client_deregistered_callback, Callback@1} ->
case gleam@set:contains(erlang:element(13, State), Callback@1) of
false ->
gleam@otp@actor:continue(State);
true ->
Callbacks@1 = gleam@set:delete(
erlang:element(13, State),
Callback@1
),
gleam@otp@actor:continue(
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
erlang:element(5, State),
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
erlang:element(9, State),
erlang:element(10, State),
erlang:element(11, State),
erlang:element(12, State),
Callbacks@1}
)
end;
{effect_added_selector, Selector} ->
Base_selector = gleam_erlang_ffi:merge_selector(
erlang:element(4, State),
Selector
),
Selector@1 = gleam_erlang_ffi:merge_selector(
erlang:element(3, State),
Selector
),
_pipe = gleam@otp@actor:continue(
{state,
erlang:element(2, State),
Selector@1,
Base_selector,
erlang:element(5, State),
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
erlang:element(9, State),
erlang:element(10, State),
erlang:element(11, State),
erlang:element(12, State),
erlang:element(13, State)}
),
gleam@otp@actor:with_selector(_pipe, Selector@1);
{effect_dispatched_message, Message@2} ->
{Model, Effect} = (erlang:element(6, State))(
erlang:element(5, State),
Message@2
),
Vdom = (erlang:element(7, State))(Model),
Diff@1 = lustre@vdom@diff:diff(
erlang:element(10, State),
erlang:element(9, State),
Vdom
),
handle_effect(erlang:element(2, State), Effect),
Msg@1 = lustre@runtime@transport:reconcile(
erlang:element(2, Diff@1),
lustre@vdom@cache:memos(erlang:element(3, Diff@1))
),
_ = broadcast(
erlang:element(12, State),
erlang:element(13, State),
Msg@1
),
gleam@otp@actor:continue(
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
Model,
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
Vdom,
erlang:element(3, Diff@1),
erlang:element(11, State),
erlang:element(12, State),
erlang:element(13, State)}
);
{effect_emit_event, Name, Data} ->
_ = broadcast(
erlang:element(12, State),
erlang:element(13, State),
lustre@runtime@transport:emit(Name, Data)
),
gleam@otp@actor:continue(State);
{effect_provided_value, Key, Value} ->
Providers = case gleam_stdlib:map_get(
erlang:element(11, State),
Key
) of
{ok, Old_value} when Old_value =:= Value ->
erlang:element(11, State);
{ok, _} ->
_ = broadcast(
erlang:element(12, State),
erlang:element(13, State),
lustre@runtime@transport:provide(Key, Value)
),
gleam@dict:insert(erlang:element(11, State), Key, Value);
{error, _} ->
_ = broadcast(
erlang:element(12, State),
erlang:element(13, State),
lustre@runtime@transport:provide(Key, Value)
),
gleam@dict:insert(erlang:element(11, State), Key, Value)
end,
gleam@otp@actor:continue(
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
erlang:element(5, State),
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
erlang:element(9, State),
erlang:element(10, State),
Providers,
erlang:element(12, State),
erlang:element(13, State)}
);
{monitor_reported_down, Monitor@1} ->
Subscribers@2 = gleam@dict:filter(
erlang:element(12, State),
fun(_, M) -> M /= Monitor@1 end
),
gleam@otp@actor:continue(
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
erlang:element(5, State),
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
erlang:element(9, State),
erlang:element(10, State),
erlang:element(11, State),
Subscribers@2,
erlang:element(13, State)}
);
system_requested_shutdown ->
_ = gleam@dict:each(
erlang:element(12, State),
fun(_, Monitor@2) ->
gleam@erlang@process:demonitor_process(Monitor@2)
end
),
gleam@otp@actor:stop()
end.
-file("src/lustre/runtime/server/runtime.gleam", 70).
?DOC(false).
-spec start(
gleam@option:option(gleam@erlang@process:name(message(UKK))),
{UKO, lustre@effect:effect(UKK)},
fun((UKO, UKK) -> {UKO, lustre@effect:effect(UKK)}),
fun((UKO) -> lustre@vdom@vnode:element(UKK)),
config(UKK)
) -> {ok, gleam@otp@actor:started(gleam@erlang@process:subject(message(UKK)))} |
{error, gleam@otp@actor:start_error()}.
start(Name, Init, Update, View, Config) ->
_pipe@5 = gleam@otp@actor:new_with_initialiser(
1000,
fun(Self) ->
Vdom = View(erlang:element(1, Init)),
Cache = lustre@vdom@cache:from_node(Vdom),
Base_selector = begin
_pipe = gleam_erlang_ffi:new_selector(),
_pipe@1 = gleam@erlang@process:select(_pipe, Self),
gleam@erlang@process:select_monitors(
_pipe@1,
fun(Down) ->
{monitor_reported_down, erlang:element(2, Down)}
end
)
end,
State = {state,
Self,
Base_selector,
Base_selector,
erlang:element(1, Init),
Update,
View,
Config,
Vdom,
Cache,
maps:new(),
maps:new(),
gleam@set:new()},
handle_effect(Self, erlang:element(2, Init)),
_pipe@2 = gleam@otp@actor:initialised(State),
_pipe@3 = gleam@otp@actor:selecting(_pipe@2, Base_selector),
_pipe@4 = gleam@otp@actor:returning(_pipe@3, Self),
{ok, _pipe@4}
end
),
_pipe@6 = gleam@otp@actor:on_message(_pipe@5, fun loop/2),
_pipe@7 = case Name of
{some, Name@1} ->
fun(_capture) -> gleam@otp@actor:named(_capture, Name@1) end;
none ->
fun gleam@function:identity/1
end(_pipe@6),
gleam@otp@actor:start(_pipe@7).