Skip to main content
zerotal

Documentation


Documentation / zerotal / orm / BaseModel

Class: BaseModel

Defined in: packages/orm/src/model/BaseModel.ts:547

Base class for every Zerotal Active Record model, backed by Bun.sql.

Subclass it, declare columns with @column, and you get querying, persistence, dirty tracking, relationships, serialization, timestamps, lifecycle hooks, and (opt-in) soft deletes — Active Record-style, but fully typed against your model's own properties.

Remarks

An instance is a row: its enumerable data properties are the attributes. The model snapshots them on load, so isDirty, $dirty, and save write only changed columns (an UPDATE touches dirty columns only; a new instance INSERTs).

Mass assignment is guarded by default. A model that declares neither fillable (allowlist) nor guarded (denylist) rejects every attribute passed to fill / create with a MassAssignmentError, so a stray key from a request body can never reach the database. Use forceFill / forceCreate for trusted, framework-internal writes only.

Timestamps (created_at / updated_at) are maintained automatically when timestamps is true (the default). The primary key is id unless primaryKey is overridden. Soft deletes are opt-in via the SoftDeletes mixin (which sets softDeletes); once enabled, queries scope WHERE deleted_at IS NULL and delete sets deleted_at instead of removing the row.

@column({ cast }) / casts coerce values on read and write (booleans, JSON/array, dates via Carbon, decimals, enums). hashable fields are bcrypt-hashed transparently on save. hidden / visible / appends shape toJSON output.

Examples

Defining a model with @column:

@table("users").withTimestamps()
export class User extends BaseModel {
  static fillable: Columns<User>[] = ["name", "email", "password"];
  static hidden: Columns<User>[] = ["password"];
  static hashable = ["password"];

  @column() name!: string;
  @column() email!: string;
  @column() password!: string;
  @column({ cast: "boolean" }) active?: boolean;
}

Querying, creating, and saving:

// Create (mass-assignment respects `fillable`)
const user = await User.create({ name: "Ada", email: "ada@example.com", password: "s3cret" });

// Query
const admins = await User.where("role", "admin").orderBy("name").get();
const found = await User.findOrFail(user.id); // throws ModelNotFoundError if missing

// Mutate + persist (only dirty columns are written)
found.name = "Ada Lovelace";
await found.save();

Extended by

Constructors

Constructor

new BaseModel(): BaseModel

Returns

BaseModel

Attributes & mass assignment

table

static table: string

Defined in: packages/orm/src/model/BaseModel.ts:569

Database table this model maps to. Usually set for you by the @table("…") decorator; assign directly to override.


primaryKey

static primaryKey: string = "id"

Defined in: packages/orm/src/model/BaseModel.ts:576

Primary-key column name. Defaults to id.


casts?

static optional casts?: Record<string, "boolean" | "json" | "date" | "array" | "datetime" | "integer" | "float" | "enum" | "immutable_datetime" | `decimal:${number}` | { get?: (dbValue) => unknown; set?: (jsValue) => unknown; } | CastContract<unknown> | undefined>

Defined in: packages/orm/src/model/BaseModel.ts:604

Per-attribute cast map applied on read/write — string shorthands ("boolean", "json", "array", "date", "datetime", "integer", "float", "decimal:2", "enum", "immutable_datetime") or a custom cast object with get/set. Merged across the prototype chain.


reactiveCasts

static reactiveCasts: boolean = true

Defined in: packages/orm/src/model/BaseModel.ts:621

Wrap json/array cast columns in a reactive proxy so mutating them in place (user.meta.count = 99) marks the column dirty. Defaults to true.

Off, the failure is silent and looks like success: _applyRow stores the same object reference in the instance and in _original, and $dirty() compares with !==, so user.meta.count = 99; await user.save() issues no UPDATE and reports no error. The proxy is allocated only for columns actually cast to json/array.

Set false for a model where that cost is measurable and every write to a JSON column replaces the whole value (user.meta = { ...user.meta, count: 99 }), which dirty tracking sees either way.


fillable?

static optional fillable?: string[]

Defined in: packages/orm/src/model/BaseModel.ts:663

