@mikro-orm/core 7.0.0-dev.114 → 7.0.0-dev.116
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 +8 -8
- package/EntityManager.js +42 -62
- package/MikroORM.d.ts +1 -1
- package/MikroORM.js +2 -3
- package/drivers/DatabaseDriver.d.ts +11 -11
- package/drivers/DatabaseDriver.js +7 -8
- package/drivers/IDatabaseDriver.d.ts +10 -10
- package/entity/Collection.js +5 -5
- package/entity/EntityAssigner.js +9 -9
- package/entity/EntityFactory.js +14 -17
- package/entity/EntityHelper.d.ts +2 -2
- package/entity/EntityHelper.js +2 -2
- package/entity/EntityLoader.d.ts +3 -3
- package/entity/EntityLoader.js +17 -16
- package/entity/WrappedEntity.js +1 -1
- package/entity/defineEntity.d.ts +11 -11
- package/errors.d.ts +8 -8
- package/errors.js +14 -13
- package/hydration/ObjectHydrator.js +23 -16
- package/metadata/EntitySchema.d.ts +5 -5
- package/metadata/EntitySchema.js +23 -21
- package/metadata/MetadataDiscovery.d.ts +2 -3
- package/metadata/MetadataDiscovery.js +117 -90
- package/metadata/MetadataProvider.js +2 -0
- package/metadata/MetadataStorage.d.ts +13 -6
- package/metadata/MetadataStorage.js +64 -19
- package/metadata/MetadataValidator.d.ts +2 -2
- package/metadata/MetadataValidator.js +22 -28
- package/metadata/types.d.ts +3 -3
- package/package.json +1 -1
- package/serialization/EntitySerializer.d.ts +3 -0
- package/serialization/EntitySerializer.js +15 -13
- package/serialization/EntityTransformer.js +6 -6
- package/serialization/SerializationContext.d.ts +6 -6
- package/typings.d.ts +16 -14
- package/typings.js +15 -10
- package/unit-of-work/ChangeSet.d.ts +2 -3
- package/unit-of-work/ChangeSet.js +2 -3
- package/unit-of-work/ChangeSetComputer.js +3 -3
- package/unit-of-work/ChangeSetPersister.js +14 -14
- package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
- package/unit-of-work/CommitOrderCalculator.js +13 -13
- package/unit-of-work/UnitOfWork.d.ts +3 -3
- package/unit-of-work/UnitOfWork.js +46 -45
- package/utils/AbstractSchemaGenerator.js +7 -7
- package/utils/Configuration.d.ts +0 -5
- package/utils/DataloaderUtils.js +13 -11
- package/utils/EntityComparator.d.ts +6 -6
- package/utils/EntityComparator.js +26 -24
- package/utils/QueryHelper.d.ts +5 -5
- package/utils/QueryHelper.js +7 -7
- package/utils/TransactionManager.js +1 -1
- package/utils/Utils.d.ts +1 -1
- package/utils/Utils.js +1 -2
- package/utils/env-vars.js +0 -1
package/entity/Collection.js
CHANGED
|
@@ -84,7 +84,7 @@ export class Collection {
|
|
|
84
84
|
return this._count = this.length;
|
|
85
85
|
}
|
|
86
86
|
const cond = this.createLoadCountCondition(where ?? {});
|
|
87
|
-
const count = await em.count(this.property.
|
|
87
|
+
const count = await em.count(this.property.targetMeta.class, cond, countOptions);
|
|
88
88
|
if (!where) {
|
|
89
89
|
this._count = count;
|
|
90
90
|
}
|
|
@@ -96,12 +96,12 @@ export class Collection {
|
|
|
96
96
|
opts.orderBy = this.createOrderBy(opts.orderBy);
|
|
97
97
|
let items;
|
|
98
98
|
if (this.property.kind === ReferenceKind.MANY_TO_MANY && em.getPlatform().usesPivotTable()) {
|
|
99
|
-
const cond = await em.applyFilters(this.property.
|
|
99
|
+
const cond = await em.applyFilters(this.property.targetMeta.class, where, options.filters ?? {}, 'read');
|
|
100
100
|
const map = await em.getDriver().loadFromPivotTable(this.property, [helper(this.owner).__primaryKeys], cond, opts.orderBy, ctx, options);
|
|
101
|
-
items = map[helper(this.owner).getSerializedPrimaryKey()].map((item) => em.merge(this.property.
|
|
101
|
+
items = map[helper(this.owner).getSerializedPrimaryKey()].map((item) => em.merge(this.property.targetMeta.class, item, { convertCustomTypes: true }));
|
|
102
102
|
}
|
|
103
103
|
else {
|
|
104
|
-
items = await em.find(this.property.
|
|
104
|
+
items = await em.find(this.property.targetMeta.class, this.createCondition(where), opts);
|
|
105
105
|
}
|
|
106
106
|
if (options.store) {
|
|
107
107
|
this.hydrate(items, true);
|
|
@@ -331,7 +331,7 @@ export class Collection {
|
|
|
331
331
|
}
|
|
332
332
|
checkInitialized() {
|
|
333
333
|
if (!this.isInitialized()) {
|
|
334
|
-
throw new Error(`Collection<${this.property.type}> of entity ${this.owner.
|
|
334
|
+
throw new Error(`Collection<${this.property.type}> of entity ${helper(this.owner).__meta.name}[${helper(this.owner).getSerializedPrimaryKey()}] not initialized`);
|
|
335
335
|
}
|
|
336
336
|
}
|
|
337
337
|
/**
|
package/entity/EntityAssigner.js
CHANGED
|
@@ -77,7 +77,7 @@ export class EntityAssigner {
|
|
|
77
77
|
if (options.updateByPrimaryKey) {
|
|
78
78
|
const pk = Utils.extractPK(value, prop.targetMeta);
|
|
79
79
|
if (pk) {
|
|
80
|
-
const ref = options.em.getReference(prop.
|
|
80
|
+
const ref = options.em.getReference(prop.targetMeta.class, pk, options);
|
|
81
81
|
// if the PK differs, we want to change the target entity, not update it
|
|
82
82
|
const wrappedChild = helper(ref);
|
|
83
83
|
const sameTarget = wrappedChild.getSerializedPrimaryKey() === wrapped.getSerializedPrimaryKey();
|
|
@@ -141,13 +141,13 @@ export class EntityAssigner {
|
|
|
141
141
|
entity[prop.name] = Reference.wrapReference(value, prop);
|
|
142
142
|
}
|
|
143
143
|
else if (Utils.isPrimaryKey(value, true) && EntityAssigner.validateEM(em)) {
|
|
144
|
-
entity[prop.name] = prop.mapToPk ? value : Reference.wrapReference(em.getReference(prop.
|
|
144
|
+
entity[prop.name] = prop.mapToPk ? value : Reference.wrapReference(em.getReference(prop.targetMeta.class, value, options), prop);
|
|
145
145
|
}
|
|
146
146
|
else if (Utils.isPlainObject(value) && options.merge && EntityAssigner.validateEM(em)) {
|
|
147
|
-
entity[prop.name] = Reference.wrapReference(em.merge(prop.
|
|
147
|
+
entity[prop.name] = Reference.wrapReference(em.merge(prop.targetMeta.class, value, options), prop);
|
|
148
148
|
}
|
|
149
149
|
else if (Utils.isPlainObject(value) && EntityAssigner.validateEM(em)) {
|
|
150
|
-
entity[prop.name] = Reference.wrapReference(em.create(prop.
|
|
150
|
+
entity[prop.name] = Reference.wrapReference(em.create(prop.targetMeta.class, value, options), prop);
|
|
151
151
|
}
|
|
152
152
|
else {
|
|
153
153
|
const name = entity.constructor.name;
|
|
@@ -166,7 +166,7 @@ export class EntityAssigner {
|
|
|
166
166
|
if (options.updateNestedEntities && options.updateByPrimaryKey && Utils.isPlainObject(item)) {
|
|
167
167
|
const pk = Utils.extractPK(item, prop.targetMeta);
|
|
168
168
|
if (pk && EntityAssigner.validateEM(em)) {
|
|
169
|
-
const ref = em.getUnitOfWork().getById(prop.
|
|
169
|
+
const ref = em.getUnitOfWork().getById(prop.targetMeta.class, pk, options.schema);
|
|
170
170
|
if (ref) {
|
|
171
171
|
return EntityAssigner.assign(ref, item, options);
|
|
172
172
|
}
|
|
@@ -207,7 +207,7 @@ export class EntityAssigner {
|
|
|
207
207
|
entity[propName].push(...Object.values(tmp));
|
|
208
208
|
});
|
|
209
209
|
}
|
|
210
|
-
const create = () => EntityAssigner.validateEM(em) && em.getEntityFactory().createEmbeddable(prop.
|
|
210
|
+
const create = () => EntityAssigner.validateEM(em) && em.getEntityFactory().createEmbeddable(prop.targetMeta.class, value, {
|
|
211
211
|
convertCustomTypes: options.convertCustomTypes,
|
|
212
212
|
newEntity: options.mergeEmbeddedProperties ? !('propName' in entity) : true,
|
|
213
213
|
});
|
|
@@ -221,13 +221,13 @@ export class EntityAssigner {
|
|
|
221
221
|
return item;
|
|
222
222
|
}
|
|
223
223
|
if (Utils.isPrimaryKey(item) && EntityAssigner.validateEM(em)) {
|
|
224
|
-
return em.getReference(prop.
|
|
224
|
+
return em.getReference(prop.targetMeta.class, item, options);
|
|
225
225
|
}
|
|
226
226
|
if (Utils.isPlainObject(item) && options.merge && EntityAssigner.validateEM(em)) {
|
|
227
|
-
return em.merge(prop.
|
|
227
|
+
return em.merge(prop.targetMeta.class, item, options);
|
|
228
228
|
}
|
|
229
229
|
if (Utils.isPlainObject(item) && EntityAssigner.validateEM(em)) {
|
|
230
|
-
return em.create(prop.
|
|
230
|
+
return em.create(prop.targetMeta.class, item, options);
|
|
231
231
|
}
|
|
232
232
|
invalid.push(item);
|
|
233
233
|
return item;
|
package/entity/EntityFactory.js
CHANGED
|
@@ -30,7 +30,6 @@ export class EntityFactory {
|
|
|
30
30
|
if (data.__entity) {
|
|
31
31
|
return data;
|
|
32
32
|
}
|
|
33
|
-
entityName = Utils.className(entityName);
|
|
34
33
|
const meta = this.metadata.get(entityName);
|
|
35
34
|
if (meta.virtual) {
|
|
36
35
|
data = { ...data };
|
|
@@ -110,12 +109,12 @@ export class EntityFactory {
|
|
|
110
109
|
data = QueryHelper.processParams(data);
|
|
111
110
|
const existsData = this.comparator.prepareEntity(entity);
|
|
112
111
|
const originalEntityData = helper(entity).__originalEntityData ?? {};
|
|
113
|
-
const diff = this.comparator.diffEntities(meta.
|
|
112
|
+
const diff = this.comparator.diffEntities(meta.class, originalEntityData, existsData);
|
|
114
113
|
// version properties are not part of entity snapshots
|
|
115
114
|
if (meta.versionProperty && data[meta.versionProperty] && data[meta.versionProperty] !== originalEntityData[meta.versionProperty]) {
|
|
116
115
|
diff[meta.versionProperty] = data[meta.versionProperty];
|
|
117
116
|
}
|
|
118
|
-
const diff2 = this.comparator.diffEntities(meta.
|
|
117
|
+
const diff2 = this.comparator.diffEntities(meta.class, existsData, data, { includeInverseSides: true });
|
|
119
118
|
// do not override values changed by user
|
|
120
119
|
Utils.keys(diff).forEach(key => delete diff2[key]);
|
|
121
120
|
Utils.keys(diff2).filter(key => {
|
|
@@ -152,18 +151,17 @@ export class EntityFactory {
|
|
|
152
151
|
// we just create the entity from scratch, which will automatically pick the right one from the identity map and call `mergeData` on it
|
|
153
152
|
data[prop.name]
|
|
154
153
|
.filter(child => Utils.isPlainObject(child)) // objects with prototype can be PKs (e.g. `ObjectId`)
|
|
155
|
-
.forEach(child => this.create(prop.
|
|
154
|
+
.forEach(child => this.create(prop.targetMeta.class, child, options)); // we can ignore the value, we just care about the `mergeData` call
|
|
156
155
|
return;
|
|
157
156
|
}
|
|
158
157
|
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(data[prop.name]) && entity[prop.name] && helper(entity[prop.name]).__initialized) {
|
|
159
|
-
this.create(prop.
|
|
158
|
+
this.create(prop.targetMeta.class, data[prop.name], options); // we can ignore the value, we just care about the `mergeData` call
|
|
160
159
|
}
|
|
161
160
|
});
|
|
162
161
|
this.unitOfWork.normalizeEntityData(meta, originalEntityData);
|
|
163
162
|
}
|
|
164
163
|
createReference(entityName, id, options = {}) {
|
|
165
164
|
options.convertCustomTypes ??= true;
|
|
166
|
-
entityName = Utils.className(entityName);
|
|
167
165
|
const meta = this.metadata.get(entityName);
|
|
168
166
|
const schema = this.driver.getSchemaName(meta, options);
|
|
169
167
|
if (meta.simplePK) {
|
|
@@ -188,7 +186,6 @@ export class EntityFactory {
|
|
|
188
186
|
return this.create(entityName, id, { ...options, initialized: false });
|
|
189
187
|
}
|
|
190
188
|
createEmbeddable(entityName, data, options = {}) {
|
|
191
|
-
entityName = Utils.className(entityName);
|
|
192
189
|
data = { ...data };
|
|
193
190
|
const meta = this.metadata.get(entityName);
|
|
194
191
|
const meta2 = this.processDiscriminatorColumn(meta, data);
|
|
@@ -200,7 +197,7 @@ export class EntityFactory {
|
|
|
200
197
|
createEntity(data, meta, options) {
|
|
201
198
|
const schema = this.driver.getSchemaName(meta, options);
|
|
202
199
|
if (options.newEntity || meta.forceConstructor || meta.virtual) {
|
|
203
|
-
if (
|
|
200
|
+
if (meta.polymorphs) {
|
|
204
201
|
throw new Error(`Cannot create entity ${meta.className}, class prototype is unknown`);
|
|
205
202
|
}
|
|
206
203
|
const params = this.extractConstructorParams(meta, data, options);
|
|
@@ -263,13 +260,13 @@ export class EntityFactory {
|
|
|
263
260
|
findEntity(data, meta, options) {
|
|
264
261
|
const schema = this.driver.getSchemaName(meta, options);
|
|
265
262
|
if (meta.simplePK) {
|
|
266
|
-
return this.unitOfWork.getById(meta.
|
|
263
|
+
return this.unitOfWork.getById(meta.class, data[meta.primaryKeys[0]], schema);
|
|
267
264
|
}
|
|
268
265
|
if (!Array.isArray(data) && meta.primaryKeys.some(pk => data[pk] == null)) {
|
|
269
266
|
return undefined;
|
|
270
267
|
}
|
|
271
268
|
const pks = Utils.getOrderedPrimaryKeys(data, meta, this.platform, options.convertCustomTypes);
|
|
272
|
-
return this.unitOfWork.getById(meta.
|
|
269
|
+
return this.unitOfWork.getById(meta.class, pks, schema);
|
|
273
270
|
}
|
|
274
271
|
processDiscriminatorColumn(meta, data) {
|
|
275
272
|
if (!meta.root.discriminatorColumn) {
|
|
@@ -278,7 +275,7 @@ export class EntityFactory {
|
|
|
278
275
|
const prop = meta.properties[meta.root.discriminatorColumn];
|
|
279
276
|
const value = data[prop.name];
|
|
280
277
|
const type = meta.root.discriminatorMap[value];
|
|
281
|
-
meta = type ? this.metadata.
|
|
278
|
+
meta = type ? this.metadata.get(type) : meta;
|
|
282
279
|
return meta;
|
|
283
280
|
}
|
|
284
281
|
/**
|
|
@@ -307,7 +304,7 @@ export class EntityFactory {
|
|
|
307
304
|
const value = data[k];
|
|
308
305
|
if (prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && value) {
|
|
309
306
|
const pk = Reference.unwrapReference(value);
|
|
310
|
-
const entity = this.unitOfWork.getById(prop.
|
|
307
|
+
const entity = this.unitOfWork.getById(prop.targetMeta.class, pk, options.schema, true);
|
|
311
308
|
if (entity) {
|
|
312
309
|
return entity;
|
|
313
310
|
}
|
|
@@ -316,10 +313,10 @@ export class EntityFactory {
|
|
|
316
313
|
}
|
|
317
314
|
const nakedPk = Utils.extractPK(value, prop.targetMeta, true);
|
|
318
315
|
if (Utils.isObject(value) && !nakedPk) {
|
|
319
|
-
return this.create(prop.
|
|
316
|
+
return this.create(prop.targetMeta.class, value, options);
|
|
320
317
|
}
|
|
321
318
|
const { newEntity, initialized, ...rest } = options;
|
|
322
|
-
const target = this.createReference(prop.
|
|
319
|
+
const target = this.createReference(prop.targetMeta.class, nakedPk, rest);
|
|
323
320
|
return Reference.wrapReference(target, prop);
|
|
324
321
|
}
|
|
325
322
|
if (prop?.kind === ReferenceKind.EMBEDDED && value) {
|
|
@@ -327,7 +324,7 @@ export class EntityFactory {
|
|
|
327
324
|
if (Utils.isEntity(value)) {
|
|
328
325
|
return value;
|
|
329
326
|
}
|
|
330
|
-
return this.createEmbeddable(prop.
|
|
327
|
+
return this.createEmbeddable(prop.targetMeta.class, value, options);
|
|
331
328
|
}
|
|
332
329
|
if (!prop) {
|
|
333
330
|
const tmp = { ...data };
|
|
@@ -335,8 +332,8 @@ export class EntityFactory {
|
|
|
335
332
|
if (!options.convertCustomTypes || !prop.customType || tmp[prop.name] == null) {
|
|
336
333
|
continue;
|
|
337
334
|
}
|
|
338
|
-
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(tmp[prop.name]) && !Utils.extractPK(tmp[prop.name],
|
|
339
|
-
tmp[prop.name] = Reference.wrapReference(this.create(
|
|
335
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(tmp[prop.name]) && !Utils.extractPK(tmp[prop.name], prop.targetMeta, true)) {
|
|
336
|
+
tmp[prop.name] = Reference.wrapReference(this.create(prop.targetMeta.class, tmp[prop.name], options), prop);
|
|
340
337
|
}
|
|
341
338
|
else if (prop.kind === ReferenceKind.SCALAR) {
|
|
342
339
|
tmp[prop.name] = prop.customType.convertToJSValue(tmp[prop.name], this.platform);
|
package/entity/EntityHelper.d.ts
CHANGED
|
@@ -6,9 +6,9 @@ import { type EntityMetadata, type EntityProperty, type IHydrator } from '../typ
|
|
|
6
6
|
export declare class EntityHelper {
|
|
7
7
|
static decorate<T extends object>(meta: EntityMetadata<T>, em: EntityManager): void;
|
|
8
8
|
/**
|
|
9
|
-
* As a performance optimization, we create entity state methods
|
|
9
|
+
* As a performance optimization, we create entity state methods lazily. We first add
|
|
10
10
|
* the `null` value to the prototype to reserve space in memory. Then we define a setter on the
|
|
11
|
-
* prototype
|
|
11
|
+
* prototype that will be executed exactly once per entity instance. There we redefine the given
|
|
12
12
|
* property on the entity instance, so shadowing the prototype setter.
|
|
13
13
|
*/
|
|
14
14
|
private static defineBaseProperties;
|
package/entity/EntityHelper.js
CHANGED
|
@@ -38,9 +38,9 @@ export class EntityHelper {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
|
-
* As a performance optimization, we create entity state methods
|
|
41
|
+
* As a performance optimization, we create entity state methods lazily. We first add
|
|
42
42
|
* the `null` value to the prototype to reserve space in memory. Then we define a setter on the
|
|
43
|
-
* prototype
|
|
43
|
+
* prototype that will be executed exactly once per entity instance. There we redefine the given
|
|
44
44
|
* property on the entity instance, so shadowing the prototype setter.
|
|
45
45
|
*/
|
|
46
46
|
static defineBaseProperties(meta, prototype, em) {
|
package/entity/EntityLoader.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyEntity, ConnectionType, EntityProperty, FilterQuery, PopulateOptions } from '../typings.js';
|
|
1
|
+
import type { AnyEntity, ConnectionType, EntityName, EntityProperty, FilterQuery, PopulateOptions } from '../typings.js';
|
|
2
2
|
import type { EntityManager } from '../EntityManager.js';
|
|
3
3
|
import { LoadStrategy, type LockMode, type PopulateHint, PopulatePath, type QueryOrderMap } from '../enums.js';
|
|
4
4
|
import type { EntityField, FilterOptions } from '../drivers/IDatabaseDriver.js';
|
|
@@ -30,8 +30,8 @@ export declare class EntityLoader {
|
|
|
30
30
|
* Loads specified relations in batch.
|
|
31
31
|
* This will execute one query for each relation, that will populate it on all the specified entities.
|
|
32
32
|
*/
|
|
33
|
-
populate<Entity extends object, Fields extends string = PopulatePath.ALL>(entityName:
|
|
34
|
-
normalizePopulate<Entity>(entityName:
|
|
33
|
+
populate<Entity extends object, Fields extends string = PopulatePath.ALL>(entityName: EntityName<Entity>, entities: Entity[], populate: PopulateOptions<Entity>[] | boolean, options: EntityLoaderOptions<Entity, Fields>): Promise<void>;
|
|
34
|
+
normalizePopulate<Entity>(entityName: EntityName<Entity>, populate: (PopulateOptions<Entity> | boolean)[] | PopulateOptions<Entity> | boolean, strategy?: LoadStrategy, lookup?: boolean): PopulateOptions<Entity>[];
|
|
35
35
|
private setSerializationContext;
|
|
36
36
|
/**
|
|
37
37
|
* Merge multiple populates for the same entity with different children. Also skips `*` fields, those can come from
|
package/entity/EntityLoader.js
CHANGED
|
@@ -157,7 +157,7 @@ export class EntityLoader {
|
|
|
157
157
|
const ids = Utils.unique(filtered.map(e => Utils.getPrimaryKeyValues(e, meta, true)));
|
|
158
158
|
const where = this.mergePrimaryCondition(ids, pk, options, meta, this.metadata, this.driver.getPlatform());
|
|
159
159
|
const { filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging, fields } = options;
|
|
160
|
-
await this.em.find(meta.
|
|
160
|
+
await this.em.find(meta.class, where, {
|
|
161
161
|
filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging,
|
|
162
162
|
fields: fields,
|
|
163
163
|
populate: [],
|
|
@@ -181,7 +181,7 @@ export class EntityLoader {
|
|
|
181
181
|
for (const child of children) {
|
|
182
182
|
const pk = child.__helper.__data[prop.mappedBy] ?? child[prop.mappedBy];
|
|
183
183
|
if (pk) {
|
|
184
|
-
const key = helper(mapToPk ? this.em.getReference(prop.
|
|
184
|
+
const key = helper(mapToPk ? this.em.getReference(prop.targetMeta.class, pk) : pk).getSerializedPrimaryKey();
|
|
185
185
|
map[key]?.push(child);
|
|
186
186
|
}
|
|
187
187
|
}
|
|
@@ -244,7 +244,7 @@ export class EntityLoader {
|
|
|
244
244
|
// skip consecutive ordering with the same key to get around mongo issues
|
|
245
245
|
return idx === 0 || !Utils.equals(Utils.getObjectQueryKeys(array[idx - 1]), Utils.getObjectQueryKeys(order));
|
|
246
246
|
});
|
|
247
|
-
const items = await this.em.find(
|
|
247
|
+
const items = await this.em.find(meta.class, where, {
|
|
248
248
|
filters, convertCustomTypes, lockMode, populateWhere, logging,
|
|
249
249
|
orderBy,
|
|
250
250
|
populate: populate.children ?? populate.all ?? [],
|
|
@@ -283,7 +283,7 @@ export class EntityLoader {
|
|
|
283
283
|
return { items, partial };
|
|
284
284
|
}
|
|
285
285
|
mergePrimaryCondition(ids, pk, options, meta, metadata, platform) {
|
|
286
|
-
const cond1 = QueryHelper.processWhere({ where: { [pk]: { $in: ids } }, entityName: meta.
|
|
286
|
+
const cond1 = QueryHelper.processWhere({ where: { [pk]: { $in: ids } }, entityName: meta.class, metadata, platform, convertCustomTypes: !options.convertCustomTypes });
|
|
287
287
|
const where = { ...options.where };
|
|
288
288
|
Utils.dropUndefinedProperties(where);
|
|
289
289
|
return where[pk]
|
|
@@ -335,7 +335,11 @@ export class EntityLoader {
|
|
|
335
335
|
for (const entity of entities) {
|
|
336
336
|
visited.add(entity);
|
|
337
337
|
}
|
|
338
|
-
|
|
338
|
+
// skip lazy scalar properties
|
|
339
|
+
if (!prop.targetMeta) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
await this.populate(prop.targetMeta.class, unique, populate.children ?? populate.all, {
|
|
339
343
|
where: await this.extractChildCondition(options, prop, false),
|
|
340
344
|
orderBy: innerOrderBy,
|
|
341
345
|
fields,
|
|
@@ -380,12 +384,12 @@ export class EntityLoader {
|
|
|
380
384
|
for (const entity of filtered) {
|
|
381
385
|
const items = map[entity.__helper.getSerializedPrimaryKey()].map(item => {
|
|
382
386
|
if (pivotJoin) {
|
|
383
|
-
return this.em.getReference(prop.
|
|
387
|
+
return this.em.getReference(prop.targetMeta.class, item, {
|
|
384
388
|
convertCustomTypes: true,
|
|
385
389
|
schema: options.schema ?? this.em.config.get('schema'),
|
|
386
390
|
});
|
|
387
391
|
}
|
|
388
|
-
const entity = this.em.getEntityFactory().create(prop.
|
|
392
|
+
const entity = this.em.getEntityFactory().create(prop.targetMeta.class, item, {
|
|
389
393
|
refresh,
|
|
390
394
|
merge: true,
|
|
391
395
|
convertCustomTypes: true,
|
|
@@ -401,10 +405,7 @@ export class EntityLoader {
|
|
|
401
405
|
async extractChildCondition(options, prop, filters = false) {
|
|
402
406
|
const where = options.where;
|
|
403
407
|
const subCond = Utils.isPlainObject(where[prop.name]) ? where[prop.name] : {};
|
|
404
|
-
const meta2 =
|
|
405
|
-
if (!meta2) {
|
|
406
|
-
return {};
|
|
407
|
-
}
|
|
408
|
+
const meta2 = prop.targetMeta;
|
|
408
409
|
const pk = Utils.getPrimaryKeyHash(meta2.primaryKeys);
|
|
409
410
|
['$and', '$or'].forEach(op => {
|
|
410
411
|
if (where[op]) {
|
|
@@ -431,7 +432,7 @@ export class EntityLoader {
|
|
|
431
432
|
});
|
|
432
433
|
}
|
|
433
434
|
if (filters) {
|
|
434
|
-
return this.em.applyFilters(
|
|
435
|
+
return this.em.applyFilters(meta2.class, subCond, options.filters, 'read', options);
|
|
435
436
|
}
|
|
436
437
|
return subCond;
|
|
437
438
|
}
|
|
@@ -564,10 +565,10 @@ export class EntityLoader {
|
|
|
564
565
|
if (!meta && !prefix) {
|
|
565
566
|
return populate;
|
|
566
567
|
}
|
|
567
|
-
if (visited.includes(
|
|
568
|
+
if (!meta || visited.includes(meta)) {
|
|
568
569
|
return [];
|
|
569
570
|
}
|
|
570
|
-
visited.push(
|
|
571
|
+
visited.push(meta);
|
|
571
572
|
const ret = prefix === '' ? [...populate] : [];
|
|
572
573
|
meta.relations
|
|
573
574
|
.filter(prop => {
|
|
@@ -580,12 +581,12 @@ export class EntityLoader {
|
|
|
580
581
|
const field = this.getRelationName(meta, prop);
|
|
581
582
|
const prefixed = prefix ? `${prefix}.${field}` : field;
|
|
582
583
|
const nestedPopulate = populate.filter(p => p.field === prop.name).flatMap(p => p.children).filter(Boolean);
|
|
583
|
-
const nested = this.lookupEagerLoadedRelationships(prop.
|
|
584
|
+
const nested = this.lookupEagerLoadedRelationships(prop.targetMeta.class, nestedPopulate, strategy, prefixed, visited.slice());
|
|
584
585
|
if (nested.length > 0) {
|
|
585
586
|
ret.push(...nested);
|
|
586
587
|
}
|
|
587
588
|
else {
|
|
588
|
-
const selfReferencing = [meta.
|
|
589
|
+
const selfReferencing = [meta.tableName, ...visited.map(m => m.tableName)].includes(prop.targetMeta.tableName) && prop.eager;
|
|
589
590
|
ret.push({
|
|
590
591
|
field: prefixed,
|
|
591
592
|
// enforce select-in strategy for self-referencing relations
|
package/entity/WrappedEntity.js
CHANGED
|
@@ -71,7 +71,7 @@ export class WrappedEntity {
|
|
|
71
71
|
if (!this.__em) {
|
|
72
72
|
throw ValidationError.entityNotManaged(this.entity);
|
|
73
73
|
}
|
|
74
|
-
return this.__em.findOne(this.entity.constructor
|
|
74
|
+
return this.__em.findOne(this.entity.constructor, this.entity, { ...options, refresh: true, schema: this.__schema });
|
|
75
75
|
}
|
|
76
76
|
async populate(populate, options = {}) {
|
|
77
77
|
if (!this.__em) {
|
package/entity/defineEntity.d.ts
CHANGED
|
@@ -326,7 +326,7 @@ export declare class UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys
|
|
|
326
326
|
/** Override default name for pivot table (see {@doclink naming-strategy | Naming Strategy}). */
|
|
327
327
|
pivotTable(pivotTable: string): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
328
328
|
/** Set pivot entity for this relation (see {@doclink collections#custom-pivot-table-entity | Custom pivot table entity}). */
|
|
329
|
-
pivotEntity(pivotEntity:
|
|
329
|
+
pivotEntity(pivotEntity: () => EntityName): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
330
330
|
/** Override the default database column name on the owning side (see {@doclink naming-strategy | Naming Strategy}). This option is only for simple properties represented by a single column. */
|
|
331
331
|
joinColumn(joinColumn: string): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
332
332
|
/** Override the default database column name on the owning side (see {@doclink naming-strategy | Naming Strategy}). This option is suitable for composite keys, where one property is represented by multiple columns. */
|
|
@@ -380,15 +380,15 @@ declare const propertyBuilders: {
|
|
|
380
380
|
time: (length?: number) => UniversalPropertyOptionsBuilder<any, EmptyOptions, IncludeKeysForProperty>;
|
|
381
381
|
type: <T extends PropertyValueType>(type: T) => UniversalPropertyOptionsBuilder<InferPropertyValueType<T>, EmptyOptions, IncludeKeysForProperty>;
|
|
382
382
|
enum: <const T extends (number | string)[] | (() => Dictionary)>(items?: T) => UniversalPropertyOptionsBuilder<T extends () => Dictionary ? ValueOf<ReturnType<T>> : T extends (infer Value)[] ? Value : T, EmptyOptions, IncludeKeysForEnumOptions>;
|
|
383
|
-
embedded: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass
|
|
384
|
-
manyToMany: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass
|
|
383
|
+
embedded: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass | EntitySchemaWithMeta<any, any, any, any, any>[] | EntityClass[]>(target: Target) => UniversalPropertyOptionsBuilder<InferEntity<Target extends (infer T)[] ? T : Target>, EmptyOptions, IncludeKeysForEmbeddedOptions>;
|
|
384
|
+
manyToMany: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass>(target: Target) => UniversalPropertyOptionsBuilder<InferEntity<Target>, EmptyOptions & {
|
|
385
385
|
kind: "m:n";
|
|
386
386
|
}, IncludeKeysForManyToManyOptions>;
|
|
387
|
-
manyToOne: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass
|
|
387
|
+
manyToOne: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass>(target: Target) => UniversalPropertyOptionsBuilder<InferEntity<Target>, EmptyOptions & {
|
|
388
388
|
kind: "m:1";
|
|
389
389
|
}, IncludeKeysForManyToOneOptions>;
|
|
390
|
-
oneToMany: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass
|
|
391
|
-
oneToOne: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass
|
|
390
|
+
oneToMany: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass>(target: Target) => OneToManyOptionsBuilderOnlyMappedBy<InferEntity<Target>>;
|
|
391
|
+
oneToOne: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass>(target: Target) => UniversalPropertyOptionsBuilder<InferEntity<Target>, EmptyOptions & {
|
|
392
392
|
kind: "1:1";
|
|
393
393
|
}, IncludeKeysForOneToOneOptions>;
|
|
394
394
|
date: () => UniversalPropertyOptionsBuilder<string, EmptyOptions, IncludeKeysForProperty>;
|
|
@@ -454,15 +454,15 @@ export declare namespace defineEntity {
|
|
|
454
454
|
time: (length?: number) => UniversalPropertyOptionsBuilder<any, EmptyOptions, IncludeKeysForProperty>;
|
|
455
455
|
type: <T extends PropertyValueType>(type: T) => UniversalPropertyOptionsBuilder<InferPropertyValueType<T>, EmptyOptions, IncludeKeysForProperty>;
|
|
456
456
|
enum: <const T extends (number | string)[] | (() => Dictionary)>(items?: T) => UniversalPropertyOptionsBuilder<T extends () => Dictionary ? ValueOf<ReturnType<T>> : T extends (infer Value)[] ? Value : T, EmptyOptions, IncludeKeysForEnumOptions>;
|
|
457
|
-
embedded: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass
|
|
458
|
-
manyToMany: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass
|
|
457
|
+
embedded: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass | EntitySchemaWithMeta<any, any, any, any, any>[] | EntityClass[]>(target: Target) => UniversalPropertyOptionsBuilder<InferEntity<Target extends (infer T)[] ? T : Target>, EmptyOptions, IncludeKeysForEmbeddedOptions>;
|
|
458
|
+
manyToMany: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass>(target: Target) => UniversalPropertyOptionsBuilder<InferEntity<Target>, EmptyOptions & {
|
|
459
459
|
kind: "m:n";
|
|
460
460
|
}, IncludeKeysForManyToManyOptions>;
|
|
461
|
-
manyToOne: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass
|
|
461
|
+
manyToOne: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass>(target: Target) => UniversalPropertyOptionsBuilder<InferEntity<Target>, EmptyOptions & {
|
|
462
462
|
kind: "m:1";
|
|
463
463
|
}, IncludeKeysForManyToOneOptions>;
|
|
464
|
-
oneToMany: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass
|
|
465
|
-
oneToOne: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass
|
|
464
|
+
oneToMany: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass>(target: Target) => OneToManyOptionsBuilderOnlyMappedBy<InferEntity<Target>>;
|
|
465
|
+
oneToOne: <Target extends EntitySchemaWithMeta<any, any, any, any, any> | EntityClass>(target: Target) => UniversalPropertyOptionsBuilder<InferEntity<Target>, EmptyOptions & {
|
|
466
466
|
kind: "1:1";
|
|
467
467
|
}, IncludeKeysForOneToOneOptions>;
|
|
468
468
|
date: () => UniversalPropertyOptionsBuilder<string, EmptyOptions, IncludeKeysForProperty>;
|
package/errors.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyEntity, Constructor, Dictionary, EntityMetadata, EntityProperty, IPrimaryKey } from './typings.js';
|
|
1
|
+
import type { AnyEntity, Constructor, Dictionary, EntityMetadata, EntityName, EntityProperty, IPrimaryKey } from './typings.js';
|
|
2
2
|
export declare class ValidationError<T extends AnyEntity = AnyEntity> extends Error {
|
|
3
3
|
readonly entity?: T | undefined;
|
|
4
4
|
constructor(message: string, entity?: T | undefined);
|
|
@@ -13,7 +13,7 @@ export declare class ValidationError<T extends AnyEntity = AnyEntity> extends Er
|
|
|
13
13
|
static entityNotManaged(entity: AnyEntity): ValidationError;
|
|
14
14
|
static notEntity(owner: AnyEntity, prop: EntityProperty, data: any): ValidationError;
|
|
15
15
|
static notDiscoveredEntity(data: any, meta?: EntityMetadata, action?: string): ValidationError;
|
|
16
|
-
static invalidPropertyName(entityName:
|
|
16
|
+
static invalidPropertyName(entityName: EntityName, invalid: string): ValidationError;
|
|
17
17
|
static invalidCollectionValues(entityName: string, propName: string, invalid: unknown): ValidationError;
|
|
18
18
|
static invalidEnumArrayItems(entityName: string, invalid: unknown): ValidationError;
|
|
19
19
|
static invalidType(type: Constructor<any>, value: any, mode: string): ValidationError;
|
|
@@ -24,9 +24,9 @@ export declare class ValidationError<T extends AnyEntity = AnyEntity> extends Er
|
|
|
24
24
|
static invalidCompositeIdentifier(meta: EntityMetadata): ValidationError;
|
|
25
25
|
static cannotCommit(): ValidationError;
|
|
26
26
|
static cannotUseGlobalContext(): ValidationError;
|
|
27
|
-
static cannotUseOperatorsInsideEmbeddables(
|
|
28
|
-
static cannotUseGroupOperatorsInsideScalars(
|
|
29
|
-
static invalidEmbeddableQuery(
|
|
27
|
+
static cannotUseOperatorsInsideEmbeddables(entityName: EntityName, propName: string, payload: unknown): ValidationError;
|
|
28
|
+
static cannotUseGroupOperatorsInsideScalars(entityName: EntityName, propName: string, payload: unknown): ValidationError;
|
|
29
|
+
static invalidEmbeddableQuery(entityName: EntityName, propName: string, embeddableType: string): ValidationError;
|
|
30
30
|
static invalidQueryCondition(cond: unknown): ValidationError;
|
|
31
31
|
}
|
|
32
32
|
export declare class CursorError<T extends AnyEntity = AnyEntity> extends ValidationError<T> {
|
|
@@ -49,11 +49,11 @@ export declare class MetadataError<T extends AnyEntity = AnyEntity> extends Vali
|
|
|
49
49
|
static unknownIndexProperty(meta: EntityMetadata, prop: string, type: string): MetadataError;
|
|
50
50
|
static multipleVersionFields(meta: EntityMetadata, fields: string[]): MetadataError;
|
|
51
51
|
static invalidVersionFieldType(meta: EntityMetadata): MetadataError;
|
|
52
|
-
static fromUnknownEntity(
|
|
52
|
+
static fromUnknownEntity(entityName: string, source: string): MetadataError;
|
|
53
53
|
static noEntityDiscovered(): MetadataError;
|
|
54
54
|
static onlyAbstractEntitiesDiscovered(): MetadataError;
|
|
55
|
-
static duplicateEntityDiscovered(paths: string[]
|
|
56
|
-
static duplicateFieldName(
|
|
55
|
+
static duplicateEntityDiscovered(paths: string[]): MetadataError;
|
|
56
|
+
static duplicateFieldName(entityName: EntityName, names: [string, string][]): MetadataError;
|
|
57
57
|
static multipleDecorators(entityName: string, propertyName: string): MetadataError;
|
|
58
58
|
static missingMetadata(entity: string): MetadataError;
|
|
59
59
|
static invalidPrimaryKey(meta: EntityMetadata, prop: EntityProperty, requiredName: string): MetadataError<Partial<any>>;
|
package/errors.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { inspect } from './logging/inspect.js';
|
|
2
|
+
import { Utils } from '@mikro-orm/core';
|
|
2
3
|
export class ValidationError extends Error {
|
|
3
4
|
entity;
|
|
4
5
|
constructor(message, entity) {
|
|
@@ -46,7 +47,7 @@ export class ValidationError extends Error {
|
|
|
46
47
|
return new ValidationError(err);
|
|
47
48
|
}
|
|
48
49
|
static invalidPropertyName(entityName, invalid) {
|
|
49
|
-
return new ValidationError(`Entity '${entityName}' does not have property '${invalid}'`);
|
|
50
|
+
return new ValidationError(`Entity '${Utils.className(entityName)}' does not have property '${invalid}'`);
|
|
50
51
|
}
|
|
51
52
|
static invalidCollectionValues(entityName, propName, invalid) {
|
|
52
53
|
return new ValidationError(`Invalid collection values provided for '${entityName}.${propName}' in ${entityName}.assign(): ${inspect(invalid)}`);
|
|
@@ -92,14 +93,14 @@ export class ValidationError extends Error {
|
|
|
92
93
|
static cannotUseGlobalContext() {
|
|
93
94
|
return new ValidationError('Using global EntityManager instance methods for context specific actions is disallowed. If you need to work with the global instance\'s identity map, use `allowGlobalContext` configuration option or `fork()` instead.');
|
|
94
95
|
}
|
|
95
|
-
static cannotUseOperatorsInsideEmbeddables(
|
|
96
|
-
return new ValidationError(`Using operators inside embeddables is not allowed, move the operator above. (property: ${className}.${propName}, payload: ${inspect(payload)})`);
|
|
96
|
+
static cannotUseOperatorsInsideEmbeddables(entityName, propName, payload) {
|
|
97
|
+
return new ValidationError(`Using operators inside embeddables is not allowed, move the operator above. (property: ${Utils.className(entityName)}.${propName}, payload: ${inspect(payload)})`);
|
|
97
98
|
}
|
|
98
|
-
static cannotUseGroupOperatorsInsideScalars(
|
|
99
|
-
return new ValidationError(`Using group operators ($and/$or) inside scalar properties is not allowed, move the operator above. (property: ${className}.${propName}, payload: ${inspect(payload)})`);
|
|
99
|
+
static cannotUseGroupOperatorsInsideScalars(entityName, propName, payload) {
|
|
100
|
+
return new ValidationError(`Using group operators ($and/$or) inside scalar properties is not allowed, move the operator above. (property: ${Utils.className(entityName)}.${propName}, payload: ${inspect(payload)})`);
|
|
100
101
|
}
|
|
101
|
-
static invalidEmbeddableQuery(
|
|
102
|
-
return new ValidationError(`Invalid query for entity '${className}', property '${propName}' does not exist in embeddable '${embeddableType}'`);
|
|
102
|
+
static invalidEmbeddableQuery(entityName, propName, embeddableType) {
|
|
103
|
+
return new ValidationError(`Invalid query for entity '${Utils.className(entityName)}', property '${propName}' does not exist in embeddable '${embeddableType}'`);
|
|
103
104
|
}
|
|
104
105
|
/* v8 ignore next */
|
|
105
106
|
static invalidQueryCondition(cond) {
|
|
@@ -169,8 +170,8 @@ export class MetadataError extends ValidationError {
|
|
|
169
170
|
const prop = meta.properties[meta.versionProperty];
|
|
170
171
|
return new MetadataError(`Version property ${meta.className}.${prop.name} has unsupported type '${prop.type}'. Only 'number' and 'Date' are allowed.`);
|
|
171
172
|
}
|
|
172
|
-
static fromUnknownEntity(
|
|
173
|
-
return new MetadataError(`Entity '${
|
|
173
|
+
static fromUnknownEntity(entityName, source) {
|
|
174
|
+
return new MetadataError(`Entity '${entityName}' was not discovered, please make sure to provide it in 'entities' array when initializing the ORM (used in ${source})`);
|
|
174
175
|
}
|
|
175
176
|
static noEntityDiscovered() {
|
|
176
177
|
return new MetadataError('No entities were discovered');
|
|
@@ -178,11 +179,11 @@ export class MetadataError extends ValidationError {
|
|
|
178
179
|
static onlyAbstractEntitiesDiscovered() {
|
|
179
180
|
return new MetadataError('Only abstract entities were discovered, maybe you forgot to use @Entity() decorator? This can also happen when you have multiple `@mikro-orm/core` packages installed side by side.');
|
|
180
181
|
}
|
|
181
|
-
static duplicateEntityDiscovered(paths
|
|
182
|
-
return new MetadataError(`Duplicate
|
|
182
|
+
static duplicateEntityDiscovered(paths) {
|
|
183
|
+
return new MetadataError(`Duplicate table names are not allowed: ${paths.join(', ')}`);
|
|
183
184
|
}
|
|
184
|
-
static duplicateFieldName(
|
|
185
|
-
return new MetadataError(`Duplicate fieldNames are not allowed: ${names.map(n => `${className}.${n[0]} (fieldName: '${n[1]}')`).join(', ')}`);
|
|
185
|
+
static duplicateFieldName(entityName, names) {
|
|
186
|
+
return new MetadataError(`Duplicate fieldNames are not allowed: ${names.map(n => `${Utils.className(entityName)}.${n[0]} (fieldName: '${n[1]}')`).join(', ')}`);
|
|
186
187
|
}
|
|
187
188
|
static multipleDecorators(entityName, propertyName) {
|
|
188
189
|
return new MetadataError(`Multiple property decorators used on '${entityName}.${propertyName}' property`);
|