@mikro-orm/core 7.0.0-rc.2 → 7.0.0-rc.3

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 (65) hide show
  1. package/EntityManager.d.ts +2 -1
  2. package/EntityManager.js +106 -42
  3. package/MikroORM.js +4 -4
  4. package/cache/FileCacheAdapter.js +1 -3
  5. package/connections/Connection.js +16 -3
  6. package/drivers/DatabaseDriver.js +26 -8
  7. package/drivers/IDatabaseDriver.d.ts +43 -0
  8. package/entity/Collection.js +43 -17
  9. package/entity/EntityAssigner.js +23 -11
  10. package/entity/EntityFactory.js +32 -12
  11. package/entity/EntityHelper.js +25 -16
  12. package/entity/EntityLoader.js +55 -22
  13. package/entity/Reference.d.ts +1 -1
  14. package/entity/Reference.js +37 -8
  15. package/entity/WrappedEntity.js +5 -1
  16. package/entity/defineEntity.d.ts +24 -12
  17. package/entity/utils.js +28 -26
  18. package/entity/validators.js +2 -1
  19. package/enums.js +12 -17
  20. package/errors.js +18 -8
  21. package/events/EventManager.js +1 -1
  22. package/exceptions.js +7 -2
  23. package/hydration/ObjectHydrator.js +27 -13
  24. package/index.d.ts +1 -1
  25. package/index.js +1 -1
  26. package/logging/DefaultLogger.js +3 -5
  27. package/logging/colors.js +3 -6
  28. package/metadata/EntitySchema.d.ts +2 -2
  29. package/metadata/EntitySchema.js +12 -2
  30. package/metadata/MetadataDiscovery.js +106 -47
  31. package/metadata/MetadataProvider.js +26 -1
  32. package/metadata/MetadataStorage.js +2 -4
  33. package/metadata/MetadataValidator.js +20 -5
  34. package/metadata/types.d.ts +2 -2
  35. package/naming-strategy/AbstractNamingStrategy.js +5 -2
  36. package/not-supported.js +5 -1
  37. package/package.json +38 -38
  38. package/platforms/Platform.d.ts +1 -0
  39. package/platforms/Platform.js +49 -23
  40. package/serialization/EntitySerializer.js +7 -3
  41. package/serialization/SerializationContext.js +1 -1
  42. package/typings.d.ts +23 -23
  43. package/typings.js +9 -9
  44. package/unit-of-work/ChangeSet.js +4 -4
  45. package/unit-of-work/ChangeSetComputer.js +8 -6
  46. package/unit-of-work/ChangeSetPersister.js +13 -8
  47. package/unit-of-work/CommitOrderCalculator.js +4 -2
  48. package/unit-of-work/UnitOfWork.d.ts +7 -1
  49. package/unit-of-work/UnitOfWork.js +51 -22
  50. package/utils/AbstractMigrator.d.ts +1 -1
  51. package/utils/AbstractMigrator.js +3 -5
  52. package/utils/AbstractSchemaGenerator.js +2 -1
  53. package/utils/AsyncContext.js +1 -1
  54. package/utils/Configuration.js +8 -4
  55. package/utils/Cursor.js +4 -2
  56. package/utils/DataloaderUtils.js +15 -12
  57. package/utils/EntityComparator.js +51 -43
  58. package/utils/QueryHelper.js +38 -26
  59. package/utils/RawQueryFragment.js +3 -2
  60. package/utils/TransactionManager.js +2 -1
  61. package/utils/Utils.d.ts +1 -1
  62. package/utils/Utils.js +36 -30
  63. package/utils/env-vars.js +6 -5
  64. package/utils/fs-utils.js +2 -5
  65. package/utils/upsert-utils.js +6 -3
@@ -22,7 +22,7 @@ export class Collection {
22
22
  if (items) {
23
23
  let i = 0;
24
24
  this.items = new Set(items);
25
- this.items.forEach(item => this[i++] = item);
25
+ this.items.forEach(item => (this[i++] = item));
26
26
  }
27
27
  this.initialized = !!items || initialized;
28
28
  }
@@ -58,7 +58,7 @@ export class Collection {
58
58
  helper(this.owner).setSerializationContext({
59
59
  populate: Array.isArray(options.populate)
60
60
  ? options.populate.map(hint => `${this.property.name}.${hint}`)
61
- : options.populate ?? [this.property.name],
61
+ : (options.populate ?? [this.property.name]),
62
62
  });
63
63
  }