Allowlist of camelCase field names accepted by create() / fill(). When set, any key not in this list is rejected with MassAssignmentError. Cannot be used together with guarded.


guarded?

static optional guarded?: string[]

Defined in: packages/orm/src/model/BaseModel.ts:672

Denylist of camelCase field names blocked from create() / fill(). When set, listed keys are rejected; all other keys are accepted. Cannot be used together with fillable.


unguarded

static unguarded: boolean = false

Defined in: packages/orm/src/model/BaseModel.ts:685

Disable mass-assignment protection for this model — every attribute passed to fill() / create() is accepted.

Models guard by default: when neither fillable nor guarded is declared, fill() rejects every attribute (throwing MassAssignmentError) so an unexpected key from a request body can never reach the database. Set this to true only for models whose writes never come from user input.


unguard()

static unguard(): void

Defined in: packages/orm/src/model/BaseModel.ts:705

Turn off mass-assignment guarding process-wide (trusted contexts only).

Returns

void


reguard()

static reguard(): void

Defined in: packages/orm/src/model/BaseModel.ts:714

Restore mass-assignment guarding process-wide.

Returns

void


withoutGuard()

static withoutGuard<T>(callback): Promise<T>

Defined in: packages/orm/src/model/BaseModel.ts:724

Run callback with mass-assignment guarding disabled process-wide, restoring the previous setting afterwards (even on throw).

Type Parameters

T

T

Parameters

callback

() => T | Promise<T>

Returns

Promise<T>


id

id: number

Defined in: packages/orm/src/model/BaseModel.ts:819

Primary-key value. Populated after save inserts a new row, or when the instance is hydrated from the database.


fill()

fill(data): this

Defined in: packages/orm/src/model/BaseModel.ts:1235

Mass-assign fields, respecting fillable / guarded protection. Call this instead of Object.assign when data comes from user input.

Guarded by default: a model that declares neither fillable nor guarded (and is not unguarded) rejects every attribute with a MassAssignmentError, so a stray key from a request body can never reach the database. Declare fillable to allow specific columns, or use forceFill for trusted, framework-internal writes.

Accepts UpdatePayload<this> — a partial of the model's writable, non-relation, non-auto-managed columns. Passing id, createdAt, relations, or methods is a compile-time error.

Parameters

data

UpdatePayload<this>

Returns

this

Example

post.fill(ctx.body<UpdatePayload<Post>>());

Throws

when data contains a key not permitted by this model's fillable / guarded configuration.


forceFill()

forceFill(data): this

Defined in: packages/orm/src/model/BaseModel.ts:1277

Mass-assign fields bypassing fillable / guarded protection. Use only for trusted data you construct yourself (framework-internal writes, factories, seeders) — never for request input.

Parameters

data

Record<string, unknown>

Returns

this

Example

// Trusted, non-user data:
role.forceFill({ name, guard });

isDirty()

isDirty(column?): boolean

Defined in: packages/orm/src/model/BaseModel.ts:2167

True when the model (or a specific column) has unsaved changes since it was loaded or last saved.

Parameters

column?

string

Returns

boolean


$dirty()

$dirty(): Record<string, unknown>

Defined in: packages/orm/src/model/BaseModel.ts:2182

Return a map of changed columns to their current values — the set that a subsequent save would write.

Returns

Record<string, unknown>


markDirty()

markDirty(property): this

Defined in: packages/orm/src/model/BaseModel.ts:2202

Force a property to be treated as dirty so it is included in the next save, even if its value is reference-equal to the loaded snapshot (e.g. an in-place mutation of a JSON column).

Parameters

property

keyof BaseModel

Returns

this

Comparison

is()

is(other): boolean

Defined in: packages/orm/src/model/BaseModel.ts:1900

True when other is the same model class with the same primary key.

Parameters

other

BaseModel | null | undefined

Returns

boolean


isNot()

isNot(other): boolean

Defined in: packages/orm/src/model/BaseModel.ts:1915

Inverse of is.

Parameters

other

BaseModel | null | undefined

Returns

boolean

Lifecycle & hooks

dispatchesEvents?

static optional dispatchesEvents?: Record<string, (model) => object>

Defined in: packages/orm/src/model/BaseModel.ts:654

