@mikro-orm/core 7.1.12-dev.9 → 7.1.12

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.
@@ -601,7 +601,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
601
601
  * some additional lazy properties, if so, we reload and merge the data from database
602
602
  */
603
603
  protected shouldRefresh<T extends object, P extends string = never, F extends string = never, E extends string = never>(meta: EntityMetadata<T>, entity: T, options: FindOneOptions<T, P, F, E>): boolean;
604
- protected prepareOptions(options: (FindOptions<any, any, any, any> | FindOneOptions<any, any, any, any> | CountOptions<any, any> | CountByOptions<any>) & AbortQueryOptions): void;
604
+ protected prepareOptions<Options extends (FindOptions<any, any, any, any> | FindOneOptions<any, any, any, any> | CountOptions<any, any> | CountByOptions<any>) & AbortQueryOptions>(options: Options): Options;
605
605
  /**
606
606
  * @internal
607
607
  */
package/EntityManager.js CHANGED
@@ -116,7 +116,7 @@ export class EntityManager {
116
116
  return ret;
117
117
  }
118
118
  const em = this.getContext();
119
- em.prepareOptions(options);
119
+ options = em.prepareOptions(options);
120
120
  const meta = this.metadata.get(entityName);
121
121
  em.validateIndexUsage(meta, where, options);
122
122
  await em.tryFlush(entityName, options);
