%%%------------------------------------------------------------------- %%% @doc Standard directory layout for plugin data. %%% %%% Replaces per-plugin path modules (e.g., app_scribed_paths.erl). %%% All plugins get the same layout under their data directory: %%% %%% ~/.hecate/plugins/{plugin_name}/ %%% ├── sqlite/ — SQLite read model databases %%% ├── reckon-db/ — ReckonDB event store %%% └── run/ — Runtime files (PID, etc.) %%% %%% When HECATE_HOME is set (e.g., ~/.hecate-dev), paths adjust automatically. %%% @end %%%------------------------------------------------------------------- -module(hecate_plugin_paths). -export([base_dir/1, sqlite_dir/1, sqlite_path/2, reckon_dir/1, reckon_path/2, run_dir/1, run_path/2, ensure_layout/1]). %% @doc Root data directory for a plugin. -spec base_dir(PluginName :: string() | binary()) -> file:filename(). base_dir(PluginName) -> Name = to_list(PluginName), HecateHome = hecate_home(), filename:join([HecateHome, "plugins", Name]). %% @doc SQLite directory for a plugin's read models. -spec sqlite_dir(string() | binary()) -> file:filename(). sqlite_dir(PluginName) -> filename:join(base_dir(PluginName), "sqlite"). %% @doc Full path to a named SQLite database file. -spec sqlite_path(string() | binary(), string()) -> file:filename(). sqlite_path(PluginName, DbName) -> filename:join(sqlite_dir(PluginName), DbName). %% @doc ReckonDB directory for a plugin's event store. -spec reckon_dir(string() | binary()) -> file:filename(). reckon_dir(PluginName) -> filename:join(base_dir(PluginName), "reckon-db"). %% @doc Full path to a named ReckonDB store directory. -spec reckon_path(string() | binary(), string()) -> file:filename(). reckon_path(PluginName, StoreName) -> filename:join(reckon_dir(PluginName), StoreName). %% @doc Runtime directory for PID files, temp data. -spec run_dir(string() | binary()) -> file:filename(). run_dir(PluginName) -> filename:join(base_dir(PluginName), "run"). %% @doc Full path to a named runtime file. -spec run_path(string() | binary(), string()) -> file:filename(). run_path(PluginName, FileName) -> filename:join(run_dir(PluginName), FileName). %% @doc Create all standard directories for a plugin. -spec ensure_layout(string() | binary()) -> ok. ensure_layout(PluginName) -> Dirs = [sqlite_dir(PluginName), reckon_dir(PluginName), run_dir(PluginName)], lists:foreach(fun(Dir) -> ok = filelib:ensure_path(Dir) end, Dirs). %%-------------------------------------------------------------------- %% Internal %%-------------------------------------------------------------------- hecate_home() -> case os:getenv("HECATE_HOME") of false -> filename:join(os:getenv("HOME"), ".hecate"); Dir -> Dir end. to_list(V) when is_binary(V) -> binary_to_list(V); to_list(V) when is_list(V) -> V.