Packages
lustre
5.3.3
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/4]).
-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(QXG, QXH) :: {state,
gleam@erlang@process:subject(message(QXH)),
gleam@erlang@process:selector(message(QXH)),
gleam@erlang@process:selector(message(QXH)),
QXG,
fun((QXG, QXH) -> {QXG, lustre@effect:effect(QXH)}),
fun((QXG) -> lustre@vdom@vnode:element(QXH)),
config(QXH),
lustre@vdom@vnode:element(QXH),
lustre@vdom@events:events(QXH),
gleam@dict:dict(binary(), gleam@json:json()),
gleam@dict:dict(gleam@erlang@process:subject(lustre@runtime@transport:client_message(QXH)), gleam@erlang@process:monitor()),
gleam@set:set(fun((lustre@runtime@transport:client_message(QXH)) -> nil))}.
-type config(QXI) :: {config,
boolean(),
boolean(),
gleam@dict:dict(binary(), fun((binary()) -> {ok, QXI} | {error, nil})),
gleam@dict:dict(binary(), gleam@dynamic@decode:decoder(QXI)),
gleam@dict:dict(binary(), gleam@dynamic@decode:decoder(QXI))}.
-type message(QXJ) :: {client_dispatched_message,
lustre@runtime@transport:server_message()} |
{client_registered_subject,
gleam@erlang@process:subject(lustre@runtime@transport:client_message(QXJ))} |
{client_deregistered_subject,
gleam@erlang@process:subject(lustre@runtime@transport:client_message(QXJ))} |
{client_registered_callback,
fun((lustre@runtime@transport:client_message(QXJ)) -> nil)} |
{client_deregistered_callback,
fun((lustre@runtime@transport:client_message(QXJ)) -> nil)} |
{effect_added_selector, gleam@erlang@process:selector(message(QXJ))} |
{effect_dispatched_message, QXJ} |
{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", 328).
?DOC(false).
-spec handle_attribute_change(
gleam@dict:dict(binary(), fun((binary()) -> {ok, QYN} | {error, nil})),
binary(),
binary()
) -> {ok, QYN} | {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", 339).
?DOC(false).
-spec handle_property_change(
gleam@dict:dict(binary(), gleam@dynamic@decode:decoder(QYU)),
binary(),
gleam@dynamic:dynamic_()
) -> {ok, QYU} | {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", 351).
?DOC(false).
-spec handle_effect(
gleam@erlang@process:subject(message(QZA)),
lustre@effect:effect(QZA)
) -> 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", 260).
?DOC(false).
-spec handle_client_message(
state(QYH, QYI),
lustre@runtime@transport:server_message()
) -> state(QYH, QYI).
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@events:handle(
erlang:element(10, State),
Path,
Name@2,
Event
) of
{Events, {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),
Events,
erlang:element(11, State),
erlang:element(12, State),
erlang:element(13, State)};
{Events@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,
Events@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", 370).
?DOC(false).
-spec broadcast(
gleam@dict:dict(gleam@erlang@process:subject(lustre@runtime@transport:client_message(QZE)), gleam@erlang@process:monitor()),
gleam@set:set(fun((lustre@runtime@transport:client_message(QZE)) -> nil)),
lustre@runtime@transport:client_message(QZE)
) -> 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).
-file("src/lustre/runtime/server/runtime.gleam", 127).
?DOC(false).
-spec loop(state(QXX, QXY), message(QXY)) -> gleam@otp@actor:next(state(QXX, QXY), message(QXY)).
loop(State, Message) ->
case Message of
{client_dispatched_message, Message@1} ->
Next = handle_client_message(State, Message@1),
{diff, Patch, Events} = lustre@vdom@diff:diff(
erlang:element(10, State),
erlang:element(9, State),
erlang:element(9, Next)
),
broadcast(
erlang:element(12, State),
erlang:element(13, State),
lustre@runtime@transport:reconcile(Patch)
),
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),
Events,
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)
)
),
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)
)
),
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, Patch@1, Events@1} = lustre@vdom@diff:diff(
erlang:element(10, State),
erlang:element(9, State),
Vdom
),
handle_effect(erlang:element(2, State), Effect),
broadcast(
erlang:element(12, State),
erlang:element(13, State),
lustre@runtime@transport:reconcile(Patch@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,
Events@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 = gleam@dict:insert(erlang:element(11, State), Key, Value),
broadcast(
erlang:element(12, State),
erlang:element(13, State),
lustre@runtime@transport:provide(Key, Value)
),
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", 55).
?DOC(false).
-spec start(
{QXN, lustre@effect:effect(QXO)},
fun((QXN, QXO) -> {QXN, lustre@effect:effect(QXO)}),
fun((QXN) -> lustre@vdom@vnode:element(QXO)),
config(QXO)
) -> {ok, gleam@erlang@process:subject(message(QXO))} |
{error, gleam@otp@actor:start_error()}.
start(Init, Update, View, Config) ->
Result = begin
_pipe@5 = gleam@otp@actor:new_with_initialiser(
1000,
fun(Self) ->
Vdom = View(erlang:element(1, Init)),
Events = lustre@vdom@events: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,
Events,
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),
gleam@otp@actor:start(_pipe@6)
end,
case Result of
{ok, Started} ->
{ok, erlang:element(3, Started)};
{error, Error} ->
{error, Error}
end.