-module(cigogne). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([new_migration/1, get_migrations/0, get_schema/1, update_schema_file/1, print_error/1, apply_migration/2, apply_next_migration/1, migrate_up/0, execute_migrations_to_last/1, migrate_to_last/0, roll_back_migration/2, roll_back_previous_migration/1, migrate_down/0, execute_n_migrations/2, migrate_n/1, main/0]). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 16). -spec migration_zero() -> cigogne@types:migration(). migration_zero() -> {migration, <<""/utf8>>, cigogne@internal@utils:tempo_epoch(), <<"CreateMigrationsTable"/utf8>>, [<<"CREATE TABLE IF NOT EXISTS _migrations( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, createdAt TIMESTAMP WITHOUT TIME ZONE NOT NULL, appliedAt TIMESTAMP NOT NULL DEFAULT NOW() );"/utf8>>], []}. -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 56). -spec show_usage() -> {ok, nil} | {error, cigogne@types:migrate_error()}. show_usage() -> gleam_stdlib:println(<<"======================================="/utf8>>), gleam_stdlib:println(<<"= CIGOGNE ="/utf8>>), gleam_stdlib:println(<<"======================================="/utf8>>), gleam_stdlib:println(<<""/utf8>>), gleam_stdlib:println(<<"Usage: gleam run -m cigogne [command]"/utf8>>), gleam_stdlib:println(<<""/utf8>>), gleam_stdlib:println(<<"List of commands:"/utf8>>), gleam_stdlib:println( <<" - show: Show the last currently applied migration"/utf8>> ), gleam_stdlib:println( <<" - up: Migrate up one version / Apply one migration"/utf8>> ), gleam_stdlib:println( <<" - down: Migrate down one version / Rollback one migration"/utf8>> ), gleam_stdlib:println( <<" - last: Apply all migrations until the last one defined"/utf8>> ), gleam_stdlib:println( <<" - apply N: Apply or roll back N migrations (N can be positive or negative)"/utf8>> ), gleam_stdlib:println( <<" - new NAME: Create a new migration file in /priv/migrations with the specified name"/utf8>> ), {ok, nil}. -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 123). -spec new_migration(binary()) -> {ok, nil} | {error, cigogne@types:migrate_error()}. new_migration(Name) -> cigogne@internal@fs:create_new_migration_file( tempo@naive_datetime:now_utc(), Name ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 268). -spec get_migrations() -> {ok, list(cigogne@types:migration())} | {error, cigogne@types:migrate_error()}. get_migrations() -> cigogne@internal@fs:get_migrations(). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 273). -spec get_schema(binary()) -> {ok, binary()} | {error, cigogne@types:migrate_error()}. get_schema(Url) -> cigogne@internal@database:get_schema(Url). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 279). -spec update_schema_file(binary()) -> {ok, nil} | {error, cigogne@types:migrate_error()}. update_schema_file(Url) -> gleam@result:'try'( get_schema(Url), fun(Schema) -> cigogne@internal@fs:write_schema_file(Schema) end ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 352). -spec print_error(cigogne@types:migrate_error()) -> nil. print_error(Error) -> cigogne@types:print_migrate_error(Error). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 302). -spec get_applied_migrations(pog:connection()) -> {ok, list(cigogne@types:migration())} | {error, cigogne@types:migrate_error()}. get_applied_migrations(Conn) -> _pipe = pog:'query'( <<"SELECT createdAt, name FROM _migrations ORDER BY appliedAt ASC;"/utf8>> ), _pipe@1 = pog:returning( _pipe, begin gleam@dynamic@decode:field( 0, pog:timestamp_decoder(), fun(Timestamp) -> gleam@dynamic@decode:field( 1, {decoder, fun gleam@dynamic@decode:decode_string/1}, fun(Name) -> gleam@dynamic@decode:success({Timestamp, Name}) end ) end ) end ), _pipe@2 = pog:execute(_pipe@1, Conn), _pipe@3 = gleam@result:map_error( _pipe@2, fun(Field@0) -> {pgo_query_error, Field@0} end ), gleam@result:then(_pipe@3, fun(Returned) -> case Returned of {returned, 0, _} -> {error, no_result_error}; {returned, _, []} -> {error, no_result_error}; {returned, _, Applied} -> _pipe@4 = Applied, gleam@list:try_map( _pipe@4, fun(Data) -> _pipe@5 = cigogne@internal@utils:pog_to_tempo_timestamp( erlang:element(1, Data) ), _pipe@6 = gleam@result:map( _pipe@5, fun(Timestamp@1) -> {migration, <<""/utf8>>, Timestamp@1, erlang:element(2, Data), [], []} end ), gleam@result:replace_error( _pipe@6, {date_parse_error, cigogne@internal@utils:pog_timestamp_to_string( erlang:element(1, Data) )} ) end ) end end). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 284). -spec get_last_applied_migration(pog:connection()) -> {ok, cigogne@types:migration()} | {error, cigogne@types:migrate_error()}. get_last_applied_migration(Conn) -> _pipe = get_applied_migrations(Conn), _pipe@1 = gleam@result:map(_pipe, fun lists:reverse/1), gleam@result:then( _pipe@1, fun(Migs) -> case begin _pipe@2 = Migs, gleam@list:first(_pipe@2) end of {error, nil} -> {error, no_migration_to_rollback_error}; {ok, Mig} -> case tempo@naive_datetime:compare( erlang:element(3, Mig), cigogne@internal@utils:tempo_epoch() ) of eq -> {error, no_migration_to_rollback_error}; _ -> {ok, Mig} end end end ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 208). -spec apply_migration(pog:connection(), cigogne@types:migration()) -> {ok, nil} | {error, cigogne@types:migrate_error()}. apply_migration(Connection, Migration) -> gleam_stdlib:println( <<<<<<<<"\nApplying migration "/utf8, (begin _pipe = erlang:element(3, Migration), tempo@naive_datetime:format( _pipe, <<"YYYYMMDDhhmmss"/utf8>> ) end)/binary>>/binary, "-"/utf8>>/binary, (erlang:element(4, Migration))/binary>>/binary, "\n"/utf8>> ), Queries = begin _pipe@1 = gleam@list:map( erlang:element(5, Migration), fun pog:'query'/1 ), lists:append( _pipe@1, [begin _pipe@2 = pog:'query'( <<"INSERT INTO _migrations(createdAt, name) VALUES ($1, $2);"/utf8>> ), _pipe@4 = pog:parameter( _pipe@2, pog:timestamp( begin _pipe@3 = erlang:element(3, Migration), cigogne@internal@utils:tempo_to_pog_timestamp( _pipe@3 ) end ) ), pog:parameter( _pipe@4, pog_ffi:coerce(erlang:element(4, Migration)) ) end] ) end, cigogne@internal@database:execute_batch( Connection, Queries, cigogne@internal@migrations:compare_migrations( Migration, migration_zero() ) =:= eq ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 194). -spec apply_migration_zero_if_not_applied(pog:connection()) -> {ok, nil} | {error, cigogne@types:migrate_error()}. apply_migration_zero_if_not_applied(Connection) -> case get_applied_migrations(Connection) of {error, {pgo_query_error, {postgresql_error, Code, _, _}}} when Code =:= <<"42P01"/utf8>> -> apply_migration(Connection, migration_zero()); _ -> {ok, nil} end. -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 130). -spec apply_next_migration(pog:connection()) -> {ok, nil} | {error, cigogne@types:migrate_error()}. apply_next_migration(Connection) -> gleam@result:'try'( apply_migration_zero_if_not_applied(Connection), fun(_) -> gleam@result:'try'( get_applied_migrations(Connection), fun(Applied) -> gleam@result:'try'( cigogne@internal@fs:get_migrations(), fun(Migs) -> gleam@result:'try'( cigogne@internal@migrations:find_first_non_applied_migration( Migs, Applied ), fun(Migration) -> apply_migration(Connection, Migration) end ) end ) end ) end ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 82). -spec migrate_up() -> {ok, nil} | {error, cigogne@types:migrate_error()}. migrate_up() -> gleam@result:'try'( cigogne@internal@database:get_url(), fun(Url) -> gleam@result:'try'( cigogne@internal@database:connect(Url), fun(Conn) -> gleam@result:'try'( apply_next_migration(Conn), fun(_) -> update_schema_file(Url) end ) end ) end ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 181). -spec execute_migrations_to_last(pog:connection()) -> {ok, nil} | {error, cigogne@types:migrate_error()}. execute_migrations_to_last(Connection) -> gleam@result:'try'( apply_migration_zero_if_not_applied(Connection), fun(_) -> gleam@result:'try'( get_applied_migrations(Connection), fun(Applied) -> gleam@result:'try'( cigogne@internal@fs:get_migrations(), fun(Migs) -> _pipe = cigogne@internal@migrations:find_all_non_applied_migration( Migs, Applied ), gleam@result:then( _pipe, fun(_capture) -> gleam@list:try_each( _capture, fun(Migration) -> apply_migration( Connection, Migration ) end ) end ) end ) end ) end ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 115). -spec migrate_to_last() -> {ok, nil} | {error, cigogne@types:migrate_error()}. migrate_to_last() -> gleam@result:'try'( cigogne@internal@database:get_url(), fun(Url) -> gleam@result:'try'( cigogne@internal@database:connect(Url), fun(Conn) -> gleam@result:'try'( execute_migrations_to_last(Conn), fun(_) -> update_schema_file(Url) end ) end ) end ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 331). -spec show() -> {ok, nil} | {error, cigogne@types:migrate_error()}. show() -> gleam@result:'try'( cigogne@internal@database:get_url(), fun(Url) -> gleam@result:'try'( cigogne@internal@database:connect(Url), fun(Conn) -> gleam@result:'try'( apply_migration(Conn, migration_zero()), fun(_) -> gleam@result:'try'( get_last_applied_migration(Conn), fun(Last) -> gleam_stdlib:println( <<<<<<"Last applied migration: "/utf8, (begin _pipe = erlang:element( 3, Last ), tempo@naive_datetime:format( _pipe, <<"YYYYMMDDhhmmss"/utf8>> ) end)/binary>>/binary, "-"/utf8>>/binary, (erlang:element(4, Last))/binary>> ), gleam@result:'try'( get_schema(Url), fun(Schema) -> gleam_stdlib:println(<<""/utf8>>), gleam_stdlib:println(Schema), {ok, nil} end ) end ) end ) end ) end ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 238). -spec roll_back_migration(pog:connection(), cigogne@types:migration()) -> {ok, nil} | {error, cigogne@types:migrate_error()}. roll_back_migration(Connection, Migration) -> gleam_stdlib:println( <<<<<<<<"\nRolling back migration "/utf8, (begin _pipe = erlang:element(3, Migration), tempo@naive_datetime:format( _pipe, <<"YYYYMMDDhhmmss"/utf8>> ) end)/binary>>/binary, "-"/utf8>>/binary, (erlang:element(4, Migration))/binary>>/binary, "\n"/utf8>> ), Queries = begin _pipe@1 = gleam@list:map( erlang:element(6, Migration), fun pog:'query'/1 ), lists:append( _pipe@1, [begin _pipe@2 = pog:'query'( <<"DELETE FROM _migrations WHERE name = $1 AND createdAt = $2;"/utf8>> ), _pipe@3 = pog:parameter( _pipe@2, pog_ffi:coerce(erlang:element(4, Migration)) ), pog:parameter( _pipe@3, pog:timestamp( begin _pipe@4 = erlang:element(3, Migration), cigogne@internal@utils:tempo_to_pog_timestamp( _pipe@4 ) end ) ) end] ) end, cigogne@internal@database:execute_batch( Connection, Queries, cigogne@internal@migrations:compare_migrations( Migration, migration_zero() ) =:= eq ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 146). -spec roll_back_previous_migration(pog:connection()) -> {ok, nil} | {error, cigogne@types:migrate_error()}. roll_back_previous_migration(Connection) -> gleam@result:'try'( apply_migration_zero_if_not_applied(Connection), fun(_) -> gleam@result:'try'( get_last_applied_migration(Connection), fun(Last) -> gleam@result:'try'( cigogne@internal@fs:get_migrations(), fun(Migs) -> gleam@result:'try'( cigogne@internal@migrations:find_migration( Migs, Last ), fun(Migration) -> roll_back_migration(Connection, Migration) end ) end ) end ) end ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 93). -spec migrate_down() -> {ok, nil} | {error, cigogne@types:migrate_error()}. migrate_down() -> gleam@result:'try'( cigogne@internal@database:get_url(), fun(Url) -> gleam@result:'try'( cigogne@internal@database:connect(Url), fun(Conn) -> gleam@result:'try'( roll_back_previous_migration(Conn), fun(_) -> update_schema_file(Url) end ) end ) end ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 159). -spec execute_n_migrations(pog:connection(), integer()) -> {ok, nil} | {error, cigogne@types:migrate_error()}. execute_n_migrations(Connection, Count) -> gleam@result:'try'( apply_migration_zero_if_not_applied(Connection), fun(_) -> gleam@result:'try'( get_applied_migrations(Connection), fun(Applied) -> gleam@result:'try'( cigogne@internal@fs:get_migrations(), fun(Migs) -> _pipe = cigogne@internal@migrations:find_n_migrations_to_apply( Migs, Applied, Count ), gleam@result:then( _pipe, fun(_capture) -> gleam@list:try_each( _capture, fun(Migration) -> case Count > 0 of true -> apply_migration( Connection, Migration ); false -> roll_back_migration( Connection, Migration ) end end ) end ) end ) end ) end ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 104). -spec migrate_n(integer()) -> {ok, nil} | {error, cigogne@types:migrate_error()}. migrate_n(Count) -> gleam@result:'try'( cigogne@internal@database:get_url(), fun(Url) -> gleam@result:'try'( cigogne@internal@database:connect(Url), fun(Conn) -> gleam@result:'try'( execute_n_migrations(Conn, Count), fun(_) -> update_schema_file(Url) end ) end ) end ). -file("/home/runner/work/cigogne/cigogne/src/cigogne.gleam", 39). -spec main() -> {ok, nil} | {error, nil}. main() -> _pipe = case erlang:element(4, argv:load()) of [<<"show"/utf8>>] -> show(); [<<"up"/utf8>>] -> migrate_up(); [<<"down"/utf8>>] -> migrate_down(); [<<"last"/utf8>>] -> migrate_to_last(); [<<"apply"/utf8>>, X] -> case gleam_stdlib:parse_int(X) of {error, _} -> show_usage(); {ok, Mig} -> migrate_n(Mig) end; [<<"new"/utf8>>, Name] -> new_migration(Name); _ -> show_usage() end, gleam@result:map_error(_pipe, fun cigogne@types:print_migrate_error/1).