@mikro-orm/core 7.0.0-dev.23 → 7.0.0-dev.230

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 (209) hide show
  1. package/EntityManager.d.ts +91 -59
  2. package/EntityManager.js +303 -251
  3. package/MikroORM.d.ts +44 -35
  4. package/MikroORM.js +109 -143
  5. package/README.md +2 -0
  6. package/cache/FileCacheAdapter.d.ts +1 -1
  7. package/cache/FileCacheAdapter.js +17 -8
  8. package/cache/GeneratedCacheAdapter.d.ts +0 -1
  9. package/cache/GeneratedCacheAdapter.js +0 -2
  10. package/cache/index.d.ts +0 -1
  11. package/cache/index.js +0 -1
  12. package/connections/Connection.d.ts +12 -5
  13. package/connections/Connection.js +21 -12
  14. package/drivers/DatabaseDriver.d.ts +25 -16
  15. package/drivers/DatabaseDriver.js +118 -35
  16. package/drivers/IDatabaseDriver.d.ts +42 -19
  17. package/entity/BaseEntity.d.ts +61 -2
  18. package/entity/BaseEntity.js +0 -3
  19. package/entity/Collection.d.ts +101 -29
  20. package/entity/Collection.js +436 -104
  21. package/entity/EntityAssigner.d.ts +1 -1
  22. package/entity/EntityAssigner.js +26 -18
  23. package/entity/EntityFactory.d.ts +7 -1
  24. package/entity/EntityFactory.js +83 -54
  25. package/entity/EntityHelper.d.ts +2 -2
  26. package/entity/EntityHelper.js +48 -15
  27. package/entity/EntityLoader.d.ts +7 -6
  28. package/entity/EntityLoader.js +215 -89
  29. package/entity/EntityRepository.d.ts +27 -7
  30. package/entity/EntityRepository.js +8 -2
  31. package/entity/PolymorphicRef.d.ts +12 -0
  32. package/entity/PolymorphicRef.js +18 -0
  33. package/entity/Reference.d.ts +1 -5
  34. package/entity/Reference.js +21 -12
  35. package/entity/WrappedEntity.d.ts +0 -5
  36. package/entity/WrappedEntity.js +2 -7
  37. package/entity/defineEntity.d.ts +380 -310
  38. package/entity/defineEntity.js +124 -273
  39. package/entity/index.d.ts +2 -2
  40. package/entity/index.js +2 -2
  41. package/entity/utils.js +1 -1
  42. package/entity/validators.d.ts +11 -0
  43. package/entity/validators.js +65 -0
  44. package/enums.d.ts +8 -6
  45. package/enums.js +2 -1
  46. package/errors.d.ts +20 -10
  47. package/errors.js +55 -23
  48. package/events/EventManager.d.ts +2 -1
  49. package/events/EventManager.js +19 -11
  50. package/hydration/Hydrator.js +1 -2
  51. package/hydration/ObjectHydrator.d.ts +4 -4
  52. package/hydration/ObjectHydrator.js +87 -35
  53. package/index.d.ts +2 -2
  54. package/index.js +1 -2
  55. package/logging/DefaultLogger.d.ts +1 -1
  56. package/logging/DefaultLogger.js +1 -0
  57. package/logging/SimpleLogger.d.ts +1 -1
  58. package/logging/colors.d.ts +1 -1
  59. package/logging/colors.js +7 -6
  60. package/logging/index.d.ts +1 -0
  61. package/logging/index.js +1 -0
  62. package/logging/inspect.d.ts +2 -0
  63. package/logging/inspect.js +11 -0
  64. package/metadata/EntitySchema.d.ts +47 -23
  65. package/metadata/EntitySchema.js +92 -33
  66. package/metadata/MetadataDiscovery.d.ts +64 -9
  67. package/metadata/MetadataDiscovery.js +778 -325
  68. package/metadata/MetadataProvider.d.ts +11 -2
  69. package/metadata/MetadataProvider.js +46 -2
  70. package/metadata/MetadataStorage.d.ts +13 -11
  71. package/metadata/MetadataStorage.js +70 -37
  72. package/metadata/MetadataValidator.d.ts +32 -9
  73. package/metadata/MetadataValidator.js +196 -41
  74. package/metadata/discover-entities.d.ts +5 -0
  75. package/metadata/discover-entities.js +40 -0
  76. package/metadata/index.d.ts +1 -1
  77. package/metadata/index.js +1 -1
  78. package/metadata/types.d.ts +526 -0
  79. package/metadata/types.js +1 -0
  80. package/naming-strategy/AbstractNamingStrategy.d.ts +16 -4
  81. package/naming-strategy/AbstractNamingStrategy.js +20 -2
  82. package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
  83. package/naming-strategy/EntityCaseNamingStrategy.js +6 -5
  84. package/naming-strategy/MongoNamingStrategy.d.ts +3 -3
  85. package/naming-strategy/MongoNamingStrategy.js +6 -6
  86. package/naming-strategy/NamingStrategy.d.ts +28 -4
  87. package/naming-strategy/UnderscoreNamingStrategy.d.ts +3 -3
  88. package/naming-strategy/UnderscoreNamingStrategy.js +6 -6
  89. package/not-supported.d.ts +2 -0
  90. package/not-supported.js +4 -0
  91. package/package.json +19 -11
  92. package/platforms/ExceptionConverter.js +1 -1
  93. package/platforms/Platform.d.ts +7 -14
  94. package/platforms/Platform.js +20 -43
  95. package/serialization/EntitySerializer.d.ts +5 -0
  96. package/serialization/EntitySerializer.js +47 -27
  97. package/serialization/EntityTransformer.js +28 -18
  98. package/serialization/SerializationContext.d.ts +6 -6
  99. package/serialization/SerializationContext.js +3 -3
  100. package/types/ArrayType.d.ts +1 -1
  101. package/types/ArrayType.js +2 -3
  102. package/types/BigIntType.d.ts +8 -6
  103. package/types/BigIntType.js +1 -1
  104. package/types/BlobType.d.ts +0 -1
  105. package/types/BlobType.js +0 -3
  106. package/types/BooleanType.d.ts +1 -0
  107. package/types/BooleanType.js +3 -0
  108. package/types/DecimalType.d.ts +6 -4
  109. package/types/DecimalType.js +2 -2
  110. package/types/DoubleType.js +1 -1
  111. package/types/EnumArrayType.js +1 -2
  112. package/types/JsonType.d.ts +1 -1
  113. package/types/JsonType.js +7 -2
  114. package/types/TinyIntType.js +1 -1
  115. package/types/Type.d.ts +2 -4
  116. package/types/Type.js +3 -3
  117. package/types/Uint8ArrayType.d.ts +0 -1
  118. package/types/Uint8ArrayType.js +1 -4
  119. package/types/index.d.ts +1 -1
  120. package/typings.d.ts +381 -171
  121. package/typings.js +97 -44
  122. package/unit-of-work/ChangeSet.d.ts +4 -6
  123. package/unit-of-work/ChangeSet.js +4 -5
  124. package/unit-of-work/ChangeSetComputer.d.ts +1 -3
  125. package/unit-of-work/ChangeSetComputer.js +35 -14
  126. package/unit-of-work/ChangeSetPersister.d.ts +7 -3
  127. package/unit-of-work/ChangeSetPersister.js +83 -25
  128. package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
  129. package/unit-of-work/CommitOrderCalculator.js +13 -13
  130. package/unit-of-work/IdentityMap.d.ts +12 -0
  131. package/unit-of-work/IdentityMap.js +39 -1
  132. package/unit-of-work/UnitOfWork.d.ts +27 -3
  133. package/unit-of-work/UnitOfWork.js +258 -92
  134. package/utils/AbstractSchemaGenerator.d.ts +5 -5
  135. package/utils/AbstractSchemaGenerator.js +28 -17
  136. package/utils/AsyncContext.d.ts +6 -0
  137. package/utils/AsyncContext.js +42 -0
  138. package/utils/Configuration.d.ts +795 -209
  139. package/utils/Configuration.js +150 -192
  140. package/utils/ConfigurationLoader.d.ts +1 -54
  141. package/utils/ConfigurationLoader.js +1 -352
  142. package/utils/Cursor.d.ts +0 -3
  143. package/utils/Cursor.js +24 -11
  144. package/utils/DataloaderUtils.d.ts +10 -5
  145. package/utils/DataloaderUtils.js +29 -12
  146. package/utils/EntityComparator.d.ts +16 -9
  147. package/utils/EntityComparator.js +158 -58
  148. package/utils/QueryHelper.d.ts +18 -6
  149. package/utils/QueryHelper.js +76 -23
  150. package/utils/RawQueryFragment.d.ts +28 -34
  151. package/utils/RawQueryFragment.js +35 -71
  152. package/utils/RequestContext.js +2 -2
  153. package/utils/TransactionContext.js +2 -2
  154. package/utils/TransactionManager.js +28 -4
  155. package/utils/Utils.d.ts +14 -127
  156. package/utils/Utils.js +85 -397
  157. package/utils/clone.js +8 -23
  158. package/utils/env-vars.d.ts +7 -0
  159. package/utils/env-vars.js +97 -0
  160. package/utils/fs-utils.d.ts +33 -0
  161. package/utils/fs-utils.js +192 -0
  162. package/utils/index.d.ts +1 -1
  163. package/utils/index.js +1 -1
  164. package/utils/upsert-utils.d.ts +9 -4
  165. package/utils/upsert-utils.js +46 -3
  166. package/decorators/Check.d.ts +0 -3
  167. package/decorators/Check.js +0 -13
  168. package/decorators/CreateRequestContext.d.ts +0 -3
  169. package/decorators/CreateRequestContext.js +0 -32
  170. package/decorators/Embeddable.d.ts +0 -8
  171. package/decorators/Embeddable.js +0 -11
  172. package/decorators/Embedded.d.ts +0 -12
  173. package/decorators/Embedded.js +0 -18
  174. package/decorators/Entity.d.ts +0 -33
  175. package/decorators/Entity.js +0 -12
  176. package/decorators/Enum.d.ts +0 -9
  177. package/decorators/Enum.js +0 -16
  178. package/decorators/Filter.d.ts +0 -2
  179. package/decorators/Filter.js +0 -8
  180. package/decorators/Formula.d.ts +0 -4
  181. package/decorators/Formula.js +0 -15
  182. package/decorators/Indexed.d.ts +0 -19
  183. package/decorators/Indexed.js +0 -20
  184. package/decorators/ManyToMany.d.ts +0 -42
  185. package/decorators/ManyToMany.js +0 -14
  186. package/decorators/ManyToOne.d.ts +0 -34
  187. package/decorators/ManyToOne.js +0 -14
  188. package/decorators/OneToMany.d.ts +0 -28
  189. package/decorators/OneToMany.js +0 -17
  190. package/decorators/OneToOne.d.ts +0 -28
  191. package/decorators/OneToOne.js +0 -7
  192. package/decorators/PrimaryKey.d.ts +0 -8
  193. package/decorators/PrimaryKey.js +0 -20
  194. package/decorators/Property.d.ts +0 -250
  195. package/decorators/Property.js +0 -32
  196. package/decorators/Transactional.d.ts +0 -14
  197. package/decorators/Transactional.js +0 -28
  198. package/decorators/hooks.d.ts +0 -16
  199. package/decorators/hooks.js +0 -47
  200. package/decorators/index.d.ts +0 -17
  201. package/decorators/index.js +0 -17
  202. package/entity/ArrayCollection.d.ts +0 -118
  203. package/entity/ArrayCollection.js +0 -407
  204. package/entity/EntityValidator.d.ts +0 -19
  205. package/entity/EntityValidator.js +0 -150
  206. package/metadata/ReflectMetadataProvider.d.ts +0 -8
  207. package/metadata/ReflectMetadataProvider.js +0 -44
  208. package/utils/resolveContextProvider.d.ts +0 -10
  209. package/utils/resolveContextProvider.js +0 -28
