@mikro-orm/core 6.4.16-dev.8 → 6.4.16
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 +1 -0
- package/EntityManager.js +2 -1
- package/decorators/Entity.d.ts +1 -0
- package/entity/Collection.js +3 -2
- package/errors.d.ts +1 -0
- package/errors.js +3 -0
- package/metadata/MetadataDiscovery.js +9 -4
- package/package.json +2 -2
- package/typings.d.ts +1 -0
- package/utils/DataloaderUtils.d.ts +6 -1
- package/utils/DataloaderUtils.js +37 -19
package/EntityManager.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
27
27
|
readonly name: string;
|
|
28
28
|
protected readonly refLoader: DataLoader<[Reference<any>, (Omit<import("./entity").LoadReferenceOptions<any, any, "*", never>, "dataloader"> | undefined)?], any, [Reference<any>, (Omit<import("./entity").LoadReferenceOptions<any, any, "*", never>, "dataloader"> | undefined)?]>;
|
|
29
29
|
protected readonly colLoader: DataLoader<[import("./entity").Collection<any, object>, (Omit<import("./entity").InitCollectionOptions<any, any, "*", never>, "dataloader"> | undefined)?], any, [import("./entity").Collection<any, object>, (Omit<import("./entity").InitCollectionOptions<any, any, "*", never>, "dataloader"> | undefined)?]>;
|
|
30
|
+
protected readonly colLoaderMtoN: DataLoader<[import("./entity").Collection<any, object>, (Omit<import("./entity").InitCollectionOptions<any, any, "*", never>, "dataloader"> | undefined)?], any, [import("./entity").Collection<any, object>, (Omit<import("./entity").InitCollectionOptions<any, any, "*", never>, "dataloader"> | undefined)?]>;
|
|
30
31
|
private readonly validator;
|
|
31
32
|
private readonly repositoryMap;
|
|
32
33
|
private readonly entityLoader;
|
package/EntityManager.js
CHANGED
|
@@ -29,6 +29,7 @@ class EntityManager {
|
|
|
29
29
|
name;
|
|
30
30
|
refLoader = new dataloader_1.default(utils_1.DataloaderUtils.getRefBatchLoadFn(this));
|
|
31
31
|
colLoader = new dataloader_1.default(utils_1.DataloaderUtils.getColBatchLoadFn(this));
|
|
32
|
+
colLoaderMtoN = new dataloader_1.default(utils_1.DataloaderUtils.getManyToManyColBatchLoadFn(this));
|
|
32
33
|
validator;
|
|
33
34
|
repositoryMap = {};
|
|
34
35
|
entityLoader;
|
|
@@ -488,7 +489,7 @@ class EntityManager {
|
|
|
488
489
|
flushMode: enums_1.FlushMode.COMMIT,
|
|
489
490
|
});
|
|
490
491
|
if (reloaded) {
|
|
491
|
-
this.config.getHydrator(this.metadata).hydrate(entity, (0, entity_1.helper)(entity).__meta, (0, entity_1.helper)(reloaded).toPOJO(), this.getEntityFactory(), 'full');
|
|
492
|
+
this.config.getHydrator(this.metadata).hydrate(entity, (0, entity_1.helper)(entity).__meta, (0, entity_1.helper)(reloaded).toPOJO(), this.getEntityFactory(), 'full', false, true);
|
|
492
493
|
}
|
|
493
494
|
else {
|
|
494
495
|
this.getUnitOfWork().unsetIdentity(entity);
|
package/decorators/Entity.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export type EntityOptions<T, E = T extends EntityClass<infer P> ? P : T> = {
|
|
|
13
13
|
abstract?: boolean;
|
|
14
14
|
readonly?: boolean;
|
|
15
15
|
virtual?: boolean;
|
|
16
|
+
hasTriggers?: boolean;
|
|
16
17
|
expression?: string | ((em: any, where: ObjectQuery<E>, options: FindOptions<E, any, any, any>) => object);
|
|
17
18
|
repository?: () => Constructor;
|
|
18
19
|
};
|
package/entity/Collection.js
CHANGED
|
@@ -224,8 +224,9 @@ class Collection extends ArrayCollection_1.ArrayCollection {
|
|
|
224
224
|
const order = [...this.items]; // copy order of references
|
|
225
225
|
const orderBy = this.createOrderBy(options.orderBy);
|
|
226
226
|
const customOrder = orderBy.length > 0;
|
|
227
|
-
|
|
228
|
-
const
|
|
227
|
+
const pivotTable = this.property.kind === enums_1.ReferenceKind.MANY_TO_MANY && em.getPlatform().usesPivotTable();
|
|
228
|
+
const loader = pivotTable ? 'colLoaderMtoN' : 'colLoader';
|
|
229
|
+
const items = await em[loader].load([
|
|
229
230
|
this,
|
|
230
231
|
{ ...options, orderBy },
|
|
231
232
|
]);
|
package/errors.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export declare class ValidationError<T extends AnyEntity = AnyEntity> extends Er
|
|
|
24
24
|
static cannotCommit(): ValidationError;
|
|
25
25
|
static cannotUseGlobalContext(): ValidationError;
|
|
26
26
|
static cannotUseOperatorsInsideEmbeddables(className: string, propName: string, payload: unknown): ValidationError;
|
|
27
|
+
static cannotUseGroupOperatorsInsideScalars(className: string, propName: string, payload: unknown): ValidationError;
|
|
27
28
|
static invalidEmbeddableQuery(className: string, propName: string, embeddableType: string): ValidationError;
|
|
28
29
|
}
|
|
29
30
|
export declare class CursorError<T extends AnyEntity = AnyEntity> extends ValidationError<T> {
|
package/errors.js
CHANGED
|
@@ -98,6 +98,9 @@ class ValidationError extends Error {
|
|
|
98
98
|
static cannotUseOperatorsInsideEmbeddables(className, propName, payload) {
|
|
99
99
|
return new ValidationError(`Using operators inside embeddables is not allowed, move the operator above. (property: ${className}.${propName}, payload: ${(0, node_util_1.inspect)(payload)})`);
|
|
100
100
|
}
|
|
101
|
+
static cannotUseGroupOperatorsInsideScalars(className, propName, payload) {
|
|
102
|
+
return new ValidationError(`Using group operators ($and/$or) inside scalar properties is not allowed, move the operator above. (property: ${className}.${propName}, payload: ${(0, node_util_1.inspect)(payload)})`);
|
|
103
|
+
}
|
|
101
104
|
static invalidEmbeddableQuery(className, propName, embeddableType) {
|
|
102
105
|
return new ValidationError(`Invalid query for entity '${className}', property '${propName}' does not exist in embeddable '${embeddableType}'`);
|
|
103
106
|
}
|
|
@@ -1004,7 +1004,7 @@ class MetadataDiscovery {
|
|
|
1004
1004
|
return o;
|
|
1005
1005
|
}, {});
|
|
1006
1006
|
}
|
|
1007
|
-
getDefaultVersionValue(prop) {
|
|
1007
|
+
getDefaultVersionValue(meta, prop) {
|
|
1008
1008
|
if (typeof prop.defaultRaw !== 'undefined') {
|
|
1009
1009
|
return prop.defaultRaw;
|
|
1010
1010
|
}
|
|
@@ -1012,7 +1012,9 @@ class MetadataDiscovery {
|
|
|
1012
1012
|
if (prop.default != null) {
|
|
1013
1013
|
return '' + this.platform.quoteVersionValue(prop.default, prop);
|
|
1014
1014
|
}
|
|
1015
|
-
|
|
1015
|
+
this.initCustomType(meta, prop, true);
|
|
1016
|
+
const type = prop.customType?.runtimeType ?? prop.runtimeType ?? prop.type;
|
|
1017
|
+
if (type === 'Date') {
|
|
1016
1018
|
prop.length ??= this.platform.getDefaultVersionLength();
|
|
1017
1019
|
return this.platform.getCurrentTimestampSQL(prop.length);
|
|
1018
1020
|
}
|
|
@@ -1083,13 +1085,13 @@ class MetadataDiscovery {
|
|
|
1083
1085
|
if (prop.version) {
|
|
1084
1086
|
this.initDefaultValue(prop);
|
|
1085
1087
|
meta.versionProperty = prop.name;
|
|
1086
|
-
prop.defaultRaw = this.getDefaultVersionValue(prop);
|
|
1088
|
+
prop.defaultRaw = this.getDefaultVersionValue(meta, prop);
|
|
1087
1089
|
}
|
|
1088
1090
|
if (prop.concurrencyCheck && !prop.primary) {
|
|
1089
1091
|
meta.concurrencyCheckKeys.add(prop.name);
|
|
1090
1092
|
}
|
|
1091
1093
|
}
|
|
1092
|
-
initCustomType(meta, prop) {
|
|
1094
|
+
initCustomType(meta, prop, simple = false) {
|
|
1093
1095
|
// `prop.type` might be actually instance of custom type class
|
|
1094
1096
|
if (types_1.Type.isMappedType(prop.type) && !prop.customType) {
|
|
1095
1097
|
prop.customType = prop.type;
|
|
@@ -1100,6 +1102,9 @@ class MetadataDiscovery {
|
|
|
1100
1102
|
prop.customType = new prop.type();
|
|
1101
1103
|
prop.type = prop.customType.constructor.name;
|
|
1102
1104
|
}
|
|
1105
|
+
if (simple) {
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1103
1108
|
if (!prop.customType && ['json', 'jsonb'].includes(prop.type?.toLowerCase())) {
|
|
1104
1109
|
prop.customType = new types_1.JsonType();
|
|
1105
1110
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
|
-
"version": "6.4.16
|
|
3
|
+
"version": "6.4.16",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"esprima": "4.0.1",
|
|
65
65
|
"fs-extra": "11.3.0",
|
|
66
66
|
"globby": "11.1.0",
|
|
67
|
-
"mikro-orm": "6.4.16
|
|
67
|
+
"mikro-orm": "6.4.16",
|
|
68
68
|
"reflect-metadata": "0.2.2"
|
|
69
69
|
}
|
|
70
70
|
}
|
package/typings.d.ts
CHANGED
|
@@ -477,6 +477,7 @@ export interface EntityMetadata<T = any> {
|
|
|
477
477
|
polymorphs?: EntityMetadata[];
|
|
478
478
|
root: EntityMetadata<T>;
|
|
479
479
|
definedProperties: Dictionary;
|
|
480
|
+
hasTriggers?: boolean;
|
|
480
481
|
/** @internal can be used for computed numeric cache keys */
|
|
481
482
|
readonly _id: number;
|
|
482
483
|
}
|
|
@@ -35,9 +35,14 @@ export declare class DataloaderUtils {
|
|
|
35
35
|
*/
|
|
36
36
|
static getColFilter<T, S extends T>(collection: Collection<any>): (result: T) => result is S;
|
|
37
37
|
/**
|
|
38
|
-
* Returns the collection dataloader batchLoadFn, which aggregates collections by entity,
|
|
38
|
+
* Returns the 1:M collection dataloader batchLoadFn, which aggregates collections by entity,
|
|
39
39
|
* makes one query per entity and maps each input collection to the corresponding result.
|
|
40
40
|
*/
|
|
41
41
|
static getColBatchLoadFn(em: EntityManager): DataLoader.BatchLoadFn<[Collection<any>, Omit<InitCollectionOptions<any, any>, 'dataloader'>?], any>;
|
|
42
|
+
/**
|
|
43
|
+
* Returns the M:N collection dataloader batchLoadFn, which aggregates collections by entity,
|
|
44
|
+
* makes one query per entity and maps each input collection to the corresponding result.
|
|
45
|
+
*/
|
|
46
|
+
static getManyToManyColBatchLoadFn(em: EntityManager): DataLoader.BatchLoadFn<[Collection<any>, Omit<InitCollectionOptions<any, any>, 'dataloader'>?], any>;
|
|
42
47
|
static getDataloaderType(dataloaderCfg: DataloaderType | boolean): DataloaderType;
|
|
43
48
|
}
|
package/utils/DataloaderUtils.js
CHANGED
|
@@ -156,29 +156,11 @@ class DataloaderUtils {
|
|
|
156
156
|
};
|
|
157
157
|
}
|
|
158
158
|
/**
|
|
159
|
-
* Returns the collection dataloader batchLoadFn, which aggregates collections by entity,
|
|
159
|
+
* Returns the 1:M collection dataloader batchLoadFn, which aggregates collections by entity,
|
|
160
160
|
* makes one query per entity and maps each input collection to the corresponding result.
|
|
161
161
|
*/
|
|
162
162
|
static getColBatchLoadFn(em) {
|
|
163
163
|
return async (collsWithOpts) => {
|
|
164
|
-
const prop = collsWithOpts[0][0].property;
|
|
165
|
-
if (prop.kind === enums_1.ReferenceKind.MANY_TO_MANY && em.getPlatform().usesPivotTable()) {
|
|
166
|
-
const options = {};
|
|
167
|
-
const wrap = (cond) => ({ [prop.name]: cond });
|
|
168
|
-
const orderBy = Utils_1.Utils.asArray(collsWithOpts[0][1]?.orderBy).map(o => wrap(o));
|
|
169
|
-
const populate = wrap(collsWithOpts[0][1]?.populate);
|
|
170
|
-
const owners = collsWithOpts.map(c => c[0].owner);
|
|
171
|
-
const $or = [];
|
|
172
|
-
// a bit of a hack, but we need to prefix the key, since we have only a column name, not a property name
|
|
173
|
-
const alias = em.config.getNamingStrategy().aliasName(prop.pivotEntity, 0);
|
|
174
|
-
const fk = `${alias}.${Utils_1.Utils.getPrimaryKeyHash(prop.joinColumns)}`;
|
|
175
|
-
for (const c of collsWithOpts) {
|
|
176
|
-
$or.push({ $and: [c[1]?.where ?? {}, { [fk]: c[0].owner }] });
|
|
177
|
-
options.refresh ??= c[1]?.refresh;
|
|
178
|
-
}
|
|
179
|
-
options.where = wrap({ $or });
|
|
180
|
-
return em.getEntityLoader().findChildrenFromPivotTable(owners, prop, options, orderBy, populate, collsWithOpts[0][1]?.ref);
|
|
181
|
-
}
|
|
182
164
|
const entitiesAndOptsMap = DataloaderUtils.groupInversedOrMappedKeysByEntityAndOpts(collsWithOpts);
|
|
183
165
|
const promises = DataloaderUtils.entitiesAndOptsMapToQueries(entitiesAndOptsMap, em);
|
|
184
166
|
const resultsMap = new Map(await Promise.all(promises));
|
|
@@ -196,6 +178,42 @@ class DataloaderUtils {
|
|
|
196
178
|
});
|
|
197
179
|
};
|
|
198
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Returns the M:N collection dataloader batchLoadFn, which aggregates collections by entity,
|
|
183
|
+
* makes one query per entity and maps each input collection to the corresponding result.
|
|
184
|
+
*/
|
|
185
|
+
static getManyToManyColBatchLoadFn(em) {
|
|
186
|
+
return async (collsWithOpts) => {
|
|
187
|
+
const groups = new Map();
|
|
188
|
+
for (const [col, opts] of collsWithOpts) {
|
|
189
|
+
const key = `${col.property.targetMeta.className}.${col.property.name}|${JSON.stringify(opts ?? {})}`;
|
|
190
|
+
const value = groups.get(key) ?? [];
|
|
191
|
+
value.push([col, opts ?? {}]);
|
|
192
|
+
groups.set(key, value);
|
|
193
|
+
}
|
|
194
|
+
const ret = [];
|
|
195
|
+
for (const group of groups.values()) {
|
|
196
|
+
const prop = group[0][0].property;
|
|
197
|
+
const options = {};
|
|
198
|
+
const wrap = (cond) => ({ [prop.name]: cond });
|
|
199
|
+
const orderBy = Utils_1.Utils.asArray(group[0][1]?.orderBy).map(o => wrap(o));
|
|
200
|
+
const populate = wrap(group[0][1]?.populate);
|
|
201
|
+
const owners = group.map(c => c[0].owner);
|
|
202
|
+
const $or = [];
|
|
203
|
+
// a bit of a hack, but we need to prefix the key, since we have only a column name, not a property name
|
|
204
|
+
const alias = em.config.getNamingStrategy().aliasName(prop.pivotEntity, 0);
|
|
205
|
+
const fk = `${alias}.${Utils_1.Utils.getPrimaryKeyHash(prop.joinColumns)}`;
|
|
206
|
+
for (const c of group) {
|
|
207
|
+
$or.push({ $and: [c[1]?.where ?? {}, { [fk]: c[0].owner }] });
|
|
208
|
+
options.refresh ??= c[1]?.refresh;
|
|
209
|
+
}
|
|
210
|
+
options.where = wrap({ $or });
|
|
211
|
+
const r = await em.getEntityLoader().findChildrenFromPivotTable(owners, prop, options, orderBy, populate, group[0][1]?.ref);
|
|
212
|
+
ret.push(...r);
|
|
213
|
+
}
|
|
214
|
+
return ret;
|
|
215
|
+
};
|
|
216
|
+
}
|
|
199
217
|
static getDataloaderType(dataloaderCfg) {
|
|
200
218
|
switch (dataloaderCfg) {
|
|
201
219
|
case true:
|