Skip to main content

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

HookSignatureDescription
beforeFetchstatic beforeFetch(qb: ModelQueryBuilder<T>)Modify query before fetching
afterFetchstatic async afterFetch(data: T[]): Promise<T[]>Transform results after fetching
beforeInsertstatic async beforeInsert(data: any): Promise<void>Modify data before insert
beforeInsertManystatic async beforeInsertMany(data: any[]): Promise<void>Modify data before bulk insert
beforeUpdatestatic beforeUpdate(qb: ModelQueryBuilder<T>)Modify query before update
beforeDeletestatic 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