defmodule Linear.Pagination do @moduledoc """ Cursor-based auto-pagination for Linear GraphQL connections. Linear uses the Relay connection pattern with `nodes`, `pageInfo.hasNextPage`, and `pageInfo.endCursor`. This module handles following cursors automatically. """ @spec paginate((String.t() | nil -> {:ok, map()} | {:error, term()})) :: {:ok, [map()]} | {:error, term()} def paginate(query_fn) do do_paginate(query_fn, nil, []) end defp do_paginate(query_fn, cursor, acc) do case query_fn.(cursor) do {:ok, %{"nodes" => nodes, "pageInfo" => page_info}} when is_list(nodes) -> updated = acc ++ nodes case page_info do %{"hasNextPage" => true, "endCursor" => next} when is_binary(next) and next != "" -> do_paginate(query_fn, next, updated) _ -> {:ok, updated} end {:ok, %{"nodes" => nodes}} when is_list(nodes) -> {:ok, acc ++ nodes} {:error, reason} -> {:error, reason} other -> {:error, {:unexpected_connection_shape, other}} end end end