metal-orm 1.0.89 → 1.0.91

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.
Files changed (57) hide show
  1. package/dist/index.cjs +2968 -2983
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +784 -251
  4. package/dist/index.d.ts +784 -251
  5. package/dist/index.js +2913 -2975
  6. package/dist/index.js.map +1 -1
  7. package/package.json +6 -3
  8. package/src/codegen/typescript.ts +29 -40
  9. package/src/core/ast/expression-builders.ts +34 -53
  10. package/src/core/ast/expression-nodes.ts +51 -72
  11. package/src/core/ast/expression-visitor.ts +219 -252
  12. package/src/core/ast/expression.ts +20 -21
  13. package/src/core/ddl/introspect/utils.ts +45 -45
  14. package/src/core/dialect/abstract.ts +55 -81
  15. package/src/core/execution/db-executor.ts +4 -5
  16. package/src/core/execution/executors/mysql-executor.ts +7 -9
  17. package/src/decorators/bootstrap.ts +29 -26
  18. package/src/dto/apply-filter.ts +279 -0
  19. package/src/dto/dto-types.ts +229 -0
  20. package/src/dto/filter-types.ts +193 -0
  21. package/src/dto/index.ts +97 -0
  22. package/src/dto/openapi/generators/base.ts +29 -0
  23. package/src/dto/openapi/generators/column.ts +34 -0
  24. package/src/dto/openapi/generators/dto.ts +94 -0
  25. package/src/dto/openapi/generators/filter.ts +74 -0
  26. package/src/dto/openapi/generators/nested-dto.ts +532 -0
  27. package/src/dto/openapi/generators/pagination.ts +111 -0
  28. package/src/dto/openapi/generators/relation-filter.ts +210 -0
  29. package/src/dto/openapi/index.ts +17 -0
  30. package/src/dto/openapi/type-mappings.ts +191 -0
  31. package/src/dto/openapi/types.ts +90 -0
  32. package/src/dto/openapi/utilities.ts +45 -0
  33. package/src/dto/pagination-utils.ts +150 -0
  34. package/src/dto/transform.ts +197 -0
  35. package/src/index.ts +5 -3
  36. package/src/orm/entity-context.ts +9 -9
  37. package/src/orm/entity.ts +74 -74
  38. package/src/orm/orm-session.ts +159 -159
  39. package/src/orm/relation-change-processor.ts +3 -3
  40. package/src/orm/runtime-types.ts +5 -5
  41. package/src/orm/unit-of-work.ts +13 -25
  42. package/src/query-builder/query-ast-service.ts +287 -300
  43. package/src/query-builder/relation-filter-utils.ts +159 -160
  44. package/src/query-builder/select.ts +137 -192
  45. package/src/schema/column-types.ts +4 -4
  46. package/src/schema/types.ts +5 -1
  47. package/src/core/ast/ast-validation.ts +0 -19
  48. package/src/core/ast/param-proxy.ts +0 -47
  49. package/src/core/ast/query-visitor.ts +0 -273
  50. package/src/openapi/index.ts +0 -4
  51. package/src/openapi/query-parameters.ts +0 -207
  52. package/src/openapi/schema-extractor-input.ts +0 -193
  53. package/src/openapi/schema-extractor-output.ts +0 -427
  54. package/src/openapi/schema-extractor-utils.ts +0 -110
  55. package/src/openapi/schema-extractor.ts +0 -120
  56. package/src/openapi/schema-types.ts +0 -187
  57. package/src/openapi/type-mappers.ts +0 -227
@@ -18,7 +18,7 @@ import { RelationChangeProcessor } from './relation-change-processor.js';
18
18
  import { createQueryLoggingExecutor, QueryLogger } from './query-logger.js';
19
19
  import { ExecutionContext } from './execution-context.js';
20
20
  import type { HydrationContext } from './hydration-context.js';
