Query Scopes

Reusable query filters for cleaner, more maintainable code

Define Scopes

Scopes are defined in the scopes property of your model config. Each scope receives the QueryBuilder and optional parameters:

models/User.ts
import { defineModel, DataTypes } from "stabilize-orm";
const User = defineModel({
tableName: "users",
columns: {
id: { type: DataTypes.STRING, required: true, unique: true },
email: { type: DataTypes.STRING, length: 255, required: true },
name: { type: DataTypes.STRING, length: 100 },
isActive: { type: DataTypes.BOOLEAN, defaultValue: true },
role: { type: DataTypes.STRING, length: 50, defaultValue: "user" },
},
scopes: {
active: (qb) => qb.where("isActive = ?", true),
inactive: (qb) => qb.where("isActive = ?", false),
admin: (qb) => qb.where("role = ?", "admin"),
byRole: (qb, role: string) => qb.where("role = ?", role),
recent: (qb, days: number) => qb.where(
"createdAt >= ?",
new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString()
),
},
});

Use Scopes

Apply scopes via the scope() method on the repository or query builder:

examples/use-scopes.ts
const userRepo = orm.getRepository(User);
// Single scope
const activeUsers = await userRepo
.scope("active")
.execute(orm.client);
// Chain multiple scopes
const activeAdmins = await userRepo
.scope("active")
.scope("admin")
.execute(orm.client);
// Scope with parameters
const editors = await userRepo
.scope("byRole", "editor")
.execute(orm.client);
// Recent users (last 7 days)
const recentUsers = await userRepo
.scope("recent", 7)
.execute(orm.client);
// Combine scopes with other query methods
const recentActiveAdmins = await userRepo
.scope("active")
.scope("admin")
.scope("recent", 30)
.orderBy("createdAt", "DESC")
.limit(10)
.execute(orm.client);

Scopes with Soft Deletes

The find() method automatically filters out soft-deleted records. Scopes work within this filter:

examples/scope-soft-delete.ts
// Automatically excludes soft-deleted records
const activePosts = await postRepo
.scope("published")
.execute(orm.client);
// Find soft-deleted records
const deletedPosts = await postRepo
.findDeleted()
.execute(orm.client);
// Find all records including soft-deleted
const allPosts = await postRepo
.withTrashed()
.execute(orm.client);