metal-orm 1.1.21 → 1.1.22

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": "metal-orm",
3
- "version": "1.1.21",
3
+ "version": "1.1.22",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,7 +17,6 @@ export const SysColumns = defineTable(
17
17
  user_type_id: col.int()
18
18
  },
19
19
  {},
20
- undefined,
21
20
  { schema: 'sys' }
22
21
  );
23
22
 
@@ -30,7 +29,6 @@ export const SysTables = defineTable(
30
29
  is_ms_shipped: col.boolean()
31
30
  },
32
31
  {},
33
- undefined,
34
32
  { schema: 'sys' }
35
33
  );
36
34
 
@@ -41,7 +39,6 @@ export const SysSchemas = defineTable(
41
39
  name: col.varchar(255)
42
40
  },
43
41
  {},
44
- undefined,
45
42
  { schema: 'sys' }
46
43
  );
47
44
 
@@ -52,7 +49,6 @@ export const SysTypes = defineTable(
52
49
  name: col.varchar(255)
53
50
  },
54
51
  {},
55
- undefined,
56
52
  { schema: 'sys' }
57
53
  );
58
54
 
@@ -69,7 +65,6 @@ export const SysIndexes = defineTable(
69
65
  is_hypothetical: col.boolean()
70
66
  },
71
67
  {},
72
- undefined,
73
68
  { schema: 'sys' }
74
69
  );
75
70
 
@@ -82,7 +77,6 @@ export const SysIndexColumns = defineTable(
82
77
  key_ordinal: col.int()
83
78
  },
84
79
  {},
85
- undefined,
86
80
  { schema: 'sys' }
87
81
  );
88
82
 
@@ -95,7 +89,6 @@ export const SysForeignKeys = defineTable(
95
89
  update_referential_action_desc: col.varchar(64)
96
90
  },
97
91
  {},
98
- undefined,
99
92
  { schema: 'sys' }
100
93
  );
101
94
 
@@ -110,7 +103,6 @@ export const SysForeignKeyColumns = defineTable(
110
103
  constraint_column_id: col.int()
111
104
  },
112
105
  {},
113
- undefined,
114
106
  { schema: 'sys' }
115
107
  );
116
108
 
@@ -12,7 +12,6 @@ export const InformationSchemaTables = defineTable(
12
12
  table_comment: col.varchar(1024)
13
13
  },
14
14
  {},
15
- undefined,
16
15
  { schema: INFORMATION_SCHEMA }
17
16
  );
18
17
 
@@ -32,7 +31,6 @@ export const InformationSchemaColumns = defineTable(
32
31
  ordinal_position: col.int()
33
32
  },
34
33
  {},
35
- undefined,
36
34
  { schema: INFORMATION_SCHEMA }
37
35
  );
38
36
 
@@ -51,7 +49,6 @@ export const InformationSchemaKeyColumnUsage = defineTable(
51
49
  referenced_column_name: col.varchar(255)
52
50
  },
53
51
  {},
54
- undefined,
55
52
  { schema: INFORMATION_SCHEMA }
56
53
  );
57
54
 
@@ -65,7 +62,6 @@ export const InformationSchemaReferentialConstraints = defineTable(
65
62
  update_rule: col.varchar(255)
66
63
  },
67
64
  {},
68
- undefined,
69
65
  { schema: INFORMATION_SCHEMA }
70
66
  );
71
67
 
@@ -81,7 +77,6 @@ export const InformationSchemaStatistics = defineTable(
81
77
  seq_in_index: col.int()
82
78
  },
83
79
  {},
84
- undefined,
85
80
  { schema: INFORMATION_SCHEMA }
86
81
  );
87
82
 
@@ -14,7 +14,6 @@ export const PgInformationSchemaColumns = defineTable(
14
14
  ordinal_position: col.int()
15
15
  },
16
16
  {},
17
- undefined,
18
17
  { schema: 'information_schema' }
19
18
  );
20
19
 
@@ -27,7 +26,6 @@ export const PgClass = defineTable(
27
26
  relkind: col.varchar(1)
28
27
  },
29
28
  {},
30
- undefined,
31
29
  { schema: 'pg_catalog' }
32
30
  );
33
31
 
@@ -38,7 +36,6 @@ export const PgNamespace = defineTable(
38
36
  nspname: col.varchar(255)
39
37
  },
40
38
  {},
41
- undefined,
42
39
  { schema: 'pg_catalog' }
43
40
  );
44
41
 
