@mikro-orm/core 7.0.0-dev.5 → 7.0.0-dev.50

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 (115) hide show
  1. package/EntityManager.d.ts +81 -27
  2. package/EntityManager.js +287 -175
  3. package/MikroORM.d.ts +6 -6
  4. package/MikroORM.js +31 -74
  5. package/README.md +3 -2
  6. package/cache/FileCacheAdapter.d.ts +2 -1
  7. package/cache/FileCacheAdapter.js +6 -4
  8. package/connections/Connection.d.ts +9 -5
  9. package/connections/Connection.js +16 -13
  10. package/decorators/Embedded.d.ts +5 -11
  11. package/decorators/Entity.d.ts +18 -3
  12. package/decorators/Indexed.d.ts +2 -2
  13. package/decorators/ManyToMany.d.ts +2 -0
  14. package/decorators/ManyToOne.d.ts +4 -0
  15. package/decorators/OneToOne.d.ts +4 -0
  16. package/decorators/Property.d.ts +53 -9
  17. package/decorators/Transactional.d.ts +1 -0
  18. package/decorators/Transactional.js +3 -3
  19. package/decorators/index.d.ts +1 -1
  20. package/drivers/DatabaseDriver.d.ts +10 -5
  21. package/drivers/DatabaseDriver.js +4 -4
  22. package/drivers/IDatabaseDriver.d.ts +28 -4
  23. package/entity/ArrayCollection.d.ts +6 -4
  24. package/entity/ArrayCollection.js +26 -9
  25. package/entity/BaseEntity.d.ts +0 -1
  26. package/entity/BaseEntity.js +0 -3
  27. package/entity/Collection.d.ts +3 -4
  28. package/entity/Collection.js +37 -17
  29. package/entity/EntityAssigner.d.ts +1 -1
  30. package/entity/EntityAssigner.js +9 -1
  31. package/entity/EntityFactory.d.ts +7 -0
  32. package/entity/EntityFactory.js +29 -11
  33. package/entity/EntityHelper.js +25 -8
  34. package/entity/EntityLoader.d.ts +5 -4
  35. package/entity/EntityLoader.js +69 -36
  36. package/entity/EntityRepository.d.ts +1 -1
  37. package/entity/EntityValidator.js +1 -1
  38. package/entity/Reference.d.ts +9 -7
  39. package/entity/Reference.js +30 -3
  40. package/entity/WrappedEntity.d.ts +0 -2
  41. package/entity/WrappedEntity.js +1 -5
  42. package/entity/defineEntity.d.ts +555 -0
  43. package/entity/defineEntity.js +529 -0
  44. package/entity/index.d.ts +2 -0
  45. package/entity/index.js +2 -0
  46. package/entity/utils.d.ts +7 -0
  47. package/entity/utils.js +15 -3
  48. package/enums.d.ts +16 -3
  49. package/enums.js +13 -0
  50. package/errors.d.ts +6 -1
  51. package/errors.js +14 -4
  52. package/events/EventSubscriber.d.ts +3 -1
  53. package/hydration/ObjectHydrator.d.ts +4 -4
  54. package/hydration/ObjectHydrator.js +35 -24
  55. package/index.d.ts +2 -1
  56. package/index.js +1 -1
  57. package/logging/DefaultLogger.d.ts +1 -1
  58. package/logging/SimpleLogger.d.ts +1 -1
  59. package/metadata/EntitySchema.d.ts +8 -4
  60. package/metadata/EntitySchema.js +39 -19
  61. package/metadata/MetadataDiscovery.d.ts +4 -4
  62. package/metadata/MetadataDiscovery.js +139 -122
  63. package/metadata/MetadataStorage.js +1 -1
  64. package/metadata/MetadataValidator.js +4 -3
  65. package/naming-strategy/AbstractNamingStrategy.d.ts +5 -1
  66. package/naming-strategy/AbstractNamingStrategy.js +7 -1
  67. package/naming-strategy/NamingStrategy.d.ts +11 -1
  68. package/package.json +5 -5
  69. package/platforms/Platform.d.ts +5 -3
  70. package/platforms/Platform.js +4 -8
  71. package/serialization/EntitySerializer.d.ts +2 -0
  72. package/serialization/EntitySerializer.js +23 -5
  73. package/serialization/EntityTransformer.js +16 -6
  74. package/serialization/SerializationContext.js +14 -11
  75. package/types/BigIntType.d.ts +9 -6
  76. package/types/BigIntType.js +3 -0
  77. package/types/BooleanType.d.ts +1 -1
  78. package/types/DecimalType.d.ts +6 -4
  79. package/types/DecimalType.js +1 -1
  80. package/types/DoubleType.js +1 -1
  81. package/types/JsonType.d.ts +1 -1
  82. package/types/JsonType.js +7 -2
  83. package/types/Type.d.ts +2 -1
  84. package/types/Type.js +1 -1
  85. package/types/index.d.ts +1 -1
  86. package/typings.d.ts +89 -49
  87. package/typings.js +31 -31
  88. package/unit-of-work/ChangeSetComputer.js +8 -3
  89. package/unit-of-work/ChangeSetPersister.d.ts +4 -2
  90. package/unit-of-work/ChangeSetPersister.js +37 -16
  91. package/unit-of-work/UnitOfWork.d.ts +8 -1
  92. package/unit-of-work/UnitOfWork.js +110 -53
  93. package/utils/AbstractSchemaGenerator.js +3 -1
  94. package/utils/Configuration.d.ts +29 -16
  95. package/utils/Configuration.js +17 -18
  96. package/utils/ConfigurationLoader.d.ts +9 -22
  97. package/utils/ConfigurationLoader.js +49 -72
  98. package/utils/Cursor.d.ts +3 -3
  99. package/utils/Cursor.js +3 -0
  100. package/utils/DataloaderUtils.d.ts +7 -2
  101. package/utils/DataloaderUtils.js +38 -7
  102. package/utils/EntityComparator.d.ts +6 -2
  103. package/utils/EntityComparator.js +104 -58
  104. package/utils/QueryHelper.d.ts +9 -1
  105. package/utils/QueryHelper.js +66 -5
  106. package/utils/RawQueryFragment.d.ts +36 -4
  107. package/utils/RawQueryFragment.js +34 -13
  108. package/utils/TransactionManager.d.ts +65 -0
  109. package/utils/TransactionManager.js +223 -0
  110. package/utils/Utils.d.ts +13 -11
  111. package/utils/Utils.js +82 -55
  112. package/utils/index.d.ts +1 -0
  113. package/utils/index.js +1 -0
  114. package/utils/upsert-utils.d.ts +7 -2
  115. package/utils/upsert-utils.js +52 -1
