@coherent.js/database 1.0.0-beta.5 → 1.0.0-beta.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coherent.js/database",
3
- "version": "1.0.0-beta.5",
3
+ "version": "1.0.0-beta.6",
4
4
  "description": "Database utilities and adapters for Coherent.js",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "peerDependencies": {
46
46
  "sqlite3": "^5.0.0",
47
- "@coherent.js/core": "1.0.0-beta.5"
47
+ "@coherent.js/core": "1.0.0-beta.6"
48
48
  },
49
49
  "peerDependenciesMeta": {
50
50
  "sqlite3": {
package/types/index.d.ts CHANGED
@@ -9,9 +9,104 @@
9
9
  // Database Connection Types
10
10
  // ============================================================================
11
11
 
12
+ /**
13
+ * Database type identifier.
14
+ */
15
+ export type DatabaseType = 'postgresql' | 'mysql' | 'sqlite' | 'mongodb' | 'memory';
16
+
17
+ /**
18
+ * PostgreSQL-specific configuration options.
19
+ */
20
+ export interface PostgreSQLConfig {
21
+ type: 'postgresql';
22
+ host: string;
23
+ port?: number;
24
+ username: string;
25
+ password: string;
26
+ database: string;
27
+ ssl?: boolean | {
28
+ rejectUnauthorized?: boolean;
29
+ ca?: string;
30
+ key?: string;
31
+ cert?: string;
32
+ };
33
+ schema?: string;
34
+ applicationName?: string;
35
+ statementTimeout?: number;
36
+ idleTimeout?: number;
37
+ }
38
+
39
+ /**
40
+ * MySQL-specific configuration options.
41
+ */
42
+ export interface MySQLConfig {
43
+ type: 'mysql';
44
+ host: string;
45
+ port?: number;
46
+ username: string;
47
+ password: string;
48
+ database: string;
49
+ ssl?: boolean | {
50
+ ca?: string;
51
+ key?: string;
52
+ cert?: string;
53
+ };
54
+ multipleStatements?: boolean;
55
+ namedPlaceholders?: boolean;
56
+ dateStrings?: boolean;
57
+ supportBigNumbers?: boolean;
58
+ bigNumberStrings?: boolean;
59
+ }
60
+
61
+ /**
62
+ * SQLite-specific configuration options.
63
+ */
64
+ export interface SQLiteConfig {
65
+ type: 'sqlite';
66
+ database: string;
67
+ mode?: 'readonly' | 'readwrite' | 'create';
68
+ wal?: boolean;
69
+ busyTimeout?: number;
70
+ }
71
+
72
+ /**
73
+ * MongoDB-specific configuration options.
74
+ */
75
+ export interface MongoDBConfig {
76
+ type: 'mongodb';
77
+ uri?: string;
78
+ host?: string;
79
+ port?: number;
80
+ username?: string;
81
+ password?: string;
82
+ database: string;
83
+ authSource?: string;
84
+ replicaSet?: string;
85
+ retryWrites?: boolean;
86
+ w?: number | 'majority';
87
+ }
88
+
89
+ /**
90
+ * In-memory database configuration for testing.
91
+ */
92
+ export interface MemoryConfig {
93
+ type: 'memory';
94
+ database?: string;
95
+ }
96
+
97
+ /**
98
+ * Database-specific configuration union type.
99
+ */
100
+ export type DatabaseSpecificConfig =
101
+ | PostgreSQLConfig
102
+ | MySQLConfig
103
+ | SQLiteConfig
104
+ | MongoDBConfig
105
+ | MemoryConfig;
106
+
12
107
  /** Database configuration options */
13
108
  export interface DatabaseConfig {
14
- type: 'postgresql' | 'mysql' | 'sqlite' | 'mongodb' | 'memory';
109
+ type: DatabaseType;
15
110
  host?: string;
16
111
  port?: number;
17
112
  username?: string;
@@ -57,14 +152,22 @@ export interface DatabaseConnection {
57
152
  ping(): Promise<boolean>;
58
153
  }
59
154
 
60
- /** Database transaction interface */
155
+ /**
156
+ * Database transaction interface.
157
+ * Supports nested transactions via savepoints.
158
+ */
61
159
  export interface Transaction {
62
160
  query<T = any>(sql: string, parameters?: any[]): Promise<T>;
63
161
  commit(): Promise<void>;
64
162
  rollback(): Promise<void>;
163
+ /** Create a savepoint for nested transaction */
65
164
  savepoint(name: string): Promise<void>;
165
+ /** Release a savepoint */
66
166
  release(name: string): Promise<void>;
167
+ /** Rollback to a savepoint */
67
168
  rollbackTo(name: string): Promise<void>;
169
+ /** Whether transaction is still active */
170
+ readonly isActive: boolean;
68
171
  }
69
172
 
70
173
  /** Database manager interface */
@@ -206,9 +309,14 @@ export interface FieldInfo {
206
309
  // Model Types
207
310
  // ============================================================================
208
311
 
312
+ /**
313
+ * Field type definitions for model schema.
314
+ */
315
+ export type FieldType = 'string' | 'number' | 'boolean' | 'date' | 'json' | 'array' | 'object' | 'uuid' | 'bigint' | 'decimal';
316
+
209
317
  /** Model field definition */
210
318
  export interface FieldDefinition {
211
- type: 'string' | 'number' | 'boolean' | 'date' | 'json' | 'array' | 'object';
319
+ type: FieldType;
212
320
  required?: boolean;
213
321
  default?: any;
214
322
  primaryKey?: boolean;
@@ -250,106 +358,131 @@ export interface RelationDefinition {
250
358
  }
251
359
 
252
360
  /** Model configuration */
253
- export interface ModelConfig {
361
+ export interface ModelConfig<T extends Record<string, any> = Record<string, any>> {
254
362
  table: string;
255
363
  schema: ModelSchema;
256
364
  timestamps?: boolean | { created?: string; updated?: string };
257
365
  softDeletes?: boolean | string;
258
366
  primaryKey?: string;
259
- fillable?: string[];
260
- guarded?: string[];
261
- hidden?: string[];
262
- visible?: string[];
263
- casts?: Record<string, string>;
367
+ fillable?: (keyof T)[];
368
+ guarded?: (keyof T)[];
369
+ hidden?: (keyof T)[];
370
+ visible?: (keyof T)[];
371
+ casts?: Record<keyof T, string>;
264
372
  relations?: Record<string, RelationDefinition>;
265
- hooks?: ModelHooks;
266
- validators?: Record<string, (value: any, instance: ModelInstance) => boolean | string>;
373
+ hooks?: ModelHooks<T>;
374
+ validators?: Record<string, (value: any, instance: ModelInstance<T>) => boolean | string>;
267
375
  }
268
376
 
269
377
  /** Model lifecycle hooks */
270
- export interface ModelHooks {
271
- beforeSave?: (instance: ModelInstance) => void | Promise<void>;
272
- afterSave?: (instance: ModelInstance) => void | Promise<void>;
273
- beforeCreate?: (instance: ModelInstance) => void | Promise<void>;
274
- afterCreate?: (instance: ModelInstance) => void | Promise<void>;
275
- beforeUpdate?: (instance: ModelInstance) => void | Promise<void>;
276
- afterUpdate?: (instance: ModelInstance) => void | Promise<void>;
277
- beforeDelete?: (instance: ModelInstance) => void | Promise<void>;
278
- afterDelete?: (instance: ModelInstance) => void | Promise<void>;
279
- beforeValidate?: (instance: ModelInstance) => void | Promise<void>;
280
- afterValidate?: (instance: ModelInstance) => void | Promise<void>;
281
- }
282
-
283
- /** Model instance interface */
284
- export interface ModelInstance {
285
- readonly $model: Model;
378
+ export interface ModelHooks<T extends Record<string, any> = Record<string, any>> {
379
+ beforeSave?: (instance: ModelInstance<T>) => void | Promise<void>;
380
+ afterSave?: (instance: ModelInstance<T>) => void | Promise<void>;
381
+ beforeCreate?: (instance: ModelInstance<T>) => void | Promise<void>;
382
+ afterCreate?: (instance: ModelInstance<T>) => void | Promise<void>;
383
+ beforeUpdate?: (instance: ModelInstance<T>) => void | Promise<void>;
384
+ afterUpdate?: (instance: ModelInstance<T>) => void | Promise<void>;
385
+ beforeDelete?: (instance: ModelInstance<T>) => void | Promise<void>;
386
+ afterDelete?: (instance: ModelInstance<T>) => void | Promise<void>;
387
+ beforeValidate?: (instance: ModelInstance<T>) => void | Promise<void>;
388
+ afterValidate?: (instance: ModelInstance<T>) => void | Promise<void>;
389
+ }
390
+
391
+ /**
392
+ * Model instance interface with generic type support.
393
+ * Type parameter T represents the model's attribute shape.
394
+ */
395
+ export interface ModelInstance<T extends Record<string, any> = Record<string, any>> {
396
+ readonly $model: Model<T>;
286
397
  readonly $table: string;
287
398
  readonly $primaryKey: string;
288
399
  readonly $exists: boolean;
289
400
  readonly $dirty: boolean;
290
- readonly $original: Record<string, any>;
291
- readonly $attributes: Record<string, any>;
401
+ readonly $original: T;
402
+ readonly $attributes: T;
292
403
  readonly $relations: Record<string, any>;
293
404
 
294
- get<K extends keyof this>(key: K): this[K];
295
- set<K extends keyof this>(key: K, value: this[K]): this;
296
- setAttribute(key: string, value: any): this;
297
- getAttribute(key: string): any;
405
+ get<K extends keyof T>(key: K): T[K];
406
+ set<K extends keyof T>(key: K, value: T[K]): this;
407
+ setAttribute<K extends keyof T>(key: K, value: T[K]): this;
408
+ getAttribute<K extends keyof T>(key: K): T[K];
298
409
  hasAttribute(key: string): boolean;
299
- fill(attributes: Record<string, any>): this;
410
+ fill(attributes: Partial<T>): this;
300
411
  save(): Promise<this>;
301
- update(attributes: Record<string, any>): Promise<this>;
412
+ update(attributes: Partial<T>): Promise<this>;
302
413
  delete(): Promise<boolean>;
303
414
  refresh(): Promise<this>;
304
415
  validate(): Promise<boolean>;
305
416
  getValidationErrors(): string[];
306
- toObject(): Record<string, any>;
307
- toJSON(): Record<string, any>;
308
- clone(): ModelInstance;
309
- is(instance: ModelInstance): boolean;
310
- isNot(instance: ModelInstance): boolean;
311
- getKey(): any;
312
- setKey(value: any): this;
313
- getDirty(): Record<string, any>;
314
- getOriginal(): Record<string, any>;
417
+ toObject(): T;
418
+ toJSON(): T;
419
+ clone(): ModelInstance<T>;
420
+ is(instance: ModelInstance<T>): boolean;
421
+ isNot(instance: ModelInstance<T>): boolean;
422
+ getKey(): T[keyof T];
423
+ setKey(value: T[keyof T]): this;
424
+ getDirty(): Partial<T>;
425
+ getOriginal(): T;
315
426
  syncOriginal(): this;
316
- wasChanged(key?: string): boolean;
317
- getChanges(): Record<string, any>;
427
+ wasChanged(key?: keyof T): boolean;
428
+ getChanges(): Partial<T>;
318
429
  load(relations: string | string[]): Promise<this>;
319
430
  loadMissing(relations: string | string[]): Promise<this>;
320
431
  }
321
432
 
322
- /** Model query builder interface */
323
- export interface ModelQuery<T extends ModelInstance = ModelInstance> {
324
- readonly model: Model;
325
-
326
- find(id: any): Promise<T | null>;
327
- findOrFail(id: any): Promise<T>;
328
- findMany(ids: any[]): Promise<T[]>;
329
- first(): Promise<T | null>;
330
- firstOrFail(): Promise<T>;
331
- get(): Promise<T[]>;
332
- all(): Promise<T[]>;
433
+ /**
434
+ * Model query builder interface with full generic chaining.
435
+ * Type parameter T flows through all query methods to the results.
436
+ *
437
+ * @example
438
+ * ```typescript
439
+ * interface User {
440
+ * id: number;
441
+ * email: string;
442
+ * name: string;
443
+ * createdAt: Date;
444
+ * }
445
+ *
446
+ * const userModel = createModel<User>({ table: 'users', ... });
447
+ *
448
+ * // Type-safe query chain
449
+ * const users = await userModel.query()
450
+ * .where({ email: 'test@example.com' })
451
+ * .orderBy('createdAt', 'DESC')
452
+ * .limit(10)
453
+ * .get(); // users: ModelInstance<User>[]
454
+ * ```
455
+ */
456
+ export interface ModelQuery<T extends Record<string, any> = Record<string, any>> {
457
+ readonly model: Model<T>;
458
+
459
+ find(id: any): Promise<ModelInstance<T> | null>;
460
+ findOrFail(id: any): Promise<ModelInstance<T>>;
461
+ findMany(ids: any[]): Promise<ModelInstance<T>[]>;
462
+ first(): Promise<ModelInstance<T> | null>;
463
+ firstOrFail(): Promise<ModelInstance<T>>;
464
+ get(): Promise<ModelInstance<T>[]>;
465
+ all(): Promise<ModelInstance<T>[]>;
333
466
  count(): Promise<number>;
334
467
  exists(): Promise<boolean>;
335
- sum(column: string): Promise<number>;
336
- avg(column: string): Promise<number>;
337
- min(column: string): Promise<number>;
338
- max(column: string): Promise<number>;
339
-
340
- where(conditions: WhereConditions): ModelQuery<T>;
341
- where(column: string, value: any): ModelQuery<T>;
342
- where(column: string, operator: SqlOperator, value: any): ModelQuery<T>;
343
- whereIn(column: string, values: any[]): ModelQuery<T>;
344
- whereNotIn(column: string, values: any[]): ModelQuery<T>;
345
- whereBetween(column: string, values: [any, any]): ModelQuery<T>;
346
- whereNull(column: string): ModelQuery<T>;
347
- whereNotNull(column: string): ModelQuery<T>;
348
-
349
- orderBy(column: string, direction?: OrderDirection): ModelQuery<T>;
350
- orderByDesc(column: string): ModelQuery<T>;
351
- latest(column?: string): ModelQuery<T>;
352
- oldest(column?: string): ModelQuery<T>;
468
+ sum(column: keyof T & string): Promise<number>;
469
+ avg(column: keyof T & string): Promise<number>;
470
+ min(column: keyof T & string): Promise<number>;
471
+ max(column: keyof T & string): Promise<number>;
472
+
473
+ where(conditions: Partial<T> | WhereConditions): ModelQuery<T>;
474
+ where<K extends keyof T>(column: K, value: T[K]): ModelQuery<T>;
475
+ where<K extends keyof T>(column: K, operator: SqlOperator, value: T[K]): ModelQuery<T>;
476
+ whereIn<K extends keyof T>(column: K, values: T[K][]): ModelQuery<T>;
477
+ whereNotIn<K extends keyof T>(column: K, values: T[K][]): ModelQuery<T>;
478
+ whereBetween<K extends keyof T>(column: K, values: [T[K], T[K]]): ModelQuery<T>;
479
+ whereNull(column: keyof T & string): ModelQuery<T>;
480
+ whereNotNull(column: keyof T & string): ModelQuery<T>;
481
+
482
+ orderBy(column: keyof T & string, direction?: OrderDirection): ModelQuery<T>;
483
+ orderByDesc(column: keyof T & string): ModelQuery<T>;
484
+ latest(column?: keyof T & string): ModelQuery<T>;
485
+ oldest(column?: keyof T & string): ModelQuery<T>;
353
486
 
354
487
  limit(count: number): ModelQuery<T>;
355
488
  take(count: number): ModelQuery<T>;
@@ -359,21 +492,24 @@ export interface ModelQuery<T extends ModelInstance = ModelInstance> {
359
492
  with(relations: string | string[]): ModelQuery<T>;
360
493
  withCount(relations: string | string[]): ModelQuery<T>;
361
494
  has(relation: string, operator?: string, count?: number): ModelQuery<T>;
362
- whereHas(relation: string, callback?: (query: ModelQuery) => void): ModelQuery<T>;
495
+ whereHas(relation: string, callback?: (query: ModelQuery<any>) => void): ModelQuery<T>;
363
496
  doesntHave(relation: string): ModelQuery<T>;
364
- whereDoesntHave(relation: string, callback?: (query: ModelQuery) => void): ModelQuery<T>;
497
+ whereDoesntHave(relation: string, callback?: (query: ModelQuery<any>) => void): ModelQuery<T>;
498
+
499
+ /** Select specific columns */
500
+ select<K extends keyof T>(...columns: K[]): ModelQuery<Pick<T, K>>;
365
501
 
366
- create(attributes: Record<string, any>): Promise<T>;
367
- insert(records: Record<string, any>[]): Promise<void>;
368
- update(attributes: Record<string, any>): Promise<number>;
502
+ create(attributes: Partial<T>): Promise<ModelInstance<T>>;
503
+ insert(records: Partial<T>[]): Promise<void>;
504
+ update(attributes: Partial<T>): Promise<number>;
369
505
  delete(): Promise<number>;
370
506
  forceDelete(): Promise<number>;
371
507
 
372
508
  paginate(page: number, perPage: number): Promise<PaginationResult<T>>;
373
509
  simplePaginate(page: number, perPage: number): Promise<SimplePaginationResult<T>>;
374
510
 
375
- chunk(size: number, callback: (items: T[]) => void | Promise<void>): Promise<void>;
376
- each(callback: (item: T) => void | Promise<void>): Promise<void>;
511
+ chunk(size: number, callback: (items: ModelInstance<T>[]) => void | Promise<void>): Promise<void>;
512
+ each(callback: (item: ModelInstance<T>) => void | Promise<void>): Promise<void>;
377
513
 
378
514
  toSql(): string;
379
515
  explain(): Promise<any[]>;
@@ -381,26 +517,50 @@ export interface ModelQuery<T extends ModelInstance = ModelInstance> {
381
517
  clone(): ModelQuery<T>;
382
518
  }
383
519
 
384
- /** Model class interface */
385
- export interface Model {
520
+ /**
521
+ * Model class interface with generic type support.
522
+ *
523
+ * @example
524
+ * ```typescript
525
+ * interface User {
526
+ * id: number;
527
+ * email: string;
528
+ * name: string;
529
+ * }
530
+ *
531
+ * const User: Model<User> = createModel<User>({
532
+ * table: 'users',
533
+ * schema: {
534
+ * id: { type: 'number', primaryKey: true },
535
+ * email: { type: 'string', unique: true },
536
+ * name: { type: 'string' }
537
+ * }
538
+ * });
539
+ *
540
+ * // Type-safe operations
541
+ * const user = await User.create({ email: 'test@example.com', name: 'Test' });
542
+ * const found = await User.find(1);
543
+ * ```
544
+ */
545
+ export interface Model<T extends Record<string, any> = Record<string, any>> {
386
546
  readonly table: string;
387
547
  readonly primaryKey: string;
388
548
  readonly schema: ModelSchema;
389
- readonly config: ModelConfig;
549
+ readonly config: ModelConfig<T>;
390
550
  readonly connection: DatabaseConnection;
391
551
 
392
- query(): ModelQuery;
393
- newInstance(attributes?: Record<string, any>, exists?: boolean): ModelInstance;
394
- create(attributes: Record<string, any>): Promise<ModelInstance>;
395
- find(id: any): Promise<ModelInstance | null>;
396
- findOrFail(id: any): Promise<ModelInstance>;
397
- findMany(ids: any[]): Promise<ModelInstance[]>;
398
- first(): Promise<ModelInstance | null>;
399
- firstOrFail(): Promise<ModelInstance>;
400
- all(): Promise<ModelInstance[]>;
401
- where(conditions: WhereConditions): ModelQuery;
402
- insert(records: Record<string, any>[]): Promise<void>;
403
- update(attributes: Record<string, any>, conditions?: WhereConditions): Promise<number>;
552
+ query(): ModelQuery<T>;
553
+ newInstance(attributes?: Partial<T>, exists?: boolean): ModelInstance<T>;
554
+ create(attributes: Partial<T>): Promise<ModelInstance<T>>;
555
+ find(id: any): Promise<ModelInstance<T> | null>;
556
+ findOrFail(id: any): Promise<ModelInstance<T>>;
557
+ findMany(ids: any[]): Promise<ModelInstance<T>[]>;
558
+ first(): Promise<ModelInstance<T> | null>;
559
+ firstOrFail(): Promise<ModelInstance<T>>;
560
+ all(): Promise<ModelInstance<T>[]>;
561
+ where(conditions: Partial<T> | WhereConditions): ModelQuery<T>;
562
+ insert(records: Partial<T>[]): Promise<void>;
563
+ update(attributes: Partial<T>, conditions?: WhereConditions): Promise<number>;
404
564
  delete(conditions?: WhereConditions): Promise<number>;
405
565
  count(conditions?: WhereConditions): Promise<number>;
406
566
 
@@ -410,14 +570,14 @@ export interface Model {
410
570
  getSchema(): ModelSchema;
411
571
  getRelations(): Record<string, RelationDefinition>;
412
572
 
413
- on(event: string, listener: (...args: any[]) => void): Model;
414
- off(event: string, listener?: (...args: any[]) => void): Model;
573
+ on(event: string, listener: (...args: any[]) => void): Model<T>;
574
+ off(event: string, listener?: (...args: any[]) => void): Model<T>;
415
575
  emit(event: string, ...args: any[]): boolean;
416
576
  }
417
577
 
418
- /** Pagination result */
419
- export interface PaginationResult<T> {
420
- data: T[];
578
+ /** Pagination result with typed data */
579
+ export interface PaginationResult<T extends Record<string, any> = Record<string, any>> {
580
+ data: ModelInstance<T>[];
421
581
  total: number;
422
582
  perPage: number;
423
583
  currentPage: number;
@@ -428,9 +588,9 @@ export interface PaginationResult<T> {
428
588
  hasPrevPage: boolean;
429
589
  }
430
590
 
431
- /** Simple pagination result */
432
- export interface SimplePaginationResult<T> {
433
- data: T[];
591
+ /** Simple pagination result with typed data */
592
+ export interface SimplePaginationResult<T extends Record<string, any> = Record<string, any>> {
593
+ data: ModelInstance<T>[];
434
594
  perPage: number;
435
595
  currentPage: number;
436
596
  hasNextPage: boolean;
@@ -467,20 +627,28 @@ export interface SchemaBuilder {
467
627
  /** Table builder for schema modifications */
468
628
  export interface TableBuilder {
469
629
  increments(name?: string): ColumnBuilder;
630
+ bigIncrements(name?: string): ColumnBuilder;
470
631
  string(name: string, length?: number): ColumnBuilder;
471
632
  text(name: string): ColumnBuilder;
633
+ mediumText(name: string): ColumnBuilder;
634
+ longText(name: string): ColumnBuilder;
472
635
  integer(name: string): ColumnBuilder;
636
+ smallInteger(name: string): ColumnBuilder;
637
+ tinyInteger(name: string): ColumnBuilder;
473
638
  bigInteger(name: string): ColumnBuilder;
474
639
  float(name: string, precision?: number, scale?: number): ColumnBuilder;
640
+ double(name: string, precision?: number, scale?: number): ColumnBuilder;
475
641
  decimal(name: string, precision?: number, scale?: number): ColumnBuilder;
476
642
  boolean(name: string): ColumnBuilder;
477
643
  date(name: string): ColumnBuilder;
478
644
  datetime(name: string): ColumnBuilder;
479
645
  timestamp(name: string): ColumnBuilder;
480
646
  timestamps(useTimestamps?: boolean, defaultToNow?: boolean): void;
647
+ softDeletes(columnName?: string): ColumnBuilder;
481
648
  json(name: string): ColumnBuilder;
482
649
  jsonb(name: string): ColumnBuilder;
483
650
  uuid(name: string): ColumnBuilder;
651
+ binary(name: string, length?: number): ColumnBuilder;
484
652
  enum(name: string, values: string[]): ColumnBuilder;
485
653
 
486
654
  primary(columns: string | string[]): void;
@@ -533,8 +701,10 @@ export type ForeignKeyAction = 'CASCADE' | 'SET NULL' | 'SET DEFAULT' | 'RESTRIC
533
701
  /** Index options */
534
702
  export interface IndexOptions {
535
703
  indexName?: string;
536
- indexType?: 'btree' | 'hash' | 'gist' | 'gin' | 'spgist';
704
+ indexType?: 'btree' | 'hash' | 'gist' | 'gin' | 'spgist' | 'brin';
537
705
  storageParameters?: Record<string, any>;
706
+ unique?: boolean;
707
+ where?: string;
538
708
  }
539
709
 
540
710
  /** Migration interface */
@@ -580,7 +750,8 @@ export type DatabaseFeature =
580
750
  | 'cte'
581
751
  | 'window'
582
752
  | 'upsert'
583
- | 'returning';
753
+ | 'returning'
754
+ | 'fullTextSearch';
584
755
 
585
756
  // ============================================================================
586
757
  // Middleware Types
@@ -610,8 +781,8 @@ export type TransactionIsolation =
610
781
  | 'SERIALIZABLE';
611
782
 
612
783
  /** Model middleware options */
613
- export interface ModelMiddlewareOptions {
614
- model: string | Model;
784
+ export interface ModelMiddlewareOptions<T extends Record<string, any> = Record<string, any>> {
785
+ model: string | Model<T>;
615
786
  connection?: string;
616
787
  as?: string;
617
788
  }
@@ -649,6 +820,21 @@ export interface MigrationStatus {
649
820
  error?: string;
650
821
  }
651
822
 
823
+ /**
824
+ * Helper type to infer model attributes from schema definition.
825
+ */
826
+ export type InferModelAttributes<S extends ModelSchema> = {
827
+ [K in keyof S]: S[K]['type'] extends 'string' ? string
828
+ : S[K]['type'] extends 'number' ? number
829
+ : S[K]['type'] extends 'boolean' ? boolean
830
+ : S[K]['type'] extends 'date' ? Date
831
+ : S[K]['type'] extends 'json' | 'array' | 'object' ? any
832
+ : S[K]['type'] extends 'uuid' ? string
833
+ : S[K]['type'] extends 'bigint' ? bigint
834
+ : S[K]['type'] extends 'decimal' ? number
835
+ : unknown;
836
+ };
837
+
652
838
  // ============================================================================
653
839
  // Main Functions
654
840
  // ============================================================================
@@ -659,8 +845,34 @@ export function createQuery(config: QueryConfig): QueryConfig;
659
845
  /** Execute a query using the provided configuration */
660
846
  export function executeQuery<T = any>(db: DatabaseConnection, query: QueryConfig): Promise<QueryResult<T>>;
661
847
 
662
- /** Create a model */
663
- export function createModel(config: ModelConfig): Model;
848
+ /**
849
+ * Create a typed model.
850
+ *
851
+ * @example
852
+ * ```typescript
853
+ * interface User {
854
+ * id: number;
855
+ * email: string;
856
+ * name: string;
857
+ * }
858
+ *
859
+ * const User = createModel<User>({
860
+ * table: 'users',
861
+ * schema: {
862
+ * id: { type: 'number', primaryKey: true },
863
+ * email: { type: 'string', unique: true },
864
+ * name: { type: 'string' }
865
+ * }
866
+ * });
867
+ *
868
+ * // Type-safe: user is ModelInstance<User>
869
+ * const user = await User.create({ email: 'test@example.com', name: 'Test' });
870
+ * console.log(user.email); // Type-safe access
871
+ * ```
872
+ */
873
+ export function createModel<T extends Record<string, any> = Record<string, any>>(
874
+ config: ModelConfig<T>
875
+ ): Model<T>;
664
876
 
665
877
  /** Create a migration */
666
878
  export function createMigration(config: MigrationConfig): Migration;
@@ -671,6 +883,14 @@ export function createDatabaseManager(config: DatabaseConfig): DatabaseManager;
671
883
  /** Create a connection */
672
884
  export function createConnection(config: DatabaseConfig): Promise<DatabaseConnection>;
673
885
 
886
+ /**
887
+ * Create a connection from database-specific configuration.
888
+ * Provides better type inference for database-specific options.
889
+ */
890
+ export function createTypedConnection<T extends DatabaseSpecificConfig>(
891
+ config: T
892
+ ): Promise<DatabaseConnection>;
893
+
674
894
  /** Run migrations */
675
895
  export function runMigrations(
676
896
  connection: DatabaseConnection,
@@ -679,15 +899,15 @@ export function runMigrations(
679
899
  ): Promise<MigrationStatus[]>;
680
900
 
681
901
  /** Database adapter creators */
682
- export function createPostgreSQLAdapter(config: DatabaseConfig): DatabaseAdapter;
683
- export function createMySQLAdapter(config: DatabaseConfig): DatabaseAdapter;
684
- export function createSQLiteAdapter(config: DatabaseConfig): DatabaseAdapter;
685
- export function createMongoDBAdapter(config: DatabaseConfig): DatabaseAdapter;
902
+ export function createPostgreSQLAdapter(config: PostgreSQLConfig | DatabaseConfig): DatabaseAdapter;
903
+ export function createMySQLAdapter(config: MySQLConfig | DatabaseConfig): DatabaseAdapter;
904
+ export function createSQLiteAdapter(config: SQLiteConfig | DatabaseConfig): DatabaseAdapter;
905
+ export function createMongoDBAdapter(config: MongoDBConfig | DatabaseConfig): DatabaseAdapter;
686
906
 
687
907
  /** Middleware functions */
688
908
  export function withDatabase(options?: DatabaseMiddlewareOptions): any;
689
909
  export function withTransaction(options?: TransactionMiddlewareOptions): any;
690
- export function withModel(options: ModelMiddlewareOptions): any;
910
+ export function withModel<T extends Record<string, any>>(options: ModelMiddlewareOptions<T>): any;
691
911
  export function withPagination(options?: PaginationMiddlewareOptions): any;
692
912
 
693
913
  /** Setup database with default configuration */
@@ -724,6 +944,7 @@ declare const coherentDatabase: {
724
944
  SQLiteAdapter: typeof SQLiteAdapter;
725
945
  MongoDBAdapter: typeof MongoDBAdapter;
726
946
  createConnection: typeof createConnection;
947
+ createTypedConnection: typeof createTypedConnection;
727
948
  runMigrations: typeof runMigrations;
728
949
  setupDatabase: typeof setupDatabase;
729
950
  DEFAULT_DB_CONFIG: typeof DEFAULT_DB_CONFIG;