# `Pluggy.HTTP`
[🔗](https://github.com/fellipessanha/pluggy_ai_ex/blob/main/lib/pluggy/http.ex#L1)

Low-level HTTP interface and cursor-based pagination for the Pluggy API.

Most users should call the resource modules (`Pluggy.Accounts`,
`Pluggy.Transactions`, etc.) rather than using this module directly.
This module is primarily useful for its pagination helpers:

  * `with_cursor/1` — advance a `Pluggy.HTTP.Cursor` to fetch the next page
  * `with_cursor/2` — start cursor-based iteration from a fetcher function
  * `stream_results/1` — lazily stream pages from a cursor result
  * `unwrap_tuple!/1` — extract the success value from a result tuple, raising on errors

## Cursor-based pagination

Resource modules that support pagination return
`{:ok, response, cursor}` tuples. The `cursor` is a `Pluggy.HTTP.Cursor`
struct that you can pass back to `with_cursor/1` to fetch successive pages.

    fetcher = fn page -> Pluggy.Connectors.list(client, page: page) end
    {:ok, first_page, cursor} = Pluggy.HTTP.with_cursor(fetcher)
    {:ok, second_page, nil}   = Pluggy.HTTP.with_cursor(cursor)

# `cursor_result`

```elixir
@type cursor_result() ::
  {:ok, paginated(), Pluggy.HTTP.Cursor.t() | nil} | {:error, Pluggy.Error.t()}
```

A cursor-paginated result from `list_with_cursor`.

# `fetcher`

```elixir
@type fetcher() :: (pos_integer() -&gt; {:ok, map()} | {:error, Pluggy.Error.t()})
```

A function that fetches a specific page number.

# `paginated`

```elixir
@type paginated() :: %{
  results: list(),
  page: pos_integer(),
  total_pages: non_neg_integer(),
  total: non_neg_integer()
}
```

A paginated API response body.

# `stream_results`

```elixir
@spec stream_results(cursor_result()) :: Enumerable.t()
```

Returns a lazy stream of pages from a cursor-paginated result.

Each stream element is one page's `:results` list. Accepts the return
value of a `list_with_cursor` call.

Raises on errors encountered during pagination. Use `all_results/1`
if you prefer error tuples.

## Examples

    {:ok, data, cursor} = Pluggy.Connectors.list_with_cursor(client)

    {:ok, data, cursor}
    |> Pluggy.HTTP.stream_results()
    |> Enum.take(2)
    #=> [[%{id: 201, ...}, ...], [%{id: 301, ...}, ...]]

# `unwrap_tuple!`

Extracts the success value from a result tuple, raising on errors.

- `{:ok, value}` — returns `value`.
- `{:ok, a, b, ...}` — returns the tuple with `:ok` removed (e.g. `{a, b}`).
- `{:error, reason}` — raises `reason`.
- Anything else — raises `"Unexpected error"`.

## Examples

    iex> Pluggy.HTTP.unwrap_tuple!({:ok, 42})
    42

    iex> Pluggy.HTTP.unwrap_tuple!({:ok, :a, :b})
    {:a, :b}

    iex> Pluggy.HTTP.unwrap_tuple!({:ok, 1, 2, 3})
    {1, 2, 3}

    iex> Pluggy.HTTP.unwrap_tuple!({:error, %RuntimeError{message: "boom"}})
    ** (RuntimeError) boom

    iex> Pluggy.HTTP.unwrap_tuple!(:not_a_tuple)
    ** (RuntimeError) Unexpected error

# `with_cursor`

Fetches a page using the given fetcher and returns a cursor for the next page.

The `fetcher` is a function that accepts a page number and returns
`{:ok, paginated_response}` or `{:error, error}`.

Returns `{:ok, response, cursor}` where `cursor` is a `%Cursor{}` struct
when more pages are available, or `nil` when on the last page.

## Examples

    fetcher = fn page -> Pluggy.Connectors.list(client, page: page) end
    {:ok, response, cursor} = Pluggy.HTTP.with_cursor(fetcher)
    {:ok, next_response, nil} = Pluggy.HTTP.with_cursor(cursor)

# `with_cursor`

```elixir
@spec with_cursor(fetcher() | Pluggy.HTTP.Cursor.t(), pos_integer()) ::
  {:ok, map(), Pluggy.HTTP.Cursor.t() | nil} | {:error, Pluggy.Error.t()}
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
