93 lines
12 KiB
Markdown
93 lines
12 KiB
Markdown
# @suaveplan/pagination - Universal pagination primitives: cursor, offset, keyset strategies with adapters, iterators, and type-safe request/response shapes.
|
||
|
||
## Summary
|
||
|
||
Universal pagination primitives for cursor-based, offset-based, and keyset-based (seek) pagination strategies. The package covers the full pagination surface: request normalisation, response envelope construction, opaque cursor and page-token encoding, async iterators that drain pages automatically, a pluggable adapter interface for any data source, and optional OpenTelemetry instrumentation. All three strategies share the same error hierarchy and Zod schemas so they compose cleanly in multi-strategy APIs.
|
||
|
||
<!-- begin:auto-docs -->
|
||
## Documentation tree
|
||
|
||
- [adapters](./src/adapters/database-adapter.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [database-adapter](./src/adapters/database-adapter.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [cursor](./src/cursor/cursor.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [cursor-pagination](./src/cursor/cursor-pagination.md) — The `cursor-pagination` module provides base64url cursor encoding/decoding and adapter-backed forward/backward fetch op…
|
||
- [cursor](./src/cursor/cursor.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [codes](./src/errors/codes.md) — Defines and registers all stable error codes for the `@suaveplan/pagination` package using `defineCodes` from `@suavepl…
|
||
- [pagination-error](./src/errors/pagination-error.md) — `PaginationError` is the structured error base class for all failures originating within `@suaveplan/pagination`. It ex…
|
||
- [helpers](./src/helpers/helpers.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [helpers](./src/helpers/helpers.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [keyset](./src/keyset/keyset-pagination.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [keyset-pagination](./src/keyset/keyset-pagination.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [offset](./src/offset/offset.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [offset](./src/offset/offset.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [otel](./src/otel/pagination-otel.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [pagination-otel](./src/otel/pagination-otel.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [tokens](./src/tokens/page-tokens.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [page-tokens](./src/tokens/page-tokens.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
<!-- end:auto-docs --> - [database-adapter](./src/adapters/database-adapter.md) — <!-- begin:auto-docs --> _(no submodules)_- [cursor](./src/cursor/cursor.md) — <!-- begin:auto-docs --> _(no submodules)_- [cursor-pagination](./src/cursor/cursor-pagination.md) — The `cursor-pagination` module provides base64url cursor encoding/decoding and adapter-backed forward/backward fetch op…
|
||
- [cursor](./src/cursor/cursor.md) — <!-- begin:auto-docs --> _(no submodules)_- [codes](./src/errors/codes.md) — Defines and registers all stable error codes for the `@suaveplan/pagination` package using `defineCodes` from `@suavepl…
|
||
- [pagination-error](./src/errors/pagination-error.md) — `PaginationError` is the structured error base class for all failures originating within `@suaveplan/pagination`. It ex…
|
||
- [helpers](./src/helpers/helpers.md) — <!-- begin:auto-docs --> _(no submodules)_- [helpers](./src/helpers/helpers.md) — <!-- begin:auto-docs --> _(no submodules)_- [keyset](./src/keyset/keyset-pagination.md) — <!-- begin:auto-docs --> _(no submodules)_- [keyset-pagination](./src/keyset/keyset-pagination.md) — <!-- begin:auto-docs --> _(no submodules)_- [offset](./src/offset/offset.md) — <!-- begin:auto-docs --> _(no submodules)_- [offset](./src/offset/offset.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/pagination-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [pagination-otel](./src/otel/pagination-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [tokens](./src/tokens/page-tokens.md) — <!-- begin:auto-docs --> _(no submodules)_- [page-tokens](./src/tokens/page-tokens.md) — <!-- begin:auto-docs --> _(no submodules)_- [database-adapter](./src/adapters/database-adapter.md) — <!-- begin:auto-docs --> _(no submodules)_- [cursor](./src/cursor/cursor.md) — <!-- begin:auto-docs --> _(no submodules)_- [cursor-pagination](./src/cursor/cursor-pagination.md) — The `cursor-pagination` module provides base64url cursor encoding/decoding and adapter-backed forward/backward fetch op…
|
||
- [cursor](./src/cursor/cursor.md) — <!-- begin:auto-docs --> _(no submodules)_- [codes](./src/errors/codes.md) — Defines and registers all stable error codes for the `@suaveplan/pagination` package using `defineCodes` from `@suavepl…
|
||
- [pagination-error](./src/errors/pagination-error.md) — `PaginationError` is the structured error base class for all failures originating within `@suaveplan/pagination`. It ex…
|
||
- [helpers](./src/helpers/helpers.md) — <!-- begin:auto-docs --> _(no submodules)_- [helpers](./src/helpers/helpers.md) — <!-- begin:auto-docs --> _(no submodules)_- [keyset](./src/keyset/keyset-pagination.md) — <!-- begin:auto-docs --> _(no submodules)_- [keyset-pagination](./src/keyset/keyset-pagination.md) — <!-- begin:auto-docs --> _(no submodules)_- [offset](./src/offset/offset.md) — <!-- begin:auto-docs --> _(no submodules)_- [offset](./src/offset/offset.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/pagination-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [pagination-otel](./src/otel/pagination-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [tokens](./src/tokens/page-tokens.md) — <!-- begin:auto-docs --> _(no submodules)_- [page-tokens](./src/tokens/page-tokens.md) — <!-- begin:auto-docs --> _(no submodules)_- [database-adapter](./src/adapters/database-adapter.md) — <!-- begin:auto-docs --> _(no submodules)_- [cursor](./src/cursor/cursor.md) — <!-- begin:auto-docs --> _(no submodules)_- [cursor-pagination](./src/cursor/cursor-pagination.md) — The `cursor-pagination` module provides base64url cursor encoding/decoding and adapter-backed forward/backward fetch op…
|
||
- [cursor](./src/cursor/cursor.md) — <!-- begin:auto-docs --> _(no submodules)_- [codes](./src/errors/codes.md) — Defines and registers all stable error codes for the `@suaveplan/pagination` package using `defineCodes` from `@suavepl…
|
||
- [pagination-error](./src/errors/pagination-error.md) — `PaginationError` is the structured error base class for all failures originating within `@suaveplan/pagination`. It ex…
|
||
- [helpers](./src/helpers/helpers.md) — <!-- begin:auto-docs --> _(no submodules)_- [helpers](./src/helpers/helpers.md) — <!-- begin:auto-docs --> _(no submodules)_- [keyset](./src/keyset/keyset-pagination.md) — <!-- begin:auto-docs --> _(no submodules)_- [keyset-pagination](./src/keyset/keyset-pagination.md) — <!-- begin:auto-docs --> _(no submodules)_- [offset](./src/offset/offset.md) — <!-- begin:auto-docs --> _(no submodules)_- [offset](./src/offset/offset.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/pagination-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [pagination-otel](./src/otel/pagination-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [tokens](./src/tokens/page-tokens.md) — <!-- begin:auto-docs --> _(no submodules)_- [page-tokens](./src/tokens/page-tokens.md) — <!-- begin:auto-docs --> _(no submodules)_- [database-adapter](./src/adapters/database-adapter.md) — <!-- begin:auto-docs --> _(no submodules)_- [cursor](./src/cursor/cursor.md) — <!-- begin:auto-docs --> _(no submodules)_ - [cursor-pagination](./src/cursor/cursor-pagination.md) — The `cursor-pagination` module provides base64url cursor encoding/decoding and adapter-backed forward/backward fetch op…
|
||
- [cursor](./src/cursor/cursor.md) — <!-- begin:auto-docs --> _(no submodules)_- [codes](./src/errors/codes.md) — Defines and registers all stable error codes for the `@suaveplan/pagination` package using `defineCodes` from `@suavepl…
|
||
- [pagination-error](./src/errors/pagination-error.md) — `PaginationError` is the structured error base class for all failures originating within `@suaveplan/pagination`. It ex…
|
||
- [helpers](./src/helpers/helpers.md) — <!-- begin:auto-docs --> _(no submodules)_ - [helpers](./src/helpers/helpers.md) — <!-- begin:auto-docs --> _(no submodules)_- [keyset](./src/keyset/keyset-pagination.md) — <!-- begin:auto-docs --> _(no submodules)_ - [keyset-pagination](./src/keyset/keyset-pagination.md) — <!-- begin:auto-docs --> _(no submodules)_- [offset](./src/offset/offset.md) — <!-- begin:auto-docs --> _(no submodules)_ - [offset](./src/offset/offset.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/pagination-otel.md) — <!-- begin:auto-docs --> _(no submodules)_ - [pagination-otel](./src/otel/pagination-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [tokens](./src/tokens/page-tokens.md) — <!-- begin:auto-docs --> _(no submodules)_ - [page-tokens](./src/tokens/page-tokens.md) — <!-- begin:auto-docs --> _(no submodules)_
|
||
## Install
|
||
|
||
```bash
|
||
bun add @suaveplan/pagination
|
||
```
|
||
|
||
## Quick start
|
||
|
||
```ts
|
||
import { paginateArray } from "@suaveplan/pagination/offset";
|
||
import { cursorPaginateArray } from "@suaveplan/pagination/cursor";
|
||
import { createOffsetIterator, collectAll } from "@suaveplan/pagination/helpers";
|
||
|
||
// Offset: slice page 2, 10 items per page
|
||
const items = Array.from({ length: 50 }, (_, i) => ({ id: i + 1 }));
|
||
const page2 = paginateArray(items, 2, 10);
|
||
// page2.data → items 11–20
|
||
// page2.meta.totalPages → 5, page2.meta.hasNext → true
|
||
|
||
// Cursor: paginate an in-memory array by item.id
|
||
const users = [{ id: "a" }, { id: "b" }, { id: "c" }, { id: "d" }];
|
||
const first = cursorPaginateArray(users, { limit: 2 }, (u) => u.id);
|
||
// first.meta.endCursor → "b", first.meta.hasNextPage → true
|
||
const second = cursorPaginateArray(
|
||
users,
|
||
{ cursor: first.meta.endCursor ?? undefined, limit: 2 },
|
||
(u) => u.id
|
||
);
|
||
// second.data → [{ id: "c" }, { id: "d" }]
|
||
|
||
// Helpers: drain all pages into a flat array
|
||
const iter = createOffsetIterator(
|
||
(page, limit) => Promise.resolve(paginateArray(items, page, limit)),
|
||
{ limit: 10 }
|
||
);
|
||
const all = await collectAll(iter); // → all 50 items
|
||
```
|
||
|
||
## Modules
|
||
|
||
| Module | Description |
|
||
|--------|-------------|
|
||
| [src/cursor/cursor.md](src/cursor/cursor.md) | In-memory cursor pagination building blocks: `cursorPaginateArray`, `createEdges`, `createConnection`, `calculateCursorMeta`, `normalizeCursorRequest` |
|
||
| [src/cursor/cursor-pagination.md](src/cursor/cursor-pagination.md) | Adapter-backed cursor pagination: `encodeCursor`, `decodeCursor`, `validateCursor`, `fetchAfter`, `fetchBefore` |
|
||
| [src/offset/offset.md](src/offset/offset.md) | Offset/page-number pagination: `paginateArray`, `normalizeOffsetRequest`, `calculateOffsetMeta`, `pageToOffset`, `offsetToPage`, `getPageRange`, `estimateTotalCount` |
|
||
| [src/keyset/keyset-pagination.md](src/keyset/keyset-pagination.md) | Seek-based keyset pagination: `keysetPaginate`, `fetchKeysetPage`, `encodeKeysetCursor`, `decodeKeysetCursor`, `extractSortKeys` |
|
||
| [src/helpers/helpers.md](src/helpers/helpers.md) | Higher-order iteration utilities: `createOffsetIterator`, `createCursorIterator`, `collectAll`, `collectUpTo`, `mapPaginated`, `mergeOffsetResponses` |
|
||
| [src/adapters/database-adapter.md](src/adapters/database-adapter.md) | `PaginationAdapter` interface, `MemoryPaginationAdapter`, and `createMemoryAdapter` factory |
|
||
| [src/tokens/page-tokens.md](src/tokens/page-tokens.md) | Opaque page tokens with sort and filter metadata: `createCursorToken`, `createOffsetToken`, `encodePageToken`, `decodePageToken`, `hashFilters`, `validateTokenFilter` |
|
||
| [src/otel/pagination-otel.md](src/otel/pagination-otel.md) | OTel instrumentation: `getPaginationInstruments` with request counter, page-size histogram, and encode/decode histogram; graceful no-op fallback |
|
||
| [src/errors/pagination-error.md](src/errors/pagination-error.md) | `PaginationError` — structured error class extending `SuaveplanError` with `PAGINATION.*` codes |
|
||
| [src/errors/codes.md](src/errors/codes.md) | `PAGINATION_CODES` constant and `PaginationCode` union type |
|
||
|