@@ -1,5 +1,6 @@
1
- import type { EntityData, EntityDictionary, EntityMetadata, EntityProperty, IMetadataStorage } from '../typings.js';
1
+ import type { EntityData, EntityDictionary, EntityMetadata, EntityName, EntityProperty, IMetadataStorage } from '../typings.js';
2
2
  import type { Platform } from '../platforms/Platform.js';
3
+ import type { Configuration } from './Configuration.js';
3
4
  type Comparator<T> = (a: T, b: T, options?: {
4
5
  includeInverseSides?: boolean;
5
6
  }) => EntityData<T>;
@@ -9,6 +10,7 @@ type CompositeKeyPart = string | CompositeKeyPart[];
9
10
  export declare class EntityComparator {
10
11
  private readonly metadata;
11
12
  private readonly platform;
13
+ private readonly config?;
12
14
  private readonly comparators;
13
15
  private readonly mappers;
14
16
  private readonly snapshotGenerators;
@@ -16,23 +18,23 @@ export declare class EntityComparator {
16
18
  private readonly pkGettersConverted;
17
19
  private readonly pkSerializers;
18
20
  private tmpIndex;
19
- constructor(metadata: IMetadataStorage, platform: Platform);
21
+ constructor(metadata: IMetadataStorage, platform: Platform, config?: Configuration | undefined);
20
22
  /**
21
23
  * Computes difference between two entities.
22
24
  */
23
- diffEntities<T>(entityName: string, a: EntityData<T>, b: EntityData<T>, options?: {
25
+ diffEntities<T extends object>(entityName: EntityName<T>, a: EntityData<T>, b: EntityData<T>, options?: {
24
26
  includeInverseSides?: boolean;
25
27
  }): EntityData<T>;
26
- matching<T>(entityName: string, a: EntityData<T>, b: EntityData<T>): boolean;
28
+ matching<T extends object>(entityName: EntityName<T>, a: EntityData<T>, b: EntityData<T>): boolean;
27
29
  /**
28
30
  * Removes ORM specific code from entities and prepares it for serializing. Used before change set computation.
29
31
  * References will be mapped to primary keys, collections to arrays of primary keys.
30
32
  */
31
- prepareEntity<T>(entity: T): EntityData<T>;
33
+ prepareEntity<T extends object>(entity: T): EntityData<T>;
32
34
  /**
33
35
  * Maps database columns to properties.
34
36
  */
35
- mapResult<T>(entityName: string, result: EntityDictionary<T>): EntityData<T>;
37
+ mapResult<T>(meta: EntityMetadata<T>, result: EntityDictionary<T>): EntityData<T>;
36
38
  /**
37
39
  * @internal Highly performance-sensitive method.
38
40
  */
@@ -48,7 +50,7 @@ export declare class EntityComparator {
48
50
  /**
49
51
  * @internal Highly performance-sensitive method.
50
52
  */
51
- getSnapshotGenerator<T>(entityName: string): SnapshotGenerator<T>;
53
+ getSnapshotGenerator<T>(entityName: EntityName<T>): SnapshotGenerator<T>;
52
54
  /**
53
55
  * @internal
54
56
  */
@@ -64,7 +66,7 @@ export declare class EntityComparator {
64
66
  /**
65
67
  * @internal Highly performance-sensitive method.
66
68
  */
67
- getResultMapper<T>(entityName: string): ResultMapper<T>;
69
+ getResultMapper<T>(meta: EntityMetadata<T>): ResultMapper<T>;
68
70
  private getPropertyCondition;
69
71
  private getEmbeddedArrayPropertySnapshot;
70
72
  /**
@@ -78,11 +80,16 @@ export declare class EntityComparator {
78
80
  /**
79
81
  * @internal Highly performance-sensitive method.
80
82
  */
81
- getEntityComparator<T extends object>(entityName: string): Comparator<T>;
83
+ getEntityComparator<T extends object>(entityName: EntityName<T>): Comparator<T>;
82
84
  private getGenericComparator;
83
85
  private getPropertyComparator;
84
86
  private wrap;
85
87
  private safeKey;
88
+ /**
89
+ * Sets the toArray helper in the context if not already set.
90
+ * Used for converting composite PKs to arrays.
91
+ */
92
+ private setToArrayHelper;
86
93
  /**
87
94
  * perf: used to generate list of comparable properties during discovery, so we speed up the runtime comparison
88
95
  */
@@ -2,10 +2,13 @@ import { clone } from './clone.js';
2
2
  import { ReferenceKind } from '../enums.js';
3
3
  import { compareArrays, compareBooleans, compareBuffers, compareObjects, equals, parseJsonSafe, Utils } from './Utils.js';
4
4
  import { JsonType } from '../types/JsonType.js';
5
- import { RawQueryFragment } from './RawQueryFragment.js';
5
+ import { Raw } from './RawQueryFragment.js';
6
+ import { EntityIdentifier } from '../entity/EntityIdentifier.js';
7
+ import { PolymorphicRef } from '../entity/PolymorphicRef.js';
6
8
  export class EntityComparator {
7
9
  metadata;
8
10
  platform;
11
+ config;
9
12
  comparators = new Map();
10
13
  mappers = new Map();
11
14
  snapshotGenerators = new Map();
@@ -13,9 +16,10 @@ export class EntityComparator {
13
16
  pkGettersConverted = new Map();
14
17
  pkSerializers = new Map();
15
18
  tmpIndex = 0;
16
- constructor(metadata, platform) {
19
+ constructor(metadata, platform, config) {
17
20
  this.metadata = metadata;
18
21
  this.platform = platform;
22
+ this.config = config;
19
23
  }
20
24
  /**
21
25
  * Computes difference between two entities.
@@ -33,22 +37,22 @@ export class EntityComparator {
33
37
  * References will be mapped to primary keys, collections to arrays of primary keys.
34
38
  */
35
39
  prepareEntity(entity) {
36
- const generator = this.getSnapshotGenerator(entity.constructor.name);
40
+ const generator = this.getSnapshotGenerator(entity.constructor);
37
41
  return Utils.callCompiledFunction(generator, entity);
38
42
  }
39
43
  /**
40
44
  * Maps database columns to properties.
41
45
  */
42
- mapResult(entityName, result) {
43
- const mapper = this.getResultMapper(entityName);
46
+ mapResult(meta, result) {
47
+ const mapper = this.getResultMapper(meta);
44
48
  return Utils.callCompiledFunction(mapper, result);
45
49
  }
46
50
  /**
47
51
  * @internal Highly performance-sensitive method.
48
52
  */
49
53
  getPkGetter(meta) {
50
- const exists = this.pkGetters.get(meta.className);
51
- /* v8 ignore next 3 */
54
+ const exists = this.pkGetters.get(meta);
55
+ /* v8 ignore next */
52
56
  if (exists) {
53
57
  return exists;
54
58
  }
@@ -87,18 +91,19 @@ export class EntityComparator {
87
91
  }
88
92
  lines.push(` return entity${this.wrap(pk)};`);
89
93
  }
90
- const code = `// compiled pk serializer for entity ${meta.className}\n`
94
+ const code = `// compiled pk getter for entity ${meta.className}\n`
91
95
  + `return function(entity) {\n${lines.join('\n')}\n}`;
92
- const pkSerializer = Utils.createFunction(context, code);
93
- this.pkGetters.set(meta.className, pkSerializer);
96
+ const fnKey = `pkGetter-${meta.uniqueName}`;
97
+ const pkSerializer = Utils.createFunction(context, code, this.config?.get('compiledFunctions'), fnKey);
98
+ this.pkGetters.set(meta, pkSerializer);
94
99
  return pkSerializer;
95
100
  }
96
101
  /**
97
102
  * @internal Highly performance-sensitive method.
98
103
  */
99
104
  getPkGetterConverted(meta) {
100
- const exists = this.pkGettersConverted.get(meta.className);
101
- /* v8 ignore next 3 */
105
+ const exists = this.pkGettersConverted.get(meta);
106
+ /* v8 ignore next */
102
107
  if (exists) {
103
108
  return exists;
104
109
  }
@@ -139,16 +144,17 @@ export class EntityComparator {
139
144
  }
140
145
  const code = `// compiled pk getter (with converted custom types) for entity ${meta.className}\n`
141
146
  + `return function(entity) {\n${lines.join('\n')}\n}`;
142
- const pkSerializer = Utils.createFunction(context, code);
143
- this.pkGettersConverted.set(meta.className, pkSerializer);
147
+ const fnKey = `pkGetterConverted-${meta.uniqueName}`;
148
+ const pkSerializer = Utils.createFunction(context, code, this.config?.get('compiledFunctions'), fnKey);
149
+ this.pkGettersConverted.set(meta, pkSerializer);
144
150
  return pkSerializer;
145
151
  }
146
152
  /**
147
153
  * @internal Highly performance-sensitive method.
148
154
  */
149
155
  getPkSerializer(meta) {
150
- const exists = this.pkSerializers.get(meta.className);
151
- /* v8 ignore next 3 */
156
+ const exists = this.pkSerializers.get(meta);
157
+ /* v8 ignore next */
152
158
  if (exists) {
153
159
  return exists;
154
160
  }
@@ -191,24 +197,25 @@ export class EntityComparator {
191
197
  }
192
198
  const code = `// compiled pk serializer for entity ${meta.className}\n`
193
199
  + `return function(entity) {\n${lines.join('\n')}\n}`;
194
- const pkSerializer = Utils.createFunction(context, code);
195
- this.pkSerializers.set(meta.className, pkSerializer);
200
+ const fnKey = `pkSerializer-${meta.uniqueName}`;
201
+ const pkSerializer = Utils.createFunction(context, code, this.config?.get('compiledFunctions'), fnKey);
202
+ this.pkSerializers.set(meta, pkSerializer);
196
203
  return pkSerializer;
197
204
  }
198
205
  /**
199
206
  * @internal Highly performance-sensitive method.
200
207
  */
201
208
  getSnapshotGenerator(entityName) {
202
- const exists = this.snapshotGenerators.get(entityName);
209
+ const meta = this.metadata.find(entityName);
210
+ const exists = this.snapshotGenerators.get(meta);
203
211
  if (exists) {
204
212
  return exists;
205
213
  }
206
- const meta = this.metadata.find(entityName);
207
214
  const lines = [];
208
215
  const context = new Map();
209
216
  context.set('clone', clone);
210
217
  context.set('cloneEmbeddable', (o) => this.platform.cloneEmbeddable(o)); // do not clone prototypes
211
- if (meta.discriminatorValue) {
218
+ if (meta.root.inheritanceType === 'sti' && meta.discriminatorValue) {
212
219
  lines.push(` ret${this.wrap(meta.root.discriminatorColumn)} = '${meta.discriminatorValue}'`);
213
220
  }
214
221
  const getRootProperty = (prop) => prop.embedded ? getRootProperty(meta.properties[prop.embedded[0]]) : prop;
@@ -220,8 +227,9 @@ export class EntityComparator {
220
227
  })
221
228
  .forEach(prop => lines.push(this.getPropertySnapshot(meta, prop, context, this.wrap(prop.name), this.wrap(prop.name), [prop.name])));
222
229
  const code = `return function(entity) {\n const ret = {};\n${lines.join('\n')}\n return ret;\n}`;
223
- const snapshotGenerator = Utils.createFunction(context, code);
224
- this.snapshotGenerators.set(entityName, snapshotGenerator);
230
+ const fnKey = `snapshotGenerator-${meta.uniqueName}`;
231
+ const snapshotGenerator = Utils.createFunction(context, code, this.config?.get('compiledFunctions'), fnKey);
232
+ this.snapshotGenerators.set(meta, snapshotGenerator);
225
233
  return snapshotGenerator;
226
234
  }
227
235
  /**
@@ -271,23 +279,27 @@ export class EntityComparator {
271
279
  /**
272
280
  * @internal Highly performance-sensitive method.
273
281
  */
274
- getResultMapper(entityName) {
275
- const exists = this.mappers.get(entityName);
282
+ getResultMapper(meta) {
283
+ const exists = this.mappers.get(meta);
276
284
  if (exists) {
277
285
  return exists;
278
286
  }
279
- const meta = this.metadata.get(entityName);
280
287
  const lines = [];
281
288
  const context = new Map();
289
+ context.set('PolymorphicRef', PolymorphicRef);
282
290
  const tz = this.platform.getTimezone();
283
291
  const parseDate = (key, value, padding = '') => {
284
292
  lines.push(`${padding} if (${value} == null || ${value} instanceof Date) {`);
285
293
  lines.push(`${padding} ${key} = ${value};`);
286
294
  if (!tz || tz === 'local') {
295
+ lines.push(`${padding} } else if (typeof ${value} === 'bigint') {`);
296
+ lines.push(`${padding} ${key} = parseDate(Number(${value}));`);
287
297
  lines.push(`${padding} } else {`);
288
298
  lines.push(`${padding} ${key} = parseDate(${value});`);
289
299
  }
290
300
  else {
301
+ lines.push(`${padding} } else if (typeof ${value} === 'bigint') {`);
302
+ lines.push(`${padding} ${key} = parseDate(Number(${value}));`);
291
303
  lines.push(`${padding} } else if (typeof ${value} === 'number' || ${value}.includes('+') || ${value}.lastIndexOf('-') > 10 || ${value}.endsWith('Z')) {`);
292
304
  lines.push(`${padding} ${key} = parseDate(${value});`);
293
305
  lines.push(`${padding} } else {`);
@@ -301,12 +313,28 @@ export class EntityComparator {
301
313
  if (!prop.fieldNames) {
302
314
  continue;
303
315
  }
316
+ if (prop.polymorphic && prop.fieldNames.length >= 2) {
317
+ const discriminatorField = prop.fieldNames[0];
318
+ const idFields = prop.fieldNames.slice(1);
319
+ lines.push(`${padding} if (${prop.fieldNames.map(field => `typeof ${this.propName(field)} === 'undefined'`).join(' && ')}) {`);
320
+ lines.push(`${padding} } else if (${prop.fieldNames.map(field => `${this.propName(field)} != null`).join(' && ')}) {`);
321
+ if (idFields.length === 1) {
322
+ lines.push(`${padding} ret${this.wrap(prop.name)} = new PolymorphicRef(${this.propName(discriminatorField)}, ${this.propName(idFields[0])});`);
323
+ }
324
+ else {
325
+ lines.push(`${padding} ret${this.wrap(prop.name)} = new PolymorphicRef(${this.propName(discriminatorField)}, [${idFields.map(f => this.propName(f)).join(', ')}]);`);
326
+ }
327
+ lines.push(...prop.fieldNames.map(field => `${padding} ${this.propName(field, 'mapped')} = true;`));
328
+ lines.push(`${padding} } else if (${prop.fieldNames.map(field => `${this.propName(field)} == null`).join(' && ')}) {\n${padding} ret${this.wrap(prop.name)} = null;`);
329
+ lines.push(...prop.fieldNames.map(field => `${padding} ${this.propName(field, 'mapped')} = true;`), ' }');
330
+ continue;
331
+ }
304
332
  if (prop.targetMeta && prop.fieldNames.length > 1) {
305
333
  lines.push(`${padding} if (${prop.fieldNames.map(field => `typeof ${this.propName(field)} === 'undefined'`).join(' && ')}) {`);
306
334
  lines.push(`${padding} } else if (${prop.fieldNames.map(field => `${this.propName(field)} != null`).join(' && ')}) {`);
307
335
  lines.push(`${padding} ret${this.wrap(prop.name)} = ${this.createCompositeKeyArray(prop)};`);
308
336
  lines.push(...prop.fieldNames.map(field => `${padding} ${this.propName(field, 'mapped')} = true;`));
309
- lines.push(`${padding} } else if (${prop.fieldNames.map(field => `${this.propName(field)} == null`).join(' && ')}) {\n ret${this.wrap(prop.name)} = null;`);
337
+ lines.push(`${padding} } else if (${prop.fieldNames.map(field => `${this.propName(field)} == null`).join(' && ')}) {\n${padding} ret${this.wrap(prop.name)} = null;`);
310
338
  lines.push(...prop.fieldNames.map(field => `${padding} ${this.propName(field, 'mapped')} = true;`), ' }');
311
339
  continue;
312
340
  }
@@ -331,9 +359,9 @@ export class EntityComparator {
331
359
  context.set(`mapEmbeddedResult_${idx}`, (data) => {
332
360
  const item = parseJsonSafe(data);
333
361
  if (Array.isArray(item)) {
334
- return item.map(row => row == null ? row : this.getResultMapper(prop.type)(row));
362
+ return item.map(row => row == null ? row : this.getResultMapper(prop.targetMeta)(row));
335
363
  }
336
- return item == null ? item : this.getResultMapper(prop.type)(item);
364
+ return item == null ? item : this.getResultMapper(prop.targetMeta)(item);
337
365
  });
338
366
  lines.push(`${padding} if (typeof ${this.propName(prop.fieldNames[0])} !== 'undefined') {`);
339
367
  lines.push(`${padding} ret${this.wrap(prop.name)} = ${this.propName(prop.fieldNames[0])} == null ? ${this.propName(prop.fieldNames[0])} : mapEmbeddedResult_${idx}(${this.propName(prop.fieldNames[0])});`);
@@ -362,11 +390,12 @@ export class EntityComparator {
362
390
  else {
363
391
  mapEntityProperties(meta);
364
392
  }
365
- lines.push(` for (let k in result) { if (Object.hasOwn(result, k) && !mapped[k]) ret[k] = result[k]; }`);
393
+ lines.push(` for (let k in result) { if (Object.hasOwn(result, k) && !mapped[k] && ret[k] === undefined) ret[k] = result[k]; }`);
366
394
  const code = `// compiled mapper for entity ${meta.className}\n`
367
395
  + `return function(result) {\n const ret = {};\n${lines.join('\n')}\n return ret;\n}`;
368
- const resultMapper = Utils.createFunction(context, code);
369
- this.mappers.set(entityName, resultMapper);
396
+ const fnKey = `resultMapper-${meta.uniqueName}`;
397
+ const resultMapper = Utils.createFunction(context, code, this.config?.get('compiledFunctions'), fnKey);
398
+ this.mappers.set(meta, resultMapper);
370
399
  return resultMapper;
371
400
  }
372
401
  getPropertyCondition(path) {
@@ -417,11 +446,21 @@ export class EntityComparator {
417
446
  }
418
447
  getEmbeddedPropertySnapshot(meta, prop, context, level, path, dataKey, object = prop.object) {
419
448
  const padding = ' '.repeat(level * 2);
449
+ const nullCond = `entity${path.map(k => this.wrap(k)).join('')} === null`;
420
450
  let ret = `${level === 1 ? '' : '\n'}`;
421
451
  if (object) {
422
- const nullCond = `entity${path.map(k => this.wrap(k)).join('')} === null`;
423
452
  ret += `${padding}if (${nullCond}) ret${dataKey} = null;\n`;
424
453
  }
454
+ else {
455
+ ret += `${padding}if (${nullCond}) {\n`;
456
+ ret += meta.props.filter(p => p.embedded?.[0] === prop.name
457
+ // object for JSON embeddable
458
+ && (p.object || (p.persist !== false))).map(childProp => {
459
+ const childDataKey = meta.embeddable || prop.object ? dataKey + this.wrap(childProp.embedded[1]) : this.wrap(childProp.name);
460
+ return `${padding} ret${childDataKey} = null;`;
461
+ }).join('\n') + `\n`;
462
+ ret += `${padding}}\n`;
463
+ }
425
464
  const cond = `entity${path.map(k => this.wrap(k)).join('')} != null`;
426
465
  ret += `${padding}if (${cond}) {\n`;
427
466
  if (object) {
@@ -466,8 +505,8 @@ export class EntityComparator {
466
505
  registerCustomType(prop, context) {
467
506
  const convertorKey = this.safeKey(prop.name);
468
507
  context.set(`convertToDatabaseValue_${convertorKey}`, (val) => {
469
- /* v8 ignore next 3 */
470
- if (RawQueryFragment.isKnownFragment(val)) {
508
+ /* v8 ignore next */
509
+ if (Raw.isKnownFragment(val)) {
471
510
  return val;
472
511
  }
473
512
  return prop.customType.convertToDatabaseValue(val, this.platform, { mode: 'serialization' });
@@ -496,16 +535,51 @@ export class EntityComparator {
496
535
  ret += ` ret${dataKey} = entity${entityKey};\n`;
497
536
  }
498
537
  }
538
+ else if (prop.polymorphic) {
539
+ const discriminatorMapKey = `discriminatorMapReverse_${prop.name}`;
540
+ const reverseMap = new Map();
541
+ for (const [key, value] of Object.entries(prop.discriminatorMap)) {
542
+ reverseMap.set(value, key);
543
+ }
544
+ context.set(discriminatorMapKey, reverseMap);
545
+ this.setToArrayHelper(context);
546
+ context.set('EntityIdentifier', EntityIdentifier);
547
+ context.set('PolymorphicRef', PolymorphicRef);
548
+ ret += ` if (entity${entityKey} === null) {\n`;
549
+ ret += ` ret${dataKey} = null;\n`;
550
+ ret += ` } else if (typeof entity${entityKey} !== 'undefined') {\n`;
551
+ ret += ` const val${level} = entity${entityKey}${unwrap};\n`;
552
+ ret += ` const discriminator = ${discriminatorMapKey}.get(val${level}?.constructor);\n`;
553
+ ret += ` const pk = val${level}?.__helper?.__identifier && !val${level}?.__helper?.hasPrimaryKey()\n`;
554
+ ret += ` ? val${level}.__helper.__identifier\n`;
555
+ ret += ` : toArray(val${level}?.__helper?.getPrimaryKey(true));\n`;
556
+ ret += ` ret${dataKey} = new PolymorphicRef(discriminator, pk);\n`;
557
+ ret += ` }\n`;
558
+ }
559
+ else if (prop.targetKey) {
560
+ // When targetKey is set, extract that property value instead of the PK
561
+ const targetProp = prop.targetMeta?.properties[prop.targetKey];
562
+ ret += ` if (entity${entityKey} === null) {\n`;
563
+ ret += ` ret${dataKey} = null;\n`;
564
+ ret += ` } else if (typeof entity${entityKey} !== 'undefined') {\n`;
565
+ ret += ` const val${level} = entity${entityKey}${unwrap};\n`;
566
+ if (targetProp?.customType) {
567
+ // If targetKey property has a custom type, convert to database value
568
+ const convertorKey = this.registerCustomType(targetProp, context);
569
+ ret += ` ret${dataKey} = convertToDatabaseValue_${convertorKey}(val${level}?.${prop.targetKey});\n`;
570
+ }
571
+ else {
572
+ ret += ` ret${dataKey} = val${level}?.${prop.targetKey};\n`;
573
+ }
574
+ ret += ` }\n`;
575
+ }
499
576
  else {
500
- const toArray = (val) => {
501
- if (Utils.isPlainObject(val)) {
502
- return Object.values(val).map(v => toArray(v));
503
- }
504
- return val;
505
- };
506
- context.set('toArray', toArray);
577
+ this.setToArrayHelper(context);
578
+ context.set('EntityIdentifier', EntityIdentifier);
507
579
  ret += ` if (entity${entityKey} === null) {\n`;
508
580
  ret += ` ret${dataKey} = null;\n`;
581
+ ret += ` } else if (entity${entityKey}?.__helper.__identifier && !entity${entityKey}.__helper.hasPrimaryKey()) {\n`;
582
+ ret += ` ret${dataKey} = entity${entityKey}?.__helper.__identifier;\n`;
509
583
  ret += ` } else if (typeof entity${entityKey} !== 'undefined') {\n`;
510
584
  ret += ` ret${dataKey} = toArray(entity${entityKey}.__helper.getPrimaryKey(true));\n`;
511
585
  ret += ` }\n`;
@@ -529,11 +603,11 @@ export class EntityComparator {
529
603
  * @internal Highly performance-sensitive method.
530
604
  */
531
605
  getEntityComparator(entityName) {
532
- const exists = this.comparators.get(entityName);
606
+ const meta = this.metadata.find(entityName);
607
+ const exists = this.comparators.get(meta);
533
608
  if (exists) {
534
609
  return exists;
535
610
  }
536
- const meta = this.metadata.find(entityName);
537
611
  const lines = [];
538
612
  const context = new Map();
539
613
  context.set('compareArrays', compareArrays);
@@ -542,10 +616,7 @@ export class EntityComparator {
542
616
  context.set('compareObjects', compareObjects);
543
617
  context.set('equals', equals);
544
618
  for (const prop of meta.comparableProps) {
545
- // skip properties that are not hydrated
546
- if (prop.hydrate !== false) {
547
- lines.push(this.getPropertyComparator(prop, context));
548
- }
619
+ lines.push(this.getPropertyComparator(prop, context));
549
620
  }
550
621
  // also compare 1:1 inverse sides, important for `factory.mergeData`
551
622
  lines.push(`if (options?.includeInverseSides) {`);
@@ -557,12 +628,15 @@ export class EntityComparator {
557
628
  lines.push(`}`);
558
629
  const code = `// compiled comparator for entity ${meta.className}\n`
559
630
  + `return function(last, current, options) {\n const diff = {};\n${lines.join('\n')}\n return diff;\n}`;
560
- const comparator = Utils.createFunction(context, code);
561
- this.comparators.set(entityName, comparator);
631
+ const fnKey = `comparator-${meta.uniqueName}`;
632
+ const comparator = Utils.createFunction(context, code, this.config?.get('compiledFunctions'), fnKey);
633
+ this.comparators.set(meta, comparator);
562
634
  return comparator;
563
635
  }
564
636
  getGenericComparator(prop, cond) {
565
- return ` if (current${prop} == null && last${prop} == null) {\n\n` +
637
+ return ` if (current${prop} === null && last${prop} === undefined) {\n` +
638
+ ` diff${prop} = current${prop};\n` +
639
+ ` } else if (current${prop} == null && last${prop} == null) {\n\n` +
566
640
  ` } else if ((current${prop} != null && last${prop} == null) || (current${prop} == null && last${prop} != null)) {\n` +
567
641
  ` diff${prop} = current${prop};\n` +
568
642
  ` } else if (${cond}) {\n` +
@@ -572,18 +646,28 @@ export class EntityComparator {
572
646
  getPropertyComparator(prop, context) {
573
647
  let type = prop.type.toLowerCase();
574
648
  if (prop.kind !== ReferenceKind.SCALAR && prop.kind !== ReferenceKind.EMBEDDED) {
575
- const meta2 = this.metadata.find(prop.type);
576
- if (meta2.primaryKeys.length > 1) {
577
- type = 'array';
649
+ if (prop.polymorphic) {
650
+ type = 'object';
578
651
  }
579
652
  else {
580
- type = meta2.properties[meta2.primaryKeys[0]].type.toLowerCase();
653
+ const meta2 = prop.targetMeta;
654
+ if (meta2.primaryKeys.length > 1) {
655
+ type = 'array';
656
+ }
657
+ else {
658
+ type = meta2.getPrimaryProp().type.toLowerCase();
659
+ }
581
660
  }
582
661
  }
583
662
  if (prop.customType) {
584
663
  if (prop.customType.compareValues) {
585
664
  const idx = this.tmpIndex++;
586
- context.set(`compareValues_${idx}`, (a, b) => prop.customType.compareValues(a, b));
665
+ context.set(`compareValues_${idx}`, (a, b) => {
666
+ if (Raw.isKnownFragment(a) || Raw.isKnownFragment(b)) {
667
+ return Raw.getKnownFragment(a) === Raw.getKnownFragment(b);
668
+ }
669
+ return prop.customType.compareValues(a, b);
670
+ });
587
671
  return this.getGenericComparator(this.wrap(prop.name), `!compareValues_${idx}(last${this.wrap(prop.name)}, current${this.wrap(prop.name)})`);
588
672
  }
589
673
  type = prop.customType.compareAsType().toLowerCase();
@@ -603,10 +687,10 @@ export class EntityComparator {
603
687
  if (['buffer', 'uint8array'].includes(type)) {
604
688
  return this.getGenericComparator(this.wrap(prop.name), `!compareBuffers(last${this.wrap(prop.name)}, current${this.wrap(prop.name)})`);
605
689
  }
606
- if (['date'].includes(type)) {
690
+ if (type === 'date') {
607
691
  return this.getGenericComparator(this.wrap(prop.name), `last${this.wrap(prop.name)}.valueOf() !== current${this.wrap(prop.name)}.valueOf()`);
608
692
  }
609
- if (['objectid'].includes(type)) {
693
+ if (type === 'objectid') {
610
694
  // We might be comparing PK to object, in case we compare with cached data of populated entity
611
695
  // in such case we just ignore the comparison and fallback to `equals()` (which will still mark
612
696
  // it as not equal as we compare PK to plain object).
@@ -624,6 +708,22 @@ export class EntityComparator {
624
708
  safeKey(key) {
625
709
  return key.replace(/\W/g, '_');
626
710
  }
711
+ /**
712
+ * Sets the toArray helper in the context if not already set.
713
+ * Used for converting composite PKs to arrays.
714
+ */
715
+ setToArrayHelper(context) {
716
+ if (context.has('toArray')) {
717
+ return;
718
+ }
719
+ const toArray = (val) => {
720
+ if (Utils.isPlainObject(val)) {
721
+ return Object.values(val).map(v => toArray(v));
722
+ }
723
+ return val;
724
+ };
725
+ context.set('toArray', toArray);
726
+ }
627
727
  /**
628
728
  * perf: used to generate list of comparable properties during discovery, so we speed up the runtime comparison
629
729
  */
@@ -1,11 +1,17 @@
1
- import type { Dictionary, EntityMetadata, EntityProperty, FilterDef, FilterQuery } from '../typings.js';
1
+ import type { Dictionary, EntityMetadata, EntityName, EntityProperty, FilterDef, FilterQuery } from '../typings.js';
2
+ import { type QueryOrderMap } from '../enums.js';
2
3
  import type { Platform } from '../platforms/Platform.js';
3
4
  import type { MetadataStorage } from '../metadata/MetadataStorage.js';
5
+ import type { FilterOptions } from '../drivers/IDatabaseDriver.js';
4
6
  /** @internal */
5
7
  export declare class QueryHelper {
6
8
  static readonly SUPPORTED_OPERATORS: string[];
9
+ /**
10
+ * Finds the discriminator value (key) for a given entity class in a discriminator map.
11
+ */
12
+ static findDiscriminatorValue<T>(discriminatorMap: Dictionary<T>, targetClass: T): string | undefined;
7
13
  static processParams(params: unknown): any;
8
- static processObjectParams<T extends object>(params?: T): T;
14
+ static processObjectParams<T extends Dictionary>(params?: T): T;
9
15
  /**
10
16
  * converts `{ account: { $or: [ [Object], [Object] ] } }`
11
17
  * to `{ $or: [ { account: [Object] }, { account: [Object] } ] }`
@@ -13,21 +19,27 @@ export declare class QueryHelper {
13
19
  static liftGroupOperators<T extends object>(where: Dictionary, meta: EntityMetadata<T>, metadata: MetadataStorage, key?: string): string | undefined;
14
20
  static inlinePrimaryKeyObjects<T extends object>(where: Dictionary, meta: EntityMetadata<T>, metadata: MetadataStorage, key?: string): boolean;
15
21
  static processWhere<T extends object>(options: ProcessWhereOptions<T>): FilterQuery<T>;
16
- static getActiveFilters(entityName: string, options: Dictionary<boolean | Dictionary> | string[] | boolean, filters: Dictionary<FilterDef>): FilterDef[];
17
- static isFilterActive(entityName: string, filterName: string, filter: FilterDef, options: Dictionary<boolean | Dictionary>): boolean;
22
+ static getActiveFilters<T>(meta: EntityMetadata<T>, options: FilterOptions | undefined, filters: Dictionary<FilterDef>): FilterDef[];
23
+ static mergePropertyFilters(propFilters: FilterOptions | undefined, options: FilterOptions | undefined): FilterOptions | undefined;
24
+ static isFilterActive<T>(meta: EntityMetadata<T>, filterName: string, filter: FilterDef, options: Dictionary<boolean | Dictionary>): boolean;
18
25
  static processCustomType<T extends object>(prop: EntityProperty<T>, cond: FilterQuery<T>, platform: Platform, key?: string, fromQuery?: boolean): FilterQuery<T>;
19
26
  private static isSupportedOperator;
20
27
  private static processJsonCondition;
21
28
  private static getValueType;
22
29
  static findProperty<T>(fieldName: string, options: ProcessWhereOptions<T>): EntityProperty<T> | undefined;
30
+ /**
31
+ * Merges multiple orderBy sources with key-level deduplication (first-seen key wins).
32
+ * RawQueryFragment symbol keys are never deduped (each is unique).
33
+ */
34
+ static mergeOrderBy<T>(...sources: (QueryOrderMap<T> | QueryOrderMap<T>[] | undefined)[]): QueryOrderMap<T>[];
23
35
  }
24
36
  interface ProcessWhereOptions<T> {
25
37
  where: FilterQuery<T>;
26
- entityName: string;
38
+ entityName: EntityName<T>;
27
39
  metadata: MetadataStorage;
28
40
  platform: Platform;
29
41
  aliased?: boolean;
30
- aliasMap?: Dictionary<string>;
42
+ aliasMap?: Dictionary<EntityName>;
31
43
  convertCustomTypes?: boolean;
32
44
  root?: boolean;
33
45
  type?: 'where' | 'orderBy';