Solaris.Pagination (Solaris v1.0.0)

Copy Markdown View Source

Cursor-based pagination helpers for Solaris API list endpoints.

Solaris uses cursor pagination. Paginated responses include a meta object with next_page and previous_page cursor strings.

Usage

# Single page
{:ok, body} = Solaris.Onboarding.Persons.list(per_page: 25)
page = Solaris.Pagination.from_response(body)
IO.inspect(page.data)        # list of persons
IO.inspect(page.next_cursor) # nil or cursor string

# Lazy stream of all items across all pages
Solaris.Pagination.stream(fn cursor ->
  Solaris.Onboarding.Persons.list(after: cursor, per_page: 100)
  |> case do
    {:ok, body} -> {:ok, Solaris.Pagination.from_response(body)}
    err -> err
  end
end)
|> Stream.each(&process/1)
|> Stream.run()

# Collect all into memory
{:ok, all} = Solaris.Pagination.all(fn cursor ->
  Solaris.Onboarding.Persons.list(after: cursor)
  |> case do
    {:ok, body} -> {:ok, Solaris.Pagination.from_response(body)}
    err -> err
  end
end)

Summary

Functions

Fetches all pages and returns all items in a single list.

Parses a raw Solaris paginated response body into a %Solaris.Pagination{} struct.

Returns a lazy Stream that auto-paginates through all results.

Converts page options into query parameters for a Solaris list request.

Types

page_opts()

@type page_opts() :: [
  page: pos_integer(),
  per_page: pos_integer(),
  after: String.t() | nil,
  before: String.t() | nil
]

t()

@type t() :: %Solaris.Pagination{
  data: [map()],
  meta: map(),
  next_cursor: String.t() | nil,
  prev_cursor: String.t() | nil,
  total: integer() | nil
}

Functions

all(fetch_fn)

@spec all((String.t() | nil -> {:ok, t()} | {:error, term()})) ::
  {:ok, [map()]} | {:error, term()}

Fetches all pages and returns all items in a single list.

Uses stream/1 internally. For large datasets, prefer stream/1 to avoid loading everything into memory at once.

from_response(data)

@spec from_response(map() | [map()] | term()) :: t() | term()

Parses a raw Solaris paginated response body into a %Solaris.Pagination{} struct.

Accepts the decoded JSON body map. Falls back gracefully if the response is a plain list (some endpoints skip the wrapper).

stream(fetch_fn)

@spec stream((String.t() | nil -> {:ok, t()} | {:error, term()})) :: Enumerable.t()

Returns a lazy Stream that auto-paginates through all results.

fetch_fn receives a cursor (nil for the first page) and must return {:ok, %Solaris.Pagination{}} or {:error, reason}.

The stream halts automatically when next_cursor is nil. Raises on fetch errors to surface them through Stream.run/1 or Enum.to_list/1.

to_query(opts)

@spec to_query(page_opts()) :: keyword()

Converts page options into query parameters for a Solaris list request.

Filters out nil values automatically.

Examples

Pagination.to_query(page: 2, per_page: 50)
# => [page: 2, per_page: 50]

Pagination.to_query(after: "cursor_abc", per_page: 100, before: nil)
# => [after: "cursor_abc", per_page: 100]