@@ -52,7 +49,6 @@ export const PgIndex = defineTable(
52
49
  indpred: col.varchar(1024)
53
50
  },
54
51
  {},
55
- undefined,
56
52
  { schema: 'pg_catalog' }
57
53
  );
58
54
 
@@ -64,7 +60,6 @@ export const PgAttribute = defineTable(
64
60
  attnum: col.int()
65
61
  },
66
62
  {},
67
- undefined,
68
63
  { schema: 'pg_catalog' }
69
64
  );
70
65
 
@@ -80,7 +75,6 @@ export const PgTableConstraints = defineTable(
80
75
  constraint_type: col.varchar(255)
81
76
  },
82
77
  {},
83
- undefined,
84
78
  { schema: 'information_schema' }
85
79
  );
86
80
 
@@ -97,7 +91,6 @@ export const PgKeyColumnUsage = defineTable(
97
91
  ordinal_position: col.int()
98
92
  },
99
93
  {},
100
- undefined,
101
94
  { schema: 'information_schema' }
102
95
  );
103
96
 
@@ -113,7 +106,6 @@ export const PgConstraintColumnUsage = defineTable(
113
106
  column_name: col.varchar(255)
114
107
  },
115
108
  {},
116
- undefined,
117
109
  { schema: 'information_schema' }
118
110
  );
119
111
 
@@ -131,7 +123,6 @@ export const PgReferentialConstraints = defineTable(
131
123
  delete_rule: col.varchar(64)
132
124
  },
133
125
  {},
134
- undefined,
135
126
  { schema: 'information_schema' }
136
127
  );
137
128
 
@@ -14,7 +14,6 @@ export const SqliteMaster = defineTable(
14
14
  sql: col.varchar(4096) // Original DDL
15
15
  },
16
16
  {},
17
- undefined,
18
17
  { schema: undefined }
19
18
  );
20
19
 
@@ -26,7 +25,6 @@ export const SqliteSequence = defineTable(
26
25
  seq: col.int() // Last autoincrement value
27
26
  },
28
27
  {},
29
- undefined,
30
28
  { schema: undefined }
31
29
  );
32
30
 
@@ -39,7 +37,6 @@ export const SqliteStat1 = defineTable(
39
37
  stat: col.varchar(255) // Statistics string
40
38
  },
41
39
  {},
42
- undefined,
43
40
  { schema: undefined }
44
41
  );
45
42
 
@@ -1,4 +1,3 @@
1
- import { TableHooks } from '../schema/table.js';
2
1
  import { RelationKinds } from '../schema/relation.js';
