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

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 (114) hide show
  1. package/EntityManager.d.ts +4 -16
  2. package/EntityManager.js +248 -181
  3. package/MikroORM.d.ts +4 -6
  4. package/MikroORM.js +24 -24
  5. package/README.md +5 -4
  6. package/cache/FileCacheAdapter.d.ts +1 -5
  7. package/cache/FileCacheAdapter.js +22 -24
  8. package/cache/GeneratedCacheAdapter.d.ts +1 -1
  9. package/cache/GeneratedCacheAdapter.js +6 -6
  10. package/cache/MemoryCacheAdapter.d.ts +1 -2
  11. package/cache/MemoryCacheAdapter.js +8 -8
  12. package/cache/index.d.ts +1 -1
  13. package/cache/index.js +0 -1
  14. package/connections/Connection.d.ts +1 -0
  15. package/connections/Connection.js +43 -14
  16. package/drivers/DatabaseDriver.d.ts +0 -2
  17. package/drivers/DatabaseDriver.js +28 -12
  18. package/drivers/IDatabaseDriver.d.ts +43 -0
  19. package/entity/Collection.d.ts +1 -9
  20. package/entity/Collection.js +124 -108
  21. package/entity/EntityAssigner.js +23 -11
  22. package/entity/EntityFactory.d.ts +1 -8
  23. package/entity/EntityFactory.js +79 -59
  24. package/entity/EntityHelper.js +25 -16
  25. package/entity/EntityLoader.d.ts +1 -3
  26. package/entity/EntityLoader.js +90 -60
  27. package/entity/Reference.d.ts +2 -3
  28. package/entity/Reference.js +48 -19
  29. package/entity/WrappedEntity.d.ts +4 -2
  30. package/entity/WrappedEntity.js +5 -1
  31. package/entity/defineEntity.d.ts +42 -85
  32. package/entity/utils.js +28 -26
  33. package/entity/validators.js +2 -1
  34. package/enums.d.ts +2 -1
  35. package/enums.js +13 -17
  36. package/errors.d.ts +11 -11
  37. package/errors.js +8 -8
  38. package/events/EventManager.d.ts +1 -4
  39. package/events/EventManager.js +26 -23
  40. package/events/index.d.ts +1 -1
  41. package/events/index.js +0 -1
  42. package/exceptions.js +9 -2
  43. package/hydration/ObjectHydrator.d.ts +1 -2
  44. package/hydration/ObjectHydrator.js +41 -27
  45. package/index.d.ts +1 -1
  46. package/index.js +1 -1
  47. package/logging/DefaultLogger.js +6 -7
  48. package/logging/Logger.d.ts +2 -1
  49. package/logging/colors.js +2 -5
  50. package/logging/index.d.ts +1 -1
  51. package/logging/index.js +0 -1
  52. package/metadata/EntitySchema.d.ts +3 -3
  53. package/metadata/EntitySchema.js +12 -2
  54. package/metadata/MetadataDiscovery.d.ts +1 -9
  55. package/metadata/MetadataDiscovery.js +251 -179
  56. package/metadata/MetadataProvider.js +26 -1
  57. package/metadata/MetadataStorage.d.ts +1 -5
  58. package/metadata/MetadataStorage.js +37 -39
  59. package/metadata/MetadataValidator.js +20 -5
  60. package/metadata/discover-entities.js +1 -1
  61. package/metadata/index.d.ts +1 -1
  62. package/metadata/index.js +0 -1
  63. package/metadata/types.d.ts +2 -2
  64. package/naming-strategy/AbstractNamingStrategy.js +6 -3
  65. package/naming-strategy/EntityCaseNamingStrategy.js +1 -1
  66. package/naming-strategy/index.d.ts +1 -1
  67. package/naming-strategy/index.js +0 -1
  68. package/not-supported.js +5 -1
  69. package/package.json +38 -38
  70. package/platforms/Platform.d.ts +24 -1
  71. package/platforms/Platform.js +106 -27
  72. package/serialization/EntitySerializer.js +8 -4
  73. package/serialization/EntityTransformer.js +4 -1
  74. package/serialization/SerializationContext.d.ts +4 -8
  75. package/serialization/SerializationContext.js +21 -16
  76. package/types/UuidType.d.ts +2 -0
  77. package/types/UuidType.js +14 -2
  78. package/types/index.d.ts +2 -1
  79. package/typings.d.ts +35 -24
  80. package/typings.js +9 -9
  81. package/unit-of-work/ChangeSet.js +4 -4
  82. package/unit-of-work/ChangeSetComputer.d.ts +1 -6
  83. package/unit-of-work/ChangeSetComputer.js +29 -27
  84. package/unit-of-work/ChangeSetPersister.d.ts +1 -9
  85. package/unit-of-work/ChangeSetPersister.js +63 -58
  86. package/unit-of-work/CommitOrderCalculator.d.ts +1 -4
  87. package/unit-of-work/CommitOrderCalculator.js +17 -15
  88. package/unit-of-work/IdentityMap.d.ts +2 -5
  89. package/unit-of-work/IdentityMap.js +18 -18
  90. package/unit-of-work/UnitOfWork.d.ts +12 -20
  91. package/unit-of-work/UnitOfWork.js +228 -191
  92. package/utils/AbstractMigrator.d.ts +2 -2
  93. package/utils/AbstractMigrator.js +10 -12
  94. package/utils/AbstractSchemaGenerator.js +2 -1
  95. package/utils/AsyncContext.js +1 -1
  96. package/utils/Configuration.d.ts +90 -189
  97. package/utils/Configuration.js +97 -77
  98. package/utils/Cursor.d.ts +3 -3
  99. package/utils/Cursor.js +8 -6
  100. package/utils/DataloaderUtils.js +15 -12
  101. package/utils/EntityComparator.d.ts +8 -15
  102. package/utils/EntityComparator.js +100 -92
  103. package/utils/QueryHelper.d.ts +16 -1
  104. package/utils/QueryHelper.js +108 -50
  105. package/utils/RawQueryFragment.d.ts +4 -4
  106. package/utils/RawQueryFragment.js +3 -2
  107. package/utils/TransactionManager.js +3 -3
  108. package/utils/Utils.d.ts +2 -2
  109. package/utils/Utils.js +39 -32
  110. package/utils/clone.js +5 -0
  111. package/utils/env-vars.js +6 -5
  112. package/utils/fs-utils.d.ts +3 -17
  113. package/utils/fs-utils.js +2 -5
  114. package/utils/upsert-utils.js +7 -4
