@mikro-orm/core 7.0.0-dev.99 → 7.0.0-rc.1
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.
- package/EntityManager.d.ts +34 -17
- package/EntityManager.js +95 -103
- package/MikroORM.d.ts +5 -5
- package/MikroORM.js +25 -20
- package/cache/FileCacheAdapter.js +11 -3
- package/connections/Connection.d.ts +3 -2
- package/connections/Connection.js +4 -3
- package/drivers/DatabaseDriver.d.ts +11 -11
- package/drivers/DatabaseDriver.js +91 -25
- package/drivers/IDatabaseDriver.d.ts +50 -20
- package/entity/BaseEntity.d.ts +61 -1
- package/entity/Collection.d.ts +8 -1
- package/entity/Collection.js +12 -13
- package/entity/EntityAssigner.js +9 -9
- package/entity/EntityFactory.d.ts +6 -1
- package/entity/EntityFactory.js +40 -22
- package/entity/EntityHelper.d.ts +2 -2
- package/entity/EntityHelper.js +27 -4
- package/entity/EntityLoader.d.ts +5 -4
- package/entity/EntityLoader.js +193 -80
- package/entity/EntityRepository.d.ts +27 -7
- package/entity/EntityRepository.js +8 -2
- package/entity/PolymorphicRef.d.ts +12 -0
- package/entity/PolymorphicRef.js +18 -0
- package/entity/WrappedEntity.d.ts +2 -2
- package/entity/WrappedEntity.js +1 -1
- package/entity/defineEntity.d.ts +89 -50
- package/entity/defineEntity.js +12 -0
- package/entity/index.d.ts +1 -0
- package/entity/index.js +1 -0
- package/entity/utils.d.ts +6 -1
- package/entity/utils.js +33 -0
- package/entity/validators.js +2 -2
- package/enums.d.ts +2 -2
- package/enums.js +1 -0
- package/errors.d.ts +16 -8
- package/errors.js +40 -13
- package/hydration/ObjectHydrator.js +63 -21
- package/index.d.ts +1 -1
- package/logging/colors.d.ts +1 -1
- package/logging/colors.js +7 -6
- package/logging/inspect.js +1 -6
- package/metadata/EntitySchema.d.ts +43 -13
- package/metadata/EntitySchema.js +82 -27
- package/metadata/MetadataDiscovery.d.ts +60 -3
- package/metadata/MetadataDiscovery.js +665 -154
- package/metadata/MetadataProvider.js +3 -1
- package/metadata/MetadataStorage.d.ts +13 -6
- package/metadata/MetadataStorage.js +64 -19
- package/metadata/MetadataValidator.d.ts +32 -2
- package/metadata/MetadataValidator.js +196 -31
- package/metadata/discover-entities.js +5 -5
- package/metadata/types.d.ts +111 -14
- package/naming-strategy/AbstractNamingStrategy.d.ts +11 -3
- package/naming-strategy/AbstractNamingStrategy.js +12 -0
- package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
- package/naming-strategy/EntityCaseNamingStrategy.js +6 -5
- package/naming-strategy/MongoNamingStrategy.d.ts +3 -3
- package/naming-strategy/MongoNamingStrategy.js +6 -6
- package/naming-strategy/NamingStrategy.d.ts +17 -3
- package/naming-strategy/UnderscoreNamingStrategy.d.ts +3 -3
- package/naming-strategy/UnderscoreNamingStrategy.js +6 -6
- package/package.json +2 -2
- package/platforms/Platform.d.ts +4 -2
- package/platforms/Platform.js +5 -2
- package/serialization/EntitySerializer.d.ts +3 -0
- package/serialization/EntitySerializer.js +15 -13
- package/serialization/EntityTransformer.js +6 -6
- package/serialization/SerializationContext.d.ts +6 -6
- package/typings.d.ts +325 -110
- package/typings.js +84 -17
- package/unit-of-work/ChangeSet.d.ts +4 -3
- package/unit-of-work/ChangeSet.js +2 -3
- package/unit-of-work/ChangeSetComputer.d.ts +3 -6
- package/unit-of-work/ChangeSetComputer.js +34 -13
- package/unit-of-work/ChangeSetPersister.d.ts +12 -10
- package/unit-of-work/ChangeSetPersister.js +55 -25
- package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
- package/unit-of-work/CommitOrderCalculator.js +13 -13
- package/unit-of-work/IdentityMap.d.ts +12 -0
- package/unit-of-work/IdentityMap.js +39 -1
- package/unit-of-work/UnitOfWork.d.ts +21 -3
- package/unit-of-work/UnitOfWork.js +203 -56
- package/utils/AbstractSchemaGenerator.js +17 -8
- package/utils/AsyncContext.d.ts +6 -0
- package/utils/AsyncContext.js +42 -0
- package/utils/Configuration.d.ts +52 -11
- package/utils/Configuration.js +12 -8
- package/utils/Cursor.js +21 -8
- package/utils/DataloaderUtils.js +13 -11
- package/utils/EntityComparator.d.ts +14 -7
- package/utils/EntityComparator.js +132 -46
- package/utils/QueryHelper.d.ts +16 -6
- package/utils/QueryHelper.js +53 -18
- package/utils/RawQueryFragment.d.ts +28 -23
- package/utils/RawQueryFragment.js +34 -56
- package/utils/RequestContext.js +2 -2
- package/utils/TransactionContext.js +2 -2
- package/utils/TransactionManager.js +1 -1
- package/utils/Utils.d.ts +7 -26
- package/utils/Utils.js +25 -79
- package/utils/clone.js +7 -21
- package/utils/env-vars.d.ts +4 -0
- package/utils/env-vars.js +13 -3
- package/utils/fs-utils.d.ts +21 -0
- package/utils/fs-utils.js +106 -11
- package/utils/upsert-utils.d.ts +4 -4
package/EntityManager.js
CHANGED
|
@@ -4,7 +4,7 @@ import { Cursor } from './utils/Cursor.js';
|
|
|
4
4
|
import { DataloaderUtils } from './utils/DataloaderUtils.js';
|
|
5
5
|
import { QueryHelper } from './utils/QueryHelper.js';
|
|
6
6
|
import { TransactionContext } from './utils/TransactionContext.js';
|
|
7
|
-
import { isRaw,
|
|
7
|
+
import { isRaw, Raw } from './utils/RawQueryFragment.js';
|
|
8
8
|
import { EntityFactory } from './entity/EntityFactory.js';
|
|
9
9
|
import { EntityAssigner } from './entity/EntityAssigner.js';
|
|
10
10
|
import { validateEmptyWhere, validateParams, validatePrimaryKey, validateProperty } from './entity/validators.js';
|
|
@@ -17,7 +17,7 @@ import { EventType, FlushMode, LoadStrategy, LockMode, PopulateHint, PopulatePat
|
|
|
17
17
|
import { EventManager } from './events/EventManager.js';
|
|
18
18
|
import { TransactionEventBroadcaster } from './events/TransactionEventBroadcaster.js';
|
|
19
19
|
import { OptimisticLockError, ValidationError } from './errors.js';
|
|
20
|
-
import { getLoadingStrategy } from './entity/utils.js';
|
|
20
|
+
import { applyPopulateHints, getLoadingStrategy } from './entity/utils.js';
|
|
21
21
|
import { TransactionManager } from './utils/TransactionManager.js';
|
|
22
22
|
/**
|
|
23
23
|
* The EntityManager is the central access point to ORM functionality. It is a facade to all different ORM subsystems
|
|
@@ -35,7 +35,7 @@ export class EntityManager {
|
|
|
35
35
|
global = false;
|
|
36
36
|
name;
|
|
37
37
|
loaders = {};
|
|
38
|
-
repositoryMap =
|
|
38
|
+
repositoryMap = new Map();
|
|
39
39
|
entityLoader;
|
|
40
40
|
comparator;
|
|
41
41
|
entityFactory;
|
|
@@ -88,13 +88,12 @@ export class EntityManager {
|
|
|
88
88
|
* Gets repository for given entity. You can pass either string name or entity class reference.
|
|
89
89
|
*/
|
|
90
90
|
getRepository(entityName) {
|
|
91
|
-
|
|
92
|
-
if (!this.repositoryMap
|
|
93
|
-
const meta = this.metadata.get(entityName);
|
|
91
|
+
const meta = this.metadata.get(entityName);
|
|
92
|
+
if (!this.repositoryMap.has(meta)) {
|
|
94
93
|
const RepositoryClass = this.config.getRepositoryClass(meta.repository);
|
|
95
|
-
this.repositoryMap
|
|
94
|
+
this.repositoryMap.set(meta, new RepositoryClass(this, entityName));
|
|
96
95
|
}
|
|
97
|
-
return this.repositoryMap
|
|
96
|
+
return this.repositoryMap.get(meta);
|
|
98
97
|
}
|
|
99
98
|
/**
|
|
100
99
|
* Shortcut for `em.getRepository()`.
|
|
@@ -116,10 +115,15 @@ export class EntityManager {
|
|
|
116
115
|
const em = this.getContext();
|
|
117
116
|
em.prepareOptions(options);
|
|
118
117
|
await em.tryFlush(entityName, options);
|
|
119
|
-
entityName = Utils.className(entityName);
|
|
120
118
|
where = await em.processWhere(entityName, where, options, 'read');
|
|
121
119
|
validateParams(where);
|
|
122
|
-
|
|
120
|
+
const meta = this.metadata.get(entityName);
|
|
121
|
+
if (meta.orderBy) {
|
|
122
|
+
options.orderBy = QueryHelper.mergeOrderBy(options.orderBy, meta.orderBy);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
options.orderBy ??= {};
|
|
126
|
+
}
|
|
123
127
|
options.populate = await em.preparePopulate(entityName, options);
|
|
124
128
|
const populate = options.populate;
|
|
125
129
|
const cacheKey = em.cacheKey(entityName, options, 'em.find', where);
|
|
@@ -133,7 +137,6 @@ export class EntityManager {
|
|
|
133
137
|
});
|
|
134
138
|
return cached.data;
|
|
135
139
|
}
|
|
136
|
-
const meta = this.metadata.get(entityName);
|
|
137
140
|
options = { ...options };
|
|
138
141
|
// save the original hint value so we know it was infer/all
|
|
139
142
|
options._populateWhere = options.populateWhere ?? this.config.get('populateWhere');
|
|
@@ -192,7 +195,6 @@ export class EntityManager {
|
|
|
192
195
|
em.prepareOptions(options);
|
|
193
196
|
options.strategy = 'joined';
|
|
194
197
|
await em.tryFlush(entityName, options);
|
|
195
|
-
entityName = Utils.className(entityName);
|
|
196
198
|
const where = await em.processWhere(entityName, options.where ?? {}, options, 'read');
|
|
197
199
|
validateParams(where);
|
|
198
200
|
options.orderBy = options.orderBy || {};
|
|
@@ -300,18 +302,18 @@ export class EntityManager {
|
|
|
300
302
|
// this method only handles the problem for mongo driver, SQL drivers have their implementation inside QueryBuilder
|
|
301
303
|
applyDiscriminatorCondition(entityName, where) {
|
|
302
304
|
const meta = this.metadata.find(entityName);
|
|
303
|
-
if (!meta?.discriminatorValue) {
|
|
305
|
+
if (meta?.root.inheritanceType !== 'sti' || !meta?.discriminatorValue) {
|
|
304
306
|
return where;
|
|
305
307
|
}
|
|
306
|
-
const types = Object.values(meta.root.discriminatorMap).map(cls => this.metadata.
|
|
308
|
+
const types = Object.values(meta.root.discriminatorMap).map(cls => this.metadata.get(cls));
|
|
307
309
|
const children = [];
|
|
308
310
|
const lookUpChildren = (ret, type) => {
|
|
309
311
|
const children = types.filter(meta2 => meta2.extends === type);
|
|
310
|
-
children.forEach(m => lookUpChildren(ret, m.
|
|
312
|
+
children.forEach(m => lookUpChildren(ret, m.class));
|
|
311
313
|
ret.push(...children.filter(c => c.discriminatorValue));
|
|
312
314
|
return children;
|
|
313
315
|
};
|
|
314
|
-
lookUpChildren(children, meta.
|
|
316
|
+
lookUpChildren(children, meta.class);
|
|
315
317
|
/* v8 ignore next */
|
|
316
318
|
where[meta.root.discriminatorColumn] = children.length > 0 ? { $in: [meta.discriminatorValue, ...children.map(c => c.discriminatorValue)] } : meta.discriminatorValue;
|
|
317
319
|
return where;
|
|
@@ -328,8 +330,10 @@ export class EntityManager {
|
|
|
328
330
|
return ret;
|
|
329
331
|
}
|
|
330
332
|
async getJoinedFilters(meta, options) {
|
|
333
|
+
// If user provided populateFilter, merge it with computed filters
|
|
334
|
+
const userFilter = options.populateFilter;
|
|
331
335
|
if (!this.config.get('filtersOnRelations') || !options.populate) {
|
|
332
|
-
return
|
|
336
|
+
return userFilter;
|
|
333
337
|
}
|
|
334
338
|
const ret = {};
|
|
335
339
|
for (const hint of options.populate) {
|
|
@@ -341,7 +345,7 @@ export class EntityManager {
|
|
|
341
345
|
continue;
|
|
342
346
|
}
|
|
343
347
|
const filters = QueryHelper.mergePropertyFilters(prop.filters, options.filters);
|
|
344
|
-
const where = await this.applyFilters(prop.
|
|
348
|
+
const where = await this.applyFilters(prop.targetMeta.class, {}, filters, 'read', {
|
|
345
349
|
...options,
|
|
346
350
|
populate: hint.children,
|
|
347
351
|
});
|
|
@@ -363,7 +367,11 @@ export class EntityManager {
|
|
|
363
367
|
}
|
|
364
368
|
}
|
|
365
369
|
}
|
|
366
|
-
|
|
370
|
+
// Merge user-provided populateFilter with computed filters
|
|
371
|
+
if (userFilter) {
|
|
372
|
+
Utils.merge(ret, userFilter);
|
|
373
|
+
}
|
|
374
|
+
return Utils.hasObjectKeys(ret) ? ret : undefined;
|
|
367
375
|
}
|
|
368
376
|
/**
|
|
369
377
|
* When filters are active on M:1 or 1:1 relations, we need to ref join them eagerly as they might affect the FK value.
|
|
@@ -377,11 +385,11 @@ export class EntityManager {
|
|
|
377
385
|
if (prop.object
|
|
378
386
|
|| ![ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)
|
|
379
387
|
|| !((options.fields?.length ?? 0) === 0 || options.fields?.some(f => prop.name === f || prop.name.startsWith(`${String(f)}.`)))
|
|
380
|
-
|| (parent?.
|
|
388
|
+
|| (parent?.class === prop.targetMeta.root.class && parent.propName === prop.inversedBy)) {
|
|
381
389
|
continue;
|
|
382
390
|
}
|
|
383
391
|
options = { ...options, filters: QueryHelper.mergePropertyFilters(prop.filters, options.filters) };
|
|
384
|
-
const cond = await this.applyFilters(prop.
|
|
392
|
+
const cond = await this.applyFilters(prop.targetMeta.class, {}, options.filters, 'read', options);
|
|
385
393
|
if (!Utils.isEmpty(cond)) {
|
|
386
394
|
const populated = options.populate.filter(({ field }) => field.split(':')[0] === prop.name);
|
|
387
395
|
let found = false;
|
|
@@ -404,7 +412,7 @@ export class EntityManager {
|
|
|
404
412
|
const prop = meta?.properties[field];
|
|
405
413
|
if (prop && !ref) {
|
|
406
414
|
hint.children ??= [];
|
|
407
|
-
await this.autoJoinRefsForFilters(prop.targetMeta, { ...options, populate: hint.children }, {
|
|
415
|
+
await this.autoJoinRefsForFilters(prop.targetMeta, { ...options, populate: hint.children }, { class: meta.root.class, propName: prop.name });
|
|
408
416
|
}
|
|
409
417
|
}
|
|
410
418
|
}
|
|
@@ -412,16 +420,13 @@ export class EntityManager {
|
|
|
412
420
|
* @internal
|
|
413
421
|
*/
|
|
414
422
|
async applyFilters(entityName, where, options, type, findOptions) {
|
|
415
|
-
const meta = this.metadata.
|
|
423
|
+
const meta = this.metadata.get(entityName);
|
|
416
424
|
const filters = [];
|
|
417
425
|
const ret = [];
|
|
418
|
-
if (!meta) {
|
|
419
|
-
return where;
|
|
420
|
-
}
|
|
421
426
|
const active = new Set();
|
|
422
427
|
const push = (source) => {
|
|
423
428
|
const activeFilters = QueryHelper
|
|
424
|
-
.getActiveFilters(
|
|
429
|
+
.getActiveFilters(meta, options, source)
|
|
425
430
|
.filter(f => !active.has(f.name));
|
|
426
431
|
filters.push(...activeFilters);
|
|
427
432
|
activeFilters.forEach(f => active.add(f.name));
|
|
@@ -440,7 +445,7 @@ export class EntityManager {
|
|
|
440
445
|
if (!args && filter.cond.length > 0 && filter.args !== false) {
|
|
441
446
|
throw new Error(`No arguments provided for filter '${filter.name}'`);
|
|
442
447
|
}
|
|
443
|
-
cond = await filter.cond(args, type, this, findOptions, entityName);
|
|
448
|
+
cond = await filter.cond(args, type, this, findOptions, Utils.className(entityName));
|
|
444
449
|
}
|
|
445
450
|
else {
|
|
446
451
|
cond = filter.cond;
|
|
@@ -457,7 +462,7 @@ export class EntityManager {
|
|
|
457
462
|
}
|
|
458
463
|
ret.push(cond);
|
|
459
464
|
}
|
|
460
|
-
const conds = [...ret, where].filter(c => Utils.hasObjectKeys(c));
|
|
465
|
+
const conds = [...ret, where].filter(c => Utils.hasObjectKeys(c) || Raw.hasObjectFragments(c));
|
|
461
466
|
return conds.length > 1 ? { $and: conds } : conds[0];
|
|
462
467
|
}
|
|
463
468
|
/**
|
|
@@ -468,12 +473,10 @@ export class EntityManager {
|
|
|
468
473
|
const em = this.getContext(false);
|
|
469
474
|
await em.tryFlush(entityName, options);
|
|
470
475
|
options.flushMode = 'commit'; // do not try to auto flush again
|
|
471
|
-
return
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
]);
|
|
476
|
-
});
|
|
476
|
+
return Promise.all([
|
|
477
|
+
em.find(entityName, where, options),
|
|
478
|
+
em.count(entityName, where, options),
|
|
479
|
+
]);
|
|
477
480
|
}
|
|
478
481
|
/**
|
|
479
482
|
* Calls `em.find()` and `em.count()` with the same arguments (where applicable) and returns the results as {@apilink Cursor} object.
|
|
@@ -489,21 +492,21 @@ export class EntityManager {
|
|
|
489
492
|
* - POJO/entity instance
|
|
490
493
|
*
|
|
491
494
|
* ```ts
|
|
492
|
-
* const currentCursor = await em.findByCursor(User, {
|
|
495
|
+
* const currentCursor = await em.findByCursor(User, {
|
|
493
496
|
* first: 10,
|
|
494
497
|
* after: previousCursor, // cursor instance
|
|
495
498
|
* orderBy: { id: 'desc' },
|
|
496
499
|
* });
|
|
497
500
|
*
|
|
498
501
|
* // to fetch next page
|
|
499
|
-
* const nextCursor = await em.findByCursor(User, {
|
|
502
|
+
* const nextCursor = await em.findByCursor(User, {
|
|
500
503
|
* first: 10,
|
|
501
504
|
* after: currentCursor.endCursor, // opaque string
|
|
502
505
|
* orderBy: { id: 'desc' },
|
|
503
506
|
* });
|
|
504
507
|
*
|
|
505
508
|
* // to fetch next page
|
|
506
|
-
* const nextCursor2 = await em.findByCursor(User, {
|
|
509
|
+
* const nextCursor2 = await em.findByCursor(User, {
|
|
507
510
|
* first: 10,
|
|
508
511
|
* after: { id: lastSeenId }, // entity-like POJO
|
|
509
512
|
* orderBy: { id: 'desc' },
|
|
@@ -531,16 +534,16 @@ export class EntityManager {
|
|
|
531
534
|
* }
|
|
532
535
|
* ```
|
|
533
536
|
*/
|
|
534
|
-
async findByCursor(entityName,
|
|
537
|
+
async findByCursor(entityName, options) {
|
|
535
538
|
const em = this.getContext(false);
|
|
536
|
-
entityName = Utils.className(entityName);
|
|
537
539
|
options.overfetch ??= true;
|
|
538
|
-
|
|
540
|
+
options.where ??= {};
|
|
541
|
+
if (Utils.isEmpty(options.orderBy) && !Raw.hasObjectFragments(options.orderBy)) {
|
|
539
542
|
throw new Error('Explicit `orderBy` option required');
|
|
540
543
|
}
|
|
541
544
|
const [entities, count] = options.includeCount !== false
|
|
542
|
-
? await em.findAndCount(entityName, where, options)
|
|
543
|
-
: [await em.find(entityName, where, options)];
|
|
545
|
+
? await em.findAndCount(entityName, options.where, options)
|
|
546
|
+
: [await em.find(entityName, options.where, options)];
|
|
544
547
|
return new Cursor(entities, count, options, this.metadata.get(entityName));
|
|
545
548
|
}
|
|
546
549
|
/**
|
|
@@ -552,9 +555,9 @@ export class EntityManager {
|
|
|
552
555
|
const ret = await this.refresh(entity, options);
|
|
553
556
|
if (!ret) {
|
|
554
557
|
options.failHandler ??= this.config.get('findOneOrFailHandler');
|
|
555
|
-
const
|
|
556
|
-
const where =
|
|
557
|
-
throw options.failHandler(
|
|
558
|
+
const wrapped = helper(entity);
|
|
559
|
+
const where = wrapped.getPrimaryKey();
|
|
560
|
+
throw options.failHandler(wrapped.__meta.className, where);
|
|
558
561
|
}
|
|
559
562
|
return ret;
|
|
560
563
|
}
|
|
@@ -565,9 +568,8 @@ export class EntityManager {
|
|
|
565
568
|
*/
|
|
566
569
|
async refresh(entity, options = {}) {
|
|
567
570
|
const fork = this.fork({ keepTransactionContext: true });
|
|
568
|
-
const entityName = entity.constructor.name;
|
|
569
571
|
const wrapped = helper(entity);
|
|
570
|
-
const reloaded = await fork.findOne(
|
|
572
|
+
const reloaded = await fork.findOne(wrapped.__meta.class, entity, {
|
|
571
573
|
schema: wrapped.__schema,
|
|
572
574
|
...options,
|
|
573
575
|
flushMode: FlushMode.COMMIT,
|
|
@@ -579,14 +581,14 @@ export class EntityManager {
|
|
|
579
581
|
}
|
|
580
582
|
let found = false;
|
|
581
583
|
for (const e of fork.unitOfWork.getIdentityMap()) {
|
|
582
|
-
const ref = em.getReference(e.constructor
|
|
583
|
-
const data = helper(e).serialize({ ignoreSerializers: true, includeHidden: true });
|
|
584
|
-
em.config.getHydrator(this.metadata).hydrate(ref, helper(ref).__meta, data, em.entityFactory, 'full', false,
|
|
584
|
+
const ref = em.getReference(e.constructor, helper(e).getPrimaryKey());
|
|
585
|
+
const data = helper(e).serialize({ ignoreSerializers: true, includeHidden: true, convertCustomTypes: false });
|
|
586
|
+
em.config.getHydrator(this.metadata).hydrate(ref, helper(ref).__meta, data, em.entityFactory, 'full', false, false);
|
|
585
587
|
Utils.merge(helper(ref).__originalEntityData, this.comparator.prepareEntity(e));
|
|
586
588
|
found ||= ref === entity;
|
|
587
589
|
}
|
|
588
590
|
if (!found) {
|
|
589
|
-
const data = helper(reloaded).serialize({ ignoreSerializers: true, includeHidden: true });
|
|
591
|
+
const data = helper(reloaded).serialize({ ignoreSerializers: true, includeHidden: true, convertCustomTypes: true });
|
|
590
592
|
em.config.getHydrator(this.metadata).hydrate(entity, wrapped.__meta, data, em.entityFactory, 'full', false, true);
|
|
591
593
|
Utils.merge(wrapped.__originalEntityData, this.comparator.prepareEntity(reloaded));
|
|
592
594
|
}
|
|
@@ -604,7 +606,6 @@ export class EntityManager {
|
|
|
604
606
|
return ret;
|
|
605
607
|
}
|
|
606
608
|
const em = this.getContext();
|
|
607
|
-
entityName = Utils.className(entityName);
|
|
608
609
|
em.prepareOptions(options);
|
|
609
610
|
let entity = em.unitOfWork.tryGetById(entityName, where, options.schema);
|
|
610
611
|
// query for a not managed entity which is already in the identity map as it
|
|
@@ -682,10 +683,10 @@ export class EntityManager {
|
|
|
682
683
|
if (!entity || isStrictViolation) {
|
|
683
684
|
const key = options.strict ? 'findExactlyOneOrFailHandler' : 'findOneOrFailHandler';
|
|
684
685
|
options.failHandler ??= this.config.get(key);
|
|
685
|
-
|
|
686
|
+
const name = Utils.className(entityName);
|
|
686
687
|
/* v8 ignore next */
|
|
687
688
|
where = Utils.isEntity(where) ? helper(where).getPrimaryKey() : where;
|
|
688
|
-
throw options.failHandler(
|
|
689
|
+
throw options.failHandler(name, where);
|
|
689
690
|
}
|
|
690
691
|
return entity;
|
|
691
692
|
}
|
|
@@ -725,11 +726,11 @@ export class EntityManager {
|
|
|
725
726
|
let where;
|
|
726
727
|
let entity = null;
|
|
727
728
|
if (data === undefined) {
|
|
728
|
-
entityName = entityNameOrEntity.constructor
|
|
729
|
+
entityName = entityNameOrEntity.constructor;
|
|
729
730
|
data = entityNameOrEntity;
|
|
730
731
|
}
|
|
731
732
|
else {
|
|
732
|
-
entityName =
|
|
733
|
+
entityName = entityNameOrEntity;
|
|
733
734
|
}
|
|
734
735
|
const meta = this.metadata.get(entityName);
|
|
735
736
|
const convertCustomTypes = !Utils.isEntity(data);
|
|
@@ -792,7 +793,7 @@ export class EntityManager {
|
|
|
792
793
|
where[meta.primaryKeys[0]] = ret.insertId;
|
|
793
794
|
}
|
|
794
795
|
}
|
|
795
|
-
const data2 = await this.driver.findOne(meta.
|
|
796
|
+
const data2 = await this.driver.findOne(meta.class, where, {
|
|
796
797
|
fields: returning,
|
|
797
798
|
ctx: em.transactionContext,
|
|
798
799
|
convertCustomTypes: true,
|
|
@@ -847,11 +848,11 @@ export class EntityManager {
|
|
|
847
848
|
let entityName;
|
|
848
849
|
let propIndex;
|
|
849
850
|
if (data === undefined) {
|
|
850
|
-
entityName = entityNameOrEntity[0].constructor
|
|
851
|
+
entityName = entityNameOrEntity[0].constructor;
|
|
851
852
|
data = entityNameOrEntity;
|
|
852
853
|
}
|
|
853
854
|
else {
|
|
854
|
-
entityName =
|
|
855
|
+
entityName = entityNameOrEntity;
|
|
855
856
|
}
|
|
856
857
|
const batchSize = options.batchSize ?? this.config.get('batchSize');
|
|
857
858
|
if (data.length > batchSize) {
|
|
@@ -959,7 +960,7 @@ export class EntityManager {
|
|
|
959
960
|
where.$or[idx][prop] = item[prop];
|
|
960
961
|
});
|
|
961
962
|
});
|
|
962
|
-
const data2 = await this.driver.find(meta.
|
|
963
|
+
const data2 = await this.driver.find(meta.class, where, {
|
|
963
964
|
fields: returning.concat(...add).concat(...(Array.isArray(uniqueFields) ? uniqueFields : [])),
|
|
964
965
|
ctx: em.transactionContext,
|
|
965
966
|
convertCustomTypes: true,
|
|
@@ -1112,11 +1113,11 @@ export class EntityManager {
|
|
|
1112
1113
|
em.prepareOptions(options);
|
|
1113
1114
|
let entityName;
|
|
1114
1115
|
if (data === undefined) {
|
|
1115
|
-
entityName = entityNameOrEntity.constructor
|
|
1116
|
+
entityName = entityNameOrEntity.constructor;
|
|
1116
1117
|
data = entityNameOrEntity;
|
|
1117
1118
|
}
|
|
1118
1119
|
else {
|
|
1119
|
-
entityName =
|
|
1120
|
+
entityName = entityNameOrEntity;
|
|
1120
1121
|
}
|
|
1121
1122
|
if (Utils.isEntity(data)) {
|
|
1122
1123
|
if (options.schema && helper(data).getSchema() == null) {
|
|
@@ -1147,11 +1148,11 @@ export class EntityManager {
|
|
|
1147
1148
|
em.prepareOptions(options);
|
|
1148
1149
|
let entityName;
|
|
1149
1150
|
if (data === undefined) {
|
|
1150
|
-
entityName = entityNameOrEntities[0].constructor
|
|
1151
|
+
entityName = entityNameOrEntities[0].constructor;
|
|
1151
1152
|
data = entityNameOrEntities;
|
|
1152
1153
|
}
|
|
1153
1154
|
else {
|
|
1154
|
-
entityName =
|
|
1155
|
+
entityName = entityNameOrEntities;
|
|
1155
1156
|
}
|
|
1156
1157
|
if (data.length === 0) {
|
|
1157
1158
|
return [];
|
|
@@ -1188,7 +1189,6 @@ export class EntityManager {
|
|
|
1188
1189
|
async nativeUpdate(entityName, where, data, options = {}) {
|
|
1189
1190
|
const em = this.getContext(false);
|
|
1190
1191
|
em.prepareOptions(options);
|
|
1191
|
-
entityName = Utils.className(entityName);
|
|
1192
1192
|
data = QueryHelper.processObjectParams(data);
|
|
1193
1193
|
where = await em.processWhere(entityName, where, { ...options, convertCustomTypes: false }, 'update');
|
|
1194
1194
|
validateParams(data, 'update data');
|
|
@@ -1202,7 +1202,6 @@ export class EntityManager {
|
|
|
1202
1202
|
async nativeDelete(entityName, where, options = {}) {
|
|
1203
1203
|
const em = this.getContext(false);
|
|
1204
1204
|
em.prepareOptions(options);
|
|
1205
|
-
entityName = Utils.className(entityName);
|
|
1206
1205
|
where = await em.processWhere(entityName, where, options, 'delete');
|
|
1207
1206
|
validateParams(where, 'delete condition');
|
|
1208
1207
|
const res = await em.driver.nativeDelete(entityName, where, { ctx: em.transactionContext, ...options });
|
|
@@ -1212,7 +1211,6 @@ export class EntityManager {
|
|
|
1212
1211
|
* Maps raw database result to an entity and merges it to this EntityManager.
|
|
1213
1212
|
*/
|
|
1214
1213
|
map(entityName, result, options = {}) {
|
|
1215
|
-
entityName = Utils.className(entityName);
|
|
1216
1214
|
const meta = this.metadata.get(entityName);
|
|
1217
1215
|
const data = this.driver.mapResult(result, meta);
|
|
1218
1216
|
for (const k of Object.keys(data)) {
|
|
@@ -1234,13 +1232,12 @@ export class EntityManager {
|
|
|
1234
1232
|
*/
|
|
1235
1233
|
merge(entityName, data, options = {}) {
|
|
1236
1234
|
if (Utils.isEntity(entityName)) {
|
|
1237
|
-
return this.merge(entityName.constructor
|
|
1235
|
+
return this.merge(entityName.constructor, entityName, data);
|
|
1238
1236
|
}
|
|
1239
1237
|
const em = options.disableContextResolution ? this : this.getContext();
|
|
1240
1238
|
options.schema ??= em._schema;
|
|
1241
1239
|
options.validate ??= true;
|
|
1242
1240
|
options.cascade ??= true;
|
|
1243
|
-
entityName = Utils.className(entityName);
|
|
1244
1241
|
validatePrimaryKey(data, em.metadata.get(entityName));
|
|
1245
1242
|
let entity = em.unitOfWork.tryGetById(entityName, data, options.schema, false);
|
|
1246
1243
|
if (entity && helper(entity).__managed && helper(entity).__initialized && !options.refresh) {
|
|
@@ -1294,7 +1291,7 @@ export class EntityManager {
|
|
|
1294
1291
|
getReference(entityName, id, options = {}) {
|
|
1295
1292
|
options.schema ??= this.schema;
|
|
1296
1293
|
options.convertCustomTypes ??= false;
|
|
1297
|
-
const meta = this.metadata.get(
|
|
1294
|
+
const meta = this.metadata.get(entityName);
|
|
1298
1295
|
if (Utils.isPrimaryKey(id)) {
|
|
1299
1296
|
if (meta.compositePK) {
|
|
1300
1297
|
throw ValidationError.invalidCompositeIdentifier(meta);
|
|
@@ -1315,7 +1312,6 @@ export class EntityManager {
|
|
|
1315
1312
|
// Shallow copy options since the object will be modified when deleting orderBy
|
|
1316
1313
|
options = { ...options };
|
|
1317
1314
|
em.prepareOptions(options);
|
|
1318
|
-
entityName = Utils.className(entityName);
|
|
1319
1315
|
await em.tryFlush(entityName, options);
|
|
1320
1316
|
where = await em.processWhere(entityName, where, options, 'read');
|
|
1321
1317
|
options.populate = await em.preparePopulate(entityName, options);
|
|
@@ -1351,7 +1347,7 @@ export class EntityManager {
|
|
|
1351
1347
|
for (const ent of entities) {
|
|
1352
1348
|
if (!Utils.isEntity(ent, true)) {
|
|
1353
1349
|
/* v8 ignore next */
|
|
1354
|
-
const meta = typeof ent === 'object' ? em.metadata.find(ent.constructor
|
|
1350
|
+
const meta = typeof ent === 'object' ? em.metadata.find(ent.constructor) : undefined;
|
|
1355
1351
|
throw ValidationError.notDiscoveredEntity(ent, meta);
|
|
1356
1352
|
}
|
|
1357
1353
|
// do not cascade just yet, cascading of entities in persist stack is done when flushing
|
|
@@ -1395,7 +1391,6 @@ export class EntityManager {
|
|
|
1395
1391
|
async tryFlush(entityName, options) {
|
|
1396
1392
|
const em = this.getContext();
|
|
1397
1393
|
const flushMode = options.flushMode ?? em.flushMode ?? em.config.get('flushMode');
|
|
1398
|
-
entityName = Utils.className(entityName);
|
|
1399
1394
|
const meta = em.metadata.get(entityName);
|
|
1400
1395
|
if (flushMode === FlushMode.COMMIT) {
|
|
1401
1396
|
return;
|
|
@@ -1414,7 +1409,6 @@ export class EntityManager {
|
|
|
1414
1409
|
* Checks whether given property can be populated on the entity.
|
|
1415
1410
|
*/
|
|
1416
1411
|
canPopulate(entityName, property) {
|
|
1417
|
-
entityName = Utils.className(entityName);
|
|
1418
1412
|
// eslint-disable-next-line prefer-const
|
|
1419
1413
|
let [p, ...parts] = property.split('.');
|
|
1420
1414
|
const meta = this.metadata.find(entityName);
|
|
@@ -1424,12 +1418,11 @@ export class EntityManager {
|
|
|
1424
1418
|
if (p.includes(':')) {
|
|
1425
1419
|
p = p.split(':', 2)[0];
|
|
1426
1420
|
}
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
}
|
|
1421
|
+
// For TPT inheritance, check the entity's own properties, not just the root's
|
|
1422
|
+
// For STI, meta.properties includes all properties anyway
|
|
1423
|
+
const ret = p in meta.properties;
|
|
1431
1424
|
if (parts.length > 0) {
|
|
1432
|
-
return this.canPopulate(
|
|
1425
|
+
return this.canPopulate(meta.properties[p].targetMeta.class, parts.join('.'));
|
|
1433
1426
|
}
|
|
1434
1427
|
return ret;
|
|
1435
1428
|
}
|
|
@@ -1443,7 +1436,7 @@ export class EntityManager {
|
|
|
1443
1436
|
}
|
|
1444
1437
|
const em = this.getContext();
|
|
1445
1438
|
em.prepareOptions(options);
|
|
1446
|
-
const entityName = arr[0].constructor
|
|
1439
|
+
const entityName = arr[0].constructor;
|
|
1447
1440
|
const preparedPopulate = await em.preparePopulate(entityName, { populate: populate, filters: options.filters }, options.validate);
|
|
1448
1441
|
await em.entityLoader.populate(entityName, arr, preparedPopulate, options);
|
|
1449
1442
|
return entities;
|
|
@@ -1572,7 +1565,6 @@ export class EntityManager {
|
|
|
1572
1565
|
*/
|
|
1573
1566
|
getMetadata(entityName) {
|
|
1574
1567
|
if (entityName) {
|
|
1575
|
-
entityName = Utils.className(entityName);
|
|
1576
1568
|
return this.metadata.get(entityName);
|
|
1577
1569
|
}
|
|
1578
1570
|
return this.metadata;
|
|
@@ -1601,8 +1593,8 @@ export class EntityManager {
|
|
|
1601
1593
|
lockTableAliases: options.lockTableAliases,
|
|
1602
1594
|
});
|
|
1603
1595
|
}
|
|
1604
|
-
const preparedPopulate = await this.preparePopulate(meta.
|
|
1605
|
-
await this.entityLoader.populate(meta.
|
|
1596
|
+
const preparedPopulate = await this.preparePopulate(meta.class, options);
|
|
1597
|
+
await this.entityLoader.populate(meta.class, [entity], preparedPopulate, {
|
|
1606
1598
|
...options,
|
|
1607
1599
|
...this.getPopulateWhere(where, options),
|
|
1608
1600
|
orderBy: options.populateOrderBy ?? options.orderBy,
|
|
@@ -1622,6 +1614,7 @@ export class EntityManager {
|
|
|
1622
1614
|
return ret;
|
|
1623
1615
|
}, []);
|
|
1624
1616
|
}
|
|
1617
|
+
/** @internal */
|
|
1625
1618
|
async preparePopulate(entityName, options, validate = true) {
|
|
1626
1619
|
if (options.populate === false) {
|
|
1627
1620
|
return [];
|
|
@@ -1662,7 +1655,7 @@ export class EntityManager {
|
|
|
1662
1655
|
options.populate = pruneToOneRelations(meta, this.buildFields(options.fields));
|
|
1663
1656
|
}
|
|
1664
1657
|
if (!options.populate) {
|
|
1665
|
-
const populate = this.entityLoader.normalizePopulate(entityName, [], options.strategy);
|
|
1658
|
+
const populate = this.entityLoader.normalizePopulate(entityName, [], options.strategy, true, options.exclude);
|
|
1666
1659
|
await this.autoJoinRefsForFilters(meta, { ...options, populate });
|
|
1667
1660
|
return populate;
|
|
1668
1661
|
}
|
|
@@ -1684,18 +1677,21 @@ export class EntityManager {
|
|
|
1684
1677
|
return [field];
|
|
1685
1678
|
}).flat();
|
|
1686
1679
|
}
|
|
1687
|
-
const populate = this.entityLoader.normalizePopulate(entityName, options.populate, options.strategy);
|
|
1680
|
+
const populate = this.entityLoader.normalizePopulate(entityName, options.populate, options.strategy, true, options.exclude);
|
|
1688
1681
|
const invalid = populate.find(({ field }) => !this.canPopulate(entityName, field));
|
|
1689
1682
|
if (validate && invalid) {
|
|
1690
1683
|
throw ValidationError.invalidPropertyName(entityName, invalid.field);
|
|
1691
1684
|
}
|
|
1692
1685
|
await this.autoJoinRefsForFilters(meta, { ...options, populate });
|
|
1693
|
-
|
|
1686
|
+
for (const field of populate) {
|
|
1694
1687
|
// force select-in strategy when populating all relations as otherwise we could cause infinite loops when self-referencing
|
|
1695
1688
|
const all = field.all ?? (Array.isArray(options.populate) && options.populate.includes('*'));
|
|
1696
1689
|
field.strategy = all ? LoadStrategy.SELECT_IN : (options.strategy ?? field.strategy);
|
|
1697
|
-
|
|
1698
|
-
|
|
1690
|
+
}
|
|
1691
|
+
if (options.populateHints) {
|
|
1692
|
+
applyPopulateHints(populate, options.populateHints);
|
|
1693
|
+
}
|
|
1694
|
+
return populate;
|
|
1699
1695
|
}
|
|
1700
1696
|
/**
|
|
1701
1697
|
* when the entity is found in identity map, we check if it was partially loaded or we are trying to populate
|
|
@@ -1715,7 +1711,7 @@ export class EntityManager {
|
|
|
1715
1711
|
return !inlineEmbedded && !prop.lazy && !helper(entity).__loadedProperties.has(prop.name);
|
|
1716
1712
|
});
|
|
1717
1713
|
}
|
|
1718
|
-
if (autoRefresh) {
|
|
1714
|
+
if (autoRefresh || options.filters) {
|
|
1719
1715
|
return true;
|
|
1720
1716
|
}
|
|
1721
1717
|
if (Array.isArray(options.populate)) {
|
|
@@ -1739,7 +1735,7 @@ export class EntityManager {
|
|
|
1739
1735
|
for (const k of ['ctx', 'strategy', 'flushMode', 'logging', 'loggerContext']) {
|
|
1740
1736
|
delete opts[k];
|
|
1741
1737
|
}
|
|
1742
|
-
return [entityName, method, opts, where];
|
|
1738
|
+
return [Utils.className(entityName), method, opts, where];
|
|
1743
1739
|
}
|
|
1744
1740
|
/**
|
|
1745
1741
|
* @internal
|
|
@@ -1756,21 +1752,17 @@ export class EntityManager {
|
|
|
1756
1752
|
return { key: cacheKey, data: cached };
|
|
1757
1753
|
}
|
|
1758
1754
|
let data;
|
|
1755
|
+
const createOptions = {
|
|
1756
|
+
merge: true,
|
|
1757
|
+
convertCustomTypes: false,
|
|
1758
|
+
refresh,
|
|
1759
|
+
recomputeSnapshot: true,
|
|
1760
|
+
};
|
|
1759
1761
|
if (Array.isArray(cached) && merge) {
|
|
1760
|
-
data = cached.map(item => em.entityFactory.create(entityName, item,
|
|
1761
|
-
merge: true,
|
|
1762
|
-
convertCustomTypes: true,
|
|
1763
|
-
refresh,
|
|
1764
|
-
recomputeSnapshot: true,
|
|
1765
|
-
}));
|
|
1762
|
+
data = cached.map(item => em.entityFactory.create(entityName, item, createOptions));
|
|
1766
1763
|
}
|
|
1767
1764
|
else if (Utils.isObject(cached) && merge) {
|
|
1768
|
-
data = em.entityFactory.create(entityName, cached,
|
|
1769
|
-
merge: true,
|
|
1770
|
-
convertCustomTypes: true,
|
|
1771
|
-
refresh,
|
|
1772
|
-
recomputeSnapshot: true,
|
|
1773
|
-
});
|
|
1765
|
+
data = em.entityFactory.create(entityName, cached, createOptions);
|
|
1774
1766
|
}
|
|
1775
1767
|
else {
|
|
1776
1768
|
data = cached;
|
package/MikroORM.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { Configuration, type Options } from './utils/Configuration.js';
|
|
|
5
5
|
import type { EntityManager } from './EntityManager.js';
|
|
6
6
|
import type { AnyEntity, Constructor, EntityClass, EntityMetadata, EntityName, IEntityGenerator, IMigrator, ISeedManager } from './typings.js';
|
|
7
7
|
/** @internal */
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function loadOptionalDependencies(options: Options): Promise<void>;
|
|
9
9
|
/**
|
|
10
10
|
* The main class used to configure and bootstrap the ORM.
|
|
11
11
|
*
|
|
@@ -51,9 +51,9 @@ export declare class MikroORM<Driver extends IDatabaseDriver = IDatabaseDriver,
|
|
|
51
51
|
static init<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager<D> = D[typeof EntityManagerType] & EntityManager<D>, Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]>(options: Options<D, EM, Entities>): Promise<MikroORM<D, EM, Entities>>;
|
|
52
52
|
/**
|
|
53
53
|
* Synchronous variant of the `init` method with some limitations:
|
|
54
|
-
* -
|
|
55
|
-
* -
|
|
56
|
-
* -
|
|
54
|
+
* - folder-based discovery not supported
|
|
55
|
+
* - ORM extensions are not autoloaded
|
|
56
|
+
* - when metadata cache is enabled, `FileCacheAdapter` needs to be explicitly set in the config
|
|
57
57
|
*/
|
|
58
58
|
constructor(options: Options<Driver, EM, Entities>);
|
|
59
59
|
/**
|
|
@@ -94,7 +94,7 @@ export declare class MikroORM<Driver extends IDatabaseDriver = IDatabaseDriver,
|
|
|
94
94
|
/**
|
|
95
95
|
* Allows dynamically discovering new entity by reference, handy for testing schema diffing.
|
|
96
96
|
*/
|
|
97
|
-
discoverEntity<T extends Constructor | EntitySchema>(entities: T | T[], reset?:
|
|
97
|
+
discoverEntity<T extends Constructor | EntitySchema>(entities: T | T[], reset?: EntityName | EntityName[]): void;
|
|
98
98
|
/**
|
|
99
99
|
* Gets the SchemaGenerator.
|
|
100
100
|
*/
|