@mikro-orm/core 7.0.0-dev.30 → 7.0.0-dev.300

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 +68 -60
  2. package/EntityManager.js +290 -259
  3. package/MikroORM.d.ts +44 -35
  4. package/MikroORM.js +109 -142
  5. package/README.md +2 -0
  6. package/cache/FileCacheAdapter.d.ts +1 -2
  7. package/cache/FileCacheAdapter.js +18 -11
  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 +119 -36
  16. package/drivers/IDatabaseDriver.d.ts +118 -23
  17. package/entity/BaseEntity.d.ts +63 -4
  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.js +17 -17
  22. package/entity/EntityFactory.d.ts +7 -1
  23. package/entity/EntityFactory.js +87 -55
  24. package/entity/EntityHelper.d.ts +2 -2
  25. package/entity/EntityHelper.js +57 -19
  26. package/entity/EntityLoader.d.ts +11 -10
  27. package/entity/EntityLoader.js +213 -82
  28. package/entity/EntityRepository.d.ts +28 -8
  29. package/entity/EntityRepository.js +8 -2
  30. package/entity/PolymorphicRef.d.ts +12 -0
  31. package/entity/PolymorphicRef.js +18 -0
  32. package/entity/Reference.d.ts +1 -5
  33. package/entity/Reference.js +15 -11
  34. package/entity/WrappedEntity.d.ts +3 -8
  35. package/entity/WrappedEntity.js +2 -7
  36. package/entity/defineEntity.d.ts +526 -310
  37. package/entity/defineEntity.js +134 -290
  38. package/entity/index.d.ts +2 -2
  39. package/entity/index.js +2 -2
  40. package/entity/utils.d.ts +6 -1
  41. package/entity/utils.js +34 -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 +79 -34
  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 +782 -325
  68. package/metadata/MetadataProvider.d.ts +11 -2
  69. package/metadata/MetadataProvider.js +66 -2
  70. package/metadata/MetadataStorage.d.ts +13 -11
  71. package/metadata/MetadataStorage.js +72 -39
  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 +577 -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 +22 -11
  92. package/platforms/ExceptionConverter.js +1 -1
  93. package/platforms/Platform.d.ts +11 -15
  94. package/platforms/Platform.js +24 -44
  95. package/serialization/EntitySerializer.d.ts +6 -3
  96. package/serialization/EntitySerializer.js +46 -26
  97. package/serialization/EntityTransformer.js +33 -21
  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.js +1 -1
  103. package/types/BlobType.d.ts +0 -1
  104. package/types/BlobType.js +0 -3
  105. package/types/BooleanType.d.ts +1 -0
  106. package/types/BooleanType.js +3 -0
  107. package/types/DecimalType.js +2 -2
  108. package/types/DoubleType.js +1 -1
  109. package/types/EnumArrayType.js +1 -2
  110. package/types/JsonType.d.ts +1 -1
  111. package/types/JsonType.js +7 -2
  112. package/types/TinyIntType.js +1 -1
  113. package/types/Type.d.ts +2 -4
  114. package/types/Type.js +3 -3
  115. package/types/Uint8ArrayType.d.ts +0 -1
  116. package/types/Uint8ArrayType.js +1 -4
  117. package/types/index.d.ts +1 -1
  118. package/typings.d.ts +412 -155
  119. package/typings.js +99 -44
  120. package/unit-of-work/ChangeSet.d.ts +4 -6
  121. package/unit-of-work/ChangeSet.js +4 -5
  122. package/unit-of-work/ChangeSetComputer.d.ts +3 -8
  123. package/unit-of-work/ChangeSetComputer.js +41 -20
  124. package/unit-of-work/ChangeSetPersister.d.ts +13 -12
  125. package/unit-of-work/ChangeSetPersister.js +94 -36
  126. package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
  127. package/unit-of-work/CommitOrderCalculator.js +13 -13
  128. package/unit-of-work/IdentityMap.d.ts +12 -0
  129. package/unit-of-work/IdentityMap.js +39 -1
  130. package/unit-of-work/UnitOfWork.d.ts +27 -3
  131. package/unit-of-work/UnitOfWork.js +248 -90
  132. package/utils/AbstractMigrator.d.ts +101 -0
  133. package/utils/AbstractMigrator.js +305 -0
  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 -211
  139. package/utils/Configuration.js +153 -194
  140. package/utils/ConfigurationLoader.d.ts +1 -52
  141. package/utils/ConfigurationLoader.js +1 -330
  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 +154 -56
  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 +9 -6
  155. package/utils/Utils.d.ts +15 -126
  156. package/utils/Utils.js +80 -382
  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 +34 -0
  161. package/utils/fs-utils.js +196 -0
  162. package/utils/index.d.ts +1 -3
  163. package/utils/index.js +1 -3
  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,42 +1,47 @@