@@ -28,6 +28,12 @@ export declare class UnitOfWork {
28
28
  private working;
29
29
  constructor(em: EntityManager);
30
30
  merge<T extends object>(entity: T, visited?: Set<AnyEntity>): void;
31
+ /**
32
+ * Entity data can wary in its shape, e.g. we might get a deep relation graph with joined strategy, but for diffing,
33
+ * we need to normalize the shape, so relation values are only raw FKs. This method handles that.
34
+ * @internal
35
+ */
36
+ normalizeEntityData<T extends object>(meta: EntityMetadata<T>, data: EntityData<T>): void;
31
37
  /**
32
38
  * @internal
33
39
  */
@@ -39,7 +45,7 @@ export declare class UnitOfWork {
39
45
  /**
40
46
  * 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
47
  */
42
- getById<T extends object>(entityName: string, id: Primary<T> | Primary<T>[], schema?: string): T | undefined;
48
+ getById<T extends object>(entityName: string, id: Primary<T> | Primary<T>[], schema?: string, convertCustomTypes?: boolean): T | undefined;
43
49
  tryGetById<T extends object>(entityName: string, where: FilterQuery<T>, schema?: string, strict?: boolean): T | null;
44
50
  /**
45
51
  * Returns map of all managed entities.
@@ -103,6 +109,7 @@ export declare class UnitOfWork {
103
109
  private commitDeleteChangeSets;
104
110
  private commitExtraUpdates;
105
111
  private commitCollectionUpdates;
112
+ private filterCollectionUpdates;
106
113
  /**
107
114
  * Orders change sets so FK constrains are maintained, ensures stable order (needed for node < 11)
108
115
  */
@@ -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);
@@ -61,10 +61,43 @@ export class UnitOfWork {
61
61
  // as there can be some entity with already changed state that is not yet flushed
62
62
  if (wrapped.__initialized && (!visited || !wrapped.__originalEntityData)) {
63
63
  wrapped.__originalEntityData = this.comparator.prepareEntity(entity);
64
- wrapped.__touched = false;
65
64
  }
66
65
  this.cascade(entity, Cascade.MERGE, visited ?? new Set());
67
66
  }
67
+ /**
68
+ * Entity data can wary in its shape, e.g. we might get a deep relation graph with joined strategy, but for diffing,
69
+ * we need to normalize the shape, so relation values are only raw FKs. This method handles that.
70
+ * @internal
71
+ */
72
+ normalizeEntityData(meta, data) {
73
+ const forceUndefined = this.em.config.get('forceUndefined');
74
+ for (const key of Utils.keys(data)) {
75
+ const prop = meta.properties[key];
76
+ if (!prop) {
77
+ continue;
78
+ }
79
+ if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(data[prop.name])) {
80
+ data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
81
+ }
82
+ else if (prop.kind === ReferenceKind.EMBEDDED && !prop.object && Utils.isPlainObject(data[prop.name])) {
83
+ for (const p of prop.targetMeta.props) {
84
+ /* v8 ignore next */
85
+ const prefix = prop.prefix === false ? '' : prop.prefix === true ? prop.name + '_' : prop.prefix;
86
+ data[prefix + p.name] = data[prop.name][p.name];
87
+ }
88
+ data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
89
+ }
90
+ if (prop.hydrate === false && prop.customType?.ensureComparable(meta, prop)) {
91
+ const converted = prop.customType.convertToJSValue(data[key], this.platform, { key, mode: 'hydration', force: true });
92
+ data[key] = prop.customType.convertToDatabaseValue(converted, this.platform, { key, mode: 'hydration' });
93
+ }
94
+ if (forceUndefined) {
95
+ if (data[key] === null) {
96
+ data[key] = undefined;
97
+ }
98
+ }
99
+ }
100
+ }
68
101
  /**
69
102
  * @internal
70
103
  */
