Bonfire.API.MastoCompat.PaginationHelpers (Bonfire v1.0.1-social-alpha.28)

View Source

Shared pagination utilities for Mastodon-compatible REST API adapters.

Provides consistent pagination handling across all Mastodon API endpoints:

  • Limit validation with configurable defaults and maximums
  • Cursor-based pagination parameter handling (max_id, since_id, min_id)
  • Link header generation for Mastodon-compatible pagination

Summary

Functions

Add Mastodon-compatible Link headers for pagination.

Simplified Link headers for adapters that use item IDs as cursors.

Convert pagination param keys from strings to atoms.

Build feed parameters from Mastodon-style params.

Build pagination opts from Mastodon-style params (max_id, since_id, min_id).

Encode a plain ID as a cursor with a given field map.

Encode a cursor for GraphQL query parameters.

Encode a cursor for use in Link headers.

Encode a plain ULID as a cursor.

Extract limit and determine pagination direction (first vs last).

Extract pagination cursors from Mastodon-style params.

Add cursor to opts if present in params.

Validate that an already-encoded cursor can be decoded properly.

Validate and normalize pagination limit.

Functions

atomize_pagination_keys(params)

Convert pagination param keys from strings to atoms.

Pagination module expects atom keys for :after, :before, :first, :last.

build_feed_params(params, filter, opts \\ [])

Build feed parameters from Mastodon-style params.

Converts Mastodon timeline parameters to Bonfire GraphQL format:

  • Extracts and encodes pagination cursors (max_id, since_id, min_id)
  • Determines limit with first/last based on cursor direction
  • Atomizes pagination keys for GraphQL compatibility

Options

  • :default_limit - Default limit when not specified (default: 20)
  • :max_limit - Maximum allowed limit (default: 40)

Examples

iex> build_feed_params(%{"limit" => "10", "max_id" => "abc"}, %{"feed_name" => "my"})
%{filter: %{"feed_name" => "my", "time_limit" => 0}, after: "encoded...", first: 10}

build_pagination_opts(params, limit)

Build pagination opts from Mastodon-style params (max_id, since_id, min_id).

Converts Mastodon cursor params to keyword list format for Bonfire queries.

Examples

iex> build_pagination_opts(%{"max_id" => "abc123"}, 20)
[limit: 20, after: "abc123"]

iex> build_pagination_opts(%{}, 40)
[limit: 40]

encode_cursor(id, cursor_map)

Encode a plain ID as a cursor with a given field map.

Examples

iex> encode_cursor("abc123", %{id: "abc123"})
{:ok, "base64_encoded_string"}

encode_cursor_for_graphql(id)

Encode a cursor for GraphQL query parameters.

Handles both already-encoded cursors and plain IDs:

  • Already base64 encoded (from Link headers) → validate and pass through
  • Plain ID (ULID) → create proper cursor map and encode

Returns {:ok, cursor} or {:error, reason}.

encode_plain_id_cursor(id)

Encode a plain ULID as a cursor.

Creates a cursor map matching Bonfire's cursor_fields format: %{{:activity, :id} => id}

extract_limit_with_direction(params, cursors, opts \\ [])

Extract limit and determine pagination direction (first vs last).

Relay pagination: "first" with "after", "last" with "before" With descending sort:

  • "after" + "first" = older posts (max_id)
  • "before" + "last" = newer posts (min_id/since_id)

extract_pagination_cursors(params)

Extract pagination cursors from Mastodon-style params.

Maps Mastodon pagination IDs to Relay cursor params:

  • max_id → after (items AFTER cursor in descending list = older/lower IDs)
  • since_id/min_id → before (items BEFORE cursor in descending list = newer/higher IDs)

Cursors are encoded as base64 for GraphQL compatibility.

maybe_add_cursor(opts, params, param_name, cursor_key)

Add cursor to opts if present in params.

Works with both keyword list opts and map opts.

Examples

iex> maybe_add_cursor([limit: 20], %{"max_id" => "abc"}, "max_id", :after)
[after: "abc", limit: 20]

iex> maybe_add_cursor(%{limit: 20}, %{"max_id" => "abc"}, "max_id", :after)
%{limit: 20, after: "abc"}

validate_encoded_cursor(cursor)

Validate that an already-encoded cursor can be decoded properly.

validate_limit(limit, opts \\ [])

Validate and normalize pagination limit.

Options

  • :default - Default limit when nil or invalid (default: 40)
  • :max - Maximum allowed limit (default: 80)

Examples

iex> validate_limit(nil)
40

iex> validate_limit("20")
20

iex> validate_limit(100)
80

iex> validate_limit(nil, default: 20, max: 40)
20