@mikro-orm/core 7.0.0-dev.114 → 7.0.0-dev.115

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 (54) hide show
  1. package/EntityManager.d.ts +8 -8
  2. package/EntityManager.js +40 -60
  3. package/MikroORM.d.ts +1 -1
  4. package/MikroORM.js +2 -3
  5. package/drivers/DatabaseDriver.d.ts +11 -11
  6. package/drivers/DatabaseDriver.js +7 -8
  7. package/drivers/IDatabaseDriver.d.ts +10 -10
  8. package/entity/Collection.js +5 -5
  9. package/entity/EntityAssigner.js +9 -9
  10. package/entity/EntityFactory.js +14 -17
  11. package/entity/EntityHelper.d.ts +2 -2
  12. package/entity/EntityHelper.js +2 -2
  13. package/entity/EntityLoader.d.ts +3 -3
  14. package/entity/EntityLoader.js +17 -16
  15. package/entity/WrappedEntity.js +1 -1
  16. package/entity/defineEntity.d.ts +11 -11
  17. package/errors.d.ts +8 -8
  18. package/errors.js +14 -13
  19. package/hydration/ObjectHydrator.js +23 -16
  20. package/metadata/EntitySchema.d.ts +5 -5
  21. package/metadata/EntitySchema.js +23 -21
  22. package/metadata/MetadataDiscovery.d.ts +2 -3
  23. package/metadata/MetadataDiscovery.js +117 -90
  24. package/metadata/MetadataProvider.js +2 -0
  25. package/metadata/MetadataStorage.d.ts +13 -6
  26. package/metadata/MetadataStorage.js +64 -19
  27. package/metadata/MetadataValidator.d.ts +2 -2
  28. package/metadata/MetadataValidator.js +22 -28
  29. package/metadata/types.d.ts +3 -3
  30. package/package.json +1 -1
  31. package/serialization/EntitySerializer.js +2 -2
  32. package/serialization/EntityTransformer.js +6 -6
  33. package/serialization/SerializationContext.d.ts +6 -6
  34. package/typings.d.ts +16 -14
  35. package/typings.js +15 -10
  36. package/unit-of-work/ChangeSet.d.ts +2 -3
  37. package/unit-of-work/ChangeSet.js +2 -3
  38. package/unit-of-work/ChangeSetComputer.js +3 -3
  39. package/unit-of-work/ChangeSetPersister.js +14 -14
  40. package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
  41. package/unit-of-work/CommitOrderCalculator.js +13 -13
  42. package/unit-of-work/UnitOfWork.d.ts +3 -3
  43. package/unit-of-work/UnitOfWork.js +46 -45
  44. package/utils/AbstractSchemaGenerator.js +7 -7
  45. package/utils/Configuration.d.ts +0 -5
  46. package/utils/DataloaderUtils.js +13 -11
  47. package/utils/EntityComparator.d.ts +6 -6
  48. package/utils/EntityComparator.js +22 -24
  49. package/utils/QueryHelper.d.ts +5 -5
  50. package/utils/QueryHelper.js +7 -7
  51. package/utils/TransactionManager.js +1 -1
  52. package/utils/Utils.d.ts +1 -1
  53. package/utils/Utils.js +1 -2
  54. package/utils/env-vars.js +0 -1
@@ -7,7 +7,7 @@ import { EntityLoader, type EntityLoaderOptions } from './entity/EntityLoader.js
7
7
  import { Reference } from './entity/Reference.js';
8
8
  import { UnitOfWork } from './unit-of-work/UnitOfWork.js';
9
9
  import type { CountOptions, DeleteOptions, FilterOptions, FindAllOptions, FindByCursorOptions, FindOneOptions, FindOneOrFailOptions, FindOptions, GetReferenceOptions, IDatabaseDriver, LockOptions, NativeInsertUpdateOptions, StreamOptions, UpdateOptions, UpsertManyOptions, UpsertOptions } from './drivers/IDatabaseDriver.js';
10
- import type { AnyString, ArrayElement, AutoPath, ConnectionType, Dictionary, EntityData, EntityDictionary, EntityDTO, EntityMetadata, EntityName, FilterDef, FilterQuery, FromEntityType, GetRepository, IHydrator, IsSubset, Loaded, MergeLoaded, MergeSelected, NoInfer, ObjectQuery, Primary, Ref, RequiredEntityData, UnboxArray } from './typings.js';
10
+ import type { AnyString, ArrayElement, AutoPath, ConnectionType, Dictionary, EntityClass, EntityData, EntityDictionary, EntityDTO, EntityMetadata, EntityName, FilterDef, FilterQuery, FromEntityType, GetRepository, IHydrator, IsSubset, Loaded, MergeLoaded, MergeSelected, NoInfer, ObjectQuery, Primary, Ref, RequiredEntityData, UnboxArray } from './typings.js';
11
11
  import { FlushMode, LockMode, PopulatePath, type TransactionOptions } from './enums.js';
12
12
  import type { MetadataStorage } from './metadata/MetadataStorage.js';
13
13
  import type { Transaction } from './connections/Connection.js';
@@ -99,7 +99,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
99
99
  /**
100
100
  * Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
101
101
  */
