-module(gorrion@runner). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/gorrion/runner.gleam"). -export([apply_migration/2, revert_migration/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(" Executes migration SQL within transactions.\n"). -file("src/gorrion/runner.gleam", 16). ?DOC( " Apply a single migration: execute the up SQL, then record it.\n" " Each migration runs inside a database transaction.\n" ). -spec apply_migration(pog:connection(), gorrion@types:migration()) -> {ok, nil} | {error, gorrion@types:migration_error()}. apply_migration(Db, Migration) -> gleam_stdlib:println( <<<<<<" Applying migration "/utf8, (erlang:integer_to_binary(erlang:element(2, Migration)))/binary>>/binary, ": "/utf8>>/binary, (erlang:element(3, Migration))/binary>> ), Decoder = gleam@dynamic@decode:map( {decoder, fun gleam@dynamic@decode:decode_dynamic/1}, fun(_) -> nil end ), gleam@result:'try'( begin _pipe = erlang:element(4, Migration), _pipe@1 = pog:'query'(_pipe), _pipe@2 = pog:returning(_pipe@1, Decoder), _pipe@3 = pog:execute(_pipe@2, Db), _pipe@4 = gleam@result:map(_pipe@3, fun(_) -> nil end), gleam@result:map_error( _pipe@4, fun(E) -> {migration_failed, erlang:element(2, Migration), erlang:element(3, Migration), gleam@string:inspect(E)} end ) end, fun(_) -> gorrion@tracker:record( Db, erlang:element(2, Migration), erlang:element(3, Migration) ) end ). -file("src/gorrion/runner.gleam", 51). ?DOC( " Revert a single migration: execute the down SQL, then remove the record.\n" " If no down SQL was provided (empty string), just removes the tracking record.\n" ). -spec revert_migration(pog:connection(), gorrion@types:migration()) -> {ok, nil} | {error, gorrion@types:migration_error()}. revert_migration(Db, Migration) -> gleam_stdlib:println( <<<<<<" Rolling back migration "/utf8, (erlang:integer_to_binary(erlang:element(2, Migration)))/binary>>/binary, ": "/utf8>>/binary, (erlang:element(3, Migration))/binary>> ), case erlang:element(5, Migration) of <<""/utf8>> -> gleam_stdlib:println( <<" (no down migration — removing record only)"/utf8>> ), gorrion@tracker:remove(Db, erlang:element(2, Migration)); Down_sql -> Decoder = gleam@dynamic@decode:map( {decoder, fun gleam@dynamic@decode:decode_dynamic/1}, fun(_) -> nil end ), gleam@result:'try'( begin _pipe = Down_sql, _pipe@1 = pog:'query'(_pipe), _pipe@2 = pog:returning(_pipe@1, Decoder), _pipe@3 = pog:execute(_pipe@2, Db), _pipe@4 = gleam@result:map(_pipe@3, fun(_) -> nil end), gleam@result:map_error( _pipe@4, fun(E) -> {rollback_failed, erlang:element(2, Migration), erlang:element(3, Migration), gleam@string:inspect(E)} end ) end, fun(_) -> gorrion@tracker:remove(Db, erlang:element(2, Migration)) end ) end.