Packages

The official Elixir SDK for the Nomba One subscription-billing API — recurring billing for Nigeria over card, direct debit, and bank transfer, with dunning that recovers and a ledger that never loses a kobo.

Current section

Files

Jump to
nombaone lib nombaone api.ex
Raw

lib/nombaone/api.ex

defmodule Nombaone.API do
@moduledoc false
# The thin bridge resources call: run the request through the engine, then
# cast `data` into a struct (or pass it through). Honors the `with_response`
# per-call option, which wraps the result in a `Nombaone.Response`.
alias Nombaone.{Client, HTTP, Page, Response}
@type caster :: module() | (term() -> term()) | nil
@doc "A single-resource request. `caster` shapes `data` into a struct."
@spec request(Client.t(), HTTP.spec(), caster()) ::
{:ok, term()} | {:ok, Response.t()} | {:error, Nombaone.Error.t()}
def request(client, spec, caster) do
case HTTP.request(client, spec) do
{:ok, result} -> {:ok, wrap(spec, result, cast(caster, result.data))}
{:error, error} -> {:error, error}
end
end
@doc "A list request. Returns a `Nombaone.Page` that auto-paginates."
@spec list(Client.t(), HTTP.spec(), caster()) ::
{:ok, Page.t()} | {:ok, Response.t()} | {:error, Nombaone.Error.t()}
def list(client, spec, caster) do
case HTTP.request(client, spec) do
{:ok, result} ->
page = Page.new(client, spec, caster, result)
{:ok, wrap(spec, result, page)}
{:error, error} ->
{:error, error}
end
end
defp wrap(spec, result, data) do
if with_response?(spec), do: to_response(result, data), else: data
end
defp to_response(result, data) do
%Response{
data: data,
status: result.status,
request_id: result.request_id,
headers: result.headers
}
end
defp with_response?(spec) do
spec |> Map.get(:options, []) |> Keyword.get(:with_response, false)
end
defp cast(nil, data), do: data
defp cast(fun, data) when is_function(fun, 1), do: fun.(data)
defp cast(module, data) when is_atom(module), do: module.cast(data)
end