@mikro-orm/core 6.4.17-dev.9 → 6.4.17-dev.91
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 +11 -2
- package/EntityManager.js +37 -22
- package/README.md +1 -2
- package/connections/Connection.d.ts +4 -2
- package/connections/Connection.js +2 -2
- package/decorators/Entity.d.ts +14 -0
- package/decorators/Indexed.d.ts +2 -2
- package/decorators/Transactional.d.ts +1 -0
- package/decorators/Transactional.js +3 -3
- package/drivers/IDatabaseDriver.d.ts +4 -0
- package/entity/ArrayCollection.d.ts +3 -1
- package/entity/ArrayCollection.js +7 -2
- package/entity/EntityFactory.d.ts +6 -0
- package/entity/EntityFactory.js +17 -6
- package/entity/EntityHelper.js +4 -1
- package/entity/EntityLoader.js +26 -18
- package/entity/Reference.d.ts +5 -0
- package/entity/Reference.js +16 -0
- package/entity/WrappedEntity.js +1 -1
- package/entity/defineEntity.d.ts +528 -0
- package/entity/defineEntity.js +684 -0
- package/entity/index.d.ts +2 -0
- package/entity/index.js +2 -0
- package/entity/utils.d.ts +7 -0
- package/entity/utils.js +16 -3
- package/enums.d.ts +3 -1
- package/enums.js +2 -0
- package/hydration/ObjectHydrator.js +1 -1
- package/index.d.ts +1 -1
- package/index.mjs +4 -0
- package/metadata/MetadataDiscovery.d.ts +0 -1
- package/metadata/MetadataDiscovery.js +16 -13
- package/package.json +4 -4
- package/platforms/Platform.d.ts +3 -1
- package/types/BooleanType.d.ts +1 -1
- package/types/DecimalType.js +1 -1
- package/types/DoubleType.js +1 -1
- package/typings.d.ts +18 -9
- package/typings.js +21 -4
- package/unit-of-work/ChangeSetPersister.d.ts +4 -2
- package/unit-of-work/ChangeSetPersister.js +14 -10
- package/unit-of-work/UnitOfWork.d.ts +1 -1
- package/unit-of-work/UnitOfWork.js +22 -6
- package/utils/Configuration.d.ts +7 -1
- package/utils/Configuration.js +1 -0
- package/utils/ConfigurationLoader.js +2 -2
- package/utils/Cursor.js +3 -0
- package/utils/EntityComparator.d.ts +6 -2
- package/utils/EntityComparator.js +29 -8
- package/utils/QueryHelper.d.ts +6 -0
- package/utils/QueryHelper.js +47 -4
- package/utils/RawQueryFragment.d.ts +34 -0
- package/utils/RawQueryFragment.js +35 -0
- package/utils/Utils.d.ts +2 -2
- package/utils/Utils.js +32 -8
- package/utils/upsert-utils.js +9 -1
package/entity/EntityLoader.js
CHANGED
|
@@ -41,7 +41,7 @@ class EntityLoader {
|
|
|
41
41
|
options.refresh ??= false;
|
|
42
42
|
options.convertCustomTypes ??= true;
|
|
43
43
|
if (references.length > 0) {
|
|
44
|
-
await this.populateScalar(meta, references, options);
|
|
44
|
+
await this.populateScalar(meta, references, { ...options, populateWhere: undefined });
|
|
45
45
|
}
|
|
46
46
|
populate = this.normalizePopulate(entityName, populate, options.strategy, options.lookup);
|
|
47
47
|
const invalid = populate.find(({ field }) => !this.em.canPopulate(entityName, field));
|
|
@@ -143,18 +143,22 @@ class EntityLoader {
|
|
|
143
143
|
const innerOrderBy = Utils_1.Utils.asArray(options.orderBy)
|
|
144
144
|
.filter(orderBy => (Array.isArray(orderBy[prop.name]) && orderBy[prop.name].length > 0) || Utils_1.Utils.isObject(orderBy[prop.name]))
|
|
145
145
|
.flatMap(orderBy => orderBy[prop.name]);
|
|
146
|
+
const where = await this.extractChildCondition(options, prop);
|
|
146
147
|
if (prop.kind === enums_1.ReferenceKind.MANY_TO_MANY && this.driver.getPlatform().usesPivotTable()) {
|
|
147
148
|
const res = await this.findChildrenFromPivotTable(filtered, prop, options, innerOrderBy, populate, !!ref);
|
|
148
149
|
return Utils_1.Utils.flatten(res);
|
|
149
150
|
}
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
const { items, partial } = await this.findChildren(options.filtered ?? entities, prop, populate, {
|
|
152
|
+
...options,
|
|
153
|
+
where,
|
|
154
|
+
orderBy: innerOrderBy,
|
|
155
|
+
}, !!(ref || prop.mapToPk));
|
|
156
|
+
this.initializeCollections(filtered, prop, field, items, innerOrderBy.length > 0, partial);
|
|
157
|
+
return items;
|
|
154
158
|
}
|
|
155
159
|
async populateScalar(meta, filtered, options) {
|
|
156
160
|
const pk = Utils_1.Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
157
|
-
const ids = Utils_1.Utils.unique(filtered.map(e => Utils_1.Utils.getPrimaryKeyValues(e, meta
|
|
161
|
+
const ids = Utils_1.Utils.unique(filtered.map(e => Utils_1.Utils.getPrimaryKeyValues(e, meta, true)));
|
|
158
162
|
const where = this.mergePrimaryCondition(ids, pk, options, meta, this.metadata, this.driver.getPlatform());
|
|
159
163
|
const { filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging, fields } = options;
|
|
160
164
|
await this.em.find(meta.className, where, {
|
|
@@ -163,15 +167,15 @@ class EntityLoader {
|
|
|
163
167
|
populate: [],
|
|
164
168
|
});
|
|
165
169
|
}
|
|
166
|
-
initializeCollections(filtered, prop, field, children, customOrder) {
|
|
170
|
+
initializeCollections(filtered, prop, field, children, customOrder, partial) {
|
|
167
171
|
if (prop.kind === enums_1.ReferenceKind.ONE_TO_MANY) {
|
|
168
|
-
this.initializeOneToMany(filtered, children, prop, field);
|
|
172
|
+
this.initializeOneToMany(filtered, children, prop, field, partial);
|
|
169
173
|
}
|
|
170
174
|
if (prop.kind === enums_1.ReferenceKind.MANY_TO_MANY && !this.driver.getPlatform().usesPivotTable()) {
|
|
171
|
-
this.initializeManyToMany(filtered, children, prop, field, customOrder);
|
|
175
|
+
this.initializeManyToMany(filtered, children, prop, field, customOrder, partial);
|
|
172
176
|
}
|
|
173
177
|
}
|
|
174
|
-
initializeOneToMany(filtered, children, prop, field) {
|
|
178
|
+
initializeOneToMany(filtered, children, prop, field, partial) {
|
|
175
179
|
const mapToPk = prop.targetMeta.properties[prop.mappedBy].mapToPk;
|
|
176
180
|
const map = {};
|
|
177
181
|
for (const entity of filtered) {
|
|
@@ -187,14 +191,14 @@ class EntityLoader {
|
|
|
187
191
|
}
|
|
188
192
|
for (const entity of filtered) {
|
|
189
193
|
const key = (0, wrap_1.helper)(entity).getSerializedPrimaryKey();
|
|
190
|
-
entity[field].hydrate(map[key]);
|
|
194
|
+
entity[field].hydrate(map[key], undefined, partial);
|
|
191
195
|
}
|
|
192
196
|
}
|
|
193
|
-
initializeManyToMany(filtered, children, prop, field, customOrder) {
|
|
197
|
+
initializeManyToMany(filtered, children, prop, field, customOrder, partial) {
|
|
194
198
|
if (prop.mappedBy) {
|
|
195
199
|
for (const entity of filtered) {
|
|
196
200
|
const items = children.filter(child => child[prop.mappedBy].contains(entity, false));
|
|
197
|
-
entity[field].hydrate(items, true);
|
|
201
|
+
entity[field].hydrate(items, true, partial);
|
|
198
202
|
}
|
|
199
203
|
}
|
|
200
204
|
else { // owning side of M:N without pivot table needs to be reordered
|
|
@@ -204,7 +208,7 @@ class EntityLoader {
|
|
|
204
208
|
if (!customOrder) {
|
|
205
209
|
items.sort((a, b) => order.indexOf(a) - order.indexOf(b));
|
|
206
210
|
}
|
|
207
|
-
entity[field].hydrate(items, true);
|
|
211
|
+
entity[field].hydrate(items, true, partial);
|
|
208
212
|
}
|
|
209
213
|
}
|
|
210
214
|
}
|
|
@@ -213,6 +217,7 @@ class EntityLoader {
|
|
|
213
217
|
const meta = prop.targetMeta;
|
|
214
218
|
let fk = Utils_1.Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
215
219
|
let schema = options.schema;
|
|
220
|
+
const partial = !Utils_1.Utils.isEmpty(prop.where) || !Utils_1.Utils.isEmpty(options.where);
|
|
216
221
|
if (prop.kind === enums_1.ReferenceKind.ONE_TO_MANY || (prop.kind === enums_1.ReferenceKind.MANY_TO_MANY && !prop.owner)) {
|
|
217
222
|
fk = meta.properties[prop.mappedBy].name;
|
|
218
223
|
}
|
|
@@ -222,7 +227,7 @@ class EntityLoader {
|
|
|
222
227
|
children.push(...this.filterByReferences(entities, prop.name, options.refresh));
|
|
223
228
|
}
|
|
224
229
|
if (children.length === 0) {
|
|
225
|
-
return [];
|
|
230
|
+
return { items: [], partial };
|
|
226
231
|
}
|
|
227
232
|
if (!schema && [enums_1.ReferenceKind.ONE_TO_ONE, enums_1.ReferenceKind.MANY_TO_ONE].includes(prop.kind)) {
|
|
228
233
|
schema = children.find(e => e.__helper.__schema)?.__helper.__schema;
|
|
@@ -271,7 +276,7 @@ class EntityLoader {
|
|
|
271
276
|
this.em.getUnitOfWork()['loadedEntities'].delete(item);
|
|
272
277
|
}
|
|
273
278
|
}
|
|
274
|
-
return items;
|
|
279
|
+
return { items, partial };
|
|
275
280
|
}
|
|
276
281
|
mergePrimaryCondition(ids, pk, options, meta, metadata, platform) {
|
|
277
282
|
const cond1 = QueryHelper_1.QueryHelper.processWhere({ where: { [pk]: { $in: ids } }, entityName: meta.className, metadata, platform, convertCustomTypes: !options.convertCustomTypes });
|
|
@@ -320,11 +325,12 @@ class EntityLoader {
|
|
|
320
325
|
for (const entity of entities) {
|
|
321
326
|
visited.delete(entity);
|
|
322
327
|
}
|
|
323
|
-
const
|
|
328
|
+
const unique = Utils_1.Utils.unique(children);
|
|
329
|
+
const filtered = unique.filter(e => !visited.has(e));
|
|
324
330
|
for (const entity of entities) {
|
|
325
331
|
visited.add(entity);
|
|
326
332
|
}
|
|
327
|
-
await this.populate(prop.type,
|
|
333
|
+
await this.populate(prop.type, unique, populate.children ?? populate.all, {
|
|
328
334
|
where: await this.extractChildCondition(options, prop, false),
|
|
329
335
|
orderBy: innerOrderBy,
|
|
330
336
|
fields,
|
|
@@ -341,6 +347,8 @@ class EntityLoader {
|
|
|
341
347
|
refresh: refresh && !filtered.every(item => options.visited.has(item)),
|
|
342
348
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
343
349
|
visited: options.visited,
|
|
350
|
+
// @ts-ignore not a public option
|
|
351
|
+
filtered,
|
|
344
352
|
});
|
|
345
353
|
}
|
|
346
354
|
/** @internal */
|
package/entity/Reference.d.ts
CHANGED
|
@@ -56,6 +56,11 @@ export declare class ScalarReference<Value> {
|
|
|
56
56
|
* Returns either the whole entity, or the requested property.
|
|
57
57
|
*/
|
|
58
58
|
load(options?: Omit<LoadReferenceOptions<any, any>, 'populate' | 'fields' | 'exclude'>): Promise<Value | undefined>;
|
|
59
|
+
/**
|
|
60
|
+
* Ensures the underlying entity is loaded first (without reloading it if it already is loaded).
|
|
61
|
+
* Returns the entity or throws an error just like `em.findOneOrFail()` (and respects the same config options).
|
|
62
|
+
*/
|
|
63
|
+
loadOrFail(options?: Omit<LoadReferenceOrFailOptions<any, any>, 'populate' | 'fields' | 'exclude'>): Promise<Value>;
|
|
59
64
|
set(value: Value): void;
|
|
60
65
|
bind<Entity extends object>(entity: Entity, property: EntityKey<Entity>): void;
|
|
61
66
|
unwrap(): Value | undefined;
|
package/entity/Reference.js
CHANGED
|
@@ -7,6 +7,7 @@ const node_util_1 = require("node:util");
|
|
|
7
7
|
const enums_1 = require("../enums");
|
|
8
8
|
const wrap_1 = require("./wrap");
|
|
9
9
|
const utils_1 = require("../utils");
|
|
10
|
+
const errors_1 = require("../errors");
|
|
10
11
|
class Reference {
|
|
11
12
|
entity;
|
|
12
13
|
constructor(entity) {
|
|
@@ -178,6 +179,21 @@ class ScalarReference {
|
|
|
178
179
|
}
|
|
179
180
|
return this.value;
|
|
180
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Ensures the underlying entity is loaded first (without reloading it if it already is loaded).
|
|
184
|
+
* Returns the entity or throws an error just like `em.findOneOrFail()` (and respects the same config options).
|
|
185
|
+
*/
|
|
186
|
+
async loadOrFail(options = {}) {
|
|
187
|
+
const ret = await this.load(options);
|
|
188
|
+
if (!ret) {
|
|
189
|
+
const wrapped = (0, wrap_1.helper)(this.entity);
|
|
190
|
+
options.failHandler ??= wrapped.__em.config.get('findOneOrFailHandler');
|
|
191
|
+
const entityName = this.entity.constructor.name;
|
|
192
|
+
const where = wrapped.getPrimaryKey();
|
|
193
|
+
throw new errors_1.NotFoundError(`${entityName} (${where}) failed to load property '${this.property}'`);
|
|
194
|
+
}
|
|
195
|
+
return ret;
|
|
196
|
+
}
|
|
181
197
|
set(value) {
|
|
182
198
|
this.value = value;
|
|
183
199
|
this.initialized = true;
|
package/entity/WrappedEntity.js
CHANGED
|
@@ -153,7 +153,7 @@ class WrappedEntity {
|
|
|
153
153
|
return this.__em?.config ?? this.entity.__config;
|
|
154
154
|
}
|
|
155
155
|
get __primaryKeys() {
|
|
156
|
-
return Utils_1.Utils.getPrimaryKeyValues(this.entity, this.__meta
|
|
156
|
+
return Utils_1.Utils.getPrimaryKeyValues(this.entity, this.__meta);
|
|
157
157
|
}
|
|
158
158
|
/** @ignore */
|
|
159
159
|
[node_util_1.inspect.custom]() {
|