-module(olive). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -define(FILEPATH, "src/olive.gleam"). -export([main/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. -file("src/olive.gleam", 110). -spec has_main_file(olive@config:config(), list(olive@watcher:change())) -> boolean(). has_main_file(Config, Changes) -> Main_file = <<<<"src/"/utf8, (erlang:element(7, Config))/binary>>/binary, ".gleam"/utf8>>, _pipe = Changes, gleam@list:any( _pipe, fun(Change) -> gleam_stdlib:string_ends_with(erlang:element(2, Change), Main_file) end ). -file("src/olive.gleam", 116). -spec needs_rebuild(list(olive@watcher:change())) -> boolean(). needs_rebuild(Changes) -> _pipe = Changes, gleam@list:any(_pipe, fun(Change) -> case Change of {source_change, _} -> true; {priv_change, _} -> false end end). -file("src/olive.gleam", 68). -spec listen_to_file_changes( olive@config:config(), gleam@erlang@process:subject(olive@watcher:message()), olive@client_registry:client_registry() ) -> nil. listen_to_file_changes(Config, Subject, Clients) -> Msg = gleam_erlang_ffi:'receive'(Subject), case Msg of {files_changed, Changes} -> case has_main_file(Config, Changes) of true -> olive@logging:warning( erlang:element(2, Config), <<"Main file changed. You need to restart olive for changes to be applied!"/utf8>> ); false -> Changelog = begin _pipe = Changes, _pipe@1 = gleam@list:map( _pipe, fun(Change) -> erlang:element(2, Change) end ), gleam@string:join(_pipe@1, <<"\n"/utf8>>) end, olive@logging:debug( erlang:element(2, Config), <<"Files changed:\n"/utf8, Changelog/binary>> ), After_build = case needs_rebuild(Changes) of true -> olive@server_run:reload_server_code(Config); false -> {ok, nil} end, case After_build of {ok, _} -> olive@client_registry:trigger(Clients); {error, Msg@1} -> olive@logging:error( erlang:element(2, Config), Msg@1 ) end, listen_to_file_changes(Config, Subject, Clients) end end. -file("src/olive.gleam", 33). -spec run_olive(olive@config:config()) -> nil. run_olive(Config) -> Clients = olive@client_registry:start(erlang:element(2, Config)), Subject = gleam@erlang@process:new_subject(), case olive@watcher:start(Config, Subject) of {error, init_timeout} -> olive@logging:error( erlang:element(2, Config), <<"Watcher took too much time to initialize"/utf8>> ); {error, {init_failed, Msg}} -> olive@logging:error(erlang:element(2, Config), Msg); {error, {init_exited, killed}} -> olive@logging:error( erlang:element(2, Config), <<"Watcher was killed before initialisation"/utf8>> ); {error, {init_exited, {abnormal, _}}} -> olive@logging:error( erlang:element(2, Config), <<"Watcher shutdown abnormally"/utf8>> ); {error, {init_exited, normal}} -> olive@logging:error( erlang:element(2, Config), <<"Watcher shutdown before end of initialisation"/utf8>> ); {ok, _} -> case olive@server_run:start_server(Config) of {ok, _} -> case olive@proxy:start_http(Config, Clients) of {ok, _} -> nil; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"olive"/utf8>>, function => <<"run_olive"/utf8>>, line => 53, value => _assert_fail, start => 1649, 'end' => 1701, pattern_start => 1660, pattern_end => 1665}) end, listen_to_file_changes(Config, Subject, Clients); {error, Reason} -> olive@logging:error( erlang:element(2, Config), <<"Could not start your server:\n"/utf8, Reason/binary>> ) end end. -file("src/olive.gleam", 19). ?DOC( " Process is as follow:\n" " - Start a client registry\n" " - Start watcher, giving it a subject we will listen to.\n" " - Every time watcher sends us a message:\n" " - Reload server code\n" " - Send reload message to clients\n" ). -spec main() -> nil. main() -> case olive@cli:get_options() of {error, nil} -> nil; {ok, Options} -> Logger = olive@logging:get_logger(erlang:element(5, Options)), case olive@config:read_config(Logger, Options) of {error, Error} -> olive@logging:error(Logger, Error); {ok, Config} -> run_olive(Config) end end.