outlet-orm 5.0.0 → 5.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/types/index.d.ts CHANGED
@@ -1,660 +1,674 @@
1
- // Type definitions for outlet-orm
2
-
3
- declare module 'outlet-orm' {
4
-
5
- // ==================== Type Utilities ====================
6
-
7
- /** Event names for Model lifecycle hooks */
8
- export type ModelEventName =
9
- | 'creating' | 'created'
10
- | 'updating' | 'updated'
11
- | 'saving' | 'saved'
12
- | 'deleting' | 'deleted'
13
- | 'restoring' | 'restored';
14
-
15
- /** SQL WHERE operators */
16
- export type WhereOperator =
17
- | '=' | '!=' | '<>'
18
- | '>' | '>=' | '<' | '<='
19
- | 'LIKE' | 'NOT LIKE' | 'like' | 'not like'
20
- | 'IN' | 'NOT IN' | 'in' | 'not in'
21
- | 'BETWEEN' | 'NOT BETWEEN'
22
- | 'IS NULL' | 'IS NOT NULL';
23
-
24
- /** Base attributes every model has */
25
- export interface BaseModelAttributes {
26
- id?: number | string;
27
- created_at?: Date | string;
28
- updated_at?: Date | string;
29
- deleted_at?: Date | string | null;
30
- }
31
-
32
- /** Insert operation result */
33
- export interface InsertResult {
34
- insertId: number | string;
35
- affectedRows: number;
36
- }
37
-
38
- /** Update operation result */
39
- export interface UpdateResult {
40
- affectedRows: number;
41
- changedRows?: number;
42
- }
43
-
44
- /** Delete operation result */
45
- export interface DeleteResult {
46
- affectedRows: number;
47
- }
48
-
49
- // ==================== Database Connection ====================
50
-
51
- export interface DatabaseConfig {
52
- driver: 'mysql' | 'postgres' | 'postgresql' | 'sqlite';
53
- host?: string;
54
- port?: number;
55
- database?: string;
56
- user?: string;
57
- password?: string;
58
- connectionLimit?: number;
59
- }
60
-
61
- export interface QueryLogEntry {
62
- sql: string;
63
- params: any[];
64
- duration: number;
65
- timestamp: Date;
66
- }
67
-
68
- export class DatabaseConnection {
69
- constructor(config?: Partial<DatabaseConfig>);
70
- connect(): Promise<void>;
71
-
72
- // Transaction support
73
- beginTransaction(): Promise<void>;
74
- commit(): Promise<void>;
75
- rollback(): Promise<void>;
76
- transaction<T>(callback: (connection: DatabaseConnection) => Promise<T>): Promise<T>;
77
-
78
- // Query logging
79
- static enableQueryLog(): void;
80
- static disableQueryLog(): void;
81
- static getQueryLog(): QueryLogEntry[];
82
- static flushQueryLog(): void;
83
- static isLogging(): boolean;
84
-
85
- select(table: string, query: QueryObject): Promise<any[]>;
86
- insert(table: string, data: Record<string, any>): Promise<InsertResult>;
87
- insertMany(table: string, data: Record<string, any>[]): Promise<{ affectedRows: number }>;
88
- update(table: string, data: Record<string, any>, query: QueryObject): Promise<UpdateResult>;
89
- delete(table: string, query: QueryObject): Promise<DeleteResult>;
90
- count(table: string, query: QueryObject): Promise<number>;
91
- executeRawQuery(sql: string, params?: any[]): Promise<any[]>;
92
- /** Execute raw SQL and return driver-native results (used by migrations) */
93
- execute(sql: string, params?: any[]): Promise<any>;
94
- /** Atomically increment a column respecting query wheres */
95
- increment(table: string, column: string, query: QueryObject, amount?: number): Promise<UpdateResult>;
96
- /** Atomically decrement a column respecting query wheres */
97
- decrement(table: string, column: string, query: QueryObject, amount?: number): Promise<UpdateResult>;
98
- close(): Promise<void>;
99
- /** Backwards-compatible alias used by CLI */
100
- disconnect(): Promise<void>;
101
- }
102
-
103
- // ==================== Query Builder ====================
104
-
105
- export interface QueryObject {
106
- columns?: string[];
107
- wheres?: WhereClause[];
108
- orders?: OrderClause[];
109
- joins?: JoinClause[];
110
- distinct?: boolean;
111
- groupBys?: string[];
112
- havings?: HavingClause[];
113
- limit?: number | null;
114
- offset?: number | null;
115
- }
116
-
117
- export interface WhereClause {
118
- column?: string;
119
- operator?: WhereOperator | string;
120
- value?: any;
121
- values?: any[];
122
- type: 'basic' | 'in' | 'notIn' | 'null' | 'notNull' | 'between' | 'like';
123
- boolean: 'and' | 'or';
124
- }
125
-
126
- export interface OrderClause {
127
- column: string;
128
- direction: 'asc' | 'desc';
129
- }
130
-
131
- export interface HavingClause {
132
- type: 'basic' | 'count';
133
- column: string;
134
- operator: string;
135
- value: any;
136
- }
137
-
138
- export interface JoinClause {
139
- table: string;
140
- first: string;
141
- operator: string;
142
- second: string;
143
- type: 'inner' | 'left';
144
- }
145
-
146
- export interface PaginationResult<T> {
147
- data: T[];
148
- total: number;
149
- per_page: number;
150
- current_page: number;
151
- last_page: number;
152
- from: number | null;
153
- to: number;
154
- }
155
-
156
- export class QueryBuilder<T extends Model> {
157
- constructor(model: typeof Model);
158
-
159
- select(...columns: string[]): this;
160
- /** Convenience alias to pass an array of columns */
161
- columns(cols: string[]): this;
162
- distinct(): this;
163
- where(column: string, value: any): this;
164
- where(column: string, operator: string, value: any): this;
165
- whereIn(column: string, values: any[]): this;
166
- whereNotIn(column: string, values: any[]): this;
167
- whereNull(column: string): this;
168
- whereNotNull(column: string): this;
169
- orWhere(column: string, value: any): this;
170
- orWhere(column: string, operator: string, value: any): this;
171
- whereBetween(column: string, values: [any, any]): this;
172
- whereLike(column: string, value: string): this;
173
- /** Filter parents where a relation has matches */
174
- whereHas(relationName: string, callback?: (qb: QueryBuilder<any>) => void): this;
175
- /** Filter parents where relation count matches */
176
- has(relationName: string, count: number): this;
177
- has(relationName: string, operator: string, count: number): this;
178
- /** Filter parents without related rows */
179
- whereDoesntHave(relationName: string): this;
180
- orderBy(column: string, direction?: 'asc' | 'desc'): this;
181
- /** Typo-friendly alias for orderBy */
182
- ordrer(column: string, direction?: 'asc' | 'desc'): this;
183
- limit(value: number): this;
184
- offset(value: number): this;
185
- skip(value: number): this;
186
- take(value: number): this;
187
- with(...relations: string[] | [Record<string, (qb: QueryBuilder<any>) => void> | string[]]): this;
188
- withCount(relations: string | string[]): this;
189
- groupBy(...columns: string[]): this;
190
- having(column: string, operator: string, value: any): this;
191
- join(table: string, first: string, second: string): this;
192
- join(table: string, first: string, operator: string, second: string): this;
193
- leftJoin(table: string, first: string, second: string): this;
194
- leftJoin(table: string, first: string, operator: string, second: string): this;
195
-
196
- // Soft delete methods
197
- withTrashed(): this;
198
- onlyTrashed(): this;
199
-
200
- // Scope methods
201
- withoutGlobalScope(name: string): this;
202
- withoutGlobalScopes(): this;
203
-
204
- get(): Promise<T[]>;
205
- first(): Promise<T | null>;
206
- firstOrFail(): Promise<T>;
207
- paginate(page?: number, perPage?: number): Promise<PaginationResult<T>>;
208
- count(): Promise<number>;
209
- exists(): Promise<boolean>;
210
- insert(data: Record<string, any> | Record<string, any>[]): Promise<any>;
211
- update(attributes: Record<string, any>): Promise<any>;
212
- /** Update and return first matching row as model, optionally eager-loading relations */
213
- updateAndFetch(attributes: Record<string, any>, relations?: string[]): Promise<T | null>;
214
- delete(): Promise<any>;
215
- increment(column: string, amount?: number): Promise<any>;
216
- decrement(column: string, amount?: number): Promise<any>;
217
-
218
- clone(): QueryBuilder<T>;
219
- }
220
-
221
- // ==================== Model ====================
222
-
223
- export type CastType = 'int' | 'integer' | 'float' | 'double' | 'string' | 'bool' | 'boolean' | 'array' | 'json' | 'date' | 'datetime' | 'timestamp';
224
-
225
- /** Individual validation rule types */
226
- export type ValidationRule =
227
- | 'required'
228
- | 'string'
229
- | 'number'
230
- | 'numeric'
231
- | 'integer'
232
- | 'email'
233
- | 'url'
234
- | 'boolean'
235
- | 'date'
236
- | 'array'
237
- | 'object'
238
- | 'nullable'
239
- | `min:${number}`
240
- | `max:${number}`
241
- | `between:${number},${number}`
242
- | `in:${string}`
243
- | `not_in:${string}`
244
- | `regex:${string}`
245
- | `size:${number}`
246
- | `digits:${number}`
247
- | `digits_between:${number},${number}`;
248
-
249
- /** Validation rule as pipe-separated string */
250
- export type ValidationRuleString = string;
251
-
252
- export interface ValidationResult {
253
- valid: boolean;
254
- errors: Record<string, string[]>;
255
- }
256
-
257
- export type EventCallback<T extends Model = Model> = (model: T) => boolean | void | Promise<boolean | void>;
258
-
259
- /**
260
- * Base Model class with optional generic for typed attributes
261
- * @template TAttributes - Type of model attributes (defaults to Record<string, any>)
262
- */
263
- export class Model<TAttributes extends Record<string, any> = Record<string, any>> {
264
- static table: string;
265
- static primaryKey: string;
266
- static timestamps: boolean;
267
- static fillable: string[];
268
- static hidden: string[];
269
- static casts: Record<string, CastType>;
270
- static connection: DatabaseConnection | null;
271
-
272
- // Soft Deletes
273
- static softDeletes: boolean;
274
- static DELETED_AT: string;
275
-
276
- // Scopes
277
- static globalScopes: Record<string, (qb: QueryBuilder<any>) => void>;
278
-
279
- // Events
280
- static eventListeners: Record<ModelEventName, EventCallback[]>;
281
-
282
- // Validation
283
- static rules: Record<string, ValidationRuleString | ValidationRule[]>;
284
-
285
- /** Model attributes with optional typing */
286
- attributes: TAttributes;
287
- /** Original attributes before modifications */
288
- original: TAttributes;
289
- /** Loaded relations */
290
- relations: Record<string, any>;
291
- /** Whether the model exists in database */
292
- exists: boolean;
293
-
294
- constructor(attributes?: Partial<TAttributes>);
295
-
296
- // Event registration with typed event names
297
- static on(event: ModelEventName, callback: EventCallback): void;
298
- static fireEvent(event: ModelEventName, model: Model): Promise<boolean>;
299
- static creating(callback: EventCallback): void;
300
- static created(callback: EventCallback): void;
301
- static updating(callback: EventCallback): void;
302
- static updated(callback: EventCallback): void;
303
- static saving(callback: EventCallback): void;
304
- static saved(callback: EventCallback): void;
305
- static deleting(callback: EventCallback): void;
306
- static deleted(callback: EventCallback): void;
307
- static restoring(callback: EventCallback): void;
308
- static restored(callback: EventCallback): void;
309
-
310
- // Scope methods
311
- static addGlobalScope(name: string, callback: (qb: QueryBuilder<any>) => void): void;
312
- static removeGlobalScope(name: string): void;
313
- static withoutGlobalScope<T extends Model>(this: new () => T, name: string): QueryBuilder<T>;
314
- static withoutGlobalScopes<T extends Model>(this: new () => T): QueryBuilder<T>;
315
-
316
- // Soft delete methods
317
- static withTrashed<T extends Model>(this: new () => T): QueryBuilder<T>;
318
- static onlyTrashed<T extends Model>(this: new () => T): QueryBuilder<T>;
319
-
320
- // Static methods
321
- static setConnection(connection: DatabaseConnection): void;
322
- /** Get the active database connection (v3.0.0+) */
323
- static getConnection(): DatabaseConnection;
324
- static query<T extends Model>(this: new () => T): QueryBuilder<T>;
325
- static all<T extends Model>(this: new () => T): Promise<T[]>;
326
- static find<T extends Model>(this: new () => T, id: any): Promise<T | null>;
327
- static findOrFail<T extends Model>(this: new () => T, id: any): Promise<T>;
328
- static where<T extends Model>(this: new () => T, column: string, value: any): QueryBuilder<T>;
329
- static where<T extends Model>(this: new () => T, column: string, operator: string, value: any): QueryBuilder<T>;
330
- static create<T extends Model>(this: new () => T, attributes: Record<string, any>): Promise<T>;
331
- static insert(data: Record<string, any> | Record<string, any>[]): Promise<any>;
332
- static update(attributes: Record<string, any>): Promise<any>;
333
- /** Update by primary key and return the updated model, optionally eager-loading relations */
334
- static updateAndFetchById<T extends Model>(this: new () => T, id: any, attributes: Record<string, any>, relations?: string[]): Promise<T | null>;
335
- /** Update by primary key */
336
- static updateById<T extends Model>(this: new () => T, id: any, attributes: Record<string, any>): Promise<any>;
337
- static delete(): Promise<any>;
338
- static first<T extends Model>(this: new () => T): Promise<T | null>;
339
- static orderBy<T extends Model>(this: new () => T, column: string, direction?: 'asc' | 'desc'): QueryBuilder<T>;
340
- static limit<T extends Model>(this: new () => T, value: number): QueryBuilder<T>;
341
- static offset<T extends Model>(this: new () => T, value: number): QueryBuilder<T>;
342
- static paginate<T extends Model>(this: new () => T, page?: number, perPage?: number): Promise<PaginationResult<T>>;
343
- static whereIn<T extends Model>(this: new () => T, column: string, values: any[]): QueryBuilder<T>;
344
- static whereNull<T extends Model>(this: new () => T, column: string): QueryBuilder<T>;
345
- static whereNotNull<T extends Model>(this: new () => T, column: string): QueryBuilder<T>;
346
- static count(): Promise<number>;
347
- static with<T extends Model>(this: new () => T, ...relations: string[] | [Record<string, (qb: QueryBuilder<any>) => void> | string[]]): QueryBuilder<T>;
348
- /** Include hidden attributes in query results */
349
- static withHidden<T extends Model>(this: new () => T): QueryBuilder<T>;
350
- /** Control visibility of hidden attributes (false = hide, true = show) */
351
- static withoutHidden<T extends Model>(this: new () => T, show?: boolean): QueryBuilder<T>;
352
-
353
- // Instance methods with typed attributes
354
- /** Fill model with attributes */
355
- fill(attributes: Partial<TAttributes>): this;
356
- /** Set a single attribute with type safety */
357
- setAttribute<K extends keyof TAttributes>(key: K, value: TAttributes[K]): this;
358
- setAttribute(key: string, value: any): this;
359
- /** Get a single attribute with type safety */
360
- getAttribute<K extends keyof TAttributes>(key: K): TAttributes[K];
361
- getAttribute(key: string): any;
362
- castAttribute(key: string, value: any): any;
363
- save(): Promise<this>;
364
- destroy(): Promise<boolean>;
365
- getDirty(): Partial<TAttributes>;
366
- isDirty(): boolean;
367
- toJSON(): TAttributes;
368
- /** Load relations on an existing instance. Supports dot-notation and arrays. */
369
- load(...relations: string[] | [string[]]): Promise<this>;
370
-
371
- // Soft delete instance methods
372
- trashed(): boolean;
373
- restore(): Promise<this>;
374
- forceDelete(): Promise<boolean>;
375
-
376
- // Validation
377
- validate(): ValidationResult;
378
- validateOrFail(): void;
379
-
380
- // Relationships
381
- hasOne<T extends Model>(related: new () => T, foreignKey?: string, localKey?: string): HasOneRelation<T>;
382
- hasMany<T extends Model>(related: new () => T, foreignKey?: string, localKey?: string): HasManyRelation<T>;
383
- belongsTo<T extends Model>(related: new () => T, foreignKey?: string, ownerKey?: string): BelongsToRelation<T>;
384
- belongsToMany<T extends Model>(
385
- related: new () => T,
386
- pivot: string,
387
- foreignPivotKey?: string,
388
- relatedPivotKey?: string,
389
- parentKey?: string,
390
- relatedKey?: string
391
- ): BelongsToManyRelation<T>;
392
- hasManyThrough<T extends Model>(
393
- relatedFinal: new () => T,
394
- through: new () => Model,
395
- foreignKeyOnThrough?: string,
396
- throughKeyOnFinal?: string,
397
- localKey?: string,
398
- throughLocalKey?: string
399
- ): HasManyThroughRelation<T>;
400
- /** Has one through intermediate model */
401
- hasOneThrough<T extends Model>(
402
- relatedFinal: new () => T,
403
- through: new () => Model,
404
- foreignKeyOnThrough?: string,
405
- throughKeyOnFinal?: string,
406
- localKey?: string,
407
- throughLocalKey?: string
408
- ): HasOneThroughRelation<T>;
409
- /** Polymorphic one-to-one relation */
410
- morphOne<T extends Model>(related: new () => T, name: string, typeColumn?: string, idColumn?: string, localKey?: string): MorphOneRelation<T>;
411
- /** Polymorphic one-to-many relation */
412
- morphMany<T extends Model>(related: new () => T, name: string, typeColumn?: string, idColumn?: string, localKey?: string): MorphManyRelation<T>;
413
- /** Inverse polymorphic relation */
414
- morphTo<T extends Model>(): MorphToRelation<T>;
415
- }
416
-
417
- // ==================== Relations ====================
418
-
419
- export abstract class Relation<T extends Model> {
420
- constructor(parent: Model, related: new () => T, foreignKey: string, localKey: string);
421
- abstract get(): Promise<T | T[] | null>;
422
- abstract eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
423
- }
424
-
425
- export class HasOneRelation<T extends Model> extends Relation<T> {
426
- get(): Promise<T | null>;
427
- eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
428
- where(column: string, value: any): QueryBuilder<T>;
429
- where(column: string, operator: string, value: any): QueryBuilder<T>;
430
- }
431
-
432
- export class HasManyRelation<T extends Model> extends Relation<T> {
433
- get(): Promise<T[]>;
434
- eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
435
- where(column: string, value: any): QueryBuilder<T>;
436
- where(column: string, operator: string, value: any): QueryBuilder<T>;
437
- count(): Promise<number>;
438
- }
439
-
440
- export class BelongsToRelation<T extends Model> extends Relation<T> {
441
- get(): Promise<T | null>;
442
- eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
443
- where(column: string, value: any): QueryBuilder<T>;
444
- where(column: string, operator: string, value: any): QueryBuilder<T>;
445
- }
446
-
447
- export class BelongsToManyRelation<T extends Model> extends Relation<T> {
448
- get(): Promise<T[]>;
449
- eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
450
- attach(ids: number | number[]): Promise<void>;
451
- detach(ids?: number | number[] | null): Promise<void>;
452
- sync(ids: number[]): Promise<void>;
453
- }
454
-
455
- export class HasManyThroughRelation<T extends Model> extends Relation<T> {
456
- get(): Promise<T[]>;
457
- eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
458
- }
459
-
460
- export class HasOneThroughRelation<T extends Model> extends Relation<T> {
461
- get(): Promise<T | null>;
462
- eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
463
- }
464
-
465
- export class MorphOneRelation<T extends Model> extends Relation<T> {
466
- get(): Promise<T | null>;
467
- eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
468
- }
469
-
470
- export class MorphManyRelation<T extends Model> extends Relation<T> {
471
- get(): Promise<T[]>;
472
- eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
473
- }
474
-
475
- export class MorphToRelation<T extends Model> extends Relation<T> {
476
- get(): Promise<T | null>;
477
- eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
478
- }
479
-
480
- // ==================== Schema Builder (Migrations) ====================
481
-
482
- /** Foreign key action types */
483
- export type ForeignKeyAction = 'CASCADE' | 'SET NULL' | 'RESTRICT' | 'NO ACTION' | 'SET DEFAULT';
484
-
485
- /** Schema builder for database migrations */
486
- export interface SchemaBuilder {
487
- /** Create a new table */
488
- createTable(name: string, callback: (table: TableBuilder) => void): Promise<void>;
489
- /** Drop a table */
490
- dropTable(name: string): Promise<void>;
491
- /** Drop a table if it exists */
492
- dropTableIfExists(name: string): Promise<void>;
493
- /** Rename a table */
494
- renameTable(from: string, to: string): Promise<void>;
495
- /** Check if table exists */
496
- hasTable(name: string): Promise<boolean>;
497
- /** Modify an existing table */
498
- table(name: string, callback: (table: TableBuilder) => void): Promise<void>;
499
- /** Check if column exists */
500
- hasColumn(table: string, column: string): Promise<boolean>;
501
- }
502
-
503
- /** Table builder for creating/modifying tables */
504
- export interface TableBuilder {
505
- // Primary keys
506
- /** Auto-incrementing primary key */
507
- id(name?: string): ColumnBuilder;
508
- /** Big integer auto-incrementing primary key */
509
- bigIncrements(name?: string): ColumnBuilder;
510
- /** UUID primary key */
511
- uuid(name?: string): ColumnBuilder;
512
-
513
- // Numeric types
514
- /** Integer column */
515
- integer(name: string): ColumnBuilder;
516
- /** Big integer column */
517
- bigInteger(name: string): ColumnBuilder;
518
- /** Small integer column */
519
- smallInteger(name: string): ColumnBuilder;
520
- /** Tiny integer column */
521
- tinyInteger(name: string): ColumnBuilder;
522
- /** Decimal column */
523
- decimal(name: string, precision?: number, scale?: number): ColumnBuilder;
524
- /** Float column */
525
- float(name: string, precision?: number, scale?: number): ColumnBuilder;
526
- /** Double column */
527
- double(name: string, precision?: number, scale?: number): ColumnBuilder;
528
-
529
- // String types
530
- /** String/VARCHAR column */
531
- string(name: string, length?: number): ColumnBuilder;
532
- /** Text column */
533
- text(name: string): ColumnBuilder;
534
- /** Medium text column */
535
- mediumText(name: string): ColumnBuilder;
536
- /** Long text column */
537
- longText(name: string): ColumnBuilder;
538
- /** Char column */
539
- char(name: string, length?: number): ColumnBuilder;
540
-
541
- // Boolean
542
- /** Boolean column */
543
- boolean(name: string): ColumnBuilder;
544
-
545
- // Date/Time
546
- /** Date column */
547
- date(name: string): ColumnBuilder;
548
- /** DateTime column */
549
- dateTime(name: string): ColumnBuilder;
550
- /** Timestamp column */
551
- timestamp(name: string): ColumnBuilder;
552
- /** Time column */
553
- time(name: string): ColumnBuilder;
554
- /** Year column */
555
- year(name: string): ColumnBuilder;
556
- /** Add created_at and updated_at columns */
557
- timestamps(): void;
558
- /** Add nullable deleted_at column for soft deletes */
559
- softDeletes(): void;
560
-
561
- // Binary
562
- /** Binary/Blob column */
563
- binary(name: string): ColumnBuilder;
564
- /** Blob column */
565
- blob(name: string): ColumnBuilder;
566
-
567
- // JSON
568
- /** JSON column */
569
- json(name: string): ColumnBuilder;
570
- /** JSONB column (PostgreSQL) */
571
- jsonb(name: string): ColumnBuilder;
572
-
573
- // Enum
574
- /** Enum column */
575
- enum(name: string, values: string[]): ColumnBuilder;
576
-
577
- // Indexes
578
- /** Add primary key constraint */
579
- primary(columns: string | string[]): void;
580
- /** Add unique constraint */
581
- unique(columns: string | string[]): void;
582
- /** Add index */
583
- index(columns: string | string[], name?: string): void;
584
- /** Add foreign key */
585
- foreign(column: string): ForeignKeyBuilder;
586
-
587
- // Modifications
588
- /** Drop a column */
589
- dropColumn(name: string | string[]): void;
590
- /** Rename a column */
591
- renameColumn(from: string, to: string): void;
592
- /** Drop an index */
593
- dropIndex(name: string): void;
594
- /** Drop a unique constraint */
595
- dropUnique(name: string): void;
596
- /** Drop a foreign key */
597
- dropForeign(name: string): void;
598
- }
599
-
600
- /** Column builder for column definitions */
601
- export interface ColumnBuilder {
602
- /** Make column nullable */
603
- nullable(): this;
604
- /** Set default value */
605
- default(value: any): this;
606
- /** Make column unsigned (numeric only) */
607
- unsigned(): this;
608
- /** Add unique constraint */
609
- unique(): this;
610
- /** Make column primary key */
611
- primary(): this;
612
- /** Add index */
613
- index(): this;
614
- /** Add auto increment */
615
- autoIncrement(): this;
616
- /** Add comment */
617
- comment(text: string): this;
618
- /** Add after clause (MySQL) */
619
- after(column: string): this;
620
- /** Add first clause (MySQL) */
621
- first(): this;
622
- /** Set character set */
623
- charset(charset: string): this;
624
- /** Set collation */
625
- collation(collation: string): this;
626
- /** Add references for foreign key */
627
- references(column: string): ForeignKeyBuilder;
628
- }
629
-
630
- /** Foreign key builder */
631
- export interface ForeignKeyBuilder {
632
- /** Referenced table */
633
- on(table: string): this;
634
- /** Referenced column */
635
- references(column: string): this;
636
- /** On delete action */
637
- onDelete(action: ForeignKeyAction): this;
638
- /** On update action */
639
- onUpdate(action: ForeignKeyAction): this;
640
- }
641
-
642
- /** Migration interface for typed migrations */
643
- export interface MigrationInterface {
644
- /** Run the migration */
645
- up(schema: SchemaBuilder): Promise<void>;
646
- /** Reverse the migration */
647
- down(schema: SchemaBuilder): Promise<void>;
648
- }
649
-
650
- /** Schema class export */
651
- export class Schema {
652
- static create(name: string, callback: (table: TableBuilder) => void): Promise<void>;
653
- static drop(name: string): Promise<void>;
654
- static dropIfExists(name: string): Promise<void>;
655
- static table(name: string, callback: (table: TableBuilder) => void): Promise<void>;
656
- static rename(from: string, to: string): Promise<void>;
657
- static hasTable(name: string): Promise<boolean>;
658
- static hasColumn(table: string, column: string): Promise<boolean>;
659
- }
660
- }
1
+ // Type definitions for outlet-orm
2
+
3
+ declare module 'outlet-orm' {
4
+
5
+ // ==================== Type Utilities ====================
6
+
7
+ /** Event names for Model lifecycle hooks */
8
+ export type ModelEventName =
9
+ | 'creating' | 'created'
10
+ | 'updating' | 'updated'
11
+ | 'saving' | 'saved'
12
+ | 'deleting' | 'deleted'
13
+ | 'restoring' | 'restored';
14
+
15
+ /** SQL WHERE operators */
16
+ export type WhereOperator =
17
+ | '=' | '!=' | '<>'
18
+ | '>' | '>=' | '<' | '<='
19
+ | 'LIKE' | 'NOT LIKE' | 'like' | 'not like'
20
+ | 'IN' | 'NOT IN' | 'in' | 'not in'
21
+ | 'BETWEEN' | 'NOT BETWEEN'
22
+ | 'IS NULL' | 'IS NOT NULL';
23
+
24
+ /** Base attributes every model has */
25
+ export interface BaseModelAttributes {
26
+ id?: number | string;
27
+ created_at?: Date | string;
28
+ updated_at?: Date | string;
29
+ deleted_at?: Date | string | null;
30
+ }
31
+
32
+ /** Insert operation result */
33
+ export interface InsertResult {
34
+ insertId: number | string;
35
+ affectedRows: number;
36
+ }
37
+
38
+ /** Update operation result */
39
+ export interface UpdateResult {
40
+ affectedRows: number;
41
+ changedRows?: number;
42
+ }
43
+
44
+ /** Delete operation result */
45
+ export interface DeleteResult {
46
+ affectedRows: number;
47
+ }
48
+
49
+ // ==================== Database Connection ====================
50
+
51
+ export interface DatabaseConfig {
52
+ driver: 'mysql' | 'postgres' | 'postgresql' | 'sqlite';
53
+ host?: string;
54
+ port?: number;
55
+ database?: string;
56
+ user?: string;
57
+ password?: string;
58
+ connectionLimit?: number;
59
+ }
60
+
61
+ export interface QueryLogEntry {
62
+ sql: string;
63
+ params: any[];
64
+ duration: number;
65
+ timestamp: Date;
66
+ }
67
+
68
+ export class DatabaseConnection {
69
+ constructor(config?: Partial<DatabaseConfig>);
70
+ connect(): Promise<void>;
71
+
72
+ // Transaction support
73
+ beginTransaction(): Promise<void>;
74
+ commit(): Promise<void>;
75
+ rollback(): Promise<void>;
76
+ transaction<T>(callback: (connection: DatabaseConnection) => Promise<T>): Promise<T>;
77
+
78
+ // Query logging
79
+ static enableQueryLog(): void;
80
+ static disableQueryLog(): void;
81
+ static getQueryLog(): QueryLogEntry[];
82
+ static flushQueryLog(): void;
83
+ static isLogging(): boolean;
84
+
85
+ select(table: string, query: QueryObject): Promise<any[]>;
86
+ insert(table: string, data: Record<string, any>): Promise<InsertResult>;
87
+ insertMany(table: string, data: Record<string, any>[]): Promise<{ affectedRows: number }>;
88
+ update(table: string, data: Record<string, any>, query: QueryObject): Promise<UpdateResult>;
89
+ delete(table: string, query: QueryObject): Promise<DeleteResult>;
90
+ count(table: string, query: QueryObject): Promise<number>;
91
+ executeRawQuery(sql: string, params?: any[]): Promise<any[]>;
92
+ /** Execute raw SQL and return driver-native results (used by migrations) */
93
+ execute(sql: string, params?: any[]): Promise<any>;
94
+ /** Atomically increment a column respecting query wheres */
95
+ increment(table: string, column: string, query: QueryObject, amount?: number): Promise<UpdateResult>;
96
+ /** Atomically decrement a column respecting query wheres */
97
+ decrement(table: string, column: string, query: QueryObject, amount?: number): Promise<UpdateResult>;
98
+ close(): Promise<void>;
99
+ /** Backwards-compatible alias used by CLI */
100
+ disconnect(): Promise<void>;
101
+ }
102
+
103
+ // ==================== Query Builder ====================
104
+
105
+ export interface QueryObject {
106
+ columns?: string[];
107
+ wheres?: WhereClause[];
108
+ orders?: OrderClause[];
109
+ joins?: JoinClause[];
110
+ distinct?: boolean;
111
+ groupBys?: string[];
112
+ havings?: HavingClause[];
113
+ limit?: number | null;
114
+ offset?: number | null;
115
+ }
116
+
117
+ export interface WhereClause {
118
+ column?: string;
119
+ operator?: WhereOperator | string;
120
+ value?: any;
121
+ values?: any[];
122
+ type: 'basic' | 'in' | 'notIn' | 'null' | 'notNull' | 'between' | 'like';
123
+ boolean: 'and' | 'or';
124
+ }
125
+
126
+ export interface OrderClause {
127
+ column: string;
128
+ direction: 'asc' | 'desc';
129
+ }
130
+
131
+ export interface HavingClause {
132
+ type: 'basic' | 'count';
133
+ column: string;
134
+ operator: string;
135
+ value: any;
136
+ }
137
+
138
+ export interface JoinClause {
139
+ table: string;
140
+ first: string;
141
+ operator: string;
142
+ second: string;
143
+ type: 'inner' | 'left';
144
+ }
145
+
146
+ export interface PaginationResult<T> {
147
+ data: T[];
148
+ total: number;
149
+ per_page: number;
150
+ current_page: number;
151
+ last_page: number;
152
+ from: number | null;
153
+ to: number;
154
+ }
155
+
156
+ export class QueryBuilder<T extends Model> {
157
+ constructor(model: typeof Model);
158
+
159
+ select(...columns: string[]): this;
160
+ /** Convenience alias to pass an array of columns */
161
+ columns(cols: string[]): this;
162
+ distinct(): this;
163
+ where(column: string, value: any): this;
164
+ where(column: string, operator: string, value: any): this;
165
+ whereIn(column: string, values: any[]): this;
166
+ whereNotIn(column: string, values: any[]): this;
167
+ whereNull(column: string): this;
168
+ whereNotNull(column: string): this;
169
+ orWhere(column: string, value: any): this;
170
+ orWhere(column: string, operator: string, value: any): this;
171
+ whereBetween(column: string, values: [any, any]): this;
172
+ whereLike(column: string, value: string): this;
173
+ /** Filter parents where a relation has matches */
174
+ whereHas(relationName: string, callback?: (qb: QueryBuilder<any>) => void): this;
175
+ /** Filter parents where relation count matches */
176
+ has(relationName: string, count: number): this;
177
+ has(relationName: string, operator: string, count: number): this;
178
+ /** Filter parents without related rows */
179
+ whereDoesntHave(relationName: string): this;
180
+ orderBy(column: string, direction?: 'asc' | 'desc'): this;
181
+ /** Typo-friendly alias for orderBy */
182
+ ordrer(column: string, direction?: 'asc' | 'desc'): this;
183
+ limit(value: number): this;
184
+ offset(value: number): this;
185
+ skip(value: number): this;
186
+ take(value: number): this;
187
+ with(...relations: string[] | [Record<string, (qb: QueryBuilder<any>) => void> | string[]]): this;
188
+ withCount(relations: string | string[]): this;
189
+ groupBy(...columns: string[]): this;
190
+ having(column: string, operator: string, value: any): this;
191
+ join(table: string, first: string, second: string): this;
192
+ join(table: string, first: string, operator: string, second: string): this;
193
+ leftJoin(table: string, first: string, second: string): this;
194
+ leftJoin(table: string, first: string, operator: string, second: string): this;
195
+
196
+ // Soft delete methods
197
+ withTrashed(): this;
198
+ onlyTrashed(): this;
199
+
200
+ // Scope methods
201
+ withoutGlobalScope(name: string): this;
202
+ withoutGlobalScopes(): this;
203
+
204
+ get(): Promise<T[]>;
205
+ first(): Promise<T | null>;
206
+ firstOrFail(): Promise<T>;
207
+ paginate(page?: number, perPage?: number): Promise<PaginationResult<T>>;
208
+ count(): Promise<number>;
209
+ exists(): Promise<boolean>;
210
+ insert(data: Record<string, any> | Record<string, any>[]): Promise<any>;
211
+ update(attributes: Record<string, any>): Promise<any>;
212
+ /** Update and return first matching row as model, optionally eager-loading relations */
213
+ updateAndFetch(attributes: Record<string, any>, relations?: string[]): Promise<T | null>;
214
+ delete(): Promise<any>;
215
+ increment(column: string, amount?: number): Promise<any>;
216
+ decrement(column: string, amount?: number): Promise<any>;
217
+
218
+ clone(): QueryBuilder<T>;
219
+ }
220
+
221
+ // ==================== Model ====================
222
+
223
+ export type CastType = 'int' | 'integer' | 'float' | 'double' | 'string' | 'bool' | 'boolean' | 'array' | 'json' | 'date' | 'datetime' | 'timestamp';
224
+
225
+ /** Individual validation rule types */
226
+ export type ValidationRule =
227
+ | 'required'
228
+ | 'string'
229
+ | 'number'
230
+ | 'numeric'
231
+ | 'integer'
232
+ | 'email'
233
+ | 'url'
234
+ | 'boolean'
235
+ | 'date'
236
+ | 'array'
237
+ | 'object'
238
+ | 'nullable'
239
+ | `min:${number}`
240
+ | `max:${number}`
241
+ | `between:${number},${number}`
242
+ | `in:${string}`
243
+ | `not_in:${string}`
244
+ | `regex:${string}`
245
+ | `size:${number}`
246
+ | `digits:${number}`
247
+ | `digits_between:${number},${number}`;
248
+
249
+ /** Validation rule as pipe-separated string */
250
+ export type ValidationRuleString = string;
251
+
252
+ export interface ValidationResult {
253
+ valid: boolean;
254
+ errors: Record<string, string[]>;
255
+ }
256
+
257
+ export type EventCallback<T extends Model = Model> = (model: T) => boolean | void | Promise<boolean | void>;
258
+
259
+ /**
260
+ * Base Model class with optional generic for typed attributes
261
+ * @template TAttributes - Type of model attributes (defaults to Record<string, any>)
262
+ */
263
+ export class Model<TAttributes extends Record<string, any> = Record<string, any>> {
264
+ static table: string;
265
+ static primaryKey: string;
266
+ static timestamps: boolean;
267
+ static fillable: string[];
268
+ static hidden: string[];
269
+ static casts: Record<string, CastType>;
270
+ static connection: DatabaseConnection | null;
271
+
272
+ // Soft Deletes
273
+ static softDeletes: boolean;
274
+ static DELETED_AT: string;
275
+
276
+ // Scopes
277
+ static globalScopes: Record<string, (qb: QueryBuilder<any>) => void>;
278
+
279
+ // Events
280
+ static eventListeners: Record<ModelEventName, EventCallback[]>;
281
+
282
+ // Validation
283
+ static rules: Record<string, ValidationRuleString | ValidationRule[]>;
284
+
285
+ /** Model attributes with optional typing */
286
+ attributes: TAttributes;
287
+ /** Original attributes before modifications */
288
+ original: TAttributes;
289
+ /** Loaded relations */
290
+ relations: Record<string, any>;
291
+ /** Whether the model exists in database */
292
+ exists: boolean;
293
+
294
+ constructor(attributes?: Partial<TAttributes>);
295
+
296
+ // Event registration with typed event names
297
+ static on(event: ModelEventName, callback: EventCallback): void;
298
+ static fireEvent(event: ModelEventName, model: Model): Promise<boolean>;
299
+ static creating(callback: EventCallback): void;
300
+ static created(callback: EventCallback): void;
301
+ static updating(callback: EventCallback): void;
302
+ static updated(callback: EventCallback): void;
303
+ static saving(callback: EventCallback): void;
304
+ static saved(callback: EventCallback): void;
305
+ static deleting(callback: EventCallback): void;
306
+ static deleted(callback: EventCallback): void;
307
+ static restoring(callback: EventCallback): void;
308
+ static restored(callback: EventCallback): void;
309
+
310
+ // Scope methods
311
+ static addGlobalScope(name: string, callback: (qb: QueryBuilder<any>) => void): void;
312
+ static removeGlobalScope(name: string): void;
313
+ static withoutGlobalScope<T extends Model>(this: new () => T, name: string): QueryBuilder<T>;
314
+ static withoutGlobalScopes<T extends Model>(this: new () => T): QueryBuilder<T>;
315
+
316
+ // Soft delete methods
317
+ static withTrashed<T extends Model>(this: new () => T): QueryBuilder<T>;
318
+ static onlyTrashed<T extends Model>(this: new () => T): QueryBuilder<T>;
319
+
320
+ // Static methods
321
+ static setConnection(connection: DatabaseConnection): void;
322
+ /** Get the active database connection (v3.0.0+) */
323
+ static getConnection(): DatabaseConnection;
324
+ static query<T extends Model>(this: new () => T): QueryBuilder<T>;
325
+ static all<T extends Model>(this: new () => T): Promise<T[]>;
326
+ static find<T extends Model>(this: new () => T, id: any): Promise<T | null>;
327
+ static findOrFail<T extends Model>(this: new () => T, id: any): Promise<T>;
328
+ static where<T extends Model>(this: new () => T, column: string, value: any): QueryBuilder<T>;
329
+ static where<T extends Model>(this: new () => T, column: string, operator: string, value: any): QueryBuilder<T>;
330
+ static create<T extends Model>(this: new () => T, attributes: Record<string, any>): Promise<T>;
331
+ static insert(data: Record<string, any> | Record<string, any>[]): Promise<any>;
332
+ static update(attributes: Record<string, any>): Promise<any>;
333
+ /** Update by primary key and return the updated model, optionally eager-loading relations */
334
+ static updateAndFetchById<T extends Model>(this: new () => T, id: any, attributes: Record<string, any>, relations?: string[]): Promise<T | null>;
335
+ /** Update by primary key */
336
+ static updateById<T extends Model>(this: new () => T, id: any, attributes: Record<string, any>): Promise<any>;
337
+ static delete(): Promise<any>;
338
+ static first<T extends Model>(this: new () => T): Promise<T | null>;
339
+ static orderBy<T extends Model>(this: new () => T, column: string, direction?: 'asc' | 'desc'): QueryBuilder<T>;
340
+ static limit<T extends Model>(this: new () => T, value: number): QueryBuilder<T>;
341
+ static offset<T extends Model>(this: new () => T, value: number): QueryBuilder<T>;
342
+ static paginate<T extends Model>(this: new () => T, page?: number, perPage?: number): Promise<PaginationResult<T>>;
343
+ static whereIn<T extends Model>(this: new () => T, column: string, values: any[]): QueryBuilder<T>;
344
+ static whereNull<T extends Model>(this: new () => T, column: string): QueryBuilder<T>;
345
+ static whereNotNull<T extends Model>(this: new () => T, column: string): QueryBuilder<T>;
346
+ static count(): Promise<number>;
347
+ static with<T extends Model>(this: new () => T, ...relations: string[] | [Record<string, (qb: QueryBuilder<any>) => void> | string[]]): QueryBuilder<T>;
348
+ /** Include hidden attributes in query results */
349
+ static withHidden<T extends Model>(this: new () => T): QueryBuilder<T>;
350
+ /** Control visibility of hidden attributes (false = hide, true = show) */
351
+ static withoutHidden<T extends Model>(this: new () => T, show?: boolean): QueryBuilder<T>;
352
+
353
+ // Instance methods with typed attributes
354
+ /** Fill model with attributes */
355
+ fill(attributes: Partial<TAttributes>): this;
356
+ /** Set a single attribute with type safety */
357
+ setAttribute<K extends keyof TAttributes>(key: K, value: TAttributes[K]): this;
358
+ setAttribute(key: string, value: any): this;
359
+ /** Get a single attribute with type safety */
360
+ getAttribute<K extends keyof TAttributes>(key: K): TAttributes[K];
361
+ getAttribute(key: string): any;
362
+ castAttribute(key: string, value: any): any;
363
+ save(): Promise<this>;
364
+ destroy(): Promise<boolean>;
365
+ getDirty(): Partial<TAttributes>;
366
+ isDirty(): boolean;
367
+ toJSON(): TAttributes;
368
+ /** Load relations on an existing instance. Supports dot-notation and arrays. */
369
+ load(...relations: string[] | [string[]]): Promise<this>;
370
+
371
+ // Soft delete instance methods
372
+ trashed(): boolean;
373
+ restore(): Promise<this>;
374
+ forceDelete(): Promise<boolean>;
375
+
376
+ // Validation
377
+ validate(): ValidationResult;
378
+ validateOrFail(): void;
379
+
380
+ // Relationships
381
+ hasOne<T extends Model>(related: new () => T, foreignKey?: string, localKey?: string): HasOneRelation<T>;
382
+ hasMany<T extends Model>(related: new () => T, foreignKey?: string, localKey?: string): HasManyRelation<T>;
383
+ belongsTo<T extends Model>(related: new () => T, foreignKey?: string, ownerKey?: string): BelongsToRelation<T>;
384
+ belongsToMany<T extends Model>(
385
+ related: new () => T,
386
+ pivot: string,
387
+ foreignPivotKey?: string,
388
+ relatedPivotKey?: string,
389
+ parentKey?: string,
390
+ relatedKey?: string
391
+ ): BelongsToManyRelation<T>;
392
+ hasManyThrough<T extends Model>(
393
+ relatedFinal: new () => T,
394
+ through: new () => Model,
395
+ foreignKeyOnThrough?: string,
396
+ throughKeyOnFinal?: string,
397
+ localKey?: string,
398
+ throughLocalKey?: string
399
+ ): HasManyThroughRelation<T>;
400
+ /** Has one through intermediate model */
401
+ hasOneThrough<T extends Model>(
402
+ relatedFinal: new () => T,
403
+ through: new () => Model,
404
+ foreignKeyOnThrough?: string,
405
+ throughKeyOnFinal?: string,
406
+ localKey?: string,
407
+ throughLocalKey?: string
408
+ ): HasOneThroughRelation<T>;
409
+ /** Polymorphic one-to-one relation */
410
+ morphOne<T extends Model>(related: new () => T, name: string, typeColumn?: string, idColumn?: string, localKey?: string): MorphOneRelation<T>;
411
+ /** Polymorphic one-to-many relation */
412
+ morphMany<T extends Model>(related: new () => T, name: string, typeColumn?: string, idColumn?: string, localKey?: string): MorphManyRelation<T>;
413
+ /** Inverse polymorphic relation */
414
+ morphTo<T extends Model>(): MorphToRelation<T>;
415
+ }
416
+
417
+ // ==================== Relations ====================
418
+
419
+ export abstract class Relation<T extends Model> {
420
+ constructor(parent: Model, related: new () => T, foreignKey: string, localKey: string);
421
+ abstract get(): Promise<T | T[] | null>;
422
+ abstract eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
423
+ }
424
+
425
+ export class HasOneRelation<T extends Model> extends Relation<T> {
426
+ get(): Promise<T | null>;
427
+ eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
428
+ where(column: string, value: any): QueryBuilder<T>;
429
+ where(column: string, operator: string, value: any): QueryBuilder<T>;
430
+ }
431
+
432
+ export class HasManyRelation<T extends Model> extends Relation<T> {
433
+ get(): Promise<T[]>;
434
+ eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
435
+ where(column: string, value: any): QueryBuilder<T>;
436
+ where(column: string, operator: string, value: any): QueryBuilder<T>;
437
+ count(): Promise<number>;
438
+ }
439
+
440
+ export class BelongsToRelation<T extends Model> extends Relation<T> {
441
+ get(): Promise<T | null>;
442
+ eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
443
+ where(column: string, value: any): QueryBuilder<T>;
444
+ where(column: string, operator: string, value: any): QueryBuilder<T>;
445
+ }
446
+
447
+ export class BelongsToManyRelation<T extends Model> extends Relation<T> {
448
+ get(): Promise<T[]>;
449
+ eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
450
+ attach(ids: number | number[]): Promise<void>;
451
+ detach(ids?: number | number[] | null): Promise<void>;
452
+ sync(ids: number[]): Promise<void>;
453
+ }
454
+
455
+ export class HasManyThroughRelation<T extends Model> extends Relation<T> {
456
+ get(): Promise<T[]>;
457
+ eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
458
+ }
459
+
460
+ export class HasOneThroughRelation<T extends Model> extends Relation<T> {
461
+ get(): Promise<T | null>;
462
+ eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
463
+ }
464
+
465
+ export class MorphOneRelation<T extends Model> extends Relation<T> {
466
+ get(): Promise<T | null>;
467
+ eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
468
+ }
469
+
470
+ export class MorphManyRelation<T extends Model> extends Relation<T> {
471
+ get(): Promise<T[]>;
472
+ eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
473
+ }
474
+
475
+ export class MorphToRelation<T extends Model> extends Relation<T> {
476
+ get(): Promise<T | null>;
477
+ eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
478
+ }
479
+
480
+ // ==================== Schema Builder (Migrations) ====================
481
+
482
+ /** Foreign key action types */
483
+ export type ForeignKeyAction = 'CASCADE' | 'SET NULL' | 'RESTRICT' | 'NO ACTION' | 'SET DEFAULT';
484
+
485
+ /** Schema builder for database migrations */
486
+ export interface SchemaBuilder {
487
+ /** Create a new table */
488
+ createTable(name: string, callback: (table: TableBuilder) => void): Promise<void>;
489
+ /** Drop a table */
490
+ dropTable(name: string): Promise<void>;
491
+ /** Drop a table if it exists */
492
+ dropTableIfExists(name: string): Promise<void>;
493
+ /** Rename a table */
494
+ renameTable(from: string, to: string): Promise<void>;
495
+ /** Check if table exists */
496
+ hasTable(name: string): Promise<boolean>;
497
+ /** Modify an existing table */
498
+ table(name: string, callback: (table: TableBuilder) => void): Promise<void>;
499
+ /** Check if column exists */
500
+ hasColumn(table: string, column: string): Promise<boolean>;
501
+ }
502
+
503
+ /** Table builder for creating/modifying tables */
504
+ export interface TableBuilder {
505
+ // Primary keys
506
+ /** Auto-incrementing primary key */
507
+ id(name?: string): ColumnBuilder;
508
+ /** Big integer auto-incrementing primary key */
509
+ bigIncrements(name?: string): ColumnBuilder;
510
+ /** UUID primary key */
511
+ uuid(name?: string): ColumnBuilder;
512
+
513
+ // Numeric types
514
+ /** Integer column */
515
+ integer(name: string): ColumnBuilder;
516
+ /** Big integer column */
517
+ bigInteger(name: string): ColumnBuilder;
518
+ /** Small integer column */
519
+ smallInteger(name: string): ColumnBuilder;
520
+ /** Tiny integer column */
521
+ tinyInteger(name: string): ColumnBuilder;
522
+ /** Decimal column */
523
+ decimal(name: string, precision?: number, scale?: number): ColumnBuilder;
524
+ /** Float column */
525
+ float(name: string, precision?: number, scale?: number): ColumnBuilder;
526
+ /** Double column */
527
+ double(name: string, precision?: number, scale?: number): ColumnBuilder;
528
+
529
+ // String types
530
+ /** String/VARCHAR column */
531
+ string(name: string, length?: number): ColumnBuilder;
532
+ /** Text column */
533
+ text(name: string): ColumnBuilder;
534
+ /** Medium text column */
535
+ mediumText(name: string): ColumnBuilder;
536
+ /** Long text column */
537
+ longText(name: string): ColumnBuilder;
538
+ /** Char column */
539
+ char(name: string, length?: number): ColumnBuilder;
540
+
541
+ // Boolean
542
+ /** Boolean column */
543
+ boolean(name: string): ColumnBuilder;
544
+
545
+ // Date/Time
546
+ /** Date column */
547
+ date(name: string): ColumnBuilder;
548
+ /** DateTime column */
549
+ dateTime(name: string): ColumnBuilder;
550
+ /** Timestamp column */
551
+ timestamp(name: string): ColumnBuilder;
552
+ /** Time column */
553
+ time(name: string): ColumnBuilder;
554
+ /** Year column */
555
+ year(name: string): ColumnBuilder;
556
+ /** Add created_at and updated_at columns */
557
+ timestamps(): void;
558
+ /** Add nullable deleted_at column for soft deletes */
559
+ softDeletes(): void;
560
+
561
+ // Binary
562
+ /** Binary/Blob column */
563
+ binary(name: string): ColumnBuilder;
564
+ /** Blob column */
565
+ blob(name: string): ColumnBuilder;
566
+
567
+ // JSON
568
+ /** JSON column */
569
+ json(name: string): ColumnBuilder;
570
+ /** JSONB column (PostgreSQL) */
571
+ jsonb(name: string): ColumnBuilder;
572
+
573
+ // Enum
574
+ /** Enum column */
575
+ enum(name: string, values: string[]): ColumnBuilder;
576
+
577
+ // Indexes
578
+ /** Add primary key constraint */
579
+ primary(columns: string | string[]): void;
580
+ /** Add unique constraint */
581
+ unique(columns: string | string[]): void;
582
+ /** Add index */
583
+ index(columns: string | string[], name?: string): void;
584
+ /** Add foreign key */
585
+ foreign(column: string): ForeignKeyBuilder;
586
+
587
+ // Modifications
588
+ /** Drop a column */
589
+ dropColumn(name: string | string[]): void;
590
+ /** Rename a column */
591
+ renameColumn(from: string, to: string): void;
592
+ /** Drop an index */
593
+ dropIndex(name: string): void;
594
+ /** Drop a unique constraint */
595
+ dropUnique(name: string): void;
596
+ /** Drop a foreign key */
597
+ dropForeign(name: string): void;
598
+ }
599
+
600
+ /** Column builder for column definitions */
601
+ export interface ColumnBuilder {
602
+ /** Make column nullable */
603
+ nullable(): this;
604
+ /** Set default value */
605
+ default(value: any): this;
606
+ /** Make column unsigned (numeric only) */
607
+ unsigned(): this;
608
+ /** Add unique constraint */
609
+ unique(): this;
610
+ /** Make column primary key */
611
+ primary(): this;
612
+ /** Add index */
613
+ index(): this;
614
+ /** Add auto increment */
615
+ autoIncrement(): this;
616
+ /** Add comment */
617
+ comment(text: string): this;
618
+ /** Add after clause (MySQL) */
619
+ after(column: string): this;
620
+ /** Add first clause (MySQL) */
621
+ first(): this;
622
+ /** Set character set */
623
+ charset(charset: string): this;
624
+ /** Set collation */
625
+ collation(collation: string): this;
626
+ /** Add references for foreign key */
627
+ references(column: string): ForeignKeyBuilder;
628
+ }
629
+
630
+ /** Foreign key builder */
631
+ export interface ForeignKeyBuilder {
632
+ /** Referenced table */
633
+ on(table: string): this;
634
+ /** Referenced column */
635
+ references(column: string): this;
636
+ /** On delete action */
637
+ onDelete(action: ForeignKeyAction): this;
638
+ /** On update action */
639
+ onUpdate(action: ForeignKeyAction): this;
640
+ }
641
+
642
+ /** Migration interface for typed migrations */
643
+ export interface MigrationInterface {
644
+ /** Run the migration */
645
+ up(schema: SchemaBuilder): Promise<void>;
646
+ /** Reverse the migration */
647
+ down(schema: SchemaBuilder): Promise<void>;
648
+ }
649
+
650
+ /** Schema class export */
651
+ export class Schema {
652
+ static create(name: string, callback: (table: TableBuilder) => void): Promise<void>;
653
+ static drop(name: string): Promise<void>;
654
+ static dropIfExists(name: string): Promise<void>;
655
+ static table(name: string, callback: (table: TableBuilder) => void): Promise<void>;
656
+ static rename(from: string, to: string): Promise<void>;
657
+ static hasTable(name: string): Promise<boolean>;
658
+ static hasColumn(table: string, column: string): Promise<boolean>;
659
+ }
660
+
661
+ export class Seeder {
662
+ constructor(connection: DatabaseConnection, manager?: SeederManager | null);
663
+ run(): Promise<void>;
664
+ call(seeder: string): Promise<void>;
665
+ insert(table: string, rows: Record<string, any> | Record<string, any>[]): Promise<any>;
666
+ truncate(table: string): Promise<void>;
667
+ }
668
+
669
+ export class SeederManager {
670
+ constructor(connection: DatabaseConnection, seedsPath?: string);
671
+ run(target?: string | null): Promise<void>;
672
+ runSeeder(seederRef: string): Promise<void>;
673
+ }
674
+ }