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

Utilities for unwrapping paginated Pluggy API responses.

Pluggy list endpoints return a paginated map:

    %{results: [items...], page: 1, total_pages: 3, total: 150}

This module provides helpers for working with these responses:

  * `results/1` — extract the `:results` list from a single page;
    also accepts cursor tuples from `list_with_cursor`
  * `all_results/1` — eagerly collect and flatten all pages into one list

All functions accept `{:ok, body}` or `{:error, reason}` tuples and
propagate errors unchanged. `results/1` also accepts a bare
`%Req.Response{}` struct and cursor tuples for convenience.

## Req plugin

`attach/2` adds a response step to a `Req.Request` that automatically
unwraps paginated responses.

# `all_results`

```elixir
@spec all_results(Pluggy.HTTP.cursor_result()) ::
  {:ok, list()} | {:error, Pluggy.Error.t()}
```

Collects all items across every page into a single flat list.

Accepts the return value of a `list_with_cursor` call. Fetches all
remaining pages eagerly and returns `{:ok, items}` or `{:error, reason}`
if any page fetch fails.

## Examples

    Pluggy.Connectors.list_with_cursor(client)
    |> Pluggy.Unwrap.all_results()
    #=> [%{id: 201, ...}, %{id: 202, ...}, ...]

# `attach`

```elixir
@spec attach(Req.Request.t(), :results | :all_results | :stream) :: Req.Request.t()
```

Attaches an unwrap response step to a `Req.Request`.

The step transforms paginated response bodies according to the given mode.
Non-paginated responses (e.g. single-resource GETs) pass through unchanged.

## Modes

  * `:results` — replaces the body with the `:results` list from the
    current page
  * `:all_results` — eagerly fetches every page and replaces the body
    with a single flat list of all items
  * `:stream` — replaces the body with a lazy `Stream` that yields
    one paginated map per page (use `Enum` or `Stream` to consume)

Non-paginated responses pass through unchanged for all modes.

## Usage

    req = Pluggy.Unwrap.attach(req, :results)

    # Now paginated responses return just the items list:
    {:ok, %Req.Response{body: items}} = Req.request(req, url: "/transactions", ...)

    # Or eagerly fetch all pages:
    req = Pluggy.Unwrap.attach(req, :all_results)
    {:ok, %Req.Response{body: all_items}} = Req.request(req, url: "/transactions", ...)

    # Or stream pages lazily:
    req = Pluggy.Unwrap.attach(req, :stream)
    {:ok, %Req.Response{body: stream}} = Req.request(req, url: "/transactions", ...)
    stream |> Stream.flat_map(& &1.results) |> Enum.take(50)

# `result`

```elixir
@spec result({:ok, term()} | {:error, term()}) :: {:ok, term()} | {:error, term()}
```

Bang variant of `results/1` — extracts the `:results` list on success
or raises on error.

Also accepts cursor tuples from `list_with_cursor`.

## Examples

    iex> Pluggy.Unwrap.results!({:ok, %{results: [1, 2], page: 1, total_pages: 1, total: 2}})
    [1, 2]

    iex> Pluggy.Unwrap.result({:error, %Pluggy.Error{code: 500, message: "boom"}})
    {:error, %Pluggy.Error{code: 500, message: "boom"}}

# `results`

```elixir
@spec results(
  Req.Response.t()
  | {:ok, map(), nil}
  | {:ok, map(), Pluggy.HTTP.Cursor.t()}
  | {:ok, map()}
  | {:error, term()}
) :: {:ok, list() | term()} | {:error, term()}
```

Extracts the `:results` list from a paginated response.

Accepts `{:ok, body}`, `{:ok, body, cursor}`, `{:error, reason}`, or a
bare `%Req.Response{}`. Returns the body unchanged when it is not a
paginated map.

## Examples

    iex> Pluggy.Unwrap.results({:ok, %{results: [1, 2], page: 1, total_pages: 1, total: 2}})
    {:ok, [1, 2]}

    iex> Pluggy.Unwrap.results({:ok, %{id: "single"}})
    {:ok, %{id: "single"}}

    iex> Pluggy.Unwrap.results(%Req.Response{status: 200, body: %{results: [1, 2], page: 1, total_pages: 1, total: 2}})
    {:ok, [1, 2]}

    iex> Pluggy.Unwrap.results({:error, %Pluggy.Error{code: 500, message: "boom"}})
    {:error, %Pluggy.Error{code: 500, message: "boom"}}

# `results!`

```elixir
@spec results!(
  Req.Response.t()
  | {:ok, term(), nil}
  | {:ok, term(), Pluggy.HTTP.Cursor.t()}
  | {:ok, term()}
  | {:error, term()}
) :: term()
```

Unwraps a response tuple, returning the value on success or raising on error.

## Examples

    iex> Pluggy.Unwrap.result!({:ok, %{id: "single"}})
    %{id: "single"}

---

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