metal-orm 1.0.41 → 1.0.43

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 (87) hide show
  1. package/README.md +74 -20
  2. package/dist/index.cjs +180 -74
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +142 -96
  5. package/dist/index.d.ts +142 -96
  6. package/dist/index.js +177 -74
  7. package/dist/index.js.map +1 -1
  8. package/package.json +8 -2
  9. package/scripts/run-eslint.mjs +34 -0
  10. package/src/codegen/typescript.ts +32 -15
  11. package/src/core/ast/builders.ts +7 -2
  12. package/src/core/ast/expression-builders.ts +0 -2
  13. package/src/core/ast/expression-nodes.ts +14 -5
  14. package/src/core/ast/expression-visitor.ts +11 -8
  15. package/src/core/ast/expression.ts +2 -2
  16. package/src/core/ast/join-node.ts +1 -1
  17. package/src/core/ast/query.ts +6 -6
  18. package/src/core/ast/window-functions.ts +10 -2
  19. package/src/core/ddl/dialects/base-schema-dialect.ts +30 -3
  20. package/src/core/ddl/dialects/mssql-schema-dialect.ts +4 -0
  21. package/src/core/ddl/dialects/mysql-schema-dialect.ts +2 -0
  22. package/src/core/ddl/dialects/postgres-schema-dialect.ts +13 -1
  23. package/src/core/ddl/dialects/render-reference.test.ts +69 -0
  24. package/src/core/ddl/dialects/sqlite-schema-dialect.ts +9 -0
  25. package/src/core/ddl/introspect/mssql.ts +42 -8
  26. package/src/core/ddl/introspect/mysql.ts +30 -6
  27. package/src/core/ddl/introspect/postgres.ts +88 -34
  28. package/src/core/ddl/introspect/run-select.ts +6 -4
  29. package/src/core/ddl/introspect/sqlite.ts +56 -11
  30. package/src/core/ddl/introspect/types.ts +0 -1
  31. package/src/core/ddl/introspect/utils.ts +3 -3
  32. package/src/core/ddl/schema-dialect.ts +1 -0
  33. package/src/core/ddl/schema-generator.ts +4 -12
  34. package/src/core/ddl/sql-writing.ts +4 -4
  35. package/src/core/dialect/abstract.ts +18 -6
  36. package/src/core/dialect/base/function-table-formatter.ts +3 -2
  37. package/src/core/dialect/base/join-compiler.ts +5 -3
  38. package/src/core/dialect/base/returning-strategy.ts +1 -0
  39. package/src/core/dialect/base/sql-dialect.ts +3 -3
  40. package/src/core/dialect/mssql/functions.ts +24 -25
  41. package/src/core/dialect/mssql/index.ts +1 -4
  42. package/src/core/dialect/mysql/functions.ts +0 -1
  43. package/src/core/dialect/postgres/functions.ts +33 -34
  44. package/src/core/dialect/postgres/index.ts +1 -0
  45. package/src/core/dialect/sqlite/functions.ts +18 -19
  46. package/src/core/dialect/sqlite/index.ts +2 -0
  47. package/src/core/execution/db-executor.ts +1 -1
  48. package/src/core/execution/executors/mysql-executor.ts +2 -2
  49. package/src/core/execution/executors/postgres-executor.ts +1 -1
  50. package/src/core/execution/pooling/pool.ts +2 -0
  51. package/src/core/functions/datetime.ts +1 -1
  52. package/src/core/functions/numeric.ts +1 -1
  53. package/src/core/functions/text.ts +1 -1
  54. package/src/decorators/bootstrap.ts +27 -8
  55. package/src/decorators/column.ts +3 -11
  56. package/src/decorators/decorator-metadata.ts +3 -9
  57. package/src/decorators/entity.ts +21 -5
  58. package/src/decorators/relations.ts +2 -11
  59. package/src/orm/entity-context.ts +8 -8
  60. package/src/orm/entity-meta.ts +8 -8
  61. package/src/orm/entity-metadata.ts +11 -9
  62. package/src/orm/entity.ts +28 -29
  63. package/src/orm/execute.ts +4 -4
  64. package/src/orm/hydration.ts +42 -39
  65. package/src/orm/identity-map.ts +1 -1
  66. package/src/orm/lazy-batch.ts +9 -9
  67. package/src/orm/orm-session.ts +24 -23
  68. package/src/orm/orm.ts +2 -5
  69. package/src/orm/relation-change-processor.ts +12 -11
  70. package/src/orm/relations/belongs-to.ts +11 -11
  71. package/src/orm/relations/has-many.ts +10 -10
  72. package/src/orm/relations/has-one.ts +8 -7
  73. package/src/orm/relations/many-to-many.ts +13 -13
  74. package/src/orm/runtime-types.ts +4 -4
  75. package/src/orm/save-graph.ts +31 -25
  76. package/src/orm/unit-of-work.ts +17 -17
  77. package/src/query-builder/delete.ts +4 -3
  78. package/src/query-builder/hydration-manager.ts +6 -5
  79. package/src/query-builder/insert.ts +12 -8
  80. package/src/query-builder/query-ast-service.ts +2 -2
  81. package/src/query-builder/raw-column-parser.ts +2 -1
  82. package/src/query-builder/select-helpers.ts +2 -2
  83. package/src/query-builder/select.ts +31 -31
  84. package/src/query-builder/update.ts +4 -3
  85. package/src/schema/column.ts +26 -26
  86. package/src/schema/table.ts +239 -115
  87. package/src/schema/types.ts +22 -22