3
2
  import {
4
3
  addColumnMetadata,
@@ -15,7 +14,6 @@ import { syncTreeEntityMetadata } from '../tree/tree-decorator.js';
15
14
  */
16
15
  export interface EntityOptions {
17
16
  tableName?: string;
18
- hooks?: TableHooks;
19
17
  /** Entity type: 'table' (default) or 'view'. Views are read-only. */
20
18
  type?: 'table' | 'view';
21
19
  }
@@ -42,6 +40,7 @@ const deriveTableNameFromConstructor = (ctor: EntityConstructor<unknown>): strin
42
40
 
43
41
  /**
44
42
  * Class decorator to mark a class as an entity and configure its table mapping.
43
+ * Runtime lifecycle hooks are registered on OrmSession, not entity metadata.
45
44
  * @param options - Configuration options for the entity.
46
45
  * @returns A class decorator that registers the entity metadata.
47
46
  */
@@ -52,7 +51,7 @@ export function Entity(options: EntityOptions = {}) {
52
51
  ): T {
53
52
  const ctor = value;
54
53
  const tableName = options.tableName ?? deriveTableNameFromConstructor(ctor);
55
- setEntityTableName(ctor, tableName, options.hooks, options.type);
54
+ setEntityTableName(ctor, tableName, options.type);
56
55
 
57
56
  const bag = context ? readMetadataBag(context) : readMetadataBagFromConstructor(ctor);
58
57
  if (bag) {
package/src/index.ts CHANGED
@@ -38,6 +38,7 @@ export * from './orm/hydration.js';
38
38
  export * from './codegen/typescript.js';
39
39
  export * from './orm/orm-session.js';
40
40
  export * from './orm/orm.js';
41
+ export * from './orm/lifecycle.js';
41
42
  export * from './orm/column-introspection.js';
42
43
  export * from './orm/entity.js';
43
44
  export * from './orm/lazy-batch.js';
@@ -84,4 +85,4 @@ export * from './tree/index.js';
84
85
  export * from './cache/index.js';
85
86
 
86
87
  // Bulk operations module
87
- export * from './bulk/index.js';
88
+ export * from './bulk/index.js';
@@ -1,5 +1,5 @@
1
1
  import { ColumnDef } from '../schema/column-types.js';
2
- import { defineTable, TableDef, TableHooks } from '../schema/table.js';
2
+ import { defineTable, TableDef } from '../schema/table.js';
3
3
  import { CascadeMode, RelationKinds } from '../schema/relation.js';
4
4
  import type { TransformerMetadata } from '../decorators/transformers/transformer-metadata.js';
5
5
 
@@ -153,7 +153,7 @@ export interface MorphManyRelationMetadata {
153
153
  }
154
154
 
155
155
  /**
156
- * Union type for all relation metadata.
156
+ * Union type for all relation metadata types.
157
157
  */
158
158
  export type RelationMetadata =
159
159
  | HasManyRelationMetadata
@@ -169,6 +169,7 @@ export type EntityType = 'table' | 'view';
169
169
 
170
170
  /**
171
171
  * Metadata for entities.
172
+ * Runtime lifecycle hooks intentionally live on OrmSession rather than here.
172
173
  * @template TColumns - The columns type
173
174
  */
174
175
  export interface EntityMetadata<TColumns extends Record<string, ColumnDefLike> = Record<string, ColumnDefLike>> {
@@ -184,8 +185,6 @@ export interface EntityMetadata<TColumns extends Record<string, ColumnDefLike> =
184
185
  relations: Record<string, RelationMetadata>;
185
186
  /** The transformers */
186
187
  transformers: Record<string, TransformerMetadata>;
187
- /** Optional hooks */
188
- hooks?: TableHooks;
189
188
  /** Optional table definition */
190
189
  table?: TableDef<MaterializeColumns<TColumns>>;
191
190
  }
@@ -295,25 +294,21 @@ export const addTransformerMetadata = (
295
294
  };
296
295
 
297
296
  /**
298
- * Sets the table name, hooks, and type for an entity.
297
+ * Sets the table name and type for an entity.
298
+ * Lifecycle policy is session-bound and is not persisted in metadata.
299
299
  * @param target - The entity constructor
300
300
  * @param tableName - The table name
301
- * @param hooks - Optional table hooks
302
301
  * @param type - Entity type: 'table' or 'view'
303
302
  */
304
303
  export const setEntityTableName = (
305
304
  target: EntityConstructor,
306
305
  tableName: string,
307
- hooks?: TableHooks,
308
306
  type?: EntityType
309
307
  ): void => {
310
308
  const meta = ensureEntityMetadata(target);
311
309
  if (tableName && tableName.length > 0) {
312
310
  meta.tableName = tableName;
313
311
  }
314
- if (hooks) {
315
- meta.hooks = hooks;
316
- }
317
312
  if (type) {
318
313
  meta.type = type;
319
314
  }
@@ -340,7 +335,7 @@ export const buildTableDef = <TColumns extends Record<string, ColumnDefLike>>(me
340
335
  } as ColumnDef;
341
336
  }
342
337
 
343
- const table = defineTable(meta.tableName, columns as MaterializeColumns<TColumns>, {}, meta.hooks);
338
+ const table = defineTable(meta.tableName, columns as MaterializeColumns<TColumns>);
344
339
  meta.table = table;
345
340
  return table;
346
341
  };
@@ -0,0 +1,20 @@
1
+ import type { TableDef } from '../schema/table.js';
2
+
3
+ /**
4
+ * Entity lifecycle hooks executed by the Unit of Work.
5
+ *
6
+ * Hooks are runtime/session configuration. They are intentionally not stored on
7
+ * TableDef so the same mapping can be used by independent sessions with
8
+ * different lifecycle policies.
9
+ */
10
+ export interface TableHooks<TEntity = unknown, TContext = unknown> {
11
+ beforeInsert?(ctx: TContext, entity: TEntity): Promise<void> | void;
12
+ afterInsert?(ctx: TContext, entity: TEntity): Promise<void> | void;
13
+ beforeUpdate?(ctx: TContext, entity: TEntity): Promise<void> | void;
14
+ afterUpdate?(ctx: TContext, entity: TEntity): Promise<void> | void;
15
+ beforeDelete?(ctx: TContext, entity: TEntity): Promise<void> | void;
16
+ afterDelete?(ctx: TContext, entity: TEntity): Promise<void> | void;
17
+ }
18
+
19
+ /** @internal */
20
+ export type TableHookResolver = (table: TableDef) => TableHooks | undefined;
@@ -13,6 +13,7 @@ import type { EntityConstructor } from './entity-metadata.js';
13
13
  import { Orm } from './orm.js';
14
14
  import { IdentityMap } from './identity-map.js';
15
15
  import { UnitOfWork } from './unit-of-work.js';
16
+ import type { TableHooks } from './lifecycle.js';
16
17
  import { DomainEventBus, DomainEventHandler, InitialHandlers } from './domain-event-bus.js';
17
18
  import { RelationChangeProcessor } from './relation-change-processor.js';
18
19
  import { createQueryLoggingExecutor, QueryLogger } from './query-logger.js';
@@ -38,6 +39,12 @@ const NESTED_TRANSACTIONS_REQUIRE_SAVEPOINTS =
38
39
  const ROLLBACK_ONLY_TRANSACTION =
39
40
  'Cannot commit transaction because an inner transaction failed';
40
41
 
42
+ type LifecycleHookTarget = TableDef | EntityConstructor<object>;
43
+ type LifecycleHookEntity<TTarget extends LifecycleHookTarget> =
44
+ TTarget extends TableDef ? EntityInstance<TTarget> :
45
+ TTarget extends EntityConstructor<object> ? InstanceType<TTarget> :
46
+ never;
47
+
41
48
  /**
42
49
  * Interface for ORM interceptors that allow hooking into the flush lifecycle.
43
50
  */
@@ -106,6 +113,7 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
106
113
  readonly tenantId?: string | number;
107
114
 
108
115
  private readonly interceptors: OrmInterceptor[];
116
+ private readonly tableHooks = new WeakMap<TableDef, TableHooks>();
109
117
  private saveGraphDefaults?: SaveGraphSessionOptions;
110
118
  private transactionDepth = 0;
111
119
  private savepointCounter = 0;
@@ -121,7 +129,13 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
121
129
  this.interceptors = [...(opts.interceptors ?? [])];
122
130
 
123
131
  this.identityMap = new IdentityMap();
124
- this.unitOfWork = new UnitOfWork(this.orm.dialect, this.executor, this.identityMap, () => this);
132
+ this.unitOfWork = new UnitOfWork(
133
+ this.orm.dialect,
134
+ this.executor,
135
+ this.identityMap,
136
+ () => this,
137
+ table => this.tableHooks.get(table)
138
+ );
125
139
  this.relationChanges = new RelationChangeProcessor(this.unitOfWork, this.orm.dialect, this.executor);
126
140
  this.domainEvents = new DomainEventBus<E, OrmSession<E>>(opts.domainEventHandlers);
127
141
  this.cacheManager = opts.cacheManager;
@@ -250,6 +264,24 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
250
264
  return this.unitOfWork.getEntitiesForTable(table);
251
265
  }
252
266
 
267
+ /**
268
+ * Registers INSERT/UPDATE/DELETE lifecycle hooks for this Session only.
269
+ * The target can be a TableDef or a decorated entity constructor.
270
+ * Registering again for the same table replaces the previous hook set.
271
+ */
272
+ registerTableHooks<TTarget extends LifecycleHookTarget>(
273
+ target: TTarget,
274
+ hooks: TableHooks<LifecycleHookEntity<TTarget>, OrmSession<E>>
275
+ ): void {
276
+ const table = typeof target === 'function'
277
+ ? getTableDefFromEntity(target as EntityConstructor<object>)
278
+ : target;
279
+ if (!table) {
280
+ throw new Error('Entity metadata has not been bootstrapped');
281
+ }
282
+ this.tableHooks.set(table as TableDef, hooks as unknown as TableHooks);
283
+ }
284
+
253
285
  /**
254
286
  * Registers an interceptor for flush lifecycle hooks.
255
287
  * @param interceptor - The interceptor to register
@@ -261,7 +293,7 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
261
293
  /**
262
294
  * Registers a domain event handler.
263
295
  * @param type - The event type
264
- * @param handler - The event handler
296
+ * @param handler - The domain event handler
265
297
  */
266
298
  registerDomainEventHandler<TType extends E['type']>(
267
299
  type: TType,
@@ -500,7 +532,9 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
500
532
  }
501
533
 
502
534
  /**
503
- * Flushes pending changes to the database without session hooks, relation processing, or domain events.
535
+ * Flushes pending changes to the database without session interceptors,
536
+ * relation processing, or domain events. Table lifecycle hooks still run
537
+ * because they are part of the Unit of Work.
504
538
  */
505
539
  async flush(): Promise<void> {
506
540
  await this.unitOfWork.flush();
@@ -5,13 +5,14 @@ import { InsertQueryBuilder } from '../query-builder/insert.js';
5
5
  import { UpdateQueryBuilder } from '../query-builder/update.js';
6
6
  import { DeleteQueryBuilder } from '../query-builder/delete.js';
7
7
  import { findPrimaryKey } from '../query-builder/hydration-planner.js';
8
- import type { TableDef, TableHooks } from '../schema/table.js';
8
+ import type { TableDef } from '../schema/table.js';
9
9
  import { payloadResultSets } from '../core/execution/db-executor.js';
10
10
  import type { DbExecutor, QueryResult } from '../core/execution/db-executor.js';
11
11
  import { IdentityMap } from './identity-map.js';
12
12
  import { EntityStatus } from './runtime-types.js';
13
13
  import type { TrackedEntity } from './runtime-types.js';
14
14
  import type { PrimaryKey } from './entity-context.js';
15
+ import type { TableHookResolver, TableHooks } from './lifecycle.js';
15
16
 
16
17
  /**
17
18
  * Unit of Work pattern implementation for tracking entity changes.
@@ -25,12 +26,14 @@ export class UnitOfWork {
25
26
  * @param executor - The database executor
26
27
  * @param identityMap - The identity map
27
28
  * @param hookContext - Function to get the hook context
29
+ * @param resolveTableHooks - Session/runtime lifecycle hook resolver
28
30
  */
29
31
  constructor(
30
32
  private readonly dialect: Dialect,
31
33
  private readonly executor: DbExecutor,
32
34
  private readonly identityMap: IdentityMap,
33
- private readonly hookContext: () => unknown
35
+ private readonly hookContext: () => unknown,
36
+ private readonly resolveTableHooks: TableHookResolver = () => undefined
34
37
  ) { }
35
38
 
36
39
  /**
@@ -195,7 +198,8 @@ export class UnitOfWork {
195
198
  * @param tracked - The tracked entity to insert
196
199
  */
197
200
  private async flushInsert(tracked: TrackedEntity): Promise<void> {
198
- await this.runHook(tracked.table.hooks?.beforeInsert, tracked);
201
+ const hooks = this.resolveTableHooks(tracked.table);
202
+ await this.runHook(hooks?.beforeInsert, tracked);
199
203
 
200
204
  const payload = this.extractColumns(tracked.table, tracked.entity as Record<string, unknown>);
201
205
  let builder = new InsertQueryBuilder(tracked.table).values(payload as Record<string, ValueOperandInput>);
@@ -212,7 +216,7 @@ export class UnitOfWork {
212
216
  tracked.pk = this.getPrimaryKeyValue(tracked);
213
217
  this.registerIdentity(tracked);
214
218
 
215
- await this.runHook(tracked.table.hooks?.afterInsert, tracked);
219
+ await this.runHook(hooks?.afterInsert, tracked);
216
220
  }
217
221
 
218
222
  /**
@@ -227,7 +231,8 @@ export class UnitOfWork {
227
231
  return;
228
232
  }
229
233
 
230
- await this.runHook(tracked.table.hooks?.beforeUpdate, tracked);
234
+ const hooks = this.resolveTableHooks(tracked.table);
235
+ await this.runHook(hooks?.beforeUpdate, tracked);
231
236
 
232
237
  const pkColumn = tracked.table.columns[findPrimaryKey(tracked.table)];
233
238
  if (!pkColumn) return;
@@ -248,7 +253,7 @@ export class UnitOfWork {
248
253
  tracked.original = this.createSnapshot(tracked.table, tracked.entity as Record<string, unknown>);
249
254
  this.registerIdentity(tracked);
250
255
 
251
- await this.runHook(tracked.table.hooks?.afterUpdate, tracked);
256
+ await this.runHook(hooks?.afterUpdate, tracked);
252
257
  }
253
258
 
254
259
  /**
@@ -257,7 +262,8 @@ export class UnitOfWork {
257
262
  */
258
263
  private async flushDelete(tracked: TrackedEntity): Promise<void> {
259
264
  if (tracked.pk == null) return;
260
- await this.runHook(tracked.table.hooks?.beforeDelete, tracked);
265
+ const hooks = this.resolveTableHooks(tracked.table);
266
+ await this.runHook(hooks?.beforeDelete, tracked);
261
267
 
262
268
  const pkColumn = tracked.table.columns[findPrimaryKey(tracked.table)];
263
269
  if (!pkColumn) return;
@@ -270,11 +276,11 @@ export class UnitOfWork {
270
276
  this.trackedEntities.delete(tracked.entity);
271
277
  this.identityMap.remove(tracked);
272
278
 
273
- await this.runHook(tracked.table.hooks?.afterDelete, tracked);
279
+ await this.runHook(hooks?.afterDelete, tracked);
274
280
  }
275
281
 
276
282
  /**
277
- * Runs a table hook if defined.
283
+ * Runs a lifecycle hook if defined.
278
284
  * @param hook - The hook function
279
285
  * @param tracked - The tracked entity
280
286
  */
@@ -36,23 +36,15 @@ export interface TableOptions {
36
36
  collation?: string;
37
37
  }
38
38
 
39
- export interface TableHooks<TEntity = unknown, TContext = unknown> {
40
- beforeInsert?(ctx: TContext, entity: TEntity): Promise<void> | void;
41
- afterInsert?(ctx: TContext, entity: TEntity): Promise<void> | void;
42
- beforeUpdate?(ctx: TContext, entity: TEntity): Promise<void> | void;
43
- afterUpdate?(ctx: TContext, entity: TEntity): Promise<void> | void;
44
- beforeDelete?(ctx: TContext, entity: TEntity): Promise<void> | void;
45
- afterDelete?(ctx: TContext, entity: TEntity): Promise<void> | void;
46
- }
47
-
48
39
  /**
49
- * Definition of a database table with its columns and relationships
40
+ * Definition of a database table with its columns and relationships.
41
+ *
42
+ * Runtime lifecycle policy intentionally does not live here. TableDef is
43
+ * mapping/schema metadata and can be shared by multiple OrmSession instances.
50
44
  * @typeParam T - Type of the columns record
51
45
  */
52
46
  export interface TableDef<
53
- T extends Record<string, ColumnDef> = Record<string, ColumnDef>,
54
- TEntity = unknown,
55
- TContext = unknown
47
+ T extends Record<string, ColumnDef> = Record<string, ColumnDef>
56
48
  > {
57
49
  /** Name of the table */
58
50
  name: string;
@@ -62,8 +54,6 @@ export interface TableDef<
62
54
  columns: T;
63
55
  /** Record of relationship definitions keyed by relation name */
64
56
  relations: Record<string, RelationDef>;
65
- /** Optional lifecycle hooks */
66
- hooks?: TableHooks<TEntity, TContext>;
67
57
  /** Composite primary key definition (falls back to column.primary flags) */
68
58
  primaryKey?: string[];
69
59
  /** Secondary indexes */
@@ -79,11 +69,12 @@ export interface TableDef<
79
69
  }
80
70
 
81
71
  /**
82
- * Creates a table definition with columns and relationships
72
+ * Creates a table definition with columns and relationships.
83
73
  * @typeParam T - Type of the columns record
84
74
  * @param name - Name of the table
85
- * @param columns - Record of column definitions
75
+ * @param columns - Record of column definitions keyed by property name
86
76
  * @param relations - Record of relationship definitions (optional)
77
+ * @param options - Schema/table options (optional)
87
78
  * @returns Complete table definition with runtime-filled column metadata
88
79
  *
89
80
  * @example
@@ -95,17 +86,12 @@ export interface TableDef<
95
86
  * });
96
87
  * ```
97
88
  */
98
- export const defineTable = <
99
- T extends Record<string, ColumnDef>,
100
- TEntity = unknown,
101
- TContext = unknown
102
- >(
89
+ export const defineTable = <T extends Record<string, ColumnDef>>(
103
90
  name: string,
104
91
  columns: T,
105
92
  relations: Record<string, RelationDef> = {},
106
- hooks?: TableHooks<TEntity, TContext>,
107
93
  options: TableOptions = {}
108
- ): TableDef<T, TEntity, TContext> => {
94
+ ): TableDef<T> => {
109
95
  // Runtime mutability to assign names to column definitions for convenience
110
96
  const colsWithNames = Object.entries(columns).reduce((acc, [key, def]) => {
111
97
  const colDef = { ...def, name: key, table: name };
@@ -118,7 +104,6 @@ export const defineTable = <
118
104
  schema: options.schema,
119
105
  columns: colsWithNames,
120
106
  relations,
121
- hooks,
122
107
  primaryKey: options.primaryKey,
123
108
  indexes: options.indexes,
124
109
  checks: options.checks,