1
1
  import { Hydrator } from './Hydrator.js';
2
2
  import { Collection } from '../entity/Collection.js';
3
3
  import { Reference, ScalarReference } from '../entity/Reference.js';
4
+ import { PolymorphicRef } from '../entity/PolymorphicRef.js';
4
5
  import { parseJsonSafe, Utils } from '../utils/Utils.js';
5
6
  import { ReferenceKind } from '../enums.js';
6
- import { RawQueryFragment } from '../utils/RawQueryFragment.js';
7
+ import { Raw } from '../utils/RawQueryFragment.js';
8
+ import { ValidationError } from '../errors.js';
7
9
  export class ObjectHydrator extends Hydrator {
8
10
  hydrators = {
9
- full: new Map(),
10
- reference: new Map(),
11
+ 'full~true': new Map(),
12
+ 'full~false': new Map(),
13
+ 'reference~true': new Map(),
14
+ 'reference~false': new Map(),
11
15
  };
12
16
  tmpIndex = 0;
13
17
  /**
14
18
  * @inheritDoc
15
19
  */
16
- hydrate(entity, meta, data, factory, type, newEntity = false, convertCustomTypes = false, schema, parentSchema) {
17
- const hydrate = this.getEntityHydrator(meta, type);
20
+ hydrate(entity, meta, data, factory, type, newEntity = false, convertCustomTypes = false, schema, parentSchema, normalizeAccessors) {
21
+ const hydrate = this.getEntityHydrator(meta, type, normalizeAccessors);
18
22
  const running = this.running;
19
23
  // the running state is used to consider propagation as hydration, saving the values directly to the entity data,
20
24
  // but we don't want that for new entities, their propagation should result in entity updates when flushing
21
25
  this.running = !newEntity;
22
- Utils.callCompiledFunction(hydrate, entity, data, factory, newEntity, convertCustomTypes, schema, parentSchema);
26
+ Utils.callCompiledFunction(hydrate, entity, data, factory, newEntity, convertCustomTypes, schema, parentSchema, normalizeAccessors);
23
27
  this.running = running;
24
28
  }
25
29
  /**
26
30
  * @inheritDoc
27
31
  */
28
- hydrateReference(entity, meta, data, factory, convertCustomTypes = false, schema, parentSchema) {
29
- const hydrate = this.getEntityHydrator(meta, 'reference');
32
+ hydrateReference(entity, meta, data, factory, convertCustomTypes = false, schema, parentSchema, normalizeAccessors) {
33
+ const hydrate = this.getEntityHydrator(meta, 'reference', normalizeAccessors);
30
34
  const running = this.running;
31
35
  this.running = true;
32
- Utils.callCompiledFunction(hydrate, entity, data, factory, false, convertCustomTypes, schema, parentSchema);
36
+ Utils.callCompiledFunction(hydrate, entity, data, factory, false, convertCustomTypes, schema, parentSchema, normalizeAccessors);
33
37
  this.running = running;
34
38
  }
35
39
  /**
36
40
  * @internal Highly performance-sensitive method.
37
41
  */
38
- getEntityHydrator(meta, type) {
39
- const exists = this.hydrators[type].get(meta.className);
42
+ getEntityHydrator(meta, type, normalizeAccessors = false) {
43
+ const key = `${type}~${normalizeAccessors}`;
44
+ const exists = this.hydrators[key].get(meta.class);
40
45
  if (exists) {
41
46
  return exists;
42
47
  }
@@ -46,17 +51,19 @@ export class ObjectHydrator extends Hydrator {
46
51
  context.set('isPrimaryKey', Utils.isPrimaryKey);
47
52
  context.set('Collection', Collection);
48
53
  context.set('Reference', Reference);
54
+ context.set('PolymorphicRef', PolymorphicRef);
55
+ context.set('ValidationError', ValidationError);
49
56
  const registerCustomType = (prop, convertorKey, method, context) => {
50
57
  context.set(`${method}_${convertorKey}`, (val) => {
51
- /* v8 ignore next 3 */
52
- if (RawQueryFragment.isKnownFragment(val)) {
58
+ /* v8 ignore next */
59
+ if (Raw.isKnownFragment(val)) {
53
60
  return val;
54
61
  }
55
62
  return prop.customType[method](val, this.platform, { mode: 'serialization' });
56
63
  });
57
64
  return convertorKey;
58
65
  };
59
- const hydrateScalar = (prop, object, path, dataKey) => {
66
+ const hydrateScalar = (prop, path, dataKey) => {
60
67
  const entityKey = path.map(k => this.wrap(k)).join('');
61
68
  const tz = this.platform.getTimezone();
62
69
  const convertorKey = path.filter(k => !k.match(/\[idx_\d+]/)).map(k => this.safeKey(k)).join('_');
@@ -131,24 +138,56 @@ export class ObjectHydrator extends Hydrator {
131
138
  const nullVal = this.config.get('forceUndefined') ? 'undefined' : 'null';
132
139
  ret.push(` if (data${dataKey} === null) {\n entity${entityKey} = ${nullVal};`);
133
140
  ret.push(` } else if (typeof data${dataKey} !== 'undefined') {`);
134
- ret.push(` if (isPrimaryKey(data${dataKey}, true)) {`);
135
- if (prop.ref) {
136
- ret.push(` entity${entityKey} = Reference.create(factory.createReference('${prop.type}', data${dataKey}, { merge: true, convertCustomTypes, schema }));`);
141
+ // For polymorphic: instanceof check; for regular: isPrimaryKey() check
142
+ const pkCheck = prop.polymorphic ? `data${dataKey} instanceof PolymorphicRef` : `isPrimaryKey(data${dataKey}, true)`;
143
+ ret.push(` if (${pkCheck}) {`);
144
+ // When targetKey is set, pass the key option to createReference so it uses the alternate key
145
+ const keyOption = prop.targetKey ? `, key: '${prop.targetKey}'` : '';
146
+ if (prop.polymorphic) {
147
+ // For polymorphic: target class from discriminator map, PK from data.id
148
+ const discriminatorMapKey = this.safeKey(`discriminatorMap_${prop.name}_${this.tmpIndex++}`);
149
+ context.set(discriminatorMapKey, prop.discriminatorMap);
150
+ ret.push(` const targetClass = ${discriminatorMapKey}[data${dataKey}.discriminator];`);
151
+ ret.push(` if (!targetClass) throw new ValidationError(\`Unknown discriminator value '\${data${dataKey}.discriminator}' for polymorphic relation '${prop.name}'. Valid values: \${Object.keys(${discriminatorMapKey}).join(', ')}\`);`);
152
+ if (prop.ref) {
153
+ ret.push(` entity${entityKey} = Reference.create(factory.createReference(targetClass, data${dataKey}.id, { merge: true, convertCustomTypes, normalizeAccessors, schema${keyOption} }));`);
154
+ }
155
+ else {
156
+ ret.push(` entity${entityKey} = factory.createReference(targetClass, data${dataKey}.id, { merge: true, convertCustomTypes, normalizeAccessors, schema${keyOption} });`);
157
+ }
137
158
  }
138
159
  else {
139
- ret.push(` entity${entityKey} = factory.createReference('${prop.type}', data${dataKey}, { merge: true, convertCustomTypes, schema });`);
160
+ // For regular: fixed target class, PK is the data itself
161
+ const targetKey = this.safeKey(`${prop.targetMeta.tableName}_${this.tmpIndex++}`);
162
+ context.set(targetKey, prop.targetMeta.class);
163
+ if (prop.ref) {
164
+ ret.push(` entity${entityKey} = Reference.create(factory.createReference(${targetKey}, data${dataKey}, { merge: true, convertCustomTypes, normalizeAccessors, schema${keyOption} }));`);
165
+ }
166
+ else {
167
+ ret.push(` entity${entityKey} = factory.createReference(${targetKey}, data${dataKey}, { merge: true, convertCustomTypes, normalizeAccessors, schema${keyOption} });`);
168
+ }
140
169
  }
141
170
  ret.push(` } else if (data${dataKey} && typeof data${dataKey} === 'object') {`);
171
+ // For full entity hydration, polymorphic needs to determine target class from entity itself
172
+ let hydrateTargetExpr;
173
+ if (prop.polymorphic) {
174
+ hydrateTargetExpr = `data${dataKey}.constructor`;
175
+ }
176
+ else {
177
+ const targetKey = this.safeKey(`${prop.targetMeta.tableName}_${this.tmpIndex++}`);
178
+ context.set(targetKey, prop.targetMeta.class);
179
+ hydrateTargetExpr = targetKey;
180
+ }
142
181
  if (prop.ref) {
143
- ret.push(` entity${entityKey} = Reference.create(factory.${method}('${prop.type}', data${dataKey}, { initialized: true, merge: true, newEntity, convertCustomTypes, schema }));`);
182
+ ret.push(` entity${entityKey} = Reference.create(factory.${method}(${hydrateTargetExpr}, data${dataKey}, { initialized: true, merge: true, newEntity, convertCustomTypes, normalizeAccessors, schema }));`);
144
183
  }
145
184
  else {
146
- ret.push(` entity${entityKey} = factory.${method}('${prop.type}', data${dataKey}, { initialized: true, merge: true, newEntity, convertCustomTypes, schema });`);
185
+ ret.push(` entity${entityKey} = factory.${method}(${hydrateTargetExpr}, data${dataKey}, { initialized: true, merge: true, newEntity, convertCustomTypes, normalizeAccessors, schema });`);
147
186
  }
148
187
  ret.push(` }`);
149
188
  ret.push(` }`);
150
189
  if (prop.kind === ReferenceKind.ONE_TO_ONE) {
151
- const meta2 = this.metadata.get(prop.type);
190
+ const meta2 = this.metadata.get(prop.targetMeta.class);
152
191
  const prop2 = meta2.properties[prop.inversedBy || prop.mappedBy];
153
192
  if (prop2 && !prop2.mapToPk) {
154
193
  ret.push(` if (data${dataKey} && entity${entityKey} && !entity${entityKey}.${this.safeKey(prop2.name)}) {`);
@@ -166,7 +205,7 @@ export class ObjectHydrator extends Hydrator {
166
205
  };
167
206
  const hydrateToMany = (prop, dataKey, entityKey) => {
168
207
  const ret = [];
169
- ret.push(...this.createCollectionItemMapper(prop));
208
+ ret.push(...this.createCollectionItemMapper(prop, context));
170
209
  ret.push(` if (data${dataKey} && !Array.isArray(data${dataKey}) && typeof data${dataKey} === 'object') {`);
171
210
  ret.push(` data${dataKey} = [data${dataKey}];`);
172
211
  ret.push(` }`);
@@ -249,10 +288,11 @@ export class ObjectHydrator extends Hydrator {
249
288
  prop.targetMeta.polymorphs.forEach(childMeta => {
250
289
  const childProp = prop.embeddedProps[prop.targetMeta.discriminatorColumn];
251
290
  const childDataKey = prop.object ? dataKey + this.wrap(childProp.embedded[1]) : this.wrap(childProp.name);
291
+ context.set(childMeta.className, childMeta.class);
252
292
  // weak comparison as we can have numbers that might have been converted to strings due to being object keys
253
293
  ret.push(` if (data${childDataKey} == '${childMeta.discriminatorValue}') {`);
254
294
  ret.push(` if (entity${entityKey} == null) {`);
255
- ret.push(` entity${entityKey} = factory.createEmbeddable('${childMeta.className}', embeddedData, { newEntity, convertCustomTypes });`);
295
+ ret.push(` entity${entityKey} = factory.createEmbeddable(${childMeta.className}, embeddedData, { newEntity, convertCustomTypes, normalizeAccessors });`);
256
296
  ret.push(` }`);
257
297
  meta.props
258
298
  .filter(p => p.embedded?.[0] === prop.name)
@@ -272,8 +312,10 @@ export class ObjectHydrator extends Hydrator {
272
312
  });
273
313
  }
274
314
  else {
315
+ const targetKey = this.safeKey(`${prop.targetMeta.tableName}_${this.tmpIndex++}`);
316
+ context.set(targetKey, prop.targetMeta.class);
275
317
  ret.push(` if (entity${entityKey} == null) {`);
276
- ret.push(` entity${entityKey} = factory.createEmbeddable('${prop.targetMeta.className}', embeddedData, { newEntity, convertCustomTypes });`);
318
+ ret.push(` entity${entityKey} = factory.createEmbeddable(${targetKey}, embeddedData, { newEntity, convertCustomTypes, normalizeAccessors });`);
277
319
  ret.push(` }`);
278
320
  meta.props
279
321
  .filter(p => p.embedded?.[0] === prop.name)
@@ -311,7 +353,7 @@ export class ObjectHydrator extends Hydrator {
311
353
  };
312
354
  const hydrateProperty = (prop, object = prop.object, path = [prop.name], dataKey) => {
313
355
  const entityKey = path.map(k => this.wrap(k)).join('');
314
- dataKey = dataKey ?? (object ? entityKey : this.wrap(prop.name));
356
+ dataKey = dataKey ?? (object ? entityKey : this.wrap(normalizeAccessors ? (prop.accessor ?? prop.name) : prop.name));
315
357
  const ret = [];
316
358
  if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && !prop.mapToPk) {
317
359
  ret.push(...hydrateToOne(prop, dataKey, entityKey));
@@ -331,7 +373,7 @@ export class ObjectHydrator extends Hydrator {
331
373
  }
332
374
  }
333
375
  else { // ReferenceKind.SCALAR
334
- ret.push(...hydrateScalar(prop, object, path, dataKey));
376
+ ret.push(...hydrateScalar(prop, path, dataKey));
335
377
  }
336
378
  if (this.config.get('forceUndefined')) {
337
379
  ret.push(` if (data${dataKey} === null) entity${entityKey} = undefined;`);
@@ -341,15 +383,16 @@ export class ObjectHydrator extends Hydrator {
341
383
  for (const prop of props) {
342
384
  lines.push(...hydrateProperty(prop));
343
385
  }
344
- const code = `// compiled hydrator for entity ${meta.className} (${type})\n`
345
- + `return function(entity, data, factory, newEntity, convertCustomTypes, schema) {\n`
386
+ const code = `// compiled hydrator for entity ${meta.className} (${type + normalizeAccessors ? ' normalized' : ''})\n`
387
+ + `return function(entity, data, factory, newEntity, convertCustomTypes, schema, parentSchema, normalizeAccessors) {\n`
346
388
  + `${lines.join('\n')}\n}`;
347
- const hydrator = Utils.createFunction(context, code);
348
- this.hydrators[type].set(meta.className, hydrator);
389
+ const fnKey = `hydrator-${meta.uniqueName}-${type}-${normalizeAccessors}`;
390
+ const hydrator = Utils.createFunction(context, code, this.config.get('compiledFunctions'), fnKey);
391
+ this.hydrators[key].set(meta.class, hydrator);
349
392
  return hydrator;
350
393
  }
351
- createCollectionItemMapper(prop) {
352
- const meta = this.metadata.get(prop.type);
394
+ createCollectionItemMapper(prop, context) {
395
+ const meta = this.metadata.get(prop.targetMeta.class);
353
396
  const lines = [];
354
397
  lines.push(` const createCollectionItem_${this.safeKey(prop.name)} = (value, entity) => {`);
355
398
  const prop2 = prop.targetMeta.properties[prop.mappedBy];
@@ -358,9 +401,11 @@ export class ObjectHydrator extends Hydrator {
358
401
  lines.push(` value = { ...value, ['${prop2.name}']: Reference.wrapReference(entity, { ref: ${prop2.ref} }) };`);
359
402
  lines.push(` }`);
360
403
  }
361
- lines.push(` if (isPrimaryKey(value, ${meta.compositePK})) return factory.createReference('${prop.type}', value, { convertCustomTypes, schema, merge: true });`);
404
+ const targetKey = this.safeKey(`${prop.targetMeta.tableName}_${this.tmpIndex++}`);
405
+ context.set(targetKey, prop.targetMeta.class);
406
+ lines.push(` if (isPrimaryKey(value, ${meta.compositePK})) return factory.createReference(${targetKey}, value, { convertCustomTypes, schema, normalizeAccessors, merge: true });`);
362
407
  lines.push(` if (value && value.__entity) return value;`);
363
- lines.push(` return factory.create('${prop.type}', value, { newEntity, convertCustomTypes, schema, merge: true });`);
408
+ lines.push(` return factory.create(${targetKey}, value, { newEntity, convertCustomTypes, schema, normalizeAccessors, merge: true });`);
364
409
  lines.push(` }`);
365
410
  return lines;
366
411
  }
package/index.d.ts CHANGED
@@ -2,7 +2,8 @@
2
2
  * @packageDocumentation
3
3
  * @module core
4
4
  */
5
- export { Constructor, ConnectionType, Dictionary, PrimaryKeyProp, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, EntityMetadata, QBFilterQuery, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, EntityRepositoryType, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, EntityClassGroup, OptionalProps, EagerProps, HiddenProps, RequiredEntityData, CheckCallback, IndexCallback, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, Opt, EntityType, FromEntityType, Selected, IsSubset, NoInfer, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, Hidden, FilterValue, MergeLoaded, MergeSelected, Config, DefineConfig, TypeConfig, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, RequiredNullable, } from './typings.js';
5
+ export { EntityMetadata, PrimaryKeyProp, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config, EntityName } from './typings.js';
6
+ export type { CompiledFunctions, Constructor, ConnectionType, Dictionary, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, InferEntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, EntityDTOFlat, EntityDTOProp, SerializeDTO, MigrationDiff, GenerateOptions, FilterObject, IMigrationRunner, IEntityGenerator, ISeedManager, SeederObject, IMigratorStorage, RequiredEntityData, CheckCallback, IndexCallback, FormulaCallback, FormulaTable, SchemaTable, SchemaColumns, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, MigrationInfo, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, EntityType, FromEntityType, Selected, IsSubset, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, FilterValue, MergeLoaded, MergeSelected, TypeConfig, AnyString, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, RequiredNullable, DefineConfig, Opt, Hidden, EntitySchemaWithMeta, InferEntity, CheckConstraint, GeneratedColumnCallback, FilterDef, EntityCtor, Subquery, PopulateHintOptions, Prefixes, } from './typings.js';
6
7
  export * from './enums.js';
7
8
  export * from './errors.js';
8
9
  export * from './exceptions.js';
@@ -22,4 +23,3 @@ export * from './types/index.js';
22
23
  export * from './naming-strategy/index.js';
23
24
  export * from './metadata/index.js';
24
25
  export * from './cache/index.js';
25
- export * from './decorators/index.js';
package/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * @packageDocumentation
3
3
  * @module core
4
4
  */
5
- export { PrimaryKeyProp, EntityMetadata, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Opt, Hidden, Config, DefineConfig, RequiredNullable, } from './typings.js';
5
+ export { EntityMetadata, PrimaryKeyProp, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config, EntityName } from './typings.js';
6
6
  export * from './enums.js';
7
7
  export * from './errors.js';
8
8
  export * from './exceptions.js';
@@ -22,4 +22,3 @@ export * from './types/index.js';
22
22
  export * from './naming-strategy/index.js';
23
23
  export * from './metadata/index.js';
24
24
  export * from './cache/index.js';
25
- export * from './decorators/index.js';
@@ -29,5 +29,5 @@ export declare class DefaultLogger implements Logger {
29
29
  logQuery(context: {
30
30
  query: string;
31
31
  } & LogContext): void;
32
- static create(options: LoggerOptions): DefaultLogger;
32
+ static create(this: void, options: LoggerOptions): DefaultLogger;
33
33
  }
@@ -60,6 +60,7 @@ export class DefaultLogger {
60
60
  if (namespace === 'deprecated') {
61
61
  const { ignoreDeprecations = false } = this.options;
62
62
  return Array.isArray(ignoreDeprecations)
63
+ /* v8 ignore next */
63
64
  ? !ignoreDeprecations.includes(context?.label ?? '')
64
65
  : !ignoreDeprecations;
65
66
  }
@@ -14,5 +14,5 @@ export declare class SimpleLogger extends DefaultLogger {
14
14
  logQuery(context: {
15
15
  query: string;
16
16
  } & LogContext): void;
17
- static create(options: LoggerOptions): SimpleLogger;
17
+ static create(this: void, options: LoggerOptions): SimpleLogger;
18
18
  }
@@ -5,5 +5,5 @@ export declare const colors: {
5
5
  yellow: (text: string) => string;
6
6
  grey: (text: string) => string;
7
7
  cyan: (text: string) => string;
8
- enabled: () => boolean | "" | undefined;
8
+ enabled: () => boolean;
9
9
  };
package/logging/colors.js CHANGED
@@ -1,9 +1,10 @@
1
- const bool = (v) => v && ['true', 't', '1'].includes(v.toLowerCase());
2
- const boolIfDefined = (v) => v != null ? bool(v) : true;
3
- const enabled = () => !bool(process.env.NO_COLOR)
4
- && !bool(process.env.MIKRO_ORM_NO_COLOR)
5
- && boolIfDefined(process.env.FORCE_COLOR)
6
- && boolIfDefined(process.env.MIKRO_ORM_COLORS);
1
+ import { getEnv } from '../utils/env-vars.js';
2
+ const bool = (k) => ['true', 't', '1'].includes(getEnv(k)?.toLowerCase() ?? '');
3
+ const boolIfDefined = (k) => getEnv(k) != null ? bool(k) : true;
4
+ const enabled = () => !bool('NO_COLOR')
5
+ && !bool('MIKRO_ORM_NO_COLOR')
6
+ && boolIfDefined('FORCE_COLOR')
7
+ && boolIfDefined('MIKRO_ORM_COLORS');
7
8
  const wrap = (fn) => (text) => enabled() ? fn(text) : text;
8
9
  /** @internal */
9
10
  export const colors = {
@@ -2,3 +2,4 @@ export * from './colors.js';
2
2
  export * from './Logger.js';
3
3
  export * from './DefaultLogger.js';
4
4
  export * from './SimpleLogger.js';
5
+ export * from './inspect.js';
package/logging/index.js CHANGED
@@ -2,3 +2,4 @@ export * from './colors.js';
2
2
  export * from './Logger.js';
3
3
  export * from './DefaultLogger.js';
4
4
  export * from './SimpleLogger.js';
5
+ export * from './inspect.js';
@@ -0,0 +1,2 @@
1
+ /** @internal */
2
+ export declare function inspect(value: unknown, options?: Record<string, any>): string;
@@ -0,0 +1,11 @@
1
+ let nodeInspect;
2
+ /** @internal */
3
+ export function inspect(value, options) {
4
+ nodeInspect ??= globalThis.process?.getBuiltinModule?.('node:util').inspect;
5
+ /* v8 ignore else */
6
+ if (nodeInspect) {
7
+ return nodeInspect(value, options);
8
+ }
9
+ /* v8 ignore next */
10
+ return JSON.stringify(value, null, 2);
11
+ }
@@ -1,25 +1,18 @@
1
- import { EntityMetadata, type AnyEntity, type EntityKey, type Constructor, type DeepPartial, type EntityName, type EntityProperty, type CleanKeys, type ExpandProperty, type IsNever, type EntityClass } from '../typings.js';
2
- import type { EmbeddedOptions } from '../decorators/Embedded.js';
3
- import type { EnumOptions } from '../decorators/Enum.js';
4
- import type { IndexOptions, UniqueOptions } from '../decorators/Indexed.js';
5
- import type { ManyToManyOptions } from '../decorators/ManyToMany.js';
6
- import type { ManyToOneOptions } from '../decorators/ManyToOne.js';
7
- import type { OneToManyOptions } from '../decorators/OneToMany.js';
8
- import type { OneToOneOptions } from '../decorators/OneToOne.js';
9
- import type { PrimaryKeyOptions, SerializedPrimaryKeyOptions } from '../decorators/PrimaryKey.js';
10
- import type { PropertyOptions } from '../decorators/Property.js';
11
- import { ReferenceKind } from '../enums.js';
1
+ import { EntityMetadata, type AnyEntity, type EntityKey, type Constructor, type DeepPartial, type EntityName, type EntityProperty, type CleanKeys, type ExpandProperty, type IsNever, type EntityCtor } from '../typings.js';
2
+ import { type EventType, ReferenceKind } from '../enums.js';
3
+ import type { EventArgs } from '../events/EventSubscriber.js';
12
4
  import { Type } from '../types/Type.js';
5
+ import type { PropertyOptions, ManyToOneOptions, OneToOneOptions, OneToManyOptions, ManyToManyOptions, EmbeddedOptions, EnumOptions, PrimaryKeyOptions, SerializedPrimaryKeyOptions, IndexOptions, UniqueOptions } from './types.js';
13
6
  type TypeType = string | NumberConstructor | StringConstructor | BooleanConstructor | DateConstructor | ArrayConstructor | Constructor<Type<any>> | Type<any>;
14
7
  type TypeDef<Target> = {
15
8
  type: TypeType;
16
9
  } | {
17
- entity: string | (() => string | EntityName<Target>);
10
+ entity: () => EntityName<Target> | EntityName[];
18
11
  };
19
12
  type EmbeddedTypeDef<Target> = {
20
13
  type: TypeType;
21
14
  } | {
22
- entity: string | (() => string | EntityName<Target> | EntityName<Target>[]);
15
+ entity: () => EntityName<Target> | EntityName[];
23
16
  };
24
17
  export type EntitySchemaProperty<Target, Owner> = ({
25
18
  kind: ReferenceKind.MANY_TO_ONE | 'm:1';
@@ -35,28 +28,32 @@ export type EntitySchemaProperty<Target, Owner> = ({
35
28
  enum: true;
36
29
  } & EnumOptions<Owner>) | (TypeDef<Target> & PropertyOptions<Owner>);
37
30
  type OmitBaseProps<Entity, Base> = IsNever<Base> extends true ? Entity : Omit<Entity, keyof Base>;
38
- export type EntitySchemaMetadata<Entity, Base = never> = Omit<Partial<EntityMetadata<Entity>>, 'name' | 'properties' | 'extends'> & ({
31
+ export type EntitySchemaMetadata<Entity, Base = never, Class extends EntityCtor = EntityCtor<Entity>> = Omit<Partial<EntityMetadata<Entity>>, 'name' | 'properties' | 'extends'> & ({
39
32
  name: string;
40
33
  } | {
41
- class: EntityClass<Entity>;
34
+ class: Class;
42
35
  name?: string;
43
36
  }) & {
44
- extends?: string | EntitySchema<Base>;
37
+ extends?: EntityName<Base>;
45
38
  } & {
46
39
  properties?: {
47
40
  [Key in keyof OmitBaseProps<Entity, Base> as CleanKeys<OmitBaseProps<Entity, Base>, Key>]-?: EntitySchemaProperty<ExpandProperty<NonNullable<Entity[Key]>>, Entity>;
48
41
  };
42
+ } & {
43
+ inheritance?: 'tpt';
49
44
  };
50
- export declare class EntitySchema<Entity = any, Base = never> {
45
+ export declare class EntitySchema<Entity = any, Base = never, Class extends EntityCtor = EntityCtor<Entity>> {
51
46
  /**
52
47
  * When schema links the entity class via `class` option, this registry allows the lookup from opposite side,
53
48
  * so we can use the class in `entities` option just like the EntitySchema instance.
54
49
  */
55
- static REGISTRY: Map<Partial<any>, EntitySchema<any, never>>;
50
+ static REGISTRY: Map<Partial<any>, EntitySchema<any, never, EntityCtor<any>>>;
51
+ /** @internal Type-level marker for fast entity type inference */
52
+ readonly '~entity': Entity;
56
53
  private readonly _meta;
57
54
  private internal;
58
55
  private initialized;
59
- constructor(meta: EntitySchemaMetadata<Entity, Base>);
56
+ constructor(meta: EntitySchemaMetadata<Entity, Base, Class>);
60
57
  static fromMetadata<T = AnyEntity, U = never>(meta: EntityMetadata<T> | DeepPartial<EntityMetadata<T>>): EntitySchema<T, U>;
61
58
  addProperty(name: EntityKey<Entity>, type?: TypeType, options?: PropertyOptions<Entity> | EntityProperty<Entity>): void;
62
59
  addEnum(name: EntityKey<Entity>, type?: TypeType, options?: EnumOptions<Entity>): void;
@@ -71,19 +68,46 @@ export declare class EntitySchema<Entity = any, Base = never> {
71
68
  addIndex<Key extends string>(options: IndexOptions<Entity, Key>): void;
72
69
  addUnique<Key extends string>(options: UniqueOptions<Entity, Key>): void;
73
70
  setCustomRepository(repository: () => Constructor): void;
74
- setExtends(base: string | EntitySchema): void;
75
- setClass(proto: EntityClass<Entity>): void;
76
- get meta(): EntityMetadata<Entity>;
77
- get name(): EntityName<Entity>;
71
+ setExtends(base: EntityName): void;
72
+ setClass(cls: Class): void;
73
+ get meta(): EntityMetadata<Entity, Class>;
74
+ get name(): string | EntityName<Entity>;
75
+ get tableName(): string;
76
+ get class(): Class;
77
+ get properties(): Record<string, any>;
78
+ new(...params: ConstructorParameters<Class>): Entity;
78
79
  /**
79
80
  * @internal
80
81
  */
81
82
  init(): this;
83
+ /**
84
+ * Check if this entity is part of a TPT hierarchy by walking up the extends chain.
85
+ * This handles mid-level abstract entities (e.g., Animal -> Mammal -> Dog where Mammal is abstract).
86
+ */
87
+ private isPartOfTPTHierarchy;
82
88
  private initProperties;
83
89
  private initPrimaryKeys;
84
90
  private normalizeType;
85
91
  private createProperty;
86
92
  private rename;
87
93
  private renameCompositeOptions;
94
+ /**
95
+ * Adds a lifecycle hook handler to the entity schema.
96
+ * This method allows registering hooks after the entity is defined,
97
+ * which can be useful for avoiding circular type references.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * export const Article = defineEntity({
102
+ * name: 'Article',
103
+ * properties: { ... },
104
+ * });
105
+ *
106
+ * Article.addHook('beforeCreate', async args => {
107
+ * args.entity.slug = args.entity.title.toLowerCase();
108
+ * });
109
+ * ```
110
+ */
111
+ addHook<T extends Entity = Entity>(event: EventType | `${EventType}`, handler: (args: EventArgs<T>) => void | Promise<void>): this;
88
112
  }
89
113
  export {};