@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
@@ -50,17 +50,21 @@ export class QueryHelper {
50
50
  }
51
51
  const keys = Object.keys(where);
52
52
  const groupOperator = keys.find(k => {
53
- return k in GroupOperator && Array.isArray(where[k]) && where[k].every(cond => {
54
- return Utils.isPlainObject(cond) && Object.keys(cond).every(k2 => {
55
- if (Utils.isOperator(k2, false)) {
56
- if (k2 === '$not') {
57
- return Object.keys(cond[k2]).every(k3 => meta.primaryKeys.includes(k3));
58
- }
59
- return true;
60
- }
61
- return meta.primaryKeys.includes(k2);
62
- });
63
- });
53
+ return (k in GroupOperator &&
54
+ Array.isArray(where[k]) &&
55
+ where[k].every(cond => {
56
+ return (Utils.isPlainObject(cond) &&
57
+ Object.keys(cond).every(k2 => {
58
+ if (Utils.isOperator(k2, false)) {
59
+ if (k2 === '$not') {
60
+ return Object.keys(cond[k2]).every(k3 => meta.primaryKeys.includes(k3));
61
+ }
62
+ /* v8 ignore next */
63
+ return true;
64
+ }
65
+ return meta.primaryKeys.includes(k2);
66
+ }));
67
+ }));
64
68
  });