Maps lifecycle events to event classes that are dispatched on the app event bus when they fire (via $dispatchesEvents). Keys: creating, created, updating, updated, saving, saved, deleting, deleted, retrieved. Each event class is constructed with the model instance and emitted (no-op if no bus is bound).

Example

static dispatchesEvents = { created: OrderPlaced, deleted: OrderCancelled };

observe()

static observe<T>(this, ObserverClass): void

Defined in: packages/orm/src/model/BaseModel.ts:806

Register an observer class for this model. The observer's lifecycle methods (creating, created, updating, …) are wired into the HookRegistry automatically.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

ObserverClass

() => ModelObserver<T>

Returns

void

Example

User.observe(UserObserver);  // call once at boot in a ServiceProvider

Other

__isZerotalModel

readonly __isZerotalModel: true

Defined in: packages/orm/src/model/BaseModel.ts:561

Phantom nominal brand, used ONLY at the type level to detect relation properties (see ColumnKeys in payload.ts). Detecting relations by this one marker — rather than structurally via extends BaseModel — avoids forcing TS to re-resolve a related model's fill(data: UpdatePayload<this>) signature, which is itself defined in terms of ColumnKeys. That structural feedback loop is what makes mutually-referential models (A.b: B, B.a: A) trip TS2615 ("circularly references itself in mapped type").

declare => purely type-level, no runtime field is emitted and instances never carry it. The leading underscore keeps it out of column/serialization key sets automatically.

Persistence

hashable?

static optional hashable?: string[]

Defined in: packages/orm/src/model/BaseModel.ts:794

Fields that are automatically hashed with Bun.password.hash() (bcrypt) before every INSERT and whenever the field changes on UPDATE.

The hash is applied transparently in save() — the plaintext value is never written to the database. Use Bun.password.verify() to check a plaintext candidate against the stored hash.

Example

static hashable = ['password'];

// Verify later:
const ok = await Bun.password.verify(candidate, user.password);

massPrune

static massPrune: boolean = false

Defined in: packages/orm/src/model/BaseModel.ts:913

When true, prune() permanently deletes rows (forceDelete) rather than soft-deleting them.


prunable()?

static optional prunable<T>(this): ModelQueryBuilder<T>

Defined in: packages/orm/src/model/BaseModel.ts:925

Override to return the query selecting records eligible for pruning. Implement this to make a model "prunable" (used by prune() and a scheduled model:prune task).

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

Returns

ModelQueryBuilder<T>

Example

static prunable() { return this.query().where('created_at', '<', cutoff); }

prune()

static prune<T>(this, chunkSize?): Promise<number>

Defined in: packages/orm/src/model/BaseModel.ts:934

Delete prunable records in chunks. Returns the number of records pruned. Honours massPrune (permanent delete) vs. soft delete.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

chunkSize?

number = 1000

Returns

Promise<number>

Throws

when the model does not define a static prunable() method.


create()

static create<T>(this, data): Promise<T>

Defined in: packages/orm/src/model/BaseModel.ts:1208

Mass-assign data (respecting fillable / guarded) onto a new instance and save it, returning the persisted model.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

data

InsertPayload<T>

Returns

Promise<T>

Throws

when data contains a non-fillable key.

Example

const user = await User.create({ name: "Ada", email: "ada@example.com" });

forceCreate()

static forceCreate<T>(this, data): Promise<T>

Defined in: packages/orm/src/model/BaseModel.ts:1291

Like create, but bypasses mass-assignment protection. Use only for trusted data (framework-internal writes, seeders), never for request input.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

data

Record<string, unknown>

Returns

Promise<T>


firstOrCreate()

static firstOrCreate<T>(this, search, create?): Promise<T>

Defined in: packages/orm/src/model/BaseModel.ts:1307

Return the first row matching search, or create one from search merged with create.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

UpdatePayload<T>

create?

Partial<InsertPayload<T>>

Returns

Promise<T>

Throws

when a created key is not fillable.


updateOrCreate()

static updateOrCreate<T>(this, search, values?): Promise<T>

Defined in: packages/orm/src/model/BaseModel.ts:1333

Update the first row matching search, or create it. Returns the model.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

search