@@ -82,31 +115,14 @@ export class UnitOfWork {
82
115
  wrapped.__em ??= this.em;
83
116
  wrapped.__managed = true;
84
117
  if (data && (options?.refresh || !wrapped.__originalEntityData)) {
118
+ this.normalizeEntityData(wrapped.__meta, data);
85
119
  for (const key of Utils.keys(data)) {
86
120
  const prop = wrapped.__meta.properties[key];
87
- if (!prop) {
88
- continue;
89
- }
90
- wrapped.__loadedProperties.add(key);
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);
93
- }
94
- else if (prop.kind === ReferenceKind.EMBEDDED && !prop.object && Utils.isPlainObject(data[prop.name])) {
95
- for (const p of prop.targetMeta.props) {
96
- /* v8 ignore next */
97
- const prefix = prop.prefix === false ? '' : prop.prefix === true ? prop.name + '_' : prop.prefix;
98
- data[prefix + p.name] = data[prop.name][p.name];
99
- }
100
- data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta.primaryKeys, true);
101
- }
102
- if (forceUndefined) {
103
- if (data[key] === null) {
104
- data[key] = undefined;
105
- }
121
+ if (prop) {
122
+ wrapped.__loadedProperties.add(key);
106
123
  }
107
124
  }
108
125
  wrapped.__originalEntityData = data;
109
- wrapped.__touched = false;
110
126
  }
111
127
  return entity;
112
128
  }
