What problem does it solve?
It solves the problem of building reliable, maintainable database access layers by providing a fluent ORM for CRUD, filtering, sorting, pagination, relations, and transactions so you can query Postgres or SQLite without hand-writing repetitive SQL.
Core Features & Use Cases
- CRUD operations: Insert, find, update, and delete rows for generated models.
- Fluent querying with filters: Use
where callbacks with typed conditions (equality, comparisons, ranges, sets, like/ilike) and logical composition.
- Sorting and pagination: Support both offset-based (
limit + offset) and cursor-based pagination patterns.
- Relations handling: Include related objects and attach/detach related rows for one-to-one and one-to-many relationships.
- Transactions and row locking: Run multiple operations atomically and optionally lock rows with
LockMode for concurrency-safe workflows.
- Runtime parameters and raw SQL: Tune Postgres runtime settings (like search paths) and fall back to parameterized raw SQL when needed.
- Client-side database sessions: Enable generated client code to create a local SQLite database session for offline-capable Flutter apps.
Quick Start
Generate your ORM models from your .spy.yaml (with table: defined), then use Model.db.find/findById/find with typed where filters and include to fetch related data from Postgres or SQLite.