UpdatePayload<T>

values?

Partial<InsertPayload<T>>

Returns

Promise<T>

Example

await User.updateOrCreate({ email }, { name, lastSeenAt: new Date() });

Throws

when an updated/created key is not fillable.


firstOrNew()

static firstOrNew<T>(this, search, values?): Promise<T>

Defined in: packages/orm/src/model/BaseModel.ts:1360

Return the first row matching search, or a new unsaved instance filled with search + values.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

search

UpdatePayload<T>

values?

Partial<InsertPayload<T>>

Returns

Promise<T>

Throws

when a filled key is not fillable.


findOrNew()

static findOrNew<T>(this, id): Promise<T>

Defined in: packages/orm/src/model/BaseModel.ts:1381

Find by primary key, or return a new unsaved instance if not found.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

id

string | number

Returns

Promise<T>


createMany()

static createMany<T>(this, records): Promise<T[]>

Defined in: packages/orm/src/model/BaseModel.ts:1398

Create multiple rows one at a time, returning the saved model instances. Each row goes through the full save() path — casts, hashing, timestamps, and observer/hook events all fire per row.

For large bulk loads where per-row events are not needed, prefer bulkInsert which issues a single multi-row INSERT.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

records

InsertPayload<T>[]

Returns

Promise<T[]>

Throws

when any record contains a non-fillable key.


bulkInsert()

static bulkInsert<T>(this, records): Promise<number>

Defined in: packages/orm/src/model/BaseModel.ts:1416

Insert many rows in a single multi-row INSERT, returning the number of rows written. Applies casts and timestamps but bypasses per-row save() lifecycle hooks — the fast path for bulk loads. Use createMany when you need hooks/observers per row.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

records

InsertPayload<T>[]

Returns

Promise<number>

the number of rows inserted (0 for an empty input).


saveMany()

static saveMany<T>(this, models): Promise<T[]>

Defined in: packages/orm/src/model/BaseModel.ts:1470

Persist multiple already-built instances (each via save).

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

models

T[]

Returns

Promise<T[]>


upsert()

static upsert<T>(this, data, conflictKeys, updateCols?): Promise<void>

Defined in: packages/orm/src/model/BaseModel.ts:1503

INSERT a row; update specified columns when the unique constraint fires.

  • PostgreSQL / SQLite: ON CONFLICT (conflictKeys) DO UPDATE SET …
  • MySQL: ON DUPLICATE KEY UPDATE … = VALUES(…)

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

data

InsertPayload<T>

Row data (camelCase keys are converted to snake_case)

conflictKeys

keyof T & string[]

Columns that define the conflict constraint (ignored on MySQL)

updateCols?

keyof T & string[]

Columns to overwrite on conflict (defaults to all non-conflict cols)

Returns

Promise<void>

Example

await User.upsert({ email: 'a@b.com', name: 'Alice' }, ['email'], ['name']);

save()

save(): Promise<BaseModel>

Defined in: packages/orm/src/model/BaseModel.ts:1594

Persist this instance: INSERT when new, or UPDATE of only the dirty columns when it already exists. Applies casts, hashes hashable fields, maintains timestamps, and runs the save/create/update lifecycle hooks. On insert the new primary key (and full row) are read back onto the instance. Returns this.

Returns

Promise<BaseModel>

Example

const user = new User();
user.fill({ name: "Ada", email: "ada@example.com" });
await user.save();

delete()

delete(): Promise<void>

Defined in: packages/orm/src/model/BaseModel.ts:1754

Delete this record. For soft-delete models this sets deleted_at (the row stays in the table but is hidden from default queries); otherwise it issues a hard DELETE. Runs the before/after delete lifecycle hooks.

Returns

Promise<void>


fresh()

fresh(): Promise<BaseModel>

Defined in: packages/orm/src/model/BaseModel.ts:1834

Re-read this record from the database and return it as a new instance, leaving the current one untouched. Use refresh to mutate in place.

Returns

Promise<BaseModel>

Throws

when the row no longer exists.


refresh()

refresh(): Promise<BaseModel>

Defined in: packages/orm/src/model/BaseModel.ts:1852