@@ -8,23 +8,23 @@ export interface EntityContext {
8
8
  dialect: Dialect;
9
9
  executor: DbExecutor;
10
10
 
11
- getEntity(table: TableDef, pk: any): any;
12
- setEntity(table: TableDef, pk: any, entity: any): void;
11
+ getEntity(table: TableDef, pk: unknown): unknown;
12
+ setEntity(table: TableDef, pk: unknown, entity: unknown): void;
13
13
 
14
- trackNew(table: TableDef, entity: any, pk?: any): void;
15
- trackManaged(table: TableDef, pk: any, entity: any): void;
14
+ trackNew(table: TableDef, entity: unknown, pk?: unknown): void;
15
+ trackManaged(table: TableDef, pk: unknown, entity: unknown): void;
16
16
 
17
- markDirty(entity: any): void;
18
- markRemoved(entity: any): void;
17
+ markDirty(entity: unknown): void;
18
+ markRemoved(entity: unknown): void;
19
19
 
20
20
  getEntitiesForTable(table: TableDef): TrackedEntity[];
21
21
 
22
22
  registerRelationChange(
23
- root: any,
23
+ root: unknown,
24
24
  relationKey: RelationKey,
25
25
  rootTable: TableDef,
26
26
  relationName: string,
27
27
  relation: RelationDef,
28
- change: RelationChange<any>
28
+ change: RelationChange<unknown>
29
29
  ): void;
30
30
  }
@@ -21,9 +21,9 @@ export interface EntityMeta<TTable extends TableDef> {
21
21
  /** Relations that should be loaded lazily */
22
22
  lazyRelations: (keyof RelationMap<TTable>)[];
23
23
  /** Cache for relation promises */
24
- relationCache: Map<string, Promise<any>>;
24
+ relationCache: Map<string, Promise<unknown>>;
25
25
  /** Hydration data for relations */
26
- relationHydration: Map<string, Map<string, any>>;
26
+ relationHydration: Map<string, Map<string, unknown>>;
27
27
  /** Relation wrapper instances */
28
28
  relationWrappers: Map<string, unknown>;
29
29
  }
