metal-orm 1.0.63 → 1.0.65

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.
@@ -1,25 +1,25 @@
1
- import { TableDef } from '../schema/table.js';
2
- import { EntityInstance } from '../schema/types.js';
3
- import { RelationKinds } from '../schema/relation.js';
4
- import { hydrateRows } from './hydration.js';
5
- import { OrmSession } from './orm-session.ts';
6
- import { SelectQueryBuilder } from '../query-builder/select.js';
7
- import {
8
- createEntityProxy,
9
- createEntityFromRow,
10
- relationLoaderCache
11
- } from './entity.js';
12
- import { EntityContext } from './entity-context.js';
13
- import { ExecutionContext } from './execution-context.js';
14
- import { HydrationContext } from './hydration-context.js';
15
- import { RelationIncludeOptions } from '../query-builder/relation-types.js';
16
- import { getEntityMeta, RelationKey } from './entity-meta.js';
17
- import {
18
- loadHasManyRelation,
19
- loadHasOneRelation,
20
- loadBelongsToRelation,
21
- loadBelongsToManyRelation
22
- } from './lazy-batch.js';
1
+ import { TableDef } from '../schema/table.js';
2
+ import { EntityInstance } from '../schema/types.js';
3
+ import { RelationKinds } from '../schema/relation.js';
4
+ import { hydrateRows } from './hydration.js';
5
+ import { OrmSession } from './orm-session.ts';
6
+ import { SelectQueryBuilder } from '../query-builder/select.js';
7
+ import {
8
+ createEntityProxy,
9
+ createEntityFromRow,
10
+ relationLoaderCache
11
+ } from './entity.js';
12
+ import { EntityContext } from './entity-context.js';
13
+ import { ExecutionContext } from './execution-context.js';
14
+ import { HydrationContext } from './hydration-context.js';
15
+ import { RelationIncludeOptions } from '../query-builder/relation-types.js';
16
+ import { getEntityMeta, RelationKey } from './entity-meta.js';
17
+ import {
18
+ loadHasManyRelation,
19
+ loadHasOneRelation,
20
+ loadBelongsToRelation,
21
+ loadBelongsToManyRelation
22
+ } from './lazy-batch.js';
23
23
 
24
24
  type Row = Record<string, unknown>;
25
25
 
@@ -38,152 +38,152 @@ const flattenResults = (results: { columns: string[]; values: unknown[][] }[]):
38
38
  return rows;
39
39
  };
40
40
 
