@mikro-orm/core 7.0.0-dev.12 → 7.0.0-dev.120

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 (207) hide show
  1. package/EntityManager.d.ts +85 -56
  2. package/EntityManager.js +332 -293
  3. package/MikroORM.d.ts +41 -32
  4. package/MikroORM.js +100 -140
  5. package/README.md +3 -2
  6. package/cache/FileCacheAdapter.d.ts +1 -1
  7. package/cache/FileCacheAdapter.js +8 -7
  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 +16 -7
  13. package/connections/Connection.js +23 -14
  14. package/drivers/DatabaseDriver.d.ts +25 -16
  15. package/drivers/DatabaseDriver.js +35 -19
  16. package/drivers/IDatabaseDriver.d.ts +38 -17
  17. package/entity/BaseEntity.d.ts +0 -1
  18. package/entity/BaseEntity.js +0 -3
  19. package/entity/Collection.d.ts +95 -30
  20. package/entity/Collection.js +439 -99
  21. package/entity/EntityAssigner.d.ts +1 -1
  22. package/entity/EntityAssigner.js +26 -18
  23. package/entity/EntityFactory.d.ts +7 -0
  24. package/entity/EntityFactory.js +72 -53
  25. package/entity/EntityHelper.d.ts +2 -2
  26. package/entity/EntityHelper.js +30 -15
  27. package/entity/EntityLoader.d.ts +7 -6
  28. package/entity/EntityLoader.js +84 -72
  29. package/entity/EntityRepository.d.ts +1 -1
  30. package/entity/EntityRepository.js +2 -2
  31. package/entity/Reference.d.ts +6 -5
  32. package/entity/Reference.js +34 -9
  33. package/entity/WrappedEntity.d.ts +2 -7
  34. package/entity/WrappedEntity.js +3 -8
  35. package/entity/defineEntity.d.ts +568 -0
  36. package/entity/defineEntity.js +529 -0
  37. package/entity/index.d.ts +3 -2
  38. package/entity/index.js +3 -2
  39. package/entity/utils.d.ts +7 -0
  40. package/entity/utils.js +16 -4
  41. package/entity/validators.d.ts +11 -0
  42. package/entity/validators.js +65 -0
  43. package/enums.d.ts +21 -6
  44. package/enums.js +14 -1
  45. package/errors.d.ts +17 -9
  46. package/errors.js +41 -21
  47. package/events/EventManager.d.ts +2 -1
  48. package/events/EventManager.js +19 -11
  49. package/hydration/Hydrator.js +1 -2
  50. package/hydration/ObjectHydrator.d.ts +4 -4
  51. package/hydration/ObjectHydrator.js +50 -33
  52. package/index.d.ts +2 -2
  53. package/index.js +1 -2
  54. package/logging/DefaultLogger.d.ts +1 -1
  55. package/logging/DefaultLogger.js +1 -0
  56. package/logging/SimpleLogger.d.ts +1 -1
  57. package/logging/colors.d.ts +1 -1
  58. package/logging/colors.js +7 -6
  59. package/logging/index.d.ts +1 -0
  60. package/logging/index.js +1 -0
  61. package/logging/inspect.d.ts +2 -0
  62. package/logging/inspect.js +11 -0
  63. package/metadata/EntitySchema.d.ts +13 -17
  64. package/metadata/EntitySchema.js +67 -51
  65. package/metadata/MetadataDiscovery.d.ts +6 -10
  66. package/metadata/MetadataDiscovery.js +289 -298
  67. package/metadata/MetadataProvider.d.ts +11 -2
  68. package/metadata/MetadataProvider.js +46 -2
  69. package/metadata/MetadataStorage.d.ts +13 -11
  70. package/metadata/MetadataStorage.js +70 -37
  71. package/metadata/MetadataValidator.d.ts +2 -9
  72. package/metadata/MetadataValidator.js +22 -38
  73. package/metadata/discover-entities.d.ts +5 -0
  74. package/metadata/discover-entities.js +40 -0
  75. package/metadata/index.d.ts +1 -1
  76. package/metadata/index.js +1 -1
  77. package/metadata/types.d.ts +480 -0
  78. package/metadata/types.js +1 -0
  79. package/naming-strategy/AbstractNamingStrategy.d.ts +8 -4
  80. package/naming-strategy/AbstractNamingStrategy.js +8 -2
  81. package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
  82. package/naming-strategy/EntityCaseNamingStrategy.js +6 -5
  83. package/naming-strategy/MongoNamingStrategy.d.ts +3 -3
  84. package/naming-strategy/MongoNamingStrategy.js +6 -6
  85. package/naming-strategy/NamingStrategy.d.ts +14 -4
  86. package/naming-strategy/UnderscoreNamingStrategy.d.ts +3 -3
  87. package/naming-strategy/UnderscoreNamingStrategy.js +6 -6
  88. package/not-supported.d.ts +2 -0
  89. package/not-supported.js +4 -0
  90. package/package.json +19 -11
  91. package/platforms/ExceptionConverter.js +1 -1
  92. package/platforms/Platform.d.ts +6 -13
  93. package/platforms/Platform.js +17 -43
  94. package/serialization/EntitySerializer.d.ts +5 -0
  95. package/serialization/EntitySerializer.js +47 -27
  96. package/serialization/EntityTransformer.js +28 -18
  97. package/serialization/SerializationContext.d.ts +6 -6
  98. package/serialization/SerializationContext.js +16 -13
  99. package/types/ArrayType.d.ts +1 -1
  100. package/types/ArrayType.js +2 -3
  101. package/types/BigIntType.d.ts +8 -6
  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 +2 -1
  106. package/types/BooleanType.js +3 -0
  107. package/types/DecimalType.d.ts +6 -4
  108. package/types/DecimalType.js +3 -3
  109. package/types/DoubleType.js +2 -2
  110. package/types/EnumArrayType.js +1 -2
  111. package/types/JsonType.d.ts +1 -1
  112. package/types/JsonType.js +7 -2
  113. package/types/TinyIntType.js +1 -1
  114. package/types/Type.d.ts +2 -4
  115. package/types/Type.js +3 -3
  116. package/types/Uint8ArrayType.d.ts +0 -1
  117. package/types/Uint8ArrayType.js +1 -4
  118. package/types/index.d.ts +1 -1
  119. package/typings.d.ts +124 -86
  120. package/typings.js +50 -42
  121. package/unit-of-work/ChangeSet.d.ts +2 -6
  122. package/unit-of-work/ChangeSet.js +4 -5
  123. package/unit-of-work/ChangeSetComputer.d.ts +1 -3
  124. package/unit-of-work/ChangeSetComputer.js +14 -12
  125. package/unit-of-work/ChangeSetPersister.d.ts +5 -4
  126. package/unit-of-work/ChangeSetPersister.js +65 -33
  127. package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
  128. package/unit-of-work/CommitOrderCalculator.js +13 -13
  129. package/unit-of-work/UnitOfWork.d.ts +10 -3
  130. package/unit-of-work/UnitOfWork.js +139 -96
  131. package/utils/AbstractSchemaGenerator.d.ts +5 -5
  132. package/utils/AbstractSchemaGenerator.js +18 -16
  133. package/utils/AsyncContext.d.ts +6 -0
  134. package/utils/AsyncContext.js +42 -0
  135. package/utils/Configuration.d.ts +753 -207
  136. package/utils/Configuration.js +145 -190
  137. package/utils/ConfigurationLoader.d.ts +1 -54
  138. package/utils/ConfigurationLoader.js +1 -352
  139. package/utils/Cursor.d.ts +0 -3
  140. package/utils/Cursor.js +9 -6
  141. package/utils/DataloaderUtils.d.ts +15 -5
  142. package/utils/DataloaderUtils.js +65 -17
  143. package/utils/EntityComparator.d.ts +13 -9
  144. package/utils/EntityComparator.js +85 -43
  145. package/utils/QueryHelper.d.ts +14 -6
  146. package/utils/QueryHelper.js +87 -25
  147. package/utils/RawQueryFragment.d.ts +48 -25
  148. package/utils/RawQueryFragment.js +66 -70
  149. package/utils/RequestContext.js +2 -2
  150. package/utils/TransactionContext.js +2 -2
  151. package/utils/TransactionManager.d.ts +65 -0
  152. package/utils/TransactionManager.js +223 -0
  153. package/utils/Utils.d.ts +12 -119
  154. package/utils/Utils.js +97 -373
  155. package/utils/clone.js +8 -23
  156. package/utils/env-vars.d.ts +7 -0
  157. package/utils/env-vars.js +97 -0
  158. package/utils/fs-utils.d.ts +32 -0
  159. package/utils/fs-utils.js +178 -0
  160. package/utils/index.d.ts +2 -1
  161. package/utils/index.js +2 -1
  162. package/utils/upsert-utils.d.ts +9 -4
  163. package/utils/upsert-utils.js +55 -4
  164. package/decorators/Check.d.ts +0 -3
  165. package/decorators/Check.js +0 -13
  166. package/decorators/CreateRequestContext.d.ts +0 -3
  167. package/decorators/CreateRequestContext.js +0 -32
  168. package/decorators/Embeddable.d.ts +0 -8
  169. package/decorators/Embeddable.js +0 -11
  170. package/decorators/Embedded.d.ts +0 -18
  171. package/decorators/Embedded.js +0 -18
  172. package/decorators/Entity.d.ts +0 -18
  173. package/decorators/Entity.js +0 -12
  174. package/decorators/Enum.d.ts +0 -9
  175. package/decorators/Enum.js +0 -16
  176. package/decorators/Filter.d.ts +0 -2
  177. package/decorators/Filter.js +0 -8
  178. package/decorators/Formula.d.ts +0 -4
  179. package/decorators/Formula.js +0 -15
  180. package/decorators/Indexed.d.ts +0 -19
  181. package/decorators/Indexed.js +0 -20
  182. package/decorators/ManyToMany.d.ts +0 -40
  183. package/decorators/ManyToMany.js +0 -14
  184. package/decorators/ManyToOne.d.ts +0 -30
  185. package/decorators/ManyToOne.js +0 -14
  186. package/decorators/OneToMany.d.ts +0 -28
  187. package/decorators/OneToMany.js +0 -17
  188. package/decorators/OneToOne.d.ts +0 -24
  189. package/decorators/OneToOne.js +0 -7
  190. package/decorators/PrimaryKey.d.ts +0 -8
  191. package/decorators/PrimaryKey.js +0 -20
  192. package/decorators/Property.d.ts +0 -250
  193. package/decorators/Property.js +0 -32
  194. package/decorators/Transactional.d.ts +0 -13
  195. package/decorators/Transactional.js +0 -28
  196. package/decorators/hooks.d.ts +0 -16
  197. package/decorators/hooks.js +0 -47
  198. package/decorators/index.d.ts +0 -17
  199. package/decorators/index.js +0 -17
  200. package/entity/ArrayCollection.d.ts +0 -116
  201. package/entity/ArrayCollection.js +0 -402
  202. package/entity/EntityValidator.d.ts +0 -19
  203. package/entity/EntityValidator.js +0 -150
  204. package/metadata/ReflectMetadataProvider.d.ts +0 -8
  205. package/metadata/ReflectMetadataProvider.js +0 -44
  206. package/utils/resolveContextProvider.d.ts +0 -10
  207. package/utils/resolveContextProvider.js +0 -28
