Current section

Files

Jump to
libero src libero@cli@new.erl
Raw

src/libero@cli@new.erl

-module(libero@cli@new).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/libero/cli/new.gleam").
-export([scaffold/2]).
-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 new` — scaffold a new Libero project at the given path.\n").
-file("src/libero/cli/new.gleam", 179).
?DOC(" Write a file, running `gleam format` on .gleam files first.\n").
-spec write_formatted(binary(), binary()) -> {ok, nil} |
{error, simplifile:file_error()}.
write_formatted(Path, Content) ->
Formatted = case gleam_stdlib:string_ends_with(Path, <<".gleam"/utf8>>) of
true ->
libero@format:format_gleam(Content);
false ->
Content
end,
simplifile:write(Path, Formatted).
-file("src/libero/cli/new.gleam", 191).
-spec map_err(
{ok, WOV} | {error, simplifile:file_error()},
fun((WOV) -> {ok, nil} | {error, binary()})
) -> {ok, nil} | {error, binary()}.
map_err(Result, Next) ->
case Result of
{ok, Value} ->
Next(Value);
{error, Err} ->
{error, simplifile:describe_error(Err)}
end.
-file("src/libero/cli/new.gleam", 93).
-spec scaffold_files(
binary(),
binary(),
binary(),
gleam@option:option(libero@cli:database())
) -> {ok, nil} | {error, binary()}.
scaffold_files(Name, Path, Server_dir, Database) ->
{Db_deps, Extra_toml, Db_readme} = case Database of
none ->
{<<""/utf8>>, <<""/utf8>>, <<""/utf8>>};
{some, Db} ->
{libero@cli@templates@db:deps(Db),
libero@cli@templates@db:extra_toml(Db),
libero@cli@templates@db:readme_section(Db)}
end,
map_err(
simplifile:create_directory_all(Server_dir),
fun(_) ->
map_err(
simplifile:write(
<<Path/binary, "/gleam.toml"/utf8>>,
libero@cli@templates:gleam_toml(Name, Db_deps, Extra_toml)
),
fun(_) ->
map_err(
write_formatted(
<<Server_dir/binary, "/handler.gleam"/utf8>>,
libero@cli@templates:starter_handler()
),
fun(_) ->
map_err(
write_formatted(
<<Server_dir/binary,
"/shared_state.gleam"/utf8>>,
case Database of
none ->
libero@cli@templates:starter_shared_state(
);
{some, Db@1} ->
libero@cli@templates@db:shared_state(
Db@1
)
end
),
fun(_) ->
map_err(
write_formatted(
<<Server_dir/binary,
"/app_error.gleam"/utf8>>,
libero@cli@templates:starter_app_error(
)
),
fun(_) -> (fun(Next) -> case Database of
none ->
Next(nil);
{some, Db@2} ->
map_err(
write_formatted(
<<Server_dir/binary,
"/db.gleam"/utf8>>,
libero@cli@templates@db:db_module(
Db@2
)
),
fun(_) ->
map_err(
simplifile:create_directory_all(
<<Server_dir/binary,
"/sql"/utf8>>
),
fun(_) ->
Next(
nil
)
end
)
end
)
end end)(
fun(_) ->
Shared_dir = <<Path/binary,
"/shared/src/shared"/utf8>>,
map_err(
simplifile:create_directory_all(
Shared_dir
),
fun(_) ->
map_err(
simplifile:write(
<<Path/binary,
"/shared/gleam.toml"/utf8>>,
libero@cli@templates:shared_gleam_toml(
)
),
fun(_) ->
map_err(
write_formatted(
<<Shared_dir/binary,
"/messages.gleam"/utf8>>,
libero@cli@templates:starter_messages(
)
),
fun(_) ->
Test_dir = <<Path/binary,
"/test"/utf8>>,
map_err(
simplifile:create_directory_all(
Test_dir
),
fun(
_
) ->
map_err(
write_formatted(
<<<<<<Test_dir/binary,
"/"/utf8>>/binary,
Name/binary>>/binary,
"_test.gleam"/utf8>>,
libero@cli@templates:starter_test(
)
),
fun(
_
) ->
map_err(
simplifile:write(
<<Path/binary,
"/README.md"/utf8>>,
libero@cli@templates:starter_readme(
Name,
Db_readme
)
),
fun(
_
) ->
{ok,
nil}
end
)
end
)
end
)
end
)
end
)
end
)
end
) end
)
end
)
end
)
end
)
end
).
-file("src/libero/cli/new.gleam", 37).
-spec scaffold_validated(
binary(),
binary(),
gleam@option:option(libero@cli:database())
) -> {ok, nil} | {error, binary()}.
scaffold_validated(Name, Path, Database) ->
case simplifile_erl:is_file(<<Path/binary, "/gleam.toml"/utf8>>) of
{ok, true} ->
{error,
<<<<"project already exists at "/utf8, Path/binary>>/binary,
" (gleam.toml found)"/utf8>>};
_ ->
Server_dir = <<Path/binary, "/src/server"/utf8>>,
scaffold_files(Name, Path, Server_dir, Database)
end.
-file("src/libero/cli/new.gleam", 84).
-spec is_lowercase_letter(binary()) -> boolean().
is_lowercase_letter(Ch) ->
gleam_stdlib:contains_string(<<"abcdefghijklmnopqrstuvwxyz"/utf8>>, Ch).
-file("src/libero/cli/new.gleam", 88).
-spec is_digit(binary()) -> boolean().
is_digit(Ch) ->
gleam_stdlib:contains_string(<<"0123456789"/utf8>>, Ch).
-file("src/libero/cli/new.gleam", 54).
-spec validate_name(binary()) -> {ok, nil} | {error, binary()}.
validate_name(Name) ->
case gleam@string:to_graphemes(Name) of
[] ->
{error, <<"project name cannot be empty"/utf8>>};
[First | Rest] ->
case is_lowercase_letter(First) of
false ->
{error,
<<"project name must start with a lowercase letter, got: "/utf8,
Name/binary>>};
true ->
case gleam@list:all(
Rest,
fun(Ch) ->
(is_lowercase_letter(Ch) orelse is_digit(Ch)) orelse (Ch
=:= <<"_"/utf8>>)
end
) of
false ->
{error,
<<"project name must contain only lowercase letters, digits, and underscores, got: "/utf8,
Name/binary>>};
true ->
{ok, nil}
end
end
end.
-file("src/libero/cli/new.gleam", 21).
?DOC(
" Scaffold a new project under `path`.\n"
"\n"
" The project name is derived from the last segment of the path\n"
" (e.g. \"tmp/test_app\" → \"test_app\").\n"
"\n"
" Creates the directory tree and writes starter source files so the\n"
" project compiles and runs out of the box.\n"
" nolint: stringly_typed_error -- CLI module, String errors are user-facing messages\n"
).
-spec scaffold(binary(), gleam@option:option(libero@cli:database())) -> {ok,
nil} |
{error, binary()}.
scaffold(Path, Database) ->
Name = begin
_pipe = gleam@string:split(Path, <<"/"/utf8>>),
_pipe@1 = gleam@list:last(_pipe),
gleam@result:unwrap(_pipe@1, Path)
end,
case validate_name(Name) of
{error, Msg} ->
{error, Msg};
{ok, nil} ->
scaffold_validated(Name, Path, Database)
end.