41
- const executeWithContexts = async <TTable extends TableDef>(
42
- execCtx: ExecutionContext,
43
- entityCtx: EntityContext,
44
- qb: SelectQueryBuilder<unknown, TTable>
45
- ): Promise<EntityInstance<TTable>[]> => {
46
- const ast = qb.getAST();
47
- const compiled = execCtx.dialect.compileSelect(ast);
48
- const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
49
- const rows = flattenResults(executed);
50
- const lazyRelations = qb.getLazyRelations() as RelationKey<TTable>[];
51
- const lazyRelationOptions = qb.getLazyRelationOptions();
52
-
53
- if (ast.setOps && ast.setOps.length > 0) {
54
- const proxies = rows.map(row => createEntityProxy(entityCtx, qb.getTable(), row, lazyRelations, lazyRelationOptions));
55
- await loadLazyRelationsForTable(entityCtx, qb.getTable(), lazyRelations, lazyRelationOptions);
56
- return proxies;
57
- }
58
-
59
- const hydrated = hydrateRows(rows, qb.getHydrationPlan());
60
- const entities = hydrated.map(row => createEntityFromRow(entityCtx, qb.getTable(), row, lazyRelations, lazyRelationOptions));
61
- await loadLazyRelationsForTable(entityCtx, qb.getTable(), lazyRelations, lazyRelationOptions);
62
- return entities;
63
- };
64
-
65
- const executePlainWithContexts = async <TTable extends TableDef>(
66
- execCtx: ExecutionContext,
67
- qb: SelectQueryBuilder<unknown, TTable>
68
- ): Promise<Record<string, unknown>[]> => {
69
- const ast = qb.getAST();
70
- const compiled = execCtx.dialect.compileSelect(ast);
71
- const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
72
- const rows = flattenResults(executed);
73
-
74
- if (ast.setOps && ast.setOps.length > 0) {
75
- return rows;
76
- }
77
-
78
- return hydrateRows(rows, qb.getHydrationPlan());
79
- };
80
-
81
- /**
82
- * Executes a hydrated query using the ORM session.
83
- * @template TTable - The table type
84
- * @param session - The ORM session
85
- * @param qb - The select query builder
41
+ const executeWithContexts = async <TTable extends TableDef>(
42
+ execCtx: ExecutionContext,
43
+ entityCtx: EntityContext,
44
+ qb: SelectQueryBuilder<unknown, TTable>
45
+ ): Promise<EntityInstance<TTable>[]> => {
46
+ const ast = qb.getAST();
47
+ const compiled = execCtx.dialect.compileSelect(ast);
48
+ const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
49
+ const rows = flattenResults(executed);
50
+ const lazyRelations = qb.getLazyRelations() as RelationKey<TTable>[];
51
+ const lazyRelationOptions = qb.getLazyRelationOptions();
52
+
53
+ if (ast.setOps && ast.setOps.length > 0) {
54
+ const proxies = rows.map(row => createEntityProxy(entityCtx, qb.getTable(), row, lazyRelations, lazyRelationOptions));
55
+ await loadLazyRelationsForTable(entityCtx, qb.getTable(), lazyRelations, lazyRelationOptions);
56
+ return proxies;
57
+ }
58
+
59
+ const hydrated = hydrateRows(rows, qb.getHydrationPlan());
60
+ const entities = hydrated.map(row => createEntityFromRow(entityCtx, qb.getTable(), row, lazyRelations, lazyRelationOptions));
61
+ await loadLazyRelationsForTable(entityCtx, qb.getTable(), lazyRelations, lazyRelationOptions);
62
+ return entities;
63
+ };
64
+
65
+ const executePlainWithContexts = async <TTable extends TableDef>(
66
+ execCtx: ExecutionContext,
67
+ qb: SelectQueryBuilder<unknown, TTable>
68
+ ): Promise<Record<string, unknown>[]> => {
69
+ const ast = qb.getAST();
70
+ const compiled = execCtx.dialect.compileSelect(ast);
71
+ const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
72
+ const rows = flattenResults(executed);
73
+
74
+ if (ast.setOps && ast.setOps.length > 0) {
75
+ return rows;
76
+ }
77
+
78
+ return hydrateRows(rows, qb.getHydrationPlan());
79
+ };
80
+
81
+ /**
82
+ * Executes a hydrated query using the ORM session.
83
+ * @template TTable - The table type
84
+ * @param session - The ORM session
85
+ * @param qb - The select query builder
86
86
  * @returns Promise resolving to array of entity instances
87
87
  */