102
- addFilter<T extends EntityName<any> | readonly EntityName<any>[]>(options: FilterDef<T>): void;
102
+ addFilter<T extends EntityName | readonly EntityName[]>(options: FilterDef<T>): void;
103
103
  /**
104
104
  * Sets filter parameter values globally inside context defined by this entity manager.
105
105
  * If you want to set shared value for all contexts, be sure to use the root entity manager.
@@ -120,21 +120,21 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
120
120
  disableContextResolution?: boolean;
121
121
  }): T;
122
122
  setFlushMode(flushMode?: FlushMode | `${FlushMode}`): void;
123
- protected processWhere<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(entityName: string, where: FilterQuery<Entity>, options: FindOptions<Entity, Hint, Fields, Excludes> | FindOneOptions<Entity, Hint, Fields, Excludes>, type: 'read' | 'update' | 'delete'): Promise<FilterQuery<Entity>>;
124
- protected applyDiscriminatorCondition<Entity extends object>(entityName: string, where: FilterQuery<Entity>): FilterQuery<Entity>;
123
+ protected processWhere<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<Entity>, options: FindOptions<Entity, Hint, Fields, Excludes> | FindOneOptions<Entity, Hint, Fields, Excludes>, type: 'read' | 'update' | 'delete'): Promise<FilterQuery<Entity>>;
124
+ protected applyDiscriminatorCondition<Entity extends object>(entityName: EntityName<Entity>, where: FilterQuery<Entity>): FilterQuery<Entity>;
125
125
  protected createPopulateWhere<Entity extends object>(cond: ObjectQuery<Entity>, options: FindOptions<Entity, any, any, any> | FindOneOptions<Entity, any, any, any> | CountOptions<Entity, any>): ObjectQuery<Entity>;
126
126
  protected getJoinedFilters<Entity extends object>(meta: EntityMetadata<Entity>, options: FindOptions<Entity, any, any, any> | FindOneOptions<Entity, any, any, any>): Promise<ObjectQuery<Entity> | undefined>;
127
127
  /**
128
128
  * When filters are active on M:1 or 1:1 relations, we need to ref join them eagerly as they might affect the FK value.
129
129
  */
130
130
  protected autoJoinRefsForFilters<T extends object>(meta: EntityMetadata<T>, options: FindOptions<T, any, any, any> | FindOneOptions<T, any, any, any>, parent?: {
131
- className: string;
131
+ class: EntityClass;
132
132
  propName: string;
133
133
  }): Promise<void>;
134
134
  /**
135
135
  * @internal
136
136
  */
137
- applyFilters<Entity extends object>(entityName: string, where: FilterQuery<Entity> | undefined, options: FilterOptions | undefined, type: 'read' | 'update' | 'delete', findOptions?: FindOptions<any, any, any, any> | FindOneOptions<any, any, any, any>): Promise<FilterQuery<Entity> | undefined>;
137
+ applyFilters<Entity extends object>(entityName: EntityName<Entity>, where: FilterQuery<Entity> | undefined, options: FilterOptions | undefined, type: 'read' | 'update' | 'delete', findOptions?: FindOptions<any, any, any, any> | FindOneOptions<any, any, any, any>): Promise<FilterQuery<Entity> | undefined>;
138
138
  /**
139
139
  * Calls `em.find()` and `em.count()` with the same arguments (where applicable) and returns the results as tuple
140
140
  * where the first element is the array of entities, and the second is the count.
@@ -508,11 +508,11 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
508
508
  /**
509
509
  * @internal
510
510
  */
511
- cacheKey<T extends object>(entityName: string, options: FindOptions<T, any, any, any> | FindOneOptions<T, any, any, any> | CountOptions<T, any>, method: string, where: FilterQuery<T>): unknown[];
511
+ cacheKey<T extends object>(entityName: EntityName<T>, options: FindOptions<T, any, any, any> | FindOneOptions<T, any, any, any> | CountOptions<T, any>, method: string, where: FilterQuery<T>): unknown[];
512
512
  /**
513
513
  * @internal
514
514
  */
