/** * Active Record `Model` base class for `@atlex/orm`. * * Responsibility: * - Attribute storage, dirty tracking, mass assignment rules * - Persistence (`save`, `delete`, `restore`) delegating to `QueryBuilder` * - Relationships (hasOne/hasMany/belongsTo/belongsToMany/through variants) * - Eager loading (`with`, `withCount`) with batched queries (no N+1) * - Scopes (global + local scope macros) * - Hooks/observers lifecycle events * * Usage example: * ```ts * class User extends SoftDeletes(Model) { * static table = 'users' * static hidden = ['password'] * static fillable = ['name', 'email', 'password'] * * getFullNameAttribute() { return `${this.first_name} ${this.last_name}` } * * posts() { return this.hasMany(Post, 'user_id') } * profile() { return this.hasOne(Profile, 'user_id') } * roles() { return this.belongsToMany(Role, 'role_user').withPivot('assigned_at') } * * scopeActive(qb: QueryBuilder) { return qb.where('active', '=', true) } * } * * const user = await User.findOrFail(1) * const posts = await user.posts().where('published', '=', true).latest().get() * const users = await User.with('posts', 'profile').active().get() * ``` */ import type { CursorPaginator } from './pagination/CursorPaginator.js'; import type { LengthAwarePaginator } from './pagination/LengthAwarePaginator.js'; import type { CursorPaginationOptions, PaginationOptions } from './pagination/PaginationMeta.js'; import type { Paginator } from './pagination/Paginator.js'; import { type QueryBuilder } from './QueryBuilder.js'; import { ManyToManyRelationBuilder } from './relations/ManyToManyRelationBuilder.js'; import { RelationBuilder } from './relations/RelationBuilder.js'; import type { Scope } from './scopes/Scope.js'; import type { ModelConstructor } from './types.js'; type Attributes = Record; type ModelClass = ModelConstructor & typeof Model; export declare abstract class Model { #private; static table: string; static primaryKey: string; static timestamps: boolean; static incrementing: boolean; static hidden: string[]; static fillable: string[]; static guarded: string[]; static appends: string[]; [key: string]: unknown; /** * Create a new model instance. * * The constructor wraps the instance in a Proxy so `model.email` maps to attributes. */ constructor(); /** * Create a fresh query builder scoped to this model (applies global scopes, hydration, local scopes). */ static query(this: ModelClass): QueryBuilder; /** * Escape hatch: build complex queries starting from the model table. */ static where(this: ModelClass, column: string, operator: string, value: unknown): QueryBuilder; static where(this: ModelClass, column: string, value: unknown): QueryBuilder; static where(this: ModelClass, callback: (qb: QueryBuilder) => void): QueryBuilder; static whereIn(this: ModelClass, column: string, values: unknown[]): QueryBuilder; static orderBy(this: ModelClass, column: string, direction?: 'asc' | 'desc'): QueryBuilder; static limit(this: ModelClass, n: number): QueryBuilder; /** * Fetch all records. */ static all(this: ModelClass): Promise; /** * Length-aware pagination for this model's table. */ static paginate(this: ModelClass, perPage?: number, options?: PaginationOptions): Promise>; /** * Simple pagination (no total count) for this model's table. */ static simplePaginate(this: ModelClass, perPage?: number, options?: PaginationOptions): Promise>; /** * Cursor pagination; uses {@link Model.primaryKey} when no `orderBy` is set on the query. */ static cursorPaginate(this: ModelClass, perPage?: number, options?: CursorPaginationOptions): Promise>; /** * Find by primary key. */ static find(this: ModelClass, id: number | string): Promise; /** * Find by primary key or throw. */ static findOrFail(this: ModelClass, id: number | string): Promise; /** * Find many by primary key; preserves input order. */ static findMany(this: ModelClass, ids: (number | string)[]): Promise; /** * Return the first row ordered by primary key asc. */ static first(this: ModelClass): Promise; /** * Return the first row or throw. */ static firstOrFail(this: ModelClass): Promise; /** * Create and persist a model with mass assignment rules and hooks. */ static create(this: ModelClass, data: Partial): Promise; /** * First or create atomically (returns [model, wasCreated]). */ static firstOrCreate(this: ModelClass, search: Partial, data?: Partial): Promise<[T, boolean]>; /** * First or new (does not persist). */ static firstOrNew(this: ModelClass, search: Partial, data?: Partial): Promise; /** * Update or create atomically. */ static updateOrCreate(this: ModelClass, search: Partial, data: Partial): Promise; /** * Bulk insert (no hydration, no hooks, no mass-assignment). */ static insert(rows: Record[]): Promise; /** * Truncate table (blocked in production unless ALLOW_UNSAFE_OPERATIONS=true). */ static truncate(): Promise; static count(column?: string): Promise; static max(column: string): Promise; static min(column: string): Promise; static avg(column: string): Promise; static sum(column: string): Promise; static exists(this: ModelClass, id: number | string): Promise; static with(this: ModelClass, ...relations: string[]): QueryBuilder; static withCount(this: ModelClass, ...relations: string[]): QueryBuilder; static addGlobalScope(name: string, scope: Scope): void; static withoutGlobalScope(this: ModelClass, name: string): QueryBuilder; static withoutGlobalScopes(this: ModelClass): QueryBuilder; /** * Boot hook for registering global scopes. Called once per model class. */ static booted(): void; /** * Register an observer instance. */ static observe(observer: object): void; /** * Persist this model (insert or update). */ save(): Promise; /** * @internal Save using an existing transaction-scoped builder. */ _saveWithBuilder(builder: QueryBuilder): Promise; /** * Delete this model. */ delete(): Promise; /** * Force delete (soft delete mixin overrides this). */ forceDelete(): Promise; /** * Restore (soft delete mixin overrides this). */ restore(): Promise; exists(): boolean; /** * Mass-assign attributes respecting fillable/guarded rules. */ fill(data: Partial): this; /** * Force fill bypasses mass-assignment. Never use with raw user input. */ forceFill(data: Partial): this; /** * Get an attribute value, applying accessors when available. */ getAttribute(key: string): unknown; /** * Set an attribute value, applying mutators when available. */ setAttribute(key: string, value: unknown): void; getAttributes(): Attributes; getDirty(): Attributes; isDirty(key?: string): boolean; isClean(key?: string): boolean; wasChanged(key?: string): boolean; /** * Re-fetch this record as a new instance. */ fresh(): Promise; /** * Refresh this instance in-place. */ refresh(): Promise; toObject(): Attributes; toJSON(): Record; toString(): string; is(other: Model): boolean; isNot(other: Model): boolean; clone(): this; protected hasOne(RelatedModel: ModelConstructor, foreignKey?: string, localKey?: string): RelationBuilder; protected hasMany(RelatedModel: ModelConstructor, foreignKey?: string, localKey?: string): RelationBuilder; protected belongsTo(RelatedModel: ModelConstructor, foreignKey?: string, ownerKey?: string): RelationBuilder; protected belongsToMany(RelatedModel: ModelConstructor, pivotTable?: string, foreignKey?: string, relatedKey?: string): ManyToManyRelationBuilder; protected hasManyThrough(FinalModel: ModelConstructor, ThroughModel: ModelConstructor, firstKey: string, secondKey: string): RelationBuilder; protected hasOneThrough(FinalModel: ModelConstructor, ThroughModel: ModelConstructor, firstKey: string, secondKey: string): RelationBuilder; setRelation(name: string, value: unknown): void; getRelation(name: string): T; private syncOriginal; /** @internal */ static applyGlobalScopes(this: typeof Model, qb: QueryBuilder, disabled?: Set): QueryBuilder; /** @internal */ static queryWithoutScopes(this: typeof Model, disabled: Set): QueryBuilder; /** @internal */ static hydrateQuery(this: typeof Model, qb: QueryBuilder): QueryBuilder; /** @internal */ static hydrate(this: typeof Model, attrs: Attributes): T; /** @internal */ static applyLocalScopeProxy(this: typeof Model, qb: QueryBuilder): QueryBuilder; private static callHook; /** @internal for SoftDeletes */ static callRestoringHook(model: Model): Promise; /** @internal for SoftDeletes */ static callRestoredHook(model: Model): Promise; private static eagerLoad; private static eagerLoadRelation; private static eagerLoadCount; } export {}; //# sourceMappingURL=Model.d.ts.map