Reload this instance's attributes from the database, mutating it in place. Unlike fresh() (which returns a new instance) this updates this.

Returns

Promise<BaseModel>

Throws

when the row no longer exists.


replicate()

replicate(except?): this

Defined in: packages/orm/src/model/BaseModel.ts:1870

Copy this model into a new unsaved instance. The primary key and timestamps are not copied; pass except to omit additional columns.

Parameters

except?

string[]

Returns

this


increment()

increment(column, amount?): Promise<BaseModel>

Defined in: packages/orm/src/model/BaseModel.ts:1924

Atomically increment a column in the DB and on this instance.

Parameters

column

"id" | "fill" | "delete" | "append" | "toJSON" | "__isZerotalModel" | "createdAt" | "updatedAt" | "forceFill" | "save" | "load" | "loadMissing" | "fresh" | "refresh" | "replicate" | "touch" | "is" | "isNot" | "increment" | "decrement" | "loadCount" | "loadSum" | "loadAvg" | "loadMin" | "loadMax" | "makeHidden" | "makeVisible" | "associate" | "dissociate" | "isDirty" | "$dirty" | "markDirty"

amount?

number = 1

Returns

Promise<BaseModel>


decrement()

decrement(column, amount?): Promise<BaseModel>

Defined in: packages/orm/src/model/BaseModel.ts:1933

Atomically decrement a column in the DB and on this instance.

Parameters

column

"id" | "fill" | "delete" | "append" | "toJSON" | "__isZerotalModel" | "createdAt" | "updatedAt" | "forceFill" | "save" | "load" | "loadMissing" | "fresh" | "refresh" | "replicate" | "touch" | "is" | "isNot" | "increment" | "decrement" | "loadCount" | "loadSum" | "loadAvg" | "loadMin" | "loadMax" | "makeHidden" | "makeVisible" | "associate" | "dissociate" | "isDirty" | "$dirty" | "markDirty"

amount?

number = 1

Returns

Promise<BaseModel>

Querying

connection?

static optional connection?: string

Defined in: packages/orm/src/model/BaseModel.ts:776

Optional named connection (registered via registerConnection). When set, queries for this model resolve to that connection instead of the default.


addGlobalScope()

static addGlobalScope<T>(this, name, callback): void

Defined in: packages/orm/src/model/BaseModel.ts:855

Register a named global scope applied to every query for this model. The callback receives the query builder and constrains it (e.g. a tenant filter). Remove it later with removeGlobalScope.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

name

string

callback

GlobalScopeCallback

Returns

void


removeGlobalScope()

static removeGlobalScope<T>(this, name): void

Defined in: packages/orm/src/model/BaseModel.ts:874

Remove a previously registered global scope by name.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

name

string

Returns

void


registerConnection()

static registerConnection(name, conn, dialect?): void

Defined in: packages/orm/src/model/BaseModel.ts:884

Register a named connection that models can select via static connection. Stored on the current OrmContext (execution-scoped).

Parameters

name

string

conn

SQLInstance

dialect?

Dialect

Returns

void


query()

static query<T>(this): ModelQueryBuilder<T>

Defined in: packages/orm/src/model/BaseModel.ts:986

Start a new query builder for this model — the entry point for building where/orderBy/with/etc. chains. Applies the soft-delete scope (deleted_at IS NULL) when the model uses soft deletes.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

Returns

ModelQueryBuilder<T>

Example

const posts = await Post.query().where("published", true).orderBy("createdAt", "desc").get();

where()

Call Signature

static where<T>(this, column, value): ModelQueryBuilder<T>

Defined in: packages/orm/src/model/BaseModel.ts:1014

Start a query constrained by a WHERE clause. Pass (column, value) for equality or (column, operator, value) for any other comparison.

Type Parameters
T

T extends BaseModel

Parameters
this

ModelCtor<T>

column

string

value

unknown

Returns

ModelQueryBuilder<T>

Example
const recent = await Post.where("views", ">=", 100).get();

Call Signature

static where<T>(this, column, operator, value): ModelQueryBuilder<T>

Defined in: packages/orm/src/model/BaseModel.ts:1019

Start a query constrained by a WHERE clause. Pass (column, value) for equality or (column, operator, value) for any other comparison.

