Fast pagination, filtering, sorting & search — one Rust core, native Python & TypeScript packages, byte-for-byte parity.
📖 Documentation · 🐍 Python · 🟦 TypeScript · 🦀 Rust
paginate implements pagination, filtering, sorting, and search once, in a Rust
core, and exposes it through thin native packages for each language. The headline
guarantee is cross-language parity: the Python and TypeScript packages return the
same filtered / sorted / ranked order and byte-identical cursors, so a cursor minted
by a Python service decodes byte-for-byte in a TypeScript client.
| Language | Package | Install | Source |
|---|---|---|---|
| Python | pypaginate |
pip install pypaginate |
py/ |
| TypeScript / Node | @cyblow/paginate |
npm i @cyblow/paginate |
ts/ |
| Rust | paginate-core |
cargo add paginate-core |
crates/core/ |
The Python wheel and the npm package bundle the native engine (PyO3 / napi-rs prebuilt binaries) — there is no Rust toolchain to install.
| Python | TypeScript |
|---|---|
from pypaginate import (
paginate, filter, OffsetParams, FilterSpec,
)
page = paginate(users, OffsetParams(page=1, limit=20))
page.total # 1000
page.has_next # True
adults = filter(
users,
FilterSpec(field="age", operator="gte", value=18),
) |
import { paginate, filter, OffsetParams } from "@cyblow/paginate";
const page = paginate(users, new OffsetParams({ page: 1, limit: 20 }));
page.total; // 1000
page.hasNext; // true
const adults = filter(users, {
field: "age",
operator: "gte",
value: 18,
}); |
- One Rust core — filtering (20 operators + nested
And/Or), stable null-aware multi-key sorting, ranked + trigram-fuzzy search, the cursor codec, and pagination math all live once inpaginate-core. - Cross-language parity — a frozen golden fixture is asserted by the Rust, Python, and TypeScript suites in CI; cursors are byte-identical across languages.
- Two pagination models — offset (page/limit) and keyset (cursor), with the cursor a typed, portable wire format.
- Framework integrations — SQLAlchemy, Django, FastAPI (Python); Express, Prisma, Drizzle (TypeScript).
- Typed & dependency-light — spec/param/page shapes are generated from one JSON Schema, so the languages can't drift; the core has zero runtime dependencies.
See the docs for guides and the API reference, and
docs/ARCHITECTURE.md / docs/BENCHMARKS.md
for the design and measured performance.
crates/
core/ # paginate-core — the pure Rust engine (no bindings/ORM/DB)
pyo3/ # PyO3 binding -> the pypaginate._core extension module
node/ # napi-rs binding -> the @cyblow/paginate-core native addon
py/ # pypaginate — the Python package (+ SQLAlchemy/Django/FastAPI adapters)
ts/ # @cyblow/paginate — the TypeScript package (+ Express/Prisma/Drizzle)
website/ # the Docusaurus documentation site
docs/ # ARCHITECTURE.md, BENCHMARKS.md
schemas/ # the cross-language JSON Schema (source of the generated types)
# Rust core + napi addon
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
# Python package (builds the native core via maturin)
cd py && uv sync && uv run pytest
# TypeScript package (builds the native addon, then tests)
cd ts && bun install && bun run test
# Documentation site
cd website && bun install && bun run buildSee CONTRIBUTING.md for the full workflow and conventions.
MIT © CybLow