@@ -199,7 +199,7 @@ export class EntityManager {
199
199
  */
200
200
  async *stream(entityName, options = {}) {
201
201
  const em = this.getContext();
202
- em.prepareOptions(options);
202
+ options = em.prepareOptions(options);
203
203
  options.strategy = 'joined';
204
204
  await em.tryFlush(entityName, options);
205
205
  const where = (await em.processWhere(entityName, options.where ?? {}, options, 'read'));
@@ -258,6 +258,7 @@ export class EntityManager {
258
258
  * Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
259
259
  */
260
260
  addFilter(options) {
261
+ options = { ...options };
261
262
  if (options.entity) {
262
263
  options.entity = Utils.asArray(options.entity).map(n => Utils.className(n));
263
264
  }
@@ -528,7 +529,7 @@ export class EntityManager {
528
529
  async findAndCount(entityName, where, options = {}) {
529
530
  const em = this.getContext(false);
530
531
  await em.tryFlush(entityName, options);
531
- options.flushMode = 'commit'; // do not try to auto flush again
532
+ options = { ...options, flushMode: 'commit' }; // do not try to auto flush again
532
533
  return Promise.all([
533
534
  em.find(entityName, where, options),
534
535
  em.count(entityName, where, options),
@@ -592,6 +593,7 @@ export class EntityManager {
592
593
  */
593
594
  async findByCursor(entityName, options) {
594
595
  const em = this.getContext(false);
596
+ options = { ...options };
595
597
  options.overfetch ??= true;
596
598
  options.where ??= {};
597
599
  if (Utils.isEmpty(options.orderBy) && !Raw.hasObjectFragments(options.orderBy)) {
@@ -610,10 +612,10 @@ export class EntityManager {
610
612
  async refreshOrFail(entity, options = {}) {
611
613
  const ret = await this.refresh(entity, options);
612
614
  if (!ret) {
613
- options.failHandler ??= this.config.get('findOneOrFailHandler');
615
+ const failHandler = options.failHandler ?? this.config.get('findOneOrFailHandler');
614
616
  const wrapped = helper(entity);
615
617
  const where = wrapped.getPrimaryKey();
616
- throw options.failHandler(wrapped.__meta.className, where);
618
+ throw failHandler(wrapped.__meta.className, where);
617
619
  }
618
620
  return ret;
619
621
  }
@@ -667,7 +669,7 @@ export class EntityManager {
667
669
  return ret;
668
670
  }
669
671
  const em = this.getContext();
670
- em.prepareOptions(options);
672
+ options = em.prepareOptions(options);
671
673
  let entity = em.#unitOfWork.tryGetById(entityName, where, options.schema);
672
674
  // query for a not managed entity which is already in the identity map as it
673
675
  // was provided with a PK this entity does not exist in the db, there can't
@@ -739,11 +741,11 @@ export class EntityManager {
739
741
  }
740
742
  if (!entity || isStrictViolation) {
741
743
  const key = options.strict ? 'findExactlyOneOrFailHandler' : 'findOneOrFailHandler';
742
- options.failHandler ??= this.config.get(key);
744
+ const failHandler = options.failHandler ?? this.config.get(key);
743
745
  const name = Utils.className(entityName);
744
746
  /* v8 ignore next */
745
747
  where = Utils.isEntity(where) ? helper(where).getPrimaryKey() : where;
746
- throw options.failHandler(name, where);
748
+ throw failHandler(name, where);
747
749
  }
748
750
  return entity;
749
751
  }
@@ -778,7 +780,7 @@ export class EntityManager {
778
780
  return ret;
779
781
  }
780
782
  const em = this.getContext(false);
781
- em.prepareOptions(options);
783
+ options = em.prepareOptions(options);
782
784
  let entityName;
783
785
  let where;
784
786
  let entity = null;
@@ -916,7 +918,7 @@ export class EntityManager {
916
918
  return ret;
917
919
  }
918
920
  const em = this.getContext(false);
919
- em.prepareOptions(options);
921
+ options = em.prepareOptions(options);
920
922
  let entityName;
921
923
  let propIndex;
922
924
  if (data === undefined) {
@@ -1202,7 +1204,7 @@ export class EntityManager {
1202
1204
  */
1203
1205
  async lock(entity, lockMode, options = {}) {
1204
1206
  options = Utils.isPlainObject(options) ? options : { lockVersion: options };
1205
- this.getContext(false).prepareOptions(options);
1207
+ options = this.getContext(false).prepareOptions(options);
1206
1208
  await this.getUnitOfWork().lock(entity, { lockMode, ...options });
1207
1209
  }
1208
1210
  /**
@@ -1210,7 +1212,7 @@ export class EntityManager {
1210
1212
  */
1211
1213
  async insert(entityNameOrEntity, data, options = {}) {
1212
1214
  const em = this.getContext(false);
1213
- em.prepareOptions(options);
1215
+ options = em.prepareOptions(options);
1214
1216
  let entityName;
1215
1217
  if (data === undefined) {
1216
1218
  entityName = entityNameOrEntity.constructor;
@@ -1277,7 +1279,7 @@ export class EntityManager {
1277
1279
  overrides = overridesOrOptions;
1278
1280
  }
1279
1281
  options ??= {};
1280
- em.prepareOptions(options);
1282
+ options = em.prepareOptions(options);
1281
1283
  const meta = em.metadata.get(entityName);
1282
1284
  const res = await em.driver.nativeClone(entityName, where, overrides, {
1283
1285
  ctx: em.#transactionContext,
@@ -1293,7 +1295,7 @@ export class EntityManager {
1293
1295
  */
1294
1296
  async insertMany(entityNameOrEntities, data, options = {}) {
1295
1297
  const em = this.getContext(false);
1296
- em.prepareOptions(options);
1298
+ options = em.prepareOptions(options);
1297
1299
  let entityName;
1298
1300
  if (data === undefined) {
1299
1301
  entityName = entityNameOrEntities[0].constructor;
@@ -1336,7 +1338,7 @@ export class EntityManager {
1336
1338
  */
1337
1339
  async nativeUpdate(entityName, where, data, options = {}) {
1338
1340
  const em = this.getContext(false);
1339
- em.prepareOptions(options);
1341
+ options = em.prepareOptions(options);
1340
1342
  await em.processUnionWhere(entityName, options, 'update');
1341
1343
  data = QueryHelper.processObjectParams(data);
1342
1344
  where = await em.processWhere(entityName, where, { ...options, convertCustomTypes: false }, 'update');
@@ -1385,7 +1387,7 @@ export class EntityManager {
1385
1387
  */
1386
1388
  async nativeDelete(entityName, where, options = {}) {
1387
1389
  const em = this.getContext(false);
1388
- em.prepareOptions(options);
1390
+ options = em.prepareOptions(options);
1389
1391
  await em.processUnionWhere(entityName, options, 'delete');
1390
1392
  where = (await em.processWhere(entityName, where, options, 'delete'));
1391
1393
  validateParams(where, 'delete condition');
@@ -1428,6 +1430,7 @@ export class EntityManager {
1428
1430
  return this.merge(entityName.constructor, entityName, data);
1429
1431
  }
1430
1432
  const em = options.disableContextResolution ? this : this.getContext();
1433
+ options = { ...options };
1431
1434
  options.schema ??= em.#schema;
1432
1435
  options.validate ??= true;
1433
1436
  options.cascade ??= true;
@@ -1461,6 +1464,7 @@ export class EntityManager {
1461
1464
  */
1462
1465
  create(entityName, data, options = {}) {
1463
1466
  const em = this.getContext();
1467
+ options = { ...options };
1464
1468
  options.schema ??= em.#schema;
1465
1469
  const entity = em.#entityFactory.create(entityName, data, {
1466
1470
  ...options,
@@ -1484,6 +1488,7 @@ export class EntityManager {
1484
1488
  * Gets a reference to the entity identified by the given type and identifier without actually loading it, if the entity is not yet loaded
1485
1489
  */
1486
1490
  getReference(entityName, id, options = {}) {
1491
+ options = { ...options };
1487
1492
  options.schema ??= this.schema;
1488
1493
  options.convertCustomTypes ??= false;
1489
1494
  const meta = this.metadata.get(entityName);
@@ -1504,13 +1509,10 @@ export class EntityManager {
1504
1509
  */
1505
1510
  async count(entityName, where = {}, options = {}) {
1506
1511
  const em = this.getContext(false);
1507
- // Shallow copy options since the object will be modified when deleting orderBy
1508
- options = { ...options };
1509
- em.prepareOptions(options);
1512
+ options = em.prepareOptions(options);
1510
1513
  await em.tryFlush(entityName, options);
1511
1514
  where = await em.processWhere(entityName, where, options, 'read');
1512
1515
  options.populate = (await em.preparePopulate(entityName, options));
1513
- options = { ...options };
1514
1516
  // save the original hint value so we know it was infer/all
1515
1517
  const meta = em.metadata.find(entityName);
1516
1518
  options._populateWhere = options.populateWhere ?? this.config.get('populateWhere');
@@ -1639,8 +1641,9 @@ export class EntityManager {
1639
1641
  }
1640
1642
  // For TPT inheritance, check the entity's own properties, not just the root's
1641
1643
  // For STI, meta.properties includes all properties anyway
1642
- const ret = p in meta.properties;
1643
- if (parts.length > 0) {
1644
+ // use an own-property check so inherited `Object.prototype` members (e.g. `__proto__`, `constructor`) are not treated as populatable
1645
+ const ret = Object.hasOwn(meta.properties, p);
1646
+ if (ret && parts.length > 0) {
1644
1647
  return this.canPopulate(meta.properties[p].targetMeta.class, parts.join('.'));
1645
1648
  }
1646
1649
  return ret;
@@ -1654,7 +1657,7 @@ export class EntityManager {
1654
1657
  return entities;
1655
1658
  }
1656
1659
  const em = this.getContext();
1657
- em.prepareOptions(options);
1660
+ options = em.prepareOptions(options);
1658
1661
  const entityName = arr[0].constructor;
1659
1662
  const preparedPopulate = await em.preparePopulate(entityName, { populate: populate, filters: options.filters, populateHints: options.populateHints }, options.validate);
1660
1663
  await em.#entityLoader.populate(entityName, arr, preparedPopulate, options);
@@ -1665,6 +1668,7 @@ export class EntityManager {
1665
1668
  */
1666
1669
  fork(options = {}) {
1667
1670
  const em = options.disableContextResolution ? this : this.getContext(false);
1671
+ options = { ...options };
1668
1672
  options.clear ??= true;
1669
1673
  options.useContext ??= false;
1670
1674
  options.freshEventManager ??= false;
@@ -2073,10 +2077,13 @@ export class EntityManager {
2073
2077
  if (!Utils.isEmpty(options.fields) && !Utils.isEmpty(options.exclude)) {
2074
2078
  throw new ValidationError(`Cannot combine 'fields' and 'exclude' option.`);
2075
2079
  }
2076
- options.schema ??= this.#schema;
2077
- options.signal ??= this.signal;
2078
- options.inflightQueryAbortStrategy ??= this.inflightQueryAbortStrategy;
2079
- options.logging = options.loggerContext = Utils.merge({ id: this.id }, this.loggerContext, options.loggerContext, options.logging);
2080
+ // the options object belongs to the caller, everything below works on our own copy
2081
+ const opts = { ...options };
2082
+ opts.schema ??= this.#schema;
2083
+ opts.signal ??= this.signal;
2084
+ opts.inflightQueryAbortStrategy ??= this.inflightQueryAbortStrategy;
2085
+ opts.logging = opts.loggerContext = Utils.merge({ id: this.id }, this.loggerContext, opts.loggerContext, opts.logging);
2086
+ return opts;
2080
2087
  }
2081
2088
  /**
2082
2089
  * @internal
@@ -1,5 +1,5 @@
1
1
  import { QueryHelper } from '../utils/QueryHelper.js';
2
- import { Utils } from '../utils/Utils.js';
2
+ import { DANGEROUS_PROPERTY_NAMES, Utils } from '../utils/Utils.js';
3
3
  import { ValidationError } from '../errors.js';
4
4
  import { LoadStrategy, PopulatePath, ReferenceKind, } from '../enums.js';
5
5
  import { Reference } from './Reference.js';
@@ -124,10 +124,10 @@ export class EntityLoader {
124
124
  mergeNestedPopulate(populate) {
125
125
  const tmp = populate.reduce((ret, item) => {
126
126
  /* v8 ignore next */
127
- if (item.field === PopulatePath.ALL) {
127
+ if (item.field === PopulatePath.ALL || DANGEROUS_PROPERTY_NAMES.includes(item.field)) {
128
128
  return ret;
129
129
  }
130
- if (!ret[item.field]) {
130
+ if (!Object.hasOwn(ret, item.field)) {
131
131
  ret[item.field] = item;
132
132
  return ret;
133
133
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
- "version": "7.1.12-dev.9",
3
+ "version": "7.1.12",
4
4
  "description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
5
5
  "keywords": [
6
6
  "data-mapper",
@@ -124,7 +124,6 @@ export class UnitOfWork {
124
124
  if (options?.newEntity) {
125
125
  return entity;
126
126
  }
127
- const forceUndefined = this.#em.config.get('forceUndefined');
128
127
  const wrapped = helper(entity);
129
128
  if (options?.loaded && wrapped.__initialized && !wrapped.__onLoadFired) {
130
129
  this.#loadedEntities.add(entity);
@@ -1,5 +1,5 @@
1
1
  import { Reference } from '../entity/Reference.js';
2
- import { Utils } from './Utils.js';
2
+ import { DANGEROUS_PROPERTY_NAMES, Utils } from './Utils.js';
3
3
  import { ARRAY_OPERATORS, GroupOperator, JSON_KEY_OPERATORS, ReferenceKind } from '../enums.js';
4
4
  import { JsonType } from '../types/JsonType.js';
5
5
  import { helper } from '../entity/wrap.js';
@@ -269,7 +269,11 @@ export class QueryHelper {
269
269
  options.forEach(filter => (opts[filter] = true));
270
270
  }
271
271
  else if (Utils.isPlainObject(options)) {
272
- Object.keys(options).forEach(filter => (opts[filter] = options[filter]));
272
+ Object.keys(options).forEach(filter => {
273
+ if (!DANGEROUS_PROPERTY_NAMES.includes(filter)) {
274
+ opts[filter] = options[filter];
275
+ }
276
+ });
273
277
  }
274
278
  return Object.keys(filters)
275
279
  .filter(f => QueryHelper.isFilterActive(meta, f, filters[f], opts))
package/utils/Utils.js CHANGED
@@ -153,7 +153,7 @@ export function parseJsonSafe(value) {
153
153
  /** Collection of general-purpose utility methods used throughout the ORM. */
154
154
  export class Utils {
155
155
  static PK_SEPARATOR = '~~~';
156
- static #ORM_VERSION = '7.1.12-dev.9';
156
+ static #ORM_VERSION = '7.1.12';
157
157
  /**
158
158
  * Checks if the argument is instance of `Object`. Returns false for arrays.
159
159
  */