Type Parameters
T

T extends BaseModel

Parameters
this

ModelCtor<T>

column

string

operator

WhereOperator

value

unknown

Returns

ModelQueryBuilder<T>

Example
const recent = await Post.where("views", ">=", 100).get();

whereIn()

static whereIn<T>(this, column, values): ModelQueryBuilder<T>

Defined in: packages/orm/src/model/BaseModel.ts:1042

Start a query constrained by WHERE column IN (values).

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

column

string

values

unknown[]

Returns

ModelQueryBuilder<T>


orderBy()

static orderBy<T>(this, column, direction?): ModelQueryBuilder<T>

Defined in: packages/orm/src/model/BaseModel.ts:1055

Start a query ordered by column (default direction "asc").

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

column

string

direction?

OrderDirection = "asc"

Returns

ModelQueryBuilder<T>


latest()

static latest<T>(this, column?): ModelQueryBuilder<T>

Defined in: packages/orm/src/model/BaseModel.ts:1068

Start a query ordered newest-first by column (default "created_at").

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

column?

string = "created_at"

Returns

ModelQueryBuilder<T>


oldest()

static oldest<T>(this, column?): ModelQueryBuilder<T>

Defined in: packages/orm/src/model/BaseModel.ts:1080

Start a query ordered oldest-first by column (default "created_at").

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

column?

string = "created_at"

Returns

ModelQueryBuilder<T>


first()

static first<T>(this): Promise<T | null>

Defined in: packages/orm/src/model/BaseModel.ts:1092

Fetch the first row, or null when none match.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

Returns

Promise<T | null>


firstOrFail()

static firstOrFail<T>(this): Promise<T>

Defined in: packages/orm/src/model/BaseModel.ts:1102

Fetch the first row, or throw when none match.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

Returns

Promise<T>

Throws

when no row matches.


count()

static count<T>(this): Promise<number>

Defined in: packages/orm/src/model/BaseModel.ts:1111

Count all rows (subject to any global/soft-delete scopes).

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

Returns

Promise<number>


find()

static find<T>(this, id): Promise<T | null>

Defined in: packages/orm/src/model/BaseModel.ts:1120

Find a single row by primary key, or null when not found.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

id

string | number

Returns

Promise<T | null>


findOrFail()

static findOrFail<T>(this, id): Promise<T>

Defined in: packages/orm/src/model/BaseModel.ts:1137

Find a single row by primary key, or throw when not found.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

id

string | number

Returns

Promise<T>

Throws

when no row has the given primary key.

Example

const user = await User.findOrFail(ctx.integer("id"));

findBy()

static findBy<T>(this, column, value): Promise<T | null>

Defined in: packages/orm/src/model/BaseModel.ts:1152

Find the first row where column equals value (the column name is converted to snake_case), or null when none match.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

column

string

value

unknown

Returns

Promise<T | null>


all()

static all<T>(this): Promise<T[]>

Defined in: packages/orm/src/model/BaseModel.ts:1165

Fetch every row for this model (subject to global/soft-delete scopes).

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

Returns

Promise<T[]>


paginate()

static paginate<T>(this, perPage?, page?, pageName?): Promise<PaginateResult<T>>

Defined in: packages/orm/src/model/BaseModel.ts:1188

Fetch one page of rows (subject to global/soft-delete scopes).

The page comes from the request in flight — the ?page= query string, or whatever a server-driven view registered instead — so a controller or a Flow page reads Post.paginate(10) and gets the page the user is actually on. Pass page to override.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

perPage?

number = 15

Rows per page. Defaults to 15.

page?

number

1-based page. Omit to use the request's current page.

pageName?

string = "page"

Which paginator to read, so one page can drive several. Defaults to "page".

Returns

Promise<PaginateResult<T>>

Example

const posts = await Post.paginate(10);              // ?page= (or the view's page)
const invoices = await Invoice.paginate(10, undefined, "invoices"); // a second paginator

findMany()

static findMany<T>(this, ids): Promise<T[]>

Defined in: packages/orm/src/model/BaseModel.ts:1480

Fetch many rows by an array of primary keys.

Type Parameters

T

T extends BaseModel

Parameters

this

