@mikro-orm/core 7.0.0-dev.3 → 7.0.0-dev.31

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 (102) hide show
  1. package/EntityManager.d.ts +50 -7
  2. package/EntityManager.js +141 -97
  3. package/MikroORM.js +0 -1
  4. package/README.md +1 -2
  5. package/cache/FileCacheAdapter.d.ts +2 -1
  6. package/cache/FileCacheAdapter.js +6 -4
  7. package/connections/Connection.d.ts +4 -2
  8. package/connections/Connection.js +2 -2
  9. package/decorators/Check.d.ts +2 -2
  10. package/decorators/Embeddable.d.ts +5 -5
  11. package/decorators/Embeddable.js +1 -1
  12. package/decorators/Embedded.d.ts +6 -12
  13. package/decorators/Entity.d.ts +20 -5
  14. package/decorators/Entity.js +0 -1
  15. package/decorators/Enum.d.ts +1 -1
  16. package/decorators/Formula.d.ts +1 -2
  17. package/decorators/Indexed.d.ts +10 -8
  18. package/decorators/Indexed.js +1 -1
  19. package/decorators/ManyToMany.d.ts +4 -2
  20. package/decorators/ManyToOne.d.ts +6 -2
  21. package/decorators/OneToMany.d.ts +4 -4
  22. package/decorators/OneToOne.d.ts +5 -1
  23. package/decorators/PrimaryKey.d.ts +2 -3
  24. package/decorators/Property.d.ts +1 -1
  25. package/decorators/Transactional.d.ts +1 -0
  26. package/decorators/Transactional.js +3 -3
  27. package/drivers/IDatabaseDriver.d.ts +8 -1
  28. package/entity/ArrayCollection.d.ts +4 -2
  29. package/entity/ArrayCollection.js +18 -6
  30. package/entity/Collection.d.ts +1 -2
  31. package/entity/Collection.js +16 -10
  32. package/entity/EntityAssigner.d.ts +1 -1
  33. package/entity/EntityAssigner.js +9 -1
  34. package/entity/EntityFactory.d.ts +6 -0
  35. package/entity/EntityFactory.js +21 -7
  36. package/entity/EntityHelper.js +8 -1
  37. package/entity/EntityLoader.d.ts +3 -2
  38. package/entity/EntityLoader.js +54 -35
  39. package/entity/EntityRepository.d.ts +1 -1
  40. package/entity/EntityValidator.js +1 -1
  41. package/entity/Reference.d.ts +8 -7
  42. package/entity/Reference.js +22 -1
  43. package/entity/WrappedEntity.js +1 -1
  44. package/entity/defineEntity.d.ts +537 -0
  45. package/entity/defineEntity.js +693 -0
  46. package/entity/index.d.ts +2 -0
  47. package/entity/index.js +2 -0
  48. package/entity/utils.d.ts +7 -0
  49. package/entity/utils.js +15 -3
  50. package/enums.d.ts +16 -3
  51. package/enums.js +13 -0
  52. package/errors.d.ts +6 -0
  53. package/errors.js +14 -0
  54. package/events/EventSubscriber.d.ts +3 -1
  55. package/hydration/ObjectHydrator.js +10 -2
  56. package/index.d.ts +1 -1
  57. package/metadata/EntitySchema.d.ts +6 -4
  58. package/metadata/EntitySchema.js +33 -19
  59. package/metadata/MetadataDiscovery.d.ts +0 -1
  60. package/metadata/MetadataDiscovery.js +51 -29
  61. package/metadata/MetadataStorage.js +1 -1
  62. package/metadata/MetadataValidator.js +4 -3
  63. package/package.json +5 -5
  64. package/platforms/Platform.d.ts +3 -1
  65. package/serialization/EntitySerializer.d.ts +2 -0
  66. package/serialization/EntitySerializer.js +1 -1
  67. package/serialization/SerializationContext.js +13 -10
  68. package/types/BigIntType.d.ts +9 -6
  69. package/types/BigIntType.js +3 -0
  70. package/types/BooleanType.d.ts +1 -1
  71. package/types/DecimalType.d.ts +6 -4
  72. package/types/DecimalType.js +1 -1
  73. package/types/DoubleType.js +1 -1
  74. package/typings.d.ts +72 -35
  75. package/typings.js +24 -4
  76. package/unit-of-work/ChangeSetComputer.js +3 -1
  77. package/unit-of-work/ChangeSetPersister.d.ts +4 -2
  78. package/unit-of-work/ChangeSetPersister.js +21 -11
  79. package/unit-of-work/UnitOfWork.d.ts +2 -1
  80. package/unit-of-work/UnitOfWork.js +71 -24
  81. package/utils/AbstractSchemaGenerator.js +5 -2
  82. package/utils/Configuration.d.ts +15 -5
  83. package/utils/Configuration.js +7 -7
  84. package/utils/ConfigurationLoader.d.ts +0 -2
  85. package/utils/ConfigurationLoader.js +2 -24
  86. package/utils/Cursor.d.ts +3 -3
  87. package/utils/Cursor.js +3 -0
  88. package/utils/DataloaderUtils.d.ts +7 -2
  89. package/utils/DataloaderUtils.js +38 -7
  90. package/utils/EntityComparator.d.ts +6 -2
  91. package/utils/EntityComparator.js +98 -59
  92. package/utils/QueryHelper.d.ts +6 -0
  93. package/utils/QueryHelper.js +48 -5
  94. package/utils/RawQueryFragment.d.ts +34 -0
  95. package/utils/RawQueryFragment.js +40 -1
  96. package/utils/TransactionManager.d.ts +65 -0
  97. package/utils/TransactionManager.js +220 -0
  98. package/utils/Utils.d.ts +11 -7
  99. package/utils/Utils.js +67 -33
  100. package/utils/index.d.ts +1 -0
  101. package/utils/index.js +1 -0
  102. package/utils/upsert-utils.js +9 -1