64
64
  /**
@@ -79,8 +79,10 @@ export class Collection {
79
79
  return this._count;
80
80
  }
81
81
  const em = this.getEntityManager();
82
- if (!em.getPlatform().usesPivotTable() && this.property.kind === ReferenceKind.MANY_TO_MANY && this.property.owner) {
83
- return this._count = this.length;
82
+ if (!em.getPlatform().usesPivotTable() &&
83
+ this.property.kind === ReferenceKind.MANY_TO_MANY &&
84
+ this.property.owner) {
85
+ return (this._count = this.length);
84
86
  }
85
87
  const cond = this.createLoadCountCondition(where ?? {});
86
88
  const count = await em.count(this.property.targetMeta.class, cond, countOptions);
@@ -96,16 +98,18 @@ export class Collection {
96
98
  if (this.property.kind === ReferenceKind.MANY_TO_MANY && em.getPlatform().usesPivotTable()) {
97
99
  // M:N via pivot table bypasses em.find(), so merge all 3 levels here
98
100
  opts.orderBy = QueryHelper.mergeOrderBy(opts.orderBy, this.property.orderBy, this.property.targetMeta?.orderBy);
99
- options.populate = await em.preparePopulate(this.property.targetMeta.class, options);
100
- const cond = await em.applyFilters(this.property.targetMeta.class, where, options.filters ?? {}, 'read');
101
- const map = await em.getDriver().loadFromPivotTable(this.property, [helper(this.owner).__primaryKeys], cond, opts.orderBy, ctx, options);
101
+ options.populate = (await em.preparePopulate(this.property.targetMeta.class, options));
102
+ const cond = (await em.applyFilters(this.property.targetMeta.class, where, options.filters ?? {}, 'read'));
103
+ const map = await em
104
+ .getDriver()
105
+ .loadFromPivotTable(this.property, [helper(this.owner).__primaryKeys], cond, opts.orderBy, ctx, options);
102
106
  items = map[helper(this.owner).getSerializedPrimaryKey()].map((item) => em.merge(this.property.targetMeta.class, item, { convertCustomTypes: true }));
103
107
  await em.populate(items, options.populate, options);
104
108
  }
105
109
  else {
106
110
  // em.find() merges entity-level orderBy, so only merge runtime + relation here
107
111
  opts.orderBy = QueryHelper.mergeOrderBy(opts.orderBy, this.property.orderBy);
108
- items = await em.find(this.property.targetMeta.class, this.createCondition(where), opts);
112
+ items = (await em.find(this.property.targetMeta.class, this.createCondition(where), opts));
109
113
  }
110
114
  if (options.store) {
111
115
  this.hydrate(items, true);
@@ -262,11 +266,9 @@ export class Collection {
262
266
  return this;
263
267
  }
264
268
  const populate = Array.isArray(options.populate)
265
- ? options.populate.map(f => f === '*' ? f : `${this.property.name}.${f}`)
269
+ ? options.populate.map(f => (f === '*' ? f : `${this.property.name}.${f}`))
266
270
  : [`${this.property.name}${options.ref ? ':ref' : ''}`];
267
- const schema = this.property.targetMeta.schema === '*'
268
- ? helper(this.owner).__schema
269
- : undefined;
271
+ const schema = this.property.targetMeta.schema === '*' ? helper(this.owner).__schema : undefined;
270
272
  await em.populate(this.owner, populate, {
271
273
  refresh: true,
272
274
  ...options,
@@ -297,7 +299,8 @@ export class Collection {
297
299
  if (this.property.kind === ReferenceKind.ONE_TO_MANY) {
298
300
  cond[this.property.mappedBy] = helper(this.owner).getPrimaryKey();
299
301
  }
300
- else { // MANY_TO_MANY
302
+ else {
303
+ // MANY_TO_MANY
301
304
  this.createManyToManyCondition(cond);
302
305
  }
303
306
  return cond;
@@ -386,7 +389,9 @@ export class Collection {
386
389
  if (items.length === 0) {
387
390
  return [];
388
391
  }
389
- field ??= targetMeta.compositePK ? targetMeta.primaryKeys : (targetMeta.serializedPrimaryKey ?? targetMeta.primaryKeys[0]);
392
+ field ??= targetMeta.compositePK
393
+ ? targetMeta.primaryKeys
394
+ : (targetMeta.serializedPrimaryKey ?? targetMeta.primaryKeys[0]);
390
395
  const cb = (i, f) => {
391
396
  if (Utils.isEntity(i[f], true)) {
392
397
  return wrap(i[f], true).getPrimaryKey();
@@ -616,6 +621,7 @@ export class Collection {
616
621
  * @internal
617
622
  */
