Packages
mercury_client
1.0.0
A complete, production-grade Elixir client for the Mercury Banking API (accounts, transactions, recipients, invoices, payments, treasury, webhooks, and more), with typed errors, retry with backoff, and lazy auto-paginating streams.
Current section
Files
Jump to
Current section
Files
lib/mercury/pagination.ex
defmodule Mercury.Pagination do
@moduledoc """
Builds lazy, auto-paginating `Stream`s over Mercury list endpoints.
Every resource module exposes a `stream/2` built on top of this — you
normally won't call `stream/1` directly.
"""
alias Mercury.Page
@type fetcher :: (String.t() | nil -> {:ok, Page.t()} | {:error, Exception.t()})
@doc """
Returns a `Stream` of individual items across every page, given a
page-fetching function of arity 1. The function receives the current
cursor (`nil` for the first page) and must return
`{:ok, %Mercury.Page{}}` or `{:error, exception}`.
The stream raises the underlying Mercury exception if a page request
fails, consistent with how `File.stream!/1` and similar raise on I/O
errors mid-enumeration.
"""
@spec stream(fetch_fun :: fetcher()) :: Enumerable.t()
def stream(fetch_fun) when is_function(fetch_fun, 1) do
Stream.resource(
fn -> {:cont, nil} end,
&next_page(&1, fetch_fun),
fn _acc -> :ok end
)
end
defp next_page(:halt, _fetch_fun), do: {:halt, :halt}
defp next_page({:cont, cursor}, fetch_fun) do
case fetch_fun.(cursor) do
{:ok, %Page{items: [], next_page: _next}} ->
{:halt, :halt}
{:ok, %Page{items: items, next_page: nil}} ->
{items, :halt}
{:ok, %Page{items: items, next_page: next}} ->
{items, {:cont, next}}
{:error, error} ->
raise error
end
end
end