src/rally.erl
-module(rally).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/rally.gleam").
-export([main/0]).
-export_type([rally_error/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(
" CLI entry point for Rally codegen. Reads [[tools.rally.clients]]\n"
" from gleam.toml and runs one codegen pipeline per client namespace:\n"
" scan routes, parse pages, discover handlers via libero, generate\n"
" server and client code, tree-shake, resolve dependencies, write output.\n"
).
-type rally_error() :: {rally_error, binary()}.
-file("src/rally.gleam", 1151).
-spec dirname(binary()) -> binary().
dirname(Path) ->
case begin
_pipe = gleam@string:split(Path, <<"/"/utf8>>),
lists:reverse(_pipe)
end of
[_ | Rest] ->
gleam@string:join(lists:reverse(Rest), <<"/"/utf8>>);
[] ->
<<"."/utf8>>
end.
-file("src/rally.gleam", 1130).
-spec write_if_changed(binary(), binary()) -> {ok, nil} | {error, binary()}.
write_if_changed(Path, Content) ->
case simplifile:read(Path) of
{ok, Existing} when Existing =:= Content ->
{ok, nil};
_ ->
gleam@result:'try'(
begin
_pipe = simplifile:create_directory_all(dirname(Path)),
gleam@result:map_error(
_pipe,
fun(E) ->
<<<<<<"Failed to create directory for "/utf8,
Path/binary>>/binary,
": "/utf8>>/binary,
(simplifile:describe_error(E))/binary>>
end
)
end,
fun(_) -> _pipe@1 = simplifile:write(Path, Content),
gleam@result:map_error(
_pipe@1,
fun(E@1) ->
<<<<<<"Failed to write "/utf8, Path/binary>>/binary,
": "/utf8>>/binary,
(simplifile:describe_error(E@1))/binary>>
end
) end
)
end.
-file("src/rally.gleam", 1118).
-spec write_generated_files(list(rally@generator@client:generated_file())) -> {ok,
nil} |
{error, binary()}.
write_generated_files(Files) ->
gleam@list:try_fold(
Files,
nil,
fun(_, File) ->
Formatted = case gleam_stdlib:string_ends_with(
erlang:element(2, File),
<<".gleam"/utf8>>
) of
true ->
rally@format:format_gleam(erlang:element(3, File));
false ->
erlang:element(3, File)
end,
write_if_changed(erlang:element(2, File), Formatted)
end
).
-file("src/rally.gleam", 1098).
-spec reset_generated_client_src(binary()) -> nil.
reset_generated_client_src(Client_root) ->
_ = simplifile:delete_all([<<Client_root/binary, "/src"/utf8>>]),
nil.
-file("src/rally.gleam", 1199).
-spec take_through_src(list(binary()), list(binary())) -> {ok, list(binary())} |
{error, nil}.
take_through_src(Parts, Acc) ->
case Parts of
[] ->
{error, nil};
[<<"src"/utf8>> | _] ->
{ok, lists:append(Acc, [<<"src"/utf8>>])};
[Part | Rest] ->
take_through_src(Rest, lists:append(Acc, [Part]))
end.
-file("src/rally.gleam", 1188).
-spec split_before_pages(list(binary()), list(binary())) -> {ok, list(binary())} |
{error, nil}.
split_before_pages(Parts, Acc) ->
case Parts of
[] ->
{error, nil};
[<<"pages"/utf8>> | _] ->
{ok, Acc};
[Part | Rest] ->
split_before_pages(Rest, lists:append(Acc, [Part]))
end.
-file("src/rally.gleam", 1176).
-spec source_root_for_pages(binary()) -> binary().
source_root_for_pages(Pages_root) ->
Parts = gleam@string:split(Pages_root, <<"/"/utf8>>),
case split_before_pages(Parts, []) of
{ok, Prefix_parts} ->
case take_through_src(Prefix_parts, []) of
{ok, Src_parts} ->
gleam@string:join(Src_parts, <<"/"/utf8>>);
_ ->
dirname(Pages_root)
end;
_ ->
dirname(Pages_root)
end.
-file("src/rally.gleam", 1103).
-spec last_module_segment(binary()) -> binary().
last_module_segment(Module_path) ->
case gleam@string:split_once(Module_path, <<"pages/"/utf8>>) of
{ok, {_, Rest}} ->
Rest;
_ ->
Module_path
end.
-file("src/rally.gleam", 1210).
-spec copy_layout_modules(
list(rally@types:scanned_route()),
rally@types:scan_config(),
list(binary())
) -> list(rally@generator@client:generated_file()).
copy_layout_modules(Routes, Config, Server_symbols) ->
_pipe = Routes,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Route) -> case erlang:element(6, Route) of
{some, Layout_module} ->
{ok, Layout_module};
none ->
{error, nil}
end end
),
_pipe@2 = gleam@list:unique(_pipe@1),
gleam@list:filter_map(
_pipe@2,
fun(Layout_module@1) ->
File_path = <<<<<<(erlang:element(2, Config))/binary, "/"/utf8>>/binary,
(last_module_segment(Layout_module@1))/binary>>/binary,
".gleam"/utf8>>,
case simplifile:read(File_path) of
{ok, Source} ->
Shaken = rally@tree_shaker:shake(Source, Server_symbols),
Dest = <<<<<<(erlang:element(13, Config))/binary,
"/src/"/utf8>>/binary,
Layout_module@1/binary>>/binary,
".gleam"/utf8>>,
{ok, {generated_file, Dest, Shaken}};
_ ->
{error, nil}
end
end
).
-file("src/rally.gleam", 1059).
?DOC(" Tree-shake client_context.gleam and collect its FFI file if present.\n").
-spec generate_client_context_files(
rally@types:scan_config(),
binary(),
binary(),
list(binary())
) -> list(rally@generator@client:generated_file()).
generate_client_context_files(
Config,
Client_context_path,
Client_context_module,
Server_symbols
) ->
case begin
_pipe = simplifile_erl:is_file(Client_context_path),
gleam@result:unwrap(_pipe, false)
end of
true ->
case simplifile:read(Client_context_path) of
{ok, Cc_source} ->
Shaken = rally@tree_shaker:shake(Cc_source, Server_symbols),
Ffi_path = <<(dirname(erlang:element(2, Config)))/binary,
"/client_context_ffi.mjs"/utf8>>,
Ffi_files = case simplifile:read(Ffi_path) of
{ok, Ffi_content} ->
[{generated_file,
<<<<<<(erlang:element(13, Config))/binary,
"/src/"/utf8>>/binary,
Client_context_module/binary>>/binary,
"_ffi.mjs"/utf8>>,
Ffi_content}];
_ ->
[]
end,
[{generated_file,
<<<<<<(erlang:element(13, Config))/binary,
"/src/"/utf8>>/binary,
Client_context_module/binary>>/binary,
".gleam"/utf8>>,
Shaken} |
Ffi_files];
_ ->
[]
end;
false ->
[]
end.
-file("src/rally.gleam", 1110).
-spec write_file(binary(), binary()) -> {ok, nil} | {error, binary()}.
write_file(Path, Content) ->
Formatted = case gleam_stdlib:string_ends_with(Path, <<".gleam"/utf8>>) of
true ->
rally@format:format_gleam(Content);
false ->
Content
end,
write_if_changed(Path, Formatted).
-file("src/rally.gleam", 1248).
-spec collect_server_symbols(list(libero@scanner:handler_endpoint())) -> list(binary()).
collect_server_symbols(Endpoints) ->
Handler_type_names = gleam@list:filter_map(
Endpoints,
fun(E) -> case erlang:element(8, E) of
{some, {_, Name}} ->
{ok, Name};
none ->
{error, nil}
end end
),
[<<"ServerContext"/utf8>> | Handler_type_names].
-file("src/rally.gleam", 974).
?DOC(
" Generate the Erlang atoms module source. For JSON protocol, extends the\n"
" base module with push dispatch functions and persistent_term registrations.\n"
).
-spec generate_atoms_erl_source(
list(libero@scanner:handler_endpoint()),
list(libero@walker:discovered_type()),
rally@types:scan_config(),
list({binary(), binary()})
) -> binary().
generate_atoms_erl_source(
Ns_endpoints,
Discovered,
Config,
Json_push_dispatches
) ->
Atoms_erl = libero:generate_atoms(
Ns_endpoints,
Discovered,
erlang:element(7, Config),
{some, erlang:element(9, Config)}
),
case erlang:element(18, Config) of
<<"json"/utf8>> ->
Json_codec_mod = gleam@string:replace(
erlang:element(7, Config),
<<"@rpc_atoms"/utf8>>,
<<"@json_codecs"/utf8>>
),
Protocol_wire_mod = gleam@string:replace(
erlang:element(7, Config),
<<"@rpc_atoms"/utf8>>,
<<"@protocol_wire"/utf8>>
),
Push_arms = case Json_push_dispatches of
[] ->
<<" _Page -> error({no_json_push_encoder, Page})\n"/utf8>>;
_ ->
_pipe = gleam@list:map(
Json_push_dispatches,
fun(D) ->
{Page_tag, Type_atom} = D,
<<<<<<<<<<<<" <<\""/utf8, Page_tag/binary>>/binary,
"\">> -> '"/utf8>>/binary,
Json_codec_mod/binary>>/binary,
"':'json_encode_"/utf8>>/binary,
Type_atom/binary>>/binary,
"'(Msg);\n"/utf8>>
end
),
_pipe@1 = gleam@string:join(_pipe, <<""/utf8>>),
(fun(Arms) ->
<<Arms/binary,
" Page -> error({no_json_push_encoder, Page})\n"/utf8>>
end)(_pipe@1)
end,
Atoms_erl@1 = gleam@string:replace(
Atoms_erl,
<<"-export([ensure/0])."/utf8>>,
<<"-export([ensure/0, encode_push_frame/2, json_encode_push_value/2])."/utf8>>
),
Atoms_erl@2 = case gleam@string:split_once(
Atoms_erl@1,
<<"persistent_term:put({?MODULE, done}, true),"/utf8>>
) of
{ok, {Before, After}} ->
<<<<<<<<<<<<<<<<Before/binary,
" persistent_term:put({libero, push_frame_module}, '"/utf8>>/binary,
(erlang:element(7, Config))/binary>>/binary,
"'),\n"/utf8>>/binary,
" persistent_term:put({libero, json_wire_module}, '"/utf8>>/binary,
Protocol_wire_mod/binary>>/binary,
"'),\n"/utf8>>/binary,
" persistent_term:put({?MODULE, done}, true),"/utf8>>/binary,
After/binary>>;
{error, nil} ->
Atoms_erl@1
end,
<<<<<<<<<<<<<<<<<<<<<<<<Atoms_erl@2/binary, "\n\n"/utf8>>/binary,
"%% Push dispatch: route page tag to the correct typed encoder.\n"/utf8>>/binary,
"json_encode_push_value(Page, Msg) ->\n"/utf8>>/binary,
" case Page of\n"/utf8>>/binary,
Push_arms/binary>>/binary,
" end.\n"/utf8>>/binary,
"\n"/utf8>>/binary,
"%% Single push-frame facade called by rally_runtime_ffi.\n"/utf8>>/binary,
"encode_push_frame(Page, Msg) ->\n"/utf8>>/binary,
" JsonValue = json_encode_push_value(Page, Msg),\n"/utf8>>/binary,
" JsonWireMod = persistent_term:get({libero, json_wire_module}),\n"/utf8>>/binary,
" JsonWireMod:encode_push(Page, JsonValue).\n"/utf8>>;
_ ->
Atoms_erl
end.
-file("src/rally.gleam", 601).
-spec do_write_files(
rally@types:scan_config(),
binary(),
binary(),
binary(),
binary(),
list({rally@types:scanned_route(), rally@types:page_contract()}),
list(libero@scanner:handler_endpoint()),
binary(),
gleam@option:option(rally@types:auth_config()),
binary(),
binary(),
binary()
) -> {ok, nil} | {error, rally_error()}.
do_write_files(
Config,
Route_source,
Dispatch_source,
Sd_source,
Ssr_source,
Contracts,
Ns_endpoints,
Rpc_dispatch_module,
Auth_config,
From_session_module,
Protocol_wire_module,
Contract_hash
) ->
Ws_source = rally@generator@ws_handler:generate(
Contracts,
erlang:element(7, Config),
Rpc_dispatch_module,
Auth_config,
From_session_module,
Ns_endpoints,
Protocol_wire_module,
erlang:element(18, Config)
),
gleam@result:'try'(
begin
_pipe = write_file(erlang:element(3, Config), Route_source),
gleam@result:map_error(
_pipe,
fun(Msg) ->
{rally_error, <<"write error: "/utf8, Msg/binary>>}
end
)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@1 = write_file(
erlang:element(4, Config),
Dispatch_source
),
gleam@result:map_error(
_pipe@1,
fun(Msg@1) ->
{rally_error,
<<"write error: "/utf8, Msg@1/binary>>}
end
)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@2 = write_file(
erlang:element(5, Config),
Sd_source
),
gleam@result:map_error(
_pipe@2,
fun(Msg@2) ->
{rally_error,
<<"write error: "/utf8, Msg@2/binary>>}
end
)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@3 = write_file(
erlang:element(10, Config),
Ssr_source
),
gleam@result:map_error(
_pipe@3,
fun(Msg@3) ->
{rally_error,
<<"write error: "/utf8,
Msg@3/binary>>}
end
)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@4 = write_file(
erlang:element(11, Config),
Ws_source
),
gleam@result:map_error(
_pipe@4,
fun(Msg@4) ->
{rally_error,
<<"write error: "/utf8,
Msg@4/binary>>}
end
)
end,
fun(_) ->
gleam@result:'try'(
case Ns_endpoints of
[] ->
{ok, nil};
_ ->
Http_source = rally@generator@http_handler:generate(
Ns_endpoints,
Rpc_dispatch_module,
Auth_config,
Contracts,
From_session_module,
Protocol_wire_module,
erlang:element(
18,
Config
)
),
_pipe@5 = write_file(
erlang:element(
12,
Config
),
Http_source
),
gleam@result:map_error(
_pipe@5,
fun(Msg@5) ->
{rally_error,
<<"write error: "/utf8,
Msg@5/binary>>}
end
)
end,
fun(_) ->
Protocol_wire_output = gleam@string:replace(
erlang:element(
11,
Config
),
<<"ws_handler.gleam"/utf8>>,
<<"protocol_wire.gleam"/utf8>>
),
Protocol_wire_source = rally@generator:generate_protocol_wire(
erlang:element(
18,
Config
),
erlang:element(
7,
Config
),
Contract_hash,
Rpc_dispatch_module,
Ns_endpoints,
Auth_config,
Protocol_wire_module
),
gleam@result:'try'(
begin
_pipe@6 = write_file(
Protocol_wire_output,
Protocol_wire_source
),
gleam@result:map_error(
_pipe@6,
fun(Msg@6) ->
{rally_error,
<<"write error: "/utf8,
Msg@6/binary>>}
end
)
end,
fun(_) -> {ok, nil} end
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/rally.gleam", 1261).
-spec has_to_client_type(
rally@types:scanned_route(),
rally@types:page_contract()
) -> boolean().
has_to_client_type(Route, Contract) ->
gleam@list:any(
erlang:element(3, Contract),
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
) ->
true;
_ ->
false
end;
_ ->
false
end end
).
-file("src/rally.gleam", 927).
?DOC(
" Compute the JSON contract hash for cache busting. Returns \"\" for\n"
" non-JSON protocols.\n"
).
-spec compute_contract_hash(
list({rally@types:scanned_route(), rally@types:page_contract()}),
list(libero@scanner:handler_endpoint()),
list(libero@walker:discovered_type()),
rally@types:scan_config()
) -> binary().
compute_contract_hash(Contracts, Ns_endpoints, Discovered, Config) ->
case erlang:element(18, Config) of
<<"json"/utf8>> ->
Push_contracts = gleam@list:filter_map(
Contracts,
fun(Pair) ->
{Route, Contract} = Pair,
case has_to_client_type(Route, Contract) of
true ->
{ok,
{push_contract,
erlang:element(5, Route),
erlang:element(5, Route),
<<"ToClient"/utf8>>}};
false ->
{error, nil}
end
end
),
Ssr_model_contracts = gleam@list:filter_map(
Contracts,
fun(Pair@1) ->
{Route@1, Contract@1} = Pair@1,
case erlang:element(4, Contract@1) andalso erlang:element(
7,
Contract@1
) of
true ->
{ok,
{ssr_model_contract,
erlang:element(5, Route@1),
erlang:element(5, Route@1),
<<"Model"/utf8>>}};
false ->
{error, nil}
end
end
),
libero@json@contract:generate_hash(
Ns_endpoints,
Discovered,
Push_contracts,
Ssr_model_contracts
);
_ ->
<<""/utf8>>
end.
-file("src/rally.gleam", 882).
?DOC(
" Build push dispatch entries for pages with ToClient types and for\n"
" ClientContextMsg when client context is present.\n"
).
-spec build_push_dispatches(
list({rally@types:scanned_route(), rally@types:page_contract()}),
boolean(),
gleam@option:option(binary()),
binary()
) -> list(libero@etf@codegen_erl:push_dispatch()).
build_push_dispatches(
Contracts,
Has_client_context,
Client_context_source,
Client_context_module
) ->
Page_dispatches = gleam@list:filter_map(
Contracts,
fun(Pair) ->
{Route, Contract} = Pair,
case has_to_client_type(Route, Contract) of
true ->
Type_atom = libero:qualified_atom_name(
erlang:element(5, Route),
<<"ToClient"/utf8>>
),
{ok, {push_dispatch, erlang:element(3, Route), Type_atom}};
false ->
{error, nil}
end
end
),
Cc_dispatch = case {Has_client_context, Client_context_source} of
{true, {some, _}} ->
Type_atom@1 = libero:qualified_atom_name(
Client_context_module,
<<"ClientContextMsg"/utf8>>
),
[{push_dispatch, <<"__ClientContext__"/utf8>>, Type_atom@1}];
{_, _} ->
[]
end,
lists:append(Page_dispatches, Cc_dispatch).
-file("src/rally.gleam", 841).
?DOC(
" Collect type seeds from handlers, client context, page models, and\n"
" ToClient types, then walk the type graph via libero.\n"
).
-spec walk_discovered_types(
list(libero@scanner:handler_endpoint()),
list({rally@types:scanned_route(), rally@types:page_contract()}),
gleam@option:option(binary()),
binary()
) -> list(libero@walker:discovered_type()).
walk_discovered_types(
Ns_endpoints,
Contracts,
Client_context_source,
Client_context_module
) ->
Handler_seeds = libero:collect_seeds(Ns_endpoints),
Cc_seeds = case Client_context_source of
{some, Source} ->
rally@generator@codec:client_context_seeds(
Source,
Client_context_module
);
none ->
[]
end,
Page_model_seeds = gleam@list:filter_map(
Contracts,
fun(Pair) ->
{Route, Contract} = Pair,
case erlang:element(7, Contract) of
true ->
{ok, {erlang:element(5, Route), <<"Model"/utf8>>}};
false ->
{error, nil}
end
end
),
To_client_seeds = gleam@list:filter_map(
Contracts,
fun(Pair@1) ->
{Route@1, Contract@1} = Pair@1,
case has_to_client_type(Route@1, Contract@1) of
true ->
{ok, {erlang:element(5, Route@1), <<"ToClient"/utf8>>}};
false ->
{error, nil}
end
end
),
Seeds = lists:append(
[Handler_seeds, Cc_seeds, Page_model_seeds, To_client_seeds]
),
case libero:walk(Seeds) of
{ok, Types} ->
Types;
{error, Errors} ->
gleam@list:each(Errors, fun libero@gen_error:print_error/1),
[]
end.
-file("src/rally.gleam", 1162).
-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.gleam", 1169).
-spec import_as_string(binary(), binary()) -> binary().
import_as_string(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.gleam", 793).
?DOC(
" Generate the RPC dispatch source via libero, with auth identity threading\n"
" when auth is configured.\n"
).
-spec generate_rpc_dispatch_source(
list(libero@scanner:handler_endpoint()),
rally@types:scan_config(),
gleam@option:option(rally@types:auth_config())
) -> binary().
generate_rpc_dispatch_source(Ns_endpoints, Config, Auth_config) ->
Extra_dispatch_params = case Auth_config of
{some, {auth_config, Auth_module}} ->
Auth_ref = last_segment(Auth_module),
[{extra_param,
<<"identity"/utf8>>,
<<Auth_ref/binary, ".Identity"/utf8>>,
import_as_string(Auth_module, Auth_ref)}];
none ->
[]
end,
Source = case Ns_endpoints of
[] ->
rally@generator:generate_empty_rpc_dispatch(
erlang:element(7, Config),
Extra_dispatch_params
);
_ ->
case Extra_dispatch_params of
[] ->
libero:generate_dispatch(
Ns_endpoints,
{some, erlang:element(7, Config)},
{some, erlang:element(9, Config)}
);
Params ->
libero:generate_dispatch_with_extra_params(
Ns_endpoints,
{some, erlang:element(7, Config)},
{some, erlang:element(9, Config)},
Params
)
end
end,
_pipe = Source,
_pipe@1 = rally@generator:normalize_rpc_dispatch_context_import(_pipe),
rally@generator:normalize_rpc_dispatch_unused_fields(_pipe@1).
-file("src/rally.gleam", 1158).
-spec module_from_src_path(binary()) -> binary().
module_from_src_path(Path) ->
_pipe = Path,
_pipe@1 = gleam@string:drop_start(_pipe, 4),
gleam@string:drop_end(_pipe@1, 6).
-file("src/rally.gleam", 1237).
-spec check_server_context_from_session(binary()) -> {boolean(), binary()}.
check_server_context_from_session(Path) ->
case simplifile:read(Path) of
{ok, Source} ->
case gleam_stdlib:contains_string(
Source,
<<"pub fn from_session"/utf8>>
) of
true ->
{true, <<"server_context"/utf8>>};
false ->
{false, <<"server_context"/utf8>>}
end;
_ ->
{false, <<"server_context"/utf8>>}
end.
-file("src/rally.gleam", 775).
?DOC(
" Find from_session: check client_context_server.gleam first, fall back\n"
" to server_context.gleam.\n"
).
-spec resolve_from_session(binary()) -> {boolean(), binary()}.
resolve_from_session(Pages_root) ->
Server_context_path = <<"src/server_context.gleam"/utf8>>,
Client_context_server_path = <<(dirname(Pages_root))/binary,
"/client_context_server.gleam"/utf8>>,
Client_context_server_module = module_from_src_path(
Client_context_server_path
),
case simplifile:read(Client_context_server_path) of
{ok, Source} ->
case gleam_stdlib:contains_string(
Source,
<<"pub fn from_session"/utf8>>
) of
true ->
{true, Client_context_server_module};
false ->
check_server_context_from_session(Server_context_path)
end;
_ ->
check_server_context_from_session(Server_context_path)
end.
-file("src/rally.gleam", 746).
?DOC(" Read and parse each page module's source to extract its contract.\n").
-spec parse_page_contracts(list(rally@types:scanned_route()), binary()) -> list({rally@types:scanned_route(),
rally@types:page_contract()}).
parse_page_contracts(Routes, Pages_root) ->
gleam@list:filter_map(
Routes,
fun(Route) ->
File_path = <<<<<<Pages_root/binary, "/"/utf8>>/binary,
(last_module_segment(erlang:element(5, Route)))/binary>>/binary,
".gleam"/utf8>>,
case simplifile:read(File_path) of
{ok, Source} ->
case rally@parser:parse_page(
Source,
erlang:element(5, Route)
) of
{ok, Contract} ->
{ok, {Route, Contract}};
_ ->
gleam_stdlib:println_error(
<<<<"warning: failed to parse "/utf8,
File_path/binary>>/binary,
", skipping"/utf8>>
),
{error, nil}
end;
_ ->
gleam_stdlib:println_error(
<<<<"warning: cannot read "/utf8, File_path/binary>>/binary,
", skipping"/utf8>>
),
{error, nil}
end
end
).
-file("src/rally.gleam", 718).
?DOC(
" Scan for server_* handler endpoints via libero. When auth is configured,\n"
" excludes Identity params from the wire contract.\n"
).
-spec discover_endpoints(gleam@option:option(rally@types:auth_config())) -> list(libero@scanner:handler_endpoint()).
discover_endpoints(Auth_config) ->
Exclude_param_types = case Auth_config of
{some, {auth_config, Auth_module}} ->
[{Auth_module, <<"Identity"/utf8>>}];
none ->
[]
end,
case libero:scan_excluding(Exclude_param_types) of
{ok, Endpoints} ->
case Endpoints of
[] ->
nil;
_ ->
gleam_stdlib:println(
<<<<"rally: discovered "/utf8,
(erlang:integer_to_binary(
erlang:length(Endpoints)
))/binary>>/binary,
" handler endpoints via libero"/utf8>>
)
end,
Endpoints;
{error, Errors} ->
gleam@list:each(Errors, fun libero@gen_error:print_error/1),
[]
end.
-file("src/rally.gleam", 690).
?DOC(" Check for an auth.gleam with the required exports alongside the pages dir.\n").
-spec detect_auth(rally@types:scan_config()) -> gleam@option:option(rally@types:auth_config()).
detect_auth(Config) ->
Auth_path = <<(dirname(erlang:element(2, Config)))/binary,
"/auth.gleam"/utf8>>,
case simplifile:read(Auth_path) of
{ok, Source} ->
Auth_module = module_from_src_path(Auth_path),
case ((gleam_stdlib:contains_string(
Source,
<<"pub type Identity"/utf8>>
)
andalso gleam_stdlib:contains_string(
Source,
<<"pub fn resolve"/utf8>>
))
andalso gleam_stdlib:contains_string(
Source,
<<"pub fn is_authenticated"/utf8>>
))
andalso gleam_stdlib:contains_string(
Source,
<<"pub const redirect_url"/utf8>>
) of
true ->
{some, {auth_config, Auth_module}};
false ->
gleam_stdlib:println_error(
<<<<"rally: auth.gleam found at "/utf8,
Auth_path/binary>>/binary,
" but missing required exports (Identity, resolve, is_authenticated, redirect_url)"/utf8>>
),
none
end;
_ ->
none
end.
-file("src/rally.gleam", 258).
-spec generate_for_config(rally@types:scan_config()) -> {ok, nil} |
{error, rally_error()}.
generate_for_config(Config) ->
gleam@result:'try'(
begin
_pipe = rally@scanner:scan(Config),
gleam@result:map_error(
_pipe,
fun(Msg) ->
{rally_error, <<"scan error: "/utf8, Msg/binary>>}
end
)
end,
fun(Routes) ->
Auth_config = detect_auth(Config),
Handler_endpoints = discover_endpoints(Auth_config),
Contracts = parse_page_contracts(Routes, erlang:element(2, Config)),
Client_context_path = <<(dirname(erlang:element(2, Config)))/binary,
"/client_context.gleam"/utf8>>,
Client_context_module = module_from_src_path(Client_context_path),
Has_client_context = begin
_pipe@1 = simplifile_erl:is_file(Client_context_path),
gleam@result:unwrap(_pipe@1, false)
end,
{Has_from_session, From_session_module} = resolve_from_session(
erlang:element(2, Config)
),
Router_module = module_from_src_path(erlang:element(3, Config)),
Rpc_dispatch_module = module_from_src_path(
erlang:element(5, Config)
),
Route_source = rally@generator:generate(Routes),
Dispatch_source = rally@generator:generate_dispatch(
Routes,
Contracts,
Has_client_context,
Router_module,
Client_context_module
),
Namespace_prefix = begin
_pipe@2 = erlang:element(2, Config),
_pipe@3 = gleam@string:drop_start(_pipe@2, 4),
(fun(P) ->
gleam@string:replace(P, <<"/pages"/utf8>>, <<""/utf8>>)
end)(_pipe@3)
end,
Ns_endpoints = gleam@list:filter(
Handler_endpoints,
fun(Ep) ->
gleam_stdlib:string_starts_with(
erlang:element(2, Ep),
<<Namespace_prefix/binary, "/"/utf8>>
)
end
),
Sd_source = generate_rpc_dispatch_source(
Ns_endpoints,
Config,
Auth_config
),
Shell_html = case simplifile:read(erlang:element(16, Config)) of
{ok, Html} ->
Html;
_ ->
<<"<!DOCTYPE html>\n<html>\n<head><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1.0'></head>\n<body><div id='app'></div><script type='module' src='/client.js'></script></body>\n</html>"/utf8>>
end,
Client_context_source = case Has_client_context of
true ->
case simplifile:read(Client_context_path) of
{ok, Source} ->
{some, Source};
_ ->
none
end;
false ->
none
end,
Discovered = walk_discovered_types(
Ns_endpoints,
Contracts,
Client_context_source,
Client_context_module
),
Push_dispatches = build_push_dispatches(
Contracts,
Has_client_context,
Client_context_source,
Client_context_module
),
Json_push_dispatches = gleam@list:map(
Push_dispatches,
fun(D) -> {erlang:element(2, D), erlang:element(3, D)} end
),
Contract_hash = compute_contract_hash(
Contracts,
Ns_endpoints,
Discovered,
Config
),
Protocol_wire_output = gleam@string:replace(
erlang:element(11, Config),
<<"ws_handler.gleam"/utf8>>,
<<"protocol_wire.gleam"/utf8>>
),
Protocol_wire_module = begin
_pipe@4 = Protocol_wire_output,
_pipe@5 = gleam@string:drop_start(_pipe@4, 4),
gleam@string:drop_end(_pipe@5, 6)
end,
Ssr_source = rally@generator@ssr_handler:generate(
Contracts,
Has_client_context,
Has_from_session,
From_session_module,
Router_module,
Shell_html,
erlang:element(7, Config),
{some, erlang:element(9, Config)},
case Has_client_context of
true ->
{some, Client_context_module};
false ->
none
end,
Auth_config,
Protocol_wire_module,
erlang:element(18, Config)
),
Result = do_write_files(
Config,
Route_source,
Dispatch_source,
Sd_source,
Ssr_source,
Contracts,
Ns_endpoints,
Rpc_dispatch_module,
Auth_config,
From_session_module,
Protocol_wire_module,
Contract_hash
),
gleam@result:'try'(
Result,
fun(_) ->
Transport_ffi_path = <<(erlang:element(15, Config))/binary,
"/src/rally_runtime/transport_ffi.mjs"/utf8>>,
gleam@result:'try'(
begin
_pipe@6 = simplifile:read(Transport_ffi_path),
gleam@result:map_error(
_pipe@6,
fun(E) ->
{rally_error,
<<<<<<"Cannot read transport_ffi.mjs from rally package at "/utf8,
Transport_ffi_path/binary>>/binary,
": "/utf8>>/binary,
(simplifile:describe_error(E))/binary>>}
end
)
end,
fun(Transport_ffi_content) ->
Atoms_erl = generate_atoms_erl_source(
Ns_endpoints,
Discovered,
Config,
Json_push_dispatches
),
gleam@result:'try'(
begin
_pipe@7 = write_file(
erlang:element(6, Config),
Atoms_erl
),
gleam@result:map_error(
_pipe@7,
fun(Msg@1) ->
{rally_error,
<<"write error: "/utf8,
Msg@1/binary>>}
end
)
end,
fun(_) ->
Wire_erl = case libero:generate_wire_erl(
Discovered,
erlang:element(9, Config),
Ns_endpoints,
Push_dispatches
) of
{ok, Src} ->
Src;
{error, Err} ->
libero@gen_error:print_error(Err),
<<""/utf8>>
end,
gleam@result:'try'(
begin
_pipe@8 = write_file(
erlang:element(8, Config),
Wire_erl
),
gleam@result:map_error(
_pipe@8,
fun(Msg@2) ->
{rally_error,
<<"write error: "/utf8,
Msg@2/binary>>}
end
)
end,
fun(_) ->
Server_symbols = collect_server_symbols(
Ns_endpoints
),
gleam@result:'try'(
case Client_context_source of
{some, Source@1} ->
_pipe@9 = rally@parser:parse_client_context(
Source@1
),
_pipe@10 = gleam@result:map(
_pipe@9,
fun(Field@0) -> {some, Field@0} end
),
gleam@result:map_error(
_pipe@10,
fun(Error) ->
{rally_error,
<<"Cannot parse client_context.gleam: "/utf8,
Error/binary>>}
end
);
none ->
{ok, none}
end,
fun(Client_context_contract) ->
Raw_codec_files = rally@generator@codec:generate(
Contracts,
Discovered,
Ns_endpoints,
Server_symbols,
erlang:element(
18,
Config
)
),
Codec_files = gleam@list:map(
Raw_codec_files,
fun(F) ->
{generated_file,
<<<<(erlang:element(
13,
Config
))/binary,
"/"/utf8>>/binary,
(erlang:element(
2,
F
))/binary>>,
erlang:element(
3,
F
)}
end
),
gleam@result:'try'(
case erlang:element(
18,
Config
) of
<<"json"/utf8>> ->
Files = rally@generator@codec:generate_json_codecs(
Discovered,
Ns_endpoints
),
case Files of
[] ->
{error,
{rally_error,
<<"JSON codec generation failed - no codec files produced"/utf8>>}};
_ ->
{ok,
Files}
end;
_ ->
{ok, []}
end,
fun(Json_codec_files) ->
gleam@result:'try'(
case erlang:element(
18,
Config
) of
<<"json"/utf8>> ->
case Json_codec_files of
[] ->
{ok,
nil};
[First |
_] ->
Server_path = gleam@string:replace(
erlang:element(
10,
Config
),
<<"ssr_handler.gleam"/utf8>>,
<<"json_codecs.gleam"/utf8>>
),
_pipe@11 = write_file(
Server_path,
erlang:element(
3,
First
)
),
gleam@result:map_error(
_pipe@11,
fun(
Msg@3
) ->
{rally_error,
<<"write error: "/utf8,
Msg@3/binary>>}
end
)
end;
_ ->
{ok,
nil}
end,
fun(_) ->
Client_files = begin
_pipe@12 = rally@generator@client:generate_package_with_client_context_contract(
Routes,
Contracts,
Config,
erlang:element(
17,
Config
),
Transport_ffi_content,
Client_context_contract,
Client_context_module,
erlang:element(
18,
Config
)
),
_pipe@13 = lists:append(
_pipe@12,
[{generated_file,
<<(erlang:element(
13,
Config
))/binary,
"/src/generated/protocol_wire.mjs"/utf8>>,
rally@generator:generate_protocol_wire_js(
erlang:element(
18,
Config
),
Contract_hash
)}]
),
lists:append(
_pipe@13,
gleam@list:filter_map(
Json_codec_files,
fun(
F@1
) ->
case erlang:element(
2,
F@1
)
=:= <<"src/generated/type_registry.mjs"/utf8>> of
true ->
{ok,
{generated_file,
<<(erlang:element(
13,
Config
))/binary,
"/src/generated/type_registry.mjs"/utf8>>,
erlang:element(
3,
F@1
)}};
false ->
{error,
nil}
end
end
)
)
end,
Client_context_files = generate_client_context_files(
Config,
Client_context_path,
Client_context_module,
Server_symbols
),
Layout_files = copy_layout_modules(
Routes,
Config,
Server_symbols
),
Seed_sources = lists:append(
[begin
_pipe@14 = Raw_codec_files,
_pipe@15 = gleam@list:filter(
_pipe@14,
fun(
F@2
) ->
(gleam_stdlib:string_ends_with(
erlang:element(
2,
F@2
),
<<".gleam"/utf8>>
)
andalso gleam_stdlib:string_starts_with(
erlang:element(
2,
F@2
),
<<"src/"/utf8>>
))
andalso gleam_stdlib:contains_string(
erlang:element(
2,
F@2
),
<<"/pages/"/utf8>>
)
end
),
gleam@list:map(
_pipe@15,
fun(
F@3
) ->
Module_path = begin
_pipe@16 = erlang:element(
2,
F@3
),
_pipe@17 = gleam@string:drop_start(
_pipe@16,
4
),
gleam@string:drop_end(
_pipe@17,
6
)
end,
{Module_path,
erlang:element(
3,
F@3
)}
end
)
end,
begin
_pipe@18 = Layout_files,
_pipe@19 = gleam@list:filter(
_pipe@18,
fun(
F@4
) ->
gleam_stdlib:string_ends_with(
erlang:element(
2,
F@4
),
<<".gleam"/utf8>>
)
end
),
gleam@list:map(
_pipe@19,
fun(
F@5
) ->
Module_path@1 = begin
_pipe@20 = erlang:element(
2,
F@5
),
_pipe@21 = gleam@string:replace(
_pipe@20,
<<(erlang:element(
13,
Config
))/binary,
"/src/"/utf8>>,
<<""/utf8>>
),
gleam@string:drop_end(
_pipe@21,
6
)
end,
{Module_path@1,
erlang:element(
3,
F@5
)}
end
)
end,
begin
_pipe@22 = Client_context_files,
gleam@list:map(
_pipe@22,
fun(
F@6
) ->
{Client_context_module,
erlang:element(
3,
F@6
)}
end
)
end]
),
gleam@result:'try'(
begin
_pipe@23 = rally@dependency_resolver:resolve(
Seed_sources,
source_root_for_pages(
erlang:element(
2,
Config
)
),
erlang:element(
13,
Config
)
),
gleam@result:map_error(
_pipe@23,
fun(
Msg@4
) ->
{rally_error,
<<"dependency resolution error: "/utf8,
Msg@4/binary>>}
end
)
end,
fun(
Dependency_files
) ->
reset_generated_client_src(
erlang:element(
13,
Config
)
),
gleam@result:'try'(
begin
_pipe@24 = write_generated_files(
lists:append(
[Codec_files,
Client_files,
Client_context_files,
Layout_files,
Dependency_files]
)
),
gleam@result:map_error(
_pipe@24,
fun(
Msg@5
) ->
{rally_error,
<<"write error: "/utf8,
Msg@5/binary>>}
end
)
end,
fun(
_
) ->
_ = case simplifile:read(
erlang:element(
4,
Config
)
) of
{ok,
Content} ->
case (not gleam_stdlib:contains_string(
Content,
<<"pub fn"/utf8>>
)
andalso not gleam_stdlib:contains_string(
Content,
<<"pub type"/utf8>>
))
andalso not gleam_stdlib:contains_string(
Content,
<<"pub const"/utf8>>
) of
true ->
simplifile_erl:delete(
erlang:element(
4,
Config
)
);
false ->
{ok,
nil}
end;
_ ->
{ok,
nil}
end,
{ok,
nil}
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/rally.gleam", 174).
-spec read_legacy_config(
gleam@dict:dict(binary(), tom:toml()),
gleam@dict:dict(binary(), tom:toml()),
binary()
) -> rally@types:scan_config().
read_legacy_config(Rally_config, Server_deps, Rally_package_path) ->
Pages_root = begin
_pipe = tom:get_string(Rally_config, [<<"pages_root"/utf8>>]),
gleam@result:unwrap(_pipe, <<"src/pages"/utf8>>)
end,
Output_route = begin
_pipe@1 = tom:get_string(Rally_config, [<<"output_route"/utf8>>]),
gleam@result:unwrap(_pipe@1, <<"src/generated/router.gleam"/utf8>>)
end,
Output_dispatch = begin
_pipe@2 = tom:get_string(Rally_config, [<<"output_dispatch"/utf8>>]),
gleam@result:unwrap(
_pipe@2,
<<"src/generated/page_dispatch.gleam"/utf8>>
)
end,
Output_server_dispatch = begin
_pipe@3 = tom:get_string(
Rally_config,
[<<"output_server_dispatch"/utf8>>]
),
gleam@result:unwrap(
_pipe@3,
<<"src/generated/rpc_dispatch.gleam"/utf8>>
)
end,
Output_server_atoms = begin
_pipe@4 = tom:get_string(Rally_config, [<<"output_server_atoms"/utf8>>]),
gleam@result:unwrap(_pipe@4, <<"src/generated@rpc_atoms.erl"/utf8>>)
end,
Atoms_module = <<"generated@rpc_atoms"/utf8>>,
Wire_module = <<"generated@rpc_wire"/utf8>>,
Output_ssr = begin
_pipe@5 = tom:get_string(Rally_config, [<<"output_ssr"/utf8>>]),
gleam@result:unwrap(_pipe@5, <<"src/generated/ssr_handler.gleam"/utf8>>)
end,
Output_ws = begin
_pipe@6 = tom:get_string(Rally_config, [<<"output_ws"/utf8>>]),
gleam@result:unwrap(_pipe@6, <<"src/generated/ws_handler.gleam"/utf8>>)
end,
Output_http = begin
_pipe@7 = tom:get_string(Rally_config, [<<"output_http"/utf8>>]),
gleam@result:unwrap(
_pipe@7,
<<"src/generated/http_handler.gleam"/utf8>>
)
end,
Client_root = begin
_pipe@8 = tom:get_string(Rally_config, [<<"client_root"/utf8>>]),
gleam@result:unwrap(_pipe@8, <<".generated_clients"/utf8>>)
end,
Route_root = begin
_pipe@9 = tom:get_string(Rally_config, [<<"route_root"/utf8>>]),
gleam@result:unwrap(_pipe@9, <<"/"/utf8>>)
end,
Shell_file = begin
_pipe@10 = tom:get_string(Rally_config, [<<"shell_file"/utf8>>]),
gleam@result:unwrap(_pipe@10, <<"src/shell.html"/utf8>>)
end,
Protocol = <<"etf"/utf8>>,
{scan_config,
Pages_root,
Output_route,
Output_dispatch,
Output_server_dispatch,
Output_server_atoms,
Atoms_module,
<<"src/generated@rpc_wire.erl"/utf8>>,
Wire_module,
Output_ssr,
Output_ws,
Output_http,
Client_root,
Route_root,
Rally_package_path,
Shell_file,
Server_deps,
Protocol}.
-file("src/rally.gleam", 1287).
-spec tom_get_error_to_string(tom:get_error()) -> binary().
tom_get_error_to_string(E) ->
case E of
{not_found, Key} ->
<<"key not found: "/utf8,
(gleam@string:join(Key, <<"."/utf8>>))/binary>>;
{wrong_type, Key@1, Expected, Got} ->
<<<<<<<<<<"expected "/utf8, Expected/binary>>/binary,
", got "/utf8>>/binary,
Got/binary>>/binary,
" at "/utf8>>/binary,
(gleam@string:join(Key@1, <<"."/utf8>>))/binary>>
end.
-file("src/rally.gleam", 119).
-spec read_client_config(
gleam@dict:dict(binary(), tom:toml()),
gleam@dict:dict(binary(), tom:toml()),
binary()
) -> {ok, rally@types:scan_config()} | {error, rally_error()}.
read_client_config(Client_config, Server_deps, Rally_package_path) ->
gleam@result:'try'(
begin
_pipe = tom:get_string(Client_config, [<<"namespace"/utf8>>]),
gleam@result:map_error(
_pipe,
fun(E) ->
{rally_error,
<<"Each [[tools.rally.clients]] entry needs namespace = \"...\": "/utf8,
(tom_get_error_to_string(E))/binary>>}
end
)
end,
fun(Namespace) ->
Route_root = begin
_pipe@1 = tom:get_string(Client_config, [<<"route_root"/utf8>>]),
gleam@result:unwrap(_pipe@1, <<"/"/utf8, Namespace/binary>>)
end,
Protocol = begin
_pipe@2 = tom:get_string(Client_config, [<<"protocol"/utf8>>]),
gleam@result:unwrap(_pipe@2, <<"etf"/utf8>>)
end,
Protocol@1 = case Protocol of
<<"etf"/utf8>> ->
Protocol;
<<"json"/utf8>> ->
Protocol;
Other ->
gleam_stdlib:println_error(
<<<<"warning: unknown protocol \""/utf8, Other/binary>>/binary,
"\" in [[tools.rally.clients]], defaulting to \"etf\""/utf8>>
),
<<"etf"/utf8>>
end,
{ok,
{scan_config,
<<<<"src/"/utf8, Namespace/binary>>/binary, "/pages"/utf8>>,
<<<<"src/generated/"/utf8, Namespace/binary>>/binary,
"/router.gleam"/utf8>>,
<<<<"src/generated/"/utf8, Namespace/binary>>/binary,
"/page_dispatch.gleam"/utf8>>,
<<<<"src/generated/"/utf8, Namespace/binary>>/binary,
"/rpc_dispatch.gleam"/utf8>>,
<<<<"src/generated@"/utf8, Namespace/binary>>/binary,
"@rpc_atoms.erl"/utf8>>,
<<<<"generated@"/utf8, Namespace/binary>>/binary,
"@rpc_atoms"/utf8>>,
<<<<"src/generated@"/utf8, Namespace/binary>>/binary,
"@rpc_wire.erl"/utf8>>,
<<<<"generated@"/utf8, Namespace/binary>>/binary,
"@rpc_wire"/utf8>>,
<<<<"src/generated/"/utf8, Namespace/binary>>/binary,
"/ssr_handler.gleam"/utf8>>,
<<<<"src/generated/"/utf8, Namespace/binary>>/binary,
"/ws_handler.gleam"/utf8>>,
<<<<"src/generated/"/utf8, Namespace/binary>>/binary,
"/http_handler.gleam"/utf8>>,
<<".generated_clients/"/utf8, Namespace/binary>>,
Route_root,
Rally_package_path,
<<<<"src/"/utf8, Namespace/binary>>/binary,
"/shell.html"/utf8>>,
Server_deps,
Protocol@1}}
end
).
-file("src/rally.gleam", 1279).
-spec tom_error_to_string(tom:parse_error()) -> binary().
tom_error_to_string(E) ->
case E of
{unexpected, Got, Expected} ->
<<<<<<"unexpected character '"/utf8, Got/binary>>/binary,
"', expected "/utf8>>/binary,
Expected/binary>>;
{key_already_in_use, Key} ->
<<"duplicate key: "/utf8,
(gleam@string:join(Key, <<"."/utf8>>))/binary>>
end.
-file("src/rally.gleam", 55).
-spec read_configs() -> {ok, list(rally@types:scan_config())} |
{error, rally_error()}.
read_configs() ->
gleam@result:'try'(
begin
_pipe = simplifile:read(<<"gleam.toml"/utf8>>),
gleam@result:map_error(
_pipe,
fun(E) ->
{rally_error,
<<"Cannot read gleam.toml: "/utf8,
(simplifile:describe_error(E))/binary>>}
end
)
end,
fun(Toml_str) ->
gleam@result:'try'(
begin
_pipe@1 = tom:parse(Toml_str),
gleam@result:map_error(
_pipe@1,
fun(E@1) ->
{rally_error,
<<"Invalid gleam.toml: "/utf8,
(tom_error_to_string(E@1))/binary>>}
end
)
end,
fun(Toml_map) ->
Rally_config = begin
_pipe@2 = tom:get_table(
Toml_map,
[<<"tools"/utf8>>, <<"rally"/utf8>>]
),
gleam@result:unwrap(_pipe@2, maps:new())
end,
Server_deps = begin
_pipe@3 = tom:get_table(
Toml_map,
[<<"dependencies"/utf8>>]
),
gleam@result:unwrap(_pipe@3, maps:new())
end,
Rally_package_path = (case gleam_stdlib:map_get(
Server_deps,
<<"rally"/utf8>>
) of
{ok, {inline_table, Rally_dep}} ->
case gleam_stdlib:map_get(
Rally_dep,
<<"path"/utf8>>
) of
{ok, {string, Path}} ->
Path;
_ ->
<<".."/utf8>>
end;
{ok, {table, Rally_dep}} ->
case gleam_stdlib:map_get(
Rally_dep,
<<"path"/utf8>>
) of
{ok, {string, Path}} ->
Path;
_ ->
<<".."/utf8>>
end;
_ ->
<<".."/utf8>>
end),
case tom:get_array(Rally_config, [<<"clients"/utf8>>]) of
{ok, Clients} ->
gleam@result:'try'(
gleam@list:try_map(
Clients,
fun(Client) -> case Client of
{table, Cfg} ->
read_client_config(
Cfg,
Server_deps,
Rally_package_path
);
{inline_table, Cfg} ->
read_client_config(
Cfg,
Server_deps,
Rally_package_path
);
_ ->
{error,
{rally_error,
<<"Each [[tools.rally.clients]] entry must be a table"/utf8>>}}
end end
),
fun(Configs) -> case Configs of
[] ->
{ok,
[read_legacy_config(
Rally_config,
Server_deps,
Rally_package_path
)]};
_ ->
{ok, Configs}
end end
);
_ ->
{ok,
[read_legacy_config(
Rally_config,
Server_deps,
Rally_package_path
)]}
end
end
)
end
).
-file("src/rally.gleam", 237).
-spec run(list(binary())) -> {ok, binary()} | {error, rally_error()}.
run(Args) ->
case Args of
[<<"init"/utf8>>] ->
gleam@result:'try'(
begin
_pipe = rally@init:init_project(<<"."/utf8>>),
gleam@result:map_error(
_pipe,
fun(Msg) ->
{rally_error, <<"init error: "/utf8, Msg/binary>>}
end
)
end,
fun(_use0) ->
nil = _use0,
{ok, <<"initialized project"/utf8>>}
end
);
[] ->
gleam@result:'try'(
read_configs(),
fun(Configs) ->
gleam@result:'try'(
gleam@list:try_each(Configs, fun generate_for_config/1),
fun(_use0@1) ->
nil = _use0@1,
{ok,
<<(erlang:integer_to_binary(
erlang:length(Configs)
))/binary,
" client(s)"/utf8>>}
end
)
end
);
[<<"gen"/utf8>>] ->
gleam@result:'try'(
read_configs(),
fun(Configs) ->
gleam@result:'try'(
gleam@list:try_each(Configs, fun generate_for_config/1),
fun(_use0@1) ->
nil = _use0@1,
{ok,
<<(erlang:integer_to_binary(
erlang:length(Configs)
))/binary,
" client(s)"/utf8>>}
end
)
end
);
_ ->
{error,
{rally_error,
<<"Unknown command. Run `gleam run -m rally` for codegen or `gleam run -m rally init` to scaffold the current project."/utf8>>}}
end.
-file("src/rally.gleam", 41).
-spec main() -> nil.
main() ->
Args = erlang:element(4, argv:load()),
case run(Args) of
{ok, Msg} ->
gleam_stdlib:println(<<"rally: "/utf8, Msg/binary>>);
{error, {rally_error, Msg@1}} ->
gleam_stdlib:println_error(<<"rally error: "/utf8, Msg@1/binary>>),
erlang:halt(1)
end.