@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/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,15 +20,15 @@ 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 ??= {};
|
|
@@ -45,9 +42,9 @@ class EntityLoader {
|
|
|
45
42
|
}
|
|
46
43
|
populate = this.normalizePopulate(entityName, populate, options.strategy, options.lookup);
|
|
47
44
|
const invalid = populate.find(({ field }) => !this.em.canPopulate(entityName, field));
|
|
48
|
-
/*
|
|
45
|
+
/* v8 ignore next 3 */
|
|
49
46
|
if (options.validate && invalid) {
|
|
50
|
-
throw
|
|
47
|
+
throw ValidationError.invalidPropertyName(entityName, invalid.field);
|
|
51
48
|
}
|
|
52
49
|
this.setSerializationContext(entities, populate, options);
|
|
53
50
|
for (const entity of entities) {
|
|
@@ -62,25 +59,25 @@ class EntityLoader {
|
|
|
62
59
|
}
|
|
63
60
|
normalizePopulate(entityName, populate, strategy, lookup = true) {
|
|
64
61
|
const meta = this.metadata.find(entityName);
|
|
65
|
-
let normalized =
|
|
66
|
-
return typeof field === 'boolean' || field.field ===
|
|
62
|
+
let normalized = Utils.asArray(populate).map(field => {
|
|
63
|
+
return typeof field === 'boolean' || field.field === PopulatePath.ALL ? { all: !!field, field: meta.primaryKeys[0] } : field;
|
|
67
64
|
});
|
|
68
65
|
if (normalized.some(p => p.all)) {
|
|
69
66
|
normalized = this.lookupAllRelationships(entityName);
|
|
70
67
|
}
|
|
71
68
|
// convert nested `field` with dot syntax to PopulateOptions with `children` array
|
|
72
|
-
|
|
69
|
+
expandDotPaths(meta, normalized, true);
|
|
73
70
|
if (lookup && populate !== false) {
|
|
74
71
|
normalized = this.lookupEagerLoadedRelationships(entityName, normalized, strategy);
|
|
75
72
|
// convert nested `field` with dot syntax produced by eager relations
|
|
76
|
-
|
|
73
|
+
expandDotPaths(meta, normalized, true);
|
|
77
74
|
}
|
|
78
75
|
// merge same fields
|
|
79
76
|
return this.mergeNestedPopulate(normalized);
|
|
80
77
|
}
|
|
81
78
|
setSerializationContext(entities, populate, options) {
|
|
82
79
|
for (const entity of entities) {
|
|
83
|
-
|
|
80
|
+
helper(entity).setSerializationContext({
|
|
84
81
|
populate,
|
|
85
82
|
fields: options.fields,
|
|
86
83
|
exclude: options.exclude,
|
|
@@ -93,7 +90,7 @@ class EntityLoader {
|
|
|
93
90
|
*/
|
|
94
91
|
mergeNestedPopulate(populate) {
|
|
95
92
|
const tmp = populate.reduce((ret, item) => {
|
|
96
|
-
if (item.field ===
|
|
93
|
+
if (item.field === PopulatePath.ALL) {
|
|
97
94
|
return ret;
|
|
98
95
|
}
|
|
99
96
|
if (!ret[item.field]) {
|
|
@@ -122,13 +119,13 @@ class EntityLoader {
|
|
|
122
119
|
const [field, ref] = populate.field.split(':', 2);
|
|
123
120
|
const meta = this.metadata.find(entityName);
|
|
124
121
|
const prop = meta.properties[field];
|
|
125
|
-
if (prop.kind ===
|
|
122
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner && !this.driver.getPlatform().usesPivotTable()) {
|
|
126
123
|
const filtered = entities.filter(e => !e[prop.name]?.isInitialized());
|
|
127
124
|
if (filtered.length > 0) {
|
|
128
125
|
await this.populateScalar(meta, filtered, { ...options, fields: [prop.name] });
|
|
129
126
|
}
|
|
130
127
|
}
|
|
131
|
-
if (prop.kind ===
|
|
128
|
+
if (prop.kind === ReferenceKind.SCALAR && prop.lazy) {
|
|
132
129
|
const filtered = entities.filter(e => options.refresh || (prop.ref ? !e[prop.name]?.isInitialized() : e[prop.name] === undefined));
|
|
133
130
|
if (options.ignoreLazyScalarProperties || filtered.length === 0) {
|
|
134
131
|
return entities;
|
|
@@ -136,14 +133,14 @@ class EntityLoader {
|
|
|
136
133
|
await this.populateScalar(meta, filtered, { ...options, fields: [prop.name] });
|
|
137
134
|
return entities;
|
|
138
135
|
}
|
|
139
|
-
if (prop.kind ===
|
|
136
|
+
if (prop.kind === ReferenceKind.EMBEDDED) {
|
|
140
137
|
return [];
|
|
141
138
|
}
|
|
142
139
|
const filtered = this.filterCollections(entities, field, options, ref);
|
|
143
|
-
const innerOrderBy =
|
|
144
|
-
.filter(orderBy => (Array.isArray(orderBy[prop.name]) && orderBy[prop.name].length > 0) ||
|
|
140
|
+
const innerOrderBy = Utils.asArray(options.orderBy)
|
|
141
|
+
.filter(orderBy => (Array.isArray(orderBy[prop.name]) && orderBy[prop.name].length > 0) || Utils.isObject(orderBy[prop.name]))
|
|
145
142
|
.flatMap(orderBy => orderBy[prop.name]);
|
|
146
|
-
if (prop.kind ===
|
|
143
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY && this.driver.getPlatform().usesPivotTable()) {
|
|
147
144
|
return this.findChildrenFromPivotTable(filtered, prop, options, innerOrderBy, populate, !!ref);
|
|
148
145
|
}
|
|
149
146
|
const where = await this.extractChildCondition(options, prop);
|
|
@@ -152,8 +149,8 @@ class EntityLoader {
|
|
|
152
149
|
return data;
|
|
153
150
|
}
|
|
154
151
|
async populateScalar(meta, filtered, options) {
|
|
155
|
-
const pk =
|
|
156
|
-
const ids =
|
|
152
|
+
const pk = Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
153
|
+
const ids = Utils.unique(filtered.map(e => Utils.getPrimaryKeyValues(e, meta.primaryKeys, true)));
|
|
157
154
|
const where = this.mergePrimaryCondition(ids, pk, options, meta, this.metadata, this.driver.getPlatform());
|
|
158
155
|
const { filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging, fields } = options;
|
|
159
156
|
await this.em.find(meta.className, where, {
|
|
@@ -163,10 +160,10 @@ class EntityLoader {
|
|
|
163
160
|
});
|
|
164
161
|
}
|
|
165
162
|
initializeCollections(filtered, prop, field, children, customOrder) {
|
|
166
|
-
if (prop.kind ===
|
|
163
|
+
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
167
164
|
this.initializeOneToMany(filtered, children, prop, field);
|
|
168
165
|
}
|
|
169
|
-
if (prop.kind ===
|
|
166
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY && !this.driver.getPlatform().usesPivotTable()) {
|
|
170
167
|
this.initializeManyToMany(filtered, children, prop, field, customOrder);
|
|
171
168
|
}
|
|
172
169
|
}
|
|
@@ -174,18 +171,18 @@ class EntityLoader {
|
|
|
174
171
|
const mapToPk = prop.targetMeta.properties[prop.mappedBy].mapToPk;
|
|
175
172
|
const map = {};
|
|
176
173
|
for (const entity of filtered) {
|
|
177
|
-
const key =
|
|
174
|
+
const key = helper(entity).getSerializedPrimaryKey();
|
|
178
175
|
map[key] = [];
|
|
179
176
|
}
|
|
180
177
|
for (const child of children) {
|
|
181
178
|
const pk = child.__helper.__data[prop.mappedBy] ?? child[prop.mappedBy];
|
|
182
179
|
if (pk) {
|
|
183
|
-
const key =
|
|
180
|
+
const key = helper(mapToPk ? this.em.getReference(prop.type, pk) : pk).getSerializedPrimaryKey();
|
|
184
181
|
map[key]?.push(child);
|
|
185
182
|
}
|
|
186
183
|
}
|
|
187
184
|
for (const entity of filtered) {
|
|
188
|
-
const key =
|
|
185
|
+
const key = helper(entity).getSerializedPrimaryKey();
|
|
189
186
|
entity[field].hydrate(map[key]);
|
|
190
187
|
}
|
|
191
188
|
}
|
|
@@ -210,12 +207,12 @@ class EntityLoader {
|
|
|
210
207
|
async findChildren(entities, prop, populate, options, ref) {
|
|
211
208
|
const children = this.getChildReferences(entities, prop, options, ref);
|
|
212
209
|
const meta = prop.targetMeta;
|
|
213
|
-
let fk =
|
|
210
|
+
let fk = Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
214
211
|
let schema = options.schema;
|
|
215
|
-
if (prop.kind ===
|
|
212
|
+
if (prop.kind === ReferenceKind.ONE_TO_MANY || (prop.kind === ReferenceKind.MANY_TO_MANY && !prop.owner)) {
|
|
216
213
|
fk = meta.properties[prop.mappedBy].name;
|
|
217
214
|
}
|
|
218
|
-
if (prop.kind ===
|
|
215
|
+
if (prop.kind === ReferenceKind.ONE_TO_ONE && !prop.owner && !ref) {
|
|
219
216
|
children.length = 0;
|
|
220
217
|
fk = meta.properties[prop.mappedBy].name;
|
|
221
218
|
children.push(...this.filterByReferences(entities, prop.name, options.refresh));
|
|
@@ -223,10 +220,10 @@ class EntityLoader {
|
|
|
223
220
|
if (children.length === 0) {
|
|
224
221
|
return [];
|
|
225
222
|
}
|
|
226
|
-
if (!schema && [
|
|
223
|
+
if (!schema && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind)) {
|
|
227
224
|
schema = children.find(e => e.__helper.__schema)?.__helper.__schema;
|
|
228
225
|
}
|
|
229
|
-
const ids =
|
|
226
|
+
const ids = Utils.unique(children.map(e => e.__helper.getPrimaryKey()));
|
|
230
227
|
let where = this.mergePrimaryCondition(ids, fk, options, meta, this.metadata, this.driver.getPlatform());
|
|
231
228
|
const fields = this.buildFields(options.fields, prop, ref);
|
|
232
229
|
/* eslint-disable prefer-const */
|
|
@@ -235,16 +232,16 @@ class EntityLoader {
|
|
|
235
232
|
if (typeof populateWhere === 'object') {
|
|
236
233
|
populateWhere = await this.extractChildCondition({ where: populateWhere }, prop);
|
|
237
234
|
}
|
|
238
|
-
if (!
|
|
235
|
+
if (!Utils.isEmpty(prop.where)) {
|
|
239
236
|
where = { $and: [where, prop.where] };
|
|
240
237
|
}
|
|
241
238
|
const propOrderBy = [];
|
|
242
239
|
if (prop.orderBy) {
|
|
243
|
-
for (const item of
|
|
244
|
-
for (const field of
|
|
245
|
-
const rawField =
|
|
240
|
+
for (const item of Utils.asArray(prop.orderBy)) {
|
|
241
|
+
for (const field of Utils.keys(item)) {
|
|
242
|
+
const rawField = RawQueryFragment.getKnownFragment(field, false);
|
|
246
243
|
if (rawField) {
|
|
247
|
-
const raw2 =
|
|
244
|
+
const raw2 = raw(rawField.sql, rawField.params);
|
|
248
245
|
propOrderBy.push({ [raw2.toString()]: item[field] });
|
|
249
246
|
continue;
|
|
250
247
|
}
|
|
@@ -254,9 +251,9 @@ class EntityLoader {
|
|
|
254
251
|
}
|
|
255
252
|
const items = await this.em.find(prop.type, where, {
|
|
256
253
|
filters, convertCustomTypes, lockMode, populateWhere, logging,
|
|
257
|
-
orderBy: [...
|
|
254
|
+
orderBy: [...Utils.asArray(options.orderBy), ...propOrderBy],
|
|
258
255
|
populate: populate.children ?? populate.all ?? [],
|
|
259
|
-
exclude: Array.isArray(options.exclude) ?
|
|
256
|
+
exclude: Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude,
|
|
260
257
|
strategy, fields, schema, connectionType,
|
|
261
258
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
262
259
|
refresh: refresh && !children.every(item => options.visited.has(item)),
|
|
@@ -264,8 +261,8 @@ class EntityLoader {
|
|
|
264
261
|
visited: options.visited,
|
|
265
262
|
});
|
|
266
263
|
for (const item of items) {
|
|
267
|
-
if (ref && !
|
|
268
|
-
|
|
264
|
+
if (ref && !helper(item).__onLoadFired) {
|
|
265
|
+
helper(item).__initialized = false;
|
|
269
266
|
// eslint-disable-next-line dot-notation
|
|
270
267
|
this.em.getUnitOfWork()['loadedEntities'].delete(item);
|
|
271
268
|
}
|
|
@@ -273,9 +270,9 @@ class EntityLoader {
|
|
|
273
270
|
return items;
|
|
274
271
|
}
|
|
275
272
|
mergePrimaryCondition(ids, pk, options, meta, metadata, platform) {
|
|
276
|
-
const cond1 =
|
|
273
|
+
const cond1 = QueryHelper.processWhere({ where: { [pk]: { $in: ids } }, entityName: meta.className, metadata, platform, convertCustomTypes: !options.convertCustomTypes });
|
|
277
274
|
const where = { ...options.where };
|
|
278
|
-
|
|
275
|
+
Utils.dropUndefinedProperties(where);
|
|
279
276
|
return where[pk]
|
|
280
277
|
? { $and: [cond1, where] }
|
|
281
278
|
: { ...cond1, ...where };
|
|
@@ -283,7 +280,7 @@ class EntityLoader {
|
|
|
283
280
|
async populateField(entityName, entities, populate, options) {
|
|
284
281
|
const field = populate.field.split(':')[0];
|
|
285
282
|
const prop = this.metadata.find(entityName).properties[field];
|
|
286
|
-
if (prop.kind ===
|
|
283
|
+
if (prop.kind === ReferenceKind.SCALAR && !prop.lazy) {
|
|
287
284
|
return;
|
|
288
285
|
}
|
|
289
286
|
const populated = await this.populateMany(entityName, entities, populate, options);
|
|
@@ -293,29 +290,29 @@ class EntityLoader {
|
|
|
293
290
|
const children = [];
|
|
294
291
|
for (const entity of entities) {
|
|
295
292
|
const ref = entity[field];
|
|
296
|
-
if (
|
|
293
|
+
if (Utils.isEntity(ref)) {
|
|
297
294
|
children.push(ref);
|
|
298
295
|
}
|
|
299
|
-
else if (
|
|
296
|
+
else if (Reference.isReference(ref)) {
|
|
300
297
|
children.push(ref.unwrap());
|
|
301
298
|
}
|
|
302
|
-
else if (
|
|
299
|
+
else if (Utils.isCollection(ref)) {
|
|
303
300
|
children.push(...ref.getItems());
|
|
304
301
|
}
|
|
305
|
-
else if (ref && prop.kind ===
|
|
306
|
-
children.push(...
|
|
302
|
+
else if (ref && prop.kind === ReferenceKind.EMBEDDED) {
|
|
303
|
+
children.push(...Utils.asArray(ref));
|
|
307
304
|
}
|
|
308
305
|
}
|
|
309
306
|
if (populated.length === 0 && !populate.children) {
|
|
310
307
|
return;
|
|
311
308
|
}
|
|
312
309
|
const fields = this.buildFields(options.fields, prop);
|
|
313
|
-
const innerOrderBy =
|
|
314
|
-
.filter(orderBy =>
|
|
310
|
+
const innerOrderBy = Utils.asArray(options.orderBy)
|
|
311
|
+
.filter(orderBy => Utils.isObject(orderBy[prop.name]))
|
|
315
312
|
.map(orderBy => orderBy[prop.name]);
|
|
316
313
|
const { refresh, filters, ignoreLazyScalarProperties, populateWhere, connectionType, logging } = options;
|
|
317
|
-
const exclude = Array.isArray(options.exclude) ?
|
|
318
|
-
const filtered =
|
|
314
|
+
const exclude = Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude;
|
|
315
|
+
const filtered = Utils.unique(children.filter(e => !options.visited.has(e)));
|
|
319
316
|
await this.populate(prop.type, filtered, populate.children ?? populate.all, {
|
|
320
317
|
where: await this.extractChildCondition(options, prop, false),
|
|
321
318
|
orderBy: innerOrderBy,
|
|
@@ -339,7 +336,7 @@ class EntityLoader {
|
|
|
339
336
|
const refresh = options.refresh;
|
|
340
337
|
let where = await this.extractChildCondition(options, prop, true);
|
|
341
338
|
const fields = this.buildFields(options.fields, prop);
|
|
342
|
-
const exclude = Array.isArray(options.exclude) ?
|
|
339
|
+
const exclude = Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude;
|
|
343
340
|
const options2 = { ...options };
|
|
344
341
|
delete options2.limit;
|
|
345
342
|
delete options2.offset;
|
|
@@ -347,9 +344,9 @@ class EntityLoader {
|
|
|
347
344
|
options2.exclude = exclude;
|
|
348
345
|
options2.populate = (populate?.children ?? []);
|
|
349
346
|
if (prop.customType) {
|
|
350
|
-
ids.forEach((id, idx) => ids[idx] =
|
|
347
|
+
ids.forEach((id, idx) => ids[idx] = QueryHelper.processCustomType(prop, id, this.driver.getPlatform()));
|
|
351
348
|
}
|
|
352
|
-
if (!
|
|
349
|
+
if (!Utils.isEmpty(prop.where)) {
|
|
353
350
|
where = { $and: [where, prop.where] };
|
|
354
351
|
}
|
|
355
352
|
const map = await this.driver.loadFromPivotTable(prop, ids, where, orderBy, this.em.getTransactionContext(), options2, pivotJoin);
|
|
@@ -377,19 +374,19 @@ class EntityLoader {
|
|
|
377
374
|
}
|
|
378
375
|
async extractChildCondition(options, prop, filters = false) {
|
|
379
376
|
const where = options.where;
|
|
380
|
-
const subCond =
|
|
377
|
+
const subCond = Utils.isPlainObject(where[prop.name]) ? where[prop.name] : {};
|
|
381
378
|
const meta2 = this.metadata.find(prop.type);
|
|
382
379
|
if (!meta2) {
|
|
383
380
|
return {};
|
|
384
381
|
}
|
|
385
|
-
const pk =
|
|
382
|
+
const pk = Utils.getPrimaryKeyHash(meta2.primaryKeys);
|
|
386
383
|
['$and', '$or'].forEach(op => {
|
|
387
384
|
if (where[op]) {
|
|
388
385
|
const child = where[op]
|
|
389
386
|
.map((cond) => cond[prop.name])
|
|
390
|
-
.filter((sub) => sub != null && !(
|
|
387
|
+
.filter((sub) => sub != null && !(Utils.isPlainObject(sub) && Object.keys(sub).every(key => Utils.isOperator(key, false))))
|
|
391
388
|
.map((cond) => {
|
|
392
|
-
if (
|
|
389
|
+
if (Utils.isPrimaryKey(cond)) {
|
|
393
390
|
return { [pk]: cond };
|
|
394
391
|
}
|
|
395
392
|
return cond;
|
|
@@ -399,7 +396,7 @@ class EntityLoader {
|
|
|
399
396
|
}
|
|
400
397
|
}
|
|
401
398
|
});
|
|
402
|
-
const operators = Object.keys(subCond).filter(key =>
|
|
399
|
+
const operators = Object.keys(subCond).filter(key => Utils.isOperator(key, false));
|
|
403
400
|
if (operators.length > 0) {
|
|
404
401
|
operators.forEach(op => {
|
|
405
402
|
subCond[pk] ??= {};
|
|
@@ -417,8 +414,8 @@ class EntityLoader {
|
|
|
417
414
|
fields = prop.targetMeta.primaryKeys.map(targetPkName => `${prop.name}.${targetPkName}`);
|
|
418
415
|
}
|
|
419
416
|
const ret = fields.reduce((ret, f) => {
|
|
420
|
-
if (
|
|
421
|
-
|
|
417
|
+
if (Utils.isPlainObject(f)) {
|
|
418
|
+
Utils.keys(f)
|
|
422
419
|
.filter(ff => ff === prop.name)
|
|
423
420
|
.forEach(ff => ret.push(...f[ff]));
|
|
424
421
|
}
|
|
@@ -426,7 +423,7 @@ class EntityLoader {
|
|
|
426
423
|
const parts = f.toString().split('.');
|
|
427
424
|
const propName = parts.shift();
|
|
428
425
|
const childPropName = parts.join('.');
|
|
429
|
-
/*
|
|
426
|
+
/* v8 ignore next 3 */
|
|
430
427
|
if (propName === prop.name) {
|
|
431
428
|
ret.push(childPropName);
|
|
432
429
|
}
|
|
@@ -437,7 +434,7 @@ class EntityLoader {
|
|
|
437
434
|
return undefined;
|
|
438
435
|
}
|
|
439
436
|
// 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 ===
|
|
437
|
+
if (prop.kind === ReferenceKind.ONE_TO_MANY || prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
441
438
|
const owner = prop.targetMeta.properties[prop.mappedBy];
|
|
442
439
|
if (owner && !ret.includes(owner.name)) {
|
|
443
440
|
ret.push(owner.name);
|
|
@@ -448,16 +445,16 @@ class EntityLoader {
|
|
|
448
445
|
getChildReferences(entities, prop, options, ref) {
|
|
449
446
|
const filtered = this.filterCollections(entities, prop.name, options, ref);
|
|
450
447
|
const children = [];
|
|
451
|
-
if (prop.kind ===
|
|
448
|
+
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
452
449
|
children.push(...filtered.map(e => e[prop.name].owner));
|
|
453
450
|
}
|
|
454
|
-
else if (prop.kind ===
|
|
451
|
+
else if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner) {
|
|
455
452
|
children.push(...filtered.reduce((a, b) => {
|
|
456
453
|
a.push(...b[prop.name].getItems());
|
|
457
454
|
return a;
|
|
458
455
|
}, []));
|
|
459
456
|
}
|
|
460
|
-
else if (prop.kind ===
|
|
457
|
+
else if (prop.kind === ReferenceKind.MANY_TO_MANY) { // inverse side
|
|
461
458
|
children.push(...filtered);
|
|
462
459
|
}
|
|
463
460
|
else { // MANY_TO_ONE or ONE_TO_ONE
|
|
@@ -469,39 +466,39 @@ class EntityLoader {
|
|
|
469
466
|
if (options.refresh) {
|
|
470
467
|
return entities.filter(e => e[field]);
|
|
471
468
|
}
|
|
472
|
-
return entities.filter(e =>
|
|
469
|
+
return entities.filter(e => Utils.isCollection(e[field]) && !e[field].isInitialized(!ref));
|
|
473
470
|
}
|
|
474
471
|
isPropertyLoaded(entity, field) {
|
|
475
472
|
if (!entity || field === '*') {
|
|
476
473
|
return true;
|
|
477
474
|
}
|
|
478
|
-
const wrapped =
|
|
475
|
+
const wrapped = helper(entity);
|
|
479
476
|
if (!field.includes('.')) {
|
|
480
477
|
return wrapped.__loadedProperties.has(field);
|
|
481
478
|
}
|
|
482
479
|
const [f, ...r] = field.split('.');
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
480
|
+
/* v8 ignore next 3 */
|
|
481
|
+
if (!wrapped.__loadedProperties.has(f) || !wrapped.__meta.properties[f]?.targetMeta) {
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
if ([ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(wrapped.__meta.properties[f].kind)) {
|
|
485
|
+
return entity[f].getItems(false).every((item) => this.isPropertyLoaded(item, r.join('.')));
|
|
488
486
|
}
|
|
489
|
-
|
|
490
|
-
return false;
|
|
487
|
+
return this.isPropertyLoaded(entity[f], r.join('.'));
|
|
491
488
|
}
|
|
492
489
|
filterReferences(entities, field, options, ref) {
|
|
493
490
|
if (ref) {
|
|
494
491
|
return [];
|
|
495
492
|
}
|
|
496
|
-
const children = entities.filter(e =>
|
|
493
|
+
const children = entities.filter(e => Utils.isEntity(e[field], true));
|
|
497
494
|
if (options.refresh) {
|
|
498
|
-
return children.map(e =>
|
|
495
|
+
return children.map(e => Reference.unwrapReference(e[field]));
|
|
499
496
|
}
|
|
500
497
|
if (options.fields) {
|
|
501
498
|
return children
|
|
502
|
-
.map(e =>
|
|
499
|
+
.map(e => Reference.unwrapReference(e[field]))
|
|
503
500
|
.filter(target => {
|
|
504
|
-
const wrapped =
|
|
501
|
+
const wrapped = helper(target);
|
|
505
502
|
const childFields = options.fields
|
|
506
503
|
.filter(f => f.startsWith(`${field}.`))
|
|
507
504
|
.map(f => f.substring(field.length + 1));
|
|
@@ -510,10 +507,10 @@ class EntityLoader {
|
|
|
510
507
|
}
|
|
511
508
|
return children
|
|
512
509
|
.filter(e => !e[field].__helper.__initialized)
|
|
513
|
-
.map(e =>
|
|
510
|
+
.map(e => Reference.unwrapReference(e[field]));
|
|
514
511
|
}
|
|
515
512
|
filterByReferences(entities, field, refresh) {
|
|
516
|
-
/*
|
|
513
|
+
/* v8 ignore next 3 */
|
|
517
514
|
if (refresh) {
|
|
518
515
|
return entities;
|
|
519
516
|
}
|
|
@@ -526,7 +523,7 @@ class EntityLoader {
|
|
|
526
523
|
ret.push({
|
|
527
524
|
field: this.getRelationName(meta, prop),
|
|
528
525
|
// force select-in strategy when populating all relations as otherwise we could cause infinite loops when self-referencing
|
|
529
|
-
strategy:
|
|
526
|
+
strategy: LoadStrategy.SELECT_IN,
|
|
530
527
|
// no need to look up populate children recursively as we just pass `all: true` here
|
|
531
528
|
all: true,
|
|
532
529
|
});
|
|
@@ -569,11 +566,10 @@ class EntityLoader {
|
|
|
569
566
|
ret.push({
|
|
570
567
|
field: prefixed,
|
|
571
568
|
// enforce select-in strategy for self-referencing relations
|
|
572
|
-
strategy: selfReferencing ?
|
|
569
|
+
strategy: selfReferencing ? LoadStrategy.SELECT_IN : strategy ?? prop.strategy,
|
|
573
570
|
});
|
|
574
571
|
}
|
|
575
572
|
});
|
|
576
573
|
return ret;
|
|
577
574
|
}
|
|
578
575
|
}
|
|
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>;
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const errors_1 = require("../errors");
|
|
5
|
-
const Utils_1 = require("../utils/Utils");
|
|
6
|
-
class EntityRepository {
|
|
1
|
+
import { ValidationError } from '../errors.js';
|
|
2
|
+
import { Utils } from '../utils/Utils.js';
|
|
3
|
+
export class EntityRepository {
|
|
7
4
|
em;
|
|
8
5
|
entityName;
|
|
9
6
|
constructor(em, entityName) {
|
|
@@ -191,7 +188,7 @@ class EntityRepository {
|
|
|
191
188
|
return this.getEntityManager().count(this.entityName, where, options);
|
|
192
189
|
}
|
|
193
190
|
getEntityName() {
|
|
194
|
-
return
|
|
191
|
+
return Utils.className(this.entityName);
|
|
195
192
|
}
|
|
196
193
|
/**
|
|
197
194
|
* Returns the underlying EntityManager instance
|
|
@@ -200,15 +197,14 @@ class EntityRepository {
|
|
|
200
197
|
return this.em;
|
|
201
198
|
}
|
|
202
199
|
validateRepositoryType(entities, method) {
|
|
203
|
-
entities =
|
|
200
|
+
entities = Utils.asArray(entities);
|
|
204
201
|
if (entities.length === 0) {
|
|
205
202
|
return;
|
|
206
203
|
}
|
|
207
204
|
const entityName = entities[0].constructor.name;
|
|
208
|
-
const repoType =
|
|
205
|
+
const repoType = Utils.className(this.entityName);
|
|
209
206
|
if (entityName && repoType !== entityName) {
|
|
210
|
-
throw
|
|
207
|
+
throw ValidationError.fromWrongRepositoryType(entityName, repoType, method);
|
|
211
208
|
}
|
|
212
209
|
}
|
|
213
210
|
}
|
|
214
|
-
exports.EntityRepository = EntityRepository;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EntityData, EntityMetadata, EntityProperty, FilterQuery } from '../typings';
|
|
1
|
+
import type { EntityData, EntityMetadata, EntityProperty, FilterQuery } from '../typings.js';
|
|
2
2
|
export declare class EntityValidator {
|
|
3
3
|
private strict;
|
|
4
4
|
KNOWN_TYPES: Set<string>;
|