-module(rally@generator@client).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/rally/generator/client.gleam").
-export([generate_package_with_client_context_contract/8, generate_package/6]).
-export_type([generated_file/0, client_context_sync_fields/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(
" Client package generation.\n"
"\n"
" Assembles the standalone Gleam project that compiles to the browser\n"
" SPA: gleam.toml, app.gleam (Lustre entry point with per-page TEA loop),\n"
" transport.gleam (WebSocket FFI bridge), and router.gleam (client-side\n"
" route parsing). The generated package lives in .generated_clients/<namespace>.\n"
).
-type generated_file() :: {generated_file, binary(), binary()}.
-type client_context_sync_fields() :: {client_context_sync_fields,
boolean(),
boolean(),
boolean()}.
-file("src/rally/generator/client.gleam", 103).
-spec empty_client_context_contract() -> rally@types:client_context_contract().
empty_client_context_contract() ->
{client_context_contract, [], [], true, true}.
-file("src/rally/generator/client.gleam", 96).
-spec config_mjs(binary()) -> binary().
config_mjs(Protocol) ->
<<<<<<"// Generated by Rally — do not edit.\n"/utf8,
"export const protocol = \""/utf8>>/binary,
Protocol/binary>>/binary,
"\";\n"/utf8>>.
-file("src/rally/generator/client.gleam", 1231).
?DOC(
" Generate the import alias for a page module, using the route's module_path.\n"
" e.g. \"pages/home_\" -> import alias \"pages_home_\"\n"
" \"pages/article/slug_\" -> import alias \"pages_article_slug_\"\n"
).
-spec page_module_alias(rally@types:scanned_route()) -> binary().
page_module_alias(Route) ->
gleam@string:replace(erlang:element(5, Route), <<"/"/utf8>>, <<"_"/utf8>>).
-file("src/rally/generator/client.gleam", 1250).
-spec generate_page_imports(
list(rally@types:scanned_route()),
gleam@dict:dict(binary(), rally@types:page_contract())
) -> binary().
generate_page_imports(Routes, Contract_map) ->
_pipe = Routes,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Route) ->
case gleam_stdlib:map_get(Contract_map, erlang:element(3, Route)) of
{ok, Contract} when erlang:element(7, Contract) ->
Alias = page_module_alias(Route),
{ok,
<<<<<<"import "/utf8,
(erlang:element(5, Route))/binary>>/binary,
" as "/utf8>>/binary,
Alias/binary>>};
_ ->
{error, nil}
end
end
),
_pipe@2 = gleam@list:unique(_pipe@1),
_pipe@3 = gleam@list:sort(_pipe@2, fun gleam@string:compare/2),
gleam@string:join(_pipe@3, <<"\n"/utf8>>).
-file("src/rally/generator/client.gleam", 1246).
-spec module_alias(binary()) -> binary().
module_alias(Module_path) ->
gleam@string:replace(Module_path, <<"/"/utf8>>, <<"_"/utf8>>).
-file("src/rally/generator/client.gleam", 1239).
-spec last_segment(binary()) -> binary().
last_segment(Module_path) ->
case begin
_pipe = gleam@string:split(Module_path, <<"/"/utf8>>),
gleam@list:last(_pipe)
end of
{ok, Seg} ->
Seg;
{error, nil} ->
Module_path
end.
-file("src/rally/generator/client.gleam", 112).
-spec import_as(binary(), binary()) -> binary().
import_as(Module_path, Alias) ->
case last_segment(Module_path) =:= Alias of
true ->
<<"import "/utf8, Module_path/binary>>;
false ->
<<<<<<"import "/utf8, Module_path/binary>>/binary, " as "/utf8>>/binary,
Alias/binary>>
end.
-file("src/rally/generator/client.gleam", 1177).
-spec generate_render_page(
list(rally@types:scanned_route()),
gleam@dict:dict(binary(), rally@types:page_contract()),
boolean()
) -> binary().
generate_render_page(Routes, Contract_map, Has_client_context) ->
Arms = begin
_pipe = Routes,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Route) ->
case gleam_stdlib:map_get(
Contract_map,
erlang:element(3, Route)
) of
{ok, Contract} when erlang:element(7, Contract) ->
Alias = page_module_alias(Route),
Vn = erlang:element(3, Route),
View_args = case Has_client_context of
true ->
<<"(client_context, m)"/utf8>>;
false ->
<<"(m)"/utf8>>
end,
{ok,
<<<<<<<<<<<<<<<<<<" "/utf8, Vn/binary>>/binary,
"PageModel(m) ->\n"/utf8>>/binary,
" element.map("/utf8>>/binary,
Alias/binary>>/binary,
".view"/utf8>>/binary,
View_args/binary>>/binary,
", fn(msg) { PageMsg("/utf8>>/binary,
Vn/binary>>/binary,
"PageMsg(msg)) })"/utf8>>};
_ ->
{error, nil}
end
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
Not_found_arm = <<" NoPageModel -> html.div([], [html.text(\"Page not found\")])"/utf8>>,
Sig = case Has_client_context of
true ->
<<"fn render_page(page_model: PageModel, client_context: client_context.ClientContext) -> Element(Msg) {"/utf8>>;
false ->
<<"fn render_page(page_model: PageModel) -> Element(Msg) {"/utf8>>
end,
<<<<<<<<<<Sig/binary, "\n case page_model {\n"/utf8>>/binary, Arms/binary>>/binary,
"\n"/utf8>>/binary,
Not_found_arm/binary>>/binary,
"\n }\n}"/utf8>>.
-file("src/rally/generator/client.gleam", 1080).
-spec generate_update_page(
list(rally@types:scanned_route()),
gleam@dict:dict(binary(), rally@types:page_contract()),
boolean()
) -> binary().
generate_update_page(Routes, Contract_map, Has_client_context) ->
Arms = begin
_pipe = Routes,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Route) ->
case gleam_stdlib:map_get(
Contract_map,
erlang:element(3, Route)
) of
{ok, Contract} when erlang:element(7, Contract) ->
Alias = page_module_alias(Route),
Vn = erlang:element(3, Route),
case {Has_client_context, erlang:element(8, Contract)} of
{true, true} ->
{ok,
<<<<<<<<<<<<<<<<<<<<<<<<<<" "/utf8,
Vn/binary>>/binary,
"PageModel(m), "/utf8>>/binary,
Vn/binary>>/binary,
"PageMsg(msg) -> {\n"/utf8>>/binary,
" let #(new_m, e, ctx_msg) = "/utf8>>/binary,
Alias/binary>>/binary,
".update(client_context, m, msg)\n"/utf8>>/binary,
" #("/utf8>>/binary,
Vn/binary>>/binary,
"PageModel(new_m), effect.map(e, fn(msg) { PageMsg("/utf8>>/binary,
Vn/binary>>/binary,
"PageMsg(msg)) }), ctx_msg)\n"/utf8>>/binary,
" }"/utf8>>};
{true, false} ->
{ok,
<<<<<<<<<<<<<<<<<<<<<<<<<<" "/utf8,
Vn/binary>>/binary,
"PageModel(m), "/utf8>>/binary,
Vn/binary>>/binary,
"PageMsg(msg) -> {\n"/utf8>>/binary,
" let #(new_m, e) = "/utf8>>/binary,
Alias/binary>>/binary,
".update(client_context, m, msg)\n"/utf8>>/binary,
" #("/utf8>>/binary,
Vn/binary>>/binary,
"PageModel(new_m), effect.map(e, fn(msg) { PageMsg("/utf8>>/binary,
Vn/binary>>/binary,
"PageMsg(msg)) }), None)\n"/utf8>>/binary,
" }"/utf8>>};
{_, _} ->
{ok,
<<<<<<<<<<<<<<<<<<<<<<<<<<" "/utf8,
Vn/binary>>/binary,
"PageModel(m), "/utf8>>/binary,
Vn/binary>>/binary,
"PageMsg(msg) -> {\n"/utf8>>/binary,
" let #(new_m, e) = "/utf8>>/binary,
Alias/binary>>/binary,
".update(m, msg)\n"/utf8>>/binary,
" #("/utf8>>/binary,
Vn/binary>>/binary,
"PageModel(new_m), effect.map(e, fn(msg) { PageMsg("/utf8>>/binary,
Vn/binary>>/binary,
"PageMsg(msg)) }))\n"/utf8>>/binary,
" }"/utf8>>}
end;
_ ->
{error, nil}
end
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
case Has_client_context of
true ->
Catch_all = <<" _, _ -> #(page_model, effect.none(), None)"/utf8>>,
Sig = <<"fn update_page(page_model page_model: PageModel, page_msg page_msg: PageMsg, client_context client_context: client_context.ClientContext) -> #(PageModel, Effect(Msg), Option(client_context.ClientContextMsg)) {"/utf8>>,
<<<<<<<<<<Sig/binary, "\n case page_model, page_msg {\n"/utf8>>/binary,
Arms/binary>>/binary,
"\n"/utf8>>/binary,
Catch_all/binary>>/binary,
"\n }\n}"/utf8>>;
false ->
Catch_all@1 = <<" _, _ -> #(page_model, effect.none())"/utf8>>,
Sig@1 = <<"fn update_page(page_model page_model: PageModel, page_msg page_msg: PageMsg) -> #(PageModel, Effect(Msg)) {"/utf8>>,
<<<<<<<<<<Sig@1/binary, "\n case page_model, page_msg {\n"/utf8>>/binary,
Arms/binary>>/binary,
"\n"/utf8>>/binary,
Catch_all@1/binary>>/binary,
"\n }\n}"/utf8>>
end.
-file("src/rally/generator/client.gleam", 834).
-spec route_pattern_with(rally@types:scanned_route(), binary()) -> binary().
route_pattern_with(Route, Prefix) ->
case erlang:element(4, Route) of
[] ->
<<"router."/utf8, (erlang:element(3, Route))/binary>>;
Params ->
Param_names = begin
_pipe = Params,
_pipe@1 = gleam@list:map(
_pipe,
fun(P) ->
<<Prefix/binary, (erlang:element(1, P))/binary>>
end
),
gleam@string:join(_pipe@1, <<", "/utf8>>)
end,
<<<<<<<<"router."/utf8, (erlang:element(3, Route))/binary>>/binary,
"("/utf8>>/binary,
Param_names/binary>>/binary,
")"/utf8>>
end.
-file("src/rally/generator/client.gleam", 826).
?DOC(
" Generate a route pattern match expression, e.g. \"router.Home\" or\n"
" \"router.ArticleSlug(slug)\" depending on whether the route has params.\n"
).
-spec route_pattern(rally@types:scanned_route()) -> binary().
route_pattern(Route) ->
route_pattern_with(Route, <<""/utf8>>).
-file("src/rally/generator/client.gleam", 1029).
-spec generate_reinit_server(
list(rally@types:scanned_route()),
gleam@dict:dict(binary(), rally@types:page_contract())
) -> binary().
generate_reinit_server(Routes, Contract_map) ->
Arms = begin
_pipe = Routes,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Route) ->
case gleam_stdlib:map_get(
Contract_map,
erlang:element(3, Route)
) of
{ok, Contract} when erlang:element(7, Contract) ->
Pattern = route_pattern(Route),
Body = case erlang:element(4, Route) of
[] ->
<<<<" transport.send_page_init(\""/utf8,
(erlang:element(3, Route))/binary>>/binary,
"\", Nil)"/utf8>>;
[Single] ->
<<<<<<<<" transport.send_page_init(\""/utf8,
(erlang:element(3, Route))/binary>>/binary,
"\", "/utf8>>/binary,
(erlang:element(1, Single))/binary>>/binary,
")"/utf8>>;
Params ->
Tuple = <<<<"#("/utf8,
(gleam@string:join(
gleam@list:map(
Params,
fun(P) ->
erlang:element(1, P)
end
),
<<", "/utf8>>
))/binary>>/binary,
")"/utf8>>,
<<<<<<<<" transport.send_page_init(\""/utf8,
(erlang:element(3, Route))/binary>>/binary,
"\", "/utf8>>/binary,
Tuple/binary>>/binary,
")"/utf8>>
end,
{ok,
<<<<<<<<" "/utf8, Pattern/binary>>/binary,
" -> {\n"/utf8>>/binary,
Body/binary>>/binary,
"\n effect.none()\n }"/utf8>>};
_ ->
{error, nil}
end
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
<<<<"fn reinit_server(route: router.Route) -> Effect(Msg) {\n case route {\n"/utf8,
Arms/binary>>/binary,
"\n _ -> effect.none()\n }\n}"/utf8>>.
-file("src/rally/generator/client.gleam", 1235).
-spec page_model_decoder_name(binary()) -> binary().
page_model_decoder_name(Module_path) ->
<<<<"decode_"/utf8,
(gleam@string:replace(Module_path, <<"/"/utf8>>, <<"_"/utf8>>))/binary>>/binary,
"_model"/utf8>>.
-file("src/rally/generator/client.gleam", 830).
-spec route_pattern_ignored(rally@types:scanned_route()) -> binary().
route_pattern_ignored(Route) ->
route_pattern_with(Route, <<"_"/utf8>>).
-file("src/rally/generator/client.gleam", 929).
-spec generate_hydrate_page(
list(rally@types:scanned_route()),
gleam@dict:dict(binary(), rally@types:page_contract()),
boolean()
) -> binary().
generate_hydrate_page(Routes, Contract_map, Has_client_context) ->
Hydrate_uses_client_context = Has_client_context andalso gleam@list:any(
Routes,
fun(Route) ->
case gleam_stdlib:map_get(Contract_map, erlang:element(3, Route)) of
{ok, Contract} ->
erlang:element(7, Contract) andalso erlang:element(
6,
Contract
);
{error, nil} ->
false
end
end
),
Hydrate_client_context_name = case Hydrate_uses_client_context of
true ->
<<"client_context"/utf8>>;
false ->
<<"_client_context"/utf8>>
end,
Error_fallback = case Has_client_context of
true ->
<<" Error(_) -> init_page(route: route, client_context: client_context)\n"/utf8>>;
false ->
<<" Error(_) -> init_page(route: route)\n"/utf8>>
end,
Arms = begin
_pipe = Routes,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Route@1) ->
case gleam_stdlib:map_get(
Contract_map,
erlang:element(3, Route@1)
) of
{ok, Contract@1} when erlang:element(7, Contract@1) andalso erlang:element(
6,
Contract@1
) ->
Alias = page_module_alias(Route@1),
Pattern = route_pattern_ignored(Route@1),
Decoder_name = page_model_decoder_name(
erlang:element(5, Route@1)
),
Init_loaded_call = case Has_client_context of
true ->
<<<<<<Alias/binary, ".init_loaded("/utf8>>/binary,
Hydrate_client_context_name/binary>>/binary,
", model)"/utf8>>;
false ->
<<Alias/binary, ".init_loaded(model)"/utf8>>
end,
Variant = erlang:element(3, Route@1),
{ok,
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" "/utf8,
Pattern/binary>>/binary,
" -> {\n"/utf8>>/binary,
" case codec.decode_flags_typed(flags, \""/utf8>>/binary,
Decoder_name/binary>>/binary,
"\") {\n"/utf8>>/binary,
" Ok(model) -> {\n"/utf8>>/binary,
" let #(m, e) = "/utf8>>/binary,
Init_loaded_call/binary>>/binary,
"\n"/utf8>>/binary,
" #("/utf8>>/binary,
Variant/binary>>/binary,
"PageModel(m), effect.map(e, fn(msg) { PageMsg("/utf8>>/binary,
Variant/binary>>/binary,
"PageMsg(msg)) }))\n"/utf8>>/binary,
" }\n"/utf8>>/binary,
Error_fallback/binary>>/binary,
" }\n"/utf8>>/binary,
" }"/utf8>>};
{ok, Contract@2} when erlang:element(7, Contract@2) ->
Pattern@1 = route_pattern_ignored(Route@1),
Decoder_name@1 = page_model_decoder_name(
erlang:element(5, Route@1)
),
Variant@1 = erlang:element(3, Route@1),
{ok,
<<<<<<<<<<<<<<<<<<<<<<" "/utf8,
Pattern@1/binary>>/binary,
" -> {\n"/utf8>>/binary,
" case codec.decode_flags_typed(flags, \""/utf8>>/binary,
Decoder_name@1/binary>>/binary,
"\") {\n"/utf8>>/binary,
" Ok(model) -> #("/utf8>>/binary,
Variant@1/binary>>/binary,
"PageModel(model), effect.none())\n"/utf8>>/binary,
Error_fallback/binary>>/binary,
" }\n"/utf8>>/binary,
" }"/utf8>>};
_ ->
{error, nil}
end
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
Sig = case Has_client_context of
true ->
<<<<"fn hydrate_page(route: router.Route, flags: String, "/utf8,
Hydrate_client_context_name/binary>>/binary,
": client_context.ClientContext) -> #(PageModel, Effect(Msg)) {"/utf8>>;
false ->
<<"fn hydrate_page(route: router.Route, flags: String) -> #(PageModel, Effect(Msg)) {"/utf8>>
end,
<<<<<<Sig/binary, "\n case route {\n"/utf8>>/binary, Arms/binary>>/binary,
"\n _ -> #(NoPageModel, effect.none())\n }\n}"/utf8>>.
-file("src/rally/generator/client.gleam", 848).
?DOC(" Generate the extra arguments for init_page calls from route params.\n").
-spec route_param_args(rally@types:scanned_route()) -> binary().
route_param_args(Route) ->
case erlang:element(4, Route) of
[] ->
<<""/utf8>>;
Params ->
_pipe = Params,
_pipe@1 = gleam@list:map(
_pipe,
fun(P) -> <<", "/utf8, (erlang:element(1, P))/binary>> end
),
gleam@string:join(_pipe@1, <<""/utf8>>)
end.
-file("src/rally/generator/client.gleam", 858).
-spec generate_init_page(
list(rally@types:scanned_route()),
gleam@dict:dict(binary(), rally@types:page_contract()),
boolean()
) -> binary().
generate_init_page(Routes, Contract_map, Has_client_context) ->
Arms = begin
_pipe = Routes,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Route) ->
case gleam_stdlib:map_get(
Contract_map,
erlang:element(3, Route)
) of
{ok, Contract} when erlang:element(7, Contract) ->
Alias = page_module_alias(Route),
Pattern = route_pattern(Route),
Param_args = route_param_args(Route),
Call_args = case {Has_client_context, Param_args} of
{true, _} ->
<<<<<<"("/utf8, "client_context"/utf8>>/binary,
Param_args/binary>>/binary,
")"/utf8>>;
{false, <<""/utf8>>} ->
<<"()"/utf8>>;
{false, _} ->
<<<<"("/utf8,
(gleam@string:drop_start(Param_args, 2))/binary>>/binary,
")"/utf8>>
end,
Server_init_call = case erlang:element(4, Route) of
[] ->
<<<<" transport.send_page_init(\""/utf8,
(erlang:element(3, Route))/binary>>/binary,
"\", Nil)\n"/utf8>>;
Params ->
Param_names = gleam@list:map(
Params,
fun(P) -> erlang:element(1, P) end
),
Params_tuple = case Param_names of
[Single] ->
Single;
_ ->
<<<<"#("/utf8,
(gleam@string:join(
Param_names,
<<", "/utf8>>
))/binary>>/binary,
")"/utf8>>
end,
<<<<<<<<" transport.send_page_init(\""/utf8,
(erlang:element(3, Route))/binary>>/binary,
"\", "/utf8>>/binary,
Params_tuple/binary>>/binary,
")\n"/utf8>>
end,
{ok,
<<<<<<<<<<<<<<<<<<<<<<<<<<<<" "/utf8,
Pattern/binary>>/binary,
" -> {\n"/utf8>>/binary,
Server_init_call/binary>>/binary,
" let #(m, e) = "/utf8>>/binary,
Alias/binary>>/binary,
".init"/utf8>>/binary,
Call_args/binary>>/binary,
"\n"/utf8>>/binary,
" #("/utf8>>/binary,
(erlang:element(3, Route))/binary>>/binary,
"PageModel(m), effect.map(e, fn(msg) { PageMsg("/utf8>>/binary,
(erlang:element(3, Route))/binary>>/binary,
"PageMsg(msg)) }))\n"/utf8>>/binary,
" }"/utf8>>};
_ ->
{error, nil}
end
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
Not_found_arm = <<" _ -> #(NoPageModel, effect.none())"/utf8>>,
Sig = case Has_client_context of
true ->
<<"fn init_page(route route: router.Route, client_context client_context: client_context.ClientContext) -> #(PageModel, Effect(Msg)) {"/utf8>>;
false ->
<<"fn init_page(route route: router.Route) -> #(PageModel, Effect(Msg)) {"/utf8>>
end,
<<<<<<<<<<Sig/binary, "\n case route {\n"/utf8>>/binary, Arms/binary>>/binary,
"\n"/utf8>>/binary,
Not_found_arm/binary>>/binary,
"\n }\n}"/utf8>>.
-file("src/rally/generator/client.gleam", 805).
-spec generate_page_msg_type(
list(rally@types:scanned_route()),
gleam@dict:dict(binary(), rally@types:page_contract())
) -> binary().
generate_page_msg_type(Routes, Contract_map) ->
Variants = begin
_pipe = Routes,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Route) ->
case gleam_stdlib:map_get(
Contract_map,
erlang:element(3, Route)
) of
{ok, Contract} when erlang:element(7, Contract) ->
Alias = page_module_alias(Route),
{ok,
<<<<<<<<" "/utf8,
(erlang:element(3, Route))/binary>>/binary,
"PageMsg("/utf8>>/binary,
Alias/binary>>/binary,
".Msg)"/utf8>>};
_ ->
{error, nil}
end
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
<<<<"pub type PageMsg {\n"/utf8, Variants/binary>>/binary, "\n}"/utf8>>.
-file("src/rally/generator/client.gleam", 786).
-spec generate_page_model_type(
list(rally@types:scanned_route()),
gleam@dict:dict(binary(), rally@types:page_contract())
) -> binary().
generate_page_model_type(Routes, Contract_map) ->
Variants = begin
_pipe = Routes,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Route) ->
case gleam_stdlib:map_get(
Contract_map,
erlang:element(3, Route)
) of
{ok, Contract} when erlang:element(7, Contract) ->
Alias = page_module_alias(Route),
{ok,
<<<<<<<<" "/utf8,
(erlang:element(3, Route))/binary>>/binary,
"PageModel("/utf8>>/binary,
Alias/binary>>/binary,
".Model)"/utf8>>};
_ ->
{error, nil}
end
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
<<<<"pub type PageModel {\n"/utf8, Variants/binary>>/binary,
"\n NoPageModel\n}"/utf8>>.
-file("src/rally/generator/client.gleam", 755).
-spec find_to_client_msg_wrapper(
rally@types:scanned_route(),
rally@types:page_contract()
) -> {ok, binary()} | {error, nil}.
find_to_client_msg_wrapper(Route, Contract) ->
_pipe = erlang:element(3, Contract),
gleam@list:find_map(
_pipe,
fun(Variant) -> case erlang:element(3, Variant) of
[Field] ->
case erlang:element(3, Field) of
{user_type, Module_path, <<"ToClient"/utf8>>, []} when Module_path =:= erlang:element(
5,
Route
) ->
{ok, erlang:element(2, Variant)};
_ ->
{error, nil}
end;
_ ->
{error, nil}
end end
).
-file("src/rally/generator/client.gleam", 734).
-spec generate_push_registrations(
list({rally@types:scanned_route(), rally@types:page_contract()})
) -> binary().
generate_push_registrations(Contracts) ->
_pipe = Contracts,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Pair) ->
{Route, Contract} = Pair,
case find_to_client_msg_wrapper(Route, Contract) of
{ok, Wrapper} ->
Alias = page_module_alias(Route),
{ok,
<<<<<<<<<<<<<<<<"
let _ =
transport.register_push_handler(\""/utf8,
(erlang:element(
3,
Route
))/binary>>/binary,
"\", fn(raw) {
dispatch(PageMsg("/utf8>>/binary,
(erlang:element(3, Route))/binary>>/binary,
"PageMsg("/utf8>>/binary,
Alias/binary>>/binary,
"."/utf8>>/binary,
Wrapper/binary>>/binary,
"(transport.coerce(raw)))))
})"/utf8>>};
{error, _} ->
{error, nil}
end
end
),
gleam@string:join(_pipe@1, <<""/utf8>>).
-file("src/rally/generator/client.gleam", 362).
-spec client_context_init_overlay(client_context_sync_fields()) -> binary().
client_context_init_overlay(Fields) ->
Assignments = [],
Assignments@1 = case erlang:element(2, Fields) of
true ->
[<<"current_path: current_path"/utf8>> | Assignments];
false ->
Assignments
end,
Assignments@2 = case erlang:element(3, Fields) of
true ->
[<<"dark_mode: rally_effect.read_dark_mode()"/utf8>> |
Assignments@1];
false ->
Assignments@1
end,
Assignments@3 = case erlang:element(4, Fields) of
true ->
[<<"lang: rally_effect.read_lang()"/utf8>> | Assignments@2];
false ->
Assignments@2
end,
Assignments@4 = lists:reverse(Assignments@3),
case Assignments@4 of
[] ->
<<""/utf8>>;
_ ->
<<<<" let client_context = client_context.ClientContext(
..client_context,
"/utf8,
(gleam@string:join(Assignments@4, <<",
"/utf8>>))/binary>>/binary,
",
)
"/utf8>>
end.
-file("src/rally/generator/client.gleam", 337).
-spec client_context_sync_fields(
gleam@option:option(rally@types:client_context_contract())
) -> client_context_sync_fields().
client_context_sync_fields(Contract) ->
Fields = case Contract of
{some, Contract@1} ->
_pipe = erlang:element(2, Contract@1),
_pipe@1 = gleam@list:find_map(
_pipe,
fun(Variant) -> case erlang:element(2, Variant) of
<<"ClientContext"/utf8>> ->
{ok, erlang:element(3, Variant)};
_ ->
{error, nil}
end end
),
_pipe@2 = gleam@result:unwrap(_pipe@1, []),
_pipe@3 = gleam@list:map(
_pipe@2,
fun(Field) -> erlang:element(2, Field) end
),
gleam@set:from_list(_pipe@3);
none ->
gleam@set:new()
end,
{client_context_sync_fields,
gleam@set:contains(Fields, <<"current_path"/utf8>>),
gleam@set:contains(Fields, <<"dark_mode"/utf8>>),
gleam@set:contains(Fields, <<"lang"/utf8>>)}.
-file("src/rally/generator/client.gleam", 392).
-spec app_gleam(
list(rally@types:scanned_route()),
list({rally@types:scanned_route(), rally@types:page_contract()}),
gleam@option:option(rally@types:client_context_contract()),
binary()
) -> binary().
app_gleam(Routes, Contracts, Client_context_contract, Client_context_module) ->
Has_client_context = gleam@option:is_some(Client_context_contract),
Sync_fields = client_context_sync_fields(Client_context_contract),
Init_context_overlay = client_context_init_overlay(Sync_fields),
Needs_rally_effect = erlang:element(3, Sync_fields) orelse erlang:element(
4,
Sync_fields
),
Contract_map = begin
_pipe = Contracts,
_pipe@1 = gleam@list:map(
_pipe,
fun(Pair) ->
{erlang:element(3, (erlang:element(1, Pair))),
erlang:element(2, Pair)}
end
),
maps:from_list(_pipe@1)
end,
Push_registrations = generate_push_registrations(Contracts),
Page_model_type = generate_page_model_type(Routes, Contract_map),
Page_msg_type = generate_page_msg_type(Routes, Contract_map),
Init_page_fn = generate_init_page(Routes, Contract_map, Has_client_context),
Hydrate_page_fn = generate_hydrate_page(
Routes,
Contract_map,
Has_client_context
),
Reinit_server_fn = generate_reinit_server(Routes, Contract_map),
Update_page_fn = generate_update_page(
Routes,
Contract_map,
Has_client_context
),
Render_page_fn = generate_render_page(
Routes,
Contract_map,
Has_client_context
),
Layout_modules = begin
_pipe@2 = Routes,
_pipe@3 = gleam@list:filter_map(
_pipe@2,
fun(Route) -> case erlang:element(6, Route) of
{some, Layout} ->
{ok, Layout};
_ ->
{error, nil}
end end
),
gleam@list:unique(_pipe@3)
end,
Ctx_import = case Has_client_context of
true ->
<<"\n"/utf8,
(import_as(Client_context_module, <<"client_context"/utf8>>))/binary>>;
false ->
<<""/utf8>>
end,
Rally_effect_import = case Needs_rally_effect of
true ->
<<"import rally_runtime/effect as rally_effect\n\n"/utf8>>;
false ->
<<"\n"/utf8>>
end,
Layout_imports = case Layout_modules of
[] ->
<<""/utf8>>;
Mods ->
_pipe@4 = gleam@list:map(
Mods,
fun(Mod) ->
<<<<<<"\nimport "/utf8, Mod/binary>>/binary, " as "/utf8>>/binary,
(module_alias(Mod))/binary>>
end
),
gleam@string:join(_pipe@4, <<""/utf8>>)
end,
Ctx_field = case Has_client_context of
true ->
<<"\n client_context: client_context.ClientContext,\n current_path: String,"/utf8>>;
false ->
<<""/utf8>>
end,
Ctx_msg_variant = case Has_client_context of
true ->
<<"\n ClientContextUpdate(client_context.ClientContextMsg)"/utf8>>;
false ->
<<""/utf8>>
end,
Modem_init = <<"modem.init(fn(uri) { UrlChanged(router.parse_route(uri)) })"/utf8>>,
Ctx_decoder_name = <<<<"decode_"/utf8,
(gleam@string:replace(
Client_context_module,
<<"/"/utf8>>,
<<"_"/utf8>>
))/binary>>/binary,
"_client_context"/utf8>>,
Ctx_init = case Has_client_context of
true ->
<<<<<<<<<<<<" let flags = transport.read_flags()
let #(ctx_model, ctx_effects) = client_context.init()
let current_path = router.route_to_path(route)
let client_context = case codec.decode_flags_typed(transport.read_client_context(), \""/utf8,
Ctx_decoder_name/binary>>/binary,
"\") {
Ok(ctx) -> ctx
Error(_) -> ctx_model
}
"/utf8>>/binary,
Init_context_overlay/binary>>/binary,
" let #(page_model, page_effects) = case flags {
\"\" -> init_page(route: route, client_context: client_context)
_ -> hydrate_page(route, flags, client_context)
}
#(Model(route:, page_model:, connection: Disconnected, client_context:, current_path:),
effect.batch([init_transport(), "/utf8>>/binary,
Modem_init/binary>>/binary,
", effect.map(ctx_effects, ClientContextUpdate), page_effects]))"/utf8>>;
false ->
<<<<" let flags = transport.read_flags()
let #(page_model, page_effects) = case flags {
\"\" -> init_page(route: route)
_ -> hydrate_page(route, flags)
}
#(Model(route:, page_model:, connection: Disconnected),
effect.batch([init_transport(), "/utf8,
Modem_init/binary>>/binary,
", page_effects]))"/utf8>>
end,
Ctx_update_arm = case Has_client_context of
true ->
<<"
ClientContextUpdate(client_context_msg) -> {
let #(new_client_context, client_context_effects) = client_context.update(model.client_context, client_context_msg)
#(Model(..model, client_context: new_client_context), effect.map(client_context_effects, ClientContextUpdate))
}"/utf8>>;
false ->
<<""/utf8>>
end,
Url_changed_body = case Has_client_context of
true ->
case erlang:element(2, Sync_fields) of
true ->
<<" case route == model.route {
True -> #(model, effect.none())
False -> {
let current_path = router.route_to_path(route)
let new_client_context =
client_context.ClientContext(..model.client_context, current_path:)
let #(page_model, page_effects) = init_page(route: route, client_context: new_client_context)
#(Model(..model, route:, page_model:, client_context: new_client_context, current_path:), page_effects)
}
}"/utf8>>;
false ->
<<" case route == model.route {
True -> #(model, effect.none())
False -> {
let current_path = router.route_to_path(route)
let #(page_model, page_effects) = init_page(route: route, client_context: model.client_context)
#(Model(..model, route:, page_model:, current_path:), page_effects)
}
}"/utf8>>
end;
false ->
<<" case route == model.route {
True -> #(model, effect.none())
False -> {
let #(page_model, page_effects) = init_page(route)
#(Model(..model, route:, page_model:), page_effects)
}
}"/utf8>>
end,
Page_msg_body = case Has_client_context of
true ->
<<" let #(page_model, page_effects, ctx_msg) = update_page(page_model: model.page_model, page_msg: page_msg, client_context: model.client_context)
let #(new_client_context, ctx_effects) = case ctx_msg {
Some(cm) -> {
let #(cc, ce) = client_context.update(model.client_context, cm)
#(cc, effect.map(ce, ClientContextUpdate))
}
None -> #(model.client_context, effect.none())
}
#(Model(..model, page_model:, client_context: new_client_context), effect.batch([page_effects, ctx_effects]))"/utf8>>;
false ->
<<" let #(page_model, page_effects) = update_page(page_model: model.page_model, page_msg: page_msg)
#(Model(..model, page_model:), page_effects)"/utf8>>
end,
Ctx_push_registration = case Has_client_context of
true ->
<<"\n let _ = transport.register_push_handler(\"__ClientContext__\", fn(raw) {\n dispatch(ClientContextUpdate(transport.coerce(raw)))\n })"/utf8>>;
false ->
<<""/utf8>>
end,
Render_page_call = case Has_client_context of
true ->
<<"render_page(model.page_model, model.client_context)"/utf8>>;
false ->
<<"render_page(model.page_model)"/utf8>>
end,
Layout_arms = case Layout_modules of
[] ->
<<""/utf8>>;
_ ->
_pipe@5 = gleam@list:map(
Routes,
fun(Route@1) -> case erlang:element(6, Route@1) of
{some, Layout@1} ->
Variant = <<(erlang:element(3, Route@1))/binary,
"PageModel"/utf8>>,
Alias = module_alias(Layout@1),
case Has_client_context of
true ->
<<<<<<<<" "/utf8, Variant/binary>>/binary,
"(_) ->\n "/utf8>>/binary,
Alias/binary>>/binary,
".layout(model.client_context, ClientContextUpdate, content)\n"/utf8>>;
false ->
<<<<<<<<" "/utf8, Variant/binary>>/binary,
"(_) ->\n "/utf8>>/binary,
Alias/binary>>/binary,
".layout(content)\n"/utf8>>
end;
none ->
<<""/utf8>>
end end
),
_pipe@6 = gleam@string:join(_pipe@5, <<""/utf8>>),
(fun(Arms) -> case Arms of
<<""/utf8>> ->
<<""/utf8>>;
_ ->
<<Arms/binary, " _ -> content\n"/utf8>>
end end)(_pipe@6)
end,
Wrap_layout = case Layout_arms of
<<""/utf8>> ->
<<""/utf8>>;
Arms@1 ->
<<<<"\nfn wrap_layout(model: Model, content: Element(Msg)) -> Element(Msg) {\n case model.page_model {\n"/utf8,
Arms@1/binary>>/binary,
" }\n}\n"/utf8>>
end,
View_body = case Layout_arms of
<<""/utf8>> ->
<<<<" html.div([attr.class(\"rally-app\")], [
"/utf8,
Render_page_call/binary>>/binary,
",
connection_banner(model.connection),
])"/utf8>>;
_ ->
<<<<" let content =
html.div([attr.class(\"rally-app\")], [
"/utf8,
Render_page_call/binary>>/binary,
",
connection_banner(model.connection),
])
wrap_layout(model, content)"/utf8>>
end,
Page_imports = generate_page_imports(Routes, Contract_map),
Option_import = case Has_client_context of
true ->
<<"import gleam/option.{type Option, None, Some}\n"/utf8>>;
false ->
<<""/utf8>>
end,
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"// Generated by Rally — do not edit.
"/utf8,
Option_import/binary>>/binary,
"import lustre
import lustre/attribute as attr
import lustre/element.{type Element}
import lustre/element/html
import lustre/effect.{type Effect}
import modem
import generated/codec
import generated/router
import generated/transport
"/utf8>>/binary,
Rally_effect_import/binary>>/binary,
"@external(javascript, \"../generated/codec_ffi.mjs\", \"ensure_decoders\")
fn ensure_decoders() -> Nil
"/utf8>>/binary,
Page_imports/binary>>/binary,
Ctx_import/binary>>/binary,
Layout_imports/binary>>/binary,
"
"/utf8>>/binary,
Page_model_type/binary>>/binary,
"
"/utf8>>/binary,
Page_msg_type/binary>>/binary,
"
pub type Model {
Model(
route: router.Route,
page_model: PageModel,
connection: Connection,"/utf8>>/binary,
Ctx_field/binary>>/binary,
"
)
}
pub type Connection {
Connected
Disconnected
Reconnecting
}
pub type Msg {
UrlChanged(router.Route)
PageMsg(PageMsg)
TransportConnected
TransportDisconnected(reason: String)"/utf8>>/binary,
Ctx_msg_variant/binary>>/binary,
"
}
pub fn main() {
let app = lustre.application(init, update, view)
lustre.start(app, \"#app\", Nil)
}
fn init(_flags: Nil) -> #(Model, Effect(Msg)) {
let _ = ensure_decoders()
let route = router.parse_route_from_url()
"/utf8>>/binary,
Ctx_init/binary>>/binary,
"
}
fn init_transport() -> Effect(Msg) {
effect.from(fn(dispatch) {
let _ = transport.init(\"/ws\")
let _ = transport.register_on_connect(fn() { dispatch(TransportConnected) })
let _ = transport.register_on_disconnect(fn(reason) { dispatch(TransportDisconnected(reason)) })
"/utf8>>/binary,
Push_registrations/binary>>/binary,
Ctx_push_registration/binary>>/binary,
"
Nil
})
}
"/utf8>>/binary,
Init_page_fn/binary>>/binary,
"
"/utf8>>/binary,
Hydrate_page_fn/binary>>/binary,
"
"/utf8>>/binary,
Reinit_server_fn/binary>>/binary,
"
"/utf8>>/binary,
Update_page_fn/binary>>/binary,
"
"/utf8>>/binary,
Render_page_fn/binary>>/binary,
"
fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
case msg {
UrlChanged(route) -> {
"/utf8>>/binary,
Url_changed_body/binary>>/binary,
"
}
PageMsg(page_msg) -> {
"/utf8>>/binary,
Page_msg_body/binary>>/binary,
"
}
TransportConnected ->
#(Model(..model, connection: Connected), reinit_server(model.route))
TransportDisconnected(_reason) ->
#(Model(..model, connection: Disconnected), effect.none())"/utf8>>/binary,
Ctx_update_arm/binary>>/binary,
"
}
}
"/utf8>>/binary,
Wrap_layout/binary>>/binary,
"
fn view(model: Model) -> Element(Msg) {
"/utf8>>/binary,
View_body/binary>>/binary,
"
}
fn connection_banner(connection: Connection) -> Element(Msg) {
case connection {
Connected -> html.text(\"\")
Disconnected ->
html.div(
[attr.class(\"rally-banner rally-banner--disconnected\")],
[html.text(\"Disconnected from server. Reconnecting...\")],
)
Reconnecting ->
html.div(
[attr.class(\"rally-banner rally-banner--reconnecting\")],
[html.text(\"Reconnecting...\")],
)
}
}
"/utf8>>.
-file("src/rally/generator/client.gleam", 119).
-spec client_router(list(rally@types:scanned_route())) -> binary().
client_router(Routes) ->
Server_router = rally@generator:generate(Routes),
Client_fns = <<"
/// Read the browser's current location.
@external(javascript, \"./router_ffi.mjs\", \"currentUrl\")
fn current_url() -> String
/// Parse the current browser URL into a Route.
pub fn parse_route_from_url() -> Route {
let url = current_url()
let uri = case uri.parse(url) {
Ok(u) -> u
Error(_) -> {
let assert Ok(fallback) = uri.parse(\"http://localhost/\")
fallback
}
}
parse_route(uri)
}
"/utf8>>,
<<<<Server_router/binary, "\n"/utf8>>/binary, Client_fns/binary>>.
-file("src/rally/generator/client.gleam", 774).
-spec router_ffi_mjs() -> binary().
router_ffi_mjs() ->
<<"// Generated by Rally — do not edit.
//
// Browser router FFI — reads the current URL.
// Used by the generated client router.gleam.
export function currentUrl() {
return globalThis.location?.href ?? \"http://localhost/\";
}
"/utf8>>.
-file("src/rally/generator/client.gleam", 238).
-spec transport_gleam(binary()) -> binary().
transport_gleam(_) ->
Protocol_wire = <<"\"./protocol_wire.mjs\""/utf8>>,
Transport_ffi = <<"\"./transport_ffi.mjs\""/utf8>>,
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"// Generated by Rally — do not edit.
import gleam/dynamic.{type Dynamic}
pub type DecodeError {
DecodeError(message: String)
}
/// Initialize the WebSocket connection. Call once on app startup.
@external(javascript, "/utf8,
Transport_ffi/binary>>/binary,
", \"ensureSocket\")
pub fn init(url: String) -> Nil
/// Send a message to the server. The protocol_wire facade encodes
/// the message according to the configured protocol (ETF binary or JSON).
@external(javascript, "/utf8>>/binary,
Transport_ffi/binary>>/binary,
", \"send\")
fn send_raw(
url: String,
page: String,
msg: a,
callback: fn(b) -> Nil,
) -> Nil
/// Register a handler for push messages from the server.
/// The handler is called with the decoded push value whenever
/// the server sends a ToClient for this page.
@external(javascript, "/utf8>>/binary,
Transport_ffi/binary>>/binary,
", \"registerPushHandler\")
pub fn register_push_handler(
page: String,
handler: fn(Dynamic) -> Nil,
) -> Nil
/// Register a callback that fires when the WebSocket connects
/// (both initial connect and reconnects).
@external(javascript, "/utf8>>/binary,
Transport_ffi/binary>>/binary,
", \"registerOnConnect\")
pub fn register_on_connect(callback: fn() -> Nil) -> Nil
/// Register a callback that fires when the WebSocket disconnects.
@external(javascript, "/utf8>>/binary,
Transport_ffi/binary>>/binary,
", \"registerOnDisconnect\")
pub fn register_on_disconnect(callback: fn(String) -> Nil) -> Nil
/// Register a handler that fires when an RPC fails at the framework
/// layer (dispatch errors, malformed requests, decode failures, or
/// connection loss while a call is in flight). Domain-level errors
/// returned by handlers flow through the per-call callback as usual.
@external(javascript, "/utf8>>/binary,
Transport_ffi/binary>>/binary,
", \"registerRpcErrorHandler\")
pub fn register_rpc_error_handler(callback: fn(String) -> Nil) -> Nil
/// Send a ToServer message to the server.
/// Encodes the message and sends it over the WebSocket.
pub fn send_to_server(page: String, msg: a) -> Nil {
send_raw(\"/ws\", page, msg, fn(_) { Nil })
}
/// Send an RPC call and invoke callback with the handler's return value.
/// Framework-level errors do not invoke this callback; they flow through
/// register_rpc_error_handler. User Msg types only need to handle whatever
/// shape the handler returns.
pub fn send_rpc(msg: a, callback: fn(b) -> Nil) -> Nil {
send_raw(\"/ws\", \"rpc\", msg, callback)
}
/// Send route params to initialize the server-side page model.
/// Uses request_id 0 as the init sentinel.
pub fn send_page_init(page: String, params: a) -> Nil {
send_page_init_raw(\"/ws\", page, params)
}
@external(javascript, "/utf8>>/binary,
Transport_ffi/binary>>/binary,
", \"send_page_init\")
fn send_page_init_raw(url: String, page: String, params: a) -> Nil
/// Read SSR flags embedded in the page by the server.
/// Returns empty string if not present.
@external(javascript, "/utf8>>/binary,
Transport_ffi/binary>>/binary,
", \"read_flags\")
pub fn read_flags() -> String
/// Read the server-provided ClientContext from SSR flags.
/// Returns empty string if not present.
@external(javascript, "/utf8>>/binary,
Transport_ffi/binary>>/binary,
", \"read_client_context\")
pub fn read_client_context() -> String
/// Type-level identity cast. The JS runtime representation is unchanged;
/// this lets generated code bridge between Dynamic/generic and concrete types
/// where the value is already the correct shape (decoded ETF, SSR flags).
@external(javascript, "/utf8>>/binary,
Protocol_wire/binary>>/binary,
", \"identity\")
pub fn coerce(value: a) -> b
"/utf8>>.
-file("src/rally/generator/client.gleam", 231).
-spec client_path(binary(), binary()) -> binary().
client_path(Path, Prefix) ->
case gleam_stdlib:string_starts_with(Path, <<"/"/utf8>>) of
true ->
Path;
_ ->
<<Prefix/binary, Path/binary>>
end.
-file("src/rally/generator/client.gleam", 202).
-spec format_dep(binary(), tom:toml(), binary()) -> binary().
format_dep(Name, Value, Prefix) ->
case Value of
{string, Version} ->
<<<<<<Name/binary, " = \""/utf8>>/binary, Version/binary>>/binary,
"\"\n"/utf8>>;
{inline_table, Table} ->
case gleam_stdlib:map_get(Table, <<"path"/utf8>>) of
{ok, {string, Path}} ->
<<<<<<Name/binary, " = { path = \""/utf8>>/binary,
(client_path(Path, Prefix))/binary>>/binary,
"\" }\n"/utf8>>;
_ ->
Entries = begin
_pipe = maps:to_list(Table),
_pipe@1 = gleam@list:map(
_pipe,
fun(Pair) -> case erlang:element(2, Pair) of
{string, S} ->
<<<<<<(erlang:element(1, Pair))/binary,
" = \""/utf8>>/binary,
S/binary>>/binary,
"\""/utf8>>;
_ ->
<<(erlang:element(1, Pair))/binary,
" = \"???\""/utf8>>
end end
),
gleam@string:join(_pipe@1, <<", "/utf8>>)
end,
<<<<<<Name/binary, " = { "/utf8>>/binary, Entries/binary>>/binary,
" }\n"/utf8>>
end;
{table, Table} ->
case gleam_stdlib:map_get(Table, <<"path"/utf8>>) of
{ok, {string, Path}} ->
<<<<<<Name/binary, " = { path = \""/utf8>>/binary,
(client_path(Path, Prefix))/binary>>/binary,
"\" }\n"/utf8>>;
_ ->
Entries = begin
_pipe = maps:to_list(Table),
_pipe@1 = gleam@list:map(
_pipe,
fun(Pair) -> case erlang:element(2, Pair) of
{string, S} ->
<<<<<<(erlang:element(1, Pair))/binary,
" = \""/utf8>>/binary,
S/binary>>/binary,
"\""/utf8>>;
_ ->
<<(erlang:element(1, Pair))/binary,
" = \"???\""/utf8>>
end end
),
gleam@string:join(_pipe@1, <<", "/utf8>>)
end,
<<<<<<Name/binary, " = { "/utf8>>/binary, Entries/binary>>/binary,
" }\n"/utf8>>
end;
_ ->
<<""/utf8>>
end.
-file("src/rally/generator/client.gleam", 185).
-spec is_server_runtime_dep(binary()) -> boolean().
is_server_runtime_dep(Name) ->
gleam@list:contains(
[<<"envoy"/utf8>>,
<<"gleam_erlang"/utf8>>,
<<"gleam_http"/utf8>>,
<<"gleam_time"/utf8>>,
<<"global_value"/utf8>>,
<<"logging"/utf8>>,
<<"mist"/utf8>>,
<<"simplifile"/utf8>>,
<<"sqlight"/utf8>>],
Name
).
-file("src/rally/generator/client.gleam", 144).
-spec client_gleam_toml(
gleam@dict:dict(binary(), tom:toml()),
binary(),
binary()
) -> binary().
client_gleam_toml(Server_deps, Client_root, Protocol) ->
Header = <<"name = \"client\"\nversion = \"0.1.0\"\ntarget = \"javascript\"\n\n[dependencies]\ngleam_stdlib = \">= 0.60.0 and < 2.0.0\"\nlustre = \">= 5.6.0 and < 7.0.0\"\nmodem = \">= 2.0.0 and < 3.0.0\"\n"/utf8>>,
Depth = erlang:length(gleam@string:split(Client_root, <<"/"/utf8>>)),
Prefix = gleam@string:repeat(<<"../"/utf8>>, Depth),
Json_deps = case Protocol of
<<"json"/utf8>> ->
<<"gleam_json = \">= 3.1.0 and < 4.0.0\"\nlibero = \">= 6.0.0 and < 7.0.0\"\n"/utf8>>;
_ ->
<<""/utf8>>
end,
Baseline = gleam@set:from_list(
[<<"gleam_stdlib"/utf8>>, <<"lustre"/utf8>>, <<"modem"/utf8>>]
),
Extra_deps = begin
_pipe = Server_deps,
_pipe@1 = maps:to_list(_pipe),
_pipe@2 = gleam@list:filter(
_pipe@1,
fun(Pair) ->
not gleam@set:contains(Baseline, erlang:element(1, Pair))
end
),
_pipe@3 = gleam@list:filter(
_pipe@2,
fun(Pair@1) ->
(erlang:element(1, Pair@1) /= <<"rally"/utf8>>) andalso (erlang:element(
1,
Pair@1
)
/= <<"marmot"/utf8>>)
end
),
_pipe@4 = gleam@list:filter(_pipe@3, fun(Pair@2) -> case Protocol of
<<"json"/utf8>> ->
(erlang:element(1, Pair@2) /= <<"libero"/utf8>>) andalso (erlang:element(
1,
Pair@2
)
/= <<"gleam_json"/utf8>>);
_ ->
true
end end),
_pipe@5 = gleam@list:filter(
_pipe@4,
fun(Pair@3) ->
not is_server_runtime_dep(erlang:element(1, Pair@3))
end
),
_pipe@6 = gleam@list:sort(
_pipe@5,
fun(A, B) ->
gleam@string:compare(erlang:element(1, A), erlang:element(1, B))
end
),
_pipe@7 = gleam@list:map(
_pipe@6,
fun(Pair@4) ->
format_dep(
erlang:element(1, Pair@4),
erlang:element(2, Pair@4),
Prefix
)
end
),
gleam@string:join(_pipe@7, <<""/utf8>>)
end,
<<<<Header/binary, Json_deps/binary>>/binary, Extra_deps/binary>>.
-file("src/rally/generator/client.gleam", 49).
-spec generate_package_with_client_context_contract(
list(rally@types:scanned_route()),
list({rally@types:scanned_route(), rally@types:page_contract()}),
rally@types:scan_config(),
gleam@dict:dict(binary(), tom:toml()),
binary(),
gleam@option:option(rally@types:client_context_contract()),
binary(),
binary()
) -> list(generated_file()).
generate_package_with_client_context_contract(
Routes,
Contracts,
Config,
Server_deps,
Transport_ffi_content,
Client_context_contract,
Client_context_module,
Protocol
) ->
[{generated_file,
<<(erlang:element(13, Config))/binary, "/gleam.toml"/utf8>>,
client_gleam_toml(Server_deps, erlang:element(13, Config), Protocol)},
{generated_file,
<<(erlang:element(13, Config))/binary,
"/src/generated/transport_ffi.mjs"/utf8>>,
Transport_ffi_content},
{generated_file,
<<(erlang:element(13, Config))/binary,
"/src/generated/transport.gleam"/utf8>>,
transport_gleam(Protocol)},
{generated_file,
<<(erlang:element(13, Config))/binary,
"/src/generated/router_ffi.mjs"/utf8>>,
router_ffi_mjs()},
{generated_file,
<<(erlang:element(13, Config))/binary,
"/src/generated/router.gleam"/utf8>>,
client_router(Routes)},
{generated_file,
<<(erlang:element(13, Config))/binary,
"/src/generated/app.gleam"/utf8>>,
app_gleam(
Routes,
Contracts,
Client_context_contract,
Client_context_module
)},
{generated_file,
<<(erlang:element(13, Config))/binary,
"/src/generated/config.mjs"/utf8>>,
config_mjs(Protocol)}].
-file("src/rally/generator/client.gleam", 26).
-spec generate_package(
list(rally@types:scanned_route()),
list({rally@types:scanned_route(), rally@types:page_contract()}),
rally@types:scan_config(),
gleam@dict:dict(binary(), tom:toml()),
binary(),
boolean()
) -> list(generated_file()).
generate_package(
Routes,
Contracts,
Config,
Server_deps,
Transport_ffi_content,
Has_client_context
) ->
generate_package_with_client_context_contract(
Routes,
Contracts,
Config,
Server_deps,
Transport_ffi_content,
case Has_client_context of
true ->
{some, empty_client_context_contract()};
false ->
none
end,
<<"client_context"/utf8>>,
erlang:element(18, Config)
).