ModelCtor<T>

ids

(string | number)[]

Returns

Promise<T[]>


scope()

static scope<Args>(fn): (...args) => ScopeApplicator

Defined in: packages/orm/src/model/BaseModel.ts:1572

Define a named query scope with typed arguments. Assign to a static property; apply via .withScopes(s => s.active()).

Type Parameters

Args

Args extends unknown[]

Parameters

fn

(query, ...args) => void

Returns

(...args) => ScopeApplicator

Example

static active  = BaseModel.scope((q) => q.where('active', 1));
static byScore = BaseModel.scope((q, min: number) => q.where('score', '>=', min));

Relationships

load()

load(relations): Promise<BaseModel>

Defined in: packages/orm/src/model/BaseModel.ts:1793

Eager-load the given relations onto this already-fetched model instance. If a relation is already loaded, it is reloaded.

Parameters

relations

string[]

Returns

Promise<BaseModel>

Example

const post = await Post.find(1);
await post.load(['comments', 'tags']);
// post.comments is now populated

loadMissing()

loadMissing(relations): Promise<BaseModel>

Defined in: packages/orm/src/model/BaseModel.ts:1815

Like load(), but skips relations that are already loaded on this instance.

Parameters

relations

string[]

Returns

Promise<BaseModel>

Example

await post.loadMissing(['comments']); // no-op if comments already loaded

loadCount()

loadCount(relations): Promise<BaseModel>

Defined in: packages/orm/src/model/BaseModel.ts:1962

Load relation COUNT(s) onto this instance (sets <rel>Count).

Parameters

relations

string | string[]

Returns

Promise<BaseModel>


loadCount()

static loadCount<T>(this, models, relations): Promise<T[]>

Defined in: packages/orm/src/model/BaseModel.ts:1990

Load relation COUNT(s) for an array of already-fetched models in a SINGLE query (no N+1), setting <rel>Count on each — prefer this over calling the instance loadCount() in a loop.

Type Parameters

T

T extends BaseModel

Parameters

this

typeof BaseModel

models

T[]

relations

string | string[]

Returns

Promise<T[]>

Example

const posts = await Post.all();
await Post.loadCount(posts, "comments");
posts[0]!.commentsCount;

loadSum()

loadSum(relation, column): Promise<BaseModel>

Defined in: packages/orm/src/model/BaseModel.ts:2044

Load SUM(column) over a relation onto this instance (sets <rel>Sum<Column>).

Parameters

relation

string

column

string

Returns

Promise<BaseModel>


loadAvg()

loadAvg(relation, column): Promise<BaseModel>

Defined in: packages/orm/src/model/BaseModel.ts:2052

Load AVG(column) over a relation onto this instance (sets <rel>Avg<Column>).

Parameters

relation

string

column

string

Returns

Promise<BaseModel>


loadMin()

loadMin(relation, column): Promise<BaseModel>

Defined in: packages/orm/src/model/BaseModel.ts:2060

Load MIN(column) over a relation onto this instance (sets <rel>Min<Column>).

Parameters

relation

string

column

string

Returns

Promise<BaseModel>


loadMax()

loadMax(relation, column): Promise<BaseModel>

Defined in: packages/orm/src/model/BaseModel.ts:2068

Load MAX(column) over a relation onto this instance (sets <rel>Max<Column>).

Parameters

relation

string

column

string

Returns

Promise<BaseModel>


associate()

associate(relation, model): this

Defined in: packages/orm/src/model/BaseModel.ts:2116

Set this model's belongsTo foreign key to model and cache the relation. Does not persist — call save() afterwards.

Parameters

relation

string

model

BaseModel

Returns

this

Example

comment.associate('post', post);
await comment.save();

Throws

when relation is not a belongsTo relation on this model.


dissociate()

dissociate(relation): this

Defined in: packages/orm/src/model/BaseModel.ts:2143

Clear this model's belongsTo foreign key and cached relation.

Parameters

relation

string

Returns

this

Throws

when relation is not a belongsTo relation on this model.

Route binding

implicitBinding?

static optional implicitBinding?: boolean

Defined in: packages/orm/src/model/BaseModel.ts:630