@@ -125,7 +141,7 @@ export class UnitOfWork {
125
141
  /**
126
142
  * 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
143
  */
128
- getById(entityName, id, schema) {
144
+ getById(entityName, id, schema, convertCustomTypes) {
129
145
  if (id == null || (Array.isArray(id) && id.length === 0)) {
130
146
  return undefined;
131
147
  }
@@ -135,7 +151,16 @@ export class UnitOfWork {
135
151
  hash = '' + id;
136
152
  }
137
153
  else {
138
- const keys = Array.isArray(id) ? Utils.flatten(id) : [id];
154
+ let keys = Array.isArray(id) ? Utils.flatten(id) : [id];
155
+ keys = meta.getPrimaryProps(true).map((p, i) => {
156
+ if (!convertCustomTypes && p.customType) {
157
+ return p.customType.convertToDatabaseValue(keys[i], this.platform, {
158
+ key: p.name,
159
+ mode: 'hydration',
160
+ });
161
+ }
162
+ return keys[i];
163
+ });
139
164
  hash = Utils.getPrimaryKeyHash(keys);
140
165
  }
141
166
  schema ??= meta.schema ?? this.em.config.getSchema();
@@ -185,10 +210,8 @@ export class UnitOfWork {
185
210
  if (this.queuedActions.has(meta.className) || this.queuedActions.has(meta.root.className)) {
186
211
  return true;
187
212
  }
188
- for (const entity of this.identityMap.getStore(meta).values()) {
189
- if (helper(entity).__initialized && helper(entity).isTouched()) {
190
- return true;
191
- }
213
+ if (meta.discriminatorMap && Object.values(meta.discriminatorMap).some(v => this.queuedActions.has(v))) {
214
+ return true;
192
215
  }
193
216
  return false;
194
217
  }
@@ -209,7 +232,6 @@ export class UnitOfWork {
209
232
  this.changeSets.set(entity, cs);
210
233
  this.persistStack.delete(entity);
211
234
  wrapped.__originalEntityData = this.comparator.prepareEntity(entity);
212
- wrapped.__touched = false;
213
235
  }
214
236
  recomputeSingleChangeSet(entity) {
215
237
  const changeSet = this.changeSets.get(entity);
@@ -220,7 +242,6 @@ export class UnitOfWork {
220
242
  if (cs && !this.checkUniqueProps(cs)) {
221
243
  Object.assign(changeSet.payload, cs.payload);
222
244
  helper(entity).__originalEntityData = this.comparator.prepareEntity(entity);
223
- helper(entity).__touched = false;
224
245
  }
225
246
  }
226
247
  persist(entity, visited, options = {}) {
@@ -303,6 +324,7 @@ export class UnitOfWork {
303
324
  cs.entity.__helper.__processing = true;
304
325
  }
305
326
  await this.eventManager.dispatchEvent(EventType.onFlush, { em: this.em, uow: this });
327
+ this.filterCollectionUpdates();
306
328
  // nothing to do, do not start transaction
307
329
  if (this.changeSets.size === 0 && this.collectionUpdates.size === 0 && this.extraUpdates.size === 0) {
308
330
  return void (await this.eventManager.dispatchEvent(EventType.afterFlush, { em: this.em, uow: this }));
@@ -311,9 +333,11 @@ export class UnitOfWork {
311
333
  const platform = this.em.getPlatform();
312
334
  const runInTransaction = !this.em.isInTransaction() && platform.supportsTransactions() && this.em.config.get('implicitTransactions');
313
335
  if (runInTransaction) {
336
+ const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
314
337
  await this.em.getConnection('write').transactional(trx => this.persistToDatabase(groups, trx), {
315
338
  ctx: oldTx,
316
339
  eventBroadcaster: new TransactionEventBroadcaster(this.em),
340
+ loggerContext,
317
341
  });
318
342
  }
319
343
  else {
@@ -369,7 +393,6 @@ export class UnitOfWork {
369
393
  }
370
394
  delete wrapped.__identifier;
371
395
  delete wrapped.__originalEntityData;
372
- wrapped.__touched = false;
373
396
  wrapped.__managed = false;
374
397
  }
375
398
  computeChangeSets() {
@@ -379,14 +402,14 @@ export class UnitOfWork {
379
402
  this.cascade(entity, Cascade.REMOVE, visited);
380
403
  }
381
404
  visited.clear();
382
- for (const entity of this.persistStack) {
383
- this.cascade(entity, Cascade.PERSIST, visited, { checkRemoveStack: true });
384
- }
385
405
  for (const entity of this.identityMap) {
386
406
  if (!this.removeStack.has(entity) && !this.persistStack.has(entity) && !this.orphanRemoveStack.has(entity)) {
387
407
  this.cascade(entity, Cascade.PERSIST, visited, { checkRemoveStack: true });
388
408
  }
389
409
  }
410
+ for (const entity of this.persistStack) {
411
+ this.cascade(entity, Cascade.PERSIST, visited, { checkRemoveStack: true });
412
+ }
390
413
  visited.clear();
391
414
  for (const entity of this.persistStack) {
392
415
  this.findNewEntities(entity, visited);
@@ -542,13 +565,22 @@ export class UnitOfWork {
542
565
  if (!wrapped || wrapped.__identifier || wrapped.hasPrimaryKey()) {
543
566
  return;
544
567
  }
545
- const pk = wrapped.__meta.getPrimaryProps()[0];
546
- if (pk.kind === ReferenceKind.SCALAR) {
547
- wrapped.__identifier = new EntityIdentifier();
568
+ const pks = wrapped.__meta.getPrimaryProps();
569
+ const idents = [];
570
+ for (const pk of pks) {
571
+ if (pk.kind === ReferenceKind.SCALAR) {
572
+ idents.push(new EntityIdentifier(entity[pk.name]));
573
+ }
574
+ else if (entity[pk.name]) {
575
+ this.initIdentifier(entity[pk.name]);
576
+ idents.push(helper(entity[pk.name])?.__identifier);
577
+ }
578
+ }
579
+ if (pks.length === 1) {
580
+ wrapped.__identifier = idents[0];
548
581
  }
549
- else if (entity[pk.name]) {
550
- this.initIdentifier(entity[pk.name]);
551
- wrapped.__identifier = helper(entity[pk.name])?.__identifier;
582
+ else {
583
+ wrapped.__identifier = idents;
552
584
  }
553
585
  }
554
586
  processReference(parent, prop, kind, visited, processed, idx) {
@@ -600,8 +632,15 @@ export class UnitOfWork {
600
632
  const diff = this.comparator.diffEntities(changeSet.name, copy, current);
601
633
  Object.assign(changeSet.payload, diff);
602
634
  const wrapped = helper(changeSet.entity);
603
- if (wrapped.__identifier && diff[wrapped.__meta.primaryKeys[0]]) {
604
- wrapped.__identifier.setValue(diff[wrapped.__meta.primaryKeys[0]]);
635
+ if (wrapped.__identifier) {
636
+ const idents = Utils.asArray(wrapped.__identifier);
637
+ let i = 0;
638
+ for (const pk of wrapped.__meta.primaryKeys) {
639
+ if (diff[pk]) {
640
+ idents[i].setValue(diff[pk]);
641
+ }
642
+ i++;
643
+ }
605
644
  }
606
645
  }
607
646
  postCommitCleanup() {
@@ -825,9 +864,16 @@ export class UnitOfWork {
825
864
  }
826
865
  await this.changeSetPersister.executeUpdates(changeSets, batched, { ctx });
827
866
  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;
867
+ const wrapped = helper(changeSet.entity);
868
+ wrapped.__originalEntityData = this.comparator.prepareEntity(changeSet.entity);
869
+ if (!wrapped.__initialized) {
870
+ for (const prop of changeSet.meta.relations) {
871
+ if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) && changeSet.entity[prop.name] == null) {
872
+ changeSet.entity[prop.name] = Collection.create(changeSet.entity, prop.name, undefined, wrapped.isInitialized());
873
+ }
874
+ }
875
+ wrapped.__initialized = true;
876
+ }
831
877
  await this.runHooks(EventType.afterUpdate, changeSet);
832
878
  }
833
879
  }
@@ -870,23 +916,34 @@ export class UnitOfWork {
870
916
  }
871
917
  }
872
918
  async commitCollectionUpdates(ctx) {
873
- const collectionUpdates = [];
919
+ this.filterCollectionUpdates();
920
+ const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
921
+ await this.em.getDriver().syncCollections(this.collectionUpdates, {
922
+ ctx,
923
+ schema: this.em.schema,
924
+ loggerContext,
925
+ });
926
+ for (const coll of this.collectionUpdates) {
927
+ coll.takeSnapshot();
928
+ }
929
+ }
930
+ filterCollectionUpdates() {
874
931
  for (const coll of this.collectionUpdates) {
932
+ let skip = true;
875
933
  if (coll.property.owner || coll.getItems(false).filter(item => !item.__helper.__initialized).length > 0) {
876
934
  if (this.platform.usesPivotTable()) {
877
- collectionUpdates.push(coll);
935
+ skip = false;
878
936
  }
879
937
  }
880
938
  else if (coll.property.kind === ReferenceKind.ONE_TO_MANY && coll.getSnapshot() === undefined) {
881
- collectionUpdates.push(coll);
939
+ skip = false;
882
940
  }
883
941
  else if (coll.property.kind === ReferenceKind.MANY_TO_MANY && !coll.property.owner) {
884
- collectionUpdates.push(coll);
942
+ skip = false;
943
+ }
944
+ if (skip) {
945
+ this.collectionUpdates.delete(coll);
885
946
  }
886
- }
887
- await this.em.getDriver().syncCollections(collectionUpdates, { ctx, schema: this.em.schema });
888
- for (const coll of this.collectionUpdates) {
889
- coll.takeSnapshot();
890
947
  }
891
948
  }
892
949
  /**
@@ -42,7 +42,9 @@ export class AbstractSchemaGenerator {
42
42
  for (const meta of this.getOrderedMetadata(options?.schema).reverse()) {
43
43
  await this.driver.nativeDelete(meta.className, {}, options);
44
44
  }
45
- this.clearIdentityMap();
45
+ if (options?.clearIdentityMap ?? true) {
46
+ this.clearIdentityMap();
47
+ }
46
48
  }
47
49
  clearIdentityMap() {
48
50
  /* v8 ignore next 3 */
@@ -2,7 +2,7 @@ import type { NamingStrategy } from '../naming-strategy/NamingStrategy.js';
2
2
  import { FileCacheAdapter } from '../cache/FileCacheAdapter.js';
3
3
  import { type SyncCacheAdapter, type CacheAdapter } from '../cache/CacheAdapter.js';
4
4
  import type { EntityRepository } from '../entity/EntityRepository.js';
5
- import type { AnyEntity, Constructor, Dictionary, EntityClass, EntityClassGroup, FilterDef, Highlighter, HydratorConstructor, IHydrator, IMigrationGenerator, IPrimaryKey, MaybePromise, MigrationObject, EntityMetadata, EnsureDatabaseOptions, GenerateOptions, Migration } from '../typings.js';
5
+ import type { AnyEntity, Constructor, Dictionary, EntityClass, FilterDef, Highlighter, HydratorConstructor, IHydrator, IMigrationGenerator, IPrimaryKey, MaybePromise, MigrationObject, EntityMetadata, EnsureDatabaseOptions, GenerateOptions, Migration } from '../typings.js';
6
6
  import { ObjectHydrator } from '../hydration/ObjectHydrator.js';
7
7
  import { NullHighlighter } from '../utils/NullHighlighter.js';
8
8
  import { type Logger, type LoggerNamespace, type LoggerOptions } from '../logging/Logger.js';
@@ -54,14 +54,14 @@ 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
- connect: true;
61
60
  ignoreUndefinedInQuery: false;
62
61
  onQuery: (sql: string) => string;
63
62
  autoJoinOneToOneOwner: true;
64
63
  autoJoinRefsForFilters: true;
64
+ filtersOnRelations: true;
65
65
  propagationOnPrototype: true;
66
66
  populateAfterFlush: true;
67
67
  serialization: {
@@ -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,17 +105,21 @@ 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;
112
116
  undefinedDefaults: false;
113
- bidirectionalRelations: false;
114
- identifiedReferences: false;
115
117
  scalarTypeInDecorator: false;
118
+ bidirectionalRelations: true;
119
+ identifiedReferences: true;
116
120
  scalarPropertiesForRelations: "never";
121
+ entityDefinition: "defineEntity";
122
+ enumMode: "dictionary";
117
123
  fileName: (className: string) => string;
118
124
  onlyPurePivotTables: false;
119
125
  outputPurePivotTables: false;
@@ -170,10 +176,6 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
170
176
  */
171
177
  getLogger(): Logger;
172
178
  getDataloaderType(): DataloaderType;
173
- /**
174
- * Gets current client URL (connection string).
175
- */
176
- getClientUrl(hidePassword?: boolean): string;
177
179
  getSchema(skipDefaultSchema?: boolean): string | undefined;
178
180
  /**
179
181
  * Gets current database driver instance.
@@ -232,7 +234,7 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
232
234
  /**
233
235
  * Type helper to make it easier to use `mikro-orm.config.js`.
234
236
  */
235
- export declare function defineConfig<D extends IDatabaseDriver>(options: Options<D>): Options<D, D[typeof EntityManagerType] & EntityManager<IDatabaseDriver<import("../index.js").Connection>>>;
237
+ export declare function defineConfig<D extends IDatabaseDriver = IDatabaseDriver, EM extends EntityManager<D> = EntityManager<D>, Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]>(options: Options<D, EM, Entities>): Options<D, EM, Entities>;
236
238
  export interface ConnectionOptions {
237
239
  dbName?: string;
238
240
  schema?: string;
@@ -294,10 +296,11 @@ export interface MetadataDiscoveryOptions {
294
296
  onMetadata?: (meta: EntityMetadata, platform: Platform) => MaybePromise<void>;
295
297
  afterDiscovered?: (storage: MetadataStorage, platform: Platform) => MaybePromise<void>;
296
298
  tsConfigPath?: string;
299
+ skipSyncDiscovery?: boolean;
297
300
  }
298
301
  export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM extends EntityManager = EntityManager> extends ConnectionOptions {
299
- entities: (string | EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[];
300
- entitiesTs: (string | EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[];
302
+ entities: (string | EntityClass<AnyEntity> | EntitySchema)[];
303
+ entitiesTs: (string | EntityClass<AnyEntity> | EntitySchema)[];
301
304
  extensions: {
302
305
  register: (orm: MikroORM) => void;
303
306
  }[];
@@ -314,12 +317,12 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
314
317
  };
315
318
  implicitTransactions?: boolean;
316
319
  disableTransactions?: boolean;
317
- connect: boolean;
318
320
  verbose: boolean;
319
321
  ignoreUndefinedInQuery?: boolean;
320
322
  onQuery: (sql: string, params: readonly unknown[]) => string;
321
323
  autoJoinOneToOneOwner: boolean;
322
324
  autoJoinRefsForFilters: boolean;
325
+ filtersOnRelations: boolean;
323
326
  propagationOnPrototype: boolean;
324
327
  populateAfterFlush: boolean;
325
328
  serialization: {
@@ -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: {
@@ -403,5 +413,8 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
403
413
  seeder: SeederOptions;
404
414
  preferReadReplicas: boolean;
405
415
  dynamicImportProvider: (id: string) => Promise<unknown>;
416
+ hashAlgorithm: 'md5' | 'sha256';
417
+ }
418
+ export interface Options<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager = D[typeof EntityManagerType] & EntityManager, Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]> extends Pick<MikroORMOptions<D, EM>, Exclude<keyof MikroORMOptions, keyof typeof Configuration.DEFAULTS>>, Partial<MikroORMOptions<D, EM>> {
419
+ entities?: Entities;
406
420
  }
407
- 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,14 +44,14 @@ 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
- connect: true,
51
50
  ignoreUndefinedInQuery: false,
52
51
  onQuery: sql => sql,
53
52
  autoJoinOneToOneOwner: true,
54
53
  autoJoinRefsForFilters: true,
54
+ filtersOnRelations: true,
55
55
  propagationOnPrototype: true,
56
56
  populateAfterFlush: true,
57
57
  serialization: {
@@ -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,17 +95,21 @@ 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,
102
106
  undefinedDefaults: false,
103
- bidirectionalRelations: false,
104
- identifiedReferences: false,
105
107
  scalarTypeInDecorator: false,
108
+ bidirectionalRelations: true,
109
+ identifiedReferences: true,
106
110
  scalarPropertiesForRelations: 'never',
111
+ entityDefinition: 'defineEntity',
112
+ enumMode: 'dictionary',
107
113
  fileName: (className) => className,
108
114
  onlyPurePivotTables: false,
109
115
  outputPurePivotTables: false,
@@ -144,7 +150,6 @@ export class Configuration {
144
150
  }
145
151
  this.options = Utils.mergeConfig({}, Configuration.DEFAULTS, options);
146
152
  this.options.baseDir = Utils.absolutePath(this.options.baseDir);
147
- this.options.preferTs ??= options.preferTs;
148
153
  if (validate) {
149
154
  this.validateOptions();
150
155
  }
@@ -204,15 +209,6 @@ export class Configuration {
204
209
  }
205
210
  return this.options.dataloader;
206
211
  }
207
- /**
208
- * Gets current client URL (connection string).
209
- */
210
- getClientUrl(hidePassword = false) {
211
- if (hidePassword) {
212
- return this.options.clientUrl.replace(/\/\/([^:]+):(.+)@/, '//$1:*****@');
213
- }
214
- return this.options.clientUrl;
215
- }
216
212
  getSchema(skipDefaultSchema = false) {
217
213
  if (skipDefaultSchema && this.options.schema === this.platform.getDefaultSchemaName()) {
218
214
  return undefined;
@@ -268,7 +264,7 @@ export class Configuration {
268
264
  * Gets instance of metadata CacheAdapter. (cached)
269
265
  */
270
266
  getMetadataCacheAdapter() {
271
- return this.getCachedService(this.options.metadataCache.adapter, this.options.metadataCache.options, this.options.baseDir, this.options.metadataCache.pretty);
267
+ return this.getCachedService(this.options.metadataCache.adapter, this.options.metadataCache.options, this.options.baseDir, this.options.metadataCache.pretty, this.options.hashAlgorithm);
272
268
  }
273
269
  /**
274
270
  * Gets instance of CacheAdapter for result cache. (cached)
@@ -315,13 +311,13 @@ export class Configuration {
315
311
  this.options.implicitTransactions = this.platform.usesImplicitTransactions();
316
312
  }
317
313
  try {
318
- const url = new URL(this.getClientUrl());
314
+ const url = new URL(this.options.clientUrl);
319
315
  if (url.pathname) {
320
316
  this.options.dbName = this.get('dbName', decodeURIComponent(url.pathname).substring(1));
321
317
  }
322
318
  }
323
319
  catch {
324
- const url = this.getClientUrl().match(/:\/\/.*\/([^?]+)/);
320
+ const url = this.options.clientUrl.match(/:\/\/.*\/([^?]+)/);
325
321
  if (url) {
326
322
  this.options.dbName = this.get('dbName', decodeURIComponent(url[1]));
327
323
  }
@@ -338,6 +334,9 @@ export class Configuration {
338
334
  Object.keys(this.options.filters).forEach(key => {
339
335
  this.options.filters[key].default ??= true;
340
336
  });
337
+ if (!this.options.filtersOnRelations) {
338
+ this.options.autoJoinRefsForFilters ??= false;
339
+ }
341
340
  this.options.subscribers = Utils.unique(this.options.subscribers).map(subscriber => {
342
341
  return subscriber.constructor.name === 'Function' ? new subscriber() : subscriber;
343
342
  });
@@ -13,42 +13,29 @@ export declare class ConfigurationLoader {
13
13
  * @param paths Array of possible paths for a configuration file. Files will be checked in order, and the first existing one will be used. Defaults to the output of {@link ConfigurationLoader.getConfigPaths}.
14
14
  * @param options Additional options to augment the final configuration with.
15
15
  */
16
- static getConfiguration<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager = EntityManager>(contextName: string, paths?: string[], options?: Partial<Options>): Promise<Configuration<D, EM>>;
17
- /**
18
- * Gets the default config from the default paths
19
- *
20
- * @deprecated Prefer to explicitly set the `contextName` at the first argument. This signature is available for backwards compatibility, and may be removed in v7.
21
- */
22
- static getConfiguration<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager = EntityManager>(): Promise<Configuration<D, EM>>;
23
- /**
24
- * Gets default configuration out of the default paths, and possibly from `process.argv`
25
- *
26
- * @param validate Whether to validate the final configuration.
27
- * @param options Additional options to augment the final configuration with (just before validation).
28
- *
29
- * @deprecated Use the other overloads of this method. This signature will be removed in v7.
30
- */
31
- static getConfiguration<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager = EntityManager>(validate: boolean, options?: Partial<Options>): Promise<Configuration<D, EM>>;
16
+ static getConfiguration<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager = EntityManager>(contextName?: string, paths?: string[], options?: Partial<Options>): Promise<Configuration<D, EM>>;
32
17
  static getConfigFile(paths: string[]): Promise<[string, unknown] | []>;
33
18
  static getPackageConfig(basePath?: string): Dictionary;
34
19
  static getSettings(): Settings;
35
- static configPathsFromArg(): string[] | undefined;
36
20
  static getConfigPaths(): string[];
37
21
  static isESM(): boolean;
38
- static registerTypeScriptSupport(configPath?: string): Promise<boolean>;
39
- static registerDotenv<D extends IDatabaseDriver>(options?: Options<D>): void;
22
+ /**
23
+ * Tries to register TS support in the following order: swc, tsx, jiti, tsimp
24
+ * Use `MIKRO_ORM_CLI_TS_LOADER` env var to set the loader explicitly.
25
+ * This method is used only in CLI context.
26
+ */
27
+ static registerTypeScriptSupport(configPath?: string, tsLoader?: 'swc' | 'tsx' | 'jiti' | 'tsimp' | 'auto'): Promise<boolean>;
28
+ static registerDotenv<D extends IDatabaseDriver>(options: Options<D>): void;
40
29
  static loadEnvironmentVars<D extends IDatabaseDriver>(): Promise<Partial<Options<D>>>;
41
30
  static loadEnvironmentVarsSync<D extends IDatabaseDriver>(): Partial<Options<D>>;
42
31
  static getORMPackages(): Set<string>;
43
- /** @internal */
44
- static commonJSCompat(options: Partial<Options>): void;
45
32
  static getORMPackageVersion(name: string): string | undefined;
46
33
  static checkPackageVersion(): string;
47
34
  }
48
35
  export interface Settings {
49
- alwaysAllowTs?: boolean;
50
36
  verbose?: boolean;
51
37
  preferTs?: boolean;
38
+ tsLoader?: 'swc' | 'tsx' | 'jiti' | 'tsimp' | 'auto';
52
39
  tsConfigPath?: string;
53
40
  configPaths?: string[];
54
41
  }