Current section
Files
Jump to
Current section
Files
src/libero@cli@gen.erl
-module(libero@cli@gen).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/libero/cli/gen.gleam").
-export([run/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(
" `libero gen` — TOML-driven codegen command.\n"
"\n"
" Reads `gleam.toml` from the project path, scans `shared/src/shared/` for\n"
" message modules, validates conventions, and runs the full codegen pipeline\n"
" for each declared client.\n"
).
-file("src/libero/cli/gen.gleam", 290).
?DOC(" Best-effort delete — ignores errors (file may not exist).\n").
-spec delete_if_exists(binary()) -> nil.
delete_if_exists(Path) ->
_pipe = simplifile_erl:delete(Path),
gleam@result:unwrap(_pipe, nil).
-file("src/libero/cli/gen.gleam", 161).
-spec run_client_codegen(
binary(),
libero@toml_config:toml_config(),
libero@toml_config:client_config(),
list(libero@scanner:message_module()),
list(libero@walker:discovered_type())
) -> {ok, nil} | {error, binary()}.
run_client_codegen(Project_path, Toml_cfg, Client, Message_modules, Discovered) ->
gleam_stdlib:println(
<<"libero: generating stubs for client: "/utf8,
(erlang:element(2, Client))/binary>>
),
gleam@result:'try'(
libero@toml_config:to_codegen_config(
Toml_cfg,
erlang:element(2, Client),
<<"/ws"/utf8>>
),
fun(Config) ->
Server_generated = <<<<Project_path/binary, "/"/utf8>>/binary,
(erlang:element(14, Config))/binary>>,
Client_generated = <<<<Project_path/binary, "/"/utf8>>/binary,
(erlang:element(15, Config))/binary>>,
gleam@result:'try'(
begin
_pipe = simplifile:create_directory_all(Server_generated),
gleam@result:map_error(
_pipe,
fun(Err) ->
<<<<<<"cannot create directory "/utf8,
Server_generated/binary>>/binary,
": "/utf8>>/binary,
(simplifile:describe_error(Err))/binary>>
end
)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@1 = simplifile:create_directory_all(
Client_generated
),
gleam@result:map_error(
_pipe@1,
fun(Err@1) ->
<<<<<<"cannot create directory "/utf8,
Client_generated/binary>>/binary,
": "/utf8>>/binary,
(simplifile:describe_error(Err@1))/binary>>
end
)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@2 = libero@codegen:write_dispatch(
Message_modules,
erlang:element(14, Config),
erlang:element(6, Config),
erlang:element(10, Toml_cfg),
erlang:element(11, Toml_cfg)
),
gleam@result:map_error(
_pipe@2,
fun(Err@2) ->
libero@gen_error:print_error(Err@2),
<<"write_dispatch failed"/utf8>>
end
)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@3 = libero@codegen:write_push_wrappers(
Message_modules,
erlang:element(14, Config)
),
gleam@result:map_error(
_pipe@3,
fun(Errors) ->
gleam@list:each(
Errors,
fun libero@gen_error:print_error/1
),
<<"write_push_wrappers failed"/utf8>>
end
)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@4 = libero@codegen:write_websocket(
erlang:element(
14,
Config
),
erlang:element(
10,
Toml_cfg
)
),
gleam@result:map_error(
_pipe@4,
fun(Err@3) ->
libero@gen_error:print_error(
Err@3
),
<<"write_websocket failed"/utf8>>
end
)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@5 = libero@codegen:write_atoms(
Config,
Discovered
),
gleam@result:map_error(
_pipe@5,
fun(Err@4) ->
libero@gen_error:print_error(
Err@4
),
<<"write_atoms failed"/utf8>>
end
)
end,
fun(_) ->
delete_if_exists(
<<(erlang:element(
15,
Config
))/binary,
"/rpc_register.gleam"/utf8>>
),
delete_if_exists(
<<(erlang:element(
15,
Config
))/binary,
"/rpc_register_ffi.mjs"/utf8>>
),
gleam@result:'try'(
begin
_pipe@6 = libero@codegen:write_send_functions(
Message_modules,
erlang:element(
15,
Config
)
),
gleam@result:map_error(
_pipe@6,
fun(
Errors@1
) ->
gleam@list:each(
Errors@1,
fun libero@gen_error:print_error/1
),
<<"write_send_functions failed"/utf8>>
end
)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@7 = libero@codegen:write_config(
Config
),
gleam@result:map_error(
_pipe@7,
fun(
Err@5
) ->
libero@gen_error:print_error(
Err@5
),
<<"write_config failed"/utf8>>
end
)
end,
fun(_) ->
gleam@result:'try'(
begin
_pipe@8 = libero@codegen:write_decoders_gleam(
Config
),
gleam@result:map_error(
_pipe@8,
fun(
Err@6
) ->
libero@gen_error:print_error(
Err@6
),
<<"write_decoders_gleam failed"/utf8>>
end
)
end,
fun(
_
) ->
gleam@result:'try'(
begin
_pipe@9 = libero@codegen:write_decoders_ffi(
Config,
Discovered
),
gleam@result:map_error(
_pipe@9,
fun(
Err@7
) ->
libero@gen_error:print_error(
Err@7
),
<<"write_decoders_ffi failed"/utf8>>
end
)
end,
fun(
_
) ->
gleam@result:'try'(
begin
_pipe@10 = libero@codegen:write_ssr_flags(
erlang:element(
15,
Config
)
),
gleam@result:map_error(
_pipe@10,
fun(
Err@8
) ->
libero@gen_error:print_error(
Err@8
),
<<"write_ssr_flags failed"/utf8>>
end
)
end,
fun(
_
) ->
{ok,
nil}
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/libero/cli/gen.gleam", 49).
-spec run_with_clients(
binary(),
libero@toml_config:toml_config(),
list(libero@toml_config:client_config())
) -> {ok, nil} | {error, binary()}.
run_with_clients(Project_path, Toml_cfg, Clients) ->
Shared_src = <<<<Project_path/binary, "/"/utf8>>/binary,
(erlang:element(9, Toml_cfg))/binary>>,
Server_src = <<<<Project_path/binary, "/"/utf8>>/binary,
(erlang:element(6, Toml_cfg))/binary>>,
gleam@result:'try'(
begin
_pipe = libero@scanner:scan_message_modules(Shared_src),
gleam@result:map_error(
_pipe,
fun(Errors) ->
gleam@list:each(Errors, fun libero@gen_error:print_error/1),
<<"scan failed"/utf8>>
end
)
end,
fun(_use0) ->
{Message_modules, Module_files} = _use0,
gleam_stdlib:println(
<<<<<<"libero: found "/utf8,
(erlang:integer_to_binary(
erlang:length(Message_modules)
))/binary>>/binary,
" message module(s) in "/utf8>>/binary,
(erlang:element(9, Toml_cfg))/binary>>
),
Shared_state_path = <<<<<<Server_src/binary, "/"/utf8>>/binary,
(erlang:element(10, Toml_cfg))/binary>>/binary,
".gleam"/utf8>>,
App_error_path = <<<<<<Server_src/binary, "/"/utf8>>/binary,
(erlang:element(11, Toml_cfg))/binary>>/binary,
".gleam"/utf8>>,
gleam@result:'try'(
begin
_pipe@1 = libero@scanner:validate_conventions(
Message_modules,
Server_src,
Shared_state_path,
App_error_path
),
gleam@result:map_error(
_pipe@1,
fun(Errors@1) ->
gleam@list:each(
Errors@1,
fun libero@gen_error:print_error/1
),
<<"convention validation failed"/utf8>>
end
)
end,
fun(Message_modules@1) ->
gleam@result:'try'(
begin
_pipe@2 = libero@scanner:validate_msg_from_server_fields(
Message_modules@1
),
gleam@result:map_error(
_pipe@2,
fun(Errors@2) ->
gleam@list:each(
Errors@2,
fun libero@gen_error:print_error/1
),
<<"MsgFromServer field validation failed"/utf8>>
end
)
end,
fun(_) ->
gleam@result:'try'(
libero@codegen:check_segment_collisions(
Message_modules@1
),
fun(_) ->
gleam@result:'try'(
begin
_pipe@3 = libero@walker:walk_message_registry_types(
Message_modules@1,
Module_files
),
gleam@result:map_error(
_pipe@3,
fun(Errors@3) ->
gleam@list:each(
Errors@3,
fun libero@gen_error:print_error/1
),
<<"type walk failed"/utf8>>
end
)
end,
fun(Discovered) ->
gleam@result:'try'(
gleam@list:try_map(
Clients,
fun(Client) ->
run_client_codegen(
Project_path,
Toml_cfg,
Client,
Message_modules@1,
Discovered
)
end
),
fun(_) ->
Js_client_names = gleam@list:filter_map(
Clients,
fun(C) ->
case erlang:element(
3,
C
) of
<<"javascript"/utf8>> ->
{ok,
erlang:element(
2,
C
)};
_ ->
{error, nil}
end
end
),
gleam@result:'try'(
begin
_pipe@4 = libero@codegen:write_main(
erlang:element(
2,
Toml_cfg
),
erlang:element(
3,
Toml_cfg
),
erlang:element(
7,
Toml_cfg
),
erlang:element(
10,
Toml_cfg
),
Js_client_names
),
gleam@result:map_error(
_pipe@4,
fun(Err) ->
libero@gen_error:print_error(
Err
),
<<"write_main failed"/utf8>>
end
)
end,
fun(_) ->
gleam_stdlib:println(
<<"libero: done"/utf8>>
),
{ok, nil}
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/libero/cli/gen.gleam", 23).
?DOC(
" Run the `gen` command from the given project path (usually `\".\"`).\n"
"\n"
" Reads `gleam.toml`, discovers message modules under `shared/src/shared/`, validates\n"
" conventions, and runs codegen for each declared client.\n"
" nolint: stringly_typed_error -- CLI module, String errors are user-facing messages\n"
).
-spec run(binary()) -> {ok, nil} | {error, binary()}.
run(Project_path) ->
gleam@result:'try'(
begin
_pipe = simplifile:read(<<Project_path/binary, "/gleam.toml"/utf8>>),
gleam@result:map_error(
_pipe,
fun(Err) ->
<<<<"error: Cannot read gleam.toml
\x{250c}\x{2500} gleam.toml
\x{2502}
\x{2502} "/utf8,
(simplifile:describe_error(Err))/binary>>/binary,
"
\x{2502}
hint: Run this command from your project root directory"/utf8>>
end
)
end,
fun(Toml_content) ->
gleam@result:'try'(
libero@toml_config:parse(Toml_content),
fun(Toml_cfg) -> case erlang:element(5, Toml_cfg) of
[] ->
gleam_stdlib:println(
<<"libero: no clients declared in gleam.toml"/utf8>>
),
{ok, nil};
Clients ->
run_with_clients(Project_path, Toml_cfg, Clients)
end end
)
end
).