MasterRecord
Lifecycle Hooks
React to persistence events right inside your entity.
Define hook methods on an entity to run code around its lifecycle. They’re ordinary methods (not field builders), so MasterRecord recognizes them by name and skips them during schema generation.
The four hooks#
| Hook | Runs |
|---|---|
beforeSave() | Before an insert or update. |
afterSave() | After a successful insert or update. |
beforeDelete() | Before deletion (throw to veto). |
afterDelete() | After a successful deletion. |
Example: hashing & timestamps#
User.js
import bcrypt from 'bcrypt';
export default class User {
id(db) { db.integer().primary().auto(); }
email(db) { db.string().unique(); }
password(db) { db.string(); }
role(db) { db.string(); }
created_at(db) { db.datetime(); }
updated_at(db) { db.datetime(); }
beforeSave() {
if (this.__dirtyFields.includes('password')) {
this.password = bcrypt.hashSync(this.password, 10);
}
if (this.__state === 'insert') this.created_at = new Date().toISOString();
this.updated_at = new Date().toISOString();
}
afterSave() {
console.log(`User ${this.id} saved`);
}
beforeDelete() {
if (this.role === 'admin') throw new Error('Cannot delete an admin');
}
async afterDelete() {
// clean up related files, caches, etc.
}
} Useful instance flags
Inside a hook,
this.__state is 'insert' or 'modified', and this.__dirtyFieldslists the changed columns — perfect for conditional logic like “only re-hash when the password changed.”