Current section

Files

Jump to
cigogne src cigogne.erl
Raw

src/cigogne.erl

-module(cigogne).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-define(FILEPATH, "src/cigogne.gleam").
-export([read_migrations/1, create_engine/1, new_migration/2, update_config/1, include_lib/2, remove_lib/2, apply_migrations/2, apply/1, apply_n/2, apply_all/1, rollback_migrations/2, rollback/1, rollback_n/2, get_all_migrations/1, get_applied_migrations/1, get_unapplied_migrations/1, print_error/1, main/0, apply_migration_if_not_applied/2]).
-export_type([migration_engine/0, cigogne_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.
-opaque migration_engine() :: {migration_engine,
cigogne@internal@database:database_data(),
list(cigogne@migration:migration()),
list(cigogne@migration:migration()),
list(cigogne@migration:migration()),
cigogne@config:config()}.
-type cigogne_error() :: {database_error,
cigogne@internal@database:database_error()} |
{f_s_error, cigogne@internal@fs:f_s_error()} |
{migration_error, cigogne@migration:migration_error()} |
{parser_error, cigogne@internal@parser_formatter:parser_error()} |
{config_error, cigogne@config:config_error()} |
nothing_to_rollback |
nothing_to_apply |
{lib_not_included, binary()} |
{compound_error, list(cigogne_error())}.
-file("src/cigogne.gleam", 165).
-spec warn_no_hash_check(cigogne@config:config()) -> nil.
warn_no_hash_check(Config) ->
case erlang:element(5, erlang:element(4, Config)) of
{some, true} ->
gleam_stdlib:println(
<<"Warning: no_hash_check is enabled ! Do not use it in production environments as it can lead to inconsistencies between your migration files and the database."/utf8>>
);
_ ->
nil
end.
-file("src/cigogne.gleam", 175).
-spec init_db_and_get_applied(cigogne@config:config()) -> {ok,
{cigogne@internal@database:database_data(),
list(cigogne@migration:migration())}} |
{error, cigogne_error()}.
init_db_and_get_applied(Config) ->
_pipe = begin
gleam@result:'try'(
cigogne@internal@database:init(Config),
fun(Db_data) ->
gleam@result:'try'(
cigogne@internal@database:apply_cigogne_zero(Db_data),
fun(_) ->
gleam@result:'try'(
cigogne@internal@database:get_applied_migrations(
Db_data
),
fun(Applied) -> {ok, {Db_data, Applied}} end
)
end
)
end
)
end,
gleam@result:map_error(_pipe, fun(Field@0) -> {database_error, Field@0} end).
-file("src/cigogne.gleam", 192).
?DOC(
" Read all migration files from the folder specified in the configuration .\n"
" It is recommended to use `create_engine` and `get_all_migrations` instead of this function.\n"
" It can still be useful if you want to read migrations without connecting to the database.\n"
).
-spec read_migrations(cigogne@config:config()) -> {ok,
list(cigogne@migration:migration())} |
{error, cigogne_error()}.
read_migrations(Config) ->
Files = begin
_pipe = begin
gleam@result:'try'(
cigogne@internal@fs:priv(
erlang:element(2, erlang:element(4, Config))
),
fun(Priv) ->
cigogne@internal@fs:read_directory(
<<<<Priv/binary, "/"/utf8>>/binary,
(cigogne@config:get_migrations_folder(
erlang:element(4, Config)
))/binary>>
)
end
)
end,
gleam@result:map_error(_pipe, fun(Field@0) -> {f_s_error, Field@0} end)
end,
gleam@result:'try'(
Files,
fun(Files@1) ->
Results = gleam@list:map(
Files@1,
fun(File) ->
_pipe@1 = cigogne@internal@parser_formatter:parse(File),
gleam@result:map_error(
_pipe@1,
fun(Field@0) -> {parser_error, Field@0} end
)
end
),
_pipe@2 = cigogne@internal@utils:get_results_or_errors(Results),
gleam@result:map_error(
_pipe@2,
fun(Field@0) -> {compound_error, Field@0} end
)
end
).
-file("src/cigogne.gleam", 145).
?DOC(
" Creates a MigrationEngine from a configuration.\n"
" This function will try to connect to the database, create the migrations table if it doesn't exist.\n"
" Then it will fetch the applied migrations and the existing migration files and check that hashes do match.\n"
" \n"
" Example usage:\n"
" ```gleam\n"
" import cigogne/config\n"
" import cigogne/cigogne\n"
" \n"
" pub fn main() {\n"
" use app_name <- result.try(config.get_app_name())\n"
" use config <- result.try(config.get(app_name))\n"
" use engine <- result.try(cigogne.create_engine(config))\n"
" \n"
" // Now you can use the engine to apply or rollback migrations\n"
" use _ <- result.try(cigogne.apply(engine))\n"
" use _ <- result.try(cigogne.rollback(engine))\n"
"\n"
" // Rest of your application logic\n"
" }\n"
" ```\n"
).
-spec create_engine(cigogne@config:config()) -> {ok, migration_engine()} |
{error, cigogne_error()}.
create_engine(Config) ->
warn_no_hash_check(Config),
gleam@result:'try'(
init_db_and_get_applied(Config),
fun(_use0) ->
{Db_data, Applied} = _use0,
gleam@result:'try'(
read_migrations(Config),
fun(Files) ->
gleam@result:'try'(
begin
_pipe@1 = cigogne@migration:match_migrations(
Applied,
Files,
begin
_pipe = erlang:element(
5,
erlang:element(4, Config)
),
gleam@option:unwrap(_pipe, false)
end
),
gleam@result:map_error(
_pipe@1,
fun(Field@0) -> {migration_error, Field@0} end
)
end,
fun(Applied@1) ->
Unapplied = cigogne@migration:find_unapplied(
Files,
Applied@1
),
{ok,
{migration_engine,
Db_data,
Files,
Applied@1,
Unapplied,
Config}}
end
)
end
)
end
).
-file("src/cigogne.gleam", 217).
?DOC(
" Create a new migration file in the folder specified by the configuration with the provided name.\n"
" Note: Migrations are always created in the `priv/<migrations_folder>` folder.\n"
).
-spec new_migration(cigogne@config:migrations_config(), binary()) -> {ok, nil} |
{error, cigogne_error()}.
new_migration(Migrations_config, Name) ->
gleam@result:'try'(
begin
_pipe = cigogne@migration:new(
<<"priv/"/utf8,
(cigogne@config:get_migrations_folder(Migrations_config))/binary>>,
Name,
gleam@time@timestamp:system_time()
),
gleam@result:map_error(
_pipe,
fun(Field@0) -> {migration_error, Field@0} end
)
end,
fun(New_mig) -> _pipe@1 = New_mig,
_pipe@2 = cigogne@internal@parser_formatter:format(_pipe@1),
_pipe@3 = cigogne@internal@fs:write_file(_pipe@2),
_pipe@4 = gleam@result:map_error(
_pipe@3,
fun(Field@0) -> {f_s_error, Field@0} end
),
gleam@result:map(
_pipe@4,
fun(_) ->
gleam_stdlib:println(
<<"Migration file created : "/utf8,
(erlang:element(2, New_mig))/binary>>
)
end
) end
).
-file("src/cigogne.gleam", 242).
?DOC(
" Update the configuration file at `priv/cigogne.toml` with the provided configuration.\n"
" If the file doesn't exist, it will be created.\n"
" If it already exists, it will be overwritten.\n"
).
-spec update_config(cigogne@config:config()) -> {ok, nil} |
{error, cigogne_error()}.
update_config(Config) ->
gleam@result:map(
begin
_pipe = cigogne@config:write(Config),
gleam@result:map_error(
_pipe,
fun(Field@0) -> {config_error, Field@0} end
)
end,
fun(_) ->
gleam_stdlib:println(
<<"Updated config file at priv/cigogne.toml"/utf8>>
)
end
).
-file("src/cigogne.gleam", 340).
?DOC(
" Include a library's migrations into your project.\n"
" This will create a new migration that applies all migrations from the library that haven't been applied yet.\n"
" This will fail if you haven't added the library to your project.\n"
"\n"
" Example usage:\n"
" ```sh\n"
" gleam add my_lib\n"
" gleam run -m cigogne include --lib-name my_lib\n"
" # There will be a new migration file created in priv/migrations with name `<timestamp>-my_lib`\n"
" ```\n"
).
-spec include_lib(migration_engine(), binary()) -> {ok, nil} |
{error, cigogne_error()}.
include_lib(Migration_engine, Lib_name) ->
gleam@result:'try'(
begin
_pipe = cigogne@config:get(Lib_name),
gleam@result:map_error(
_pipe,
fun(Field@0) -> {config_error, Field@0} end
)
end,
fun(Lib_config) ->
gleam@result:'try'(
read_migrations(Lib_config),
fun(Lib_migrations) ->
Last_migration_for_dep = begin
_pipe@1 = erlang:element(
4,
erlang:element(
4,
erlang:element(6, Migration_engine)
)
),
gleam@list:key_find(_pipe@1, Lib_name)
end,
Lib_migrations@1 = case Last_migration_for_dep of
{error, _} ->
Lib_migrations;
{ok, Name} ->
_pipe@2 = Lib_migrations,
_pipe@3 = gleam@list:drop_while(
_pipe@2,
fun(Mig) ->
cigogne@migration:to_fullname(Mig) /= Name
end
),
gleam@list:drop(_pipe@3, 1)
end,
gleam@result:'try'(
begin
_pipe@4 = cigogne@migration:merge(
Lib_migrations@1,
gleam@time@timestamp:system_time(),
Lib_name
),
gleam@result:map_error(
_pipe@4,
fun(Field@0) -> {migration_error, Field@0} end
)
end,
fun(Merged_mig) ->
Merged_mig@1 = begin
_pipe@5 = Merged_mig,
cigogne@migration:set_folder(
_pipe@5,
<<"priv/"/utf8,
(cigogne@config:get_migrations_folder(
erlang:element(
4,
erlang:element(
6,
Migration_engine
)
)
))/binary>>
)
end,
New_file = cigogne@internal@parser_formatter:format(
Merged_mig@1
),
gleam@result:'try'(
begin
_pipe@6 = New_file,
_pipe@7 = cigogne@internal@fs:write_file(
_pipe@6
),
gleam@result:map_error(
_pipe@7,
fun(Field@0) -> {f_s_error, Field@0} end
)
end,
fun(_) ->
gleam_stdlib:println(
<<"Created migration at "/utf8,
(erlang:element(2, New_file))/binary>>
),
Last_migration@1 = case gleam@list:last(
Lib_migrations@1
) of
{ok, Last_migration} -> Last_migration;
_assert_fail ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"cigogne"/utf8>>,
function => <<"include_lib"/utf8>>,
line => 378,
value => _assert_fail,
start => 12126,
'end' => 12183,
pattern_start => 12137,
pattern_end => 12155}
)
end,
New_config = begin
_record = erlang:element(
6,
Migration_engine
),
{config,
erlang:element(2, _record),
erlang:element(3, _record),
begin
_record@1 = erlang:element(
4,
erlang:element(
6,
Migration_engine
)
),
{migrations_config,
erlang:element(2, _record@1),
erlang:element(3, _record@1),
begin
_pipe@8 = erlang:element(
4,
erlang:element(
4,
erlang:element(
6,
Migration_engine
)
)
),
gleam@list:key_set(
_pipe@8,
Lib_name,
begin
_pipe@9 = Last_migration@1,
cigogne@migration:to_fullname(
_pipe@9
)
end
)
end,
erlang:element(5, _record@1)}
end}
end,
_pipe@10 = cigogne@config:write(New_config),
gleam@result:map_error(
_pipe@10,
fun(Field@0) -> {config_error, Field@0} end
)
end
)
end
)
end
)
end
).
-file("src/cigogne.gleam", 406).
?DOC(
" Remove a library's migrations from your project.\n"
" This will create a new migration that applies all the down migrations from the migrations created by include for this library.\n"
" This will fail if you haven't included the library yet.\n"
"\n"
" Example usage:\n"
" ```sh\n"
" gleam add my_lib\n"
" gleam run -m cigogne include --lib-name my_lib\n"
" gleam run -m cigogne remove --lib-name my_lib\n"
" # There will be a new migration file created in priv/migrations with name `<timestamp>-remove_my_lib`\n"
" ```\n"
).
-spec remove_lib(migration_engine(), binary()) -> {ok, nil} |
{error, cigogne_error()}.
remove_lib(Migration_engine, Lib_name) ->
Opposite_migrations = begin
_pipe = erlang:element(3, Migration_engine),
_pipe@1 = gleam@list:filter(
_pipe,
fun(Mig) -> erlang:element(4, Mig) =:= Lib_name end
),
_pipe@2 = gleam@list:map(_pipe@1, fun(Mig@1) -> _record = Mig@1,
{migration,
erlang:element(2, _record),
erlang:element(3, _record),
erlang:element(4, _record),
erlang:element(6, Mig@1),
erlang:element(5, Mig@1),
erlang:element(7, _record)} end),
lists:reverse(_pipe@2)
end,
gleam@bool:guard(
gleam@list:is_empty(Opposite_migrations),
{error, {lib_not_included, Lib_name}},
fun() ->
gleam@result:'try'(
begin
_pipe@3 = cigogne@migration:merge(
Opposite_migrations,
gleam@time@timestamp:system_time(),
<<"remove_"/utf8, Lib_name/binary>>
),
gleam@result:map_error(
_pipe@3,
fun(Field@0) -> {migration_error, Field@0} end
)
end,
fun(Merged_mig) ->
Merged_mig@1 = begin
_pipe@4 = Merged_mig,
cigogne@migration:set_folder(
_pipe@4,
<<"priv/"/utf8,
(cigogne@config:get_migrations_folder(
erlang:element(
4,
erlang:element(6, Migration_engine)
)
))/binary>>
)
end,
New_file = cigogne@internal@parser_formatter:format(
Merged_mig@1
),
gleam@result:'try'(
begin
_pipe@5 = New_file,
_pipe@6 = cigogne@internal@fs:write_file(_pipe@5),
gleam@result:map_error(
_pipe@6,
fun(Field@0) -> {f_s_error, Field@0} end
)
end,
fun(_) ->
gleam_stdlib:println(
<<"Created migration at "/utf8,
(erlang:element(2, New_file))/binary>>
),
New_config = begin
_record@1 = erlang:element(6, Migration_engine),
{config,
erlang:element(2, _record@1),
erlang:element(3, _record@1),
begin
_record@2 = erlang:element(
4,
erlang:element(6, Migration_engine)
),
{migrations_config,
erlang:element(2, _record@2),
erlang:element(3, _record@2),
begin
_pipe@7 = erlang:element(
4,
erlang:element(
4,
erlang:element(
6,
Migration_engine
)
)
),
gleam@list:filter(
_pipe@7,
fun(Dep) ->
erlang:element(1, Dep)
/= Lib_name
end
)
end,
erlang:element(5, _record@2)}
end}
end,
_pipe@8 = cigogne@config:write(New_config),
gleam@result:map_error(
_pipe@8,
fun(Field@0) -> {config_error, Field@0} end
)
end
)
end
)
end
).
-file("src/cigogne.gleam", 471).
?DOC(
" Apply migrations to the database.\n"
" It is recommended to use `apply` or `apply_n` instead of this function directly.\n"
" It can still be useful if you want to apply specific migrations or zero migrations.\n"
" All migrations will be applied in a single transaction, so either all are applied or none is.\n"
"\n"
" Be careful though as we don't check if the migration has already been applied or not, see `apply_migration_if_not_applied` for this use case.\n"
).
-spec apply_migrations(migration_engine(), list(cigogne@migration:migration())) -> {ok,
nil} |
{error, cigogne_error()}.
apply_migrations(Engine, Migrations) ->
_pipe = begin
cigogne@internal@database:transaction(
erlang:element(2, Engine),
fun(Transaction) ->
Db_data = begin
_record = erlang:element(2, Engine),
{database_data,
Transaction,
erlang:element(3, _record),
erlang:element(4, _record)}
end,
gleam@list:try_each(
Migrations,
fun(Migration) ->
gleam_stdlib:println(
<<"\nApplying migration "/utf8,
(cigogne@migration:to_fullname(Migration))/binary>>
),
cigogne@internal@database:apply_migration_no_transaction(
Db_data,
Migration
)
end
)
end
)
end,
_pipe@1 = gleam@result:map_error(
_pipe,
fun(Field@0) -> {database_error, Field@0} end
),
gleam@result:map(
_pipe@1,
fun(_) ->
gleam_stdlib:println(
<<"Migrations applied:\n\t"/utf8,
(begin
_pipe@2 = gleam@list:map(
Migrations,
fun cigogne@migration:to_fullname/1
),
gleam@string:join(_pipe@2, <<"\n\t"/utf8>>)
end)/binary>>
)
end
).
-file("src/cigogne.gleam", 250).
?DOC(
" Apply the next migration that wasn't applied yet.\n"
" See `create_engine` for an example usage.\n"
" See `apply_n` to apply multiple migrations at once.\n"
).
-spec apply(migration_engine()) -> {ok, nil} | {error, cigogne_error()}.
apply(Engine) ->
_pipe = erlang:element(5, Engine),
_pipe@1 = gleam@list:first(_pipe),
_pipe@2 = gleam@result:replace_error(_pipe@1, nothing_to_apply),
gleam@result:'try'(_pipe@2, fun(Mig) -> apply_migrations(Engine, [Mig]) end).
-file("src/cigogne.gleam", 278).
?DOC(
" Apply the next `count` migrations.\n"
" If `count` is less than or equal to 0, this function does nothing.\n"
" If there is no migration to apply, it returns an error.\n"
" If there are less than `count` migrations to apply, it applies all of them.\n"
" \n"
" Example usage:\n"
" ```gleam\n"
" use engine <- result.try(cigogne.create_engine(config))\n"
" use _ <- result.try(cigogne.apply_n(engine, 3)) // Apply the next 3 migrations\n"
" ```\n"
).
-spec apply_n(migration_engine(), integer()) -> {ok, nil} |
{error, cigogne_error()}.
apply_n(Engine, Count) ->
gleam@bool:guard(
Count =< 0,
{ok, nil},
fun() ->
Migrations_to_apply = begin
_pipe = erlang:element(5, Engine),
gleam@list:take(_pipe, Count)
end,
case Migrations_to_apply of
[] ->
{error, nothing_to_apply};
_ ->
apply_migrations(Engine, Migrations_to_apply)
end
end
).
-file("src/cigogne.gleam", 326).
?DOC(
" Apply all unapplied migrations.\n"
"\n"
" Example usage:\n"
" ```gleam\n"
" use engine <- result.try(cigogne.create_engine(config))\n"
" use _ <- result.try(cigogne.apply_all(engine))\n"
" ```\n"
).
-spec apply_all(migration_engine()) -> {ok, nil} | {error, cigogne_error()}.
apply_all(Engine) ->
apply_migrations(Engine, erlang:element(5, Engine)).
-file("src/cigogne.gleam", 499).
?DOC(
" Roll back migrations from the database.\n"
" It is recommended to use `rollback` or `rollback_n` instead of this function directly.\n"
" It can still be useful if you want to roll back specific migrations or a zero migrations.\n"
" All migrations will be rolled back in a single transaction, so either all are rolled back or none is.\n"
"\n"
" Be careful though as we don't check if the migration has been applied or not.\n"
).
-spec rollback_migrations(
migration_engine(),
list(cigogne@migration:migration())
) -> {ok, nil} | {error, cigogne_error()}.
rollback_migrations(Engine, Migrations) ->
_pipe = begin
cigogne@internal@database:transaction(
erlang:element(2, Engine),
fun(Transaction) ->
Db_data = begin
_record = erlang:element(2, Engine),
{database_data,
Transaction,
erlang:element(3, _record),
erlang:element(4, _record)}
end,
gleam@list:try_each(
Migrations,
fun(Migration) ->
gleam_stdlib:println(
<<"\nRolling back migration "/utf8,
(cigogne@migration:to_fullname(Migration))/binary>>
),
cigogne@internal@database:rollback_migration_no_transaction(
Db_data,
Migration
)
end
)
end
)
end,
_pipe@1 = gleam@result:map_error(
_pipe,
fun(Field@0) -> {database_error, Field@0} end
),
gleam@result:map(
_pipe@1,
fun(_) ->
gleam_stdlib:println(
<<"Migrations rolled back:\n\t"/utf8,
(begin
_pipe@2 = gleam@list:map(
Migrations,
fun cigogne@migration:to_fullname/1
),
gleam@string:join(_pipe@2, <<"\n\t"/utf8>>)
end)/binary>>
)
end
).
-file("src/cigogne.gleam", 260).
?DOC(
" Roll back the last applied migration.\n"
" See `create_engine` for an example usage.\n"
" See `rollback_n` to rollback multiple migrations at once.\n"
).
-spec rollback(migration_engine()) -> {ok, nil} | {error, cigogne_error()}.
rollback(Engine) ->
_pipe = erlang:element(4, Engine),
_pipe@1 = gleam@list:drop_while(
_pipe,
fun cigogne@migration:is_zero_migration/1
),
_pipe@2 = gleam@list:last(_pipe@1),
_pipe@3 = gleam@result:replace_error(_pipe@2, nothing_to_rollback),
gleam@result:'try'(
_pipe@3,
fun(Mig) -> rollback_migrations(Engine, [Mig]) end
).
-file("src/cigogne.gleam", 301).
?DOC(
" Roll back `count` migrations.\n"
" If `count` is less than or equal to 0, this function does nothing.\n"
" If there is no migration to rollback, it returns an error.\n"
" If there are less than `count` migrations to rollback, it rolls all of them back.\n"
" \n"
" Example usage:\n"
" ```gleam\n"
" use engine <- result.try(cigogne.create_engine(config))\n"
" use _ <- result.try(cigogne.rollback_n(engine, 3)) // Rollback the next 3 migrations\n"
" ```\n"
).
-spec rollback_n(migration_engine(), integer()) -> {ok, nil} |
{error, cigogne_error()}.
rollback_n(Engine, Count) ->
gleam@bool:guard(
Count =< 0,
{ok, nil},
fun() ->
Migrations_to_rollback = begin
_pipe = erlang:element(4, Engine),
_pipe@1 = gleam@list:drop_while(
_pipe,
fun cigogne@migration:is_zero_migration/1
),
_pipe@2 = lists:reverse(_pipe@1),
gleam@list:take(_pipe@2, Count)
end,
case Migrations_to_rollback of
[] ->
{error, nothing_to_rollback};
_ ->
rollback_migrations(Engine, Migrations_to_rollback)
end
end
).
-file("src/cigogne.gleam", 522).
?DOC(" Get all defined migrations in your project.\n").
-spec get_all_migrations(migration_engine()) -> list(cigogne@migration:migration()).
get_all_migrations(Engine) ->
erlang:element(3, Engine).
-file("src/cigogne.gleam", 527).
?DOC(" Get applied migrations in your project.\n").
-spec get_applied_migrations(migration_engine()) -> list(cigogne@migration:migration()).
get_applied_migrations(Engine) ->
erlang:element(4, Engine).
-file("src/cigogne.gleam", 534).
?DOC(" Get unapplied migrations in your project.\n").
-spec get_unapplied_migrations(migration_engine()) -> list(cigogne@migration:migration()).
get_unapplied_migrations(Engine) ->
erlang:element(5, Engine).
-file("src/cigogne.gleam", 540).
-spec show(migration_engine()) -> nil.
show(Engine) ->
Migration_names = begin
_pipe = erlang:element(4, Engine),
gleam@list:map(_pipe, fun cigogne@migration:to_fullname/1)
end,
To_apply = begin
_pipe@1 = erlang:element(5, Engine),
gleam@list:map(_pipe@1, fun cigogne@migration:to_fullname/1)
end,
gleam_stdlib:println(
<<<<"Applied migrations: \n - "/utf8,
(begin
_pipe@2 = Migration_names,
gleam@string:join(_pipe@2, <<"\n - "/utf8>>)
end)/binary>>/binary,
"\n"/utf8>>
),
gleam_stdlib:println(
<<"Migrations to apply: \n - "/utf8,
(begin
_pipe@3 = To_apply,
gleam@string:join(_pipe@3, <<"\n - "/utf8>>)
end)/binary>>
).
-file("src/cigogne.gleam", 552).
-spec print_unapplied(migration_engine()) -> nil.
print_unapplied(Migration_engine) ->
gleam_stdlib:print(<<"Unapplied migrations:"/utf8>>),
gleam@list:each(
erlang:element(5, Migration_engine),
fun(Unapplied_mig) ->
gleam_stdlib:println(
<<<<"\n\n--- == "/utf8,
(cigogne@migration:to_fullname(Unapplied_mig))/binary>>/binary,
" ==\n"/utf8>>
),
gleam_stdlib:println(
begin
_pipe = erlang:element(5, Unapplied_mig),
gleam@string:join(_pipe, <<"\n"/utf8>>)
end
)
end
).
-file("src/cigogne.gleam", 566).
-spec get_error_message(cigogne_error()) -> binary().
get_error_message(Error) ->
case Error of
{compound_error, Errors} ->
<<"Many errors happened ! Here is the list:\n "/utf8,
(begin
_pipe = Errors,
_pipe@1 = gleam@list:map(_pipe, fun get_error_message/1),
gleam@string:join(_pipe@1, <<"\n "/utf8>>)
end)/binary>>;
{config_error, Error@1} ->
<<"Configuration error: "/utf8,
(cigogne@config:get_error_message(Error@1))/binary>>;
{database_error, Error@2} ->
<<"Database error: "/utf8,
(cigogne@internal@database:get_error_message(Error@2))/binary>>;
{f_s_error, Error@3} ->
<<"FS error: "/utf8,
(cigogne@internal@fs:get_error_message(Error@3))/binary>>;
{lib_not_included, Name} ->
<<<<"There were no migrations for library "/utf8, Name/binary>>/binary,
" ! Did you include it ?"/utf8>>;
{migration_error, Error@4} ->
<<"Migration error: "/utf8,
(cigogne@migration:get_error_message(Error@4))/binary>>;
nothing_to_apply ->
<<"There is no migration to apply ! You are up-to-date !"/utf8>>;
nothing_to_rollback ->
<<"There is no migration to rollback !"/utf8>>;
{parser_error, Error@5} ->
<<"Parser error: "/utf8,
(cigogne@internal@parser_formatter:get_error_message(Error@5))/binary>>
end.
-file("src/cigogne.gleam", 562).
?DOC(" Print a MigrateError to the standard error stream.\n").
-spec print_error(cigogne_error()) -> nil.
print_error(Error) ->
gleam_stdlib:println_error(get_error_message(Error)).
-file("src/cigogne.gleam", 69).
?DOC(
" The main entry point of the Cigogne CLI.\n"
" \n"
" Example usage:\n"
" ```sh\n"
" # List all possible actions\n"
" gleam run -m cigogne help\n"
" # Create a new migration\n"
" gleam run -m cigogne new --name AddUsers\n"
" # Apply a single migration\n"
" gleam run -m cigogne up\n"
" # Apply the next 3 migrations\n"
" gleam run -m cigogne up --count 3\n"
" # Apply all unapplied migrations\n"
" gleam run -m cigogne all\n"
" # Rollback a single migration\n"
" gleam run -m cigogne down\n"
" ```\n"
).
-spec main() -> {ok, nil} | {error, nil}.
main() ->
Args = erlang:element(4, argv:load()),
Application_name@1 = case cigogne@config:get_app_name() of
{ok, Application_name} -> Application_name;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"cigogne"/utf8>>,
function => <<"main"/utf8>>,
line => 71,
value => _assert_fail,
start => 2154,
'end' => 2209,
pattern_start => 2165,
pattern_end => 2185})
end,
Cigogne_config@1 = case cigogne@config:get(Application_name@1) of
{ok, Cigogne_config} -> Cigogne_config;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"cigogne"/utf8>>,
function => <<"main"/utf8>>,
line => 72,
value => _assert_fail@1,
start => 2212,
'end' => 2272,
pattern_start => 2223,
pattern_end => 2241})
end,
gleam@result:'try'(
cigogne@internal@cli:get_action(Application_name@1, Args),
fun(Cli_action) -> _pipe@26 = case Cli_action of
{new_migration, Migrations, Name} ->
_pipe = erlang:element(4, Cigogne_config@1),
_pipe@1 = cigogne@config:merge_migrations_config(
_pipe,
Migrations
),
new_migration(_pipe@1, Name);
{show_migrations, Config} ->
_pipe@2 = Cigogne_config@1,
_pipe@3 = cigogne@config:merge(_pipe@2, Config),
_pipe@4 = create_engine(_pipe@3),
gleam@result:map(_pipe@4, fun show/1);
{migrate_up, Config@1, Count} ->
_pipe@5 = Cigogne_config@1,
_pipe@6 = cigogne@config:merge(_pipe@5, Config@1),
_pipe@7 = create_engine(_pipe@6),
gleam@result:'try'(
_pipe@7,
fun(_capture) -> apply_n(_capture, Count) end
);
{migrate_down, Config@2, Count@1} ->
_pipe@8 = Cigogne_config@1,
_pipe@9 = cigogne@config:merge(_pipe@8, Config@2),
_pipe@10 = create_engine(_pipe@9),
gleam@result:'try'(
_pipe@10,
fun(_capture@1) -> rollback_n(_capture@1, Count@1) end
);
{migrate_up_all, Config@3} ->
_pipe@11 = Cigogne_config@1,
_pipe@12 = cigogne@config:merge(_pipe@11, Config@3),
_pipe@13 = create_engine(_pipe@12),
gleam@result:'try'(_pipe@13, fun apply_all/1);
{include_lib, Config@4, Lib_name} ->
_pipe@14 = Cigogne_config@1,
_pipe@15 = cigogne@config:merge(_pipe@14, Config@4),
_pipe@16 = create_engine(_pipe@15),
gleam@result:'try'(
_pipe@16,
fun(_capture@2) -> include_lib(_capture@2, Lib_name) end
);
{remove_lib, Config@5, Lib_name@1} ->
_pipe@17 = Cigogne_config@1,
_pipe@18 = cigogne@config:merge(_pipe@17, Config@5),
_pipe@19 = create_engine(_pipe@18),
gleam@result:'try'(
_pipe@19,
fun(_capture@3) ->
remove_lib(_capture@3, Lib_name@1)
end
);
{update_config, Config@6} ->
_pipe@20 = Cigogne_config@1,
_pipe@21 = cigogne@config:merge(_pipe@20, Config@6),
update_config(_pipe@21);
init_config ->
_pipe@22 = Cigogne_config@1,
update_config(_pipe@22);
{print_unapplied, Config@7} ->
_pipe@23 = Cigogne_config@1,
_pipe@24 = cigogne@config:merge(_pipe@23, Config@7),
_pipe@25 = create_engine(_pipe@24),
gleam@result:map(_pipe@25, fun print_unapplied/1)
end,
gleam@result:map_error(_pipe@26, fun print_error/1) end
).
-file("src/cigogne.gleam", 590).
?DOC(" Apply a migration to the database if it hasn't been applied.\n").
-spec apply_migration_if_not_applied(
migration_engine(),
cigogne@migration:migration()
) -> {ok, nil} | {error, cigogne_error()}.
apply_migration_if_not_applied(Engine, Migration) ->
case cigogne@internal@utils:find_compare(
erlang:element(4, Engine),
Migration,
fun cigogne@migration:compare/2
) of
{ok, _} ->
{ok, nil};
{error, _} ->
apply_migrations(Engine, [Migration])
end.