@@ -40,7 +40,7 @@ export const getHydrationRows = <TTable extends TableDef>(
40
40
  meta: EntityMeta<TTable>,
41
41
  relationName: string,
42
42
  key: unknown
43
- ): Record<string, any>[] | undefined => {
43
+ ): Record<string, unknown>[] | undefined => {
44
44
  const map = meta.relationHydration.get(relationName);
45
45
  if (!map) return undefined;
46
46
  const rows = map.get(toKey(key));
@@ -60,7 +60,7 @@ export const getHydrationRecord = <TTable extends TableDef>(
60
60
  meta: EntityMeta<TTable>,
61
61
  relationName: string,
62
62
  key: unknown
63
- ): Record<string, any> | undefined => {
63
+ ): Record<string, unknown> | undefined => {
64
64
  const map = meta.relationHydration.get(relationName);
65
65
  if (!map) return undefined;
66
66
  const value = map.get(toKey(key));
@@ -68,7 +68,7 @@ export const getHydrationRecord = <TTable extends TableDef>(
68
68
  if (Array.isArray(value)) {
69
69
  return value[0];
70
70
  }
71
- return value;
71
+ return value as Record<string, unknown>;
72
72
  };
73
73
 
74
74
  /**
@@ -77,9 +77,9 @@ export const getHydrationRecord = <TTable extends TableDef>(
77
77
  * @returns Entity metadata or undefined if not found
78
78
  * @typeParam TTable - Table definition type
79
79
  */
80
- export const getEntityMeta = <TTable extends TableDef>(entity: any): EntityMeta<TTable> | undefined => {
80
+ export const getEntityMeta = <TTable extends TableDef>(entity: unknown): EntityMeta<TTable> | undefined => {
81
81
  if (!entity || typeof entity !== 'object') return undefined;
82
- return (entity as any)[ENTITY_META];
82
+ return (entity as { [ENTITY_META]: EntityMeta<TTable> })[ENTITY_META];
83
83
  };
84
84
 
85
85
  /**
@@ -87,6 +87,6 @@ export const getEntityMeta = <TTable extends TableDef>(entity: any): EntityMeta<
87
87
  * @param entity - Entity instance to check
88
88
  * @returns True if the entity has metadata, false otherwise
89
89
  */
90
- export const hasEntityMeta = (entity: any): entity is { [ENTITY_META]: EntityMeta<TableDef> } => {
90
+ export const hasEntityMeta = (entity: unknown): entity is { [ENTITY_META]: EntityMeta<TableDef> } => {
91
91
  return Boolean(getEntityMeta(entity));
92
92
  };
@@ -1,9 +1,10 @@
1
- import { ColumnType, ColumnDef } from '../schema/column.js';
1
+ import { ColumnDef } from '../schema/column.js';
2
2
  import { defineTable, TableDef, TableHooks } from '../schema/table.js';
3
3
  import { CascadeMode, RelationKinds } from '../schema/relation.js';
4
4
 
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
6
  export type EntityConstructor<T = object> = new (...args: any[]) => T;
6
- export type EntityOrTableTarget = EntityConstructor<any> | TableDef;
7
+ export type EntityOrTableTarget = EntityConstructor | TableDef;
7
8
  export type EntityOrTableTargetResolver = EntityOrTableTarget | (() => EntityOrTableTarget);
8
9
 
9
10
  export type ColumnDefLike<T extends ColumnDef = ColumnDef> = Omit<T, 'name' | 'table'>;
@@ -57,7 +58,7 @@ export type RelationMetadata =
57
58
  | BelongsToManyRelationMetadata;
58
59
 
59
60
  export interface EntityMetadata<TColumns extends Record<string, ColumnDefLike> = Record<string, ColumnDefLike>> {
60
- target: EntityConstructor<any>;
61
+ target: EntityConstructor;
61
62
  tableName: string;
62
63
  columns: TColumns;
63
64
  relations: Record<string, RelationMetadata>;
@@ -65,13 +66,13 @@ export interface EntityMetadata<TColumns extends Record<string, ColumnDefLike> =
65
66
  table?: TableDef<MaterializeColumns<TColumns>>;
66
67
  }
67
68
 
68
- const metadataMap = new Map<EntityConstructor<any>, EntityMetadata>();
69
+ const metadataMap = new Map<EntityConstructor, EntityMetadata>();
69
70
 
70
71
  export const registerEntityMetadata = (meta: EntityMetadata): void => {
71
72
  metadataMap.set(meta.target, meta);
72
73
  };
73
74
 
74
- export const ensureEntityMetadata = (target: EntityConstructor<any>): EntityMetadata => {
75
+ export const ensureEntityMetadata = (target: EntityConstructor): EntityMetadata => {
75
76
  let meta = metadataMap.get(target);
76
77
  if (!meta) {
77
78
  meta = {
@@ -85,7 +86,7 @@ export const ensureEntityMetadata = (target: EntityConstructor<any>): EntityMeta
85
86
  return meta;
86
87
  };
87
88
 
88
- export const getEntityMetadata = (target: EntityConstructor<any>): EntityMetadata | undefined => {
89
+ export const getEntityMetadata = (target: EntityConstructor): EntityMetadata | undefined => {
89
90
  return metadataMap.get(target);
90
91
  };
91
92
 
@@ -98,7 +99,7 @@ export const clearEntityMetadata = (): void => {
98
99
  };
99
100
 
100
101
  export const addColumnMetadata = (
101
- target: EntityConstructor<any>,
102
+ target: EntityConstructor,
102
103
  propertyKey: string,
103
104
  column: ColumnDefLike
104
105
  ): void => {
@@ -107,7 +108,7 @@ export const addColumnMetadata = (
107
108
  };
108
109
 
109
110
  export const addRelationMetadata = (
110
- target: EntityConstructor<any>,
111
+ target: EntityConstructor,
111
112
  propertyKey: string,
112
113
  relation: RelationMetadata
113
114
  ): void => {
@@ -116,7 +117,7 @@ export const addRelationMetadata = (
116
117
  };
117
118
 
118
119
  export const setEntityTableName = (
119
- target: EntityConstructor<any>,
120
+ target: EntityConstructor,
120
121
  tableName: string,
121
122
  hooks?: TableHooks
122
123
  ): void => {
@@ -135,6 +136,7 @@ export const buildTableDef = <TColumns extends Record<string, ColumnDefLike>>(me
135
136
  }
136
137
 
137
138
  const columns = Object.entries(meta.columns).reduce<MaterializeColumns<TColumns>>((acc, [key, def]) => {
139
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
138
140
  (acc as any)[key] = {
139
141
  ...def,
140
142
  name: key,
package/src/orm/entity.ts CHANGED
@@ -13,7 +13,7 @@ import { findPrimaryKey } from '../query-builder/hydration-planner.js';
13
13
  /**
14
14
  * Type representing an array of database rows.
15
15
  */
16
- type Rows = Record<string, any>[];
16
+ type Rows = Record<string, unknown>[];
17
17
 
18
18
  /**
19
19
  * Caches relation loader results across entities of the same type.
@@ -23,8 +23,8 @@ type Rows = Record<string, any>[];
23
23
  * @param factory - The factory function to create the cache
24
24
  * @returns Promise with the cached relation data
25
25
  */
26
- const relationLoaderCache = <T extends Map<string, any>>(
27
- meta: EntityMeta<any>,
26
+ const relationLoaderCache = <T extends Map<string, unknown>>(
27
+ meta: EntityMeta<TableDef>,
28
28
  relationName: string,
29
29
  factory: () => Promise<T>
30
30
  ): Promise<T> => {
@@ -68,10 +68,10 @@ export const createEntityProxy = <
68
68
  >(
69
69
  ctx: EntityContext,
70
70
  table: TTable,
71
- row: Record<string, any>,
71
+ row: Record<string, unknown>,
72
72
  lazyRelations: TLazy[] = [] as TLazy[]
73
73
  ): EntityInstance<TTable> => {
74
- const target: Record<string, any> = { ...row };
74
+ const target: Record<string, unknown> = { ...row };
75
75
  const meta: EntityMeta<TTable> = {
76
76
  ctx,
77
77
  table,
@@ -87,8 +87,7 @@ export const createEntityProxy = <
87
87
  writable: false
88
88
  });
89
89
 
90
- let proxy: EntityInstance<TTable>;
91
- const handler: ProxyHandler<any> = {
90
+ const handler: ProxyHandler<object> = {
92
91
  get(targetObj, prop, receiver) {
93
92
  if (prop === ENTITY_META) {
94
93
  return meta;
@@ -96,7 +95,7 @@ export const createEntityProxy = <
96
95
 
97
96
  if (prop === '$load') {
98
97
  return async (relationName: keyof RelationMap<TTable>) => {
99
- const wrapper = getRelationWrapper(meta, relationName as string, proxy);
98
+ const wrapper = getRelationWrapper(meta as unknown as EntityMeta<TableDef>, relationName as string, receiver);
100
99
  if (wrapper && typeof wrapper.load === 'function') {
101
100
  return wrapper.load();
102
101
  }
@@ -105,7 +104,7 @@ export const createEntityProxy = <
105
104
  }
106
105
 
107
106
  if (typeof prop === 'string' && table.relations[prop]) {
108
- return getRelationWrapper(meta, prop, proxy);
107
+ return getRelationWrapper(meta as unknown as EntityMeta<TableDef>, prop, receiver);
109
108
  }
110
109
 
111
110
  return Reflect.get(targetObj, prop, receiver);
@@ -114,13 +113,13 @@ export const createEntityProxy = <
114
113
  set(targetObj, prop, value, receiver) {
115
114
  const result = Reflect.set(targetObj, prop, value, receiver);
116
115
  if (typeof prop === 'string' && table.columns[prop]) {
117
- ctx.markDirty(proxy);
116
+ ctx.markDirty(receiver);
118
117
  }
119
118
  return result;
120
119
  }
121
120
  };
122
121
 
123
- proxy = new Proxy(target, handler) as EntityInstance<TTable>;
122
+ const proxy = new Proxy(target, handler) as EntityInstance<TTable>;
124
123
  populateHydrationCache(proxy, row, meta);
125
124
  return proxy;
126
125
  };
@@ -141,7 +140,7 @@ export const createEntityFromRow = <
141
140
  >(
142
141
  ctx: EntityContext,
143
142
  table: TTable,
144
- row: Record<string, any>,
143
+ row: Record<string, unknown>,
145
144
  lazyRelations: (keyof RelationMap<TTable>)[] = []
146
145
  ): TResult => {
147
146
  const pkName = findPrimaryKey(table);
@@ -176,8 +175,8 @@ const toKey = (value: unknown): string => (value === null || value === undefined
176
175
  * @param meta - The entity metadata
177
176
  */
178
177
  const populateHydrationCache = <TTable extends TableDef>(
179
- entity: any,
180
- row: Record<string, any>,
178
+ entity: Record<string, unknown>,
179
+ row: Record<string, unknown>,
181
180
  meta: EntityMeta<TTable>
182
181
  ): void => {
183
182
  for (const relationName of Object.keys(meta.table.relations)) {
@@ -188,8 +187,8 @@ const populateHydrationCache = <TTable extends TableDef>(
188
187
  const rootValue = entity[localKey];
189
188
  if (rootValue === undefined || rootValue === null) continue;
190
189
  if (!data || typeof data !== 'object') continue;
191
- const cache = new Map<string, Record<string, any>>();
192
- cache.set(toKey(rootValue), data as Record<string, any>);
190
+ const cache = new Map<string, Record<string, unknown>>();
191
+ cache.set(toKey(rootValue), data as Record<string, unknown>);
193
192
  meta.relationHydration.set(relationName, cache);
194
193
  meta.relationCache.set(relationName, Promise.resolve(cache));
195
194
  continue;
@@ -210,7 +209,7 @@ const populateHydrationCache = <TTable extends TableDef>(
210
209
 
211
210
  if (relation.type === RelationKinds.BelongsTo) {
212
211
  const targetKey = relation.localKey || findPrimaryKey(relation.target);
213
- const cache = new Map<string, Record<string, any>>();
212
+ const cache = new Map<string, Record<string, unknown>>();
214
213
  for (const item of data) {
215
214
  const pkValue = item[targetKey];
216
215
  if (pkValue === undefined || pkValue === null) continue;
@@ -232,18 +231,18 @@ const populateHydrationCache = <TTable extends TableDef>(
232
231
  * @returns The relation wrapper or undefined
233
232
  */
234
233
  const getRelationWrapper = (
235
- meta: EntityMeta<any>,
234
+ meta: EntityMeta<TableDef>,
236
235
  relationName: string,
237
- owner: any
238
- ): HasManyCollection<any> | HasOneReference<any> | BelongsToReference<any> | ManyToManyCollection<any> | undefined => {
236
+ owner: unknown
237
+ ): HasManyCollection<unknown> | HasOneReference<unknown> | BelongsToReference<unknown> | ManyToManyCollection<unknown> | undefined => {
239
238
  if (meta.relationWrappers.has(relationName)) {
240
- return meta.relationWrappers.get(relationName) as HasManyCollection<any>;
239
+ return meta.relationWrappers.get(relationName) as HasManyCollection<unknown>;
241
240
  }
242
241
 
243
242
  const relation = meta.table.relations[relationName];
244
243
  if (!relation) return undefined;
245
244
 
246
- const wrapper = instantiateWrapper(meta, relationName, relation as any, owner);
245
+ const wrapper = instantiateWrapper(meta, relationName, relation, owner);
247
246
  if (wrapper) {
248
247
  meta.relationWrappers.set(relationName, wrapper);
249
248
  }
@@ -260,11 +259,11 @@ const getRelationWrapper = (
260
259
  * @returns The relation wrapper or undefined
261
260
  */
262
261
  const instantiateWrapper = (
263
- meta: EntityMeta<any>,
262
+ meta: EntityMeta<TableDef>,
264
263
  relationName: string,
265
264
  relation: HasManyRelation | HasOneRelation | BelongsToRelation | BelongsToManyRelation,
266
- owner: any
267
- ): HasManyCollection<any> | HasOneReference<any> | BelongsToReference<any> | ManyToManyCollection<any> | undefined => {
265
+ owner: unknown
266
+ ): HasManyCollection<unknown> | HasOneReference<unknown> | BelongsToReference<unknown> | ManyToManyCollection<unknown> | undefined => {
268
267
  switch (relation.type) {
269
268
  case RelationKinds.HasOne: {
270
269
  const hasOne = relation as HasOneRelation;
@@ -280,7 +279,7 @@ const instantiateWrapper = (
280
279
  hasOne,
281
280
  meta.table,
282
281
  loader,
283
- (row: Record<string, any>) => createEntityFromRow(meta.ctx, hasOne.target, row),
282
+ (row: Record<string, unknown>) => createEntityFromRow(meta.ctx, hasOne.target, row),
284
283
  localKey
285
284
  );
286
285
  }
@@ -298,7 +297,7 @@ const instantiateWrapper = (
298
297
  hasMany,
299
298
  meta.table,
300
299
  loader,
301
- (row: Record<string, any>) => createEntityFromRow(meta.ctx, relation.target, row),
300
+ (row: Record<string, unknown>) => createEntityFromRow(meta.ctx, relation.target, row),
302
301
  localKey
303
302
  );
304
303
  }
@@ -316,7 +315,7 @@ const instantiateWrapper = (
316
315
  belongsTo,
317
316
  meta.table,
318
317
  loader,
319
- (row: Record<string, any>) => createEntityFromRow(meta.ctx, relation.target, row),
318
+ (row: Record<string, unknown>) => createEntityFromRow(meta.ctx, relation.target, row),
320
319
  targetKey
321
320
  );
322
321
  }
@@ -334,7 +333,7 @@ const instantiateWrapper = (
334
333
  many,
335
334
  meta.table,
336
335
  loader,
337
- (row: Record<string, any>) => createEntityFromRow(meta.ctx, relation.target, row),
336
+ (row: Record<string, unknown>) => createEntityFromRow(meta.ctx, relation.target, row),
338
337
  localKey
339
338
  );
340
339
  }
@@ -8,7 +8,7 @@ import { EntityContext } from './entity-context.js';
8
8
  import { ExecutionContext } from './execution-context.js';
9
9
  import { HydrationContext } from './hydration-context.js';
10
10
 
11
- type Row = Record<string, any>;
11
+ type Row = Record<string, unknown>;
12
12
 
13
13
  const flattenResults = (results: { columns: string[]; values: unknown[][] }[]): Row[] => {
14
14
  const rows: Row[] = [];
@@ -27,7 +27,7 @@ const flattenResults = (results: { columns: string[]; values: unknown[][] }[]):
27
27
 
28
28
  const executeWithEntityContext = async <TTable extends TableDef>(
29
29
  entityCtx: EntityContext,
30
- qb: SelectQueryBuilder<any, TTable>
30
+ qb: SelectQueryBuilder<unknown, TTable>
31
31
  ): Promise<EntityInstance<TTable>[]> => {
32
32
  const ast = qb.getAST();
33
33
  const compiled = entityCtx.dialect.compileSelect(ast);
@@ -44,7 +44,7 @@ const executeWithEntityContext = async <TTable extends TableDef>(
44
44
 
45
45
  export async function executeHydrated<TTable extends TableDef>(
46
46
  session: OrmSession,
47
- qb: SelectQueryBuilder<any, TTable>
47
+ qb: SelectQueryBuilder<unknown, TTable>
48
48
  ): Promise<EntityInstance<TTable>[]> {
49
49
  return executeWithEntityContext(session, qb);
50
50
  }
@@ -52,7 +52,7 @@ export async function executeHydrated<TTable extends TableDef>(
52
52
  export async function executeHydratedWithContexts<TTable extends TableDef>(
53
53
  _execCtx: ExecutionContext,
54
54
  hydCtx: HydrationContext,
55
- qb: SelectQueryBuilder<any, TTable>
55
+ qb: SelectQueryBuilder<unknown, TTable>
56
56
  ): Promise<EntityInstance<TTable>[]> {
57
57
  const entityCtx = hydCtx.entityContext;
58
58
  if (!entityCtx) {
@@ -1,6 +1,10 @@
1
- import { HydrationPlan, HydrationRelationPlan } from '../core/hydration/types.js';
2
- import { RelationKinds } from '../schema/relation.js';
3
- import { isRelationAlias, makeRelationAlias } from '../query-builder/relation-alias.js';
1
+ import { HydrationPlan, HydrationRelationPlan } from '../core/hydration/types.js';
2
+ import { RelationKinds } from '../schema/relation.js';
3
+ import { isRelationAlias, makeRelationAlias } from '../query-builder/relation-alias.js';
4
+
5
+ /**
6
+ * Hydrates query results according to a hydration plan
7
+ * @param rows - Raw database rows
4
8
 
5
9
  /**
6
10
  * Hydrates query results according to a hydration plan
@@ -8,13 +12,13 @@ import { isRelationAlias, makeRelationAlias } from '../query-builder/relation-al
8
12
  * @param plan - Hydration plan
9
13
  * @returns Hydrated result objects with nested relations
10
14
  */
11
- export const hydrateRows = (rows: Record<string, any>[], plan?: HydrationPlan): Record<string, any>[] => {
15
+ export const hydrateRows = (rows: Record<string, unknown>[], plan?: HydrationPlan): Record<string, unknown>[] => {
12
16
  if (!plan || !rows.length) return rows;
13
17
 
14
- const rootMap = new Map<any, Record<string, any>>();
15
- const relationIndex = new Map<any, Record<string, Set<any>>>();
18
+ const rootMap = new Map<unknown, Record<string, unknown>>();
19
+ const relationIndex = new Map<unknown, Record<string, Set<unknown>>>();
16
20
 
17
- const getOrCreateParent = (row: Record<string, any>) => {
21
+ const getOrCreateParent = (row: Record<string, unknown>) => {
18
22
  const rootId = row[plan.rootPrimaryKey];
19
23
  if (rootId === undefined) return undefined;
20
24
 
@@ -25,7 +29,7 @@ export const hydrateRows = (rows: Record<string, any>[], plan?: HydrationPlan):
25
29
  return rootMap.get(rootId);
26
30
  };
27
31
 
28
- const getRelationSeenSet = (rootId: any, relationName: string): Set<any> => {
32
+ const getRelationSeenSet = (rootId: unknown, relationName: string): Set<unknown> => {
29
33
  let byRelation = relationIndex.get(rootId);
30
34
  if (!byRelation) {
31
35
  byRelation = {};
@@ -34,7 +38,7 @@ export const hydrateRows = (rows: Record<string, any>[], plan?: HydrationPlan):
34
38
 
35
39
  let seen = byRelation[relationName];
36
40
  if (!seen) {
37
- seen = new Set<any>();
41
+ seen = new Set<unknown>();
38
42
  byRelation[relationName] = seen;
39
43
  }
40
44
 
@@ -48,32 +52,32 @@ export const hydrateRows = (rows: Record<string, any>[], plan?: HydrationPlan):
48
52
  const parent = getOrCreateParent(row);
49
53
  if (!parent) continue;
50
54
 
51
- for (const rel of plan.relations) {
52
- const childPkKey = makeRelationAlias(rel.aliasPrefix, rel.targetPrimaryKey);
53
- const childPk = row[childPkKey];
54
- if (childPk === null || childPk === undefined) continue;
55
-
56
- const seen = getRelationSeenSet(rootId, rel.name);
57
- if (seen.has(childPk)) continue;
58
- seen.add(childPk);
59
-
60
- if (rel.type === RelationKinds.HasOne) {
61
- if (!parent[rel.name]) {
62
- parent[rel.name] = buildChild(row, rel);
63
- }
64
- continue;
65
- }
66
-
67
- const bucket = parent[rel.name] as any[];
68
- bucket.push(buildChild(row, rel));
69
- }
55
+ for (const rel of plan.relations) {
56
+ const childPkKey = makeRelationAlias(rel.aliasPrefix, rel.targetPrimaryKey);
57
+ const childPk = row[childPkKey];
58
+ if (childPk === null || childPk === undefined) continue;
59
+
60
+ const seen = getRelationSeenSet(rootId, rel.name);
61
+ if (seen.has(childPk)) continue;
62
+ seen.add(childPk);
63
+
64
+ if (rel.type === RelationKinds.HasOne) {
65
+ if (!parent[rel.name]) {
66
+ parent[rel.name] = buildChild(row, rel);
67
+ }
68
+ continue;
69
+ }
70
+
71
+ const bucket = parent[rel.name] as unknown[];
72
+ bucket.push(buildChild(row, rel));
73
+ }
70
74
  }
71
75
 
72
76
  return Array.from(rootMap.values());
73
77
  };
74
78
 
75
- const createBaseRow = (row: Record<string, any>, plan: HydrationPlan): Record<string, any> => {
76
- const base: Record<string, any> = {};
79
+ const createBaseRow = (row: Record<string, unknown>, plan: HydrationPlan): Record<string, unknown> => {
80
+ const base: Record<string, unknown> = {};
77
81
  const baseKeys = plan.rootColumns.length
78
82
  ? plan.rootColumns
79
83
  : Object.keys(row).filter(k => !isRelationAlias(k));
@@ -82,15 +86,14 @@ const createBaseRow = (row: Record<string, any>, plan: HydrationPlan): Record<st
82
86
  base[key] = row[key];
83
87
  }
84
88
 
85
- for (const rel of plan.relations) {
86
- base[rel.name] = rel.type === RelationKinds.HasOne ? null : [];
87
- }
88
-
89
+ for (const rel of plan.relations) {
90
+ base[rel.name] = rel.type === RelationKinds.HasOne ? null : [];
91
+ }
89
92
  return base;
90
93
  };
91
94
 
92
- const buildChild = (row: Record<string, any>, rel: HydrationRelationPlan): Record<string, any> => {
93
- const child: Record<string, any> = {};
95
+ const buildChild = (row: Record<string, unknown>, rel: HydrationRelationPlan): Record<string, unknown> => {
96
+ const child: Record<string, unknown> = {};
94
97
  for (const col of rel.columns) {
95
98
  const key = makeRelationAlias(rel.aliasPrefix, col);
96
99
  child[col] = row[key];
@@ -98,16 +101,16 @@ const buildChild = (row: Record<string, any>, rel: HydrationRelationPlan): Recor
98
101
 
99
102
  const pivot = buildPivot(row, rel);
100
103
  if (pivot) {
101
- (child as any)._pivot = pivot;
104
+ (child as { _pivot: unknown })._pivot = pivot;
102
105
  }
103
106
 
104
107
  return child;
105
108
  };
106
109
 
107
- const buildPivot = (row: Record<string, any>, rel: HydrationRelationPlan): Record<string, any> | undefined => {
110
+ const buildPivot = (row: Record<string, unknown>, rel: HydrationRelationPlan): Record<string, unknown> | undefined => {
108
111
  if (!rel.pivot) return undefined;
109
112
 
110
- const pivot: Record<string, any> = {};
113
+ const pivot: Record<string, unknown> = {};
111
114
  for (const col of rel.pivot.columns) {
112
115
  const key = makeRelationAlias(rel.pivot.aliasPrefix, col);
113
116
  pivot[col] = row[key];
@@ -8,7 +8,7 @@ export class IdentityMap {
8
8
  return this.buckets;
9
9
  }
10
10
 
11
- getEntity(table: TableDef, pk: string | number): any | undefined {
11
+ getEntity(table: TableDef, pk: string | number): unknown | undefined {
12
12
  const bucket = this.buckets.get(table.name);
13
13
  return bucket?.get(this.toIdentityKey(pk))?.entity;
14
14
  }
@@ -7,7 +7,7 @@ import type { QueryResult } from '../core/execution/db-executor.js';
7
7
  import { ColumnDef } from '../schema/column.js';
8
8
  import { findPrimaryKey } from '../query-builder/hydration-planner.js';
9
9
 
10
- type Rows = Record<string, any>[];
10
+ type Rows = Record<string, unknown>[];
11
11
 
12
12
  const selectAllColumns = (table: TableDef): Record<string, ColumnDef> =>
13
13
  Object.entries(table.columns).reduce((acc, [name, def]) => {
@@ -20,7 +20,7 @@ const rowsFromResults = (results: QueryResult[]): Rows => {
20
20
  for (const result of results) {
21
21
  const { columns, values } = result;
22
22
  for (const valueRow of values) {
23
- const row: Record<string, any> = {};
23
+ const row: Record<string, unknown> = {};
24
24
  columns.forEach((column, idx) => {
25
25
  row[column] = valueRow[idx];
26
26
  });
@@ -30,7 +30,7 @@ const rowsFromResults = (results: QueryResult[]): Rows => {
30
30
  return rows;
31
31
  };
32
32
 
33
- const executeQuery = async (ctx: EntityContext, qb: SelectQueryBuilder<any, TableDef<any>>): Promise<Rows> => {
33
+ const executeQuery = async (ctx: EntityContext, qb: SelectQueryBuilder<unknown, TableDef>): Promise<Rows> => {
34
34
  const compiled = ctx.dialect.compileSelect(qb.getAST());
35
35
  const results = await ctx.executor.executeSql(compiled.sql, compiled.params);
36
36
  return rowsFromResults(results);
@@ -86,7 +86,7 @@ export const loadHasOneRelation = async (
86
86
  rootTable: TableDef,
87
87
  _relationName: string,
88
88
  relation: HasOneRelation
89
- ): Promise<Map<string, Record<string, any>>> => {
89
+ ): Promise<Map<string, Record<string, unknown>>> => {
90
90
  const localKey = relation.localKey || findPrimaryKey(rootTable);
91
91
  const roots = ctx.getEntitiesForTable(rootTable);
92
92
  const keys = new Set<unknown>();
@@ -110,7 +110,7 @@ export const loadHasOneRelation = async (
110
110
  qb.where(inList(fkColumn, Array.from(keys) as (string | number | LiteralNode)[]));
111
111
 
112
112
  const rows = await executeQuery(ctx, qb);
113
- const lookup = new Map<string, Record<string, any>>();
113
+ const lookup = new Map<string, Record<string, unknown>>();
114
114
 
115
115
  for (const row of rows) {
116
116
  const fkValue = row[relation.foreignKey];
@@ -129,7 +129,7 @@ export const loadBelongsToRelation = async (
129
129
  rootTable: TableDef,
130
130
  _relationName: string,
131
131
  relation: BelongsToRelation
132
- ): Promise<Map<string, Record<string, any>>> => {
132
+ ): Promise<Map<string, Record<string, unknown>>> => {
133
133
  const roots = ctx.getEntitiesForTable(rootTable);
134
134
  const foreignKeys = new Set<unknown>();
135
135
 
@@ -152,7 +152,7 @@ export const loadBelongsToRelation = async (
152
152
 
153
153
  qb.where(inList(pkColumn, Array.from(foreignKeys) as (string | number | LiteralNode)[]));
154
154
  const rows = await executeQuery(ctx, qb);
155
- const map = new Map<string, Record<string, any>>();
155
+ const map = new Map<string, Record<string, unknown>>();
156
156
 
157
157
  for (const row of rows) {
158
158
  const keyValue = row[targetKey];
@@ -192,7 +192,7 @@ export const loadBelongsToManyRelation = async (
192
192
  pivotQb.where(inList(pivotFkCol, Array.from(rootIds) as (string | number | LiteralNode)[]));
193
193
  const pivotRows = await executeQuery(ctx, pivotQb);
194
194
 
195
- const rootLookup = new Map<string, { targetId: unknown; pivot: Record<string, any> }[]>();
195
+ const rootLookup = new Map<string, { targetId: unknown; pivot: Record<string, unknown> }[]>();
196
196
  const targetIds = new Set<unknown>();
197
197
 
198
198
  for (const pivot of pivotRows) {
@@ -222,7 +222,7 @@ export const loadBelongsToManyRelation = async (
222
222
  const targetQb = new SelectQueryBuilder(relation.target).select(targetSelect);
223
223
  targetQb.where(inList(targetPkColumn, Array.from(targetIds) as (string | number | LiteralNode)[]));
224
224
  const targetRows = await executeQuery(ctx, targetQb);
225
- const targetMap = new Map<string, Record<string, any>>();
225
+ const targetMap = new Map<string, Record<string, unknown>>();
226
226
 
227
227
  for (const row of targetRows) {
228
228
  const pkValue = row[targetKey];