Migration guide
Upgrade notes between versions. Most upgrades need no code change — the spec / param shapes and the public helpers are stable.
→ v1.0.0 — first stable release
paginate reaches 1.0.0 across all three packages — paginate-core, pypaginate,
and @cyblow/paginate — released together with a stable public API. The
paginate / filter / sort / search / Dataset surface, the spec/param shapes,
and the cursor wire format are unchanged, so existing code keeps working.
- Malformed cursors now raise
InvalidCursorError(a subclass ofValidationError) in both languages, instead of leaking the native engine error — catch it asInvalidCursorError/ValidationError/PaginateError.
→ v0.4 — generated types, Pydantic-optional (Python)
The Python package (pypaginate) was rebuilt from scratch. Behaviour and the
public-API shapes are unchanged, but the types are now dataclasses generated
from the Rust core (not Pydantic), and Pydantic is optional.
- Construct specs / params the same way —
FilterSpec(field=…, operator=…, value=…),OffsetParams(page=1, limit=20),And(…)/Or(…)are unchanged. Operators / directions / modes are plain strings ("gte","desc","contains"). - Pages are generic containers —
OffsetPage[T]/CursorPage[T]supportlen(), iteration, and indexing, and hold your rows untouched (no per-row coercion). - Removed: the Pydantic model APIs.
.model_dump()/.model_validate()on specs and pages are gone. Use the dataclass fields directly ordataclasses.asdict(…). - Pydantic is no longer a core dependency. In-memory / SQLAlchemy / Django users
don't install it. Opt in for FastAPI:
pip install "pypaginate[fastapi]"(the FastAPI adapter still uses Pydantic for request/response models + OpenAPI).
→ v0.3 — fat core, thin adapters
v0.3 moves all computation into the shared Rust core (paginate-core): the
cursor codec, offset math, page assembly, filter / sort / search, and the keyset
predicate now have a single implementation that the Python and TypeScript packages
wrap. The headline guarantee is cross-language parity.
Python (pypaginate)
Most code needs no change. Notable points:
- New one-shot
filter/sort/searchfor in-memory lists, alongsidepaginate— see the Python quickstart. - Invalid enum tokens now raise instead of silently defaulting (canonical
string↔enum parsing moved into the core): a misspelled operator / direction / mode
raises
FilterError/SortError/SearchError. - The native
_coreextension is mandatory — no pure-Python fallback; install a wheel or build with a Rust toolchain (PyPy unsupported). - Fuzzy / token-sort search is now trigram-based (pg_trgm model), not rapidfuzz —
faster and length-normalized, but scores/ranking differ and the default
thresholddrops 75 → 30. Tunethresholdfor your data. - Removed (dev/internal only): the
pypaginateconsole-script CLI (use the repo'sjustrecipes) and the internalpypaginate.filtering/sorting/search/text.normalizeimport paths (use the publicDataset/ helpers). - New: the Django adapter —
pip install "pypaginate[django]".
TypeScript (@cyblow/paginate)
Completed to parity and split into modules. Breaking changes from the 0.1.x preview:
| Before | After |
|---|---|
filterIndices(items, [{ field, op, value }]) | [{ field, operator, value }] (op still accepted) |
searchIndices(items, query, fields, opts) | searchIndices(items, { query, fields, mode, fuzzy, … }) |
ds.page(1, 20, opts) | ds.page(new OffsetParams({ page: 1, limit: 20 }), opts) |
ds.search(query, fields, opts) | ds.search({ query, fields, mode, … }) |
New surface: OffsetParams / CursorParams, OffsetPage<T> / CursorPage<T>,
And() / Or(), a top-level paginate(), the error hierarchy, and the express /
prisma / drizzle adapters. See the API Reference section (TypeScript, Python,
Rust) in the sidebar for the full surface.