Whether this model participates in implicit route-model binding (default: true). When on, a route param matching the model name auto-resolves to a loaded instance (e.g. :user -> User.findOrFail(value)). Set to false to opt out.


implicitBindingKey?

static optional implicitBindingKey?: string

Defined in: packages/orm/src/model/BaseModel.ts:641

Override which route param this model claims for implicit binding. By default a model named User binds the :user param; set this to claim a different key.

Example

static implicitBindingKey = "author"; // any :author param resolves via this model

Serialization

hidden

static hidden: string[] = []

Defined in: packages/orm/src/model/BaseModel.ts:746

Fields to exclude from toJSON() and therefore from any JSON.stringify() output — API responses, cache serialisation, etc.

List camelCase property names. Nested models serialise independently via their own toJSON(), so a parent's hidden list does not propagate to relations.

Example

static hidden = ['password', 'rememberToken'];

visible

static visible: string[] = []

Defined in: packages/orm/src/model/BaseModel.ts:754

Allow-list for serialization. When set (non-empty), toJSON() includes ONLY these keys (plus appends). Takes precedence over hidden.


appends

static appends: string[] = []

Defined in: packages/orm/src/model/BaseModel.ts:768

Computed accessor names to include in toJSON() output. Each name should resolve to a getter (or plain property) on the instance.

Example

class User extends BaseModel {
  static appends = ['fullName'];
  get fullName() { return `${this.first} ${this.last}`; }
}

makeHidden()

makeHidden(...keys): this

Defined in: packages/orm/src/model/BaseModel.ts:2077

Hide additional keys from toJSON() for this instance only.

Parameters

keys

...string[]

Returns

this


makeVisible()

makeVisible(...keys): this

Defined in: packages/orm/src/model/BaseModel.ts:2088

Reveal keys that are hidden by the class hidden list, for this instance only.

Parameters

keys

...string[]

Returns

this


append()

append(...keys): this

Defined in: packages/orm/src/model/BaseModel.ts:2099

Add computed accessor name(s) to this instance's toJSON() output.

Parameters

keys

...string[]

Returns

this


toJSON()

toJSON(): Record<string, unknown>

Defined in: packages/orm/src/model/BaseModel.ts:2220

Called automatically by JSON.stringify — returns a plain object containing only user-facing data:

• All column values and loaded relation instances (enumerable own props) • Excludes internal ORM state: _original, _exists, _forcedDirty, zerotal* • Excludes any remaining getter guards (unloaded relation lazy-load traps)

Nested model instances (e.g. post.author) also have toJSON(), so JSON.stringify recurses correctly through the full object graph.

Returns

Record<string, unknown>

Soft deletes

softDeletes

static softDeletes: boolean = false

Defined in: packages/orm/src/model/BaseModel.ts:594

Whether this model uses soft deletes. Flipped to true by the SoftDeletes mixin; when set, delete sets deleted_at and queries scope WHERE deleted_at IS NULL.

Timestamps

timestamps

static timestamps: boolean = true

Defined in: packages/orm/src/model/BaseModel.ts:585

When true (default), created_at / updated_at are set automatically on insert and updated_at is bumped on every update. Toggle off, or wrap a write in withoutTimestamps, to suppress this.


createdAt?

optional createdAt?: Date

Defined in: packages/orm/src/model/BaseModel.ts:826

Creation timestamp, set on insert when timestamps is enabled.


updatedAt?

optional updatedAt?: Date

Defined in: packages/orm/src/model/BaseModel.ts:833

Last-update timestamp, bumped on every save when timestamps is enabled.


withoutTimestamps()

static withoutTimestamps<R>(callback): Promise<R>

Defined in: packages/orm/src/model/BaseModel.ts:897

Run a callback with automatic timestamp updates disabled for this model. Restores the previous setting afterwards (even on throw).

Type Parameters

R

R

Parameters

callback

() => R | Promise<R>

Returns

Promise<R>

Example

await User.withoutTimestamps(() => user.save());

touch()

touch(): Promise<BaseModel>

Defined in: packages/orm/src/model/BaseModel.ts:1887

Bump updated_at to now and persist. No-op when timestamps are disabled.

Returns

Promise<BaseModel>