Model Hooks & Lifecycle
Hooks allow you to run logic before or after certain model actions. They are static methods on your model.
note
Hooks do not apply to joined models in queries from other models.
// Post model hooks won't run here
const users = await User.query().join("posts", "posts.userId", "users.id").all();
Available Hooks
| Hook | Signature | Description |
|---|---|---|
beforeFetch | static beforeFetch(qb: ModelQueryBuilder<T>) | Modify query before fetching |
afterFetch | static async afterFetch(data: T[]): Promise<T[]> | Transform results after fetching |
beforeInsert | static async beforeInsert(data: any): Promise<void> | Modify data before insert |
beforeInsertMany | static async beforeInsertMany(data: any[]): Promise<void> | Modify data before bulk insert |
beforeUpdate | static beforeUpdate(qb: ModelQueryBuilder<T>) | Modify query before update |
beforeDelete | static beforeDelete(qb: ModelQueryBuilder<T>) | Modify query before delete |
Example: Soft Delete Filtering
import { Model, column, ModelQueryBuilder } from 'hysteria-orm';
export class User extends Model {
@column.integer({ primaryKey: true })
declare id: number;
@column()
declare name: string;
@column.date()
declare deletedAt: Date | null;
static beforeFetch(queryBuilder: ModelQueryBuilder<User>): void {
queryBuilder.whereNull('users.deleted_at');
}
static beforeInsert(data: User): void {
data.isAdmin = false;
}
static afterFetch(data: User[]): User[] {
return data.filter((user) => user.deletedAt === null);
}
}
Ignoring Hooks
You can bypass hooks when needed using the ignoreHooks option:
// Fetch soft-deleted records by ignoring beforeFetch hook
const allUsers = await User.query()
.many({ ignoreHooks: ["beforeFetch"] });
Next: Model Mixins