88
- export async function executeHydrated<TTable extends TableDef>(
89
- session: OrmSession,
90
- qb: SelectQueryBuilder<unknown, TTable>
91
- ): Promise<EntityInstance<TTable>[]> {
92
- return executeWithContexts(session.getExecutionContext(), session, qb);
93
- }
94
-
95
- /**
96
- * Executes a hydrated query and returns plain row objects (no entity proxies).
97
- * @template TTable - The table type
98
- * @param session - The ORM session
99
- * @param qb - The select query builder
100
- * @returns Promise resolving to array of plain row objects
101
- */
102
- export async function executeHydratedPlain<TTable extends TableDef>(
103
- session: OrmSession,
104
- qb: SelectQueryBuilder<unknown, TTable>
105
- ): Promise<Record<string, unknown>[]> {
106
- return executePlainWithContexts(session.getExecutionContext(), qb);
107
- }
108
-
109
- /**
110
- * Executes a hydrated query using execution and hydration contexts.
111
- * @template TTable - The table type
112
- * @param _execCtx - The execution context (unused)
113
- * @param hydCtx - The hydration context
88
+ export async function executeHydrated<TTable extends TableDef>(
89
+ session: OrmSession,
90
+ qb: SelectQueryBuilder<unknown, TTable>
91
+ ): Promise<EntityInstance<TTable>[]> {
92
+ return executeWithContexts(session.getExecutionContext(), session, qb);
93
+ }
94
+
95
+ /**
96
+ * Executes a hydrated query and returns plain row objects (no entity proxies).
97
+ * @template TTable - The table type
98
+ * @param session - The ORM session
99
+ * @param qb - The select query builder
100
+ * @returns Promise resolving to array of plain row objects
101
+ */
102
+ export async function executeHydratedPlain<TTable extends TableDef>(
103
+ session: OrmSession,
104
+ qb: SelectQueryBuilder<unknown, TTable>
105
+ ): Promise<Record<string, unknown>[]> {
106
+ return executePlainWithContexts(session.getExecutionContext(), qb);
107
+ }
108
+
109
+ /**
110
+ * Executes a hydrated query using execution and hydration contexts.
111
+ * @template TTable - The table type
112
+ * @param _execCtx - The execution context (unused)
113
+ * @param hydCtx - The hydration context
114
114
  * @param qb - The select query builder
115
115
  * @returns Promise resolving to array of entity instances
116
116
  */
