defmodule Kevo do @moduledoc """ Top-level interface and supervisor for Kevo's API and websocket connections. """ use Supervisor require Logger ## Initialization def child_spec(opts) do %{ id: name(opts), start: {__MODULE__, :start_link, [opts]} } end @doc """ Starts an instance of kevo_ex. ## Configuration * `:name` - Alias of the top-level supervisor. Can be provided if you intend to run multiple instances of `kevo_ex` in your app. Defaults to `Kevo`. * `:username` - Your Kevo username (required). * `:password` - Your Kevo password (required). * `:websocket_callback` - Websocket callback module. Defaults to `nil`. """ @spec start_link(opts :: keyword()) :: Supervisor.on_start() def start_link(opts \\ []) do Logger.add_translator({Kevo.StateMachineTranslator, :translate}) name = name(opts) config = %{ username: username!(opts), password: password!(opts), api_name: api_name(name), socket_name: socket_name(name), ws_callback_module: ws_callback_module(opts) } Supervisor.start_link(__MODULE__, config, name: name) end @impl true def init(config) do %{ username: username, password: password, api_name: api_name, socket_name: socket_name, ws_callback_module: ws_callback_module } = config api = {Kevo.Api.Client, [username: username, password: password, name: api_name]} socket = case ws_callback_module do nil -> [] module -> [{Kevo.Socket, [callback_module: module, name: socket_name, api_name: api_name]}] end Supervisor.init([api | socket], strategy: :one_for_one) end defp name(opts) do Keyword.get(opts, :name, Kevo) end defp api_name(name), do: :"#{name}.Api.Client" defp socket_name(name), do: :"#{name}.Socket" defp username!(opts) do Keyword.get(opts, :username) || raise(ArgumentError, "must supply a username") end defp password!(opts) do Keyword.get(opts, :password) || raise(ArgumentError, "must supply a password") end defp ws_callback_module(opts) do Keyword.get(opts, :ws_callback_module) end ## Developer API @doc """ Retrieves all locks visible to the logged in user. """ @spec get_locks(atom()) :: {:ok, list(map())} | {:error, Kevo.ApiError.t()} defdelegate get_locks(name \\ Kevo), to: Kevo.Api @doc """ Retrieves the given lock's state. """ @spec get_lock(String.t(), atom()) :: {:ok, map()} | {:error, Kevo.ApiError.t()} defdelegate get_lock(lock_id, name \\ Kevo), to: Kevo.Api @doc """ Locks the given lock. """ @spec lock(String.t(), atom()) :: :ok | {:error, Kevo.ApiError.t()} defdelegate lock(lock_id, name \\ Kevo), to: Kevo.Api @doc """ Unlocks the given lock. """ @spec unlock(String.t(), atom()) :: :ok | {:error, Kevo.ApiError.t()} defdelegate unlock(lock_id, name \\ Kevo), to: Kevo.Api @doc """ Gets the provided lock's event history. Follows the frontend's paging behavior. """ @spec get_events(String.t(), integer(), integer(), atom()) :: {:ok, list(map())} | {:error, Kevo.ApiError.t()} defdelegate get_events(lock_id, page \\ 1, page_size \\ 10, name \\ Kevo), to: Kevo.Api end