21
- import type { EntityContext, PrimaryKey } from './entity-context.js';
21
+ import type { EntityContext, PrimaryKey } from './entity-context.js';
22
22
  import {
23
23
  DomainEvent,
24
24
  OrmDomainEvent,
@@ -28,9 +28,9 @@ import {
28
28
  TrackedEntity
29
29
  } from './runtime-types.js';
30
30
  import { executeHydrated } from './execute.js';
31
- import { runInTransaction } from './transaction-runner.js';
32
- import { saveGraphInternal, SaveGraphOptions } from './save-graph.js';
33
- import type { SaveGraphInputPayload } from './save-graph-types.js';
31
+ import { runInTransaction } from './transaction-runner.js';
32
+ import { saveGraphInternal, SaveGraphOptions } from './save-graph.js';
33
+ import type { SaveGraphInputPayload } from './save-graph-types.js';
34
34
 
35
35
  /**
36
36
  * Interface for ORM interceptors that allow hooking into the flush lifecycle.
@@ -53,7 +53,7 @@ export interface OrmInterceptor {
53
53
  * Options for creating an OrmSession instance.
54
54
  * @template E - The domain event type
55
55
  */
56
- export interface OrmSessionOptions<E extends DomainEvent = OrmDomainEvent> {
56
+ export interface OrmSessionOptions<E extends DomainEvent = OrmDomainEvent> {
57
57
  /** The ORM instance */
58
58
  orm: Orm<E>;
59
59
  /** The database executor */
@@ -63,21 +63,21 @@ export interface OrmSessionOptions<E extends DomainEvent = OrmDomainEvent> {
63
63
  /** Optional interceptors for flush lifecycle hooks */
64
64
  interceptors?: OrmInterceptor[];
65
65
  /** Optional domain event handlers */
66
- domainEventHandlers?: InitialHandlers<E, OrmSession<E>>;
67
- }
68
-
69
- export interface SaveGraphSessionOptions extends SaveGraphOptions {
70
- /** Wrap the save operation in a transaction (default: true). */
71
- transactional?: boolean;
72
- /** Flush after saveGraph when not transactional (default: false). */
73
- flush?: boolean;
74
- }
75
-
76
- /**
77
- * ORM Session that manages entity lifecycle, identity mapping, and database operations.
78
- * @template E - The domain event type
79
- */
80
- export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements EntityContext {
66
+ domainEventHandlers?: InitialHandlers<E, OrmSession<E>>;
67
+ }
68
+
69
+ export interface SaveGraphSessionOptions extends SaveGraphOptions {
70
+ /** Wrap the save operation in a transaction (default: true). */
71
+ transactional?: boolean;
72
+ /** Flush after saveGraph when not transactional (default: false). */
73
+ flush?: boolean;
74
+ }
75
+
76
+ /**
77
+ * ORM Session that manages entity lifecycle, identity mapping, and database operations.
78
+ * @template E - The domain event type
79
+ */
80
+ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements EntityContext {
81
81
  /** The ORM instance */
82
82
  readonly orm: Orm<E>;
83
83
  /** The database executor */
@@ -88,11 +88,11 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
88
88
  readonly unitOfWork: UnitOfWork;
89
89
  /** The domain event bus */
90
90
  readonly domainEvents: DomainEventBus<E, OrmSession<E>>;
91
- /** The relation change processor */
92
- readonly relationChanges: RelationChangeProcessor;
93
-
94
- private readonly interceptors: OrmInterceptor[];
95
- private saveGraphDefaults?: SaveGraphSessionOptions;
91
+ /** The relation change processor */
92
+ readonly relationChanges: RelationChangeProcessor;
93
+
94
+ private readonly interceptors: OrmInterceptor[];
95
+ private saveGraphDefaults?: SaveGraphSessionOptions;
96
96
 
97
97
  /**
98
98
  * Creates a new OrmSession instance.
@@ -150,9 +150,9 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
150
150
  * @param pk - The primary key value
151
151
  * @returns The entity or undefined if not found
152
152
  */
153
- getEntity(table: TableDef, pk: PrimaryKey): object | undefined {
154
- return this.unitOfWork.getEntity(table, pk);
155
- }
153
+ getEntity(table: TableDef, pk: PrimaryKey): object | undefined {
154
+ return this.unitOfWork.getEntity(table, pk);
155
+ }
156
156
 
157
157
  /**
158
158
  * Sets an entity in the identity map.
@@ -160,9 +160,9 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
160
160
  * @param pk - The primary key value
161
161
  * @param entity - The entity instance
162
162
  */
163
- setEntity(table: TableDef, pk: PrimaryKey, entity: object): void {
164
- this.unitOfWork.setEntity(table, pk, entity);
165
- }
163
+ setEntity(table: TableDef, pk: PrimaryKey, entity: object): void {
164
+ this.unitOfWork.setEntity(table, pk, entity);
165
+ }
166
166
 
167
167
  /**
168
168
  * Tracks a new entity.
@@ -170,9 +170,9 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
170
170
  * @param entity - The entity instance
171
171
  * @param pk - Optional primary key value
172
172
  */
173
- trackNew(table: TableDef, entity: object, pk?: PrimaryKey): void {
174
- this.unitOfWork.trackNew(table, entity, pk);
175
- }
173
+ trackNew(table: TableDef, entity: object, pk?: PrimaryKey): void {
174
+ this.unitOfWork.trackNew(table, entity, pk);
175
+ }
176
176
 
177
177
  /**
178
178
  * Tracks a managed entity.
@@ -180,25 +180,25 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
180
180
  * @param pk - The primary key value
181
181
  * @param entity - The entity instance
182
182
  */
183
- trackManaged(table: TableDef, pk: PrimaryKey, entity: object): void {
184
- this.unitOfWork.trackManaged(table, pk, entity);
185
- }
183
+ trackManaged(table: TableDef, pk: PrimaryKey, entity: object): void {
184
+ this.unitOfWork.trackManaged(table, pk, entity);
185
+ }
186
186
 
187
187
  /**
188
188
  * Marks an entity as dirty (modified).
189
189
  * @param entity - The entity to mark as dirty
190
190
  */
191
- markDirty(entity: object): void {
192
- this.unitOfWork.markDirty(entity);
193
- }
191
+ markDirty(entity: object): void {
192
+ this.unitOfWork.markDirty(entity);
193
+ }
194
194
 
195
195
  /**
196
196
  * Marks an entity as removed.
197
197
  * @param entity - The entity to mark as removed
198
198
  */
199
- markRemoved(entity: object): void {
200
- this.unitOfWork.markRemoved(entity);
201
- }
199
+ markRemoved(entity: object): void {
200
+ this.unitOfWork.markRemoved(entity);
201
+ }
202
202
 
203
203
  /**
204
204
  * Registers a relation change.
@@ -244,22 +244,22 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
244
244
  * @param type - The event type
245
245
  * @param handler - The event handler
246
246
  */
247
- registerDomainEventHandler<TType extends E['type']>(
248
- type: TType,
249
- handler: DomainEventHandler<Extract<E, { type: TType }>, OrmSession<E>>
250
- ): void {
251
- this.domainEvents.on(type, handler);
252
- }
253
-
254
- /**
255
- * Sets default options applied to all saveGraph calls for this session.
256
- * Per-call options override these defaults.
257
- * @param defaults - Default saveGraph options for the session
258
- */
259
- withSaveGraphDefaults(defaults: SaveGraphSessionOptions): this {
260
- this.saveGraphDefaults = { ...defaults };
261
- return this;
262
- }
247
+ registerDomainEventHandler<TType extends E['type']>(
248
+ type: TType,
249
+ handler: DomainEventHandler<Extract<E, { type: TType }>, OrmSession<E>>
250
+ ): void {
251
+ this.domainEvents.on(type, handler);
252
+ }
253
+
254
+ /**
255
+ * Sets default options applied to all saveGraph calls for this session.
256
+ * Per-call options override these defaults.
257
+ * @param defaults - Default saveGraph options for the session
258
+ */
259
+ withSaveGraphDefaults(defaults: SaveGraphSessionOptions): this {
260
+ this.saveGraphDefaults = { ...defaults };
261
+ return this;
262
+ }
263
263
 
264
264
  /**
265
265
  * Finds an entity by its primary key.
@@ -323,85 +323,85 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
323
323
  * @param options - Graph save options
324
324
  * @returns The root entity instance
325
325
  */
326
- async saveGraph<TCtor extends EntityConstructor<object>>(
327
- entityClass: TCtor,
328
- payload: SaveGraphInputPayload<InstanceType<TCtor>>,
329
- options?: SaveGraphSessionOptions
330
- ): Promise<InstanceType<TCtor>>;
331
- async saveGraph<TCtor extends EntityConstructor<object>>(
332
- entityClass: TCtor,
333
- payload: Record<string, unknown>,
334
- options?: SaveGraphSessionOptions
335
- ): Promise<InstanceType<TCtor>> {
336
- const resolved = this.resolveSaveGraphOptions(options);
337
- const { transactional = true, flush = false, ...graphOptions } = resolved;
338
- const execute = () => saveGraphInternal(this, entityClass, payload, graphOptions);
339
- if (!transactional) {
340
- const result = await execute();
341
- if (flush) {
342
- await this.flush();
343
- }
344
- return result;
345
- }
346
- return this.transaction(() => execute());
347
- }
348
-
349
- /**
350
- * Saves an entity graph and flushes immediately (defaults to transactional: false).
351
- * @param entityClass - Root entity constructor
352
- * @param payload - DTO payload containing column values and nested relations
353
- * @param options - Graph save options
354
- * @returns The root entity instance
355
- */
356
- async saveGraphAndFlush<TCtor extends EntityConstructor<object>>(
357
- entityClass: TCtor,
358
- payload: SaveGraphInputPayload<InstanceType<TCtor>>,
359
- options?: SaveGraphSessionOptions
360
- ): Promise<InstanceType<TCtor>> {
361
- const merged = { ...(options ?? {}), flush: true, transactional: options?.transactional ?? false };
362
- return this.saveGraph(entityClass, payload, merged);
363
- }
364
-
365
- /**
366
- * Updates an existing entity graph (requires a primary key in the payload).
367
- * @param entityClass - Root entity constructor
368
- * @param payload - DTO payload containing column values and nested relations
369
- * @param options - Graph save options
370
- * @returns The root entity instance or null if not found
371
- */
372
- async updateGraph<TCtor extends EntityConstructor<object>>(
373
- entityClass: TCtor,
374
- payload: SaveGraphInputPayload<InstanceType<TCtor>>,
375
- options?: SaveGraphSessionOptions
376
- ): Promise<InstanceType<TCtor> | null> {
377
- const table = getTableDefFromEntity(entityClass);
378
- if (!table) {
379
- throw new Error('Entity metadata has not been bootstrapped');
380
- }
381
- const primaryKey = findPrimaryKey(table);
382
- const pkValue = (payload as Record<string, unknown>)[primaryKey];
383
- if (pkValue === undefined || pkValue === null) {
384
- throw new Error(`updateGraph requires a primary key value for "${primaryKey}"`);
385
- }
386
-
387
- const resolved = this.resolveSaveGraphOptions(options);
388
- const { transactional = true, flush = false, ...graphOptions } = resolved;
389
- const execute = async (): Promise<InstanceType<TCtor> | null> => {
390
- const tracked = this.getEntity(table, pkValue as PrimaryKey) as InstanceType<TCtor> | undefined;
391
- const existing = tracked ?? await this.find(entityClass, pkValue);
392
- if (!existing) return null;
393
- return saveGraphInternal(this, entityClass, payload, graphOptions);
394
- };
395
-
396
- if (!transactional) {
397
- const result = await execute();
398
- if (result && flush) {
399
- await this.flush();
400
- }
401
- return result;
402
- }
403
- return this.transaction(() => execute());
404
- }
326
+ async saveGraph<TCtor extends EntityConstructor<object>>(
327
+ entityClass: TCtor,
328
+ payload: SaveGraphInputPayload<InstanceType<TCtor>>,
329
+ options?: SaveGraphSessionOptions
330
+ ): Promise<InstanceType<TCtor>>;
331
+ async saveGraph<TCtor extends EntityConstructor<object>>(
332
+ entityClass: TCtor,
333
+ payload: Record<string, unknown>,
334
+ options?: SaveGraphSessionOptions
335
+ ): Promise<InstanceType<TCtor>> {
336
+ const resolved = this.resolveSaveGraphOptions(options);
337
+ const { transactional = true, flush = false, ...graphOptions } = resolved;
338
+ const execute = () => saveGraphInternal(this, entityClass, payload, graphOptions);
339
+ if (!transactional) {
340
+ const result = await execute();
341
+ if (flush) {
342
+ await this.flush();
343
+ }
344
+ return result;
345
+ }
346
+ return this.transaction(() => execute());
347
+ }
348
+
349
+ /**
350
+ * Saves an entity graph and flushes immediately (defaults to transactional: false).
351
+ * @param entityClass - Root entity constructor
352
+ * @param payload - DTO payload containing column values and nested relations
353
+ * @param options - Graph save options
354
+ * @returns The root entity instance
355
+ */
356
+ async saveGraphAndFlush<TCtor extends EntityConstructor<object>>(
357
+ entityClass: TCtor,
358
+ payload: SaveGraphInputPayload<InstanceType<TCtor>>,
359
+ options?: SaveGraphSessionOptions
360
+ ): Promise<InstanceType<TCtor>> {
361
+ const merged = { ...(options ?? {}), flush: true, transactional: options?.transactional ?? false };
362
+ return this.saveGraph(entityClass, payload, merged);
363
+ }
364
+
365
+ /**
366
+ * Updates an existing entity graph (requires a primary key in the payload).
367
+ * @param entityClass - Root entity constructor
368
+ * @param payload - DTO payload containing column values and nested relations
369
+ * @param options - Graph save options
370
+ * @returns The root entity instance or null if not found
371
+ */
372
+ async updateGraph<TCtor extends EntityConstructor<object>>(
373
+ entityClass: TCtor,
374
+ payload: SaveGraphInputPayload<InstanceType<TCtor>>,
375
+ options?: SaveGraphSessionOptions
376
+ ): Promise<InstanceType<TCtor> | null> {
377
+ const table = getTableDefFromEntity(entityClass);
378
+ if (!table) {
379
+ throw new Error('Entity metadata has not been bootstrapped');
380
+ }
381
+ const primaryKey = findPrimaryKey(table);
382
+ const pkValue = (payload as Record<string, unknown>)[primaryKey];
383
+ if (pkValue === undefined || pkValue === null) {
384
+ throw new Error(`updateGraph requires a primary key value for "${primaryKey}"`);
385
+ }
386
+
387
+ const resolved = this.resolveSaveGraphOptions(options);
388
+ const { transactional = true, flush = false, ...graphOptions } = resolved;
389
+ const execute = async (): Promise<InstanceType<TCtor> | null> => {
390
+ const tracked = this.getEntity(table, pkValue as PrimaryKey) as InstanceType<TCtor> | undefined;
391
+ const existing = tracked ?? await this.find(entityClass, pkValue);
392
+ if (!existing) return null;
393
+ return saveGraphInternal(this, entityClass, payload, graphOptions);
394
+ };
395
+
396
+ if (!transactional) {
397
+ const result = await execute();
398
+ if (result && flush) {
399
+ await this.flush();
400
+ }
401
+ return result;
402
+ }
403
+ return this.transaction(() => execute());
404
+ }
405
405
 
406
406
  /**
407
407
  * Persists an entity (either inserts or updates).
@@ -420,7 +420,7 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
420
420
  const primaryKey = findPrimaryKey(table);
421
421
  const pkValue = (entity as Record<string, unknown>)[primaryKey];
422
422
  if (pkValue !== undefined && pkValue !== null) {
423
- this.trackManaged(table, pkValue as PrimaryKey, entity);
423
+ this.trackManaged(table, pkValue as PrimaryKey, entity);
424
424
  } else {
425
425
  this.trackNew(table, entity);
426
426
  }
@@ -476,7 +476,7 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
476
476
  * @returns The result of the function
477
477
  * @throws If the transaction fails
478
478
  */
479
- async transaction<T>(fn: (session: OrmSession<E>) => Promise<T>): Promise<T> {
479
+ async transaction<T>(fn: (session: OrmSession<E>) => Promise<T>): Promise<T> {
480
480
  // If the executor can't do transactions, just run and commit once.
481
481
  if (!this.executor.capabilities.transactions) {
482
482
  const result = await fn(this);
@@ -524,25 +524,25 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
524
524
  * Gets the hydration context.
525
525
  * @returns The hydration context
526
526
  */
527
- getHydrationContext(): HydrationContext<E> {
528
- return {
529
- identityMap: this.identityMap,
530
- unitOfWork: this.unitOfWork,
531
- domainEvents: this.domainEvents,
532
- relationChanges: this.relationChanges,
533
- entityContext: this
534
- };
535
- }
536
-
537
- /**
538
- * Merges session defaults with per-call saveGraph options.
539
- * @param options - Per-call saveGraph options
540
- * @returns Combined options with per-call values taking precedence
541
- */
542
- private resolveSaveGraphOptions(options?: SaveGraphSessionOptions): SaveGraphSessionOptions {
543
- return { ...(this.saveGraphDefaults ?? {}), ...(options ?? {}) };
544
- }
545
- }
527
+ getHydrationContext(): HydrationContext<E> {
528
+ return {
529
+ identityMap: this.identityMap,
530
+ unitOfWork: this.unitOfWork,
531
+ domainEvents: this.domainEvents,
532
+ relationChanges: this.relationChanges,
533
+ entityContext: this
534
+ };
535
+ }
536
+
537
+ /**
538
+ * Merges session defaults with per-call saveGraph options.
539
+ * @param options - Per-call saveGraph options
540
+ * @returns Combined options with per-call values taking precedence
541
+ */
542
+ private resolveSaveGraphOptions(options?: SaveGraphSessionOptions): SaveGraphSessionOptions {
543
+ return { ...(this.saveGraphDefaults ?? {}), ...(options ?? {}) };
544
+ }
545
+ }
546
546
 
547
547
  const buildRelationChangeEntry = (
548
548
  root: unknown,
@@ -78,7 +78,7 @@ export class RelationChangeProcessor {
78
78
  const target = entry.change.entity;
79
79
  if (!target) return;
80
80
 
81
- const tracked = this.unitOfWork.findTracked(target as object);
81
+ const tracked = this.unitOfWork.findTracked(target as object);
82
82
  if (!tracked) return;
83
83
 
84
84
  const localKey = relation.localKey || findPrimaryKey(entry.rootTable);
@@ -105,7 +105,7 @@ export class RelationChangeProcessor {
105
105
  const target = entry.change.entity;
106
106
  if (!target) return;
107
107
 
108
- const tracked = this.unitOfWork.findTracked(target as object);
108
+ const tracked = this.unitOfWork.findTracked(target as object);
109
109
  if (!tracked) return;
110
110
 
111
111
  const localKey = relation.localKey || findPrimaryKey(entry.rootTable);
@@ -154,7 +154,7 @@ export class RelationChangeProcessor {
154
154
  await this.deletePivotRow(relation, rootId, targetId);
155
155
 
156
156
  if (relation.cascade === 'all' || relation.cascade === 'remove') {
157
- this.unitOfWork.markRemoved(entry.change.entity as object);
157
+ this.unitOfWork.markRemoved(entry.change.entity as object);
158
158
  }
159
159
  }
160
160
  }
@@ -20,11 +20,11 @@ export enum EntityStatus {
20
20
  /**
21
21
  * Represents an entity being tracked by the ORM
22
22
  */
23
- export interface TrackedEntity {
24
- /** The table definition this entity belongs to */
25
- table: TableDef;
26
- /** The actual entity instance */
27
- entity: object;
23
+ export interface TrackedEntity {
24
+ /** The table definition this entity belongs to */
25
+ table: TableDef;
26
+ /** The actual entity instance */
27
+ entity: object;
28
28
  /** Primary key value of the entity */
29
29
  pk: string | number | null;
30
30
  /** Current status of the entity */
@@ -198,13 +198,12 @@ export class UnitOfWork {
198
198
 
199
199
  const payload = this.extractColumns(tracked.table, tracked.entity as Record<string, unknown>);
200
200
  let builder = new InsertQueryBuilder(tracked.table).values(payload as Record<string, ValueOperandInput>);
201
- if (this.dialect.supportsReturning()) {
202
- builder = builder.returning(...this.getReturningColumns(tracked.table));
203
- }
204
- const compiled = builder.compile(this.dialect);
205
- const results = await this.executeCompiled(compiled);
206
- this.applyReturningResults(tracked, results);
207
- this.applyInsertId(tracked, results);
201
+ if (this.dialect.supportsReturning()) {
202
+ builder = builder.returning(...this.getReturningColumns(tracked.table));
203
+ }
204
+ const compiled = builder.compile(this.dialect);
205
+ const results = await this.executeCompiled(compiled);
206
+ this.applyReturningResults(tracked, results);
208
207
 
209
208
  tracked.status = EntityStatus.Managed;
210
209
  tracked.original = this.createSnapshot(tracked.table, tracked.entity as Record<string, unknown>);
@@ -345,29 +344,18 @@ export class UnitOfWork {
345
344
  * @param tracked - The tracked entity
346
345
  * @param results - Query results
347
346
  */
348
- private applyReturningResults(tracked: TrackedEntity, results: QueryResult[]): void {
349
- if (!this.dialect.supportsReturning()) return;
350
- const first = results[0];
351
- if (!first || first.values.length === 0) return;
347
+ private applyReturningResults(tracked: TrackedEntity, results: QueryResult[]): void {
348
+ if (!this.dialect.supportsReturning()) return;
349
+ const first = results[0];
350
+ if (!first || first.values.length === 0) return;
352
351
 
353
352
  const row = first.values[0];
354
353
  for (let i = 0; i < first.columns.length; i++) {
355
354
  const columnName = this.normalizeColumnName(first.columns[i]);
356
355
  if (!(columnName in tracked.table.columns)) continue;
357
- (tracked.entity as Record<string, unknown>)[columnName] = row[i];
358
- }
359
- }
360
-
361
- private applyInsertId(tracked: TrackedEntity, results: QueryResult[]): void {
362
- if (this.dialect.supportsReturning()) return;
363
- if (tracked.pk != null) return;
364
- const pkName = findPrimaryKey(tracked.table);
365
- const pkColumn = tracked.table.columns[pkName];
366
- if (!pkColumn?.autoIncrement) return;
367
- const insertId = results.find(result => typeof result.insertId === 'number')?.insertId;
368
- if (insertId == null) return;
369
- (tracked.entity as Record<string, unknown>)[pkName] = insertId;
370
- }
356
+ (tracked.entity as Record<string, unknown>)[columnName] = row[i];
357
+ }
358
+ }
371
359
 
372
360
  /**
373
361
  * Normalizes a column name by removing quotes and table prefixes.