defmodule Meili.Key do
@moduledoc """
Manages Meilisearch API keys.
"""
alias Meili.Client
@doc """
Lists all API keys.
## Options
- `limit`: The maximum number of keys to return.
- `offset`: The number of keys to skip.
## Examples
Meili.Key.list()
Meili.Key.list(limit: 5)
Meili.Key.list(client, limit: 5)
"""
@spec list(Meili.Client.t() | Keyword.t() | nil, Keyword.t()) ::
{:ok, map()} | {:error, Meili.Error.t()}
def list(client_or_opts \\ nil, opts \\ []) do
case client_or_opts do
%Client{} = client ->
do_list(client, opts)
nil ->
do_list(Meili.default_client(), [])
opts when is_list(opts) ->
do_list(Meili.default_client(), opts)
end
end
@doc """
Lists all API keys, raising on error.
## Examples
Meili.Key.list!()
Meili.Key.list!(limit: 5)
Meili.Key.list!(client, limit: 5)
"""
@spec list!(Meili.Client.t() | Keyword.t() | nil, Keyword.t()) :: map() | no_return()
def list!(client_or_opts \\ nil, opts \\ []) do
case list(client_or_opts, opts) do
{:ok, body} -> body
{:error, exception} -> raise exception
end
end
defp do_list(client, opts) do
params = Keyword.take(opts, [:limit, :offset])
Client.request(client, :get, "/keys", params: params)
end
@doc """
Retrieves a single API key by its value or UUID.
## Examples
Meili.Key.get("some-key-value-or-uuid")
Meili.Key.get(client, "some-key-value-or-uuid")
"""
@spec get(Meili.Client.t() | String.t(), String.t() | nil) ::
{:ok, map()} | {:error, Meili.Error.t()}
def get(client_or_key, key_or_nil \\ nil) do
case client_or_key do
%Client{} = client ->
Client.request(client, :get, "/keys/#{key_or_nil}")
key when is_binary(key) ->
Client.request(Meili.default_client(), :get, "/keys/#{key}")
end
end
@doc """
Retrieves a single API key, raising on error.
## Examples
Meili.Key.get!("some-key-value-or-uuid")
Meili.Key.get!(client, "some-key-value-or-uuid")
"""
@spec get!(Meili.Client.t() | String.t(), String.t() | nil) :: map() | no_return()
def get!(client_or_key, key_or_nil \\ nil) do
case get(client_or_key, key_or_nil) do
{:ok, body} -> body
{:error, exception} -> raise exception
end
end
@doc """
Creates a new API key.
Keys are automatically camelized from snake_case to camelCase.
## Options
- `name`: Human-readable name.
- `description`: Purpose of the key.
- `actions`: List of permitted actions (e.g. `["search"]`).
- `indexes`: List of accessible indexes.
- `expires_at` / `expiresAt`: Expiration date (RFC 3339 string).
## Examples
params = %{
name: "Search Key",
actions: ["search"],
indexes: ["*"],
expires_at: nil
}
Meili.Key.create(params)
Meili.Key.create(client, params)
"""
@spec create(Meili.Client.t() | map() | Keyword.t(), map() | Keyword.t() | nil) ::
{:ok, map()} | {:error, Meili.Error.t()}
def create(client_or_params, params_or_nil \\ nil) do
case client_or_params do
%Client{} = client ->
do_create(client, params_or_nil)
params when is_map(params) or is_list(params) ->
do_create(Meili.default_client(), params)
end
end
@doc """
Creates a new API key, raising on error.
## Examples
params = %{
name: "Search Key",
actions: ["search"],
indexes: ["*"]
}
Meili.Key.create!(params)
Meili.Key.create!(client, params)
"""
@spec create!(Meili.Client.t() | map() | Keyword.t(), map() | Keyword.t() | nil) ::
map() | no_return()
def create!(client_or_params, params_or_nil \\ nil) do
case create(client_or_params, params_or_nil) do
{:ok, body} -> body
{:error, exception} -> raise exception
end
end
defp do_create(client, params) do
body = Meili.Util.camelize_keys(params)
Client.request(client, :post, "/keys", json: body)
end
@doc """
Updates an existing API key. Only the name and description can be updated.
## Examples
Meili.Key.update("key_value", name: "New Name", description: "New Description")
Meili.Key.update(client, "key_value", %{name: "New Name"})
"""
@spec update(
Meili.Client.t() | String.t(),
String.t() | map() | Keyword.t() | nil,
map() | Keyword.t() | nil
) :: {:ok, map()} | {:error, Meili.Error.t()}
def update(client_or_key, key_or_params \\ nil, params_or_nil \\ nil) do
case client_or_key do
%Client{} = client ->
do_update(client, key_or_params, params_or_nil)
key when is_binary(key) ->
do_update(Meili.default_client(), key, key_or_params)
end
end
@doc """
Updates an API key, raising on error.
## Examples
Meili.Key.update!("key_value", name: "New Name")
Meili.Key.update!(client, "key_value", %{name: "New Name"})
"""
@spec update!(
Meili.Client.t() | String.t(),
String.t() | map() | Keyword.t() | nil,
map() | Keyword.t() | nil
) :: map() | no_return()
def update!(client_or_key, key_or_params \\ nil, params_or_nil \\ nil) do
case update(client_or_key, key_or_params, params_or_nil) do
{:ok, body} -> body
{:error, exception} -> raise exception
end
end
defp do_update(client, key, params) do
body = Meili.Util.camelize_keys(params)
Client.request(client, :patch, "/keys/#{key}", json: body)
end
@doc """
Deletes an API key.
## Examples
Meili.Key.delete("key_value")
Meili.Key.delete(client, "key_value")
"""
@spec delete(Meili.Client.t() | String.t(), String.t() | nil) ::
{:ok, term()} | {:error, Meili.Error.t()}
def delete(client_or_key, key_or_nil \\ nil) do
case client_or_key do
%Client{} = client ->
Client.request(client, :delete, "/keys/#{key_or_nil}")
key when is_binary(key) ->
Client.request(Meili.default_client(), :delete, "/keys/#{key}")
end
end
@doc """
Deletes an API key, raising on error.
## Examples
Meili.Key.delete!("key_value")
Meili.Key.delete!(client, "key_value")
"""
@spec delete!(Meili.Client.t() | String.t(), String.t() | nil) :: term() | no_return()
def delete!(client_or_key, key_or_nil \\ nil) do
case delete(client_or_key, key_or_nil) do
{:ok, body} -> body
{:error, exception} -> raise exception
end
end
end