117
- export async function executeHydratedWithContexts<TTable extends TableDef>(
118
- execCtx: ExecutionContext,
119
- hydCtx: HydrationContext,
120
- qb: SelectQueryBuilder<unknown, TTable>
121
- ): Promise<EntityInstance<TTable>[]> {
122
- const entityCtx = hydCtx.entityContext;
123
- if (!entityCtx) {
124
- throw new Error('Hydration context is missing an EntityContext');
125
- }
126
- return executeWithContexts(execCtx, entityCtx, qb);
127
- }
128
-
129
- /**
130
- * Executes a hydrated query using execution context and returns plain row objects.
131
- * @template TTable - The table type
132
- * @param execCtx - The execution context
133
- * @param qb - The select query builder
134
- * @returns Promise resolving to array of plain row objects
135
- */
136
- export async function executeHydratedPlainWithContexts<TTable extends TableDef>(
137
- execCtx: ExecutionContext,
138
- qb: SelectQueryBuilder<unknown, TTable>
139
- ): Promise<Record<string, unknown>[]> {
140
- return executePlainWithContexts(execCtx, qb);
141
- }
142
-
143
- const loadLazyRelationsForTable = async <TTable extends TableDef>(
144
- ctx: EntityContext,
145
- table: TTable,
146
- lazyRelations: RelationKey<TTable>[],
147
- lazyRelationOptions: Map<string, RelationIncludeOptions>
148
- ): Promise<void> => {
149
- if (!lazyRelations.length) return;
150
-
151
- const tracked = ctx.getEntitiesForTable(table);
152
- if (!tracked.length) return;
153
-
154
- const meta = getEntityMeta(tracked[0].entity);
155
- if (!meta) return;
156
-
157
- for (const relationName of lazyRelations) {
158
- const relation = table.relations[relationName as string];
159
- if (!relation) continue;
160
- const key = relationName as string;
161
- const options = lazyRelationOptions.get(key);
162
- if (!options) {
163
- continue;
164
- }
165
-
166
- switch (relation.type) {
167
- case RelationKinds.HasOne:
168
- await relationLoaderCache(meta, key, () =>
169
- loadHasOneRelation(ctx, table, key, relation, options)
170
- );
171
- break;
172
- case RelationKinds.HasMany:
173
- await relationLoaderCache(meta, key, () =>
174
- loadHasManyRelation(ctx, table, key, relation, options)
175
- );
176
- break;
177
- case RelationKinds.BelongsTo:
178
- await relationLoaderCache(meta, key, () =>
179
- loadBelongsToRelation(ctx, table, key, relation, options)
180
- );
181
- break;
182
- case RelationKinds.BelongsToMany:
183
- await relationLoaderCache(meta, key, () =>
184
- loadBelongsToManyRelation(ctx, table, key, relation, options)
185
- );
186
- break;
187
- }
188
- }
189
- };
117
+ export async function executeHydratedWithContexts<TTable extends TableDef>(
118
+ execCtx: ExecutionContext,
119
+ hydCtx: HydrationContext,
120
+ qb: SelectQueryBuilder<unknown, TTable>
121
+ ): Promise<EntityInstance<TTable>[]> {
122
+ const entityCtx = hydCtx.entityContext;
123
+ if (!entityCtx) {
124
+ throw new Error('Hydration context is missing an EntityContext');
125
+ }
126
+ return executeWithContexts(execCtx, entityCtx, qb);
127
+ }
128
+
129
+ /**
130
+ * Executes a hydrated query using execution context and returns plain row objects.
131
+ * @template TTable - The table type
132
+ * @param execCtx - The execution context
133
+ * @param qb - The select query builder
134
+ * @returns Promise resolving to array of plain row objects
135
+ */
136
+ export async function executeHydratedPlainWithContexts<TTable extends TableDef>(
137
+ execCtx: ExecutionContext,
138
+ qb: SelectQueryBuilder<unknown, TTable>
139
+ ): Promise<Record<string, unknown>[]> {
140
+ return executePlainWithContexts(execCtx, qb);
141
+ }
142
+
143
+ const loadLazyRelationsForTable = async <TTable extends TableDef>(
144
+ ctx: EntityContext,
145
+ table: TTable,
146
+ lazyRelations: RelationKey<TTable>[],
147
+ lazyRelationOptions: Map<string, RelationIncludeOptions>
148
+ ): Promise<void> => {
149
+ if (!lazyRelations.length) return;
150
+
151
+ const tracked = ctx.getEntitiesForTable(table);
152
+ if (!tracked.length) return;
153
+
154
+ const meta = getEntityMeta(tracked[0].entity);
155
+ if (!meta) return;
156
+
157
+ for (const relationName of lazyRelations) {
158
+ const relation = table.relations[relationName as string];
159
+ if (!relation) continue;
160
+ const key = relationName as string;
161
+ const options = lazyRelationOptions.get(key);
162
+ if (!options) {
163
+ continue;
164
+ }
165
+
166
+ switch (relation.type) {
167
+ case RelationKinds.HasOne:
168
+ await relationLoaderCache(meta, key, () =>
169
+ loadHasOneRelation(ctx, table, key, relation, options)
170
+ );
171
+ break;
172
+ case RelationKinds.HasMany:
173
+ await relationLoaderCache(meta, key, () =>
174
+ loadHasManyRelation(ctx, table, key, relation, options)
175
+ );
176
+ break;
177
+ case RelationKinds.BelongsTo:
178
+ await relationLoaderCache(meta, key, () =>
179
+ loadBelongsToRelation(ctx, table, key, relation, options)
180
+ );
181
+ break;
182
+ case RelationKinds.BelongsToMany:
183
+ await relationLoaderCache(meta, key, () =>
184
+ loadBelongsToManyRelation(ctx, table, key, relation, options)
185
+ );
186
+ break;
187
+ }
188
+ }
189
+ };
@@ -18,7 +18,7 @@ export class IdentityMap {
18
18
  * @param pk The primary key value.
19
19
  * @returns The entity instance if found, undefined otherwise.
20
20
  */
21
- getEntity(table: TableDef, pk: string | number): unknown | undefined {
21
+ getEntity(table: TableDef, pk: string | number): object | undefined {
22
22
  const bucket = this.buckets.get(table.name);
23
23
  return bucket?.get(this.toIdentityKey(pk))?.entity;
24
24
  }
@@ -71,7 +71,7 @@ export const toKey = (value: unknown): string => (value === null || value === un
71
71
  export const collectKeysFromRoots = (roots: EntityTracker[], key: string): Set<unknown> => {
72
72
  const collected = new Set<unknown>();
73
73
  for (const tracked of roots) {
74
- const value = tracked.entity[key];
74
+ const value = (tracked.entity as Record<string, unknown>)[key];
75
75
  if (value !== null && value !== undefined) {
76
76
  collected.add(value);
77
77
  }
@@ -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 } from './entity-context.js';
21
+ import type { EntityContext, PrimaryKey } from './entity-context.js';
22
22
  import {
23
23
  DomainEvent,
24
24
  OrmDomainEvent,
@@ -27,10 +27,10 @@ import {
27
27
  RelationKey,
28
28
  TrackedEntity
29
29
  } from './runtime-types.js';
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';
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';
34
34
 
35
35
  /**
36
36
  * Interface for ORM interceptors that allow hooking into the flush lifecycle.
@@ -142,9 +142,9 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
142
142
  * @param pk - The primary key value
143
143
  * @returns The entity or undefined if not found
144
144
  */
145
- getEntity(table: TableDef, pk: unknown): unknown | undefined {
146
- return this.unitOfWork.getEntity(table, pk as string | number);
147
- }
145
+ getEntity(table: TableDef, pk: PrimaryKey): object | undefined {
146
+ return this.unitOfWork.getEntity(table, pk);
147
+ }
148
148
 
149
149
  /**
150
150
  * Sets an entity in the identity map.
@@ -152,9 +152,9 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
152
152
  * @param pk - The primary key value
153
153
  * @param entity - The entity instance
154
154
  */
155
- setEntity(table: TableDef, pk: unknown, entity: unknown): void {
156
- this.unitOfWork.setEntity(table, pk as string | number, entity);
157
- }
155
+ setEntity(table: TableDef, pk: PrimaryKey, entity: object): void {
156
+ this.unitOfWork.setEntity(table, pk, entity);
157
+ }
158
158
 
159
159
  /**
160
160
  * Tracks a new entity.
@@ -162,9 +162,9 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
162
162
  * @param entity - The entity instance
163
163
  * @param pk - Optional primary key value
164
164
  */
165
- trackNew(table: TableDef, entity: unknown, pk?: unknown): void {
166
- this.unitOfWork.trackNew(table, entity, pk as string | number);
167
- }
165
+ trackNew(table: TableDef, entity: object, pk?: PrimaryKey): void {
166
+ this.unitOfWork.trackNew(table, entity, pk);
167
+ }
168
168
 
169
169
  /**
170
170
  * Tracks a managed entity.
@@ -172,25 +172,25 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
172
172
  * @param pk - The primary key value
173
173
  * @param entity - The entity instance
174
174
  */
175
- trackManaged(table: TableDef, pk: unknown, entity: unknown): void {
176
- this.unitOfWork.trackManaged(table, pk as string | number, entity);
177
- }
175
+ trackManaged(table: TableDef, pk: PrimaryKey, entity: object): void {
176
+ this.unitOfWork.trackManaged(table, pk, entity);
177
+ }
178
178
 
179
179
  /**
180
180
  * Marks an entity as dirty (modified).
181
181
  * @param entity - The entity to mark as dirty
182
182
  */
183
- markDirty(entity: unknown): void {
184
- this.unitOfWork.markDirty(entity);
185
- }
183
+ markDirty(entity: object): void {
184
+ this.unitOfWork.markDirty(entity);
185
+ }
186
186
 
187
187
  /**
188
188
  * Marks an entity as removed.
189
189
  * @param entity - The entity to mark as removed
190
190
  */
191
- markRemoved(entity: unknown): void {
192
- this.unitOfWork.markRemoved(entity);
193
- }
191
+ markRemoved(entity: object): void {
192
+ this.unitOfWork.markRemoved(entity);
193
+ }
194
194
 
195
195
  /**
196
196
  * Registers a relation change.
@@ -298,30 +298,30 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
298
298
  return executeHydrated(this, qb);
299
299
  }
300
300
 
301
- /**
302
- * Saves an entity graph (root + nested relations) based on a DTO-like payload.
303
- * @param entityClass - Root entity constructor
304
- * @param payload - DTO payload containing column values and nested relations
305
- * @param options - Graph save options
306
- * @returns The root entity instance
307
- */
308
- async saveGraph<TCtor extends EntityConstructor<object>>(
309
- entityClass: TCtor,
310
- payload: SaveGraphInputPayload<InstanceType<TCtor>>,
311
- options?: SaveGraphOptions & { transactional?: boolean }
312
- ): Promise<InstanceType<TCtor>>;
313
- async saveGraph<TCtor extends EntityConstructor<object>>(
314
- entityClass: TCtor,
315
- payload: Record<string, unknown>,
316
- options?: SaveGraphOptions & { transactional?: boolean }
317
- ): Promise<InstanceType<TCtor>> {
318
- const { transactional = true, ...graphOptions } = options ?? {};
319
- const execute = () => saveGraphInternal(this, entityClass, payload, graphOptions);
320
- if (!transactional) {
321
- return execute();
322
- }
323
- return this.transaction(() => execute());
324
- }
301
+ /**
302
+ * Saves an entity graph (root + nested relations) based on a DTO-like payload.
303
+ * @param entityClass - Root entity constructor
304
+ * @param payload - DTO payload containing column values and nested relations
305
+ * @param options - Graph save options
306
+ * @returns The root entity instance
307
+ */
308
+ async saveGraph<TCtor extends EntityConstructor<object>>(
309
+ entityClass: TCtor,
310
+ payload: SaveGraphInputPayload<InstanceType<TCtor>>,
311
+ options?: SaveGraphOptions & { transactional?: boolean }
312
+ ): Promise<InstanceType<TCtor>>;
313
+ async saveGraph<TCtor extends EntityConstructor<object>>(
314
+ entityClass: TCtor,
315
+ payload: Record<string, unknown>,
316
+ options?: SaveGraphOptions & { transactional?: boolean }
317
+ ): Promise<InstanceType<TCtor>> {
318
+ const { transactional = true, ...graphOptions } = options ?? {};
319
+ const execute = () => saveGraphInternal(this, entityClass, payload, graphOptions);
320
+ if (!transactional) {
321
+ return execute();
322
+ }
323
+ return this.transaction(() => execute());
324
+ }
325
325
 
326
326
  /**
327
327
  * Persists an entity (either inserts or updates).
@@ -340,7 +340,7 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
340
340
  const primaryKey = findPrimaryKey(table);
341
341
  const pkValue = (entity as Record<string, unknown>)[primaryKey];
342
342
  if (pkValue !== undefined && pkValue !== null) {
343
- this.trackManaged(table, pkValue, entity);
343
+ this.trackManaged(table, pkValue as PrimaryKey, entity);
344
344
  } else {
345
345
  this.trackNew(table, entity);
346
346
  }
@@ -354,12 +354,12 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
354
354
  this.markRemoved(entity);
355
355
  }
356
356
 
357
- /**
358
- * Flushes pending changes to the database without session hooks, relation processing, or domain events.
359
- */
360
- async flush(): Promise<void> {
361
- await this.unitOfWork.flush();
362
- }
357
+ /**
358
+ * Flushes pending changes to the database without session hooks, relation processing, or domain events.
359
+ */
360
+ async flush(): Promise<void> {
361
+ await this.unitOfWork.flush();
362
+ }
363
363
 
364
364
  /**
365
365
  * Flushes pending changes with interceptors and relation processing.
@@ -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);
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);
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);
157
+ this.unitOfWork.markRemoved(entry.change.entity as object);
158
158
  }
159
159
  }
160
160
  }
@@ -125,7 +125,7 @@ export class DefaultHasManyCollection<TChild> implements HasManyCollection<TChil
125
125
  attach(entity: TChild): void {
126
126
  const keyValue = this.root[this.localKey];
127
127
  (entity as Record<string, unknown>)[this.relation.foreignKey] = keyValue;
128
- this.ctx.markDirty(entity);
128
+ this.ctx.markDirty(entity as object);
129
129
  this.items.push(entity);
130
130
  this.ctx.registerRelationChange(
131
131
  this.root,
@@ -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: unknown;
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 */