@mikro-orm/core 7.0.0-dev.1 → 7.0.0-dev.100
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 +96 -58
- package/EntityManager.js +465 -395
- package/MikroORM.d.ts +45 -35
- package/MikroORM.js +109 -160
- package/README.md +3 -2
- package/cache/CacheAdapter.js +1 -2
- package/cache/FileCacheAdapter.d.ts +2 -2
- package/cache/FileCacheAdapter.js +20 -27
- package/cache/GeneratedCacheAdapter.d.ts +2 -3
- package/cache/GeneratedCacheAdapter.js +1 -7
- 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 +4 -5
- package/cache/index.js +4 -21
- package/connections/Connection.d.ts +22 -14
- package/connections/Connection.js +27 -23
- package/connections/index.d.ts +1 -1
- package/connections/index.js +1 -17
- package/drivers/DatabaseDriver.d.ts +25 -15
- package/drivers/DatabaseDriver.js +77 -64
- package/drivers/IDatabaseDriver.d.ts +40 -16
- package/drivers/IDatabaseDriver.js +1 -4
- package/drivers/index.d.ts +2 -2
- package/drivers/index.js +2 -18
- package/entity/BaseEntity.d.ts +6 -7
- package/entity/BaseEntity.js +16 -23
- package/entity/Collection.d.ts +98 -34
- package/entity/Collection.js +466 -131
- package/entity/EntityAssigner.d.ts +3 -3
- package/entity/EntityAssigner.js +67 -64
- package/entity/EntityFactory.d.ts +10 -3
- package/entity/EntityFactory.js +112 -91
- package/entity/EntityHelper.d.ts +2 -2
- package/entity/EntityHelper.js +66 -53
- package/entity/EntityIdentifier.d.ts +1 -1
- package/entity/EntityIdentifier.js +1 -5
- package/entity/EntityLoader.d.ts +8 -7
- package/entity/EntityLoader.js +161 -128
- package/entity/EntityRepository.d.ts +8 -8
- package/entity/EntityRepository.js +7 -11
- package/entity/Reference.d.ts +10 -13
- package/entity/Reference.js +64 -46
- package/entity/WrappedEntity.d.ts +12 -17
- package/entity/WrappedEntity.js +22 -31
- package/entity/defineEntity.d.ts +568 -0
- package/entity/defineEntity.js +529 -0
- package/entity/index.d.ts +14 -13
- package/entity/index.js +14 -29
- package/entity/utils.d.ts +8 -1
- package/entity/utils.js +22 -13
- package/entity/validators.d.ts +11 -0
- package/entity/validators.js +65 -0
- package/entity/wrap.d.ts +1 -1
- package/entity/wrap.js +2 -6
- package/enums.d.ts +24 -9
- package/enums.js +50 -41
- package/errors.d.ts +11 -3
- package/errors.js +42 -32
- package/events/EventManager.d.ts +5 -4
- package/events/EventManager.js +26 -22
- package/events/EventSubscriber.d.ts +8 -5
- 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 +2 -6
- package/hydration/ObjectHydrator.d.ts +7 -7
- package/hydration/ObjectHydrator.js +58 -50
- package/hydration/index.d.ts +2 -2
- package/hydration/index.js +2 -18
- package/index.d.ts +21 -21
- package/index.js +20 -46
- package/logging/DefaultLogger.d.ts +2 -2
- package/logging/DefaultLogger.js +10 -13
- package/logging/Logger.d.ts +1 -1
- package/logging/Logger.js +1 -2
- package/logging/SimpleLogger.d.ts +3 -3
- package/logging/SimpleLogger.js +2 -6
- package/logging/colors.js +1 -5
- package/logging/index.d.ts +5 -4
- package/logging/index.js +5 -20
- package/logging/inspect.d.ts +2 -0
- package/logging/inspect.js +16 -0
- package/metadata/EntitySchema.d.ts +14 -10
- package/metadata/EntitySchema.js +78 -64
- package/metadata/MetadataDiscovery.d.ts +11 -14
- package/metadata/MetadataDiscovery.js +278 -317
- package/metadata/MetadataProvider.d.ts +13 -4
- package/metadata/MetadataProvider.js +47 -8
- package/metadata/MetadataStorage.d.ts +2 -7
- package/metadata/MetadataStorage.js +19 -35
- package/metadata/MetadataValidator.d.ts +3 -10
- package/metadata/MetadataValidator.js +51 -64
- package/metadata/discover-entities.d.ts +5 -0
- package/metadata/discover-entities.js +40 -0
- package/metadata/index.d.ts +6 -6
- package/metadata/index.js +6 -22
- package/metadata/types.d.ts +480 -0
- package/metadata/types.js +1 -0
- package/naming-strategy/AbstractNamingStrategy.d.ts +7 -3
- package/naming-strategy/AbstractNamingStrategy.js +11 -9
- 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 +12 -2
- 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/not-supported.d.ts +2 -0
- package/not-supported.js +4 -0
- package/package.json +19 -20
- package/platforms/ExceptionConverter.d.ts +2 -2
- package/platforms/ExceptionConverter.js +4 -8
- package/platforms/Platform.d.ts +15 -22
- package/platforms/Platform.js +58 -88
- package/platforms/index.d.ts +2 -2
- package/platforms/index.js +2 -18
- package/serialization/EntitySerializer.d.ts +4 -2
- package/serialization/EntitySerializer.js +64 -51
- package/serialization/EntityTransformer.d.ts +1 -1
- package/serialization/EntityTransformer.js +48 -42
- package/serialization/SerializationContext.d.ts +2 -2
- package/serialization/SerializationContext.js +24 -25
- package/serialization/index.d.ts +3 -3
- package/serialization/index.js +3 -19
- package/types/ArrayType.d.ts +3 -3
- package/types/ArrayType.js +6 -11
- package/types/BigIntType.d.ts +12 -9
- package/types/BigIntType.js +6 -6
- package/types/BlobType.d.ts +3 -4
- package/types/BlobType.js +2 -11
- package/types/BooleanType.d.ts +5 -4
- package/types/BooleanType.js +5 -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 +9 -7
- package/types/DecimalType.js +5 -8
- package/types/DoubleType.d.ts +3 -3
- package/types/DoubleType.js +4 -7
- package/types/EnumArrayType.d.ts +4 -4
- package/types/EnumArrayType.js +4 -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 +4 -4
- package/types/JsonType.js +9 -8
- 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 +4 -6
- package/types/Type.js +6 -10
- package/types/Uint8ArrayType.d.ts +3 -4
- package/types/Uint8ArrayType.js +3 -12
- 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 +134 -93
- package/typings.js +67 -65
- package/unit-of-work/ChangeSet.d.ts +1 -4
- package/unit-of-work/ChangeSet.js +13 -17
- package/unit-of-work/ChangeSetComputer.d.ts +8 -9
- package/unit-of-work/ChangeSetComputer.js +36 -38
- package/unit-of-work/ChangeSetPersister.d.ts +11 -9
- package/unit-of-work/ChangeSetPersister.js +100 -65
- 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 +16 -8
- package/unit-of-work/UnitOfWork.js +266 -209
- package/unit-of-work/index.d.ts +6 -6
- package/unit-of-work/index.js +6 -22
- package/utils/AbstractSchemaGenerator.d.ts +11 -11
- package/utils/AbstractSchemaGenerator.js +21 -20
- package/utils/Configuration.d.ts +774 -224
- package/utils/Configuration.js +166 -216
- package/utils/ConfigurationLoader.d.ts +1 -53
- package/utils/ConfigurationLoader.js +1 -367
- package/utils/Cursor.d.ts +6 -9
- package/utils/Cursor.js +25 -25
- package/utils/DataloaderUtils.d.ts +18 -8
- package/utils/DataloaderUtils.js +63 -21
- package/utils/EntityComparator.d.ts +9 -5
- package/utils/EntityComparator.js +155 -108
- package/utils/NullHighlighter.d.ts +1 -1
- package/utils/NullHighlighter.js +1 -5
- package/utils/QueryHelper.d.ts +12 -4
- package/utils/QueryHelper.js +110 -53
- package/utils/RawQueryFragment.d.ts +37 -14
- package/utils/RawQueryFragment.js +50 -33
- 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/TransactionManager.d.ts +65 -0
- package/utils/TransactionManager.js +223 -0
- package/utils/Utils.d.ts +16 -100
- package/utils/Utils.js +114 -332
- package/utils/clone.js +7 -11
- package/utils/env-vars.d.ts +3 -0
- package/utils/env-vars.js +87 -0
- package/utils/fs-utils.d.ts +12 -0
- package/utils/fs-utils.js +97 -0
- package/utils/index.d.ts +14 -13
- package/utils/index.js +14 -29
- package/utils/upsert-utils.d.ts +8 -3
- package/utils/upsert-utils.js +57 -10
- package/decorators/Check.d.ts +0 -3
- package/decorators/Check.js +0 -16
- package/decorators/CreateRequestContext.d.ts +0 -3
- package/decorators/CreateRequestContext.js +0 -33
- package/decorators/Embeddable.d.ts +0 -8
- package/decorators/Embeddable.js +0 -14
- package/decorators/Embedded.d.ts +0 -18
- package/decorators/Embedded.js +0 -20
- package/decorators/Entity.d.ts +0 -18
- package/decorators/Entity.js +0 -16
- package/decorators/Enum.d.ts +0 -9
- package/decorators/Enum.js +0 -19
- package/decorators/Filter.d.ts +0 -2
- package/decorators/Filter.js +0 -11
- package/decorators/Formula.d.ts +0 -5
- package/decorators/Formula.js +0 -18
- package/decorators/Indexed.d.ts +0 -17
- package/decorators/Indexed.js +0 -24
- package/decorators/ManyToMany.d.ts +0 -40
- package/decorators/ManyToMany.js +0 -16
- package/decorators/ManyToOne.d.ts +0 -30
- package/decorators/ManyToOne.js +0 -16
- package/decorators/OneToMany.d.ts +0 -28
- package/decorators/OneToMany.js +0 -20
- package/decorators/OneToOne.d.ts +0 -24
- package/decorators/OneToOne.js +0 -10
- package/decorators/PrimaryKey.d.ts +0 -9
- package/decorators/PrimaryKey.js +0 -23
- package/decorators/Property.d.ts +0 -250
- package/decorators/Property.js +0 -34
- package/decorators/Transactional.d.ts +0 -13
- package/decorators/Transactional.js +0 -31
- package/decorators/hooks.d.ts +0 -16
- package/decorators/hooks.js +0 -59
- package/decorators/index.d.ts +0 -17
- package/decorators/index.js +0 -36
- package/entity/ArrayCollection.d.ts +0 -116
- package/entity/ArrayCollection.js +0 -399
- package/entity/EntityValidator.d.ts +0 -19
- package/entity/EntityValidator.js +0 -154
- package/index.mjs +0 -199
- package/metadata/ReflectMetadataProvider.d.ts +0 -8
- package/metadata/ReflectMetadataProvider.js +0 -48
- package/utils/resolveContextProvider.d.ts +0 -10
- package/utils/resolveContextProvider.js +0 -31
package/entity/EntityLoader.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const RawQueryFragment_1 = require("../utils/RawQueryFragment");
|
|
11
|
-
const utils_1 = require("./utils");
|
|
12
|
-
class EntityLoader {
|
|
1
|
+
import { QueryHelper } from '../utils/QueryHelper.js';
|
|
2
|
+
import { Utils } from '../utils/Utils.js';
|
|
3
|
+
import { ValidationError } from '../errors.js';
|
|
4
|
+
import { LoadStrategy, PopulatePath, ReferenceKind, } from '../enums.js';
|
|
5
|
+
import { Reference } from './Reference.js';
|
|
6
|
+
import { helper } from './wrap.js';
|
|
7
|
+
import { raw, RawQueryFragment } from '../utils/RawQueryFragment.js';
|
|
8
|
+
import { expandDotPaths } from './utils.js';
|
|
9
|
+
export class EntityLoader {
|
|
13
10
|
em;
|
|
14
11
|
metadata;
|
|
15
12
|
driver;
|
|
@@ -23,31 +20,30 @@ class EntityLoader {
|
|
|
23
20
|
* This will execute one query for each relation, that will populate it on all the specified entities.
|
|
24
21
|
*/
|
|
25
22
|
async populate(entityName, entities, populate, options) {
|
|
26
|
-
if (entities.length === 0 ||
|
|
23
|
+
if (entities.length === 0 || Utils.isEmpty(populate)) {
|
|
27
24
|
return this.setSerializationContext(entities, populate, options);
|
|
28
25
|
}
|
|
29
26
|
const meta = this.metadata.find(entityName);
|
|
30
27
|
if (entities.some(e => !e.__helper)) {
|
|
31
|
-
const entity = entities.find(e => !
|
|
32
|
-
throw
|
|
28
|
+
const entity = entities.find(e => !Utils.isEntity(e));
|
|
29
|
+
throw ValidationError.notDiscoveredEntity(entity, meta, 'populate');
|
|
33
30
|
}
|
|
34
|
-
const references = entities.filter(e => !
|
|
31
|
+
const references = entities.filter(e => !helper(e).isInitialized());
|
|
35
32
|
const visited = options.visited ??= new Set();
|
|
36
33
|
options.where ??= {};
|
|
37
34
|
options.orderBy ??= {};
|
|
38
|
-
options.filters ??= {};
|
|
39
35
|
options.lookup ??= true;
|
|
40
36
|
options.validate ??= true;
|
|
41
37
|
options.refresh ??= false;
|
|
42
38
|
options.convertCustomTypes ??= true;
|
|
43
39
|
if (references.length > 0) {
|
|
44
|
-
await this.populateScalar(meta, references, options);
|
|
40
|
+
await this.populateScalar(meta, references, { ...options, populateWhere: undefined });
|
|
45
41
|
}
|
|
46
42
|
populate = this.normalizePopulate(entityName, populate, options.strategy, options.lookup);
|
|
47
43
|
const invalid = populate.find(({ field }) => !this.em.canPopulate(entityName, field));
|
|
48
|
-
/*
|
|
44
|
+
/* v8 ignore next */
|
|
49
45
|
if (options.validate && invalid) {
|
|
50
|
-
throw
|
|
46
|
+
throw ValidationError.invalidPropertyName(entityName, invalid.field);
|
|
51
47
|
}
|
|
52
48
|
this.setSerializationContext(entities, populate, options);
|
|
53
49
|
for (const entity of entities) {
|
|
@@ -62,25 +58,25 @@ class EntityLoader {
|
|
|
62
58
|
}
|
|
63
59
|
normalizePopulate(entityName, populate, strategy, lookup = true) {
|
|
64
60
|
const meta = this.metadata.find(entityName);
|
|
65
|
-
let normalized =
|
|
66
|
-
return typeof field === 'boolean' || field.field ===
|
|
61
|
+
let normalized = Utils.asArray(populate).map(field => {
|
|
62
|
+
return typeof field === 'boolean' || field.field === PopulatePath.ALL ? { all: !!field, field: meta.primaryKeys[0] } : field;
|
|
67
63
|
});
|
|
68
64
|
if (normalized.some(p => p.all)) {
|
|
69
65
|
normalized = this.lookupAllRelationships(entityName);
|
|
70
66
|
}
|
|
71
67
|
// convert nested `field` with dot syntax to PopulateOptions with `children` array
|
|
72
|
-
|
|
68
|
+
expandDotPaths(meta, normalized, true);
|
|
73
69
|
if (lookup && populate !== false) {
|
|
74
70
|
normalized = this.lookupEagerLoadedRelationships(entityName, normalized, strategy);
|
|
75
71
|
// convert nested `field` with dot syntax produced by eager relations
|
|
76
|
-
|
|
72
|
+
expandDotPaths(meta, normalized, true);
|
|
77
73
|
}
|
|
78
74
|
// merge same fields
|
|
79
75
|
return this.mergeNestedPopulate(normalized);
|
|
80
76
|
}
|
|
81
77
|
setSerializationContext(entities, populate, options) {
|
|
82
78
|
for (const entity of entities) {
|
|
83
|
-
|
|
79
|
+
helper(entity).setSerializationContext({
|
|
84
80
|
populate,
|
|
85
81
|
fields: options.fields,
|
|
86
82
|
exclude: options.exclude,
|
|
@@ -93,7 +89,7 @@ class EntityLoader {
|
|
|
93
89
|
*/
|
|
94
90
|
mergeNestedPopulate(populate) {
|
|
95
91
|
const tmp = populate.reduce((ret, item) => {
|
|
96
|
-
if (item.field ===
|
|
92
|
+
if (item.field === PopulatePath.ALL) {
|
|
97
93
|
return ret;
|
|
98
94
|
}
|
|
99
95
|
if (!ret[item.field]) {
|
|
@@ -122,13 +118,13 @@ class EntityLoader {
|
|
|
122
118
|
const [field, ref] = populate.field.split(':', 2);
|
|
123
119
|
const meta = this.metadata.find(entityName);
|
|
124
120
|
const prop = meta.properties[field];
|
|
125
|
-
if (prop.kind ===
|
|
121
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner && !this.driver.getPlatform().usesPivotTable()) {
|
|
126
122
|
const filtered = entities.filter(e => !e[prop.name]?.isInitialized());
|
|
127
123
|
if (filtered.length > 0) {
|
|
128
124
|
await this.populateScalar(meta, filtered, { ...options, fields: [prop.name] });
|
|
129
125
|
}
|
|
130
126
|
}
|
|
131
|
-
if (prop.kind ===
|
|
127
|
+
if (prop.kind === ReferenceKind.SCALAR && prop.lazy) {
|
|
132
128
|
const filtered = entities.filter(e => options.refresh || (prop.ref ? !e[prop.name]?.isInitialized() : e[prop.name] === undefined));
|
|
133
129
|
if (options.ignoreLazyScalarProperties || filtered.length === 0) {
|
|
134
130
|
return entities;
|
|
@@ -136,24 +132,29 @@ class EntityLoader {
|
|
|
136
132
|
await this.populateScalar(meta, filtered, { ...options, fields: [prop.name] });
|
|
137
133
|
return entities;
|
|
138
134
|
}
|
|
139
|
-
if (prop.kind ===
|
|
135
|
+
if (prop.kind === ReferenceKind.EMBEDDED) {
|
|
140
136
|
return [];
|
|
141
137
|
}
|
|
142
138
|
const filtered = this.filterCollections(entities, field, options, ref);
|
|
143
|
-
const innerOrderBy =
|
|
144
|
-
.filter(orderBy => (Array.isArray(orderBy[prop.name]) && orderBy[prop.name].length > 0) ||
|
|
139
|
+
const innerOrderBy = Utils.asArray(options.orderBy)
|
|
140
|
+
.filter(orderBy => (Array.isArray(orderBy[prop.name]) && orderBy[prop.name].length > 0) || Utils.isObject(orderBy[prop.name]))
|
|
145
141
|
.flatMap(orderBy => orderBy[prop.name]);
|
|
146
|
-
if (prop.kind === enums_1.ReferenceKind.MANY_TO_MANY && this.driver.getPlatform().usesPivotTable()) {
|
|
147
|
-
return this.findChildrenFromPivotTable(filtered, prop, options, innerOrderBy, populate, !!ref);
|
|
148
|
-
}
|
|
149
142
|
const where = await this.extractChildCondition(options, prop);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
143
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY && this.driver.getPlatform().usesPivotTable()) {
|
|
144
|
+
const res = await this.findChildrenFromPivotTable(filtered, prop, options, innerOrderBy, populate, !!ref);
|
|
145
|
+
return Utils.flatten(res);
|
|
146
|
+
}
|
|
147
|
+
const { items, partial } = await this.findChildren(options.filtered ?? entities, prop, populate, {
|
|
148
|
+
...options,
|
|
149
|
+
where,
|
|
150
|
+
orderBy: innerOrderBy,
|
|
151
|
+
}, !!(ref || prop.mapToPk));
|
|
152
|
+
this.initializeCollections(filtered, prop, field, items, innerOrderBy.length > 0, partial);
|
|
153
|
+
return items;
|
|
153
154
|
}
|
|
154
155
|
async populateScalar(meta, filtered, options) {
|
|
155
|
-
const pk =
|
|
156
|
-
const ids =
|
|
156
|
+
const pk = Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
157
|
+
const ids = Utils.unique(filtered.map(e => Utils.getPrimaryKeyValues(e, meta, true)));
|
|
157
158
|
const where = this.mergePrimaryCondition(ids, pk, options, meta, this.metadata, this.driver.getPlatform());
|
|
158
159
|
const { filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging, fields } = options;
|
|
159
160
|
await this.em.find(meta.className, where, {
|
|
@@ -162,38 +163,38 @@ class EntityLoader {
|
|
|
162
163
|
populate: [],
|
|
163
164
|
});
|
|
164
165
|
}
|
|
165
|
-
initializeCollections(filtered, prop, field, children, customOrder) {
|
|
166
|
-
if (prop.kind ===
|
|
167
|
-
this.initializeOneToMany(filtered, children, prop, field);
|
|
166
|
+
initializeCollections(filtered, prop, field, children, customOrder, partial) {
|
|
167
|
+
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
168
|
+
this.initializeOneToMany(filtered, children, prop, field, partial);
|
|
168
169
|
}
|
|
169
|
-
if (prop.kind ===
|
|
170
|
-
this.initializeManyToMany(filtered, children, prop, field, customOrder);
|
|
170
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY && !this.driver.getPlatform().usesPivotTable()) {
|
|
171
|
+
this.initializeManyToMany(filtered, children, prop, field, customOrder, partial);
|
|
171
172
|
}
|
|
172
173
|
}
|
|
173
|
-
initializeOneToMany(filtered, children, prop, field) {
|
|
174
|
+
initializeOneToMany(filtered, children, prop, field, partial) {
|
|
174
175
|
const mapToPk = prop.targetMeta.properties[prop.mappedBy].mapToPk;
|
|
175
176
|
const map = {};
|
|
176
177
|
for (const entity of filtered) {
|
|
177
|
-
const key =
|
|
178
|
+
const key = helper(entity).getSerializedPrimaryKey();
|
|
178
179
|
map[key] = [];
|
|
179
180
|
}
|
|
180
181
|
for (const child of children) {
|
|
181
182
|
const pk = child.__helper.__data[prop.mappedBy] ?? child[prop.mappedBy];
|
|
182
183
|
if (pk) {
|
|
183
|
-
const key =
|
|
184
|
+
const key = helper(mapToPk ? this.em.getReference(prop.type, pk) : pk).getSerializedPrimaryKey();
|
|
184
185
|
map[key]?.push(child);
|
|
185
186
|
}
|
|
186
187
|
}
|
|
187
188
|
for (const entity of filtered) {
|
|
188
|
-
const key =
|
|
189
|
-
entity[field].hydrate(map[key]);
|
|
189
|
+
const key = helper(entity).getSerializedPrimaryKey();
|
|
190
|
+
entity[field].hydrate(map[key], undefined, partial);
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
|
-
initializeManyToMany(filtered, children, prop, field, customOrder) {
|
|
193
|
+
initializeManyToMany(filtered, children, prop, field, customOrder, partial) {
|
|
193
194
|
if (prop.mappedBy) {
|
|
194
195
|
for (const entity of filtered) {
|
|
195
196
|
const items = children.filter(child => child[prop.mappedBy].contains(entity, false));
|
|
196
|
-
entity[field].hydrate(items, true);
|
|
197
|
+
entity[field].hydrate(items, true, partial);
|
|
197
198
|
}
|
|
198
199
|
}
|
|
199
200
|
else { // owning side of M:N without pivot table needs to be reordered
|
|
@@ -203,48 +204,49 @@ class EntityLoader {
|
|
|
203
204
|
if (!customOrder) {
|
|
204
205
|
items.sort((a, b) => order.indexOf(a) - order.indexOf(b));
|
|
205
206
|
}
|
|
206
|
-
entity[field].hydrate(items, true);
|
|
207
|
+
entity[field].hydrate(items, true, partial);
|
|
207
208
|
}
|
|
208
209
|
}
|
|
209
210
|
}
|
|
210
211
|
async findChildren(entities, prop, populate, options, ref) {
|
|
211
|
-
const children = this.getChildReferences(entities, prop, options, ref);
|
|
212
|
+
const children = Utils.unique(this.getChildReferences(entities, prop, options, ref));
|
|
212
213
|
const meta = prop.targetMeta;
|
|
213
|
-
let fk =
|
|
214
|
+
let fk = Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
214
215
|
let schema = options.schema;
|
|
215
|
-
|
|
216
|
+
const partial = !Utils.isEmpty(prop.where) || !Utils.isEmpty(options.where);
|
|
217
|
+
if (prop.kind === ReferenceKind.ONE_TO_MANY || (prop.kind === ReferenceKind.MANY_TO_MANY && !prop.owner)) {
|
|
216
218
|
fk = meta.properties[prop.mappedBy].name;
|
|
217
219
|
}
|
|
218
|
-
if (prop.kind ===
|
|
220
|
+
if (prop.kind === ReferenceKind.ONE_TO_ONE && !prop.owner && !ref) {
|
|
219
221
|
children.length = 0;
|
|
220
222
|
fk = meta.properties[prop.mappedBy].name;
|
|
221
223
|
children.push(...this.filterByReferences(entities, prop.name, options.refresh));
|
|
222
224
|
}
|
|
223
225
|
if (children.length === 0) {
|
|
224
|
-
return [];
|
|
226
|
+
return { items: [], partial };
|
|
225
227
|
}
|
|
226
|
-
if (!schema && [
|
|
228
|
+
if (!schema && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind)) {
|
|
227
229
|
schema = children.find(e => e.__helper.__schema)?.__helper.__schema;
|
|
228
230
|
}
|
|
229
|
-
const ids =
|
|
231
|
+
const ids = Utils.unique(children.map(e => e.__helper.getPrimaryKey()));
|
|
230
232
|
let where = this.mergePrimaryCondition(ids, fk, options, meta, this.metadata, this.driver.getPlatform());
|
|
231
233
|
const fields = this.buildFields(options.fields, prop, ref);
|
|
232
234
|
/* eslint-disable prefer-const */
|
|
233
|
-
let { refresh, filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging, } = options;
|
|
235
|
+
let { refresh, filters, convertCustomTypes, lockMode, strategy, populateWhere = 'infer', connectionType, logging, } = options;
|
|
234
236
|
/* eslint-enable prefer-const */
|
|
235
237
|
if (typeof populateWhere === 'object') {
|
|
236
238
|
populateWhere = await this.extractChildCondition({ where: populateWhere }, prop);
|
|
237
239
|
}
|
|
238
|
-
if (!
|
|
240
|
+
if (!Utils.isEmpty(prop.where)) {
|
|
239
241
|
where = { $and: [where, prop.where] };
|
|
240
242
|
}
|
|
241
243
|
const propOrderBy = [];
|
|
242
244
|
if (prop.orderBy) {
|
|
243
|
-
for (const item of
|
|
244
|
-
for (const field of
|
|
245
|
-
const rawField =
|
|
245
|
+
for (const item of Utils.asArray(prop.orderBy)) {
|
|
246
|
+
for (const field of Utils.keys(item)) {
|
|
247
|
+
const rawField = RawQueryFragment.getKnownFragment(field, false);
|
|
246
248
|
if (rawField) {
|
|
247
|
-
const raw2 =
|
|
249
|
+
const raw2 = raw(rawField.sql, rawField.params);
|
|
248
250
|
propOrderBy.push({ [raw2.toString()]: item[field] });
|
|
249
251
|
continue;
|
|
250
252
|
}
|
|
@@ -252,30 +254,52 @@ class EntityLoader {
|
|
|
252
254
|
}
|
|
253
255
|
}
|
|
254
256
|
}
|
|
257
|
+
const orderBy = [...Utils.asArray(options.orderBy), ...propOrderBy].filter((order, idx, array) => {
|
|
258
|
+
// skip consecutive ordering with the same key to get around mongo issues
|
|
259
|
+
return idx === 0 || !Utils.equals(Object.keys(array[idx - 1]), Object.keys(order));
|
|
260
|
+
});
|
|
255
261
|
const items = await this.em.find(prop.type, where, {
|
|
256
262
|
filters, convertCustomTypes, lockMode, populateWhere, logging,
|
|
257
|
-
orderBy
|
|
263
|
+
orderBy,
|
|
258
264
|
populate: populate.children ?? populate.all ?? [],
|
|
259
|
-
exclude: Array.isArray(options.exclude) ?
|
|
265
|
+
exclude: Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude,
|
|
260
266
|
strategy, fields, schema, connectionType,
|
|
261
267
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
262
268
|
refresh: refresh && !children.every(item => options.visited.has(item)),
|
|
263
269
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
264
270
|
visited: options.visited,
|
|
265
271
|
});
|
|
272
|
+
if ([ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind) && items.length !== children.length) {
|
|
273
|
+
const nullVal = this.em.config.get('forceUndefined') ? undefined : null;
|
|
274
|
+
const itemsMap = new Set();
|
|
275
|
+
const childrenMap = new Set();
|
|
276
|
+
for (const item of items) {
|
|
277
|
+
itemsMap.add(helper(item).getSerializedPrimaryKey());
|
|
278
|
+
}
|
|
279
|
+
for (const child of children) {
|
|
280
|
+
childrenMap.add(helper(child).getSerializedPrimaryKey());
|
|
281
|
+
}
|
|
282
|
+
for (const entity of entities) {
|
|
283
|
+
const key = helper(entity[prop.name] ?? {})?.getSerializedPrimaryKey();
|
|
284
|
+
if (childrenMap.has(key) && !itemsMap.has(key)) {
|
|
285
|
+
entity[prop.name] = nullVal;
|
|
286
|
+
helper(entity).__originalEntityData[prop.name] = null;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
266
290
|
for (const item of items) {
|
|
267
|
-
if (ref && !
|
|
268
|
-
|
|
291
|
+
if (ref && !helper(item).__onLoadFired) {
|
|
292
|
+
helper(item).__initialized = false;
|
|
269
293
|
// eslint-disable-next-line dot-notation
|
|
270
294
|
this.em.getUnitOfWork()['loadedEntities'].delete(item);
|
|
271
295
|
}
|
|
272
296
|
}
|
|
273
|
-
return items;
|
|
297
|
+
return { items, partial };
|
|
274
298
|
}
|
|
275
299
|
mergePrimaryCondition(ids, pk, options, meta, metadata, platform) {
|
|
276
|
-
const cond1 =
|
|
300
|
+
const cond1 = QueryHelper.processWhere({ where: { [pk]: { $in: ids } }, entityName: meta.className, metadata, platform, convertCustomTypes: !options.convertCustomTypes });
|
|
277
301
|
const where = { ...options.where };
|
|
278
|
-
|
|
302
|
+
Utils.dropUndefinedProperties(where);
|
|
279
303
|
return where[pk]
|
|
280
304
|
? { $and: [cond1, where] }
|
|
281
305
|
: { ...cond1, ...where };
|
|
@@ -283,9 +307,10 @@ class EntityLoader {
|
|
|
283
307
|
async populateField(entityName, entities, populate, options) {
|
|
284
308
|
const field = populate.field.split(':')[0];
|
|
285
309
|
const prop = this.metadata.find(entityName).properties[field];
|
|
286
|
-
if (prop.kind ===
|
|
310
|
+
if (prop.kind === ReferenceKind.SCALAR && !prop.lazy) {
|
|
287
311
|
return;
|
|
288
312
|
}
|
|
313
|
+
options = { ...options, filters: QueryHelper.mergePropertyFilters(prop.filters, options.filters) };
|
|
289
314
|
const populated = await this.populateMany(entityName, entities, populate, options);
|
|
290
315
|
if (!populate.children && !populate.all) {
|
|
291
316
|
return;
|
|
@@ -293,30 +318,38 @@ class EntityLoader {
|
|
|
293
318
|
const children = [];
|
|
294
319
|
for (const entity of entities) {
|
|
295
320
|
const ref = entity[field];
|
|
296
|
-
if (
|
|
321
|
+
if (Utils.isEntity(ref)) {
|
|
297
322
|
children.push(ref);
|
|
298
323
|
}
|
|
299
|
-
else if (
|
|
324
|
+
else if (Reference.isReference(ref)) {
|
|
300
325
|
children.push(ref.unwrap());
|
|
301
326
|
}
|
|
302
|
-
else if (
|
|
327
|
+
else if (Utils.isCollection(ref)) {
|
|
303
328
|
children.push(...ref.getItems());
|
|
304
329
|
}
|
|
305
|
-
else if (ref && prop.kind ===
|
|
306
|
-
children.push(...
|
|
330
|
+
else if (ref && prop.kind === ReferenceKind.EMBEDDED) {
|
|
331
|
+
children.push(...Utils.asArray(ref));
|
|
307
332
|
}
|
|
308
333
|
}
|
|
309
334
|
if (populated.length === 0 && !populate.children) {
|
|
310
335
|
return;
|
|
311
336
|
}
|
|
312
337
|
const fields = this.buildFields(options.fields, prop);
|
|
313
|
-
const innerOrderBy =
|
|
314
|
-
.filter(orderBy =>
|
|
338
|
+
const innerOrderBy = Utils.asArray(options.orderBy)
|
|
339
|
+
.filter(orderBy => Utils.isObject(orderBy[prop.name]))
|
|
315
340
|
.map(orderBy => orderBy[prop.name]);
|
|
316
|
-
const { refresh, filters, ignoreLazyScalarProperties, populateWhere, connectionType, logging } = options;
|
|
317
|
-
const exclude = Array.isArray(options.exclude) ?
|
|
318
|
-
const
|
|
319
|
-
|
|
341
|
+
const { refresh, filters, ignoreLazyScalarProperties, populateWhere, connectionType, logging, schema } = options;
|
|
342
|
+
const exclude = Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude;
|
|
343
|
+
const visited = options.visited;
|
|
344
|
+
for (const entity of entities) {
|
|
345
|
+
visited.delete(entity);
|
|
346
|
+
}
|
|
347
|
+
const unique = Utils.unique(children);
|
|
348
|
+
const filtered = unique.filter(e => !visited.has(e));
|
|
349
|
+
for (const entity of entities) {
|
|
350
|
+
visited.add(entity);
|
|
351
|
+
}
|
|
352
|
+
await this.populate(prop.type, unique, populate.children ?? populate.all, {
|
|
320
353
|
where: await this.extractChildCondition(options, prop, false),
|
|
321
354
|
orderBy: innerOrderBy,
|
|
322
355
|
fields,
|
|
@@ -328,18 +361,22 @@ class EntityLoader {
|
|
|
328
361
|
populateWhere,
|
|
329
362
|
connectionType,
|
|
330
363
|
logging,
|
|
364
|
+
schema,
|
|
331
365
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
332
366
|
refresh: refresh && !filtered.every(item => options.visited.has(item)),
|
|
333
367
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
334
368
|
visited: options.visited,
|
|
369
|
+
// @ts-ignore not a public option
|
|
370
|
+
filtered,
|
|
335
371
|
});
|
|
336
372
|
}
|
|
373
|
+
/** @internal */
|
|
337
374
|
async findChildrenFromPivotTable(filtered, prop, options, orderBy, populate, pivotJoin) {
|
|
338
375
|
const ids = filtered.map(e => e.__helper.__primaryKeys);
|
|
339
376
|
const refresh = options.refresh;
|
|
340
377
|
let where = await this.extractChildCondition(options, prop, true);
|
|
341
378
|
const fields = this.buildFields(options.fields, prop);
|
|
342
|
-
const exclude = Array.isArray(options.exclude) ?
|
|
379
|
+
const exclude = Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude;
|
|
343
380
|
const options2 = { ...options };
|
|
344
381
|
delete options2.limit;
|
|
345
382
|
delete options2.offset;
|
|
@@ -347,9 +384,9 @@ class EntityLoader {
|
|
|
347
384
|
options2.exclude = exclude;
|
|
348
385
|
options2.populate = (populate?.children ?? []);
|
|
349
386
|
if (prop.customType) {
|
|
350
|
-
ids.forEach((id, idx) => ids[idx] =
|
|
387
|
+
ids.forEach((id, idx) => ids[idx] = QueryHelper.processCustomType(prop, id, this.driver.getPlatform()));
|
|
351
388
|
}
|
|
352
|
-
if (!
|
|
389
|
+
if (!Utils.isEmpty(prop.where)) {
|
|
353
390
|
where = { $and: [where, prop.where] };
|
|
354
391
|
}
|
|
355
392
|
const map = await this.driver.loadFromPivotTable(prop, ids, where, orderBy, this.em.getTransactionContext(), options2, pivotJoin);
|
|
@@ -371,25 +408,25 @@ class EntityLoader {
|
|
|
371
408
|
return this.em.getUnitOfWork().register(entity, item, { refresh, loaded: true });
|
|
372
409
|
});
|
|
373
410
|
entity[prop.name].hydrate(items, true);
|
|
374
|
-
children.push(
|
|
411
|
+
children.push(items);
|
|
375
412
|
}
|
|
376
413
|
return children;
|
|
377
414
|
}
|
|
378
415
|
async extractChildCondition(options, prop, filters = false) {
|
|
379
416
|
const where = options.where;
|
|
380
|
-
const subCond =
|
|
417
|
+
const subCond = Utils.isPlainObject(where[prop.name]) ? where[prop.name] : {};
|
|
381
418
|
const meta2 = this.metadata.find(prop.type);
|
|
382
419
|
if (!meta2) {
|
|
383
420
|
return {};
|
|
384
421
|
}
|
|
385
|
-
const pk =
|
|
422
|
+
const pk = Utils.getPrimaryKeyHash(meta2.primaryKeys);
|
|
386
423
|
['$and', '$or'].forEach(op => {
|
|
387
424
|
if (where[op]) {
|
|
388
425
|
const child = where[op]
|
|
389
426
|
.map((cond) => cond[prop.name])
|
|
390
|
-
.filter((sub) => sub != null && !(
|
|
427
|
+
.filter((sub) => sub != null && !(Utils.isPlainObject(sub) && Object.keys(sub).every(key => Utils.isOperator(key, false))))
|
|
391
428
|
.map((cond) => {
|
|
392
|
-
if (
|
|
429
|
+
if (Utils.isPrimaryKey(cond)) {
|
|
393
430
|
return { [pk]: cond };
|
|
394
431
|
}
|
|
395
432
|
return cond;
|
|
@@ -399,7 +436,7 @@ class EntityLoader {
|
|
|
399
436
|
}
|
|
400
437
|
}
|
|
401
438
|
});
|
|
402
|
-
const operators = Object.keys(subCond).filter(key =>
|
|
439
|
+
const operators = Object.keys(subCond).filter(key => Utils.isOperator(key, false));
|
|
403
440
|
if (operators.length > 0) {
|
|
404
441
|
operators.forEach(op => {
|
|
405
442
|
subCond[pk] ??= {};
|
|
@@ -417,8 +454,8 @@ class EntityLoader {
|
|
|
417
454
|
fields = prop.targetMeta.primaryKeys.map(targetPkName => `${prop.name}.${targetPkName}`);
|
|
418
455
|
}
|
|
419
456
|
const ret = fields.reduce((ret, f) => {
|
|
420
|
-
if (
|
|
421
|
-
|
|
457
|
+
if (Utils.isPlainObject(f)) {
|
|
458
|
+
Utils.keys(f)
|
|
422
459
|
.filter(ff => ff === prop.name)
|
|
423
460
|
.forEach(ff => ret.push(...f[ff]));
|
|
424
461
|
}
|
|
@@ -426,7 +463,7 @@ class EntityLoader {
|
|
|
426
463
|
const parts = f.toString().split('.');
|
|
427
464
|
const propName = parts.shift();
|
|
428
465
|
const childPropName = parts.join('.');
|
|
429
|
-
/*
|
|
466
|
+
/* v8 ignore next */
|
|
430
467
|
if (propName === prop.name) {
|
|
431
468
|
ret.push(childPropName);
|
|
432
469
|
}
|
|
@@ -437,7 +474,7 @@ class EntityLoader {
|
|
|
437
474
|
return undefined;
|
|
438
475
|
}
|
|
439
476
|
// we need to automatically select the FKs too, e.g. for 1:m relations to be able to wire them with the items
|
|
440
|
-
if (prop.kind ===
|
|
477
|
+
if (prop.kind === ReferenceKind.ONE_TO_MANY || prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
441
478
|
const owner = prop.targetMeta.properties[prop.mappedBy];
|
|
442
479
|
if (owner && !ret.includes(owner.name)) {
|
|
443
480
|
ret.push(owner.name);
|
|
@@ -447,61 +484,58 @@ class EntityLoader {
|
|
|
447
484
|
}
|
|
448
485
|
getChildReferences(entities, prop, options, ref) {
|
|
449
486
|
const filtered = this.filterCollections(entities, prop.name, options, ref);
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
children.push(...filtered.map(e => e[prop.name].owner));
|
|
487
|
+
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
488
|
+
return filtered.map(e => e[prop.name].owner);
|
|
453
489
|
}
|
|
454
|
-
|
|
455
|
-
|
|
490
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner) {
|
|
491
|
+
return filtered.reduce((a, b) => {
|
|
456
492
|
a.push(...b[prop.name].getItems());
|
|
457
493
|
return a;
|
|
458
|
-
}, [])
|
|
459
|
-
}
|
|
460
|
-
else if (prop.kind === enums_1.ReferenceKind.MANY_TO_MANY) { // inverse side
|
|
461
|
-
children.push(...filtered);
|
|
494
|
+
}, []);
|
|
462
495
|
}
|
|
463
|
-
|
|
464
|
-
|
|
496
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY) { // inverse side
|
|
497
|
+
return filtered;
|
|
465
498
|
}
|
|
466
|
-
|
|
499
|
+
// MANY_TO_ONE or ONE_TO_ONE
|
|
500
|
+
return this.filterReferences(entities, prop.name, options, ref);
|
|
467
501
|
}
|
|
468
502
|
filterCollections(entities, field, options, ref) {
|
|
469
503
|
if (options.refresh) {
|
|
470
504
|
return entities.filter(e => e[field]);
|
|
471
505
|
}
|
|
472
|
-
return entities.filter(e =>
|
|
506
|
+
return entities.filter(e => Utils.isCollection(e[field]) && !e[field].isInitialized(!ref));
|
|
473
507
|
}
|
|
474
508
|
isPropertyLoaded(entity, field) {
|
|
475
509
|
if (!entity || field === '*') {
|
|
476
510
|
return true;
|
|
477
511
|
}
|
|
478
|
-
const wrapped =
|
|
512
|
+
const wrapped = helper(entity);
|
|
479
513
|
if (!field.includes('.')) {
|
|
480
514
|
return wrapped.__loadedProperties.has(field);
|
|
481
515
|
}
|
|
482
516
|
const [f, ...r] = field.split('.');
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
517
|
+
/* v8 ignore next */
|
|
518
|
+
if (!wrapped.__loadedProperties.has(f) || !wrapped.__meta.properties[f]?.targetMeta) {
|
|
519
|
+
return false;
|
|
520
|
+
}
|
|
521
|
+
if ([ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(wrapped.__meta.properties[f].kind)) {
|
|
522
|
+
return entity[f].getItems(false).every((item) => this.isPropertyLoaded(item, r.join('.')));
|
|
488
523
|
}
|
|
489
|
-
|
|
490
|
-
return false;
|
|
524
|
+
return this.isPropertyLoaded(entity[f], r.join('.'));
|
|
491
525
|
}
|
|
492
526
|
filterReferences(entities, field, options, ref) {
|
|
493
527
|
if (ref) {
|
|
494
528
|
return [];
|
|
495
529
|
}
|
|
496
|
-
const children = entities.filter(e =>
|
|
530
|
+
const children = entities.filter(e => Utils.isEntity(e[field], true));
|
|
497
531
|
if (options.refresh) {
|
|
498
|
-
return children.map(e =>
|
|
532
|
+
return children.map(e => Reference.unwrapReference(e[field]));
|
|
499
533
|
}
|
|
500
534
|
if (options.fields) {
|
|
501
535
|
return children
|
|
502
|
-
.map(e =>
|
|
536
|
+
.map(e => Reference.unwrapReference(e[field]))
|
|
503
537
|
.filter(target => {
|
|
504
|
-
const wrapped =
|
|
538
|
+
const wrapped = helper(target);
|
|
505
539
|
const childFields = options.fields
|
|
506
540
|
.filter(f => f.startsWith(`${field}.`))
|
|
507
541
|
.map(f => f.substring(field.length + 1));
|
|
@@ -510,14 +544,14 @@ class EntityLoader {
|
|
|
510
544
|
}
|
|
511
545
|
return children
|
|
512
546
|
.filter(e => !e[field].__helper.__initialized)
|
|
513
|
-
.map(e =>
|
|
547
|
+
.map(e => Reference.unwrapReference(e[field]));
|
|
514
548
|
}
|
|
515
549
|
filterByReferences(entities, field, refresh) {
|
|
516
|
-
/*
|
|
550
|
+
/* v8 ignore next */
|
|
517
551
|
if (refresh) {
|
|
518
552
|
return entities;
|
|
519
553
|
}
|
|
520
|
-
return entities.filter(e => !e[field]?.__helper?.__initialized);
|
|
554
|
+
return entities.filter(e => e[field] !== null && !e[field]?.__helper?.__initialized);
|
|
521
555
|
}
|
|
522
556
|
lookupAllRelationships(entityName) {
|
|
523
557
|
const ret = [];
|
|
@@ -526,7 +560,7 @@ class EntityLoader {
|
|
|
526
560
|
ret.push({
|
|
527
561
|
field: this.getRelationName(meta, prop),
|
|
528
562
|
// force select-in strategy when populating all relations as otherwise we could cause infinite loops when self-referencing
|
|
529
|
-
strategy:
|
|
563
|
+
strategy: LoadStrategy.SELECT_IN,
|
|
530
564
|
// no need to look up populate children recursively as we just pass `all: true` here
|
|
531
565
|
all: true,
|
|
532
566
|
});
|
|
@@ -569,11 +603,10 @@ class EntityLoader {
|
|
|
569
603
|
ret.push({
|
|
570
604
|
field: prefixed,
|
|
571
605
|
// enforce select-in strategy for self-referencing relations
|
|
572
|
-
strategy: selfReferencing ?
|
|
606
|
+
strategy: selfReferencing ? LoadStrategy.SELECT_IN : strategy ?? prop.strategy,
|
|
573
607
|
});
|
|
574
608
|
}
|
|
575
609
|
});
|
|
576
610
|
return ret;
|
|
577
611
|
}
|
|
578
612
|
}
|
|
579
|
-
exports.EntityLoader = EntityLoader;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { PopulatePath } from '../enums';
|
|
2
|
-
import type { CreateOptions, EntityManager, MergeOptions } from '../EntityManager';
|
|
3
|
-
import type { AssignOptions } from './EntityAssigner';
|
|
4
|
-
import type { EntityData, EntityName, Primary, Loaded, FilterQuery, EntityDictionary, AutoPath, RequiredEntityData, Ref, EntityType, EntityDTO, MergeSelected, FromEntityType, IsSubset, MergeLoaded, ArrayElement } from '../typings';
|
|
5
|
-
import type { CountOptions, DeleteOptions, FindAllOptions, FindByCursorOptions, FindOneOptions, FindOneOrFailOptions, FindOptions, GetReferenceOptions, NativeInsertUpdateOptions, UpdateOptions, UpsertManyOptions, UpsertOptions } from '../drivers/IDatabaseDriver';
|
|
6
|
-
import type { EntityLoaderOptions } from './EntityLoader';
|
|
7
|
-
import type { Cursor } from '../utils/Cursor';
|
|
1
|
+
import type { PopulatePath } from '../enums.js';
|
|
2
|
+
import type { CreateOptions, EntityManager, MergeOptions } from '../EntityManager.js';
|
|
3
|
+
import type { AssignOptions } from './EntityAssigner.js';
|
|
4
|
+
import type { EntityData, EntityName, Primary, Loaded, FilterQuery, EntityDictionary, AutoPath, RequiredEntityData, Ref, EntityType, EntityDTO, MergeSelected, FromEntityType, IsSubset, MergeLoaded, ArrayElement } from '../typings.js';
|
|
5
|
+
import type { CountOptions, DeleteOptions, FindAllOptions, FindByCursorOptions, FindOneOptions, FindOneOrFailOptions, FindOptions, GetReferenceOptions, NativeInsertUpdateOptions, UpdateOptions, UpsertManyOptions, UpsertOptions } from '../drivers/IDatabaseDriver.js';
|
|
6
|
+
import type { EntityLoaderOptions } from './EntityLoader.js';
|
|
7
|
+
import type { Cursor } from '../utils/Cursor.js';
|
|
8
8
|
export declare class EntityRepository<Entity extends object> {
|
|
9
9
|
protected readonly em: EntityManager;
|
|
10
10
|
protected readonly entityName: EntityName<Entity>;
|
|
@@ -80,7 +80,7 @@ export declare class EntityRepository<Entity extends object> {
|
|
|
80
80
|
/**
|
|
81
81
|
* @inheritDoc EntityManager.findByCursor
|
|
82
82
|
*/
|
|
83
|
-
findByCursor<Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(where: FilterQuery<Entity>, options: FindByCursorOptions<Entity, Hint, Fields, Excludes>): Promise<Cursor<Entity, Hint, Fields, Excludes>>;
|
|
83
|
+
findByCursor<Hint extends string = never, Fields extends string = '*', Excludes extends string = never, IncludeCount extends boolean = true>(where: FilterQuery<Entity>, options: FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>): Promise<Cursor<Entity, Hint, Fields, Excludes, IncludeCount>>;
|
|
84
84
|
/**
|
|
85
85
|
* Finds all entities of given type. You can pass additional options via the `options` parameter.
|
|
86
86
|
*/
|