-module(migrant@filesystem). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([load_migration_files/2]). -spec is_directory( binary(), fun((binary()) -> {ok, nil} | {error, migrant@types:error()}) ) -> {ok, nil} | {error, migrant@types:error()}. is_directory(Path, Next) -> gleam@result:'try'( begin _pipe = simplifile:verify_is_directory(Path), gleam@result:map_error( _pipe, fun(Field@0) -> {file_error, Field@0} end ) end, fun(Is_dir) -> gleam@bool:guard( Is_dir, Next(Path), fun() -> {error, expected_folder_error} end ) end ). -spec list_files( binary(), fun((list(binary())) -> {ok, nil} | {error, migrant@types:error()}) ) -> {ok, nil} | {error, migrant@types:error()}. list_files(Path, Next) -> gleam@result:'try'( begin _pipe = simplifile:read_directory(Path), gleam@result:map_error( _pipe, fun(Field@0) -> {file_error, Field@0} end ) end, fun(Files) -> Next(Files) end ). -spec read_file(binary(), binary()) -> gleam@option:option(binary()). read_file(Path, Filename) -> File_path = (gleam@bool:guard( gleam@string:ends_with(Path, <<"/"/utf8>>), <>, fun() -> <<<>/binary, Filename/binary>> end )), case simplifile:read(File_path) of {ok, Contents} -> {some, gleam@string:trim(Contents)}; {error, _} -> none end. -spec parse_files( binary(), list(binary()), gleam@dict:dict(binary(), migrant@types:migration()) ) -> {ok, gleam@dict:dict(binary(), migrant@types:migration())} | {error, migrant@types:error()}. parse_files(Migrations_dir, Files, Migrations) -> case Files of [] -> {ok, Migrations}; [File | Rest] -> Res = case gleam@string:split(File, <<"."/utf8>>) of [Name, Direction, <<"sql"/utf8>>] -> migrant@lib:validate_direction( Direction, fun(Direction@1) -> migrant@lib:get_or_make_migration( Name, Migrations, fun(Migration) -> Sql = read_file(Migrations_dir, File), Migration@1 = case Direction@1 of <<"up"/utf8>> -> {some, erlang:setelement( 2, Migration, Sql )}; <<"down"/utf8>> -> {some, erlang:setelement( 3, Migration, Sql )}; _ -> none end, case Migration@1 of {some, M} -> {ok, {Name, M}}; none -> {error, {extraction_error, <<<<"Invalid migration direction, expected one of `up` or `down`, got `"/utf8, Direction@1/binary>>/binary, "`"/utf8>>}} end end ) end ); _ -> {error, {extraction_error, <<<<"Failed to extract up/down from "/utf8, File/binary>>/binary, ". Migration files must be named in the format ..sql e.g 00001_create_users.up.sql"/utf8>>}} end, case Res of {ok, {Name@1, Migration@2}} -> Migrations@1 = gleam@dict:insert( Migrations, Name@1, Migration@2 ), parse_files(Migrations_dir, Rest, Migrations@1); {error, E} -> {error, E} end end. -spec load_migration_files( binary(), fun((gleam@dict:dict(binary(), migrant@types:migration())) -> {ok, nil} | {error, migrant@types:error()}) ) -> {ok, nil} | {error, migrant@types:error()}. load_migration_files(Migrations_dir, Next) -> gleam@io:println( <<"-> Loading migrations from "/utf8, Migrations_dir/binary>> ), is_directory( Migrations_dir, fun(Migrations_dir@1) -> list_files( Migrations_dir@1, fun(Files) -> case parse_files(Migrations_dir@1, Files, gleam@dict:new()) of {ok, Migrations} -> Next(Migrations); {error, E} -> {error, E} end end ) end ).