515
- tryCache<T extends object, R>(entityName: string, config: boolean | number | [string, number] | undefined, key: unknown, refresh?: boolean, merge?: boolean): Promise<{
515
+ tryCache<T extends object, R>(entityName: EntityName<T>, config: boolean | number | [string, number] | undefined, key: unknown, refresh?: boolean, merge?: boolean): Promise<{
516
516
  data?: R | null;
517
517
  key: string;
518
518
  } | undefined>;
package/EntityManager.js CHANGED
@@ -35,7 +35,7 @@ export class EntityManager {
35
35
  global = false;
36
36
  name;
37
37
  loaders = {};
38
- repositoryMap = {};
38
+ repositoryMap = new Map();
39
39
  entityLoader;
40
40
  comparator;
41
41
  entityFactory;
@@ -88,13 +88,12 @@ export class EntityManager {
88
88
  * Gets repository for given entity. You can pass either string name or entity class reference.
89
89
  */
90
90
  getRepository(entityName) {
91
- entityName = Utils.className(entityName);
92
- if (!this.repositoryMap[entityName]) {
93
- const meta = this.metadata.get(entityName);
91
+ const meta = this.metadata.get(entityName);
92
+ if (!this.repositoryMap.has(meta)) {
94
93
  const RepositoryClass = this.config.getRepositoryClass(meta.repository);
95
- this.repositoryMap[entityName] = new RepositoryClass(this, entityName);
94
+ this.repositoryMap.set(meta, new RepositoryClass(this, entityName));
96
95
  }
97
- return this.repositoryMap[entityName];
96
+ return this.repositoryMap.get(meta);
98
97
  }
99
98
  /**
100
99
  * Shortcut for `em.getRepository()`.
@@ -116,7 +115,6 @@ export class EntityManager {
116
115
  const em = this.getContext();
117
116
  em.prepareOptions(options);
118
117
  await em.tryFlush(entityName, options);
119
- entityName = Utils.className(entityName);
120
118
  where = await em.processWhere(entityName, where, options, 'read');
121
119
  validateParams(where);
122
120
  options.orderBy = options.orderBy || {};
@@ -192,7 +190,6 @@ export class EntityManager {
192
190
  em.prepareOptions(options);
193
191
  options.strategy = 'joined';
194
192
  await em.tryFlush(entityName, options);
195
- entityName = Utils.className(entityName);
196
193
  const where = await em.processWhere(entityName, options.where ?? {}, options, 'read');
197
194
  validateParams(where);
198
195
  options.orderBy = options.orderBy || {};
@@ -303,15 +300,15 @@ export class EntityManager {
303
300
  if (!meta?.discriminatorValue) {
304
301
  return where;
305
302
  }
306
- const types = Object.values(meta.root.discriminatorMap).map(cls => this.metadata.find(cls));
303
+ const types = Object.values(meta.root.discriminatorMap).map(cls => this.metadata.get(cls));
307
304
  const children = [];
308
305
  const lookUpChildren = (ret, type) => {
309
306
  const children = types.filter(meta2 => meta2.extends === type);
310
- children.forEach(m => lookUpChildren(ret, m.className));
307
+ children.forEach(m => lookUpChildren(ret, m.class));
311
308
  ret.push(...children.filter(c => c.discriminatorValue));
312
309
  return children;
313
310
  };
314
- lookUpChildren(children, meta.className);
311
+ lookUpChildren(children, meta.class);
315
312
  /* v8 ignore next */
316
313
  where[meta.root.discriminatorColumn] = children.length > 0 ? { $in: [meta.discriminatorValue, ...children.map(c => c.discriminatorValue)] } : meta.discriminatorValue;
317
314
  return where;
@@ -341,7 +338,7 @@ export class EntityManager {
341
338
  continue;
342
339
  }
343
340
  const filters = QueryHelper.mergePropertyFilters(prop.filters, options.filters);
344
- const where = await this.applyFilters(prop.type, {}, filters, 'read', {
341
+ const where = await this.applyFilters(prop.targetMeta.class, {}, filters, 'read', {
345
342
  ...options,
346
343
  populate: hint.children,
347
344
  });
@@ -377,11 +374,11 @@ export class EntityManager {
377
374
  if (prop.object
378
375
  || ![ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)
379
376
  || !((options.fields?.length ?? 0) === 0 || options.fields?.some(f => prop.name === f || prop.name.startsWith(`${String(f)}.`)))
380
- || (parent?.className === prop.targetMeta.root.className && parent.propName === prop.inversedBy)) {
377
+ || (parent?.class === prop.targetMeta.root.class && parent.propName === prop.inversedBy)) {
381
378
  continue;
382
379
  }
383
380
  options = { ...options, filters: QueryHelper.mergePropertyFilters(prop.filters, options.filters) };
384
- const cond = await this.applyFilters(prop.type, {}, options.filters, 'read', options);
381
+ const cond = await this.applyFilters(prop.targetMeta.class, {}, options.filters, 'read', options);
385
382
  if (!Utils.isEmpty(cond)) {
386
383
  const populated = options.populate.filter(({ field }) => field.split(':')[0] === prop.name);
387
384
  let found = false;
@@ -404,7 +401,7 @@ export class EntityManager {
404
401
  const prop = meta?.properties[field];
405
402
  if (prop && !ref) {
406
403
  hint.children ??= [];
407
- await this.autoJoinRefsForFilters(prop.targetMeta, { ...options, populate: hint.children }, { className: meta.root.className, propName: prop.name });
404
+ await this.autoJoinRefsForFilters(prop.targetMeta, { ...options, populate: hint.children }, { class: meta.root.class, propName: prop.name });
408
405
  }
409
406
  }
410
407
  }
@@ -412,16 +409,13 @@ export class EntityManager {
412
409
  * @internal
413
410
  */
414
411
  async applyFilters(entityName, where, options, type, findOptions) {
415
- const meta = this.metadata.find(entityName);
412
+ const meta = this.metadata.get(entityName);
416
413
  const filters = [];
417
414
  const ret = [];
418
- if (!meta) {
419
- return where;
420
- }
421
415
  const active = new Set();
422
416
  const push = (source) => {
423
417
  const activeFilters = QueryHelper
424
- .getActiveFilters(entityName, options, source)
418
+ .getActiveFilters(meta, options, source)
425
419
  .filter(f => !active.has(f.name));
426
420
  filters.push(...activeFilters);
427
421
  activeFilters.forEach(f => active.add(f.name));
@@ -440,7 +434,7 @@ export class EntityManager {
440
434
  if (!args && filter.cond.length > 0 && filter.args !== false) {
441
435
  throw new Error(`No arguments provided for filter '${filter.name}'`);
442
436
  }
443
- cond = await filter.cond(args, type, this, findOptions, entityName);
437
+ cond = await filter.cond(args, type, this, findOptions, Utils.className(entityName));
444
438
  }
445
439
  else {
446
440
  cond = filter.cond;
@@ -531,7 +525,6 @@ export class EntityManager {
531
525
  */
532
526
  async findByCursor(entityName, options) {
533
527
  const em = this.getContext(false);
534
- entityName = Utils.className(entityName);
535
528
  options.overfetch ??= true;
536
529
  options.where ??= {};
537
530
  if (Utils.isEmpty(options.orderBy) && !Raw.hasObjectFragments(options.orderBy)) {
@@ -551,9 +544,9 @@ export class EntityManager {
551
544
  const ret = await this.refresh(entity, options);
552
545
  if (!ret) {
553
546
  options.failHandler ??= this.config.get('findOneOrFailHandler');
554
- const entityName = entity.constructor.name;
555
- const where = helper(entity).getPrimaryKey();
556
- throw options.failHandler(entityName, where);
547
+ const wrapped = helper(entity);
548
+ const where = wrapped.getPrimaryKey();
549
+ throw options.failHandler(wrapped.__meta.className, where);
557
550
  }
558
551
  return ret;
559
552
  }
@@ -564,9 +557,8 @@ export class EntityManager {
564
557
  */
565
558
  async refresh(entity, options = {}) {
566
559
  const fork = this.fork({ keepTransactionContext: true });
567
- const entityName = entity.constructor.name;
568
560
  const wrapped = helper(entity);
569
- const reloaded = await fork.findOne(entityName, entity, {
561
+ const reloaded = await fork.findOne(wrapped.__meta.class, entity, {
570
562
  schema: wrapped.__schema,
571
563
  ...options,
572
564
  flushMode: FlushMode.COMMIT,
@@ -578,7 +570,7 @@ export class EntityManager {
578
570
  }
579
571
  let found = false;
580
572
  for (const e of fork.unitOfWork.getIdentityMap()) {
581
- const ref = em.getReference(e.constructor.name, helper(e).getPrimaryKey());
573
+ const ref = em.getReference(e.constructor, helper(e).getPrimaryKey());
582
574
  const data = helper(e).serialize({ ignoreSerializers: true, includeHidden: true });
583
575
  em.config.getHydrator(this.metadata).hydrate(ref, helper(ref).__meta, data, em.entityFactory, 'full', false, true);
584
576
  Utils.merge(helper(ref).__originalEntityData, this.comparator.prepareEntity(e));
@@ -603,7 +595,6 @@ export class EntityManager {
603
595
  return ret;
604
596
  }
605
597
  const em = this.getContext();
606
- entityName = Utils.className(entityName);
607
598
  em.prepareOptions(options);
608
599
  let entity = em.unitOfWork.tryGetById(entityName, where, options.schema);
609
600
  // query for a not managed entity which is already in the identity map as it
@@ -681,10 +672,10 @@ export class EntityManager {
681
672
  if (!entity || isStrictViolation) {
682
673
  const key = options.strict ? 'findExactlyOneOrFailHandler' : 'findOneOrFailHandler';
683
674
  options.failHandler ??= this.config.get(key);
684
- entityName = Utils.className(entityName);
675
+ const name = Utils.className(entityName);
685
676
  /* v8 ignore next */
686
677
  where = Utils.isEntity(where) ? helper(where).getPrimaryKey() : where;
687
- throw options.failHandler(entityName, where);
678
+ throw options.failHandler(name, where);
688
679
  }
689
680
  return entity;
690
681
  }
@@ -724,11 +715,11 @@ export class EntityManager {
724
715
  let where;
725
716
  let entity = null;
726
717
  if (data === undefined) {
727
- entityName = entityNameOrEntity.constructor.name;
718
+ entityName = entityNameOrEntity.constructor;
728
719
  data = entityNameOrEntity;
729
720
  }
730
721
  else {
731
- entityName = Utils.className(entityNameOrEntity);
722
+ entityName = entityNameOrEntity;
732
723
  }
733
724
  const meta = this.metadata.get(entityName);
734
725
  const convertCustomTypes = !Utils.isEntity(data);
@@ -791,7 +782,7 @@ export class EntityManager {
791
782
  where[meta.primaryKeys[0]] = ret.insertId;
792
783
  }
793
784
  }
794
- const data2 = await this.driver.findOne(meta.className, where, {
785
+ const data2 = await this.driver.findOne(meta.class, where, {
795
786
  fields: returning,
796
787
  ctx: em.transactionContext,
797
788
  convertCustomTypes: true,
@@ -846,11 +837,11 @@ export class EntityManager {
846
837
  let entityName;
847
838
  let propIndex;
848
839
  if (data === undefined) {
849
- entityName = entityNameOrEntity[0].constructor.name;
840
+ entityName = entityNameOrEntity[0].constructor;
850
841
  data = entityNameOrEntity;
851
842
  }
852
843
  else {
853
- entityName = Utils.className(entityNameOrEntity);
844
+ entityName = entityNameOrEntity;
854
845
  }
855
846
  const batchSize = options.batchSize ?? this.config.get('batchSize');
856
847
  if (data.length > batchSize) {
@@ -958,7 +949,7 @@ export class EntityManager {
958
949
  where.$or[idx][prop] = item[prop];
959
950
  });
960
951
  });
961
- const data2 = await this.driver.find(meta.className, where, {
952
+ const data2 = await this.driver.find(meta.class, where, {
962
953
  fields: returning.concat(...add).concat(...(Array.isArray(uniqueFields) ? uniqueFields : [])),
963
954
  ctx: em.transactionContext,
964
955
  convertCustomTypes: true,
@@ -1111,11 +1102,11 @@ export class EntityManager {
1111
1102
  em.prepareOptions(options);
1112
1103
  let entityName;
1113
1104
  if (data === undefined) {
1114
- entityName = entityNameOrEntity.constructor.name;
1105
+ entityName = entityNameOrEntity.constructor;
1115
1106
  data = entityNameOrEntity;
1116
1107
  }
1117
1108
  else {
1118
- entityName = Utils.className(entityNameOrEntity);
1109
+ entityName = entityNameOrEntity;
1119
1110
  }
1120
1111
  if (Utils.isEntity(data)) {
1121
1112
  if (options.schema && helper(data).getSchema() == null) {
@@ -1146,11 +1137,11 @@ export class EntityManager {
1146
1137
  em.prepareOptions(options);
1147
1138
  let entityName;
1148
1139
  if (data === undefined) {
1149
- entityName = entityNameOrEntities[0].constructor.name;
1140
+ entityName = entityNameOrEntities[0].constructor;
1150
1141
  data = entityNameOrEntities;
1151
1142
  }
1152
1143
  else {
1153
- entityName = Utils.className(entityNameOrEntities);
1144
+ entityName = entityNameOrEntities;
1154
1145
  }
1155
1146
  if (data.length === 0) {
1156
1147
  return [];
@@ -1187,7 +1178,6 @@ export class EntityManager {
1187
1178
  async nativeUpdate(entityName, where, data, options = {}) {
1188
1179
  const em = this.getContext(false);
1189
1180
  em.prepareOptions(options);
1190
- entityName = Utils.className(entityName);
1191
1181
  data = QueryHelper.processObjectParams(data);
1192
1182
  where = await em.processWhere(entityName, where, { ...options, convertCustomTypes: false }, 'update');
1193
1183
  validateParams(data, 'update data');
@@ -1201,7 +1191,6 @@ export class EntityManager {
1201
1191
  async nativeDelete(entityName, where, options = {}) {
1202
1192
  const em = this.getContext(false);
1203
1193
  em.prepareOptions(options);
1204
- entityName = Utils.className(entityName);
1205
1194
  where = await em.processWhere(entityName, where, options, 'delete');
1206
1195
  validateParams(where, 'delete condition');
1207
1196
  const res = await em.driver.nativeDelete(entityName, where, { ctx: em.transactionContext, ...options });
@@ -1211,7 +1200,6 @@ export class EntityManager {
1211
1200
  * Maps raw database result to an entity and merges it to this EntityManager.
1212
1201
  */
1213
1202
  map(entityName, result, options = {}) {
1214
- entityName = Utils.className(entityName);
1215
1203
  const meta = this.metadata.get(entityName);
1216
1204
  const data = this.driver.mapResult(result, meta);
1217
1205
  for (const k of Object.keys(data)) {
@@ -1233,13 +1221,12 @@ export class EntityManager {
1233
1221
  */
1234
1222
  merge(entityName, data, options = {}) {
1235
1223
  if (Utils.isEntity(entityName)) {
1236
- return this.merge(entityName.constructor.name, entityName, data);
1224
+ return this.merge(entityName.constructor, entityName, data);
1237
1225
  }
1238
1226
  const em = options.disableContextResolution ? this : this.getContext();
1239
1227
  options.schema ??= em._schema;
1240
1228
  options.validate ??= true;
1241
1229
  options.cascade ??= true;
1242
- entityName = Utils.className(entityName);
1243
1230
  validatePrimaryKey(data, em.metadata.get(entityName));
1244
1231
  let entity = em.unitOfWork.tryGetById(entityName, data, options.schema, false);
1245
1232
  if (entity && helper(entity).__managed && helper(entity).__initialized && !options.refresh) {
@@ -1293,7 +1280,7 @@ export class EntityManager {
1293
1280
  getReference(entityName, id, options = {}) {
1294
1281
  options.schema ??= this.schema;
1295
1282
  options.convertCustomTypes ??= false;
1296
- const meta = this.metadata.get(Utils.className(entityName));
1283
+ const meta = this.metadata.get(entityName);
1297
1284
  if (Utils.isPrimaryKey(id)) {
1298
1285
  if (meta.compositePK) {
1299
1286
  throw ValidationError.invalidCompositeIdentifier(meta);
@@ -1314,7 +1301,6 @@ export class EntityManager {
1314
1301
  // Shallow copy options since the object will be modified when deleting orderBy
1315
1302
  options = { ...options };
1316
1303
  em.prepareOptions(options);
1317
- entityName = Utils.className(entityName);
1318
1304
  await em.tryFlush(entityName, options);
1319
1305
  where = await em.processWhere(entityName, where, options, 'read');
1320
1306
  options.populate = await em.preparePopulate(entityName, options);
@@ -1350,7 +1336,7 @@ export class EntityManager {
1350
1336
  for (const ent of entities) {
1351
1337
  if (!Utils.isEntity(ent, true)) {
1352
1338
  /* v8 ignore next */
1353
- const meta = typeof ent === 'object' ? em.metadata.find(ent.constructor.name) : undefined;
1339
+ const meta = typeof ent === 'object' ? em.metadata.find(ent.constructor) : undefined;
1354
1340
  throw ValidationError.notDiscoveredEntity(ent, meta);
1355
1341
  }
1356
1342
  // do not cascade just yet, cascading of entities in persist stack is done when flushing
@@ -1394,7 +1380,6 @@ export class EntityManager {
1394
1380
  async tryFlush(entityName, options) {
1395
1381
  const em = this.getContext();
1396
1382
  const flushMode = options.flushMode ?? em.flushMode ?? em.config.get('flushMode');
1397
- entityName = Utils.className(entityName);
1398
1383
  const meta = em.metadata.get(entityName);
1399
1384
  if (flushMode === FlushMode.COMMIT) {
1400
1385
  return;
@@ -1413,7 +1398,6 @@ export class EntityManager {
1413
1398
  * Checks whether given property can be populated on the entity.
1414
1399
  */
1415
1400
  canPopulate(entityName, property) {
1416
- entityName = Utils.className(entityName);
1417
1401
  // eslint-disable-next-line prefer-const
1418
1402
  let [p, ...parts] = property.split('.');
1419
1403
  const meta = this.metadata.find(entityName);
@@ -1424,11 +1408,8 @@ export class EntityManager {
1424
1408
  p = p.split(':', 2)[0];
1425
1409
  }
1426
1410
  const ret = p in meta.root.properties;
1427
- if (!ret) {
1428
- return !!this.metadata.find(property)?.pivotTable;
1429
- }
1430
1411
  if (parts.length > 0) {
1431
- return this.canPopulate((meta.root.properties)[p].type, parts.join('.'));
1412
+ return this.canPopulate(meta.root.properties[p].targetMeta.class, parts.join('.'));
1432
1413
  }
1433
1414
  return ret;
1434
1415
  }
@@ -1442,7 +1423,7 @@ export class EntityManager {
1442
1423
  }
1443
1424
  const em = this.getContext();
1444
1425
  em.prepareOptions(options);
1445
- const entityName = arr[0].constructor.name;
1426
+ const entityName = arr[0].constructor;
1446
1427
  const preparedPopulate = await em.preparePopulate(entityName, { populate: populate, filters: options.filters }, options.validate);
1447
1428
  await em.entityLoader.populate(entityName, arr, preparedPopulate, options);
1448
1429
  return entities;
@@ -1571,7 +1552,6 @@ export class EntityManager {
1571
1552
  */
1572
1553
  getMetadata(entityName) {
1573
1554
  if (entityName) {
1574
- entityName = Utils.className(entityName);
1575
1555
  return this.metadata.get(entityName);
1576
1556
  }
1577
1557
  return this.metadata;
@@ -1600,8 +1580,8 @@ export class EntityManager {
1600
1580
  lockTableAliases: options.lockTableAliases,
1601
1581
  });
1602
1582
  }
1603
- const preparedPopulate = await this.preparePopulate(meta.className, options);
1604
- await this.entityLoader.populate(meta.className, [entity], preparedPopulate, {
1583
+ const preparedPopulate = await this.preparePopulate(meta.class, options);
1584
+ await this.entityLoader.populate(meta.class, [entity], preparedPopulate, {
1605
1585
  ...options,
1606
1586
  ...this.getPopulateWhere(where, options),
1607
1587
  orderBy: options.populateOrderBy ?? options.orderBy,
@@ -1738,7 +1718,7 @@ export class EntityManager {
1738
1718
  for (const k of ['ctx', 'strategy', 'flushMode', 'logging', 'loggerContext']) {
1739
1719
  delete opts[k];
1740
1720
  }
1741
- return [entityName, method, opts, where];
1721
+ return [Utils.className(entityName), method, opts, where];
1742
1722
  }
1743
1723
  /**
1744
1724
  * @internal
package/MikroORM.d.ts CHANGED
@@ -94,7 +94,7 @@ export declare class MikroORM<Driver extends IDatabaseDriver = IDatabaseDriver,
94
94
  /**
95
95
  * Allows dynamically discovering new entity by reference, handy for testing schema diffing.
96
96
  */
97
- discoverEntity<T extends Constructor | EntitySchema>(entities: T | T[], reset?: string | string[]): void;
97
+ discoverEntity<T extends Constructor | EntitySchema>(entities: T | T[], reset?: EntityName | EntityName[]): void;
98
98
  /**
99
99
  * Gets the SchemaGenerator.
100
100
  */
package/MikroORM.js CHANGED
@@ -158,7 +158,6 @@ export class MikroORM {
158
158
  */
159
159
  getMetadata(entityName) {
160
160
  if (entityName) {
161
- entityName = Utils.className(entityName);
162
161
  return this.metadata.get(entityName);
163
162
  }
164
163
  return this.metadata;
@@ -181,8 +180,8 @@ export class MikroORM {
181
180
  const tmp = this.discovery.discoverReferences(Utils.asArray(entities));
182
181
  const metadata = this.discovery.processDiscoveredEntities(tmp);
183
182
  for (const meta of metadata) {
184
- this.metadata.set(meta.className, meta);
185
- meta.root = this.metadata.get(meta.root.className);
183
+ this.metadata.set(meta.class, meta);
184
+ meta.root = this.metadata.get(meta.root.class);
186
185
  }
187
186
  this.metadata.decorate(this.em);
188
187
  }
@@ -22,18 +22,18 @@ export declare abstract class DatabaseDriver<C extends Connection> implements ID
22
22
  protected comparator: EntityComparator;
23
23
  protected metadata: MetadataStorage;
24
24
  protected constructor(config: Configuration, dependencies: string[]);
25
- abstract find<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
26
- abstract findOne<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
27
- abstract nativeInsert<T extends object>(entityName: string, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
28
- abstract nativeInsertMany<T extends object>(entityName: string, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>, transform?: (sql: string) => string): Promise<QueryResult<T>>;
29
- abstract nativeUpdate<T extends object>(entityName: string, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
30
- nativeUpdateMany<T extends object>(entityName: string, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
31
- abstract nativeDelete<T extends object>(entityName: string, where: FilterQuery<T>, options?: DeleteOptions<T>): Promise<QueryResult<T>>;
32
- abstract count<T extends object, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: CountOptions<T, P>): Promise<number>;
25
+ abstract find<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
26
+ abstract findOne<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
27
+ abstract nativeInsert<T extends object>(entityName: EntityName<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
28
+ abstract nativeInsertMany<T extends object>(entityName: EntityName<T>, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>, transform?: (sql: string) => string): Promise<QueryResult<T>>;
29
+ abstract nativeUpdate<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
30
+ nativeUpdateMany<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
31
+ abstract nativeDelete<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options?: DeleteOptions<T>): Promise<QueryResult<T>>;
32
+ abstract count<T extends object, P extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: CountOptions<T, P>): Promise<number>;
33
33
  createEntityManager(useContext?: boolean): this[typeof EntityManagerType];
34
34
  findVirtual<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: FindOptions<T, any, any, any>): Promise<EntityData<T>[]>;
35
- countVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: CountOptions<T, any>): Promise<number>;
36
- aggregate(entityName: string, pipeline: any[]): Promise<any[]>;
35
+ countVirtual<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: CountOptions<T, any>): Promise<number>;
36
+ aggregate(entityName: EntityName, pipeline: any[]): Promise<any[]>;
37
37
  loadFromPivotTable<T extends object, O extends object>(prop: EntityProperty, owners: Primary<O>[][], where?: FilterQuery<any>, orderBy?: OrderDefinition<T>, ctx?: Transaction, options?: FindOptions<T, any, any, any>, pivotJoin?: boolean): Promise<Dictionary<T[]>>;
38
38
  syncCollections<T extends object, O extends object>(collections: Iterable<Collection<T, O>>, options?: DriverMethodOptions): Promise<void>;
39
39
  mapResult<T extends object>(result: EntityDictionary<T>, meta?: EntityMetadata<T>, populate?: PopulateOptions<T>[]): EntityData<T> | null;
@@ -58,7 +58,7 @@ export declare abstract class DatabaseDriver<C extends Connection> implements ID
58
58
  /** @internal */
59
59
  mapDataToFieldNames(data: Dictionary, stringifyJsonArrays: boolean, properties?: Record<string, EntityProperty>, convertCustomTypes?: boolean, object?: boolean): Dictionary;
60
60
  protected inlineEmbeddables<T extends object>(meta: EntityMetadata<T>, data: T, where?: boolean): void;
61
- protected getPrimaryKeyFields(entityName: string): string[];
61
+ protected getPrimaryKeyFields<T>(meta: EntityMetadata<T>): string[];
62
62
  protected createReplicas(cb: (c: ConnectionOptions) => C): C[];
63
63
  lockPessimistic<T extends object>(entity: T, options: LockOptions): Promise<void>;
64
64
  abstract stream<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: StreamOptions<T>): AsyncIterableIterator<T>;
@@ -59,7 +59,7 @@ export class DatabaseDriver {
59
59
  {
60
60
  const pk = coll.property.targetMeta.primaryKeys[0];
61
61
  const data = { [coll.property.name]: coll.getIdentifiers(pk) };
62
- await this.nativeUpdate(coll.owner.constructor.name, helper(coll.owner).getPrimaryKey(), data, options);
62
+ await this.nativeUpdate(coll.owner.constructor, helper(coll.owner).getPrimaryKey(), data, options);
63
63
  }
64
64
  }
65
65
  }
@@ -67,7 +67,7 @@ export class DatabaseDriver {
67
67
  if (!result || !meta) {
68
68
  return result ?? null;
69
69
  }
70
- return this.comparator.mapResult(meta.className, result);
70
+ return this.comparator.mapResult(meta, result);
71
71
  }
72
72
  async connect(options) {
73
73
  await this.connection.connect(options);
@@ -277,14 +277,14 @@ export class DatabaseDriver {
277
277
  // explicitly allow `$exists`, `$eq` and `$ne` operators here as they can't be misused this way
278
278
  const operator = Object.keys(data[prop.name]).some(f => Utils.isOperator(f) && !['$exists', '$ne', '$eq'].includes(f));
279
279
  if (operator) {
280
- throw ValidationError.cannotUseOperatorsInsideEmbeddables(meta.className, prop.name, data);
280
+ throw ValidationError.cannotUseOperatorsInsideEmbeddables(meta.class, prop.name, data);
281
281
  }
282
282
  if (prop.object && where) {
283
283
  const inline = (payload, sub, path) => {
284
284
  if (sub.kind === ReferenceKind.EMBEDDED && Utils.isObject(payload[sub.embedded[1]])) {
285
285
  return Object.keys(payload[sub.embedded[1]]).forEach(kkk => {
286
286
  if (!sub.embeddedProps[kkk]) {
287
- throw ValidationError.invalidEmbeddableQuery(meta.className, kkk, sub.type);
287
+ throw ValidationError.invalidEmbeddableQuery(meta.class, kkk, sub.type);
288
288
  }
289
289
  inline(payload[sub.embedded[1]], sub.embeddedProps[kkk], [...path, sub.embedded[1]]);
290
290
  });
@@ -308,7 +308,7 @@ export class DatabaseDriver {
308
308
  data[props[kk].name] = data[prop.name][props[kk].embedded[1]];
309
309
  }
310
310
  else {
311
- throw ValidationError.invalidEmbeddableQuery(meta.className, kk, prop.type);
311
+ throw ValidationError.invalidEmbeddableQuery(meta.class, kk, prop.type);
312
312
  }
313
313
  });
314
314
  if (!unknownProp) {
@@ -317,9 +317,8 @@ export class DatabaseDriver {
317
317
  }
318
318
  });
319
319
  }
320
- getPrimaryKeyFields(entityName) {
321
- const meta = this.metadata.find(entityName);
322
- return meta ? Utils.flatten(meta.getPrimaryProps().map(pk => pk.fieldNames)) : [this.config.getNamingStrategy().referenceColumnName()];
320
+ getPrimaryKeyFields(meta) {
321
+ return meta.getPrimaryProps().flatMap(pk => pk.fieldNames);
323
322
  }
324
323
  createReplicas(cb) {
325
324
  const replicas = this.config.get('replicas', []);
@@ -25,21 +25,21 @@ export interface IDatabaseDriver<C extends Connection = Connection> {
25
25
  /**
26
26
  * Finds selection of entities
27
27
  */
28
- find<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
28
+ find<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
29
29
  /**
30
30
  * Finds single entity (table row, document)
31
31
  */
32
- findOne<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
33
- findVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: FindOptions<T, any, any, any>): Promise<EntityData<T>[]>;
32
+ findOne<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
33
+ findVirtual<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: FindOptions<T, any, any, any>): Promise<EntityData<T>[]>;
34
34
  stream<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: StreamOptions<T>): AsyncIterableIterator<T>;
35
- nativeInsert<T extends object>(entityName: string, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
36
- nativeInsertMany<T extends object>(entityName: string, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>, transform?: (sql: string) => string): Promise<QueryResult<T>>;
37
- nativeUpdate<T extends object>(entityName: string, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
38
- nativeUpdateMany<T extends object>(entityName: string, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
39
- nativeDelete<T extends object>(entityName: string, where: FilterQuery<T>, options?: NativeDeleteOptions<T>): Promise<QueryResult<T>>;
35
+ nativeInsert<T extends object>(entityName: EntityName<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
36
+ nativeInsertMany<T extends object>(entityName: EntityName<T>, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>, transform?: (sql: string) => string): Promise<QueryResult<T>>;
37
+ nativeUpdate<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
38
+ nativeUpdateMany<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
39
+ nativeDelete<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options?: NativeDeleteOptions<T>): Promise<QueryResult<T>>;
40
40
  syncCollections<T extends object, O extends object>(collections: Iterable<Collection<T, O>>, options?: DriverMethodOptions): Promise<void>;
41
- count<T extends object, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: CountOptions<T, P>): Promise<number>;
42
- aggregate(entityName: string, pipeline: any[]): Promise<any[]>;
41
+ count<T extends object, P extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: CountOptions<T, P>): Promise<number>;
42
+ aggregate(entityName: EntityName, pipeline: any[]): Promise<any[]>;
43
43
  mapResult<T extends object>(result: EntityDictionary<T>, meta: EntityMetadata<T>, populate?: PopulateOptions<T>[]): EntityData<T> | null;
44
44
  /**
45
45
  * When driver uses pivot tables for M:N, this method will load identifiers for given collections from them
@@ -84,7 +84,7 @@ export class Collection {
84
84
  return this._count = this.length;
85
85
  }
86
86
  const cond = this.createLoadCountCondition(where ?? {});
87
- const count = await em.count(this.property.type, cond, countOptions);
87
+ const count = await em.count(this.property.targetMeta.class, cond, countOptions);
88
88
  if (!where) {
89
89
  this._count = count;
90
90
  }
@@ -96,12 +96,12 @@ export class Collection {
96
96
  opts.orderBy = this.createOrderBy(opts.orderBy);
97
97
  let items;
98
98
  if (this.property.kind === ReferenceKind.MANY_TO_MANY && em.getPlatform().usesPivotTable()) {
99
- const cond = await em.applyFilters(this.property.type, where, options.filters ?? {}, 'read');
99
+ const cond = await em.applyFilters(this.property.targetMeta.class, where, options.filters ?? {}, 'read');
100
100
  const map = await em.getDriver().loadFromPivotTable(this.property, [helper(this.owner).__primaryKeys], cond, opts.orderBy, ctx, options);
101
- items = map[helper(this.owner).getSerializedPrimaryKey()].map((item) => em.merge(this.property.type, item, { convertCustomTypes: true }));
101
+ items = map[helper(this.owner).getSerializedPrimaryKey()].map((item) => em.merge(this.property.targetMeta.class, item, { convertCustomTypes: true }));
102
102
  }
103
103
  else {
104
- items = await em.find(this.property.type, this.createCondition(where), opts);
104
+ items = await em.find(this.property.targetMeta.class, this.createCondition(where), opts);
105
105
  }
106
106
  if (options.store) {
107
107
  this.hydrate(items, true);
@@ -331,7 +331,7 @@ export class Collection {
331
331
  }
332
332
  checkInitialized() {
333
333
  if (!this.isInitialized()) {
334
- throw new Error(`Collection<${this.property.type}> of entity ${this.owner.constructor.name}[${helper(this.owner).getSerializedPrimaryKey()}] not initialized`);
334
+ throw new Error(`Collection<${this.property.type}> of entity ${helper(this.owner).__meta.name}[${helper(this.owner).getSerializedPrimaryKey()}] not initialized`);
335
335
  }
336
336
  }
337
337
  /**