Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@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.
Documentation tree
- adapters — (no submodules)
- database-adapter — (no submodules)
- cursor — (no submodules)
- cursor-pagination — The
cursor-paginationmodule provides base64url cursor encoding/decoding and adapter-backed forward/backward fetch op… - cursor — (no submodules)
- cursor-pagination — The
- codes — Defines and registers all stable error codes for the
@suaveplan/paginationpackage usingdefineCodesfrom `@suavepl… - pagination-error —
PaginationErroris the structured error base class for all failures originating within@suaveplan/pagination. It ex… - helpers — (no submodules)
- helpers — (no submodules)
- keyset — (no submodules)
- keyset-pagination — (no submodules)
- offset — (no submodules)
- offset — (no submodules)
- otel — (no submodules)
- pagination-otel — (no submodules)
- tokens — (no submodules)
- page-tokens — (no submodules)
- cursor — (no submodules)- codes — Defines and registers all stable error codes for the
@suaveplan/paginationpackage usingdefineCodesfrom `@suavepl… - pagination-error —
PaginationErroris the structured error base class for all failures originating within@suaveplan/pagination. It ex… - helpers — (no submodules)- helpers — (no submodules)- keyset — (no submodules)- keyset-pagination — (no submodules)- offset — (no submodules)- offset — (no submodules)- otel — (no submodules)- pagination-otel — (no submodules)- tokens — (no submodules)- page-tokens — (no submodules)- database-adapter — (no submodules)- cursor — (no submodules)- cursor-pagination — The
cursor-paginationmodule provides base64url cursor encoding/decoding and adapter-backed forward/backward fetch op… - pagination-error —
PaginationErroris the structured error base class for all failures originating within@suaveplan/pagination. It ex… - helpers — (no submodules)- helpers — (no submodules)- keyset — (no submodules)- keyset-pagination — (no submodules)- offset — (no submodules)- offset — (no submodules)- otel — (no submodules)- pagination-otel — (no submodules)- tokens — (no submodules)- page-tokens — (no submodules)- database-adapter — (no submodules)- cursor — (no submodules)- cursor-pagination — The
cursor-paginationmodule provides base64url cursor encoding/decoding and adapter-backed forward/backward fetch op… - pagination-error —
PaginationErroris the structured error base class for all failures originating within@suaveplan/pagination. It ex… - helpers — (no submodules)- helpers — (no submodules)- keyset — (no submodules)- keyset-pagination — (no submodules)- offset — (no submodules)- offset — (no submodules)- otel — (no submodules)- pagination-otel — (no submodules)- tokens — (no submodules)- page-tokens — (no submodules)- database-adapter — (no submodules)- cursor — (no submodules) - cursor-pagination — The
cursor-paginationmodule provides base64url cursor encoding/decoding and adapter-backed forward/backward fetch op… - pagination-error —
PaginationErroris the structured error base class for all failures originating within@suaveplan/pagination. It ex… - helpers — (no submodules) - helpers — (no submodules)- keyset — (no submodules) - keyset-pagination — (no submodules)- offset — (no submodules) - offset — (no submodules)- otel — (no submodules) - pagination-otel — (no submodules)- tokens — (no submodules) - page-tokens — (no submodules)
Install
bun add @suaveplan/pagination
Quick start
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 | In-memory cursor pagination building blocks: cursorPaginateArray, createEdges, createConnection, calculateCursorMeta, normalizeCursorRequest |
| src/cursor/cursor-pagination.md | Adapter-backed cursor pagination: encodeCursor, decodeCursor, validateCursor, fetchAfter, fetchBefore |
| src/offset/offset.md | Offset/page-number pagination: paginateArray, normalizeOffsetRequest, calculateOffsetMeta, pageToOffset, offsetToPage, getPageRange, estimateTotalCount |
| src/keyset/keyset-pagination.md | Seek-based keyset pagination: keysetPaginate, fetchKeysetPage, encodeKeysetCursor, decodeKeysetCursor, extractSortKeys |
| src/helpers/helpers.md | Higher-order iteration utilities: createOffsetIterator, createCursorIterator, collectAll, collectUpTo, mapPaginated, mergeOffsetResponses |
| src/adapters/database-adapter.md | PaginationAdapter interface, MemoryPaginationAdapter, and createMemoryAdapter factory |
| src/tokens/page-tokens.md | Opaque page tokens with sort and filter metadata: createCursorToken, createOffsetToken, encodePageToken, decodePageToken, hashFilters, validateTokenFilter |
| 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 | PaginationError — structured error class extending SuaveplanError with PAGINATION.* codes |
| src/errors/codes.md | PAGINATION_CODES constant and PaginationCode union type |