defmodule Flagsmith.SDK.Client do use TypedEctoSchema alias Flagsmith.SDK @type possible_error :: :environment_key | :base_url @type tesla_header_list :: [{String.t(), String.t()}] import Ecto.Changeset, only: [ cast: 3, apply_action: 2, validate_required: 2 ] @default_url "https://api.flagsmith.com/api/v1" @auth_header "X-Environment-Key" @moduledoc """ The SDK Client struct module. The functions in this module should not be called directly, instead use the `Flagsmith.SDK.new/0/1/2` function to build a new client struct. """ @primary_key false typed_embedded_schema do field(:environment_key, SDK.MaybeFunction) field(:base_url, SDK.MaybeFunction, default_value: @default_url) end @doc """ Returns the base default url for the API query: #{@default_url} """ @spec default_url() :: String.t() def default_url(), do: @default_url @doc """ Returns a new `Flagsmith.SDK.Client.t()` to be used on further `Flagsmith.SDK.API` function calls. """ @spec new(SDK.Types.environment_key() | nil, SDK.Types.base_url() | nil) :: {:ok, SDK.Client.t()} | {:error, possible_error} def new(environment_key, base_url) do %__MODULE__{} |> cast(%{environment_key: environment_key, base_url: base_url}, [:environment_key, :base_url]) |> validate_required([:environment_key, :base_url]) |> apply_action(:insert) |> case do {:ok, _} = ok -> ok {:error, changeset} -> {:error, extract_first_error(changeset)} end end @doc false @spec auth_middleware(environment_key :: String.t()) :: {Tesla.Middleware.Headers, tesla_header_list()} def auth_middleware(environment_key), do: {Tesla.Middleware.Headers, auth_header(environment_key)} @doc false @spec base_url_middleware(base_url :: String.t()) :: {Tesla.Middleware.BaseUrl, String.t()} def base_url_middleware(base_url), do: {Tesla.Middleware.BaseUrl, base_url} @spec auth_header(environment_key :: String.t()) :: tesla_header_list() defp auth_header(environment_key), do: [{@auth_header, environment_key}] @spec extract_first_error(changeset :: Ecto.Changeset.t()) :: atom() defp extract_first_error(%Ecto.Changeset{errors: [{error, _} | _]}), do: error end