@@ -3,40 +3,43 @@ import { Collection } from '../entity/Collection.js';
3
3
  import { Reference, ScalarReference } from '../entity/Reference.js';
4
4
  import { parseJsonSafe, Utils } from '../utils/Utils.js';
5
5
  import { ReferenceKind } from '../enums.js';
6
- import { RawQueryFragment } from '../utils/RawQueryFragment.js';
6
+ import { Raw } from '../utils/RawQueryFragment.js';
7
7
  export class ObjectHydrator extends Hydrator {
8
8
  hydrators = {
9
- full: new Map(),
10
- reference: new Map(),
9
+ 'full~true': new Map(),
10
+ 'full~false': new Map(),
11
+ 'reference~true': new Map(),
12
+ 'reference~false': new Map(),
11
13
  };
12
14
  tmpIndex = 0;
13
15
  /**
14
16
  * @inheritDoc
15
17
  */
16
- hydrate(entity, meta, data, factory, type, newEntity = false, convertCustomTypes = false, schema, parentSchema) {
17
- const hydrate = this.getEntityHydrator(meta, type);
18
+ hydrate(entity, meta, data, factory, type, newEntity = false, convertCustomTypes = false, schema, parentSchema, normalizeAccessors) {
19
+ const hydrate = this.getEntityHydrator(meta, type, normalizeAccessors);
18
20
  const running = this.running;
19
21
  // the running state is used to consider propagation as hydration, saving the values directly to the entity data,
20
22
  // but we don't want that for new entities, their propagation should result in entity updates when flushing
21
23
  this.running = !newEntity;
22
- Utils.callCompiledFunction(hydrate, entity, data, factory, newEntity, convertCustomTypes, schema, parentSchema);
24
+ Utils.callCompiledFunction(hydrate, entity, data, factory, newEntity, convertCustomTypes, schema, parentSchema, normalizeAccessors);
23
25
  this.running = running;
24
26
  }
25
27
  /**
26
28
  * @inheritDoc
27
29
  */
28
- hydrateReference(entity, meta, data, factory, convertCustomTypes = false, schema, parentSchema) {
29
- const hydrate = this.getEntityHydrator(meta, 'reference');
30
+ hydrateReference(entity, meta, data, factory, convertCustomTypes = false, schema, parentSchema, normalizeAccessors) {
31
+ const hydrate = this.getEntityHydrator(meta, 'reference', normalizeAccessors);
30
32
  const running = this.running;
31
33
  this.running = true;
32
- Utils.callCompiledFunction(hydrate, entity, data, factory, false, convertCustomTypes, schema, parentSchema);
34
+ Utils.callCompiledFunction(hydrate, entity, data, factory, false, convertCustomTypes, schema, parentSchema, normalizeAccessors);
33
35
  this.running = running;
34
36
  }
35
37
  /**
36
38
  * @internal Highly performance-sensitive method.
37
39
  */
38
- getEntityHydrator(meta, type) {
39
- const exists = this.hydrators[type].get(meta.className);
40
+ getEntityHydrator(meta, type, normalizeAccessors = false) {
41
+ const key = `${type}~${normalizeAccessors}`;
42
+ const exists = this.hydrators[key].get(meta.class);
40
43
  if (exists) {
41
44
  return exists;
42
45
  }
@@ -48,22 +51,22 @@ export class ObjectHydrator extends Hydrator {
48
51
  context.set('Reference', Reference);
49
52
  const registerCustomType = (prop, convertorKey, method, context) => {
50
53
  context.set(`${method}_${convertorKey}`, (val) => {
51
- /* v8 ignore next 3 */
52
- if (RawQueryFragment.isKnownFragment(val)) {
54
+ /* v8 ignore next */
55
+ if (Raw.isKnownFragment(val)) {
53
56
  return val;
54
57
  }
55
58
  return prop.customType[method](val, this.platform, { mode: 'serialization' });
56
59
  });
57
60
  return convertorKey;
58
61
  };
59
- const hydrateScalar = (prop, object, path, dataKey) => {
62
+ const hydrateScalar = (prop, path, dataKey) => {
60
63
  const entityKey = path.map(k => this.wrap(k)).join('');
61
64
  const tz = this.platform.getTimezone();
62
65
  const convertorKey = path.filter(k => !k.match(/\[idx_\d+]/)).map(k => this.safeKey(k)).join('_');
63
66
  const ret = [];
64
67
  const idx = this.tmpIndex++;
65
68
  const nullVal = this.config.get('forceUndefined') ? 'undefined' : 'null';
66
- if (prop.getter && !prop.setter) {
69
+ if (prop.getter && !prop.setter && prop.persist === false) {
67
70
  return [];
68
71
  }
69
72
  if (prop.ref) {
@@ -71,7 +74,14 @@ export class ObjectHydrator extends Hydrator {
71
74
  ret.push(` const oldValue_${idx} = entity${entityKey};`);
72
75
  }
73
76
  ret.push(` if (data${dataKey} === null) {`);
74
- ret.push(` entity${entityKey} = ${nullVal};`);
77
+ if (prop.ref) {
78
+ ret.push(` entity${entityKey} = new ScalarReference();`);
79
+ ret.push(` entity${entityKey}.bind(entity, '${prop.name}');`);
80
+ ret.push(` entity${entityKey}.set(${nullVal});`);
81
+ }
82
+ else {
83
+ ret.push(` entity${entityKey} = ${nullVal};`);
84
+ }
75
85
  ret.push(` } else if (typeof data${dataKey} !== 'undefined') {`);
76
86
  if (prop.customType) {
77
87
  registerCustomType(prop, convertorKey, 'convertToJSValue', context);
@@ -125,23 +135,25 @@ export class ObjectHydrator extends Hydrator {
125
135
  ret.push(` if (data${dataKey} === null) {\n entity${entityKey} = ${nullVal};`);
126
136
  ret.push(` } else if (typeof data${dataKey} !== 'undefined') {`);
127
137
  ret.push(` if (isPrimaryKey(data${dataKey}, true)) {`);
138
+ const targetKey = this.safeKey(`${prop.targetMeta.tableName}_${this.tmpIndex++}`);
139
+ context.set(targetKey, prop.targetMeta.class);
128
140
  if (prop.ref) {
129
- ret.push(` entity${entityKey} = Reference.create(factory.createReference('${prop.type}', data${dataKey}, { merge: true, convertCustomTypes, schema }));`);
141
+ ret.push(` entity${entityKey} = Reference.create(factory.createReference(${targetKey}, data${dataKey}, { merge: true, convertCustomTypes, normalizeAccessors, schema }));`);
130
142
  }
131
143
  else {
132
- ret.push(` entity${entityKey} = factory.createReference('${prop.type}', data${dataKey}, { merge: true, convertCustomTypes, schema });`);
144
+ ret.push(` entity${entityKey} = factory.createReference(${targetKey}, data${dataKey}, { merge: true, convertCustomTypes, normalizeAccessors, schema });`);
133
145
  }
134
146
  ret.push(` } else if (data${dataKey} && typeof data${dataKey} === 'object') {`);
135
147
  if (prop.ref) {
136
- ret.push(` entity${entityKey} = Reference.create(factory.${method}('${prop.type}', data${dataKey}, { initialized: true, merge: true, newEntity, convertCustomTypes, schema }));`);
148
+ ret.push(` entity${entityKey} = Reference.create(factory.${method}(${targetKey}, data${dataKey}, { initialized: true, merge: true, newEntity, convertCustomTypes, normalizeAccessors, schema }));`);
137
149
  }
138
150
  else {
139
- ret.push(` entity${entityKey} = factory.${method}('${prop.type}', data${dataKey}, { initialized: true, merge: true, newEntity, convertCustomTypes, schema });`);
151
+ ret.push(` entity${entityKey} = factory.${method}(${targetKey}, data${dataKey}, { initialized: true, merge: true, newEntity, convertCustomTypes, normalizeAccessors, schema });`);
140
152
  }
141
153
  ret.push(` }`);
142
154
  ret.push(` }`);
143
155
  if (prop.kind === ReferenceKind.ONE_TO_ONE) {
144
- const meta2 = this.metadata.get(prop.type);
156
+ const meta2 = this.metadata.get(prop.targetMeta.class);
145
157
  const prop2 = meta2.properties[prop.inversedBy || prop.mappedBy];
146
158
  if (prop2 && !prop2.mapToPk) {
147
159
  ret.push(` if (data${dataKey} && entity${entityKey} && !entity${entityKey}.${this.safeKey(prop2.name)}) {`);
@@ -159,7 +171,7 @@ export class ObjectHydrator extends Hydrator {
159
171
  };
160
172
  const hydrateToMany = (prop, dataKey, entityKey) => {
161
173
  const ret = [];
162
- ret.push(...this.createCollectionItemMapper(prop));
174
+ ret.push(...this.createCollectionItemMapper(prop, context));
163
175
  ret.push(` if (data${dataKey} && !Array.isArray(data${dataKey}) && typeof data${dataKey} === 'object') {`);
164
176
  ret.push(` data${dataKey} = [data${dataKey}];`);
165
177
  ret.push(` }`);
@@ -242,10 +254,11 @@ export class ObjectHydrator extends Hydrator {
242
254
  prop.targetMeta.polymorphs.forEach(childMeta => {
243
255
  const childProp = prop.embeddedProps[prop.targetMeta.discriminatorColumn];
244
256
  const childDataKey = prop.object ? dataKey + this.wrap(childProp.embedded[1]) : this.wrap(childProp.name);
257
+ context.set(childMeta.className, childMeta.class);
245
258
  // weak comparison as we can have numbers that might have been converted to strings due to being object keys
246
259
  ret.push(` if (data${childDataKey} == '${childMeta.discriminatorValue}') {`);
247
260
  ret.push(` if (entity${entityKey} == null) {`);
248
- ret.push(` entity${entityKey} = factory.createEmbeddable('${childMeta.className}', embeddedData, { newEntity, convertCustomTypes });`);
261
+ ret.push(` entity${entityKey} = factory.createEmbeddable(${childMeta.className}, embeddedData, { newEntity, convertCustomTypes, normalizeAccessors });`);
249
262
  ret.push(` }`);
250
263
  meta.props
251
264
  .filter(p => p.embedded?.[0] === prop.name)
@@ -265,8 +278,10 @@ export class ObjectHydrator extends Hydrator {
265
278
  });
266
279
  }
267
280
  else {
281
+ const targetKey = this.safeKey(`${prop.targetMeta.tableName}_${this.tmpIndex++}`);
282
+ context.set(targetKey, prop.targetMeta.class);
268
283
  ret.push(` if (entity${entityKey} == null) {`);
269
- ret.push(` entity${entityKey} = factory.createEmbeddable('${prop.targetMeta.className}', embeddedData, { newEntity, convertCustomTypes });`);
284
+ ret.push(` entity${entityKey} = factory.createEmbeddable(${targetKey}, embeddedData, { newEntity, convertCustomTypes, normalizeAccessors });`);
270
285
  ret.push(` }`);
271
286
  meta.props
272
287
  .filter(p => p.embedded?.[0] === prop.name)
@@ -304,7 +319,7 @@ export class ObjectHydrator extends Hydrator {
304
319
  };
305
320
  const hydrateProperty = (prop, object = prop.object, path = [prop.name], dataKey) => {
306
321
  const entityKey = path.map(k => this.wrap(k)).join('');
307
- dataKey = dataKey ?? (object ? entityKey : this.wrap(prop.name));
322
+ dataKey = dataKey ?? (object ? entityKey : this.wrap(normalizeAccessors ? (prop.accessor ?? prop.name) : prop.name));
308
323
  const ret = [];
309
324
  if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && !prop.mapToPk) {
310
325
  ret.push(...hydrateToOne(prop, dataKey, entityKey));
@@ -324,7 +339,7 @@ export class ObjectHydrator extends Hydrator {
324
339
  }
325
340
  }
326
341
  else { // ReferenceKind.SCALAR
327
- ret.push(...hydrateScalar(prop, object, path, dataKey));
342
+ ret.push(...hydrateScalar(prop, path, dataKey));
328
343
  }
329
344
  if (this.config.get('forceUndefined')) {
330
345
  ret.push(` if (data${dataKey} === null) entity${entityKey} = undefined;`);
@@ -334,15 +349,15 @@ export class ObjectHydrator extends Hydrator {
334
349
  for (const prop of props) {
335
350
  lines.push(...hydrateProperty(prop));
336
351
  }
337
- const code = `// compiled hydrator for entity ${meta.className} (${type})\n`
338
- + `return function(entity, data, factory, newEntity, convertCustomTypes, schema) {\n`
352
+ const code = `// compiled hydrator for entity ${meta.className} (${type + normalizeAccessors ? ' normalized' : ''})\n`
353
+ + `return function(entity, data, factory, newEntity, convertCustomTypes, schema, parentSchema, normalizeAccessors) {\n`
339
354
  + `${lines.join('\n')}\n}`;
340
355
  const hydrator = Utils.createFunction(context, code);
341
- this.hydrators[type].set(meta.className, hydrator);
356
+ this.hydrators[key].set(meta.class, hydrator);
342
357
  return hydrator;
343
358
  }
344
- createCollectionItemMapper(prop) {
345
- const meta = this.metadata.get(prop.type);
359
+ createCollectionItemMapper(prop, context) {
360
+ const meta = this.metadata.get(prop.targetMeta.class);
346
361
  const lines = [];
347
362
  lines.push(` const createCollectionItem_${this.safeKey(prop.name)} = (value, entity) => {`);
348
363
  const prop2 = prop.targetMeta.properties[prop.mappedBy];
@@ -351,9 +366,11 @@ export class ObjectHydrator extends Hydrator {
351
366
  lines.push(` value = { ...value, ['${prop2.name}']: Reference.wrapReference(entity, { ref: ${prop2.ref} }) };`);
352
367
  lines.push(` }`);
353
368
  }
354
- lines.push(` if (isPrimaryKey(value, ${meta.compositePK})) return factory.createReference('${prop.type}', value, { convertCustomTypes, schema, merge: true });`);
369
+ const targetKey = this.safeKey(`${prop.targetMeta.tableName}_${this.tmpIndex++}`);
370
+ context.set(targetKey, prop.targetMeta.class);
371
+ lines.push(` if (isPrimaryKey(value, ${meta.compositePK})) return factory.createReference(${targetKey}, value, { convertCustomTypes, schema, normalizeAccessors, merge: true });`);
355
372
  lines.push(` if (value && value.__entity) return value;`);
356
- lines.push(` return factory.create('${prop.type}', value, { newEntity, convertCustomTypes, schema, merge: true });`);
373
+ lines.push(` return factory.create(${targetKey}, value, { newEntity, convertCustomTypes, schema, normalizeAccessors, merge: true });`);
357
374
  lines.push(` }`);
358
375
  return lines;
359
376
  }
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, 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, } from './typings.js';
5
+ export { EntityMetadata, PrimaryKeyProp, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config } from './typings.js';
6
+ export type { Constructor, ConnectionType, Dictionary, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, QBFilterQuery, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, RequiredEntityData, CheckCallback, IndexCallback, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, EntityType, FromEntityType, Selected, IsSubset, NoInfer, 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, } 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, Config, } from './typings.js';
5
+ export { EntityMetadata, PrimaryKeyProp, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config } 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,17 @@
1
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
2
  import { ReferenceKind } from '../enums.js';
12
3
  import { Type } from '../types/Type.js';
4
+ import type { PropertyOptions, ManyToOneOptions, OneToOneOptions, OneToManyOptions, ManyToManyOptions, EmbeddedOptions, EnumOptions, PrimaryKeyOptions, SerializedPrimaryKeyOptions, IndexOptions, UniqueOptions } from './types.js';
13
5
  type TypeType = string | NumberConstructor | StringConstructor | BooleanConstructor | DateConstructor | ArrayConstructor | Constructor<Type<any>> | Type<any>;
14
6
  type TypeDef<Target> = {
15
7
  type: TypeType;
16
8
  } | {
17
- entity: string | (() => string | EntityName<Target>);
9
+ entity: () => EntityName<Target>;
18
10
  };
19
11
  type EmbeddedTypeDef<Target> = {
20
12
  type: TypeType;
21
13
  } | {
22
- entity: string | (() => string | EntityName<Target> | EntityName<Target>[]);
14
+ entity: () => EntityName<Target> | EntityName<Target>[];
23
15
  };
24
16
  export type EntitySchemaProperty<Target, Owner> = ({
25
17
  kind: ReferenceKind.MANY_TO_ONE | 'm:1';
@@ -31,7 +23,7 @@ export type EntitySchemaProperty<Target, Owner> = ({
31
23
  kind: ReferenceKind.MANY_TO_MANY | 'm:n';
32
24
  } & TypeDef<Target> & ManyToManyOptions<Owner, Target>) | ({
33
25
  kind: ReferenceKind.EMBEDDED | 'embedded';
34
- } & EmbeddedTypeDef<Target> & EmbeddedOptions & PropertyOptions<Owner>) | ({
26
+ } & EmbeddedTypeDef<Target> & EmbeddedOptions<Owner, Target> & PropertyOptions<Owner>) | ({
35
27
  enum: true;
36
28
  } & EnumOptions<Owner>) | (TypeDef<Target> & PropertyOptions<Owner>);
37
29
  type OmitBaseProps<Entity, Base> = IsNever<Base> extends true ? Entity : Omit<Entity, keyof Base>;
@@ -41,7 +33,7 @@ export type EntitySchemaMetadata<Entity, Base = never> = Omit<Partial<EntityMeta
41
33
  class: EntityClass<Entity>;
42
34
  name?: string;
43
35
  }) & {
44
- extends?: string | EntitySchema<Base>;
36
+ extends?: EntityName<Base>;
45
37
  } & {
46
38
  properties?: {
47
39
  [Key in keyof OmitBaseProps<Entity, Base> as CleanKeys<OmitBaseProps<Entity, Base>, Key>]-?: EntitySchemaProperty<ExpandProperty<NonNullable<Entity[Key]>>, Entity>;
@@ -63,7 +55,7 @@ export declare class EntitySchema<Entity = any, Base = never> {
63
55
  addVersion(name: EntityKey<Entity>, type: TypeType, options?: PropertyOptions<Entity>): void;
64
56
  addPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: PrimaryKeyOptions<Entity>): void;
65
57
  addSerializedPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: SerializedPrimaryKeyOptions<Entity>): void;
66
- addEmbedded<Target = AnyEntity>(name: EntityKey<Entity>, options: EmbeddedOptions): void;
58
+ addEmbedded<Target = AnyEntity>(name: EntityKey<Entity>, options: EmbeddedOptions<Entity, Target>): void;
67
59
  addManyToOne<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: ManyToOneOptions<Entity, Target>): void;
68
60
  addManyToMany<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: ManyToManyOptions<Entity, Target>): void;
69
61
  addOneToMany<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: OneToManyOptions<Entity, Target>): void;
@@ -71,10 +63,12 @@ export declare class EntitySchema<Entity = any, Base = never> {
71
63
  addIndex<Key extends string>(options: IndexOptions<Entity, Key>): void;
72
64
  addUnique<Key extends string>(options: UniqueOptions<Entity, Key>): void;
73
65
  setCustomRepository(repository: () => Constructor): void;
74
- setExtends(base: string | EntitySchema): void;
75
- setClass(proto: EntityClass<Entity>): void;
66
+ setExtends(base: EntityName): void;
67
+ setClass(cls: EntityClass<Entity>): void;
76
68
  get meta(): EntityMetadata<Entity>;
77
- get name(): EntityName<Entity>;
69
+ get name(): string | EntityName<Entity>;
70
+ get tableName(): string;
71
+ get properties(): Record<string, any>;
78
72
  /**
79
73
  * @internal
80
74
  */
@@ -83,5 +77,7 @@ export declare class EntitySchema<Entity = any, Base = never> {
83
77
  private initPrimaryKeys;
84
78
  private normalizeType;
85
79
  private createProperty;
80
+ private rename;
81
+ private renameCompositeOptions;
86
82
  }
87
83
  export {};
@@ -10,7 +10,7 @@ export class EntitySchema {
10
10
  * so we can use the class in `entities` option just like the EntitySchema instance.
11
11
  */
12
12
  static REGISTRY = new Map();
13
- _meta = new EntityMetadata();
13
+ _meta;
14
14
  internal = false;
15
15
  initialized = false;
16
16
  constructor(meta) {
@@ -18,15 +18,14 @@ export class EntitySchema {
18
18
  if (meta.name) {
19
19
  meta.abstract ??= false;
20
20
  }
21
+ this._meta = new EntityMetadata({
22
+ className: meta.name,
23
+ ...meta,
24
+ });
25
+ this._meta.root ??= this._meta;
21
26
  if (meta.class && !meta.internal) {
22
27
  EntitySchema.REGISTRY.set(meta.class, this);
23
28
  }
24
- if (meta.tableName || meta.collection) {
25
- Utils.renameKey(meta, 'tableName', 'collection');
26
- meta.tableName = meta.collection;
27
- }
28
- Object.assign(this._meta, { className: meta.name }, meta);
29
- this._meta.root ??= this._meta;
30
29
  }
31
30
  static fromMetadata(meta) {
32
31
  const schema = new EntitySchema({ ...meta, internal: true });
@@ -34,29 +33,13 @@ export class EntitySchema {
34
33
  return schema;
35
34
  }
36
35
  addProperty(name, type, options = {}) {
37
- const rename = (data, from, to) => {
38
- if (from in options && !(to in options)) {
39
- // @ts-ignore
40
- options[to] = [options[from]];
41
- // @ts-ignore
42
- delete options[from];
43
- }
44
- };
45
- if (name !== options.name) {
46
- Utils.renameKey(options, 'name', 'fieldName');
47
- }
48
- rename(options, 'fieldName', 'fieldNames');
49
- rename(options, 'ref', 'ref');
50
- rename(options, 'joinColumn', 'joinColumns');
51
- rename(options, 'inverseJoinColumn', 'inverseJoinColumns');
52
- rename(options, 'referenceColumnName', 'referencedColumnNames');
53
- rename(options, 'columnType', 'columnTypes');
54
- const prop = { name, kind: ReferenceKind.SCALAR, ...options, type: this.normalizeType(options, type) };
36
+ this.renameCompositeOptions(name, options);
37
+ const prop = { name, kind: ReferenceKind.SCALAR, ...options, ...this.normalizeType(options, type) };
55
38
  if (type && Type.isMappedType(type.prototype)) {
56
39
  prop.type = type;
57
40
  }
58
- if (Utils.isString(prop.formula)) {
59
- const formula = prop.formula; // tmp var is needed here
41
+ if (typeof prop.formula === 'string') {
42
+ const formula = prop.formula;
60
43
  prop.formula = () => formula;
61
44
  }
62
45
  if (prop.formula) {
@@ -91,17 +74,18 @@ export class EntitySchema {
91
74
  }
92
75
  addSerializedPrimaryKey(name, type, options = {}) {
93
76
  this._meta.serializedPrimaryKey = name;
94
- this.addProperty(name, type, options);
77
+ this.addProperty(name, type, { serializedPrimaryKey: true, ...options });
95
78
  }
96
79
  addEmbedded(name, options) {
80
+ this.renameCompositeOptions(name, options);
97
81
  Utils.defaultValue(options, 'prefix', true);
98
82
  if (options.array) {
99
83
  options.object = true; // force object mode for arrays
100
84
  }
101
85
  this._meta.properties[name] = {
102
86
  name,
103
- type: this.normalizeType(options),
104
87
  kind: ReferenceKind.EMBEDDED,
88
+ ...this.normalizeType(options),
105
89
  ...options,
106
90
  };
107
91
  }
@@ -114,6 +98,8 @@ export class EntitySchema {
114
98
  if (prop.fieldNames && !prop.joinColumns) {
115
99
  prop.joinColumns = prop.fieldNames;
116
100
  }
101
+ // By default, the foreign key constraint is created on the relation
102
+ Utils.defaultValue(prop, 'createForeignKeyConstraint', true);
117
103
  this.addProperty(name, type, prop);
118
104
  }
119
105
  addManyToMany(name, type, options) {
@@ -123,6 +109,8 @@ export class EntitySchema {
123
109
  }
124
110
  if (options.owner) {
125
111
  Utils.renameKey(options, 'mappedBy', 'inversedBy');
112
+ // By default, the foreign key constraint is created on the relation
113
+ Utils.defaultValue(options, 'createForeignKeyConstraint', true);
126
114
  }
127
115
  const prop = this.createProperty(ReferenceKind.MANY_TO_MANY, options);
128
116
  this.addProperty(name, type, prop);
@@ -135,8 +123,12 @@ export class EntitySchema {
135
123
  const prop = this.createProperty(ReferenceKind.ONE_TO_ONE, options);
136
124
  Utils.defaultValue(prop, 'owner', !!prop.inversedBy || !prop.mappedBy);
137
125
  Utils.defaultValue(prop, 'unique', prop.owner);
138
- if (prop.owner && options.mappedBy) {
139
- Utils.renameKey(prop, 'mappedBy', 'inversedBy');
126
+ if (prop.owner) {
127
+ if (options.mappedBy) {
128
+ Utils.renameKey(prop, 'mappedBy', 'inversedBy');
129
+ }
130
+ // By default, the foreign key constraint is created on the relation
131
+ Utils.defaultValue(prop, 'createForeignKeyConstraint', true);
140
132
  }
141
133
  if (prop.joinColumns && !prop.fieldNames) {
142
134
  prop.fieldNames = prop.joinColumns;
@@ -158,21 +150,20 @@ export class EntitySchema {
158
150
  setExtends(base) {
159
151
  this._meta.extends = base;
160
152
  }
161
- setClass(proto) {
162
- const sameClass = this._meta.className === proto.name;
163
- this._meta.class = proto;
164
- this._meta.prototype = proto.prototype;
165
- this._meta.className = proto.name;
153
+ setClass(cls) {
154
+ const sameClass = this._meta.className === cls.name;
155
+ this._meta.class = cls;
156
+ this._meta.prototype = cls.prototype;
157
+ this._meta.className = this._meta.name ?? cls.name;
166
158
  if (!sameClass || !this._meta.constructorParams) {
167
- const tokens = Utils.tokenize(proto);
168
- this._meta.constructorParams = Utils.getParamNames(tokens, 'constructor');
169
- this._meta.toJsonParams = Utils.getParamNames(tokens, 'toJSON').filter(p => p !== '...args');
159
+ this._meta.constructorParams = Utils.getConstructorParams(cls);
170
160
  }
171
161
  if (!this.internal) {
172
- EntitySchema.REGISTRY.set(proto, this);
162
+ EntitySchema.REGISTRY.set(cls, this);
173
163
  }
174
- if (Object.getPrototypeOf(proto) !== BaseEntity) {
175
- this._meta.extends = this._meta.extends || Object.getPrototypeOf(proto).name || undefined;
164
+ const base = Object.getPrototypeOf(cls);
165
+ if (base !== BaseEntity) {
166
+ this._meta.extends ??= base.name ? base : undefined;
176
167
  }
177
168
  }
178
169
  get meta() {
@@ -181,6 +172,12 @@ export class EntitySchema {
181
172
  get name() {
182
173
  return this._meta.className;
183
174
  }
175
+ get tableName() {
176
+ return this._meta.tableName;
177
+ }
178
+ get properties() {
179
+ return this._meta.properties;
180
+ }
184
181
  /**
185
182
  * @internal
186
183
  */
@@ -188,11 +185,6 @@ export class EntitySchema {
188
185
  if (this.initialized) {
189
186
  return this;
190
187
  }
191
- if (!this._meta.class) {
192
- const name = this.name;
193
- this._meta.class = ({ [name]: class {
194
- } })[name];
195
- }
196
188
  this.setClass(this._meta.class);
197
189
  if (this._meta.abstract && !this._meta.discriminatorColumn) {
198
190
  delete this._meta.name;
@@ -200,7 +192,7 @@ export class EntitySchema {
200
192
  const tableName = this._meta.collection ?? this._meta.tableName;
201
193
  if (tableName?.includes('.') && !this._meta.schema) {
202
194
  this._meta.schema = tableName.substring(0, tableName.indexOf('.'));
203
- this._meta.collection = tableName.substring(tableName.indexOf('.') + 1);
195
+ this._meta.tableName = tableName.substring(tableName.indexOf('.') + 1);
204
196
  }
205
197
  this.initProperties();
206
198
  this.initPrimaryKeys();
@@ -266,12 +258,15 @@ export class EntitySchema {
266
258
  }
267
259
  normalizeType(options, type) {
268
260
  if ('entity' in options) {
269
- if (Utils.isString(options.entity)) {
270
- type = options.type = options.entity;
261
+ /* v8 ignore next */
262
+ if (typeof options.entity === 'string') {
263
+ throw new Error(`Relation target needs to be an entity class or EntitySchema instance, string '${options.entity}' given instead for ${this._meta.className}.${options.name}.`);
271
264
  }
272
265
  else if (options.entity) {
273
266
  const tmp = options.entity();
274
267
  type = options.type = Array.isArray(tmp) ? tmp.map(t => Utils.className(t)).sort().join(' | ') : Utils.className(tmp);
268
+ const target = tmp instanceof EntitySchema ? tmp.meta.class : tmp;
269
+ return { type, target };
275
270
  }
276
271
  }
277
272
  if (type instanceof Function) {
@@ -280,7 +275,7 @@ export class EntitySchema {
280
275
  if (['String', 'Number', 'Boolean', 'Array'].includes(type)) {
281
276
  type = type.toLowerCase();
282
277
  }
283
- return type;
278
+ return { type };
284
279
  }
285
280
  createProperty(kind, options) {
286
281
  return {
@@ -289,4 +284,25 @@ export class EntitySchema {
289
284
  ...options,
290
285
  };
291
286
  }
287
+ rename(data, from, to) {
288
+ if (from in data && !(to in data)) {
289
+ // @ts-ignore
290
+ data[to] = [data[from]];
291
+ // @ts-ignore
292
+ delete data[from];
293
+ }
294
+ }
295
+ renameCompositeOptions(name, options = {}) {
296
+ if (name !== options.name && !options.fieldNames) {
297
+ Utils.renameKey(options, 'name', 'fieldName');
298
+ }
299
+ else if (options.name && (options.fieldNames?.length ?? 0) > 1) {
300
+ delete options.name;
301
+ }
302
+ this.rename(options, 'fieldName', 'fieldNames');
303
+ this.rename(options, 'joinColumn', 'joinColumns');
304
+ this.rename(options, 'inverseJoinColumn', 'inverseJoinColumns');
305
+ this.rename(options, 'referenceColumnName', 'referencedColumnNames');
306
+ this.rename(options, 'columnType', 'columnTypes');
307
+ }
292
308
  }