# Paginação

> Como percorrer qualquer coleção com um cursor opaco, e como manter uma cópia dela atualizada.

Source: https://developers.backresto.com/pt/docs/pagination

Todas as listas desta API se leem da mesma maneira: percorre-se uma
[coleção](https://developers.backresto.com/pt/docs/collections) página a página, incluindo as entregas.

```http
GET /v1/restaurants/{restaurantId}/collections/{collection}/records
  ?limit=100
  &cursor=eyJpZCI6…
```

| Parâmetro | Obrigatório | Regras |
| --- | --- | --- |
| `limit` | não | De 1 a 100. Por omissão, 50. |
| `cursor` | não | O `nextCursor` da página anterior, tal e qual. |

A resposta é `{ "data": [...], "nextCursor": string | null }`.

## Sem intervalo de tempo

Não há `from` nem `to`. Um registo é alterado no lugar (uma correção, um
tombstone), por isso percorre-se a coleção e reconcilia-se, em vez de se pedir
uma janela dela. Para ler uma semana de entregas, percorra `deliveries` e
guarde os registos cujo `data.timestamp` cai dentro dessa semana.

## Ordenação

Da alteração mais antiga para a mais recente: por `sequence` ascendente, a
posição da última alteração de cada registo no fluxo. Compare dois valores de
`sequence`; não faça aritmética com um.

## Percorrer as páginas

`nextCursor` é `null` na última página e uma cadeia de caracteres nas restantes.
Devolva-o intacto: é uma posição opaca, não um documento para analisar, e o seu
conteúdo vai mudar sem aviso.

```js
async function* records({ apiKey, restaurantId, collection }) {
  const base = `https://api.backresto.com/v1/restaurants/${restaurantId}/collections/${collection}/records`;
  let cursor = null;

  do {
    const url = new URL(base);
    url.searchParams.set('limit', '100');
    if (cursor !== null) {
      url.searchParams.set('cursor', cursor);
    }

    const response = await fetch(url, {
      headers: { Authorization: `Bearer ${apiKey}` }
    });
    if (!response.ok) {
      throw new Error(`BackResto ${response.status}`);
    }

    const page = await response.json();
    yield* page.data;
    cursor = page.nextCursor;
  } while (cursor !== null);
}
```

**Um percurso é um snapshot coerente.** A primeira página fixa a posição no
fluxo, e todas as páginas seguintes são respondidas a partir dessa mesma
posição. Os registos escritos enquanto está a paginar não deslocam as páginas
debaixo de si. Vê-os no percurso seguinte.

O cursor está ligado ao restaurante, à coleção **e ao limite**. Mude o tamanho
da página a meio do percurso e a resposta é `400`: escolha um limite e
mantenha-o durante todo o percurso.

## Manter uma cópia atualizada

De momento não há parâmetro `since`. Uma atualização é outro percurso, e
reconcilia-se com o que já tem:

- **Indexe pelo `id`** dentro de uma coleção, e substitua quando o `sequence`
  que recebe for maior do que o que guardou.
- **Respeite os tombstones.** `deleted: true` é a instrução de apagar;
  aplicá-la é a única forma de a sua cópia deixar de divergir.
- **Conte com chegadas tardias.** Um dispositivo que esteve offline durante o
  serviço envia os dados quando volta a ligar-se, por isso um registo pode
  aparecer depois de um percurso que teria abrangido o seu `data.timestamp`.
  Faça os relatórios por `capturedAt` e sincronize por `receivedAt`.

Uma página vazia não é prova de que nada aconteceu. Veja
[a nota sobre a completude](https://developers.backresto.com/pt/docs/support).
