# `Sofa.Changes.Parser`
[🔗](https://github.com/skunkwerks/sofa/blob/0.5.1/lib/sofa/changes/parser.ex#L1)

Decodes `_changes` responses into events, using pure functions.

A continuous feed is one JSON object per line, arriving in chunks that
may split a line or have several. Empty lines are heartbeats. The
normal and longpoll feeds are a single JSON body with `results` and
`last_seq`. Both end up as the same formatted stream of events:

- `{:change, row}` for a document change, a map with `"id"`, `"seq"`,
  `"changes"` and optionally `"deleted"` and `"doc"`
- `{:last_seq, seq}` for the bare `{"last_seq": ...}` object a feed ends
  with, or the `last_seq` of a batch
- `{:error, map}` for `{"error": ..., "reason": ...}` objects, which
  CouchDB can emit inside a stream, and for lines that are not JSON

Sequences are opaque and are passed through untouched.

## Examples

    iex> {events, rest} = Sofa.Changes.Parser.feed("", ~s({"seq": 1, "id": "a", "changes": []}\n\n{"last_))
    iex> events
    [{:change, %{"seq" => 1, "id" => "a", "changes" => []}}]
    iex> rest
    ~s({"last_)
    iex> Sofa.Changes.Parser.feed(rest, ~s(seq": 1}\n))
    {[{:last_seq, 1}], ""}

# `event`

```elixir
@type event() :: {:change, row()} | {:last_seq, term()} | {:error, map()}
```

# `row`

```elixir
@type row() :: %{required(String.t()) =&gt; term()}
```

# `batch`

```elixir
@spec batch(map()) :: [event()]
```

The events for a normal or longpoll body. The rows come first, in order,
followed by the batch's `last_seq`.

# `feed`

```elixir
@spec feed(binary(), binary()) :: {[event()], binary()}
```

Appends `chunk` to the buffered partial line, returns the events for every
complete line, and the remaining partial line as the new buffer.

# `flush`

```elixir
@spec flush(binary()) :: [event()]
```

Decodes whatever is left in the buffer once the response has ended. A
well-behaved server ends with a newline, leaving nothing. Anything else
is decoded as a final line.

---

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