@@ -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;
@@ -123,6 +133,9 @@ export class QueryHelper {
123
133
  QueryHelper.liftGroupOperators(where, meta, metadata);
124
134
  QueryHelper.inlinePrimaryKeyObjects(where, meta, metadata);
125
135
  }
136
+ if (meta && root) {
137
+ QueryHelper.convertCompositeEntityRefs(where, meta);
138
+ }
126
139
  if (platform.getConfig().get('ignoreUndefinedInQuery') && where && typeof where === 'object') {
127
140
  Utils.dropUndefinedProperties(where);
128
141
  }
@@ -139,7 +152,9 @@ export class QueryHelper {
139
152
  let cond = { [rootPrimaryKey]: { $in: where } };
140
153
  // @ts-ignore
141
154
  // 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))))) {
155
+ if (meta &&
156
+ !where.every(c => Utils.isPrimaryKey(c) ||
157
+ (Array.isArray(c) && c.length === meta.primaryKeys.length && c.every(i => Utils.isPrimaryKey(i))))) {
143
158
  cond = { $or: where };
144
159
  }
145
160
  return QueryHelper.processWhere({ ...options, where: cond, root: false });
@@ -170,10 +185,12 @@ export class QueryHelper {
170
185
  if (prop?.customType && convertCustomTypes && !isRaw(value)) {
171
186
  value = QueryHelper.processCustomType(prop, value, platform, undefined, true);
172
187
  }
173
- const isJsonProperty = prop?.customType instanceof JsonType && Utils.isPlainObject(value) && !isRaw(value) && Object.keys(value)[0] !== '$eq';
188
+ // oxfmt-ignore
189
+ const isJsonProperty = prop?.customType instanceof JsonType && !isRaw(value) && (Utils.isPlainObject(value) ? !['$eq', '$elemMatch'].includes(Object.keys(value)[0]) : !Array.isArray(value));
174
190
  if (isJsonProperty && prop?.kind !== ReferenceKind.EMBEDDED) {
175
191
  return this.processJsonCondition(o, value, [prop.fieldNames[0]], platform, aliased);
176
192
  }
193
+ // oxfmt-ignore
177
194
  if (Array.isArray(value) && !Utils.isOperator(key) && !QueryHelper.isSupportedOperator(key) && !(customExpression && Raw.getKnownFragment(key).params.length > 0) && options.type !== 'orderBy') {
178
195
  // comparing single composite key - use $eq instead of $in
179
196
  const op = composite && !value.every(v => Array.isArray(v)) ? '$eq' : '$in';
@@ -200,10 +217,10 @@ export class QueryHelper {
200
217
  }
201
218
  const opts = {};
202
219
  if (Array.isArray(options)) {
203
- options.forEach(filter => opts[filter] = true);
220
+ options.forEach(filter => (opts[filter] = true));
204
221
  }
205
222
  else if (Utils.isPlainObject(options)) {
206
- Object.keys(options).forEach(filter => opts[filter] = options[filter]);
223
+ Object.keys(options).forEach(filter => (opts[filter] = options[filter]));
207
224
  }
208
225
  return Object.keys(filters)
209
226
  .filter(f => QueryHelper.isFilterActive(meta, f, filters[f], opts))
@@ -252,9 +269,7 @@ export class QueryHelper {
252
269
  }, {});
253
270
  }
254
271
  if (key && JSON_KEY_OPERATORS.includes(key)) {
255
- return Array.isArray(cond)
256
- ? platform.marshallArray(cond)
257
- : cond;
272
+ return Array.isArray(cond) ? platform.marshallArray(cond) : cond;
258
273
  }
259
274
  if (Array.isArray(cond) && !(key && ARRAY_OPERATORS.includes(key))) {
260
275
  return cond.map(v => QueryHelper.processCustomType(prop, v, platform, key, fromQuery));
@@ -268,29 +283,7 @@ export class QueryHelper {
268
283
  return !!QueryHelper.SUPPORTED_OPERATORS.find(op => key === op);
269
284
  }
270
285
  static processJsonCondition(o, value, path, platform, alias) {
271
- if (Utils.isPlainObject(value) && !Object.keys(value).some(k => Utils.isOperator(k))) {
272
- Utils.keys(value).forEach(k => {
273
- this.processJsonCondition(o, value[k], [...path, k], platform, alias);
274
- });
275
- return o;
276
- }
277
- if (path.length === 1) {
278
- o[path[0]] = value;
279
- return o;
280
- }
281
- const type = this.getValueType(value);
282
- const k = platform.getSearchJsonPropertyKey(path, type, alias, value);
283
- o[k] = value;
284
- return o;
285
- }
286
- static getValueType(value) {
287
- if (Array.isArray(value)) {
288
- return typeof value[0];
289
- }
290
- if (Utils.isPlainObject(value) && Object.keys(value).every(k => Utils.isOperator(k))) {
291
- return this.getValueType(Object.values(value)[0]);
292
- }
293
- return typeof value;
286
+ return platform.processJsonCondition(o, value, path, alias);
294
287
  }
295
288
  static findProperty(fieldName, options) {
296
289
  const parts = fieldName.split('.');
@@ -300,6 +293,71 @@ export class QueryHelper {
300
293
  const meta = entityName ? options.metadata.find(entityName) : undefined;
301
294
  return meta?.properties[propName];
302
295
  }
296
+ /**
297
+ * Converts entity references for composite FK properties into flat arrays
298
+ * of correctly-ordered join column values, before processParams flattens them
299
+ * incorrectly due to shared FK columns.
300
+ */
301
+ static convertCompositeEntityRefs(where, meta) {
302
+ if (!Utils.isPlainObject(where)) {
303
+ return;
304
+ }
305
+ for (const k of Object.keys(where)) {
306
+ if (k in GroupOperator) {
307
+ if (Array.isArray(where[k])) {
308
+ where[k].forEach((sub) => this.convertCompositeEntityRefs(sub, meta));
309
+ }
310
+ continue;
311
+ }
312
+ if (k === '$not') {
313
+ this.convertCompositeEntityRefs(where[k], meta);
314
+ continue;
315
+ }
316
+ const prop = meta.properties[k];
317
+ if (!prop?.joinColumns || prop.joinColumns.length <= 1) {
318
+ continue;
319
+ }
320
+ const w = where[k];
321
+ if (Utils.isEntity(w)) {
322
+ where[k] = this.extractJoinColumnValues(w, prop);
323
+ }
324
+ else if (Utils.isPlainObject(w)) {
325
+ for (const op of Object.keys(w)) {
326
+ if (Utils.isOperator(op, false) && Array.isArray(w[op])) {
327
+ w[op] = w[op].map((item) => Utils.isEntity(item) ? this.extractJoinColumnValues(item, prop) : item);
328
+ }
329
+ }
330
+ }
331
+ }
332
+ }
333
+ /**
334
+ * Extracts values for a FK's join columns from an entity by traversing the FK chain.
335
+ * Handles shared FK columns (e.g., tenant_id referenced by multiple FKs) correctly.
336
+ */
337
+ static extractJoinColumnValues(entity, prop) {
338
+ return prop.referencedColumnNames.map(refCol => {
339
+ return this.extractColumnValue(entity, prop.targetMeta, refCol);
340
+ });
341
+ }
342
+ /**
343
+ * Extracts the value for a specific column from an entity by finding which PK property
344
+ * owns that column and recursively traversing FK references.
345
+ */
346
+ static extractColumnValue(entity, meta, columnName) {
347
+ for (const pk of meta.primaryKeys) {
348
+ const pkProp = meta.properties[pk];
349
+ const colIdx = pkProp.fieldNames.indexOf(columnName);
350
+ if (colIdx !== -1) {
351
+ const value = entity[pk];
352
+ if (pkProp.targetMeta && Utils.isEntity(value, true)) {
353
+ const refCol = pkProp.referencedColumnNames[colIdx];
354
+ return this.extractColumnValue(value, pkProp.targetMeta, refCol);
355
+ }
356
+ return value;
357
+ }
358
+ }
359
+ return null;
360
+ }
303
361
  /**
304
362
  * Merges multiple orderBy sources with key-level deduplication (first-seen key wins).
305
363
  * RawQueryFragment symbol keys are never deduped (each is unique).
@@ -19,7 +19,7 @@ export declare class RawQueryFragment<Alias extends string = string> {
19
19
  static isKnownFragmentSymbol(key: unknown): key is RawQueryFragmentSymbol;
20
20
  static hasObjectFragments(object: unknown): boolean;
21
21
  static isKnownFragment(key: unknown): key is RawQueryFragment | symbol;
22
- static getKnownFragment(key: unknown): RawQueryFragment<any> | undefined;
22
+ static getKnownFragment(key: unknown): RawQueryFragment | undefined;
23
23
  }
24
24
  export { RawQueryFragment as Raw };
25
25
  export declare function isRaw(value: unknown): value is RawQueryFragment;
@@ -102,8 +102,8 @@ export declare function raw<R = RawQueryFragment & symbol, T extends object = an
102
102
  */
103
103
  export declare function sql<R = RawQueryFragment & symbol>(sql: readonly string[], ...values: unknown[]): R;
104
104
  export declare namespace sql {
105
- var ref: <T extends object = any>(...keys: string[]) => RawQueryFragment<string> & symbol;
106
- var now: (length?: number) => RawQueryFragment<string> & symbol;
105
+ var ref: <T extends object = any>(...keys: string[]) => RawQueryFragment & symbol;
106
+ var now: (length?: number) => RawQueryFragment & symbol;
107
107
  var lower: <R = RawQueryFragment<string> & symbol, T extends object = any>(key: string | ((alias: string) => string)) => R;
108
108
  var upper: <R = RawQueryFragment<string> & symbol, T extends object = any>(key: string | ((alias: string) => string)) => R;
109
109
  }
@@ -123,4 +123,4 @@ export declare function createSqlFunction<R = RawQueryFragment & symbol, T exten
123
123
  */
124
124
  export declare function quote(expParts: readonly string[], ...values: (string | {
125
125
  toString(): string;
126
- })[]): RawQueryFragment<string> & symbol;
126
+ })[]): RawQueryFragment & symbol;
@@ -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})`));
@@ -160,8 +160,7 @@ export class TransactionManager {
160
160
  for (const entity of fork.getUnitOfWork(false).getIdentityMap()) {
161
161
  const wrapped = helper(entity);
162
162
  const meta = wrapped.__meta;
163
- // eslint-disable-next-line dot-notation
164
- const parentEntity = parentUoW.getById(meta.class, wrapped.getPrimaryKey(), parent['_schema'], true);
163
+ const parentEntity = parentUoW.getById(meta.class, wrapped.getPrimaryKey(), parent.schema, true);
165
164
  if (parentEntity && parentEntity !== entity) {
166
165
  const parentWrapped = helper(parentEntity);
167
166
  parentWrapped.__data = wrapped.__data;
@@ -183,7 +182,8 @@ export class TransactionManager {
183
182
  registerDeletionHandler(fork, parent) {
184
183
  fork.getEventManager().registerSubscriber({
185
184
  afterFlush: (args) => {
186
- const deletionChangeSets = args.uow.getChangeSets()
185
+ const deletionChangeSets = args.uow
186
+ .getChangeSets()
187
187
  .filter(cs => cs.type === ChangeSetType.DELETE || cs.type === ChangeSetType.DELETE_EARLY);
188
188
  for (const cs of deletionChangeSets) {
189
189
  parent.getUnitOfWork(false).unsetIdentity(cs.entity);
package/utils/Utils.d.ts CHANGED
@@ -22,7 +22,7 @@ export declare class Utils {
22
22
  /**
23
23
  * Removes `undefined` properties (recursively) so they are not saved as nulls
24
24
  */
25
- static dropUndefinedProperties(o: any, value?: undefined | null, visited?: Set<unknown>): void;
25
+ static dropUndefinedProperties(o: any, value?: null, visited?: Set<unknown>): void;
26
26
  /**
27
27
  * Returns the number of properties on `obj`. This is 20x faster than Object.keys(obj).length.
28
28
  * @see https://github.com/deepkit/deepkit-framework/blob/master/packages/core/src/core.ts
@@ -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';
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 => /\.([mc]?ts|tsx)$/.exec(arg)) || // 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.
@@ -557,7 +559,7 @@ export class Utils {
557
559
  return simple;
558
560
  }
559
561
  const objectType = Object.prototype.toString.call(value);
560
- const type = objectType.match(/^\[object (.+)]$/)[1];
562
+ const type = /^\[object (.+)]$/.exec(objectType)[1];
561
563
  if (type === 'Uint8Array') {
562
564
  return 'Buffer';
563
565
  }
@@ -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.
@@ -610,7 +613,7 @@ export class Utils {
610
613
  }
611
614
  static findDuplicates(items) {
612
615
  return items.reduce((acc, v, i, arr) => {
613
- return arr.indexOf(v) !== i && acc.indexOf(v) === -1 ? acc.concat(v) : acc;
616
+ return arr.indexOf(v) !== i && !acc.includes(v) ? acc.concat(v) : acc;
614
617
  }, []);
615
618
  }
616
619
  static removeDuplicates(items) {
@@ -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) {
@@ -671,6 +677,7 @@ export class Utils {
671
677
  return compiledFunctions[key](...context.values());
672
678
  }
673
679
  try {
680
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
674
681
  return new Function(...context.keys(), `'use strict';\n` + code)(...context.values());
675
682
  /* v8 ignore next */
676
683
  }
@@ -784,7 +791,7 @@ export class Utils {
784
791
  }
785
792
  }
786
793
  }
787
- static async tryImport({ module, warning }) {
794
+ static async tryImport({ module, warning, }) {
788
795
  try {
789
796
  return await import(module);
790
797
  }
package/utils/clone.js CHANGED
@@ -20,6 +20,7 @@ function getPropertyDescriptor(obj, prop) {
20
20
  }
21
21
  return null;
22
22
  }
23
+ const TypedArray = Object.getPrototypeOf(Uint8Array);
23
24
  export function clone(parent, respectCustomCloneMethod = true) {
24
25
  const allParents = [];
25
26
  const allChildren = [];
@@ -74,6 +75,10 @@ export function clone(parent, respectCustomCloneMethod = true) {
74
75
  parent.copy(child);
75
76
  return child;
76
77
  }
78
+ else if (parent instanceof TypedArray) {
79
+ child = parent.slice();
80
+ return child;
81
+ }
77
82
  else if (parent instanceof Error) {
78
83
  child = new parent.constructor(parent.message);
79
84
  }
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);
@@ -1,5 +1,5 @@
1
1
  import { type Dictionary } from '../typings.js';
2
- export declare const fs: {
2
+ export interface FsUtils {
3
3
  init(): Promise<void>;
4
4
  pathExists(path: string): boolean;
5
5
  ensureDir(path: string): void;
@@ -10,25 +10,11 @@ export declare const fs: {
10
10
  getORMPackages(): Set<string>;
11
11
  getORMPackageVersion(name: string): string | undefined;
12
12
  checkPackageVersion(): void;
13
- /**
14
- * Resolves and normalizes a series of path parts relative to each preceding part.
15
- * If any part is a `file:` URL, it is converted to a local path. If any part is an
16
- * absolute path, it replaces preceding paths (similar to `path.resolve` in NodeJS).
17
- * Trailing directory separators are removed, and all directory separators are converted
18
- * to POSIX-style separators (`/`).
19
- */
20
13
  normalizePath(...parts: string[]): string;
21
- /**
22
- * Determines the relative path between two paths. If either path is a `file:` URL,
23
- * it is converted to a local path.
24
- */
25
14
  relativePath(path: string, relativeTo: string): string;
26
- /**
27
- * Computes the absolute path to for the given path relative to the provided base directory.
28
- * If either `path` or `baseDir` are `file:` URLs, they are converted to local paths.
29
- */
30
15
  absolutePath(path: string, baseDir?: string): string;
31
16
  writeFile(path: string, data: string, options?: Record<string, any>): Promise<void>;
32
17
  dynamicImport<T = any>(id: string): Promise<T>;
33
- };
18
+ }
19
+ export declare const fs: FsUtils;
34
20
  export * from '../cache/FileCacheAdapter.js';
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 /^[/.]|[a-zA-Z]:/.exec(path) || 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
  }
@@ -99,7 +101,7 @@ export function getOnConflictReturningFields(meta, data, uniqueFields, options)
99
101
  return keys.filter(key => !(key in data));
100
102
  }
101
103
  function getPropertyValue(obj, key) {
102
- if (key.indexOf('.') === -1) {
104
+ if (!key.includes('.')) {
103
105
  return obj[key];
104
106
  }
105
107
  const parts = key.split('.');
@@ -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];