65
69
  if (groupOperator) {
66
70
  return groupOperator;
@@ -96,15 +100,21 @@ export class QueryHelper {
96
100
  return false;
97
101
  }
98
102
  if (meta.primaryKeys.every(pk => pk in where) && Utils.getObjectKeysSize(where) === meta.primaryKeys.length) {
99
- return !!key && !GroupOperator[key] && key !== '$not' && Object.keys(where).every(k => !Utils.isPlainObject(where[k]) || Object.keys(where[k]).every(v => {
100
- if (Utils.isOperator(v, false)) {
101
- return true;
102
- }
103
- if (meta.properties[k].primary && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(meta.properties[k].kind)) {
104
- return this.inlinePrimaryKeyObjects(where[k], meta.properties[k].targetMeta, metadata, v);
105
- }
106
- return true;
107
- }));
103
+ return (!!key &&
104
+ !GroupOperator[key] &&
105
+ key !== '$not' &&
106
+ Object.keys(where).every(k => !Utils.isPlainObject(where[k]) ||
107
+ Object.keys(where[k]).every(v => {
108
+ if (Utils.isOperator(v, false)) {
109
+ return true;
110
+ }
111
+ if (meta.properties[k].primary &&
112
+ [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(meta.properties[k].kind)) {
113
+ return this.inlinePrimaryKeyObjects(where[k], meta.properties[k].targetMeta, metadata, v);
114
+ }
115
+ /* v8 ignore next */
116
+ return true;
117
+ })));
108
118
  }
109
119
  Object.keys(where).forEach(k => {
110
120
  const meta2 = metadata.find(meta.properties[k]?.targetMeta?.class) || meta;
@@ -139,7 +149,9 @@ export class QueryHelper {
139
149
  let cond = { [rootPrimaryKey]: { $in: where } };
140
150
  // @ts-ignore
141
151
  // detect tuple comparison, use `$or` in case the number of constituents don't match
142
- if (meta && !where.every(c => Utils.isPrimaryKey(c) || (Array.isArray(c) && c.length === meta.primaryKeys.length && c.every(i => Utils.isPrimaryKey(i))))) {
152
+ if (meta &&
153
+ !where.every(c => Utils.isPrimaryKey(c) ||
154
+ (Array.isArray(c) && c.length === meta.primaryKeys.length && c.every(i => Utils.isPrimaryKey(i))))) {
143
155
  cond = { $or: where };
144
156
  }
145
157
  return QueryHelper.processWhere({ ...options, where: cond, root: false });
@@ -170,10 +182,12 @@ export class QueryHelper {
170
182
  if (prop?.customType && convertCustomTypes && !isRaw(value)) {
171
183
  value = QueryHelper.processCustomType(prop, value, platform, undefined, true);
172
184
  }
185
+ // oxfmt-ignore
173
186
  const isJsonProperty = prop?.customType instanceof JsonType && Utils.isPlainObject(value) && !isRaw(value) && Object.keys(value)[0] !== '$eq';
174
187
  if (isJsonProperty && prop?.kind !== ReferenceKind.EMBEDDED) {
175
188
  return this.processJsonCondition(o, value, [prop.fieldNames[0]], platform, aliased);
176
189
  }
190
+ // oxfmt-ignore
177
191
  if (Array.isArray(value) && !Utils.isOperator(key) && !QueryHelper.isSupportedOperator(key) && !(customExpression && Raw.getKnownFragment(key).params.length > 0) && options.type !== 'orderBy') {
178
192
  // comparing single composite key - use $eq instead of $in
179
193
  const op = composite && !value.every(v => Array.isArray(v)) ? '$eq' : '$in';
@@ -200,10 +214,10 @@ export class QueryHelper {
200
214
  }
201
215
  const opts = {};
202
216
  if (Array.isArray(options)) {
203
- options.forEach(filter => opts[filter] = true);
217
+ options.forEach(filter => (opts[filter] = true));
204
218
  }
205
219
  else if (Utils.isPlainObject(options)) {
206
- Object.keys(options).forEach(filter => opts[filter] = options[filter]);
220
+ Object.keys(options).forEach(filter => (opts[filter] = options[filter]));
207
221
  }
208
222
  return Object.keys(filters)
209
223
  .filter(f => QueryHelper.isFilterActive(meta, f, filters[f], opts))
@@ -252,9 +266,7 @@ export class QueryHelper {
252
266
  }, {});
253
267
  }
254
268
  if (key && JSON_KEY_OPERATORS.includes(key)) {
255
- return Array.isArray(cond)
256
- ? platform.marshallArray(cond)
257
- : cond;
269
+ return Array.isArray(cond) ? platform.marshallArray(cond) : cond;
258
270
  }
259
271
  if (Array.isArray(cond) && !(key && ARRAY_OPERATORS.includes(key))) {
260
272
  return cond.map(v => QueryHelper.processCustomType(prop, v, platform, key, fromQuery));
@@ -39,7 +39,8 @@ export class RawQueryFragment {
39
39
  return typeof key === 'symbol' && this.#rawQueryReferences.has(key);
40
40
  }
41
41
  static hasObjectFragments(object) {
42
- return Utils.isPlainObject(object) && Object.getOwnPropertySymbols(object).some(symbol => this.isKnownFragmentSymbol(symbol));
42
+ return (Utils.isPlainObject(object) &&
43
+ Object.getOwnPropertySymbols(object).some(symbol => this.isKnownFragmentSymbol(symbol)));
43
44
  }
44
45
  static isKnownFragment(key) {
45
46
  if (key instanceof RawQueryFragment) {
@@ -181,7 +182,7 @@ export function createSqlFunction(func, key) {
181
182
  if (typeof key === 'string') {
182
183
  return raw(`${func}(${key})`);
183
184
  }
184
- return raw(a => `${func}(${(key(a))})`);
185
+ return raw(a => `${func}(${key(a)})`);
185
186
  }
186
187
  sql.ref = (...keys) => raw('??', [keys.join('.')]);
187
188
  sql.now = (length) => raw('current_timestamp' + (length == null ? '' : `(${length})`));
@@ -183,7 +183,8 @@ export class TransactionManager {
183
183
  registerDeletionHandler(fork, parent) {
184
184
  fork.getEventManager().registerSubscriber({
185
185
  afterFlush: (args) => {
186
- const deletionChangeSets = args.uow.getChangeSets()
186
+ const deletionChangeSets = args.uow
187
+ .getChangeSets()
187
188
  .filter(cs => cs.type === ChangeSetType.DELETE || cs.type === ChangeSetType.DELETE_EARLY);
188
189
  for (const cs of deletionChangeSets) {
189
190
  parent.getUnitOfWork(false).unsetIdentity(cs.entity);
package/utils/Utils.d.ts CHANGED
@@ -147,7 +147,7 @@ export declare class Utils {
147
147
  static callCompiledFunction<T extends unknown[], R>(fn: (...args: T) => R, ...args: T): R;
148
148
  static unwrapProperty<T>(entity: T, meta: EntityMetadata<T>, prop: EntityProperty<T>, payload?: boolean): [unknown, number[]][];
149
149
  static setPayloadProperty<T>(entity: EntityDictionary<T>, meta: EntityMetadata<T>, prop: EntityProperty<T>, value: unknown, idx: number[]): void;
150
- static tryImport<T extends Dictionary = any>({ module, warning }: {
150
+ static tryImport<T extends Dictionary = any>({ module, warning, }: {
151
151
  module: string;
152
152
  warning?: string;
153
153
  }): Promise<T | undefined>;
package/utils/Utils.js CHANGED
@@ -25,7 +25,7 @@ export function compareObjects(a, b) {
25
25
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
26
26
  return a.sql === b.sql && compareArrays(a.params, b.params);
27
27
  }
28
- if ((a instanceof Date && b instanceof Date)) {
28
+ if (a instanceof Date && b instanceof Date) {
29
29
  const timeA = a.getTime();
30
30
  const timeB = b.getTime();
31
31
  if (isNaN(timeA) || isNaN(timeB)) {
@@ -123,7 +123,7 @@ export function parseJsonSafe(value) {
123
123
  }
124
124
  export class Utils {
125
125
  static PK_SEPARATOR = '~~~';
126
- static #ORM_VERSION = '7.0.0-rc.2';
126
+ static #ORM_VERSION = '7.0.0-rc.3';
127
127
  /**
128
128
  * Checks if the argument is instance of `Object`. Returns false for arrays.
129
129
  */
@@ -305,7 +305,7 @@ export class Utils {
305
305
  .split(',')
306
306
  .map(s => s.trim().replace(/=.*$/, '').trim())
307
307
  .filter(Boolean)
308
- .map(raw => raw.startsWith('{') && raw.endsWith('}') ? '' : raw);
308
+ .map(raw => (raw.startsWith('{') && raw.endsWith('}') ? '' : raw));
309
309
  }
310
310
  /**
311
311
  * Checks whether the argument looks like primary key (string, number or ObjectId).
@@ -374,7 +374,8 @@ export class Utils {
374
374
  return Utils.getPrimaryKeyHash(pks);
375
375
  }
376
376
  static getPrimaryKeyHash(pks) {
377
- return pks.map(pk => {
377
+ return pks
378
+ .map(pk => {
378
379
  if (Buffer.isBuffer(pk)) {
379
380
  return pk.toString('hex');
380
381
  }
@@ -382,7 +383,8 @@ export class Utils {
382
383
  return pk.toISOString();
383
384
  }
384
385
  return pk;
385
- }).join(this.PK_SEPARATOR);
386
+ })
387
+ .join(this.PK_SEPARATOR);
386
388
  }
387
389
  static splitPrimaryKeys(key) {
388
390
  return key.split(this.PK_SEPARATOR);
@@ -419,7 +421,7 @@ export class Utils {
419
421
  }
420
422
  if (allowScalar) {
421
423
  if (Utils.isPlainObject(pk)) {
422
- return pk[(meta.primaryKeys)[0]];
424
+ return pk[meta.primaryKeys[0]];
423
425
  }
424
426
  return pk;
425
427
  }
@@ -527,7 +529,7 @@ export class Utils {
527
529
  static extractChildElements(items, prefix, allSymbol) {
528
530
  return items
529
531
  .filter(field => field === allSymbol || field.startsWith(`${prefix}.`))
530
- .map(field => field === allSymbol ? allSymbol : field.substring(prefix.length + 1));
532
+ .map(field => (field === allSymbol ? allSymbol : field.substring(prefix.length + 1)));
531
533
  }
532
534
  /**
533
535
  * Tries to detect TypeScript support.
@@ -536,17 +538,17 @@ export class Utils {
536
538
  /* v8 ignore next */
537
539
  const process = globalThis.process ?? {};
538
540
  /* v8 ignore next */
539
- return process.argv?.[0]?.endsWith('ts-node') // running via ts-node directly
540
- || !!process.env?.MIKRO_ORM_CLI_ALWAYS_ALLOW_TS // forced explicitly or enabled via `registerTypeScriptSupport()`
541
- || !!process.env?.TS_JEST // check if ts-jest is used
542
- || !!process.env?.VITEST // check if vitest is used
543
- || !!process.versions?.bun // check if bun is used
544
- || process.argv?.slice(1).some(arg => arg.match(/\.([mc]?ts|tsx)$/)) // executing `.ts` file
545
- || process.execArgv?.some(arg => {
546
- return arg.includes('ts-node') // check for ts-node loader
547
- || arg.includes('@swc-node/register') // check for swc-node/register loader
548
- || arg.includes('node_modules/tsx/'); // check for tsx loader
549
- });
541
+ return (process.argv?.[0]?.endsWith('ts-node') || // running via ts-node directly
542
+ !!process.env?.MIKRO_ORM_CLI_ALWAYS_ALLOW_TS || // forced explicitly or enabled via `registerTypeScriptSupport()`
543
+ !!process.env?.TS_JEST || // check if ts-jest is used
544
+ !!process.env?.VITEST || // check if vitest is used
545
+ !!process.versions?.bun || // check if bun is used
546
+ process.argv?.slice(1).some(arg => arg.match(/\.([mc]?ts|tsx)$/)) || // executing `.ts` file
547
+ process.execArgv?.some(arg => {
548
+ return (arg.includes('ts-node') || // check for ts-node loader
549
+ arg.includes('@swc-node/register') || // check for swc-node/register loader
550
+ arg.includes('node_modules/tsx/')); // check for tsx loader
551
+ }));
550
552
  }
551
553
  /**
552
554
  * Gets the type of the argument.
@@ -567,12 +569,13 @@ export class Utils {
567
569
  * Checks whether the value is POJO (e.g. `{ foo: 'bar' }`, and not instance of `Foo`)
568
570
  */
569
571
  static isPlainObject(value) {
570
- return (value !== null
571
- && typeof value === 'object'
572
- && typeof value.constructor === 'function'
573
- && (Object.hasOwn(value.constructor.prototype, 'isPrototypeOf') || Object.getPrototypeOf(value.constructor.prototype) === null))
574
- || (value && Object.getPrototypeOf(value) === null)
575
- || value instanceof PlainObject;
572
+ return ((value !== null &&
573
+ typeof value === 'object' &&
574
+ typeof value.constructor === 'function' &&
575
+ (Object.hasOwn(value.constructor.prototype, 'isPrototypeOf') ||
576
+ Object.getPrototypeOf(value.constructor.prototype) === null)) ||
577
+ (value && Object.getPrototypeOf(value) === null) ||
578
+ value instanceof PlainObject);
576
579
  }
577
580
  /**
578
581
  * Executes the `cb` promise serially on every element of the `items` array and returns array of resolved values.
@@ -633,17 +636,20 @@ export class Utils {
633
636
  const keys = Object.keys(target);
634
637
  const values = Object.values(target);
635
638
  const numeric = !!values.find(v => typeof v === 'number');
636
- const constEnum = values.length % 2 === 0 // const enum will have even number of items
637
- && values.slice(0, values.length / 2).every(v => typeof v === 'string') // first half are strings
638
- && values.slice(values.length / 2).every(v => typeof v === 'number') // second half are numbers
639
- && this.equals(keys, values.slice(values.length / 2).concat(values.slice(0, values.length / 2)).map(v => '' + v)); // and when swapped, it will match the keys
639
+ const constEnum = values.length % 2 === 0 && // const enum will have even number of items
640
+ values.slice(0, values.length / 2).every(v => typeof v === 'string') && // first half are strings
641
+ values.slice(values.length / 2).every(v => typeof v === 'number') && // second half are numbers
642
+ this.equals(keys, values
643
+ .slice(values.length / 2)
644
+ .concat(values.slice(0, values.length / 2))
645
+ .map(v => '' + v)); // and when swapped, it will match the keys
640
646
  if (numeric || constEnum) {
641
647
  return values.filter(val => !keys.includes(val));
642
648
  }
643
649
  return values;
644
650
  }
645
651
  static flatten(arrays, deep) {
646
- return arrays.flatMap(v => deep && Array.isArray(v) ? this.flatten(v, true) : v);
652
+ return arrays.flatMap(v => (deep && Array.isArray(v) ? this.flatten(v, true) : v));
647
653
  }
648
654
  static isOperator(key, includeGroupOperators = true) {
649
655
  if (!includeGroupOperators) {
@@ -784,7 +790,7 @@ export class Utils {
784
790
  }
785
791
  }
786
792
  }
787
- static async tryImport({ module, warning }) {
793
+ static async tryImport({ module, warning, }) {
788
794
  try {
789
795
  return await import(module);
790
796
  }
package/utils/env-vars.js CHANGED
@@ -13,10 +13,11 @@ export function getEnv(key) {
13
13
  export function loadEnvironmentVars() {
14
14
  const ret = {};
15
15
  const getEnvKey = (key, envPrefix = 'MIKRO_ORM_') => {
16
- return envPrefix + key
17
- .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
18
- .replace(/([A-Z])([A-Z][a-z])/g, '$1_$2')
19
- .toUpperCase();
16
+ return (envPrefix +
17
+ key
18
+ .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
19
+ .replace(/([A-Z])([A-Z][a-z])/g, '$1_$2')
20
+ .toUpperCase());
20
21
  };
21
22
  const array = (v) => v.split(',').map(vv => vv.trim());
22
23
  const bool = (v) => ['true', 't', '1'].includes(v.toLowerCase());
@@ -28,7 +29,7 @@ export function loadEnvironmentVars() {
28
29
  o[key] = mapper(getEnv(envKey));
29
30
  }
30
31
  };
31
- const cleanup = (o, k) => Utils.hasObjectKeys(o[k]) ? {} : delete o[k];
32
+ const cleanup = (o, k) => (Utils.hasObjectKeys(o[k]) ? {} : delete o[k]);
32
33
  const read0 = read.bind(null, ret, 'MIKRO_ORM_');
33
34
  read0('baseDir');
34
35
  read0('entities', array);
package/utils/fs-utils.js CHANGED
@@ -95,10 +95,7 @@ export const fs = {
95
95
  },
96
96
  getORMPackages() {
97
97
  const pkg = this.getPackageConfig();
98
- return new Set([
99
- ...Object.keys(pkg.dependencies ?? {}),
100
- ...Object.keys(pkg.devDependencies ?? {}),
101
- ]);
98
+ return new Set([...Object.keys(pkg.dependencies ?? {}), ...Object.keys(pkg.devDependencies ?? {})]);
102
99
  },
103
100
  getORMPackageVersion(name) {
104
101
  try {
@@ -153,7 +150,7 @@ export const fs = {
153
150
  }
154
151
  let path = parts.join('/').replace(/\\/g, '/').replace(/\/$/, '');
155
152
  path = normalize(path).replace(/\\/g, '/');
156
- return (path.match(/^[/.]|[a-zA-Z]:/) || path.startsWith('!')) ? path : './' + path;
153
+ return path.match(/^[/.]|[a-zA-Z]:/) || path.startsWith('!') ? path : './' + path;
157
154
  },
158
155
  /**
159
156
  * Determines the relative path between two paths. If either path is a `file:` URL,
@@ -73,7 +73,8 @@ export function getOnConflictReturningFields(meta, data, uniqueFields, options)
73
73
  if (!meta) {
74
74
  return '*';
75
75
  }
76
- const keys = meta.comparableProps.filter(p => {
76
+ const keys = meta.comparableProps
77
+ .filter(p => {
77
78
  if (p.lazy || p.embeddable) {
78
79
  return false;
79
80
  }
@@ -81,7 +82,8 @@ export function getOnConflictReturningFields(meta, data, uniqueFields, options)
81
82
  return true;
82
83
  }
83
84
  return Array.isArray(uniqueFields) && !uniqueFields.includes(p.name);
84
- }).map(p => p.name);
85
+ })
86
+ .map(p => p.name);
85
87
  if (meta.versionProperty) {
86
88
  keys.push(meta.versionProperty);
87
89
  }
@@ -113,7 +115,8 @@ function getPropertyValue(obj, key) {
113
115
  /** @internal */
114
116
  export function getWhereCondition(meta, onConflictFields, data, where) {
115
117
  const unique = onConflictFields ?? meta.props.filter(p => p.unique).map(p => p.name);
116
- const propIndex = !isRaw(unique) && unique.findIndex(p => data[p] ?? data[p.substring(0, p.indexOf('.'))] != null);
118
+ const propIndex = !isRaw(unique) &&
119
+ unique.findIndex(p => data[p] ?? data[p.substring(0, p.indexOf('.'))] != null);
117
120
  if (onConflictFields || where == null) {
118
121
  if (propIndex !== false && propIndex >= 0) {
119
122
  let key = unique[propIndex];