# Paginación

> Cómo recorrer cualquier colección con un cursor opaco, y cómo mantener una copia al día.

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

Todos los listados de esta API se leen igual: usted recorre una
[colección](https://developers.backresto.com/es/docs/collections) página a página, las entregas incluidas.

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

| Parámetro | Obligatorio | Reglas |
| --- | --- | --- |
| `limit` | no | De 1 a 100. Por defecto, 50. |
| `cursor` | no | El `nextCursor` de la página anterior, tal cual. |

La respuesta es `{ "data": [...], "nextCursor": string | null }`.

## Sin rango de tiempo

No hay `from` ni `to`. Un registro se modifica in situ (una corrección, un
tombstone), así que usted recorre la colección y concilia en lugar de pedir una
ventana de ella. Para leer una semana de entregas, recorra `deliveries` y quédese
con los registros cuyo `data.timestamp` caiga dentro de esa semana.

## Orden

Del cambio más antiguo al más reciente: ascendente por `sequence`, la posición
del último cambio de cada registro en el flujo. Compare dos valores de
`sequence`; no haga aritmética con uno.

## Recorrer las páginas

`nextCursor` es `null` en la última página y una cadena en las demás. Devuélvalo
intacto: es una posición opaca, no un documento que analizar, y su estructura
interna cambiará sin previo 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);
}
```

**Un recorrido es un snapshot coherente.** La primera página fija la posición
del flujo, y todas las páginas siguientes se responden en esa misma posición. Los
registros escritos mientras pagina no le mueven las páginas bajo los pies: los
verá en el siguiente recorrido.

El cursor está ligado al restaurante, a la colección **y al límite**. Cambie el
tamaño de página a mitad del recorrido y responde `400`: elija un límite y
consérvelo durante todo el recorrido.

## Mantener una copia al día

Hoy no hay parámetro `since`. Una actualización es otro recorrido, y usted
concilia con lo que ya tiene:

- **Indexe por `id`** dentro de una colección, y sobrescriba cuando el
  `sequence` que reciba sea mayor que el que guardó.
- **Respete los tombstones.** `deleted: true` es la instrucción de borrado;
  aplicarla es la única manera de que su copia deje de divergir.
- **Cuente con llegadas tardías.** Un dispositivo que estuvo sin conexión
  durante el servicio sube los datos al reconectarse, así que un registro puede
  aparecer después de un recorrido que habría cubierto su `data.timestamp`.
  Informe sobre `capturedAt`, sincronice sobre `receivedAt`.

Una página vacía no es prueba de que no ocurriera nada; consulte
[la nota sobre exhaustividad](https://developers.backresto.com/es/docs/support).