@@ -12,16 +12,18 @@ export class ChangeSetPersister {
12
12
  factory;
13
13
  validator;
14
14
  config;
15
+ em;
15
16
  platform;
16
17
  comparator;
17
18
  usesReturningStatement;
18
- constructor(driver, metadata, hydrator, factory, validator, config) {
19
+ constructor(driver, metadata, hydrator, factory, validator, config, em) {
19
20
  this.driver = driver;
20
21
  this.metadata = metadata;
21
22
  this.hydrator = hydrator;
22
23
  this.factory = factory;
23
24
  this.validator = validator;
24
25
  this.config = config;
26
+ this.em = em;
25
27
  this.platform = this.driver.getPlatform();
26
28
  this.comparator = this.config.getComparator(this.metadata);
27
29
  this.usesReturningStatement = this.platform.usesReturningStatement() || this.platform.usesOutputStatement();
@@ -62,7 +64,7 @@ export class ChangeSetPersister {
62
64
  for (let i = 0; i < changeSets.length; i += size) {
63
65
  const chunk = changeSets.slice(i, i + size);
64
66
  const pks = chunk.map(cs => cs.getPrimaryKey());
65
- options = this.propagateSchemaFromMetadata(meta, options);
67
+ options = this.prepareOptions(meta, options);
66
68
  await this.driver.nativeDelete(meta.root.className, { [pk]: { $in: pks } }, options);
67
69
  }
68
70
  }
@@ -90,7 +92,7 @@ export class ChangeSetPersister {
90
92
  }
91
93
  async persistNewEntity(meta, changeSet, options) {
92
94
  const wrapped = helper(changeSet.entity);
93
- options = this.propagateSchemaFromMetadata(meta, options, {
95
+ options = this.prepareOptions(meta, options, {
94
96
  convertCustomTypes: false,
95
97
  });
96
98
  const res = await this.driver.nativeInsertMany(meta.className, [changeSet.payload], options);
@@ -116,15 +118,17 @@ export class ChangeSetPersister {
116
118
  }
117
119
  }
118
120
  }
119
- propagateSchemaFromMetadata(meta, options, additionalOptions) {
121
+ prepareOptions(meta, options, additionalOptions) {
122
+ const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
120
123
  return {
121
124
  ...options,
122
125
  ...additionalOptions,
123
126
  schema: options?.schema ?? meta.schema,
127
+ loggerContext,
124
128
  };
125
129
  }
126
130
  async persistNewEntitiesBatch(meta, changeSets, options) {
127
- options = this.propagateSchemaFromMetadata(meta, options, {
131
+ options = this.prepareOptions(meta, options, {
128
132
  convertCustomTypes: false,
129
133
  processCollections: false,
130
134
  });
@@ -175,7 +179,7 @@ export class ChangeSetPersister {
175
179
  }
176
180
  async persistManagedEntitiesBatch(meta, changeSets, options) {
177
181
  await this.checkOptimisticLocks(meta, changeSets, options);
178
- options = this.propagateSchemaFromMetadata(meta, options, {
182
+ options = this.prepareOptions(meta, options, {
179
183
  convertCustomTypes: false,
180
184
  processCollections: false,
181
185
  });
@@ -210,7 +214,9 @@ export class ChangeSetPersister {
210
214
  // of using the raw value from db, we convert it back to the db value explicitly
211
215
  value = prop.customType ? prop.customType.convertToDatabaseValue(insertId, this.platform, { mode: 'serialization' }) : value;
212
216
  changeSet.payload[wrapped.__meta.primaryKeys[0]] = value;
213
- wrapped.__identifier?.setValue(value);
217
+ if (wrapped.__identifier && !Array.isArray(wrapped.__identifier)) {
218
+ wrapped.__identifier.setValue(value);
219
+ }
214
220
  }
215
221
  /**
216
222
  * Sets populate flag to new entities so they are serialized like if they were loaded from the db
@@ -233,7 +239,7 @@ export class ChangeSetPersister {
233
239
  }
234
240
  async updateEntity(meta, changeSet, options) {
235
241
  const cond = changeSet.getPrimaryKey(true);
236
- options = this.propagateSchemaFromMetadata(meta, options, {
242
+ options = this.prepareOptions(meta, options, {
237
243
  convertCustomTypes: false,
238
244
  });
239
245
  if (meta.concurrencyCheckKeys.size === 0 && (!meta.versionProperty || changeSet.entity[meta.versionProperty] == null)) {
@@ -260,7 +266,7 @@ export class ChangeSetPersister {
260
266
  return cond;
261
267
  });
262
268
  const primaryKeys = meta.primaryKeys.concat(...meta.concurrencyCheckKeys);
263
- options = this.propagateSchemaFromMetadata(meta, options, {
269
+ options = this.prepareOptions(meta, options, {
264
270
  fields: primaryKeys,
265
271
  });
266
272
  const res = await this.driver.find(meta.root.className, { $or }, options);
@@ -319,12 +325,12 @@ export class ChangeSetPersister {
319
325
  }
320
326
  return val;
321
327
  });
322
- options = this.propagateSchemaFromMetadata(meta, options, {
328
+ options = this.prepareOptions(meta, options, {
323
329
  fields: Utils.unique(reloadProps.map(prop => prop.name)),
324
330
  });
325
331
  const data = await this.driver.find(meta.className, { [pk]: { $in: pks } }, options);
326
332
  const map = new Map();
327
- data.forEach(item => map.set(Utils.getCompositeKeyHash(item, meta, true, this.platform, true), item));
333
+ data.forEach(item => map.set(Utils.getCompositeKeyHash(item, meta, false, this.platform, true), item));
328
334
  for (const changeSet of changeSets) {
329
335
  const data = map.get(helper(changeSet.entity).getSerializedPrimaryKey());
330
336
  this.hydrator.hydrate(changeSet.entity, meta, data, this.factory, 'full', false, true);
@@ -338,6 +344,10 @@ export class ChangeSetPersister {
338
344
  changeSet.payload[prop.name] = value.getValue();
339
345
  return;
340
346
  }
347
+ if (Array.isArray(value) && value.every(item => item instanceof EntityIdentifier)) {
348
+ changeSet.payload[prop.name] = value.map(item => item.getValue());
349
+ return;
350
+ }
341
351
  if (prop.kind === ReferenceKind.MANY_TO_MANY && Array.isArray(value)) {
342
352
  changeSet.payload[prop.name] = value.map(val => val instanceof EntityIdentifier ? val.getValue() : val);
343
353
  return;
@@ -39,7 +39,7 @@ export declare class UnitOfWork {
39
39
  /**
40
40
  * Returns entity from the identity map. For composite keys, you need to pass an array of PKs in the same order as they are defined in `meta.primaryKeys`.
41
41
  */
42
- getById<T extends object>(entityName: string, id: Primary<T> | Primary<T>[], schema?: string): T | undefined;
42
+ getById<T extends object>(entityName: string, id: Primary<T> | Primary<T>[], schema?: string, convertCustomTypes?: boolean): T | undefined;
43
43
  tryGetById<T extends object>(entityName: string, where: FilterQuery<T>, schema?: string, strict?: boolean): T | null;
44
44
  /**
45
45
  * Returns map of all managed entities.
@@ -103,6 +103,7 @@ export declare class UnitOfWork {
103
103
  private commitDeleteChangeSets;
104
104
  private commitExtraUpdates;
105
105
  private commitCollectionUpdates;
106
+ private filterCollectionUpdates;
106
107
  /**
107
108
  * Orders change sets so FK constrains are maintained, ensures stable order (needed for node < 11)
108
109
  */
@@ -43,7 +43,7 @@ export class UnitOfWork {
43
43
  this.eventManager = this.em.getEventManager();
44
44
  this.comparator = this.em.getComparator();
45
45
  this.changeSetComputer = new ChangeSetComputer(this.em.getValidator(), this.collectionUpdates, this.metadata, this.platform, this.em.config, this.em);
46
- this.changeSetPersister = new ChangeSetPersister(this.em.getDriver(), this.metadata, this.em.config.getHydrator(this.metadata), this.em.getEntityFactory(), this.em.getValidator(), this.em.config);
46
+ this.changeSetPersister = new ChangeSetPersister(this.em.getDriver(), this.metadata, this.em.config.getHydrator(this.metadata), this.em.getEntityFactory(), this.em.getValidator(), this.em.config, this.em);
47
47
  }
48
48
  merge(entity, visited) {
49
49
  const wrapped = helper(entity);
@@ -89,7 +89,7 @@ export class UnitOfWork {
89
89
  }
90
90
  wrapped.__loadedProperties.add(key);
91
91
  if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(data[prop.name])) {
92
- data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta.primaryKeys, true);
92
+ data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
93
93
  }
94
94
  else if (prop.kind === ReferenceKind.EMBEDDED && !prop.object && Utils.isPlainObject(data[prop.name])) {
95
95
  for (const p of prop.targetMeta.props) {
@@ -97,7 +97,7 @@ export class UnitOfWork {
97
97
  const prefix = prop.prefix === false ? '' : prop.prefix === true ? prop.name + '_' : prop.prefix;
98
98
  data[prefix + p.name] = data[prop.name][p.name];
99
99
  }
100
- data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta.primaryKeys, true);
100
+ data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
101
101
  }
102
102
  if (forceUndefined) {
103
103
  if (data[key] === null) {
@@ -125,7 +125,7 @@ export class UnitOfWork {
125
125
  /**
126
126
  * Returns entity from the identity map. For composite keys, you need to pass an array of PKs in the same order as they are defined in `meta.primaryKeys`.
127
127
  */
128
- getById(entityName, id, schema) {
128
+ getById(entityName, id, schema, convertCustomTypes) {
129
129
  if (id == null || (Array.isArray(id) && id.length === 0)) {
130
130
  return undefined;
131
131
  }
@@ -135,7 +135,16 @@ export class UnitOfWork {
135
135
  hash = '' + id;
136
136
  }
137
137
  else {
138
- const keys = Array.isArray(id) ? Utils.flatten(id) : [id];
138
+ let keys = Array.isArray(id) ? Utils.flatten(id) : [id];
139
+ keys = meta.getPrimaryProps(true).map((p, i) => {
140
+ if (!convertCustomTypes && p.customType) {
141
+ return p.customType.convertToDatabaseValue(keys[i], this.platform, {
142
+ key: p.name,
143
+ mode: 'hydration',
144
+ });
145
+ }
146
+ return keys[i];
147
+ });
139
148
  hash = Utils.getPrimaryKeyHash(keys);
140
149
  }
141
150
  schema ??= meta.schema ?? this.em.config.getSchema();
@@ -303,6 +312,7 @@ export class UnitOfWork {
303
312
  cs.entity.__helper.__processing = true;
304
313
  }
305
314
  await this.eventManager.dispatchEvent(EventType.onFlush, { em: this.em, uow: this });
315
+ this.filterCollectionUpdates();
306
316
  // nothing to do, do not start transaction
307
317
  if (this.changeSets.size === 0 && this.collectionUpdates.size === 0 && this.extraUpdates.size === 0) {
308
318
  return void (await this.eventManager.dispatchEvent(EventType.afterFlush, { em: this.em, uow: this }));
@@ -311,9 +321,11 @@ export class UnitOfWork {
311
321
  const platform = this.em.getPlatform();
312
322
  const runInTransaction = !this.em.isInTransaction() && platform.supportsTransactions() && this.em.config.get('implicitTransactions');
313
323
  if (runInTransaction) {
324
+ const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
314
325
  await this.em.getConnection('write').transactional(trx => this.persistToDatabase(groups, trx), {
315
326
  ctx: oldTx,
316
327
  eventBroadcaster: new TransactionEventBroadcaster(this.em),
328
+ loggerContext,
317
329
  });
318
330
  }
319
331
  else {
@@ -542,13 +554,22 @@ export class UnitOfWork {
542
554
  if (!wrapped || wrapped.__identifier || wrapped.hasPrimaryKey()) {
543
555
  return;
544
556
  }
545
- const pk = wrapped.__meta.getPrimaryProps()[0];
546
- if (pk.kind === ReferenceKind.SCALAR) {
547
- wrapped.__identifier = new EntityIdentifier();
557
+ const pks = wrapped.__meta.getPrimaryProps();
558
+ const idents = [];
559
+ for (const pk of pks) {
560
+ if (pk.kind === ReferenceKind.SCALAR) {
561
+ idents.push(new EntityIdentifier(entity[pk.name]));
562
+ }
563
+ else if (entity[pk.name]) {
564
+ this.initIdentifier(entity[pk.name]);
565
+ idents.push(helper(entity[pk.name])?.__identifier);
566
+ }
548
567
  }
549
- else if (entity[pk.name]) {
550
- this.initIdentifier(entity[pk.name]);
551
- wrapped.__identifier = helper(entity[pk.name])?.__identifier;
568
+ if (pks.length === 1) {
569
+ wrapped.__identifier = idents[0];
570
+ }
571
+ else {
572
+ wrapped.__identifier = idents;
552
573
  }
553
574
  }
554
575
  processReference(parent, prop, kind, visited, processed, idx) {
@@ -600,8 +621,15 @@ export class UnitOfWork {
600
621
  const diff = this.comparator.diffEntities(changeSet.name, copy, current);
601
622
  Object.assign(changeSet.payload, diff);
602
623
  const wrapped = helper(changeSet.entity);
603
- if (wrapped.__identifier && diff[wrapped.__meta.primaryKeys[0]]) {
604
- wrapped.__identifier.setValue(diff[wrapped.__meta.primaryKeys[0]]);
624
+ if (wrapped.__identifier) {
625
+ const idents = Utils.asArray(wrapped.__identifier);
626
+ let i = 0;
627
+ for (const pk of wrapped.__meta.primaryKeys) {
628
+ if (diff[pk]) {
629
+ idents[i].setValue(diff[pk]);
630
+ }
631
+ i++;
632
+ }
605
633
  }
606
634
  }
607
635
  postCommitCleanup() {
@@ -825,9 +853,17 @@ export class UnitOfWork {
825
853
  }
826
854
  await this.changeSetPersister.executeUpdates(changeSets, batched, { ctx });
827
855
  for (const changeSet of changeSets) {
828
- helper(changeSet.entity).__originalEntityData = this.comparator.prepareEntity(changeSet.entity);
829
- helper(changeSet.entity).__touched = false;
830
- helper(changeSet.entity).__initialized = true;
856
+ const wrapped = helper(changeSet.entity);
857
+ wrapped.__originalEntityData = this.comparator.prepareEntity(changeSet.entity);
858
+ wrapped.__touched = false;
859
+ if (!wrapped.__initialized) {
860
+ for (const prop of changeSet.meta.relations) {
861
+ if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) && changeSet.entity[prop.name] == null) {
862
+ changeSet.entity[prop.name] = Collection.create(changeSet.entity, prop.name, undefined, wrapped.isInitialized());
863
+ }
864
+ }
865
+ wrapped.__initialized = true;
866
+ }
831
867
  await this.runHooks(EventType.afterUpdate, changeSet);
832
868
  }
833
869
  }
@@ -870,23 +906,34 @@ export class UnitOfWork {
870
906
  }
871
907
  }
872
908
  async commitCollectionUpdates(ctx) {
873
- const collectionUpdates = [];
909
+ this.filterCollectionUpdates();
910
+ const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
911
+ await this.em.getDriver().syncCollections(this.collectionUpdates, {
912
+ ctx,
913
+ schema: this.em.schema,
914
+ loggerContext,
915
+ });
874
916
  for (const coll of this.collectionUpdates) {
917
+ coll.takeSnapshot();
918
+ }
919
+ }
920
+ filterCollectionUpdates() {
921
+ for (const coll of this.collectionUpdates) {
922
+ let skip = true;
875
923
  if (coll.property.owner || coll.getItems(false).filter(item => !item.__helper.__initialized).length > 0) {
876
924
  if (this.platform.usesPivotTable()) {
877
- collectionUpdates.push(coll);
925
+ skip = false;
878
926
  }
879
927
  }
880
928
  else if (coll.property.kind === ReferenceKind.ONE_TO_MANY && coll.getSnapshot() === undefined) {
881
- collectionUpdates.push(coll);
929
+ skip = false;
882
930
  }
883
931
  else if (coll.property.kind === ReferenceKind.MANY_TO_MANY && !coll.property.owner) {
884
- collectionUpdates.push(coll);
932
+ skip = false;
933
+ }
934
+ if (skip) {
935
+ this.collectionUpdates.delete(coll);
885
936
  }
886
- }
887
- await this.em.getDriver().syncCollections(collectionUpdates, { ctx });
888
- for (const coll of this.collectionUpdates) {
889
- coll.takeSnapshot();
890
937
  }
891
938
  }
892
939
  /**
@@ -32,7 +32,7 @@ export class AbstractSchemaGenerator {
32
32
  }
33
33
  else {
34
34
  await this.ensureDatabase();
35
- await this.dropSchema();
35
+ await this.dropSchema(options);
36
36
  }
37
37
  if (options?.createSchema !== false) {
38
38
  await this.createSchema(options);
@@ -103,7 +103,10 @@ export class AbstractSchemaGenerator {
103
103
  }
104
104
  return calc.sort()
105
105
  .map(cls => this.metadata.find(cls))
106
- .filter(meta => schema ? [schema, '*'].includes(meta.schema) : meta.schema !== '*');
106
+ .filter(meta => {
107
+ const targetSchema = meta.schema ?? this.config.get('schema', this.platform.getDefaultSchemaName());
108
+ return schema ? [schema, '*'].includes(targetSchema) : meta.schema !== '*';
109
+ });
107
110
  }
108
111
  notImplemented() {
109
112
  throw new Error(`This method is not supported by ${this.driver.constructor.name} driver`);
@@ -54,7 +54,7 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
54
54
  baseDir: string;
55
55
  hydrator: typeof ObjectHydrator;
56
56
  flushMode: FlushMode.AUTO;
57
- loadStrategy: LoadStrategy.JOINED;
57
+ loadStrategy: LoadStrategy.BALANCED;
58
58
  dataloader: DataloaderType.NONE;
59
59
  populateWhere: PopulateHint.ALL;
60
60
  connect: true;
@@ -78,9 +78,11 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
78
78
  upsertManaged: true;
79
79
  forceEntityConstructor: false;
80
80
  forceUndefined: false;
81
+ processOnCreateHooksEarly: false;
81
82
  ensureDatabase: true;
82
83
  ensureIndexes: false;
83
84
  batchSize: number;
85
+ hashAlgorithm: "md5";
84
86
  debug: false;
85
87
  ignoreDeprecations: false;
86
88
  verbose: false;
@@ -103,9 +105,11 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
103
105
  disableForeignKeys: false;
104
106
  createForeignKeyConstraints: true;
105
107
  ignoreSchema: never[];
108
+ skipTables: never[];
109
+ skipColumns: {};
106
110
  };
107
111
  embeddables: {
108
- prefixMode: "absolute";
112
+ prefixMode: "relative";
109
113
  };
110
114
  entityGenerator: {
111
115
  forceUndefined: true;
@@ -142,7 +146,6 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
142
146
  fileName: (className: string) => string;
143
147
  };
144
148
  preferReadReplicas: true;
145
- dynamicImportProvider: (id: string) => Promise<any>;
146
149
  };
147
150
  private readonly options;
148
151
  private readonly logger;
@@ -332,6 +335,11 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
332
335
  upsertManaged: boolean;
333
336
  forceEntityConstructor: boolean | (Constructor<AnyEntity> | string)[];
334
337
  forceUndefined: boolean;
338
+ /**
339
+ * Property `onCreate` hooks are normally executed during `flush` operation.
340
+ * With this option, they will be processed early inside `em.create()` method.
341
+ */
342
+ processOnCreateHooksEarly: boolean;
335
343
  forceUtcTimezone?: boolean;
336
344
  timezone?: string;
337
345
  ensureDatabase: boolean | EnsureDatabaseOptions;
@@ -340,7 +348,7 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
340
348
  useBatchUpdates?: boolean;
341
349
  batchSize: number;
342
350
  hydrator: HydratorConstructor;
343
- loadStrategy: LoadStrategy | 'select-in' | 'joined';
351
+ loadStrategy: LoadStrategy | `${LoadStrategy}`;
344
352
  dataloader: DataloaderType | boolean;
345
353
  populateWhere?: PopulateHint | `${PopulateHint}`;
346
354
  flushMode: FlushMode | 'commit' | 'auto' | 'always';
@@ -374,6 +382,8 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
374
382
  disableForeignKeys?: boolean;
375
383
  createForeignKeyConstraints?: boolean;
376
384
  ignoreSchema?: string[];
385
+ skipTables?: (string | RegExp)[];
386
+ skipColumns?: Dictionary<(string | RegExp)[]>;
377
387
  managementDbName?: string;
378
388
  };
379
389
  embeddables: {
@@ -402,6 +412,6 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
402
412
  };
403
413
  seeder: SeederOptions;
404
414
  preferReadReplicas: boolean;
405
- dynamicImportProvider: (id: string) => Promise<unknown>;
415
+ hashAlgorithm: 'md5' | 'sha256';
406
416
  }
407
417
  export type Options<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager = D[typeof EntityManagerType] & EntityManager> = Pick<MikroORMOptions<D, EM>, Exclude<keyof MikroORMOptions<D, EM>, keyof typeof Configuration.DEFAULTS>> & Partial<MikroORMOptions<D, EM>>;
@@ -44,7 +44,7 @@ export class Configuration {
44
44
  baseDir: process.cwd(),
45
45
  hydrator: ObjectHydrator,
46
46
  flushMode: FlushMode.AUTO,
47
- loadStrategy: LoadStrategy.JOINED,
47
+ loadStrategy: LoadStrategy.BALANCED,
48
48
  dataloader: DataloaderType.NONE,
49
49
  populateWhere: PopulateHint.ALL,
50
50
  connect: true,
@@ -68,9 +68,11 @@ export class Configuration {
68
68
  upsertManaged: true,
69
69
  forceEntityConstructor: false,
70
70
  forceUndefined: false,
71
+ processOnCreateHooksEarly: false,
71
72
  ensureDatabase: true,
72
73
  ensureIndexes: false,
73
74
  batchSize: 300,
75
+ hashAlgorithm: 'md5',
74
76
  debug: false,
75
77
  ignoreDeprecations: false,
76
78
  verbose: false,
@@ -93,9 +95,11 @@ export class Configuration {
93
95
  disableForeignKeys: false,
94
96
  createForeignKeyConstraints: true,
95
97
  ignoreSchema: [],
98
+ skipTables: [],
99
+ skipColumns: {},
96
100
  },
97
101
  embeddables: {
98
- prefixMode: 'absolute',
102
+ prefixMode: 'relative',
99
103
  },
100
104
  entityGenerator: {
101
105
  forceUndefined: true,
@@ -130,7 +134,6 @@ export class Configuration {
130
134
  fileName: (className) => className,
131
135
  },
132
136
  preferReadReplicas: true,
133
- dynamicImportProvider: /* v8 ignore next */ (id) => import(id),
134
137
  };
135
138
  options;
136
139
  logger;
@@ -139,9 +142,6 @@ export class Configuration {
139
142
  cache = new Map();
140
143
  extensions = new Map();
141
144
  constructor(options, validate = true) {
142
- if (options.dynamicImportProvider) {
143
- Utils.setDynamicImportProvider(options.dynamicImportProvider);
144
- }
145
145
  this.options = Utils.mergeConfig({}, Configuration.DEFAULTS, options);
146
146
  this.options.baseDir = Utils.absolutePath(this.options.baseDir);
147
147
  this.options.preferTs ??= options.preferTs;
@@ -268,7 +268,7 @@ export class Configuration {
268
268
  * Gets instance of metadata CacheAdapter. (cached)
269
269
  */
270
270
  getMetadataCacheAdapter() {
271
- return this.getCachedService(this.options.metadataCache.adapter, this.options.metadataCache.options, this.options.baseDir, this.options.metadataCache.pretty);
271
+ return this.getCachedService(this.options.metadataCache.adapter, this.options.metadataCache.options, this.options.baseDir, this.options.metadataCache.pretty, this.options.hashAlgorithm);
272
272
  }
273
273
  /**
274
274
  * Gets instance of CacheAdapter for result cache. (cached)
@@ -40,8 +40,6 @@ export declare class ConfigurationLoader {
40
40
  static loadEnvironmentVars<D extends IDatabaseDriver>(): Promise<Partial<Options<D>>>;
41
41
  static loadEnvironmentVarsSync<D extends IDatabaseDriver>(): Partial<Options<D>>;
42
42
  static getORMPackages(): Set<string>;
43
- /** @internal */
44
- static commonJSCompat(options: Partial<Options>): void;
45
43
  static getORMPackageVersion(name: string): string | undefined;
46
44
  static checkPackageVersion(): string;
47
45
  }
@@ -1,7 +1,5 @@
1
1
  import dotenv from 'dotenv';
2
2
  import { realpathSync } from 'node:fs';
3
- import { platform } from 'node:os';
4
- import { fileURLToPath } from 'node:url';
5
3
  import { colors } from '../logging/colors.js';
6
4
  import { Configuration } from './Configuration.js';
7
5
  import { Utils } from './Utils.js';
@@ -12,7 +10,6 @@ export class ConfigurationLoader {
12
10
  static async getConfiguration(contextName = 'default', paths = ConfigurationLoader.getConfigPaths(), options = {}) {
13
11
  // Backwards compatibility layer
14
12
  if (typeof contextName === 'boolean' || !Array.isArray(paths)) {
15
- this.commonJSCompat(options);
16
13
  this.registerDotenv(options);
17
14
  const configPathFromArg = ConfigurationLoader.configPathsFromArg();
18
15
  const configPaths = configPathFromArg ?? (Array.isArray(paths) ? paths : ConfigurationLoader.getConfigPaths());
@@ -192,7 +189,7 @@ export class ConfigurationLoader {
192
189
  static registerDotenv(options) {
193
190
  const path = process.env.MIKRO_ORM_ENV ?? ((options?.baseDir ?? process.cwd()) + '/.env');
194
191
  const env = {};
195
- dotenv.config({ path, processEnv: env });
192
+ dotenv.config({ path, processEnv: env, quiet: true });
196
193
  // only propagate known env vars
197
194
  for (const key of Object.keys(env)) {
198
195
  if (key.startsWith('MIKRO_ORM_')) {
@@ -300,25 +297,6 @@ export class ConfigurationLoader {
300
297
  ...Object.keys(pkg.devDependencies ?? {}),
301
298
  ]);
302
299
  }
303
- /** @internal */
304
- static commonJSCompat(options) {
305
- if (this.isESM()) {
306
- return;
307
- }
308
- /* v8 ignore next 11 */
309
- options.dynamicImportProvider ??= id => {
310
- if (platform() === 'win32') {
311
- try {
312
- id = fileURLToPath(id);
313
- }
314
- catch {
315
- // ignore
316
- }
317
- }
318
- return Utils.requireFrom(id);
319
- };
320
- Utils.setDynamicImportProvider(options.dynamicImportProvider);
321
- }
322
300
  static getORMPackageVersion(name) {
323
301
  try {
324
302
  const pkg = Utils.requireFrom(`${name}/package.json`);
@@ -332,7 +310,7 @@ export class ConfigurationLoader {
332
310
  // inspired by https://github.com/facebook/docusaurus/pull/3386
333
311
  static checkPackageVersion() {
334
312
  const coreVersion = Utils.getORMVersion();
335
- if (process.env.MIKRO_ORM_ALLOW_VERSION_MISMATCH) {
313
+ if (process.env.MIKRO_ORM_ALLOW_VERSION_MISMATCH || coreVersion === 'N/A') {
336
314
  return coreVersion;
337
315
  }
338
316
  const deps = this.getORMPackages();
package/utils/Cursor.d.ts CHANGED
@@ -49,13 +49,13 @@ import { type QueryOrder } from '../enums.js';
49
49
  * }
50
50
  * ```
51
51
  */
52
- export declare class Cursor<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never> {
52
+ export declare class Cursor<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never, IncludeCount extends boolean = true> {
53
53
  readonly items: Loaded<Entity, Hint, Fields, Excludes>[];
54
- readonly totalCount: number;
54
+ readonly totalCount: IncludeCount extends true ? number : undefined;
55
55
  readonly hasPrevPage: boolean;
56
56
  readonly hasNextPage: boolean;
57
57
  private readonly definition;
58
- constructor(items: Loaded<Entity, Hint, Fields, Excludes>[], totalCount: number, options: FindByCursorOptions<Entity, Hint, Fields, Excludes>, meta: EntityMetadata<Entity>);
58
+ constructor(items: Loaded<Entity, Hint, Fields, Excludes>[], totalCount: IncludeCount extends true ? number : undefined, options: FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>, meta: EntityMetadata<Entity>);
59
59
  get startCursor(): string | null;
60
60
  get endCursor(): string | null;
61
61
  /**
package/utils/Cursor.js CHANGED
@@ -107,6 +107,9 @@ export class Cursor {
107
107
  if (Utils.isEntity(value, true)) {
108
108
  value = helper(value).getPrimaryKey();
109
109
  }
110
+ if (Utils.isScalarReference(value)) {
111
+ value = value.unwrap();
112
+ }
110
113
  if (object) {
111
114
  return ({ [prop]: value });
112
115
  }
@@ -1,7 +1,7 @@
1
+ import type DataLoader from 'dataloader';
1
2
  import type { Primary, Ref } from '../typings.js';
2
3
  import { Collection, type InitCollectionOptions } from '../entity/Collection.js';
3
4
  import { type EntityManager } from '../EntityManager.js';
4
- import type DataLoader from 'dataloader';
5
5
  import { type LoadReferenceOptions } from '../entity/Reference.js';
6
6
  export declare class DataloaderUtils {
7
7
  /**
@@ -34,8 +34,13 @@ export declare class DataloaderUtils {
34
34
  */
35
35
  static getColFilter<T, S extends T>(collection: Collection<any>): (result: T) => result is S;
36
36
  /**
37
- * Returns the collection dataloader batchLoadFn, which aggregates collections by entity,
37
+ * Returns the 1:M collection dataloader batchLoadFn, which aggregates collections by entity,
38
38
  * makes one query per entity and maps each input collection to the corresponding result.
39
39
  */
40
40
  static getColBatchLoadFn(em: EntityManager): DataLoader.BatchLoadFn<[Collection<any>, Omit<InitCollectionOptions<any, any>, 'dataloader'>?], any>;
41
+ /**
42
+ * Returns the M:N collection dataloader batchLoadFn, which aggregates collections by entity,
43
+ * makes one query per entity and maps each input collection to the corresponding result.
44
+ */
45
+ static getManyToManyColBatchLoadFn(em: EntityManager): DataLoader.BatchLoadFn<[Collection<any>, Omit<InitCollectionOptions<any, any>, 'dataloader'>?], any>;
41
46
  }