@mikro-orm/core 7.0.0-dev.1 → 7.0.0-dev.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.
- package/EntityManager.d.ts +18 -13
- package/EntityManager.js +203 -203
- package/MikroORM.d.ts +7 -6
- package/MikroORM.js +33 -45
- package/cache/CacheAdapter.js +1 -2
- package/cache/FileCacheAdapter.d.ts +1 -1
- package/cache/FileCacheAdapter.js +18 -26
- package/cache/GeneratedCacheAdapter.d.ts +2 -2
- package/cache/GeneratedCacheAdapter.js +1 -5
- package/cache/MemoryCacheAdapter.d.ts +1 -1
- package/cache/MemoryCacheAdapter.js +1 -5
- package/cache/NullCacheAdapter.d.ts +1 -1
- package/cache/NullCacheAdapter.js +1 -5
- package/cache/index.d.ts +5 -5
- package/cache/index.js +5 -21
- package/connections/Connection.d.ts +7 -7
- package/connections/Connection.js +8 -12
- package/connections/index.d.ts +1 -1
- package/connections/index.js +1 -17
- package/decorators/Check.d.ts +1 -1
- package/decorators/Check.js +5 -8
- package/decorators/CreateRequestContext.d.ts +1 -1
- package/decorators/CreateRequestContext.js +13 -14
- package/decorators/Embeddable.d.ts +1 -1
- package/decorators/Embeddable.js +3 -6
- package/decorators/Embedded.d.ts +1 -1
- package/decorators/Embedded.js +10 -12
- package/decorators/Entity.d.ts +2 -2
- package/decorators/Entity.js +5 -8
- package/decorators/Enum.d.ts +2 -2
- package/decorators/Enum.js +7 -10
- package/decorators/Filter.d.ts +1 -1
- package/decorators/Filter.js +3 -6
- package/decorators/Formula.d.ts +2 -2
- package/decorators/Formula.js +7 -10
- package/decorators/Indexed.d.ts +2 -2
- package/decorators/Indexed.js +6 -10
- package/decorators/ManyToMany.d.ts +3 -3
- package/decorators/ManyToMany.js +10 -12
- package/decorators/ManyToOne.d.ts +3 -3
- package/decorators/ManyToOne.js +10 -12
- package/decorators/OneToMany.d.ts +3 -3
- package/decorators/OneToMany.js +11 -14
- package/decorators/OneToOne.d.ts +4 -4
- package/decorators/OneToOne.js +4 -7
- package/decorators/PrimaryKey.d.ts +2 -2
- package/decorators/PrimaryKey.js +10 -13
- package/decorators/Property.d.ts +5 -5
- package/decorators/Property.js +10 -12
- package/decorators/Transactional.d.ts +2 -2
- package/decorators/Transactional.js +7 -10
- package/decorators/hooks.js +23 -35
- package/decorators/index.d.ts +17 -17
- package/decorators/index.js +17 -36
- package/drivers/DatabaseDriver.d.ts +13 -12
- package/drivers/DatabaseDriver.js +60 -64
- package/drivers/IDatabaseDriver.d.ts +12 -12
- package/drivers/IDatabaseDriver.js +1 -4
- package/drivers/index.d.ts +2 -2
- package/drivers/index.js +2 -18
- package/entity/ArrayCollection.d.ts +2 -2
- package/entity/ArrayCollection.js +29 -33
- package/entity/BaseEntity.d.ts +6 -6
- package/entity/BaseEntity.js +17 -21
- package/entity/Collection.d.ts +6 -6
- package/entity/Collection.js +40 -44
- package/entity/EntityAssigner.d.ts +2 -2
- package/entity/EntityAssigner.js +58 -63
- package/entity/EntityFactory.d.ts +3 -3
- package/entity/EntityFactory.js +58 -62
- package/entity/EntityHelper.d.ts +2 -2
- package/entity/EntityHelper.js +41 -45
- package/entity/EntityIdentifier.d.ts +1 -1
- package/entity/EntityIdentifier.js +1 -5
- package/entity/EntityLoader.d.ts +5 -5
- package/entity/EntityLoader.js +92 -96
- package/entity/EntityRepository.d.ts +7 -7
- package/entity/EntityRepository.js +7 -11
- package/entity/EntityValidator.d.ts +1 -1
- package/entity/EntityValidator.js +25 -29
- package/entity/Reference.d.ts +2 -2
- package/entity/Reference.js +35 -42
- package/entity/WrappedEntity.d.ts +12 -12
- package/entity/WrappedEntity.js +23 -27
- package/entity/index.d.ts +13 -13
- package/entity/index.js +13 -29
- package/entity/utils.d.ts +1 -1
- package/entity/utils.js +9 -12
- package/entity/wrap.d.ts +1 -1
- package/entity/wrap.js +2 -6
- package/enums.d.ts +3 -3
- package/enums.js +37 -41
- package/errors.d.ts +1 -1
- package/errors.js +15 -24
- package/events/EventManager.d.ts +3 -3
- package/events/EventManager.js +8 -12
- package/events/EventSubscriber.d.ts +5 -4
- package/events/EventSubscriber.js +1 -2
- package/events/TransactionEventBroadcaster.d.ts +3 -3
- package/events/TransactionEventBroadcaster.js +1 -5
- package/events/index.d.ts +3 -3
- package/events/index.js +3 -19
- package/exceptions.js +18 -39
- package/hydration/Hydrator.d.ts +5 -5
- package/hydration/Hydrator.js +3 -6
- package/hydration/ObjectHydrator.d.ts +3 -3
- package/hydration/ObjectHydrator.js +25 -28
- package/hydration/index.d.ts +2 -2
- package/hydration/index.js +2 -18
- package/index.d.ts +21 -21
- package/index.js +21 -46
- package/logging/DefaultLogger.d.ts +1 -1
- package/logging/DefaultLogger.js +9 -13
- package/logging/Logger.d.ts +1 -1
- package/logging/Logger.js +1 -2
- package/logging/SimpleLogger.d.ts +2 -2
- package/logging/SimpleLogger.js +2 -6
- package/logging/colors.js +1 -5
- package/logging/index.d.ts +4 -4
- package/logging/index.js +4 -20
- package/metadata/EntitySchema.d.ts +12 -4
- package/metadata/EntitySchema.js +41 -45
- package/metadata/MetadataDiscovery.d.ts +7 -7
- package/metadata/MetadataDiscovery.js +174 -177
- package/metadata/MetadataProvider.d.ts +2 -2
- package/metadata/MetadataProvider.js +4 -7
- package/metadata/MetadataStorage.d.ts +2 -2
- package/metadata/MetadataStorage.js +15 -19
- package/metadata/MetadataValidator.d.ts +4 -4
- package/metadata/MetadataValidator.js +49 -53
- package/metadata/ReflectMetadataProvider.d.ts +2 -2
- package/metadata/ReflectMetadataProvider.js +8 -12
- package/metadata/index.d.ts +6 -6
- package/metadata/index.js +6 -22
- package/naming-strategy/AbstractNamingStrategy.d.ts +2 -2
- package/naming-strategy/AbstractNamingStrategy.js +4 -8
- package/naming-strategy/EntityCaseNamingStrategy.d.ts +1 -1
- package/naming-strategy/EntityCaseNamingStrategy.js +2 -6
- package/naming-strategy/MongoNamingStrategy.d.ts +1 -1
- package/naming-strategy/MongoNamingStrategy.js +2 -6
- package/naming-strategy/NamingStrategy.d.ts +1 -1
- package/naming-strategy/NamingStrategy.js +1 -2
- package/naming-strategy/UnderscoreNamingStrategy.d.ts +1 -1
- package/naming-strategy/UnderscoreNamingStrategy.js +2 -6
- package/naming-strategy/index.d.ts +5 -5
- package/naming-strategy/index.js +5 -21
- package/package.json +5 -14
- package/platforms/ExceptionConverter.d.ts +2 -2
- package/platforms/ExceptionConverter.js +4 -8
- package/platforms/Platform.d.ts +10 -10
- package/platforms/Platform.js +57 -61
- package/platforms/index.d.ts +2 -2
- package/platforms/index.js +2 -18
- package/serialization/EntitySerializer.d.ts +2 -2
- package/serialization/EntitySerializer.js +36 -41
- package/serialization/EntityTransformer.d.ts +1 -1
- package/serialization/EntityTransformer.js +27 -31
- package/serialization/SerializationContext.d.ts +2 -2
- package/serialization/SerializationContext.js +10 -14
- package/serialization/index.d.ts +3 -3
- package/serialization/index.js +3 -19
- package/types/ArrayType.d.ts +3 -3
- package/types/ArrayType.js +7 -11
- package/types/BigIntType.d.ts +3 -3
- package/types/BigIntType.js +3 -6
- package/types/BlobType.d.ts +3 -3
- package/types/BlobType.js +2 -8
- package/types/BooleanType.d.ts +3 -3
- package/types/BooleanType.js +2 -6
- package/types/CharacterType.d.ts +3 -3
- package/types/CharacterType.js +2 -6
- package/types/DateTimeType.d.ts +3 -3
- package/types/DateTimeType.js +2 -6
- package/types/DateType.d.ts +3 -3
- package/types/DateType.js +2 -6
- package/types/DecimalType.d.ts +3 -3
- package/types/DecimalType.js +4 -7
- package/types/DoubleType.d.ts +3 -3
- package/types/DoubleType.js +3 -6
- package/types/EnumArrayType.d.ts +4 -4
- package/types/EnumArrayType.js +5 -10
- package/types/EnumType.d.ts +3 -3
- package/types/EnumType.js +2 -6
- package/types/FloatType.d.ts +3 -3
- package/types/FloatType.js +2 -6
- package/types/IntegerType.d.ts +3 -3
- package/types/IntegerType.js +2 -6
- package/types/IntervalType.d.ts +3 -3
- package/types/IntervalType.js +2 -6
- package/types/JsonType.d.ts +3 -3
- package/types/JsonType.js +2 -6
- package/types/MediumIntType.d.ts +3 -3
- package/types/MediumIntType.js +2 -6
- package/types/SmallIntType.d.ts +3 -3
- package/types/SmallIntType.js +2 -6
- package/types/StringType.d.ts +3 -3
- package/types/StringType.js +2 -6
- package/types/TextType.d.ts +3 -3
- package/types/TextType.js +2 -6
- package/types/TimeType.d.ts +3 -3
- package/types/TimeType.js +4 -8
- package/types/TinyIntType.d.ts +3 -3
- package/types/TinyIntType.js +3 -6
- package/types/Type.d.ts +2 -2
- package/types/Type.js +5 -9
- package/types/Uint8ArrayType.d.ts +3 -3
- package/types/Uint8ArrayType.js +3 -9
- package/types/UnknownType.d.ts +3 -3
- package/types/UnknownType.js +2 -6
- package/types/UuidType.d.ts +3 -3
- package/types/UuidType.js +2 -6
- package/types/index.d.ts +25 -25
- package/types/index.js +52 -79
- package/typings.d.ts +22 -20
- package/typings.js +34 -38
- package/unit-of-work/ChangeSet.d.ts +1 -1
- package/unit-of-work/ChangeSet.js +13 -17
- package/unit-of-work/ChangeSetComputer.d.ts +8 -7
- package/unit-of-work/ChangeSetComputer.js +26 -30
- package/unit-of-work/ChangeSetPersister.d.ts +7 -6
- package/unit-of-work/ChangeSetPersister.js +44 -47
- package/unit-of-work/CommitOrderCalculator.d.ts +1 -1
- package/unit-of-work/CommitOrderCalculator.js +6 -10
- package/unit-of-work/IdentityMap.d.ts +1 -1
- package/unit-of-work/IdentityMap.js +1 -5
- package/unit-of-work/UnitOfWork.d.ts +8 -7
- package/unit-of-work/UnitOfWork.js +171 -172
- package/unit-of-work/index.d.ts +6 -6
- package/unit-of-work/index.js +6 -22
- package/utils/AbstractSchemaGenerator.d.ts +6 -6
- package/utils/AbstractSchemaGenerator.js +7 -11
- package/utils/Configuration.d.ts +26 -27
- package/utils/Configuration.js +50 -55
- package/utils/ConfigurationLoader.d.ts +9 -8
- package/utils/ConfigurationLoader.js +71 -86
- package/utils/Cursor.d.ts +3 -3
- package/utils/Cursor.js +22 -25
- package/utils/DataloaderUtils.d.ts +4 -4
- package/utils/DataloaderUtils.js +12 -16
- package/utils/EntityComparator.d.ts +2 -2
- package/utils/EntityComparator.js +48 -52
- package/utils/NullHighlighter.d.ts +1 -1
- package/utils/NullHighlighter.js +1 -5
- package/utils/QueryHelper.d.ts +3 -3
- package/utils/QueryHelper.js +47 -51
- package/utils/RawQueryFragment.d.ts +1 -1
- package/utils/RawQueryFragment.js +16 -24
- package/utils/RequestContext.d.ts +2 -2
- package/utils/RequestContext.js +3 -7
- package/utils/TransactionContext.d.ts +1 -1
- package/utils/TransactionContext.js +4 -8
- package/utils/Utils.d.ts +16 -12
- package/utils/Utils.js +89 -93
- package/utils/clone.js +8 -11
- package/utils/index.d.ts +13 -13
- package/utils/index.js +13 -29
- package/utils/resolveContextProvider.d.ts +3 -3
- package/utils/resolveContextProvider.js +9 -12
- package/utils/upsert-utils.d.ts +3 -3
- package/utils/upsert-utils.js +5 -9
- package/index.mjs +0 -199
package/EntityManager.js
CHANGED
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
import { inspect } from 'node:util';
|
|
2
|
+
import DataLoader from 'dataloader';
|
|
3
|
+
import { getOnConflictReturningFields } from './utils/upsert-utils.js';
|
|
4
|
+
import { Utils } from './utils/Utils.js';
|
|
5
|
+
import { Cursor } from './utils/Cursor.js';
|
|
6
|
+
import { DataloaderUtils } from './utils/DataloaderUtils.js';
|
|
7
|
+
import { QueryHelper } from './utils/QueryHelper.js';
|
|
8
|
+
import { TransactionContext } from './utils/TransactionContext.js';
|
|
9
|
+
import { isRaw, RawQueryFragment } from './utils/RawQueryFragment.js';
|
|
10
|
+
import { EntityFactory } from './entity/EntityFactory.js';
|
|
11
|
+
import { EntityAssigner } from './entity/EntityAssigner.js';
|
|
12
|
+
import { EntityValidator } from './entity/EntityValidator.js';
|
|
13
|
+
import { EntityLoader } from './entity/EntityLoader.js';
|
|
14
|
+
import { Reference } from './entity/Reference.js';
|
|
15
|
+
import { helper } from './entity/wrap.js';
|
|
16
|
+
import { ChangeSet, ChangeSetType } from './unit-of-work/ChangeSet.js';
|
|
17
|
+
import { UnitOfWork } from './unit-of-work/UnitOfWork.js';
|
|
18
|
+
import { EventType, FlushMode, LoadStrategy, LockMode, PopulateHint, PopulatePath, QueryFlag, ReferenceKind, SCALAR_TYPES, } from './enums.js';
|
|
19
|
+
import { EventManager } from './events/EventManager.js';
|
|
20
|
+
import { TransactionEventBroadcaster } from './events/TransactionEventBroadcaster.js';
|
|
21
|
+
import { OptimisticLockError, ValidationError } from './errors.js';
|
|
21
22
|
/**
|
|
22
23
|
* The EntityManager is the central access point to ORM functionality. It is a facade to all different ORM subsystems
|
|
23
24
|
* such as UnitOfWork, Query Language, and Repository API.
|
|
24
25
|
* @template {IDatabaseDriver} Driver current driver type
|
|
25
26
|
*/
|
|
26
|
-
class EntityManager {
|
|
27
|
+
export class EntityManager {
|
|
27
28
|
config;
|
|
28
29
|
driver;
|
|
29
30
|
metadata;
|
|
@@ -33,8 +34,8 @@ class EntityManager {
|
|
|
33
34
|
_id = EntityManager.counter++;
|
|
34
35
|
global = false;
|
|
35
36
|
name;
|
|
36
|
-
refLoader = new
|
|
37
|
-
colLoader = new
|
|
37
|
+
refLoader = new DataLoader(DataloaderUtils.getRefBatchLoadFn(this));
|
|
38
|
+
colLoader = new DataLoader(DataloaderUtils.getColBatchLoadFn(this));
|
|
38
39
|
validator;
|
|
39
40
|
repositoryMap = {};
|
|
40
41
|
entityLoader;
|
|
@@ -52,20 +53,20 @@ class EntityManager {
|
|
|
52
53
|
/**
|
|
53
54
|
* @internal
|
|
54
55
|
*/
|
|
55
|
-
constructor(config, driver, metadata, useContext = true, eventManager = new
|
|
56
|
+
constructor(config, driver, metadata, useContext = true, eventManager = new EventManager(config.get('subscribers'))) {
|
|
56
57
|
this.config = config;
|
|
57
58
|
this.driver = driver;
|
|
58
59
|
this.metadata = metadata;
|
|
59
60
|
this.useContext = useContext;
|
|
60
61
|
this.eventManager = eventManager;
|
|
61
|
-
this.entityLoader = new
|
|
62
|
+
this.entityLoader = new EntityLoader(this);
|
|
62
63
|
this.name = this.config.get('contextName');
|
|
63
|
-
this.validator = new
|
|
64
|
+
this.validator = new EntityValidator(this.config.get('strict'));
|
|
64
65
|
this.comparator = this.config.getComparator(this.metadata);
|
|
65
66
|
this.resultCache = this.config.getResultCacheAdapter();
|
|
66
67
|
this.disableTransactions = this.config.get('disableTransactions');
|
|
67
|
-
this.entityFactory = new
|
|
68
|
-
this.unitOfWork = new
|
|
68
|
+
this.entityFactory = new EntityFactory(this);
|
|
69
|
+
this.unitOfWork = new UnitOfWork(this);
|
|
69
70
|
}
|
|
70
71
|
/**
|
|
71
72
|
* Gets the Driver instance used by this EntityManager.
|
|
@@ -90,7 +91,7 @@ class EntityManager {
|
|
|
90
91
|
* Gets repository for given entity. You can pass either string name or entity class reference.
|
|
91
92
|
*/
|
|
92
93
|
getRepository(entityName) {
|
|
93
|
-
entityName =
|
|
94
|
+
entityName = Utils.className(entityName);
|
|
94
95
|
if (!this.repositoryMap[entityName]) {
|
|
95
96
|
const meta = this.metadata.get(entityName);
|
|
96
97
|
const RepositoryClass = this.config.getRepositoryClass(meta.repository);
|
|
@@ -124,7 +125,7 @@ class EntityManager {
|
|
|
124
125
|
const em = this.getContext();
|
|
125
126
|
em.prepareOptions(options);
|
|
126
127
|
await em.tryFlush(entityName, options);
|
|
127
|
-
entityName =
|
|
128
|
+
entityName = Utils.className(entityName);
|
|
128
129
|
where = await em.processWhere(entityName, where, options, 'read');
|
|
129
130
|
em.validator.validateParams(where);
|
|
130
131
|
options.orderBy = options.orderBy || {};
|
|
@@ -163,7 +164,7 @@ class EntityManager {
|
|
|
163
164
|
});
|
|
164
165
|
ret.push(entity);
|
|
165
166
|
}
|
|
166
|
-
const unique =
|
|
167
|
+
const unique = Utils.unique(ret);
|
|
167
168
|
await em.entityLoader.populate(entityName, unique, populate, {
|
|
168
169
|
...options,
|
|
169
170
|
...em.getPopulateWhere(where, options),
|
|
@@ -176,7 +177,7 @@ class EntityManager {
|
|
|
176
177
|
await em.storeCache(options.cache, cached, () => ret);
|
|
177
178
|
}
|
|
178
179
|
else {
|
|
179
|
-
await em.storeCache(options.cache, cached, () => unique.map(e =>
|
|
180
|
+
await em.storeCache(options.cache, cached, () => unique.map(e => helper(e).toPOJO()));
|
|
180
181
|
}
|
|
181
182
|
return unique;
|
|
182
183
|
}
|
|
@@ -190,11 +191,11 @@ class EntityManager {
|
|
|
190
191
|
if (options.populateWhere === undefined) {
|
|
191
192
|
options.populateWhere = this.config.get('populateWhere');
|
|
192
193
|
}
|
|
193
|
-
if (options.populateWhere ===
|
|
194
|
+
if (options.populateWhere === PopulateHint.ALL) {
|
|
194
195
|
return { where: {}, populateWhere: options.populateWhere };
|
|
195
196
|
}
|
|
196
|
-
/*
|
|
197
|
-
if (options.populateWhere ===
|
|
197
|
+
/* v8 ignore next 3 */
|
|
198
|
+
if (options.populateWhere === PopulateHint.INFER) {
|
|
198
199
|
return { where, populateWhere: options.populateWhere };
|
|
199
200
|
}
|
|
200
201
|
return { where: options.populateWhere };
|
|
@@ -205,7 +206,7 @@ class EntityManager {
|
|
|
205
206
|
addFilter(name, cond, entityName, enabled = true) {
|
|
206
207
|
const options = { name, cond, default: enabled };
|
|
207
208
|
if (entityName) {
|
|
208
|
-
options.entity =
|
|
209
|
+
options.entity = Utils.asArray(entityName).map(n => Utils.className(n));
|
|
209
210
|
}
|
|
210
211
|
this.getContext(false).filters[name] = options;
|
|
211
212
|
}
|
|
@@ -240,7 +241,7 @@ class EntityManager {
|
|
|
240
241
|
this.getContext(false).flushMode = flushMode;
|
|
241
242
|
}
|
|
242
243
|
async processWhere(entityName, where, options, type) {
|
|
243
|
-
where =
|
|
244
|
+
where = QueryHelper.processWhere({
|
|
244
245
|
where,
|
|
245
246
|
entityName,
|
|
246
247
|
metadata: this.metadata,
|
|
@@ -249,7 +250,7 @@ class EntityManager {
|
|
|
249
250
|
aliased: type === 'read',
|
|
250
251
|
});
|
|
251
252
|
where = (await this.applyFilters(entityName, where, options.filters ?? {}, type, options));
|
|
252
|
-
where =
|
|
253
|
+
where = this.applyDiscriminatorCondition(entityName, where);
|
|
253
254
|
return where;
|
|
254
255
|
}
|
|
255
256
|
// this method only handles the problem for mongo driver, SQL drivers have their implementation inside QueryBuilder
|
|
@@ -267,18 +268,18 @@ class EntityManager {
|
|
|
267
268
|
return children;
|
|
268
269
|
};
|
|
269
270
|
lookUpChildren(children, meta.className);
|
|
270
|
-
/*
|
|
271
|
+
/* v8 ignore next */
|
|
271
272
|
where[meta.root.discriminatorColumn] = children.length > 0 ? { $in: [meta.discriminatorValue, ...children.map(c => c.discriminatorValue)] } : meta.discriminatorValue;
|
|
272
273
|
return where;
|
|
273
274
|
}
|
|
274
275
|
createPopulateWhere(cond, options) {
|
|
275
276
|
const ret = {};
|
|
276
277
|
const populateWhere = options.populateWhere ?? this.config.get('populateWhere');
|
|
277
|
-
if (populateWhere ===
|
|
278
|
-
|
|
278
|
+
if (populateWhere === PopulateHint.INFER) {
|
|
279
|
+
Utils.merge(ret, cond);
|
|
279
280
|
}
|
|
280
281
|
else if (typeof populateWhere === 'object') {
|
|
281
|
-
|
|
282
|
+
Utils.merge(ret, populateWhere);
|
|
282
283
|
}
|
|
283
284
|
return ret;
|
|
284
285
|
}
|
|
@@ -288,18 +289,18 @@ class EntityManager {
|
|
|
288
289
|
for (const hint of options.populate) {
|
|
289
290
|
const field = hint.field.split(':')[0];
|
|
290
291
|
const prop = meta.properties[field];
|
|
291
|
-
const joined = (prop.strategy || options.strategy || hint.strategy || this.config.get('loadStrategy')) ===
|
|
292
|
+
const joined = (prop.strategy || options.strategy || hint.strategy || this.config.get('loadStrategy')) === LoadStrategy.JOINED && prop.kind !== ReferenceKind.SCALAR;
|
|
292
293
|
if (!joined && !hint.filter) {
|
|
293
294
|
continue;
|
|
294
295
|
}
|
|
295
296
|
const where = await this.applyFilters(prop.type, {}, options.filters ?? {}, 'read', { ...options, populate: hint.children });
|
|
296
|
-
const where2 = await this.getJoinedFilters(prop.targetMeta, {}, { ...options, populate: hint.children, populateWhere:
|
|
297
|
-
if (
|
|
297
|
+
const where2 = await this.getJoinedFilters(prop.targetMeta, {}, { ...options, populate: hint.children, populateWhere: PopulateHint.ALL });
|
|
298
|
+
if (Utils.hasObjectKeys(where)) {
|
|
298
299
|
ret[field] = ret[field] ? { $and: [where, ret[field]] } : where;
|
|
299
300
|
}
|
|
300
|
-
if (
|
|
301
|
+
if (Utils.hasObjectKeys(where2)) {
|
|
301
302
|
if (ret[field]) {
|
|
302
|
-
|
|
303
|
+
Utils.merge(ret[field], where2);
|
|
303
304
|
}
|
|
304
305
|
else {
|
|
305
306
|
ret[field] = where2;
|
|
@@ -317,19 +318,19 @@ class EntityManager {
|
|
|
317
318
|
return;
|
|
318
319
|
}
|
|
319
320
|
const props = meta.relations.filter(prop => {
|
|
320
|
-
return !prop.object && [
|
|
321
|
+
return !prop.object && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)
|
|
321
322
|
&& ((options.fields?.length ?? 0) === 0 || options.fields?.some(f => prop.name === f || prop.name.startsWith(`${String(f)}.`)));
|
|
322
323
|
});
|
|
323
324
|
const ret = options.populate;
|
|
324
325
|
for (const prop of props) {
|
|
325
326
|
const cond = await this.applyFilters(prop.type, {}, options.filters ?? {}, 'read', options);
|
|
326
|
-
if (!
|
|
327
|
+
if (!Utils.isEmpty(cond)) {
|
|
327
328
|
const populated = options.populate.filter(({ field }) => field.split(':')[0] === prop.name);
|
|
328
329
|
if (populated.length > 0) {
|
|
329
330
|
populated.forEach(hint => hint.filter = true);
|
|
330
331
|
}
|
|
331
332
|
else {
|
|
332
|
-
ret.push({ field: `${prop.name}:ref`, strategy:
|
|
333
|
+
ret.push({ field: `${prop.name}:ref`, strategy: LoadStrategy.JOINED, filter: true });
|
|
333
334
|
}
|
|
334
335
|
}
|
|
335
336
|
}
|
|
@@ -346,7 +347,7 @@ class EntityManager {
|
|
|
346
347
|
}
|
|
347
348
|
const active = new Set();
|
|
348
349
|
const push = (source) => {
|
|
349
|
-
const activeFilters =
|
|
350
|
+
const activeFilters = QueryHelper
|
|
350
351
|
.getActiveFilters(entityName, options, source)
|
|
351
352
|
.filter(f => !active.has(f.name));
|
|
352
353
|
filters.push(...activeFilters);
|
|
@@ -362,7 +363,7 @@ class EntityManager {
|
|
|
362
363
|
let cond;
|
|
363
364
|
if (filter.cond instanceof Function) {
|
|
364
365
|
// @ts-ignore
|
|
365
|
-
const args =
|
|
366
|
+
const args = Utils.isPlainObject(options[filter.name]) ? options[filter.name] : this.getContext().filterParams[filter.name];
|
|
366
367
|
if (!args && filter.cond.length > 0 && filter.args !== false) {
|
|
367
368
|
throw new Error(`No arguments provided for filter '${filter.name}'`);
|
|
368
369
|
}
|
|
@@ -371,7 +372,7 @@ class EntityManager {
|
|
|
371
372
|
else {
|
|
372
373
|
cond = filter.cond;
|
|
373
374
|
}
|
|
374
|
-
ret.push(
|
|
375
|
+
ret.push(QueryHelper.processWhere({
|
|
375
376
|
where: cond,
|
|
376
377
|
entityName,
|
|
377
378
|
metadata: this.metadata,
|
|
@@ -379,7 +380,7 @@ class EntityManager {
|
|
|
379
380
|
aliased: type === 'read',
|
|
380
381
|
}));
|
|
381
382
|
}
|
|
382
|
-
const conds = [...ret, where].filter(c =>
|
|
383
|
+
const conds = [...ret, where].filter(c => Utils.hasObjectKeys(c));
|
|
383
384
|
return conds.length > 1 ? { $and: conds } : conds[0];
|
|
384
385
|
}
|
|
385
386
|
/**
|
|
@@ -390,7 +391,7 @@ class EntityManager {
|
|
|
390
391
|
const em = this.getContext(false);
|
|
391
392
|
await em.tryFlush(entityName, options);
|
|
392
393
|
options.flushMode = 'commit'; // do not try to auto flush again
|
|
393
|
-
return
|
|
394
|
+
return RawQueryFragment.run(async () => {
|
|
394
395
|
return Promise.all([
|
|
395
396
|
em.find(entityName, where, options),
|
|
396
397
|
em.count(entityName, where, options),
|
|
@@ -451,13 +452,13 @@ class EntityManager {
|
|
|
451
452
|
*/
|
|
452
453
|
async findByCursor(entityName, where, options) {
|
|
453
454
|
const em = this.getContext(false);
|
|
454
|
-
entityName =
|
|
455
|
+
entityName = Utils.className(entityName);
|
|
455
456
|
options.overfetch ??= true;
|
|
456
|
-
if (
|
|
457
|
+
if (Utils.isEmpty(options.orderBy)) {
|
|
457
458
|
throw new Error('Explicit `orderBy` option required');
|
|
458
459
|
}
|
|
459
460
|
const [entities, count] = await em.findAndCount(entityName, where, options);
|
|
460
|
-
return new
|
|
461
|
+
return new Cursor(entities, count, options, this.metadata.get(entityName));
|
|
461
462
|
}
|
|
462
463
|
/**
|
|
463
464
|
* Refreshes the persistent state of an entity from the database, overriding any local changes that have not yet been
|
|
@@ -469,7 +470,7 @@ class EntityManager {
|
|
|
469
470
|
if (!ret) {
|
|
470
471
|
options.failHandler ??= this.config.get('findOneOrFailHandler');
|
|
471
472
|
const entityName = entity.constructor.name;
|
|
472
|
-
const where =
|
|
473
|
+
const where = helper(entity).getPrimaryKey();
|
|
473
474
|
throw options.failHandler(entityName, where);
|
|
474
475
|
}
|
|
475
476
|
return ret;
|
|
@@ -483,12 +484,12 @@ class EntityManager {
|
|
|
483
484
|
const fork = this.fork({ keepTransactionContext: true });
|
|
484
485
|
const entityName = entity.constructor.name;
|
|
485
486
|
const reloaded = await fork.findOne(entityName, entity, {
|
|
486
|
-
schema:
|
|
487
|
+
schema: helper(entity).__schema,
|
|
487
488
|
...options,
|
|
488
|
-
flushMode:
|
|
489
|
+
flushMode: FlushMode.COMMIT,
|
|
489
490
|
});
|
|
490
491
|
if (reloaded) {
|
|
491
|
-
this.config.getHydrator(this.metadata).hydrate(entity,
|
|
492
|
+
this.config.getHydrator(this.metadata).hydrate(entity, helper(entity).__meta, helper(reloaded).toPOJO(), this.getEntityFactory(), 'full');
|
|
492
493
|
}
|
|
493
494
|
else {
|
|
494
495
|
this.getUnitOfWork().unsetIdentity(entity);
|
|
@@ -507,13 +508,13 @@ class EntityManager {
|
|
|
507
508
|
return ret;
|
|
508
509
|
}
|
|
509
510
|
const em = this.getContext();
|
|
510
|
-
entityName =
|
|
511
|
+
entityName = Utils.className(entityName);
|
|
511
512
|
em.prepareOptions(options);
|
|
512
513
|
let entity = em.unitOfWork.tryGetById(entityName, where, options.schema);
|
|
513
514
|
// query for a not managed entity which is already in the identity map as it
|
|
514
515
|
// was provided with a PK this entity does not exist in the db, there can't
|
|
515
516
|
// be any relations to it, so no need to deal with the populate hint
|
|
516
|
-
if (entity && !
|
|
517
|
+
if (entity && !helper(entity).__managed) {
|
|
517
518
|
return entity;
|
|
518
519
|
}
|
|
519
520
|
await em.tryFlush(entityName, options);
|
|
@@ -521,7 +522,7 @@ class EntityManager {
|
|
|
521
522
|
where = await em.processWhere(entityName, where, options, 'read');
|
|
522
523
|
em.validator.validateEmptyWhere(where);
|
|
523
524
|
em.checkLockRequirements(options.lockMode, meta);
|
|
524
|
-
const isOptimisticLocking = !
|
|
525
|
+
const isOptimisticLocking = !Utils.isDefined(options.lockMode) || options.lockMode === LockMode.OPTIMISTIC;
|
|
525
526
|
if (entity && !em.shouldRefresh(meta, entity, options) && isOptimisticLocking) {
|
|
526
527
|
return em.lockAndPopulate(meta, entity, where, options);
|
|
527
528
|
}
|
|
@@ -560,7 +561,7 @@ class EntityManager {
|
|
|
560
561
|
});
|
|
561
562
|
await em.lockAndPopulate(meta, entity, where, options);
|
|
562
563
|
await em.unitOfWork.dispatchOnLoadEvent();
|
|
563
|
-
await em.storeCache(options.cache, cached, () =>
|
|
564
|
+
await em.storeCache(options.cache, cached, () => helper(entity).toPOJO());
|
|
564
565
|
return entity;
|
|
565
566
|
}
|
|
566
567
|
/**
|
|
@@ -583,9 +584,9 @@ class EntityManager {
|
|
|
583
584
|
if (!entity || isStrictViolation) {
|
|
584
585
|
const key = options.strict ? 'findExactlyOneOrFailHandler' : 'findOneOrFailHandler';
|
|
585
586
|
options.failHandler ??= this.config.get(key);
|
|
586
|
-
entityName =
|
|
587
|
-
/*
|
|
588
|
-
where =
|
|
587
|
+
entityName = Utils.className(entityName);
|
|
588
|
+
/* v8 ignore next */
|
|
589
|
+
where = Utils.isEntity(where) ? helper(where).getPrimaryKey() : where;
|
|
589
590
|
throw options.failHandler(entityName, where);
|
|
590
591
|
}
|
|
591
592
|
return entity;
|
|
@@ -630,22 +631,22 @@ class EntityManager {
|
|
|
630
631
|
data = entityNameOrEntity;
|
|
631
632
|
}
|
|
632
633
|
else {
|
|
633
|
-
entityName =
|
|
634
|
+
entityName = Utils.className(entityNameOrEntity);
|
|
634
635
|
}
|
|
635
636
|
const meta = this.metadata.get(entityName);
|
|
636
|
-
const convertCustomTypes = !
|
|
637
|
-
if (
|
|
637
|
+
const convertCustomTypes = !Utils.isEntity(data);
|
|
638
|
+
if (Utils.isEntity(data)) {
|
|
638
639
|
entity = data;
|
|
639
|
-
if (
|
|
640
|
+
if (helper(entity).__managed && helper(entity).__em === em && !this.config.get('upsertManaged')) {
|
|
640
641
|
em.entityFactory.mergeData(meta, entity, data, { initialized: true });
|
|
641
642
|
return entity;
|
|
642
643
|
}
|
|
643
|
-
where =
|
|
644
|
+
where = helper(entity).getPrimaryKey();
|
|
644
645
|
data = em.comparator.prepareEntity(entity);
|
|
645
646
|
}
|
|
646
647
|
else {
|
|
647
|
-
data =
|
|
648
|
-
where =
|
|
648
|
+
data = Utils.copy(QueryHelper.processParams(data));
|
|
649
|
+
where = Utils.extractPK(data, meta);
|
|
649
650
|
if (where && !this.config.get('upsertManaged')) {
|
|
650
651
|
const exists = em.unitOfWork.getById(entityName, where, options.schema);
|
|
651
652
|
if (exists) {
|
|
@@ -654,15 +655,15 @@ class EntityManager {
|
|
|
654
655
|
}
|
|
655
656
|
}
|
|
656
657
|
const unique = options.onConflictFields ?? meta.props.filter(p => p.unique).map(p => p.name);
|
|
657
|
-
const propIndex = !
|
|
658
|
+
const propIndex = !isRaw(unique) && unique.findIndex(p => data[p] != null);
|
|
658
659
|
if (options.onConflictFields || where == null) {
|
|
659
660
|
if (propIndex !== false && propIndex >= 0) {
|
|
660
661
|
where = { [unique[propIndex]]: data[unique[propIndex]] };
|
|
661
662
|
}
|
|
662
663
|
else if (meta.uniques.length > 0) {
|
|
663
664
|
for (const u of meta.uniques) {
|
|
664
|
-
if (
|
|
665
|
-
where =
|
|
665
|
+
if (Utils.asArray(u.properties).every(p => data[p] != null)) {
|
|
666
|
+
where = Utils.asArray(u.properties).reduce((o, key) => {
|
|
666
667
|
o[key] = data[key];
|
|
667
668
|
return o;
|
|
668
669
|
}, {});
|
|
@@ -671,10 +672,10 @@ class EntityManager {
|
|
|
671
672
|
}
|
|
672
673
|
}
|
|
673
674
|
}
|
|
674
|
-
data =
|
|
675
|
+
data = QueryHelper.processObjectParams(data);
|
|
675
676
|
em.validator.validateParams(data, 'insert data');
|
|
676
|
-
if (em.eventManager.hasListeners(
|
|
677
|
-
await em.eventManager.dispatchEvent(
|
|
677
|
+
if (em.eventManager.hasListeners(EventType.beforeUpsert, meta)) {
|
|
678
|
+
await em.eventManager.dispatchEvent(EventType.beforeUpsert, { entity: data, em, meta }, meta);
|
|
678
679
|
}
|
|
679
680
|
const ret = await em.driver.nativeUpdate(entityName, where, data, {
|
|
680
681
|
ctx: em.transactionContext,
|
|
@@ -688,9 +689,9 @@ class EntityManager {
|
|
|
688
689
|
initialized: true,
|
|
689
690
|
schema: options.schema,
|
|
690
691
|
});
|
|
691
|
-
const uniqueFields = options.onConflictFields ?? (
|
|
692
|
-
const returning =
|
|
693
|
-
if (options.onConflictAction === 'ignore' || !
|
|
692
|
+
const uniqueFields = options.onConflictFields ?? (Utils.isPlainObject(where) ? Object.keys(where) : meta.primaryKeys);
|
|
693
|
+
const returning = getOnConflictReturningFields(meta, data, uniqueFields, options);
|
|
694
|
+
if (options.onConflictAction === 'ignore' || !helper(entity).hasPrimaryKey() || (returning.length > 0 && !(this.getPlatform().usesReturningStatement() && ret.row))) {
|
|
694
695
|
const where = {};
|
|
695
696
|
if (Array.isArray(uniqueFields)) {
|
|
696
697
|
for (const prop of uniqueFields) {
|
|
@@ -721,8 +722,8 @@ class EntityManager {
|
|
|
721
722
|
// recompute the data as there might be some values missing (e.g. those with db column defaults)
|
|
722
723
|
const snapshot = this.comparator.prepareEntity(entity);
|
|
723
724
|
em.unitOfWork.register(entity, snapshot, { refresh: true });
|
|
724
|
-
if (em.eventManager.hasListeners(
|
|
725
|
-
await em.eventManager.dispatchEvent(
|
|
725
|
+
if (em.eventManager.hasListeners(EventType.afterUpsert, meta)) {
|
|
726
|
+
await em.eventManager.dispatchEvent(EventType.afterUpsert, { entity, em, meta }, meta);
|
|
726
727
|
}
|
|
727
728
|
return entity;
|
|
728
729
|
}
|
|
@@ -768,19 +769,19 @@ class EntityManager {
|
|
|
768
769
|
data = entityNameOrEntity;
|
|
769
770
|
}
|
|
770
771
|
else {
|
|
771
|
-
entityName =
|
|
772
|
+
entityName = Utils.className(entityNameOrEntity);
|
|
772
773
|
}
|
|
773
774
|
const batchSize = options.batchSize ?? this.config.get('batchSize');
|
|
774
775
|
if (data.length > batchSize) {
|
|
775
776
|
const ret = [];
|
|
776
777
|
for (let i = 0; i < data.length; i += batchSize) {
|
|
777
778
|
const chunk = data.slice(i, i + batchSize);
|
|
778
|
-
ret.push(...await this.upsertMany(entityName, chunk, options));
|
|
779
|
+
ret.push(...(await this.upsertMany(entityName, chunk, options)));
|
|
779
780
|
}
|
|
780
781
|
return ret;
|
|
781
782
|
}
|
|
782
783
|
const meta = this.metadata.get(entityName);
|
|
783
|
-
const convertCustomTypes = !
|
|
784
|
+
const convertCustomTypes = !Utils.isEntity(data[0]);
|
|
784
785
|
const allData = [];
|
|
785
786
|
const allWhere = [];
|
|
786
787
|
const entities = new Map();
|
|
@@ -788,20 +789,20 @@ class EntityManager {
|
|
|
788
789
|
for (let i = 0; i < data.length; i++) {
|
|
789
790
|
let row = data[i];
|
|
790
791
|
let where;
|
|
791
|
-
if (
|
|
792
|
+
if (Utils.isEntity(row)) {
|
|
792
793
|
const entity = row;
|
|
793
|
-
if (
|
|
794
|
+
if (helper(entity).__managed && helper(entity).__em === em && !this.config.get('upsertManaged')) {
|
|
794
795
|
em.entityFactory.mergeData(meta, entity, row, { initialized: true });
|
|
795
796
|
entities.set(entity, row);
|
|
796
797
|
entitiesByData.set(row, entity);
|
|
797
798
|
continue;
|
|
798
799
|
}
|
|
799
|
-
where =
|
|
800
|
+
where = helper(entity).getPrimaryKey();
|
|
800
801
|
row = em.comparator.prepareEntity(entity);
|
|
801
802
|
}
|
|
802
803
|
else {
|
|
803
|
-
row = data[i] =
|
|
804
|
-
where =
|
|
804
|
+
row = data[i] = Utils.copy(QueryHelper.processParams(row));
|
|
805
|
+
where = Utils.extractPK(row, meta);
|
|
805
806
|
if (where && !this.config.get('upsertManaged')) {
|
|
806
807
|
const exists = em.unitOfWork.getById(entityName, where, options.schema);
|
|
807
808
|
if (exists) {
|
|
@@ -820,8 +821,8 @@ class EntityManager {
|
|
|
820
821
|
}
|
|
821
822
|
else if (meta.uniques.length > 0) {
|
|
822
823
|
for (const u of meta.uniques) {
|
|
823
|
-
if (
|
|
824
|
-
where =
|
|
824
|
+
if (Utils.asArray(u.properties).every(p => row[p] != null)) {
|
|
825
|
+
where = Utils.asArray(u.properties).reduce((o, key) => {
|
|
825
826
|
o[key] = row[key];
|
|
826
827
|
return o;
|
|
827
828
|
}, {});
|
|
@@ -830,8 +831,8 @@ class EntityManager {
|
|
|
830
831
|
}
|
|
831
832
|
}
|
|
832
833
|
}
|
|
833
|
-
row =
|
|
834
|
-
where =
|
|
834
|
+
row = QueryHelper.processObjectParams(row);
|
|
835
|
+
where = QueryHelper.processWhere({
|
|
835
836
|
where,
|
|
836
837
|
entityName,
|
|
837
838
|
metadata: this.metadata,
|
|
@@ -844,10 +845,10 @@ class EntityManager {
|
|
|
844
845
|
if (entities.size === data.length) {
|
|
845
846
|
return [...entities.keys()];
|
|
846
847
|
}
|
|
847
|
-
if (em.eventManager.hasListeners(
|
|
848
|
+
if (em.eventManager.hasListeners(EventType.beforeUpsert, meta)) {
|
|
848
849
|
for (const dto of data) {
|
|
849
850
|
const entity = entitiesByData.get(dto) ?? dto;
|
|
850
|
-
await em.eventManager.dispatchEvent(
|
|
851
|
+
await em.eventManager.dispatchEvent(EventType.beforeUpsert, { entity, em, meta }, meta);
|
|
851
852
|
}
|
|
852
853
|
}
|
|
853
854
|
const res = await em.driver.nativeUpdateMany(entityName, allWhere, allData, {
|
|
@@ -860,27 +861,27 @@ class EntityManager {
|
|
|
860
861
|
entitiesByData.clear();
|
|
861
862
|
const loadPK = new Map();
|
|
862
863
|
allData.forEach((row, i) => {
|
|
863
|
-
em.unitOfWork.getChangeSetPersister().mapReturnedValues(
|
|
864
|
-
const entity =
|
|
864
|
+
em.unitOfWork.getChangeSetPersister().mapReturnedValues(Utils.isEntity(data[i]) ? data[i] : null, Utils.isEntity(data[i]) ? {} : data[i], res.rows?.[i], meta, true);
|
|
865
|
+
const entity = Utils.isEntity(data[i]) ? data[i] : em.entityFactory.create(entityName, row, {
|
|
865
866
|
refresh: true,
|
|
866
867
|
initialized: true,
|
|
867
868
|
schema: options.schema,
|
|
868
869
|
});
|
|
869
|
-
if (!
|
|
870
|
+
if (!helper(entity).hasPrimaryKey()) {
|
|
870
871
|
loadPK.set(entity, allWhere[i]);
|
|
871
872
|
}
|
|
872
873
|
entities.set(entity, row);
|
|
873
874
|
entitiesByData.set(row, entity);
|
|
874
875
|
});
|
|
875
876
|
// skip if we got the PKs via returning statement (`rows`)
|
|
876
|
-
const uniqueFields = options.onConflictFields ?? (
|
|
877
|
-
const returning =
|
|
877
|
+
const uniqueFields = options.onConflictFields ?? (Utils.isPlainObject(allWhere[0]) ? Object.keys(allWhere[0]).flatMap(key => Utils.splitPrimaryKeys(key)) : meta.primaryKeys);
|
|
878
|
+
const returning = getOnConflictReturningFields(meta, data[0], uniqueFields, options);
|
|
878
879
|
const reloadFields = returning.length > 0 && !(this.getPlatform().usesReturningStatement() && res.rows?.length);
|
|
879
880
|
if (options.onConflictAction === 'ignore' || (!res.rows?.length && loadPK.size > 0) || reloadFields) {
|
|
880
881
|
const unique = meta.hydrateProps.filter(p => !p.lazy).map(p => p.name);
|
|
881
882
|
const add = new Set(propIndex >= 0 ? [unique[propIndex]] : []);
|
|
882
883
|
for (const cond of loadPK.values()) {
|
|
883
|
-
|
|
884
|
+
Utils.keys(cond).forEach(key => add.add(key));
|
|
884
885
|
}
|
|
885
886
|
const where = { $or: [] };
|
|
886
887
|
data.forEach((item, idx) => {
|
|
@@ -906,7 +907,7 @@ class EntityManager {
|
|
|
906
907
|
});
|
|
907
908
|
return this.comparator.matching(entityName, cond, tmp);
|
|
908
909
|
});
|
|
909
|
-
/*
|
|
910
|
+
/* v8 ignore next 3 */
|
|
910
911
|
if (!row) {
|
|
911
912
|
throw new Error(`Cannot find matching entity for condition ${JSON.stringify(cond)}`);
|
|
912
913
|
}
|
|
@@ -929,7 +930,7 @@ class EntityManager {
|
|
|
929
930
|
}, {});
|
|
930
931
|
return this.comparator.matching(entityName, cond, pk);
|
|
931
932
|
});
|
|
932
|
-
/*
|
|
933
|
+
/* v8 ignore next 3 */
|
|
933
934
|
if (!row) {
|
|
934
935
|
throw new Error(`Cannot find matching entity for condition ${JSON.stringify(cond)}`);
|
|
935
936
|
}
|
|
@@ -942,9 +943,9 @@ class EntityManager {
|
|
|
942
943
|
const snapshot = this.comparator.prepareEntity(entity);
|
|
943
944
|
em.unitOfWork.register(entity, snapshot, { refresh: true });
|
|
944
945
|
}
|
|
945
|
-
if (em.eventManager.hasListeners(
|
|
946
|
+
if (em.eventManager.hasListeners(EventType.afterUpsert, meta)) {
|
|
946
947
|
for (const [entity] of entities) {
|
|
947
|
-
await em.eventManager.dispatchEvent(
|
|
948
|
+
await em.eventManager.dispatchEvent(EventType.afterUpsert, { entity, em, meta }, meta);
|
|
948
949
|
}
|
|
949
950
|
}
|
|
950
951
|
return [...entities.keys()];
|
|
@@ -966,14 +967,14 @@ class EntityManager {
|
|
|
966
967
|
});
|
|
967
968
|
options.ctx ??= em.transactionContext;
|
|
968
969
|
const propagateToUpperContext = !em.global || this.config.get('allowGlobalContext');
|
|
969
|
-
return
|
|
970
|
+
return TransactionContext.create(fork, async () => {
|
|
970
971
|
return fork.getConnection().transactional(async (trx) => {
|
|
971
972
|
fork.transactionContext = trx;
|
|
972
973
|
if (propagateToUpperContext) {
|
|
973
974
|
fork.eventManager.registerSubscriber({
|
|
974
975
|
afterFlush(args) {
|
|
975
976
|
args.uow.getChangeSets()
|
|
976
|
-
.filter(cs => [
|
|
977
|
+
.filter(cs => [ChangeSetType.DELETE, ChangeSetType.DELETE_EARLY].includes(cs.type))
|
|
977
978
|
.forEach(cs => em.unitOfWork.unsetIdentity(cs.entity));
|
|
978
979
|
},
|
|
979
980
|
});
|
|
@@ -988,7 +989,7 @@ class EntityManager {
|
|
|
988
989
|
}
|
|
989
990
|
}
|
|
990
991
|
return ret;
|
|
991
|
-
}, { ...options, eventBroadcaster: new
|
|
992
|
+
}, { ...options, eventBroadcaster: new TransactionEventBroadcaster(fork, { topLevelTransaction: !options.ctx }) });
|
|
992
993
|
});
|
|
993
994
|
}
|
|
994
995
|
/**
|
|
@@ -1001,7 +1002,7 @@ class EntityManager {
|
|
|
1001
1002
|
const em = this.getContext(false);
|
|
1002
1003
|
em.transactionContext = await em.getConnection('write').begin({
|
|
1003
1004
|
...options,
|
|
1004
|
-
eventBroadcaster: new
|
|
1005
|
+
eventBroadcaster: new TransactionEventBroadcaster(em, { topLevelTransaction: !options.ctx }),
|
|
1005
1006
|
});
|
|
1006
1007
|
}
|
|
1007
1008
|
/**
|
|
@@ -1014,10 +1015,10 @@ class EntityManager {
|
|
|
1014
1015
|
return;
|
|
1015
1016
|
}
|
|
1016
1017
|
if (!em.transactionContext) {
|
|
1017
|
-
throw
|
|
1018
|
+
throw ValidationError.transactionRequired();
|
|
1018
1019
|
}
|
|
1019
1020
|
await em.flush();
|
|
1020
|
-
await em.getConnection('write').commit(em.transactionContext, new
|
|
1021
|
+
await em.getConnection('write').commit(em.transactionContext, new TransactionEventBroadcaster(em));
|
|
1021
1022
|
delete em.transactionContext;
|
|
1022
1023
|
}
|
|
1023
1024
|
/**
|
|
@@ -1029,9 +1030,9 @@ class EntityManager {
|
|
|
1029
1030
|
}
|
|
1030
1031
|
const em = this.getContext(false);
|
|
1031
1032
|
if (!em.transactionContext) {
|
|
1032
|
-
throw
|
|
1033
|
+
throw ValidationError.transactionRequired();
|
|
1033
1034
|
}
|
|
1034
|
-
await em.getConnection('write').rollback(em.transactionContext, new
|
|
1035
|
+
await em.getConnection('write').rollback(em.transactionContext, new TransactionEventBroadcaster(em));
|
|
1035
1036
|
delete em.transactionContext;
|
|
1036
1037
|
em.unitOfWork.clearActionsQueue();
|
|
1037
1038
|
}
|
|
@@ -1039,7 +1040,7 @@ class EntityManager {
|
|
|
1039
1040
|
* Runs your callback wrapped inside a database transaction.
|
|
1040
1041
|
*/
|
|
1041
1042
|
async lock(entity, lockMode, options = {}) {
|
|
1042
|
-
options =
|
|
1043
|
+
options = Utils.isPlainObject(options) ? options : { lockVersion: options };
|
|
1043
1044
|
await this.getUnitOfWork().lock(entity, { lockMode, ...options });
|
|
1044
1045
|
}
|
|
1045
1046
|
/**
|
|
@@ -1054,25 +1055,25 @@ class EntityManager {
|
|
|
1054
1055
|
data = entityNameOrEntity;
|
|
1055
1056
|
}
|
|
1056
1057
|
else {
|
|
1057
|
-
entityName =
|
|
1058
|
+
entityName = Utils.className(entityNameOrEntity);
|
|
1058
1059
|
}
|
|
1059
|
-
if (
|
|
1060
|
-
if (options.schema &&
|
|
1061
|
-
|
|
1060
|
+
if (Utils.isEntity(data)) {
|
|
1061
|
+
if (options.schema && helper(data).getSchema() == null) {
|
|
1062
|
+
helper(data).setSchema(options.schema);
|
|
1062
1063
|
}
|
|
1063
|
-
if (!
|
|
1064
|
+
if (!helper(data).__managed) {
|
|
1064
1065
|
// the entity might have been created via `em.create()`, which adds it to the persist stack automatically
|
|
1065
1066
|
em.unitOfWork.getPersistStack().delete(data);
|
|
1066
1067
|
// it can be also in the identity map if it had a PK value already
|
|
1067
1068
|
em.unitOfWork.unsetIdentity(data);
|
|
1068
1069
|
}
|
|
1069
|
-
const meta =
|
|
1070
|
+
const meta = helper(data).__meta;
|
|
1070
1071
|
const payload = em.comparator.prepareEntity(data);
|
|
1071
|
-
const cs = new
|
|
1072
|
+
const cs = new ChangeSet(data, ChangeSetType.CREATE, payload, meta);
|
|
1072
1073
|
await em.unitOfWork.getChangeSetPersister().executeInserts([cs], { ctx: em.transactionContext, ...options });
|
|
1073
1074
|
return cs.getPrimaryKey();
|
|
1074
1075
|
}
|
|
1075
|
-
data =
|
|
1076
|
+
data = QueryHelper.processObjectParams(data);
|
|
1076
1077
|
em.validator.validateParams(data, 'insert data');
|
|
1077
1078
|
const res = await em.driver.nativeInsert(entityName, data, { ctx: em.transactionContext, ...options });
|
|
1078
1079
|
return res.insertId;
|
|
@@ -1089,30 +1090,30 @@ class EntityManager {
|
|
|
1089
1090
|
data = entityNameOrEntities;
|
|
1090
1091
|
}
|
|
1091
1092
|
else {
|
|
1092
|
-
entityName =
|
|
1093
|
+
entityName = Utils.className(entityNameOrEntities);
|
|
1093
1094
|
}
|
|
1094
1095
|
if (data.length === 0) {
|
|
1095
1096
|
return [];
|
|
1096
1097
|
}
|
|
1097
|
-
if (
|
|
1098
|
-
const meta =
|
|
1098
|
+
if (Utils.isEntity(data[0])) {
|
|
1099
|
+
const meta = helper(data[0]).__meta;
|
|
1099
1100
|
const css = data.map(row => {
|
|
1100
|
-
if (options.schema &&
|
|
1101
|
-
|
|
1101
|
+
if (options.schema && helper(row).getSchema() == null) {
|
|
1102
|
+
helper(row).setSchema(options.schema);
|
|
1102
1103
|
}
|
|
1103
|
-
if (!
|
|
1104
|
+
if (!helper(row).__managed) {
|
|
1104
1105
|
// the entity might have been created via `em.create()`, which adds it to the persist stack automatically
|
|
1105
1106
|
em.unitOfWork.getPersistStack().delete(row);
|
|
1106
1107
|
// it can be also in the identity map if it had a PK value already
|
|
1107
1108
|
em.unitOfWork.unsetIdentity(row);
|
|
1108
1109
|
}
|
|
1109
1110
|
const payload = em.comparator.prepareEntity(row);
|
|
1110
|
-
return new
|
|
1111
|
+
return new ChangeSet(row, ChangeSetType.CREATE, payload, meta);
|
|
1111
1112
|
});
|
|
1112
1113
|
await em.unitOfWork.getChangeSetPersister().executeInserts(css, { ctx: em.transactionContext, ...options });
|
|
1113
1114
|
return css.map(cs => cs.getPrimaryKey());
|
|
1114
1115
|
}
|
|
1115
|
-
data = data.map(row =>
|
|
1116
|
+
data = data.map(row => QueryHelper.processObjectParams(row));
|
|
1116
1117
|
data.forEach(row => em.validator.validateParams(row, 'insert data'));
|
|
1117
1118
|
const res = await em.driver.nativeInsertMany(entityName, data, { ctx: em.transactionContext, ...options });
|
|
1118
1119
|
if (res.insertedIds) {
|
|
@@ -1126,8 +1127,8 @@ class EntityManager {
|
|
|
1126
1127
|
async nativeUpdate(entityName, where, data, options = {}) {
|
|
1127
1128
|
const em = this.getContext(false);
|
|
1128
1129
|
em.prepareOptions(options);
|
|
1129
|
-
entityName =
|
|
1130
|
-
data =
|
|
1130
|
+
entityName = Utils.className(entityName);
|
|
1131
|
+
data = QueryHelper.processObjectParams(data);
|
|
1131
1132
|
where = await em.processWhere(entityName, where, { ...options, convertCustomTypes: false }, 'update');
|
|
1132
1133
|
em.validator.validateParams(data, 'update data');
|
|
1133
1134
|
em.validator.validateParams(where, 'update condition');
|
|
@@ -1140,7 +1141,7 @@ class EntityManager {
|
|
|
1140
1141
|
async nativeDelete(entityName, where, options = {}) {
|
|
1141
1142
|
const em = this.getContext(false);
|
|
1142
1143
|
em.prepareOptions(options);
|
|
1143
|
-
entityName =
|
|
1144
|
+
entityName = Utils.className(entityName);
|
|
1144
1145
|
where = await em.processWhere(entityName, where, options, 'delete');
|
|
1145
1146
|
em.validator.validateParams(where, 'delete condition');
|
|
1146
1147
|
const res = await em.driver.nativeDelete(entityName, where, { ctx: em.transactionContext, ...options });
|
|
@@ -1150,12 +1151,12 @@ class EntityManager {
|
|
|
1150
1151
|
* Maps raw database result to an entity and merges it to this EntityManager.
|
|
1151
1152
|
*/
|
|
1152
1153
|
map(entityName, result, options = {}) {
|
|
1153
|
-
entityName =
|
|
1154
|
+
entityName = Utils.className(entityName);
|
|
1154
1155
|
const meta = this.metadata.get(entityName);
|
|
1155
1156
|
const data = this.driver.mapResult(result, meta);
|
|
1156
1157
|
Object.keys(data).forEach(k => {
|
|
1157
1158
|
const prop = meta.properties[k];
|
|
1158
|
-
if (prop && prop.kind ===
|
|
1159
|
+
if (prop && prop.kind === ReferenceKind.SCALAR && SCALAR_TYPES.includes(prop.runtimeType) && !prop.customType && (prop.setter || !prop.getter)) {
|
|
1159
1160
|
data[k] = this.validator.validateProperty(prop, data[k], data);
|
|
1160
1161
|
}
|
|
1161
1162
|
});
|
|
@@ -1170,19 +1171,19 @@ class EntityManager {
|
|
|
1170
1171
|
*/
|
|
1171
1172
|
merge(entityName, data, options = {}) {
|
|
1172
1173
|
const em = this.getContext();
|
|
1173
|
-
if (
|
|
1174
|
+
if (Utils.isEntity(entityName)) {
|
|
1174
1175
|
return em.merge(entityName.constructor.name, entityName, data);
|
|
1175
1176
|
}
|
|
1176
1177
|
options.schema ??= em._schema;
|
|
1177
|
-
entityName =
|
|
1178
|
+
entityName = Utils.className(entityName);
|
|
1178
1179
|
em.validator.validatePrimaryKey(data, em.metadata.get(entityName));
|
|
1179
1180
|
let entity = em.unitOfWork.tryGetById(entityName, data, options.schema, false);
|
|
1180
|
-
if (entity &&
|
|
1181
|
+
if (entity && helper(entity).__managed && helper(entity).__initialized && !options.refresh) {
|
|
1181
1182
|
return entity;
|
|
1182
1183
|
}
|
|
1183
1184
|
const meta = em.metadata.find(entityName);
|
|
1184
1185
|
const childMeta = em.metadata.getByDiscriminatorColumn(meta, data);
|
|
1185
|
-
entity =
|
|
1186
|
+
entity = Utils.isEntity(data) ? data : em.entityFactory.create(entityName, data, { merge: true, ...options });
|
|
1186
1187
|
em.validator.validate(entity, data, childMeta ?? meta);
|
|
1187
1188
|
em.unitOfWork.merge(entity);
|
|
1188
1189
|
return entity;
|
|
@@ -1220,7 +1221,7 @@ class EntityManager {
|
|
|
1220
1221
|
* Shortcut for `wrap(entity).assign(data, { em })`
|
|
1221
1222
|
*/
|
|
1222
1223
|
assign(entity, data, options = {}) {
|
|
1223
|
-
return
|
|
1224
|
+
return EntityAssigner.assign(entity, data, { em: this.getContext(), ...options });
|
|
1224
1225
|
}
|
|
1225
1226
|
/**
|
|
1226
1227
|
* Gets a reference to the entity identified by the given type and identifier without actually loading it, if the entity is not yet loaded
|
|
@@ -1228,16 +1229,16 @@ class EntityManager {
|
|
|
1228
1229
|
getReference(entityName, id, options = {}) {
|
|
1229
1230
|
options.schema ??= this.schema;
|
|
1230
1231
|
options.convertCustomTypes ??= false;
|
|
1231
|
-
const meta = this.metadata.get(
|
|
1232
|
-
if (
|
|
1232
|
+
const meta = this.metadata.get(Utils.className(entityName));
|
|
1233
|
+
if (Utils.isPrimaryKey(id)) {
|
|
1233
1234
|
if (meta.compositePK) {
|
|
1234
|
-
throw
|
|
1235
|
+
throw ValidationError.invalidCompositeIdentifier(meta);
|
|
1235
1236
|
}
|
|
1236
1237
|
id = [id];
|
|
1237
1238
|
}
|
|
1238
1239
|
const entity = this.getEntityFactory().createReference(entityName, id, { merge: true, ...options });
|
|
1239
1240
|
if (options.wrapped) {
|
|
1240
|
-
return
|
|
1241
|
+
return Reference.create(entity);
|
|
1241
1242
|
}
|
|
1242
1243
|
return entity;
|
|
1243
1244
|
}
|
|
@@ -1251,7 +1252,7 @@ class EntityManager {
|
|
|
1251
1252
|
schema: em._schema,
|
|
1252
1253
|
...options,
|
|
1253
1254
|
};
|
|
1254
|
-
entityName =
|
|
1255
|
+
entityName = Utils.className(entityName);
|
|
1255
1256
|
await em.tryFlush(entityName, options);
|
|
1256
1257
|
where = await em.processWhere(entityName, where, options, 'read');
|
|
1257
1258
|
options.populate = await em.preparePopulate(entityName, options);
|
|
@@ -1278,20 +1279,20 @@ class EntityManager {
|
|
|
1278
1279
|
*/
|
|
1279
1280
|
persist(entity) {
|
|
1280
1281
|
const em = this.getContext();
|
|
1281
|
-
if (
|
|
1282
|
+
if (Utils.isEntity(entity)) {
|
|
1282
1283
|
// do not cascade just yet, cascading of entities in persist stack is done when flushing
|
|
1283
1284
|
em.unitOfWork.persist(entity, undefined, { cascade: false });
|
|
1284
1285
|
return em;
|
|
1285
1286
|
}
|
|
1286
|
-
const entities =
|
|
1287
|
+
const entities = Utils.asArray(entity);
|
|
1287
1288
|
for (const ent of entities) {
|
|
1288
|
-
if (!
|
|
1289
|
-
/*
|
|
1289
|
+
if (!Utils.isEntity(ent, true)) {
|
|
1290
|
+
/* v8 ignore next */
|
|
1290
1291
|
const meta = typeof ent === 'object' ? em.metadata.find(ent.constructor.name) : undefined;
|
|
1291
|
-
throw
|
|
1292
|
+
throw ValidationError.notDiscoveredEntity(ent, meta);
|
|
1292
1293
|
}
|
|
1293
1294
|
// do not cascade just yet, cascading of entities in persist stack is done when flushing
|
|
1294
|
-
em.unitOfWork.persist(
|
|
1295
|
+
em.unitOfWork.persist(Reference.unwrapReference(ent), undefined, { cascade: false });
|
|
1295
1296
|
}
|
|
1296
1297
|
return this;
|
|
1297
1298
|
}
|
|
@@ -1310,18 +1311,18 @@ class EntityManager {
|
|
|
1310
1311
|
*/
|
|
1311
1312
|
remove(entity) {
|
|
1312
1313
|
const em = this.getContext();
|
|
1313
|
-
if (
|
|
1314
|
+
if (Utils.isEntity(entity)) {
|
|
1314
1315
|
// do not cascade just yet, cascading of entities in persist stack is done when flushing
|
|
1315
1316
|
em.unitOfWork.remove(entity, undefined, { cascade: false });
|
|
1316
1317
|
return em;
|
|
1317
1318
|
}
|
|
1318
|
-
const entities =
|
|
1319
|
+
const entities = Utils.asArray(entity, true);
|
|
1319
1320
|
for (const ent of entities) {
|
|
1320
|
-
if (!
|
|
1321
|
+
if (!Utils.isEntity(ent, true)) {
|
|
1321
1322
|
throw new Error(`You need to pass entity instance or reference to 'em.remove()'. To remove entities by condition, use 'em.nativeDelete()'.`);
|
|
1322
1323
|
}
|
|
1323
1324
|
// do not cascade just yet, cascading of entities in remove stack is done when flushing
|
|
1324
|
-
em.unitOfWork.remove(
|
|
1325
|
+
em.unitOfWork.remove(Reference.unwrapReference(ent), undefined, { cascade: false });
|
|
1325
1326
|
}
|
|
1326
1327
|
return em;
|
|
1327
1328
|
}
|
|
@@ -1345,12 +1346,12 @@ class EntityManager {
|
|
|
1345
1346
|
async tryFlush(entityName, options) {
|
|
1346
1347
|
const em = this.getContext();
|
|
1347
1348
|
const flushMode = options.flushMode ?? em.flushMode ?? em.config.get('flushMode');
|
|
1348
|
-
entityName =
|
|
1349
|
+
entityName = Utils.className(entityName);
|
|
1349
1350
|
const meta = em.metadata.get(entityName);
|
|
1350
|
-
if (flushMode ===
|
|
1351
|
+
if (flushMode === FlushMode.COMMIT) {
|
|
1351
1352
|
return;
|
|
1352
1353
|
}
|
|
1353
|
-
if (flushMode ===
|
|
1354
|
+
if (flushMode === FlushMode.ALWAYS || em.getUnitOfWork().shouldAutoFlush(meta)) {
|
|
1354
1355
|
await em.flush();
|
|
1355
1356
|
}
|
|
1356
1357
|
}
|
|
@@ -1364,7 +1365,7 @@ class EntityManager {
|
|
|
1364
1365
|
* Checks whether given property can be populated on the entity.
|
|
1365
1366
|
*/
|
|
1366
1367
|
canPopulate(entityName, property) {
|
|
1367
|
-
entityName =
|
|
1368
|
+
entityName = Utils.className(entityName);
|
|
1368
1369
|
// eslint-disable-next-line prefer-const
|
|
1369
1370
|
let [p, ...parts] = property.split('.');
|
|
1370
1371
|
const meta = this.metadata.find(entityName);
|
|
@@ -1387,7 +1388,7 @@ class EntityManager {
|
|
|
1387
1388
|
* Loads specified relations in batch. This will execute one query for each relation, that will populate it on all the specified entities.
|
|
1388
1389
|
*/
|
|
1389
1390
|
async populate(entities, populate, options = {}) {
|
|
1390
|
-
const arr =
|
|
1391
|
+
const arr = Utils.asArray(entities);
|
|
1391
1392
|
if (arr.length === 0) {
|
|
1392
1393
|
return entities;
|
|
1393
1394
|
}
|
|
@@ -1408,7 +1409,7 @@ class EntityManager {
|
|
|
1408
1409
|
options.freshEventManager ??= false;
|
|
1409
1410
|
options.cloneEventManager ??= false;
|
|
1410
1411
|
const eventManager = options.freshEventManager
|
|
1411
|
-
? new
|
|
1412
|
+
? new EventManager(em.config.get('subscribers'))
|
|
1412
1413
|
: options.cloneEventManager
|
|
1413
1414
|
? em.eventManager.clone()
|
|
1414
1415
|
: em.eventManager;
|
|
@@ -1423,8 +1424,8 @@ class EntityManager {
|
|
|
1423
1424
|
fork.transactionContext = em.transactionContext;
|
|
1424
1425
|
}
|
|
1425
1426
|
fork.filters = { ...em.filters };
|
|
1426
|
-
fork.filterParams =
|
|
1427
|
-
fork.loggerContext =
|
|
1427
|
+
fork.filterParams = Utils.copy(em.filterParams);
|
|
1428
|
+
fork.loggerContext = Utils.merge({}, em.loggerContext, options.loggerContext);
|
|
1428
1429
|
fork._schema = options.schema ?? em._schema;
|
|
1429
1430
|
if (!options.clear) {
|
|
1430
1431
|
for (const entity of em.unitOfWork.getIdentityMap()) {
|
|
@@ -1465,14 +1466,14 @@ class EntityManager {
|
|
|
1465
1466
|
if (!this.useContext) {
|
|
1466
1467
|
return this;
|
|
1467
1468
|
}
|
|
1468
|
-
let em =
|
|
1469
|
+
let em = TransactionContext.getEntityManager(this.name); // prefer the tx context
|
|
1469
1470
|
if (em) {
|
|
1470
1471
|
return em;
|
|
1471
1472
|
}
|
|
1472
1473
|
// no explicit tx started
|
|
1473
1474
|
em = this.config.get('context')(this.name) ?? this;
|
|
1474
1475
|
if (validate && !this.config.get('allowGlobalContext') && em.global) {
|
|
1475
|
-
throw
|
|
1476
|
+
throw ValidationError.cannotUseGlobalContext();
|
|
1476
1477
|
}
|
|
1477
1478
|
return em;
|
|
1478
1479
|
}
|
|
@@ -1513,7 +1514,7 @@ class EntityManager {
|
|
|
1513
1514
|
*/
|
|
1514
1515
|
getMetadata(entityName) {
|
|
1515
1516
|
if (entityName) {
|
|
1516
|
-
entityName =
|
|
1517
|
+
entityName = Utils.className(entityName);
|
|
1517
1518
|
return this.metadata.get(entityName);
|
|
1518
1519
|
}
|
|
1519
1520
|
return this.metadata;
|
|
@@ -1528,15 +1529,15 @@ class EntityManager {
|
|
|
1528
1529
|
if (!mode) {
|
|
1529
1530
|
return;
|
|
1530
1531
|
}
|
|
1531
|
-
if (mode ===
|
|
1532
|
-
throw
|
|
1532
|
+
if (mode === LockMode.OPTIMISTIC && !meta.versionProperty) {
|
|
1533
|
+
throw OptimisticLockError.notVersioned(meta);
|
|
1533
1534
|
}
|
|
1534
|
-
if ([
|
|
1535
|
-
throw
|
|
1535
|
+
if ([LockMode.PESSIMISTIC_READ, LockMode.PESSIMISTIC_WRITE].includes(mode) && !this.isInTransaction()) {
|
|
1536
|
+
throw ValidationError.transactionRequired();
|
|
1536
1537
|
}
|
|
1537
1538
|
}
|
|
1538
1539
|
async lockAndPopulate(meta, entity, where, options) {
|
|
1539
|
-
if (!meta.virtual && options.lockMode ===
|
|
1540
|
+
if (!meta.virtual && options.lockMode === LockMode.OPTIMISTIC) {
|
|
1540
1541
|
await this.lock(entity, options.lockMode, {
|
|
1541
1542
|
lockVersion: options.lockVersion,
|
|
1542
1543
|
lockTableAliases: options.lockTableAliases,
|
|
@@ -1555,8 +1556,8 @@ class EntityManager {
|
|
|
1555
1556
|
}
|
|
1556
1557
|
buildFields(fields) {
|
|
1557
1558
|
return fields.reduce((ret, f) => {
|
|
1558
|
-
if (
|
|
1559
|
-
|
|
1559
|
+
if (Utils.isPlainObject(f)) {
|
|
1560
|
+
Utils.keys(f).forEach(ff => ret.push(...this.buildFields(f[ff]).map(field => `${ff}.${field}`)));
|
|
1560
1561
|
}
|
|
1561
1562
|
else {
|
|
1562
1563
|
ret.push(f);
|
|
@@ -1575,12 +1576,12 @@ class EntityManager {
|
|
|
1575
1576
|
const pruneToOneRelations = (meta, fields) => {
|
|
1576
1577
|
const ret = [];
|
|
1577
1578
|
for (let field of fields) {
|
|
1578
|
-
if (field ===
|
|
1579
|
-
ret.push(...meta.props.filter(prop => prop.lazy || [
|
|
1579
|
+
if (field === PopulatePath.ALL || field.startsWith(`${PopulatePath.ALL}.`)) {
|
|
1580
|
+
ret.push(...meta.props.filter(prop => prop.lazy || [ReferenceKind.SCALAR, ReferenceKind.EMBEDDED].includes(prop.kind)).map(prop => prop.name));
|
|
1580
1581
|
continue;
|
|
1581
1582
|
}
|
|
1582
1583
|
field = field.split(':')[0];
|
|
1583
|
-
if (!field.includes('.') && ![
|
|
1584
|
+
if (!field.includes('.') && ![ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(meta.properties[field].kind)) {
|
|
1584
1585
|
ret.push(field);
|
|
1585
1586
|
continue;
|
|
1586
1587
|
}
|
|
@@ -1599,7 +1600,7 @@ class EntityManager {
|
|
|
1599
1600
|
ret.push(...inner.map(c => `${key}.${c}`));
|
|
1600
1601
|
}
|
|
1601
1602
|
}
|
|
1602
|
-
return
|
|
1603
|
+
return Utils.unique(ret);
|
|
1603
1604
|
};
|
|
1604
1605
|
options.populate = pruneToOneRelations(meta, this.buildFields(options.fields));
|
|
1605
1606
|
}
|
|
@@ -1609,18 +1610,18 @@ class EntityManager {
|
|
|
1609
1610
|
return populate;
|
|
1610
1611
|
}
|
|
1611
1612
|
if (typeof options.populate !== 'boolean') {
|
|
1612
|
-
options.populate =
|
|
1613
|
-
/*
|
|
1614
|
-
if (typeof field === 'boolean' || field ===
|
|
1613
|
+
options.populate = Utils.asArray(options.populate).map(field => {
|
|
1614
|
+
/* v8 ignore next 3 */
|
|
1615
|
+
if (typeof field === 'boolean' || field === PopulatePath.ALL) {
|
|
1615
1616
|
return [{ field: meta.primaryKeys[0], strategy: options.strategy, all: !!field }]; //
|
|
1616
1617
|
}
|
|
1617
1618
|
// will be handled in QueryBuilder when processing the where condition via CriteriaNode
|
|
1618
|
-
if (field ===
|
|
1619
|
+
if (field === PopulatePath.INFER) {
|
|
1619
1620
|
options.flags ??= [];
|
|
1620
|
-
options.flags.push(
|
|
1621
|
+
options.flags.push(QueryFlag.INFER_POPULATE);
|
|
1621
1622
|
return [];
|
|
1622
1623
|
}
|
|
1623
|
-
if (
|
|
1624
|
+
if (Utils.isString(field)) {
|
|
1624
1625
|
return [{ field, strategy: options.strategy }];
|
|
1625
1626
|
}
|
|
1626
1627
|
return [field];
|
|
@@ -1629,13 +1630,13 @@ class EntityManager {
|
|
|
1629
1630
|
const populate = this.entityLoader.normalizePopulate(entityName, options.populate, options.strategy);
|
|
1630
1631
|
const invalid = populate.find(({ field }) => !this.canPopulate(entityName, field));
|
|
1631
1632
|
if (validate && invalid) {
|
|
1632
|
-
throw
|
|
1633
|
+
throw ValidationError.invalidPropertyName(entityName, invalid.field);
|
|
1633
1634
|
}
|
|
1634
1635
|
await this.autoJoinRefsForFilters(meta, { ...options, populate });
|
|
1635
1636
|
return populate.map(field => {
|
|
1636
1637
|
// force select-in strategy when populating all relations as otherwise we could cause infinite loops when self-referencing
|
|
1637
1638
|
const all = field.all ?? (Array.isArray(options.populate) && options.populate.includes('*'));
|
|
1638
|
-
field.strategy = all ?
|
|
1639
|
+
field.strategy = all ? LoadStrategy.SELECT_IN : (options.strategy ?? field.strategy);
|
|
1639
1640
|
return field;
|
|
1640
1641
|
});
|
|
1641
1642
|
}
|
|
@@ -1644,33 +1645,33 @@ class EntityManager {
|
|
|
1644
1645
|
* some additional lazy properties, if so, we reload and merge the data from database
|
|
1645
1646
|
*/
|
|
1646
1647
|
shouldRefresh(meta, entity, options) {
|
|
1647
|
-
if (!
|
|
1648
|
+
if (!helper(entity).__initialized || options.refresh) {
|
|
1648
1649
|
return true;
|
|
1649
1650
|
}
|
|
1650
1651
|
let autoRefresh;
|
|
1651
1652
|
if (options.fields) {
|
|
1652
|
-
autoRefresh = options.fields.some(field => !
|
|
1653
|
+
autoRefresh = options.fields.some(field => !helper(entity).__loadedProperties.has(field));
|
|
1653
1654
|
}
|
|
1654
1655
|
else {
|
|
1655
1656
|
autoRefresh = meta.comparableProps.some(prop => {
|
|
1656
|
-
const inlineEmbedded = prop.kind ===
|
|
1657
|
-
return !inlineEmbedded && !prop.lazy && !
|
|
1657
|
+
const inlineEmbedded = prop.kind === ReferenceKind.EMBEDDED && !prop.object;
|
|
1658
|
+
return !inlineEmbedded && !prop.lazy && !helper(entity).__loadedProperties.has(prop.name);
|
|
1658
1659
|
});
|
|
1659
1660
|
}
|
|
1660
1661
|
if (autoRefresh) {
|
|
1661
1662
|
return true;
|
|
1662
1663
|
}
|
|
1663
1664
|
if (Array.isArray(options.populate)) {
|
|
1664
|
-
return options.populate.some(field => !
|
|
1665
|
+
return options.populate.some(field => !helper(entity).__loadedProperties.has(field));
|
|
1665
1666
|
}
|
|
1666
1667
|
return !!options.populate;
|
|
1667
1668
|
}
|
|
1668
1669
|
prepareOptions(options) {
|
|
1669
|
-
if (!
|
|
1670
|
-
throw new
|
|
1670
|
+
if (!Utils.isEmpty(options.fields) && !Utils.isEmpty(options.exclude)) {
|
|
1671
|
+
throw new ValidationError(`Cannot combine 'fields' and 'exclude' option.`);
|
|
1671
1672
|
}
|
|
1672
1673
|
options.schema ??= this._schema;
|
|
1673
|
-
options.logging =
|
|
1674
|
+
options.logging = Utils.merge({ id: this.id }, this.loggerContext, options.loggerContext, options.logging);
|
|
1674
1675
|
}
|
|
1675
1676
|
/**
|
|
1676
1677
|
* @internal
|
|
@@ -1704,7 +1705,7 @@ class EntityManager {
|
|
|
1704
1705
|
recomputeSnapshot: true,
|
|
1705
1706
|
}));
|
|
1706
1707
|
}
|
|
1707
|
-
else if (
|
|
1708
|
+
else if (Utils.isObject(cached) && merge) {
|
|
1708
1709
|
data = em.entityFactory.create(entityName, cached, {
|
|
1709
1710
|
merge: true,
|
|
1710
1711
|
convertCustomTypes: true,
|
|
@@ -1727,7 +1728,7 @@ class EntityManager {
|
|
|
1727
1728
|
config ??= this.config.get('resultCache').global;
|
|
1728
1729
|
if (config) {
|
|
1729
1730
|
const em = this.getContext();
|
|
1730
|
-
const expiration = Array.isArray(config) ? config[1] : (
|
|
1731
|
+
const expiration = Array.isArray(config) ? config[1] : (Utils.isNumber(config) ? config : undefined);
|
|
1731
1732
|
await em.resultCache.set(key.key, data instanceof Function ? data() : data, '', expiration);
|
|
1732
1733
|
}
|
|
1733
1734
|
}
|
|
@@ -1768,8 +1769,7 @@ class EntityManager {
|
|
|
1768
1769
|
return this.getContext(false)._id;
|
|
1769
1770
|
}
|
|
1770
1771
|
/** @ignore */
|
|
1771
|
-
[
|
|
1772
|
+
[inspect.custom]() {
|
|
1772
1773
|
return `[EntityManager<${this.id}>]`;
|
|
1773
1774
|
}
|
|
1774
1775
|
}
|
|
1775
|
-
exports.EntityManager = EntityManager;
|