618
623
  get property() {
624
+ // cannot be typed to `EntityProperty<O, T>` as it causes issues in assignability of `Loaded` type
619
625
  if (!this._property) {
620
626
  const meta = wrap(this.owner, true).__meta;
621
627
  /* v8 ignore next */
@@ -630,6 +636,7 @@ export class Collection {
630
636
  * @internal
631
637
  */
632
638
  set property(prop) {
639
+ // cannot be typed to `EntityProperty<O, T>` as it causes issues in assignability of `Loaded` type
633
640
  this._property = prop;
634
641
  }
635
642
  propagate(item, method) {
@@ -696,7 +703,18 @@ export class Collection {
696
703
  /** @ignore */
697
704
  [Symbol.for('nodejs.util.inspect.custom')](depth = 2) {
698
705
  const object = { ...this };
699
- const hidden = ['items', 'owner', '_property', '_count', 'snapshot', '_populated', '_lazyInitialized', '_em', 'readonly', 'partial'];
706
+ const hidden = [
707
+ 'items',
708
+ 'owner',
709
+ '_property',
710
+ '_count',
711
+ 'snapshot',
712
+ '_populated',
713
+ '_lazyInitialized',
714
+ '_em',
715
+ 'readonly',
716
+ 'partial',
717
+ ];
700
718
  hidden.forEach(k => delete object[k]);
701
719
  const ret = inspect(object, { depth });
702
720
  const name = `${this.constructor.name}<${this.property?.type ?? 'unknown'}>`;
@@ -704,7 +722,15 @@ export class Collection {
704
722
  }
705
723
  }
706
724
  Object.defineProperties(Collection.prototype, {
707
- $: { get() { return this; } },
708
- get: { get() { return () => this; } },
725
+ $: {
726
+ get() {
727
+ return this;
728
+ },
729
+ },
730
+ get: {
731
+ get() {
732
+ return () => this;
733
+ },
734
+ },
709
735
  __collection: { value: true, enumerable: false, writable: false },
710
736
  });
@@ -71,7 +71,10 @@ export class EntityAssigner {
71
71
  value = customType.convertToJSValue(value, options.platform);
72
72
  }
73
73
  if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop?.kind) && value != null) {
74
- if (options.updateNestedEntities && Object.hasOwn(entity, propName) && Utils.isEntity(entity[propName], true) && Utils.isPlainObject(value)) {
74
+ if (options.updateNestedEntities &&
75
+ Object.hasOwn(entity, propName) &&
76
+ Utils.isEntity(entity[propName], true) &&
77
+ Utils.isPlainObject(value)) {
75
78
  const unwrappedEntity = Reference.unwrapReference(entity[propName]);
76
79
  const wrapped = helper(unwrappedEntity);
77
80
  if (options.updateByPrimaryKey) {
@@ -95,12 +98,14 @@ export class EntityAssigner {
95
98
  }
96
99
  if (prop.kind === ReferenceKind.SCALAR && SCALAR_TYPES.has(prop.runtimeType) && (prop.setter || !prop.getter)) {
97
100
  validateProperty(prop, value, entity);
98
- return entity[prop.name] = value;
101
+ return (entity[prop.name] = value);
99
102
  }
100
103
  if (prop.kind === ReferenceKind.EMBEDDED && EntityAssigner.validateEM(options.em)) {
101
104
  return EntityAssigner.assignEmbeddable(entity, value, prop, options.em, options);
102
105
  }
103
- if (options.mergeObjectProperties && Utils.isPlainObject(entity[propName]) && Utils.isPlainObject(value)) {
106
+ if (options.mergeObjectProperties &&
107
+ Utils.isPlainObject(entity[propName]) &&
108
+ Utils.isPlainObject(value)) {
104
109
  entity[propName] ??= {};
105
110
  entity[propName] = Utils.merge({}, entity[propName], value);
106
111
  }
@@ -141,7 +146,9 @@ export class EntityAssigner {
141
146
  entity[prop.name] = Reference.wrapReference(value, prop);
142
147
  }
143
148
  else if (Utils.isPrimaryKey(value, true) && EntityAssigner.validateEM(em)) {
144
- entity[prop.name] = prop.mapToPk ? value : Reference.wrapReference(em.getReference(prop.targetMeta.class, value, options), prop);
149
+ entity[prop.name] = prop.mapToPk
150
+ ? value
151
+ : Reference.wrapReference(em.getReference(prop.targetMeta.class, value, options), prop);
145
152
  }
146
153
  else if (Utils.isPlainObject(value) && options.merge && EntityAssigner.validateEM(em)) {
147
154
  entity[prop.name] = Reference.wrapReference(em.merge(prop.targetMeta.class, value, options), prop);
@@ -174,7 +181,10 @@ export class EntityAssigner {
174
181
  return this.createCollectionItem(item, em, prop, invalid, options);
175
182
  }
176
183
  /* v8 ignore next */
177
- if (options.updateNestedEntities && !options.updateByPrimaryKey && collection[idx] && helper(collection[idx])?.isInitialized()) {
184
+ if (options.updateNestedEntities &&
185
+ !options.updateByPrimaryKey &&
186
+ collection[idx] &&
187
+ helper(collection[idx])?.isInitialized()) {
178
188
  return EntityAssigner.assign(collection[idx], item, options);
179
189
  }
180
190
  return this.createCollectionItem(item, em, prop, invalid, options);
@@ -186,7 +196,8 @@ export class EntityAssigner {
186
196
  if (Array.isArray(value)) {
187
197
  collection.set(items);
188
198
  }
189
- else { // append to the collection in case of assigning a single value instead of array
199
+ else {
200
+ // append to the collection in case of assigning a single value instead of array
190
201
  collection.add(items);
191
202
  }
192
203
  }
@@ -207,11 +218,12 @@ export class EntityAssigner {
207
218
  entity[propName].push(...Object.values(tmp));
208
219
  });
209
220
  }
210
- const create = () => EntityAssigner.validateEM(em) && em.getEntityFactory().createEmbeddable(prop.targetMeta.class, value, {
211
- convertCustomTypes: options.convertCustomTypes,
212
- newEntity: options.mergeEmbeddedProperties ? !('propName' in entity) : true,
213
- });
214
- entity[propName] = (options.mergeEmbeddedProperties ? (entity[propName] || create()) : create());
221
+ const create = () => EntityAssigner.validateEM(em) &&
222
+ em.getEntityFactory().createEmbeddable(prop.targetMeta.class, value, {
223
+ convertCustomTypes: options.convertCustomTypes,
224
+ newEntity: options.mergeEmbeddedProperties ? !('propName' in entity) : true,
225
+ });
226
+ entity[propName] = (options.mergeEmbeddedProperties ? entity[propName] || create() : create());
215
227
  Object.keys(value).forEach(key => {
216
228
  EntityAssigner.assignProperty(entity[propName], key, prop.embeddedProps, value, options);
217
229
  });
@@ -70,11 +70,15 @@ export class EntityFactory {
70
70
  if ([ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
71
71
  continue;
72
72
  }
73
- if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(data[prop.name])) {
73
+ if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
74
+ Utils.isPlainObject(data[prop.name])) {
74
75
  data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
75
76
  }
76
77
  if (prop.customType instanceof JsonType && this.platform.convertsJsonAutomatically()) {
77
- data[prop.name] = prop.customType.convertToDatabaseValue(data[prop.name], this.platform, { key: prop.name, mode: 'hydration' });
78
+ data[prop.name] = prop.customType.convertToDatabaseValue(data[prop.name], this.platform, {
79
+ key: prop.name,
80
+ mode: 'hydration',
81
+ });
78
82
  }
79
83
  }
80
84
  }
@@ -111,23 +115,28 @@ export class EntityFactory {
111
115
  const originalEntityData = helper(entity).__originalEntityData ?? {};
112
116
  const diff = this.comparator.diffEntities(meta.class, originalEntityData, existsData);
113
117
  // version properties are not part of entity snapshots
114
- if (meta.versionProperty && data[meta.versionProperty] && data[meta.versionProperty] !== originalEntityData[meta.versionProperty]) {
118
+ if (meta.versionProperty &&
119
+ data[meta.versionProperty] &&
120
+ data[meta.versionProperty] !== originalEntityData[meta.versionProperty]) {
115
121
  diff[meta.versionProperty] = data[meta.versionProperty];
116
122
  }
117
123
  const diff2 = this.comparator.diffEntities(meta.class, existsData, data, { includeInverseSides: true });
118
124
  // do not override values changed by user
119
125
  Utils.keys(diff).forEach(key => delete diff2[key]);
120
- Utils.keys(diff2).filter(key => {
126
+ Utils.keys(diff2)
127
+ .filter(key => {
121
128
  // ignore null values if there is already present non-null value
122
129
  if (existsData[key] != null) {
123
130
  return diff2[key] == null;
124
131
  }
125
132
  return diff2[key] === undefined;
126
- }).forEach(key => delete diff2[key]);
133
+ })
134
+ .forEach(key => delete diff2[key]);
127
135
  // but always add collection properties and formulas if they are part of the `data`
128
136
  Utils.keys(data)
129
- .filter(key => meta.properties[key]?.formula || [ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(meta.properties[key]?.kind))
130
- .forEach(key => diff2[key] = data[key]);
137
+ .filter(key => meta.properties[key]?.formula ||
138
+ [ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(meta.properties[key]?.kind))
139
+ .forEach(key => (diff2[key] = data[key]));
131
140
  // rehydrated with the new values, skip those changed by user
132
141
  // use full hydration if the entity is already initialized, even if the caller used `initialized: false`
133
142
  // (e.g. from createReference), otherwise scalar properties in diff2 won't be applied
@@ -137,10 +146,15 @@ export class EntityFactory {
137
146
  const nullVal = this.config.get('forceUndefined') ? undefined : null;
138
147
  Utils.keys(diff2).forEach(key => {
139
148
  const prop = meta.properties[key];
140
- if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(data[prop.name])) {
149
+ if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
150
+ Utils.isPlainObject(data[prop.name])) {
151
+ // oxfmt-ignore
141
152
  diff2[key] = entity[prop.name] ? helper(entity[prop.name]).getPrimaryKey(options.convertCustomTypes) : null;
142
153
  }
143
- if (!options.convertCustomTypes && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE, ReferenceKind.SCALAR].includes(prop.kind) && prop.customType?.ensureComparable(meta, prop) && diff2[key] != null) {
154
+ if (!options.convertCustomTypes &&
155
+ [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE, ReferenceKind.SCALAR].includes(prop.kind) &&
156
+ prop.customType?.ensureComparable(meta, prop) &&
157
+ diff2[key] != null) {
144
158
  const converted = prop.customType.convertToJSValue(diff2[key], this.platform, { force: true });
145
159
  diff2[key] = prop.customType.convertToDatabaseValue(converted, this.platform, { fromQuery: true });
146
160
  }
@@ -149,7 +163,8 @@ export class EntityFactory {
149
163
  });
150
164
  // in case of joined loading strategy, we need to cascade the merging to possibly loaded relations manually
151
165
  meta.relations.forEach(prop => {
152
- if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) && Array.isArray(data[prop.name])) {
166
+ if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) &&
167
+ Array.isArray(data[prop.name])) {
153
168
  // instead of trying to match the collection items (which could easily fail if the collection was loaded with different ordering),
154
169
  // we just create the entity from scratch, which will automatically pick the right one from the identity map and call `mergeData` on it
155
170
  data[prop.name]
@@ -157,7 +172,10 @@ export class EntityFactory {
157
172
  .forEach(child => this.create(prop.targetMeta.class, child, options)); // we can ignore the value, we just care about the `mergeData` call
158
173
  return;
159
174
  }
160
- if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(data[prop.name]) && entity[prop.name] && helper(entity[prop.name]).__initialized) {
175
+ if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
176
+ Utils.isPlainObject(data[prop.name]) &&
177
+ entity[prop.name] &&
178
+ helper(entity[prop.name]).__initialized) {
161
179
  this.create(prop.targetMeta.class, data[prop.name], options); // we can ignore the value, we just care about the `mergeData` call
162
180
  }
163
181
  });
@@ -356,7 +374,9 @@ export class EntityFactory {
356
374
  if (!options.convertCustomTypes || !prop.customType || tmp[prop.name] == null) {
357
375
  continue;
358
376
  }
359
- if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(tmp[prop.name]) && !Utils.extractPK(tmp[prop.name], prop.targetMeta, true)) {
377
+ if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
378
+ Utils.isPlainObject(tmp[prop.name]) &&
379
+ !Utils.extractPK(tmp[prop.name], prop.targetMeta, true)) {
360
380
  tmp[prop.name] = Reference.wrapReference(this.create(prop.targetMeta.class, tmp[prop.name], options), prop);
361
381
  }
362
382
  else if (prop.kind === ReferenceKind.SCALAR) {
@@ -31,15 +31,21 @@ export class EntityHelper {
31
31
  EntityHelper.defineProperties(meta, fork);
32
32
  }
33
33
  const prototype = meta.prototype;
34
- if (!prototype.toJSON) { // toJSON can be overridden
35
- prototype.toJSON = function (...args) {
36
- // Guard against being called on the prototype itself (e.g. by serializers
37
- // walking the object graph and calling toJSON on prototype objects)
38
- if (this === prototype) {
39
- return {};
40
- }
41
- return EntityTransformer.toObject(this, ...args);
42
- };
34
+ if (!prototype.toJSON) {
35
+ // toJSON can be overridden
36
+ Object.defineProperty(prototype, 'toJSON', {
37
+ value: function (...args) {
38
+ // Guard against being called on the prototype itself (e.g. by serializers
39
+ // walking the object graph and calling toJSON on prototype objects)
40
+ if (this === prototype) {
41
+ return {};
42
+ }
43
+ return EntityTransformer.toObject(this, ...args);
44
+ },
45
+ writable: true,
46
+ configurable: true,
47
+ enumerable: false,
48
+ });
43
49
  }
44
50
  }
45
51
  /**
@@ -49,6 +55,7 @@ export class EntityHelper {
49
55
  * property on the entity instance, so shadowing the prototype setter.
50
56
  */
51
57
  static defineBaseProperties(meta, prototype, em) {
58
+ // oxfmt-ignore
52
59
  const helperParams = meta.embeddable || meta.virtual ? [] : [em.getComparator().getPkGetter(meta), em.getComparator().getPkSerializer(meta), em.getComparator().getPkGetterConverted(meta)];
53
60
  Object.defineProperties(prototype, {
54
61
  __entity: { value: !meta.embeddable, configurable: true },
@@ -78,10 +85,9 @@ export class EntityHelper {
78
85
  * than on its prototype. Thanks to this we still have those properties enumerable (e.g. part of `Object.keys(entity)`).
79
86
  */
80
87
  static defineProperties(meta, em) {
81
- Object
82
- .values(meta.properties)
83
- .forEach(prop => {
88
+ Object.values(meta.properties).forEach(prop => {
84
89
  const isCollection = [ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind);
90
+ // oxfmt-ignore
85
91
  const isReference = [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind) && (prop.inversedBy || prop.mappedBy) && !prop.mapToPk;
86
92
  if (isReference) {
87
93
  Object.defineProperty(meta.prototype, prop.name, {
@@ -131,9 +137,7 @@ export class EntityHelper {
131
137
  }
132
138
  // ensure we dont have internal symbols in the POJO
133
139
  [OptionalProps, EntityRepositoryType, PrimaryKeyProp, EagerProps, HiddenProps, EntityName].forEach(sym => delete object[sym]);
134
- meta.props
135
- .filter(prop => object[prop.name] === undefined)
136
- .forEach(prop => delete object[prop.name]);
140
+ meta.props.filter(prop => object[prop.name] === undefined).forEach(prop => delete object[prop.name]);
137
141
  const ret = inspect(object, { depth });
138
142
  let name = this.constructor.name;
139
143
  const showEM = ['true', 't', '1'].includes(getEnv('MIKRO_ORM_LOG_EM_ID')?.toLowerCase() ?? '');
@@ -161,6 +165,7 @@ export class EntityHelper {
161
165
  set(val) {
162
166
  const entity = Reference.unwrapReference(val ?? wrapped.__data[prop.name]);
163
167
  const old = Reference.unwrapReference(wrapped.__data[prop.name]);
168
+ // oxfmt-ignore
164
169
  if (old && old !== entity && prop.kind === ReferenceKind.MANY_TO_ONE && prop.inversedBy && old[prop.inversedBy]) {
165
170
  old[prop.inversedBy].removeWithoutPropagation(this);
166
171
  }
@@ -192,6 +197,7 @@ export class EntityHelper {
192
197
  if ((prop2.inversedBy || prop2.mappedBy) !== prop.name) {
193
198
  continue;
194
199
  }
200
+ // oxfmt-ignore
195
201
  if (prop2.targetMeta.abstract ? prop2.targetMeta.root.class !== meta.root.class : prop2.targetMeta.class !== meta.class) {
196
202
  continue;
197
203
  }
@@ -223,7 +229,10 @@ export class EntityHelper {
223
229
  static propagateOneToOne(entity, owner, prop, prop2, value, old) {
224
230
  helper(entity).__pk = helper(entity).getPrimaryKey();
225
231
  // the inverse side will be changed on the `value` too, so we need to clean-up and schedule orphan removal there too
226
- if (!prop.primary && !prop2.mapToPk && value?.[prop2.name] != null && Reference.unwrapReference(value[prop2.name]) !== entity) {
232
+ if (!prop.primary &&
233
+ !prop2.mapToPk &&
234
+ value?.[prop2.name] != null &&
235
+ Reference.unwrapReference(value[prop2.name]) !== entity) {
227
236
  const other = Reference.unwrapReference(value[prop2.name]);
228
237
  delete helper(other).__data[prop.name];
229
238
  if (prop2.orphanRemoval) {
@@ -29,7 +29,7 @@ export class EntityLoader {
29
29
  throw ValidationError.notDiscoveredEntity(entity, meta, 'populate');
30
30
  }
31
31
  const references = entities.filter(e => !helper(e).isInitialized());
32
- const visited = options.visited ??= new Set();
32
+ const visited = (options.visited ??= new Set());
33
33
  options.where ??= {};
34
34
  options.orderBy ??= {};
35
35
  options.lookup ??= true;
@@ -59,6 +59,7 @@ export class EntityLoader {
59
59
  normalizePopulate(entityName, populate, strategy, lookup = true, exclude) {
60
60
  const meta = this.metadata.find(entityName);
61
61
  let normalized = Utils.asArray(populate).map(field => {
62
+ // oxfmt-ignore
62
63
  return typeof field === 'boolean' || field.field === PopulatePath.ALL ? { all: !!field, field: meta.primaryKeys[0] } : field;
63
64
  });
64
65
  if (normalized.some(p => p.all)) {
@@ -89,6 +90,7 @@ export class EntityLoader {
89
90
  */
90
91
  mergeNestedPopulate(populate) {
91
92
  const tmp = populate.reduce((ret, item) => {
93
+ /* v8 ignore next */
92
94
  if (item.field === PopulatePath.ALL) {
93
95
  return ret;
94
96
  }
@@ -125,7 +127,8 @@ export class EntityLoader {
125
127
  }
126
128
  }
127
129
  if (prop.kind === ReferenceKind.SCALAR && prop.lazy) {
128
- const filtered = entities.filter(e => options.refresh || (prop.ref ? !e[prop.name]?.isInitialized() : e[prop.name] === undefined));
130
+ const filtered = entities.filter(e => options.refresh ||
131
+ (prop.ref ? !e[prop.name]?.isInitialized() : e[prop.name] === undefined));
129
132
  if (options.ignoreLazyScalarProperties || filtered.length === 0) {
130
133
  return entities;
131
134
  }
@@ -137,7 +140,8 @@ export class EntityLoader {
137
140
  }
138
141
  const filtered = this.filterCollections(entities, field, options, ref);
139
142
  const innerOrderBy = Utils.asArray(options.orderBy)
140
- .filter(orderBy => (Array.isArray(orderBy[prop.name]) && orderBy[prop.name].length > 0) || Utils.isObject(orderBy[prop.name]))
143
+ .filter(orderBy => (Array.isArray(orderBy[prop.name]) && orderBy[prop.name].length > 0) ||
144
+ Utils.isObject(orderBy[prop.name]))
141
145
  .flatMap(orderBy => orderBy[prop.name]);
142
146
  const where = await this.extractChildCondition(options, prop);
143
147
  if (prop.kind === ReferenceKind.MANY_TO_MANY && this.driver.getPlatform().usesPivotTable()) {
@@ -163,7 +167,13 @@ export class EntityLoader {
163
167
  const where = this.mergePrimaryCondition(ids, pk, options, meta, this.metadata, this.driver.getPlatform());
164
168
  const { filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging, fields } = options;
165
169
  await this.em.find(meta.class, where, {
166
- filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging,
170
+ filters,
171
+ convertCustomTypes,
172
+ lockMode,
173
+ strategy,
174
+ populateWhere,
175
+ connectionType,
176
+ logging,
167
177
  fields: fields,
168
178
  populate: [],
169
179
  });
@@ -260,7 +270,8 @@ export class EntityLoader {
260
270
  entity[field].hydrate(items, true, partial);
261
271
  }
262
272
  }
263
- else { // owning side of M:N without pivot table needs to be reordered
273
+ else {
274
+ // owning side of M:N without pivot table needs to be reordered
264
275
  for (const entity of filtered) {
265
276
  const order = !customOrder ? [...entity[prop.name].getItems(false)] : []; // copy order of references
266
277
  const items = children.filter(child => entity[prop.name].contains(child, false));
@@ -301,7 +312,7 @@ export class EntityLoader {
301
312
  if (!schema && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind)) {
302
313
  schema = children.find(e => e.__helper.__schema)?.__helper.__schema;
303
314
  }
304
- const ids = Utils.unique(children.map(e => prop.targetKey ? e[prop.targetKey] : e.__helper.getPrimaryKey()));
315
+ const ids = Utils.unique(children.map(e => (prop.targetKey ? e[prop.targetKey] : e.__helper.getPrimaryKey())));
305
316
  let where;
306
317
  if (polymorphicOwnerProp && Array.isArray(fk)) {
307
318
  const conditions = ids.map(id => {
@@ -315,7 +326,8 @@ export class EntityLoader {
315
326
  }
316
327
  if (polymorphicOwnerProp) {
317
328
  const parentMeta = this.metadata.find(entities[0].constructor);
318
- const discriminatorValue = QueryHelper.findDiscriminatorValue(polymorphicOwnerProp.discriminatorMap, parentMeta.class) ?? parentMeta.tableName;
329
+ const discriminatorValue = QueryHelper.findDiscriminatorValue(polymorphicOwnerProp.discriminatorMap, parentMeta.class) ??
330
+ parentMeta.tableName;
319
331
  const discriminatorColumn = polymorphicOwnerProp.fieldNames[0];
320
332
  where = { $and: [where, { [discriminatorColumn]: discriminatorValue }] };
321
333
  }
@@ -331,11 +343,20 @@ export class EntityLoader {
331
343
  }
332
344
  const orderBy = QueryHelper.mergeOrderBy(options.orderBy, prop.orderBy);
333
345
  const items = await this.em.find(meta.class, where, {
334
- filters, convertCustomTypes, lockMode, populateWhere, logging,
346
+ filters,
347
+ convertCustomTypes,
348
+ lockMode,
349
+ populateWhere,
350
+ logging,
335
351
  orderBy,
336
352
  populate: populate.children ?? populate.all ?? [],
337
- exclude: Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude,
338
- strategy, fields, schema, connectionType,
353
+ exclude: Array.isArray(options.exclude)
354
+ ? Utils.extractChildElements(options.exclude, prop.name)
355
+ : options.exclude,
356
+ strategy,
357
+ fields,
358
+ schema,
359
+ connectionType,
339
360
  // @ts-ignore not a public option, will be propagated to the populate call
340
361
  refresh: refresh && !children.every(item => options.visited.has(item)),
341
362
  // @ts-ignore not a public option, will be propagated to the populate call
@@ -355,6 +376,7 @@ export class EntityLoader {
355
376
  if (!ref) {
356
377
  continue;
357
378
  }
379
+ // oxfmt-ignore
358
380
  const keyValue = '' + (Reference.isReference(ref) ? ref.unwrap()[prop.targetKey] : ref[prop.targetKey]);
359
381
  const loadedItem = itemsByKey.get(keyValue);
360
382
  if (loadedItem) {
@@ -367,7 +389,7 @@ export class EntityLoader {
367
389
  const itemsMap = new Set();
368
390
  const childrenMap = new Set();
369
391
  // Use targetKey value if set, otherwise use serialized PK
370
- const getKey = (e) => prop.targetKey ? '' + e[prop.targetKey] : helper(e).getSerializedPrimaryKey();
392
+ const getKey = (e) => (prop.targetKey ? '' + e[prop.targetKey] : helper(e).getSerializedPrimaryKey());
371
393
  for (const item of items) {
372
394
  /* v8 ignore next */
373
395
  itemsMap.add(getKey(item));
@@ -394,12 +416,16 @@ export class EntityLoader {
394
416
  return { items, partial };
395
417
  }
396
418
  mergePrimaryCondition(ids, pk, options, meta, metadata, platform) {
397
- const cond1 = QueryHelper.processWhere({ where: { [pk]: { $in: ids } }, entityName: meta.class, metadata, platform, convertCustomTypes: !options.convertCustomTypes });
419
+ const cond1 = QueryHelper.processWhere({
420
+ where: { [pk]: { $in: ids } },
421
+ entityName: meta.class,
422
+ metadata,
423
+ platform,
424
+ convertCustomTypes: !options.convertCustomTypes,
425
+ });
398
426
  const where = { ...options.where };
399
427
  Utils.dropUndefinedProperties(where);
400
- return where[pk]
401
- ? { $and: [cond1, where] }
402
- : { ...cond1, ...where };
428
+ return where[pk] ? { $and: [cond1, where] } : { ...cond1, ...where };
403
429
  }
404
430
  async populateField(entityName, entities, populate, options) {
405
431
  const field = populate.field.split(':')[0];
@@ -436,6 +462,7 @@ export class EntityLoader {
436
462
  .filter(orderBy => Utils.isObject(orderBy[prop.name]))
437
463
  .map(orderBy => orderBy[prop.name]);
438
464
  const { refresh, filters, ignoreLazyScalarProperties, populateWhere, connectionType, logging, schema } = options;
465
+ // oxfmt-ignore
439
466
  const exclude = Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude;
440
467
  const visited = options.visited;
441
468
  for (const entity of entities) {
@@ -451,7 +478,7 @@ export class EntityLoader {
451
478
  }
452
479
  const populateChildren = async (targetMeta, items) => {
453
480
  await this.populate(targetMeta.class, items, populate.children ?? populate.all, {
454
- where: await this.extractChildCondition(options, prop, false),
481
+ where: (await this.extractChildCondition(options, prop, false)),
455
482
  orderBy: innerOrderBy,
456
483
  fields,
457
484
  exclude,
@@ -489,13 +516,14 @@ export class EntityLoader {
489
516
  const refresh = options.refresh;
490
517
  let where = await this.extractChildCondition(options, prop, true);
491
518
  const fields = this.buildFields(options.fields, prop);
519
+ // oxfmt-ignore
492
520
  const exclude = Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude;
493
521
  const populateFilter = options.populateFilter?.[prop.name];
494
522
  const options2 = { ...options, fields, exclude, populateFilter };
495
523
  ['limit', 'offset', 'first', 'last', 'before', 'after', 'overfetch'].forEach(prop => delete options2[prop]);
496
- options2.populate = (populate?.children ?? []);
524
+ options2.populate = populate?.children ?? [];
497
525
  if (prop.customType) {
498
- ids.forEach((id, idx) => ids[idx] = QueryHelper.processCustomType(prop, id, this.driver.getPlatform()));
526
+ ids.forEach((id, idx) => (ids[idx] = QueryHelper.processCustomType(prop, id, this.driver.getPlatform())));
499
527
  }
500
528
  if (!Utils.isEmpty(prop.where)) {
501
529
  where = { $and: [where, prop.where] };
@@ -532,7 +560,8 @@ export class EntityLoader {
532
560
  if (where[op]) {
533
561
  const child = where[op]
534
562
  .map((cond) => cond[prop.name])
535
- .filter((sub) => sub != null && !(Utils.isPlainObject(sub) && Utils.getObjectQueryKeys(sub).every(key => Utils.isOperator(key, false))))
563
+ .filter((sub) => sub != null &&
564
+ !(Utils.isPlainObject(sub) && Utils.getObjectQueryKeys(sub).every(key => Utils.isOperator(key, false))))
536
565
  .map((cond) => {
537
566
  if (Utils.isPrimaryKey(cond)) {
538
567
  return { [pk]: cond };
@@ -603,7 +632,8 @@ export class EntityLoader {
603
632
  return a;
604
633
  }, []);
605
634
  }
606
- if (prop.kind === ReferenceKind.MANY_TO_MANY) { // inverse side
635
+ if (prop.kind === ReferenceKind.MANY_TO_MANY) {
636
+ // inverse side
607
637
  return filtered;
608
638
  }
609
639
  // MANY_TO_ONE or ONE_TO_ONE
@@ -706,7 +736,10 @@ export class EntityLoader {
706
736
  .forEach(prop => {
707
737
  const field = this.getRelationName(meta, prop);
708
738
  const prefixed = prefix ? `${prefix}.${field}` : field;
709
- const nestedPopulate = populate.filter(p => p.field === prop.name).flatMap(p => p.children).filter(Boolean);
739
+ const nestedPopulate = populate
740
+ .filter(p => p.field === prop.name)
741
+ .flatMap(p => p.children)
742
+ .filter(Boolean);
710
743
  const nested = this.lookupEagerLoadedRelationships(prop.targetMeta.class, nestedPopulate, strategy, prefixed, visited.slice(), exclude);
711
744
  if (nested.length > 0) {
712
745
  ret.push(...nested);
@@ -716,7 +749,7 @@ export class EntityLoader {
716
749
  ret.push({
717
750
  field: prefixed,
718
751
  // enforce select-in strategy for self-referencing relations
719
- strategy: selfReferencing ? LoadStrategy.SELECT_IN : strategy ?? prop.strategy,
752
+ strategy: selfReferencing ? LoadStrategy.SELECT_IN : (strategy ?? prop.strategy),
720
753
  });
721
754
  }
722
755
  });
@@ -73,7 +73,7 @@ export interface LoadReferenceOrFailOptions<T extends object, P extends string =
73
73
  /**
74
74
  * shortcut for `wrap(entity).toReference()`
75
75
  */
76
- export declare function ref<I extends unknown | Ref<unknown> | undefined | null, T extends I & {}>(entity: I): Ref<T> & LoadedReference<Loaded<T, AddEager<T>>> | AddOptional<typeof entity>;
76
+ export declare function ref<I extends unknown | Ref<unknown> | undefined | null, T extends I & {}>(entity: I): (Ref<T> & LoadedReference<Loaded<T, AddEager<T>>>) | AddOptional<typeof entity>;
77
77
  /**
78
78
  * shortcut for `Reference.createFromPK(entityType, pk)`
79
79
  */