@mikro-orm/core 7.0.0-dev.4 → 7.0.0-dev.40
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 +84 -18
- package/EntityManager.js +265 -172
- package/MikroORM.d.ts +7 -5
- package/MikroORM.js +0 -1
- package/README.md +3 -2
- package/cache/FileCacheAdapter.d.ts +2 -1
- package/cache/FileCacheAdapter.js +6 -4
- package/connections/Connection.d.ts +4 -2
- package/connections/Connection.js +2 -2
- package/decorators/Check.d.ts +2 -2
- package/decorators/Embeddable.d.ts +5 -5
- package/decorators/Embeddable.js +1 -1
- package/decorators/Embedded.d.ts +6 -12
- package/decorators/Entity.d.ts +18 -3
- package/decorators/Enum.d.ts +1 -1
- package/decorators/Formula.d.ts +1 -2
- package/decorators/Indexed.d.ts +2 -2
- package/decorators/ManyToMany.d.ts +4 -2
- package/decorators/ManyToOne.d.ts +6 -2
- package/decorators/OneToMany.d.ts +4 -4
- package/decorators/OneToOne.d.ts +5 -1
- package/decorators/PrimaryKey.d.ts +2 -3
- package/decorators/Property.d.ts +54 -4
- package/decorators/Transactional.d.ts +1 -0
- package/decorators/Transactional.js +3 -3
- package/decorators/index.d.ts +1 -1
- package/drivers/DatabaseDriver.d.ts +4 -3
- package/drivers/IDatabaseDriver.d.ts +22 -2
- package/entity/ArrayCollection.d.ts +4 -2
- package/entity/ArrayCollection.js +18 -6
- package/entity/Collection.d.ts +1 -2
- package/entity/Collection.js +19 -10
- package/entity/EntityAssigner.d.ts +1 -1
- package/entity/EntityAssigner.js +9 -1
- package/entity/EntityFactory.d.ts +7 -0
- package/entity/EntityFactory.js +29 -9
- package/entity/EntityHelper.js +25 -3
- package/entity/EntityLoader.d.ts +5 -4
- package/entity/EntityLoader.js +74 -37
- package/entity/EntityRepository.d.ts +1 -1
- package/entity/EntityValidator.js +1 -1
- package/entity/Reference.d.ts +9 -7
- package/entity/Reference.js +30 -3
- package/entity/WrappedEntity.js +1 -1
- package/entity/defineEntity.d.ts +561 -0
- package/entity/defineEntity.js +537 -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 +15 -3
- package/enums.d.ts +16 -3
- package/enums.js +13 -0
- package/errors.d.ts +6 -0
- package/errors.js +14 -0
- package/events/EventSubscriber.d.ts +3 -1
- package/hydration/ObjectHydrator.d.ts +4 -4
- package/hydration/ObjectHydrator.js +35 -24
- package/index.d.ts +2 -1
- package/index.js +1 -1
- package/logging/DefaultLogger.d.ts +1 -1
- package/logging/SimpleLogger.d.ts +1 -1
- package/metadata/EntitySchema.d.ts +8 -4
- package/metadata/EntitySchema.js +39 -19
- package/metadata/MetadataDiscovery.d.ts +1 -1
- package/metadata/MetadataDiscovery.js +88 -32
- package/metadata/MetadataStorage.js +1 -1
- package/metadata/MetadataValidator.js +4 -3
- package/naming-strategy/AbstractNamingStrategy.d.ts +5 -1
- package/naming-strategy/AbstractNamingStrategy.js +7 -1
- package/naming-strategy/NamingStrategy.d.ts +11 -1
- package/package.json +5 -5
- package/platforms/Platform.d.ts +5 -3
- package/platforms/Platform.js +4 -8
- package/serialization/EntitySerializer.d.ts +2 -0
- package/serialization/EntitySerializer.js +2 -2
- package/serialization/EntityTransformer.js +1 -1
- package/serialization/SerializationContext.js +14 -11
- package/types/BigIntType.d.ts +9 -6
- package/types/BigIntType.js +3 -0
- package/types/BooleanType.d.ts +1 -1
- package/types/DecimalType.d.ts +6 -4
- package/types/DecimalType.js +1 -1
- package/types/DoubleType.js +1 -1
- package/types/JsonType.d.ts +1 -1
- package/types/JsonType.js +7 -2
- package/types/Type.d.ts +2 -1
- package/types/Type.js +1 -1
- package/types/index.d.ts +1 -1
- package/typings.d.ts +88 -39
- package/typings.js +24 -4
- package/unit-of-work/ChangeSetComputer.js +3 -1
- package/unit-of-work/ChangeSetPersister.d.ts +4 -2
- package/unit-of-work/ChangeSetPersister.js +37 -16
- package/unit-of-work/UnitOfWork.d.ts +8 -1
- package/unit-of-work/UnitOfWork.js +109 -41
- package/utils/Configuration.d.ts +23 -5
- package/utils/Configuration.js +17 -3
- package/utils/ConfigurationLoader.d.ts +0 -2
- package/utils/ConfigurationLoader.js +2 -24
- package/utils/Cursor.d.ts +3 -3
- package/utils/Cursor.js +3 -0
- package/utils/DataloaderUtils.d.ts +7 -2
- package/utils/DataloaderUtils.js +38 -7
- package/utils/EntityComparator.d.ts +6 -2
- package/utils/EntityComparator.js +104 -58
- package/utils/QueryHelper.d.ts +9 -1
- package/utils/QueryHelper.js +66 -5
- package/utils/RawQueryFragment.d.ts +36 -2
- package/utils/RawQueryFragment.js +35 -1
- package/utils/TransactionManager.d.ts +65 -0
- package/utils/TransactionManager.js +218 -0
- package/utils/Utils.d.ts +11 -5
- package/utils/Utils.js +76 -33
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/upsert-utils.d.ts +7 -2
- package/utils/upsert-utils.js +52 -1
|
@@ -28,6 +28,12 @@ export declare class UnitOfWork {
|
|
|
28
28
|
private working;
|
|
29
29
|
constructor(em: EntityManager);
|
|
30
30
|
merge<T extends object>(entity: T, visited?: Set<AnyEntity>): void;
|
|
31
|
+
/**
|
|
32
|
+
* Entity data can wary in its shape, e.g. we might get a deep relation graph with joined strategy, but for diffing,
|
|
33
|
+
* we need to normalize the shape, so relation values are only raw FKs. This method handles that.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
normalizeEntityData<T extends object>(meta: EntityMetadata<T>, data: EntityData<T>): void;
|
|
31
37
|
/**
|
|
32
38
|
* @internal
|
|
33
39
|
*/
|
|
@@ -39,7 +45,7 @@ export declare class UnitOfWork {
|
|
|
39
45
|
/**
|
|
40
46
|
* Returns entity from the identity map. For composite keys, you need to pass an array of PKs in the same order as they are defined in `meta.primaryKeys`.
|
|
41
47
|
*/
|
|
42
|
-
getById<T extends object>(entityName: string, id: Primary<T> | Primary<T>[], schema?: string): T | undefined;
|
|
48
|
+
getById<T extends object>(entityName: string, id: Primary<T> | Primary<T>[], schema?: string, convertCustomTypes?: boolean): T | undefined;
|
|
43
49
|
tryGetById<T extends object>(entityName: string, where: FilterQuery<T>, schema?: string, strict?: boolean): T | null;
|
|
44
50
|
/**
|
|
45
51
|
* Returns map of all managed entities.
|
|
@@ -103,6 +109,7 @@ export declare class UnitOfWork {
|
|
|
103
109
|
private commitDeleteChangeSets;
|
|
104
110
|
private commitExtraUpdates;
|
|
105
111
|
private commitCollectionUpdates;
|
|
112
|
+
private filterCollectionUpdates;
|
|
106
113
|
/**
|
|
107
114
|
* Orders change sets so FK constrains are maintained, ensures stable order (needed for node < 11)
|
|
108
115
|
*/
|
|
@@ -43,7 +43,7 @@ export class UnitOfWork {
|
|
|
43
43
|
this.eventManager = this.em.getEventManager();
|
|
44
44
|
this.comparator = this.em.getComparator();
|
|
45
45
|
this.changeSetComputer = new ChangeSetComputer(this.em.getValidator(), this.collectionUpdates, this.metadata, this.platform, this.em.config, this.em);
|
|
46
|
-
this.changeSetPersister = new ChangeSetPersister(this.em.getDriver(), this.metadata, this.em.config.getHydrator(this.metadata), this.em.getEntityFactory(), this.em.getValidator(), this.em.config);
|
|
46
|
+
this.changeSetPersister = new ChangeSetPersister(this.em.getDriver(), this.metadata, this.em.config.getHydrator(this.metadata), this.em.getEntityFactory(), this.em.getValidator(), this.em.config, this.em);
|
|
47
47
|
}
|
|
48
48
|
merge(entity, visited) {
|
|
49
49
|
const wrapped = helper(entity);
|
|
@@ -65,6 +65,40 @@ export class UnitOfWork {
|
|
|
65
65
|
}
|
|
66
66
|
this.cascade(entity, Cascade.MERGE, visited ?? new Set());
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Entity data can wary in its shape, e.g. we might get a deep relation graph with joined strategy, but for diffing,
|
|
70
|
+
* we need to normalize the shape, so relation values are only raw FKs. This method handles that.
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
73
|
+
normalizeEntityData(meta, data) {
|
|
74
|
+
const forceUndefined = this.em.config.get('forceUndefined');
|
|
75
|
+
for (const key of Utils.keys(data)) {
|
|
76
|
+
const prop = meta.properties[key];
|
|
77
|
+
if (!prop) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(data[prop.name])) {
|
|
81
|
+
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
82
|
+
}
|
|
83
|
+
else if (prop.kind === ReferenceKind.EMBEDDED && !prop.object && Utils.isPlainObject(data[prop.name])) {
|
|
84
|
+
for (const p of prop.targetMeta.props) {
|
|
85
|
+
/* v8 ignore next */
|
|
86
|
+
const prefix = prop.prefix === false ? '' : prop.prefix === true ? prop.name + '_' : prop.prefix;
|
|
87
|
+
data[prefix + p.name] = data[prop.name][p.name];
|
|
88
|
+
}
|
|
89
|
+
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
90
|
+
}
|
|
91
|
+
if (prop.hydrate === false && prop.customType?.ensureComparable(meta, prop)) {
|
|
92
|
+
const converted = prop.customType.convertToJSValue(data[key], this.platform, { key, mode: 'hydration', force: true });
|
|
93
|
+
data[key] = prop.customType.convertToDatabaseValue(converted, this.platform, { key, mode: 'hydration' });
|
|
94
|
+
}
|
|
95
|
+
if (forceUndefined) {
|
|
96
|
+
if (data[key] === null) {
|
|
97
|
+
data[key] = undefined;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
68
102
|
/**
|
|
69
103
|
* @internal
|
|
70
104
|
*/
|
|
@@ -82,27 +116,11 @@ export class UnitOfWork {
|
|
|
82
116
|
wrapped.__em ??= this.em;
|
|
83
117
|
wrapped.__managed = true;
|
|
84
118
|
if (data && (options?.refresh || !wrapped.__originalEntityData)) {
|
|
119
|
+
this.normalizeEntityData(wrapped.__meta, data);
|
|
85
120
|
for (const key of Utils.keys(data)) {
|
|
86
121
|
const prop = wrapped.__meta.properties[key];
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
wrapped.__loadedProperties.add(key);
|
|
91
|
-
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(data[prop.name])) {
|
|
92
|
-
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta.primaryKeys, true);
|
|
93
|
-
}
|
|
94
|
-
else if (prop.kind === ReferenceKind.EMBEDDED && !prop.object && Utils.isPlainObject(data[prop.name])) {
|
|
95
|
-
for (const p of prop.targetMeta.props) {
|
|
96
|
-
/* v8 ignore next */
|
|
97
|
-
const prefix = prop.prefix === false ? '' : prop.prefix === true ? prop.name + '_' : prop.prefix;
|
|
98
|
-
data[prefix + p.name] = data[prop.name][p.name];
|
|
99
|
-
}
|
|
100
|
-
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta.primaryKeys, true);
|
|
101
|
-
}
|
|
102
|
-
if (forceUndefined) {
|
|
103
|
-
if (data[key] === null) {
|
|
104
|
-
data[key] = undefined;
|
|
105
|
-
}
|
|
122
|
+
if (prop) {
|
|
123
|
+
wrapped.__loadedProperties.add(key);
|
|
106
124
|
}
|
|
107
125
|
}
|
|
108
126
|
wrapped.__originalEntityData = data;
|
|
@@ -125,7 +143,7 @@ export class UnitOfWork {
|
|
|
125
143
|
/**
|
|
126
144
|
* Returns entity from the identity map. For composite keys, you need to pass an array of PKs in the same order as they are defined in `meta.primaryKeys`.
|
|
127
145
|
*/
|
|
128
|
-
getById(entityName, id, schema) {
|
|
146
|
+
getById(entityName, id, schema, convertCustomTypes) {
|
|
129
147
|
if (id == null || (Array.isArray(id) && id.length === 0)) {
|
|
130
148
|
return undefined;
|
|
131
149
|
}
|
|
@@ -135,7 +153,16 @@ export class UnitOfWork {
|
|
|
135
153
|
hash = '' + id;
|
|
136
154
|
}
|
|
137
155
|
else {
|
|
138
|
-
|
|
156
|
+
let keys = Array.isArray(id) ? Utils.flatten(id) : [id];
|
|
157
|
+
keys = meta.getPrimaryProps(true).map((p, i) => {
|
|
158
|
+
if (!convertCustomTypes && p.customType) {
|
|
159
|
+
return p.customType.convertToDatabaseValue(keys[i], this.platform, {
|
|
160
|
+
key: p.name,
|
|
161
|
+
mode: 'hydration',
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
return keys[i];
|
|
165
|
+
});
|
|
139
166
|
hash = Utils.getPrimaryKeyHash(keys);
|
|
140
167
|
}
|
|
141
168
|
schema ??= meta.schema ?? this.em.config.getSchema();
|
|
@@ -185,6 +212,9 @@ export class UnitOfWork {
|
|
|
185
212
|
if (this.queuedActions.has(meta.className) || this.queuedActions.has(meta.root.className)) {
|
|
186
213
|
return true;
|
|
187
214
|
}
|
|
215
|
+
if (meta.discriminatorMap && Object.values(meta.discriminatorMap).some(v => this.queuedActions.has(v))) {
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
188
218
|
for (const entity of this.identityMap.getStore(meta).values()) {
|
|
189
219
|
if (helper(entity).__initialized && helper(entity).isTouched()) {
|
|
190
220
|
return true;
|
|
@@ -303,6 +333,7 @@ export class UnitOfWork {
|
|
|
303
333
|
cs.entity.__helper.__processing = true;
|
|
304
334
|
}
|
|
305
335
|
await this.eventManager.dispatchEvent(EventType.onFlush, { em: this.em, uow: this });
|
|
336
|
+
this.filterCollectionUpdates();
|
|
306
337
|
// nothing to do, do not start transaction
|
|
307
338
|
if (this.changeSets.size === 0 && this.collectionUpdates.size === 0 && this.extraUpdates.size === 0) {
|
|
308
339
|
return void (await this.eventManager.dispatchEvent(EventType.afterFlush, { em: this.em, uow: this }));
|
|
@@ -311,9 +342,11 @@ export class UnitOfWork {
|
|
|
311
342
|
const platform = this.em.getPlatform();
|
|
312
343
|
const runInTransaction = !this.em.isInTransaction() && platform.supportsTransactions() && this.em.config.get('implicitTransactions');
|
|
313
344
|
if (runInTransaction) {
|
|
345
|
+
const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
|
|
314
346
|
await this.em.getConnection('write').transactional(trx => this.persistToDatabase(groups, trx), {
|
|
315
347
|
ctx: oldTx,
|
|
316
348
|
eventBroadcaster: new TransactionEventBroadcaster(this.em),
|
|
349
|
+
loggerContext,
|
|
317
350
|
});
|
|
318
351
|
}
|
|
319
352
|
else {
|
|
@@ -542,13 +575,22 @@ export class UnitOfWork {
|
|
|
542
575
|
if (!wrapped || wrapped.__identifier || wrapped.hasPrimaryKey()) {
|
|
543
576
|
return;
|
|
544
577
|
}
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
578
|
+
const pks = wrapped.__meta.getPrimaryProps();
|
|
579
|
+
const idents = [];
|
|
580
|
+
for (const pk of pks) {
|
|
581
|
+
if (pk.kind === ReferenceKind.SCALAR) {
|
|
582
|
+
idents.push(new EntityIdentifier(entity[pk.name]));
|
|
583
|
+
}
|
|
584
|
+
else if (entity[pk.name]) {
|
|
585
|
+
this.initIdentifier(entity[pk.name]);
|
|
586
|
+
idents.push(helper(entity[pk.name])?.__identifier);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
if (pks.length === 1) {
|
|
590
|
+
wrapped.__identifier = idents[0];
|
|
548
591
|
}
|
|
549
|
-
else
|
|
550
|
-
|
|
551
|
-
wrapped.__identifier = helper(entity[pk.name])?.__identifier;
|
|
592
|
+
else {
|
|
593
|
+
wrapped.__identifier = idents;
|
|
552
594
|
}
|
|
553
595
|
}
|
|
554
596
|
processReference(parent, prop, kind, visited, processed, idx) {
|
|
@@ -600,8 +642,15 @@ export class UnitOfWork {
|
|
|
600
642
|
const diff = this.comparator.diffEntities(changeSet.name, copy, current);
|
|
601
643
|
Object.assign(changeSet.payload, diff);
|
|
602
644
|
const wrapped = helper(changeSet.entity);
|
|
603
|
-
if (wrapped.__identifier
|
|
604
|
-
|
|
645
|
+
if (wrapped.__identifier) {
|
|
646
|
+
const idents = Utils.asArray(wrapped.__identifier);
|
|
647
|
+
let i = 0;
|
|
648
|
+
for (const pk of wrapped.__meta.primaryKeys) {
|
|
649
|
+
if (diff[pk]) {
|
|
650
|
+
idents[i].setValue(diff[pk]);
|
|
651
|
+
}
|
|
652
|
+
i++;
|
|
653
|
+
}
|
|
605
654
|
}
|
|
606
655
|
}
|
|
607
656
|
postCommitCleanup() {
|
|
@@ -825,9 +874,17 @@ export class UnitOfWork {
|
|
|
825
874
|
}
|
|
826
875
|
await this.changeSetPersister.executeUpdates(changeSets, batched, { ctx });
|
|
827
876
|
for (const changeSet of changeSets) {
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
877
|
+
const wrapped = helper(changeSet.entity);
|
|
878
|
+
wrapped.__originalEntityData = this.comparator.prepareEntity(changeSet.entity);
|
|
879
|
+
wrapped.__touched = false;
|
|
880
|
+
if (!wrapped.__initialized) {
|
|
881
|
+
for (const prop of changeSet.meta.relations) {
|
|
882
|
+
if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) && changeSet.entity[prop.name] == null) {
|
|
883
|
+
changeSet.entity[prop.name] = Collection.create(changeSet.entity, prop.name, undefined, wrapped.isInitialized());
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
wrapped.__initialized = true;
|
|
887
|
+
}
|
|
831
888
|
await this.runHooks(EventType.afterUpdate, changeSet);
|
|
832
889
|
}
|
|
833
890
|
}
|
|
@@ -870,23 +927,34 @@ export class UnitOfWork {
|
|
|
870
927
|
}
|
|
871
928
|
}
|
|
872
929
|
async commitCollectionUpdates(ctx) {
|
|
873
|
-
|
|
930
|
+
this.filterCollectionUpdates();
|
|
931
|
+
const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
|
|
932
|
+
await this.em.getDriver().syncCollections(this.collectionUpdates, {
|
|
933
|
+
ctx,
|
|
934
|
+
schema: this.em.schema,
|
|
935
|
+
loggerContext,
|
|
936
|
+
});
|
|
937
|
+
for (const coll of this.collectionUpdates) {
|
|
938
|
+
coll.takeSnapshot();
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
filterCollectionUpdates() {
|
|
874
942
|
for (const coll of this.collectionUpdates) {
|
|
943
|
+
let skip = true;
|
|
875
944
|
if (coll.property.owner || coll.getItems(false).filter(item => !item.__helper.__initialized).length > 0) {
|
|
876
945
|
if (this.platform.usesPivotTable()) {
|
|
877
|
-
|
|
946
|
+
skip = false;
|
|
878
947
|
}
|
|
879
948
|
}
|
|
880
949
|
else if (coll.property.kind === ReferenceKind.ONE_TO_MANY && coll.getSnapshot() === undefined) {
|
|
881
|
-
|
|
950
|
+
skip = false;
|
|
882
951
|
}
|
|
883
952
|
else if (coll.property.kind === ReferenceKind.MANY_TO_MANY && !coll.property.owner) {
|
|
884
|
-
|
|
953
|
+
skip = false;
|
|
954
|
+
}
|
|
955
|
+
if (skip) {
|
|
956
|
+
this.collectionUpdates.delete(coll);
|
|
885
957
|
}
|
|
886
|
-
}
|
|
887
|
-
await this.em.getDriver().syncCollections(collectionUpdates, { ctx, schema: this.em.schema });
|
|
888
|
-
for (const coll of this.collectionUpdates) {
|
|
889
|
-
coll.takeSnapshot();
|
|
890
958
|
}
|
|
891
959
|
}
|
|
892
960
|
/**
|
package/utils/Configuration.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
54
54
|
baseDir: string;
|
|
55
55
|
hydrator: typeof ObjectHydrator;
|
|
56
56
|
flushMode: FlushMode.AUTO;
|
|
57
|
-
loadStrategy: LoadStrategy.
|
|
57
|
+
loadStrategy: LoadStrategy.BALANCED;
|
|
58
58
|
dataloader: DataloaderType.NONE;
|
|
59
59
|
populateWhere: PopulateHint.ALL;
|
|
60
60
|
connect: true;
|
|
@@ -62,6 +62,7 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
62
62
|
onQuery: (sql: string) => string;
|
|
63
63
|
autoJoinOneToOneOwner: true;
|
|
64
64
|
autoJoinRefsForFilters: true;
|
|
65
|
+
filtersOnRelations: true;
|
|
65
66
|
propagationOnPrototype: true;
|
|
66
67
|
populateAfterFlush: true;
|
|
67
68
|
serialization: {
|
|
@@ -78,9 +79,11 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
78
79
|
upsertManaged: true;
|
|
79
80
|
forceEntityConstructor: false;
|
|
80
81
|
forceUndefined: false;
|
|
82
|
+
processOnCreateHooksEarly: false;
|
|
81
83
|
ensureDatabase: true;
|
|
82
84
|
ensureIndexes: false;
|
|
83
85
|
batchSize: number;
|
|
86
|
+
hashAlgorithm: "md5";
|
|
84
87
|
debug: false;
|
|
85
88
|
ignoreDeprecations: false;
|
|
86
89
|
verbose: false;
|
|
@@ -103,9 +106,11 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
103
106
|
disableForeignKeys: false;
|
|
104
107
|
createForeignKeyConstraints: true;
|
|
105
108
|
ignoreSchema: never[];
|
|
109
|
+
skipTables: never[];
|
|
110
|
+
skipColumns: {};
|
|
106
111
|
};
|
|
107
112
|
embeddables: {
|
|
108
|
-
prefixMode: "
|
|
113
|
+
prefixMode: "relative";
|
|
109
114
|
};
|
|
110
115
|
entityGenerator: {
|
|
111
116
|
forceUndefined: true;
|
|
@@ -114,6 +119,8 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
114
119
|
identifiedReferences: false;
|
|
115
120
|
scalarTypeInDecorator: false;
|
|
116
121
|
scalarPropertiesForRelations: "never";
|
|
122
|
+
entityDefinition: "decorators";
|
|
123
|
+
enumMode: "ts-enum";
|
|
117
124
|
fileName: (className: string) => string;
|
|
118
125
|
onlyPurePivotTables: false;
|
|
119
126
|
outputPurePivotTables: false;
|
|
@@ -232,7 +239,7 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
232
239
|
/**
|
|
233
240
|
* Type helper to make it easier to use `mikro-orm.config.js`.
|
|
234
241
|
*/
|
|
235
|
-
export declare function defineConfig<D extends IDatabaseDriver>(options: Options<D>): Options<D, D[typeof EntityManagerType] & EntityManager<IDatabaseDriver<import("../index.js").Connection
|
|
242
|
+
export declare function defineConfig<D extends IDatabaseDriver>(options: Options<D>): Options<D, D[typeof EntityManagerType] & EntityManager<IDatabaseDriver<import("../index.js").Connection>>, (string | EntityClass<Partial<any>> | EntityClassGroup<Partial<any>> | EntitySchema<any, never>)[]>;
|
|
236
243
|
export interface ConnectionOptions {
|
|
237
244
|
dbName?: string;
|
|
238
245
|
schema?: string;
|
|
@@ -320,6 +327,7 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
320
327
|
onQuery: (sql: string, params: readonly unknown[]) => string;
|
|
321
328
|
autoJoinOneToOneOwner: boolean;
|
|
322
329
|
autoJoinRefsForFilters: boolean;
|
|
330
|
+
filtersOnRelations: boolean;
|
|
323
331
|
propagationOnPrototype: boolean;
|
|
324
332
|
populateAfterFlush: boolean;
|
|
325
333
|
serialization: {
|
|
@@ -332,6 +340,11 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
332
340
|
upsertManaged: boolean;
|
|
333
341
|
forceEntityConstructor: boolean | (Constructor<AnyEntity> | string)[];
|
|
334
342
|
forceUndefined: boolean;
|
|
343
|
+
/**
|
|
344
|
+
* Property `onCreate` hooks are normally executed during `flush` operation.
|
|
345
|
+
* With this option, they will be processed early inside `em.create()` method.
|
|
346
|
+
*/
|
|
347
|
+
processOnCreateHooksEarly: boolean;
|
|
335
348
|
forceUtcTimezone?: boolean;
|
|
336
349
|
timezone?: string;
|
|
337
350
|
ensureDatabase: boolean | EnsureDatabaseOptions;
|
|
@@ -340,7 +353,7 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
340
353
|
useBatchUpdates?: boolean;
|
|
341
354
|
batchSize: number;
|
|
342
355
|
hydrator: HydratorConstructor;
|
|
343
|
-
loadStrategy: LoadStrategy |
|
|
356
|
+
loadStrategy: LoadStrategy | `${LoadStrategy}`;
|
|
344
357
|
dataloader: DataloaderType | boolean;
|
|
345
358
|
populateWhere?: PopulateHint | `${PopulateHint}`;
|
|
346
359
|
flushMode: FlushMode | 'commit' | 'auto' | 'always';
|
|
@@ -374,6 +387,8 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
374
387
|
disableForeignKeys?: boolean;
|
|
375
388
|
createForeignKeyConstraints?: boolean;
|
|
376
389
|
ignoreSchema?: string[];
|
|
390
|
+
skipTables?: (string | RegExp)[];
|
|
391
|
+
skipColumns?: Dictionary<(string | RegExp)[]>;
|
|
377
392
|
managementDbName?: string;
|
|
378
393
|
};
|
|
379
394
|
embeddables: {
|
|
@@ -403,5 +418,8 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
403
418
|
seeder: SeederOptions;
|
|
404
419
|
preferReadReplicas: boolean;
|
|
405
420
|
dynamicImportProvider: (id: string) => Promise<unknown>;
|
|
421
|
+
hashAlgorithm: 'md5' | 'sha256';
|
|
422
|
+
}
|
|
423
|
+
export interface Options<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager = D[typeof EntityManagerType] & EntityManager, Entities extends (string | EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[]> extends Pick<MikroORMOptions<D, EM>, Exclude<keyof MikroORMOptions, keyof typeof Configuration.DEFAULTS>>, Partial<MikroORMOptions<D, EM>> {
|
|
424
|
+
entities?: Entities;
|
|
406
425
|
}
|
|
407
|
-
export type Options<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager = D[typeof EntityManagerType] & EntityManager> = Pick<MikroORMOptions<D, EM>, Exclude<keyof MikroORMOptions<D, EM>, keyof typeof Configuration.DEFAULTS>> & Partial<MikroORMOptions<D, EM>>;
|
package/utils/Configuration.js
CHANGED
|
@@ -44,7 +44,7 @@ export class Configuration {
|
|
|
44
44
|
baseDir: process.cwd(),
|
|
45
45
|
hydrator: ObjectHydrator,
|
|
46
46
|
flushMode: FlushMode.AUTO,
|
|
47
|
-
loadStrategy: LoadStrategy.
|
|
47
|
+
loadStrategy: LoadStrategy.BALANCED,
|
|
48
48
|
dataloader: DataloaderType.NONE,
|
|
49
49
|
populateWhere: PopulateHint.ALL,
|
|
50
50
|
connect: true,
|
|
@@ -52,6 +52,7 @@ export class Configuration {
|
|
|
52
52
|
onQuery: sql => sql,
|
|
53
53
|
autoJoinOneToOneOwner: true,
|
|
54
54
|
autoJoinRefsForFilters: true,
|
|
55
|
+
filtersOnRelations: true,
|
|
55
56
|
propagationOnPrototype: true,
|
|
56
57
|
populateAfterFlush: true,
|
|
57
58
|
serialization: {
|
|
@@ -68,9 +69,11 @@ export class Configuration {
|
|
|
68
69
|
upsertManaged: true,
|
|
69
70
|
forceEntityConstructor: false,
|
|
70
71
|
forceUndefined: false,
|
|
72
|
+
processOnCreateHooksEarly: false,
|
|
71
73
|
ensureDatabase: true,
|
|
72
74
|
ensureIndexes: false,
|
|
73
75
|
batchSize: 300,
|
|
76
|
+
hashAlgorithm: 'md5',
|
|
74
77
|
debug: false,
|
|
75
78
|
ignoreDeprecations: false,
|
|
76
79
|
verbose: false,
|
|
@@ -93,9 +96,11 @@ export class Configuration {
|
|
|
93
96
|
disableForeignKeys: false,
|
|
94
97
|
createForeignKeyConstraints: true,
|
|
95
98
|
ignoreSchema: [],
|
|
99
|
+
skipTables: [],
|
|
100
|
+
skipColumns: {},
|
|
96
101
|
},
|
|
97
102
|
embeddables: {
|
|
98
|
-
prefixMode: '
|
|
103
|
+
prefixMode: 'relative',
|
|
99
104
|
},
|
|
100
105
|
entityGenerator: {
|
|
101
106
|
forceUndefined: true,
|
|
@@ -104,6 +109,8 @@ export class Configuration {
|
|
|
104
109
|
identifiedReferences: false,
|
|
105
110
|
scalarTypeInDecorator: false,
|
|
106
111
|
scalarPropertiesForRelations: 'never',
|
|
112
|
+
entityDefinition: 'decorators',
|
|
113
|
+
enumMode: 'ts-enum',
|
|
107
114
|
fileName: (className) => className,
|
|
108
115
|
onlyPurePivotTables: false,
|
|
109
116
|
outputPurePivotTables: false,
|
|
@@ -268,7 +275,7 @@ export class Configuration {
|
|
|
268
275
|
* Gets instance of metadata CacheAdapter. (cached)
|
|
269
276
|
*/
|
|
270
277
|
getMetadataCacheAdapter() {
|
|
271
|
-
return this.getCachedService(this.options.metadataCache.adapter, this.options.metadataCache.options, this.options.baseDir, this.options.metadataCache.pretty);
|
|
278
|
+
return this.getCachedService(this.options.metadataCache.adapter, this.options.metadataCache.options, this.options.baseDir, this.options.metadataCache.pretty, this.options.hashAlgorithm);
|
|
272
279
|
}
|
|
273
280
|
/**
|
|
274
281
|
* Gets instance of CacheAdapter for result cache. (cached)
|
|
@@ -338,6 +345,9 @@ export class Configuration {
|
|
|
338
345
|
Object.keys(this.options.filters).forEach(key => {
|
|
339
346
|
this.options.filters[key].default ??= true;
|
|
340
347
|
});
|
|
348
|
+
if (!this.options.filtersOnRelations) {
|
|
349
|
+
this.options.autoJoinRefsForFilters ??= false;
|
|
350
|
+
}
|
|
341
351
|
this.options.subscribers = Utils.unique(this.options.subscribers).map(subscriber => {
|
|
342
352
|
return subscriber.constructor.name === 'Function' ? new subscriber() : subscriber;
|
|
343
353
|
});
|
|
@@ -348,6 +358,10 @@ export class Configuration {
|
|
|
348
358
|
}
|
|
349
359
|
sync() {
|
|
350
360
|
process.env.MIKRO_ORM_COLORS = '' + this.options.colors;
|
|
361
|
+
// FIXME remove `entityGenerator.entitySchema` option
|
|
362
|
+
if (this.options.entityGenerator.entitySchema) {
|
|
363
|
+
this.options.entityGenerator.entityDefinition = 'entitySchema';
|
|
364
|
+
}
|
|
351
365
|
this.logger.setDebugMode(this.options.debug);
|
|
352
366
|
}
|
|
353
367
|
/**
|
|
@@ -40,8 +40,6 @@ export declare class ConfigurationLoader {
|
|
|
40
40
|
static loadEnvironmentVars<D extends IDatabaseDriver>(): Promise<Partial<Options<D>>>;
|
|
41
41
|
static loadEnvironmentVarsSync<D extends IDatabaseDriver>(): Partial<Options<D>>;
|
|
42
42
|
static getORMPackages(): Set<string>;
|
|
43
|
-
/** @internal */
|
|
44
|
-
static commonJSCompat(options: Partial<Options>): void;
|
|
45
43
|
static getORMPackageVersion(name: string): string | undefined;
|
|
46
44
|
static checkPackageVersion(): string;
|
|
47
45
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import dotenv from 'dotenv';
|
|
2
2
|
import { realpathSync } from 'node:fs';
|
|
3
|
-
import { platform } from 'node:os';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
3
|
import { colors } from '../logging/colors.js';
|
|
6
4
|
import { Configuration } from './Configuration.js';
|
|
7
5
|
import { Utils } from './Utils.js';
|
|
@@ -12,7 +10,6 @@ export class ConfigurationLoader {
|
|
|
12
10
|
static async getConfiguration(contextName = 'default', paths = ConfigurationLoader.getConfigPaths(), options = {}) {
|
|
13
11
|
// Backwards compatibility layer
|
|
14
12
|
if (typeof contextName === 'boolean' || !Array.isArray(paths)) {
|
|
15
|
-
this.commonJSCompat(options);
|
|
16
13
|
this.registerDotenv(options);
|
|
17
14
|
const configPathFromArg = ConfigurationLoader.configPathsFromArg();
|
|
18
15
|
const configPaths = configPathFromArg ?? (Array.isArray(paths) ? paths : ConfigurationLoader.getConfigPaths());
|
|
@@ -192,7 +189,7 @@ export class ConfigurationLoader {
|
|
|
192
189
|
static registerDotenv(options) {
|
|
193
190
|
const path = process.env.MIKRO_ORM_ENV ?? ((options?.baseDir ?? process.cwd()) + '/.env');
|
|
194
191
|
const env = {};
|
|
195
|
-
dotenv.config({ path, processEnv: env });
|
|
192
|
+
dotenv.config({ path, processEnv: env, quiet: true });
|
|
196
193
|
// only propagate known env vars
|
|
197
194
|
for (const key of Object.keys(env)) {
|
|
198
195
|
if (key.startsWith('MIKRO_ORM_')) {
|
|
@@ -300,25 +297,6 @@ export class ConfigurationLoader {
|
|
|
300
297
|
...Object.keys(pkg.devDependencies ?? {}),
|
|
301
298
|
]);
|
|
302
299
|
}
|
|
303
|
-
/** @internal */
|
|
304
|
-
static commonJSCompat(options) {
|
|
305
|
-
if (this.isESM()) {
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
/* v8 ignore next 11 */
|
|
309
|
-
options.dynamicImportProvider ??= id => {
|
|
310
|
-
if (platform() === 'win32') {
|
|
311
|
-
try {
|
|
312
|
-
id = fileURLToPath(id);
|
|
313
|
-
}
|
|
314
|
-
catch {
|
|
315
|
-
// ignore
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
return Utils.requireFrom(id);
|
|
319
|
-
};
|
|
320
|
-
Utils.setDynamicImportProvider(options.dynamicImportProvider);
|
|
321
|
-
}
|
|
322
300
|
static getORMPackageVersion(name) {
|
|
323
301
|
try {
|
|
324
302
|
const pkg = Utils.requireFrom(`${name}/package.json`);
|
|
@@ -332,7 +310,7 @@ export class ConfigurationLoader {
|
|
|
332
310
|
// inspired by https://github.com/facebook/docusaurus/pull/3386
|
|
333
311
|
static checkPackageVersion() {
|
|
334
312
|
const coreVersion = Utils.getORMVersion();
|
|
335
|
-
if (process.env.MIKRO_ORM_ALLOW_VERSION_MISMATCH) {
|
|
313
|
+
if (process.env.MIKRO_ORM_ALLOW_VERSION_MISMATCH || coreVersion === 'N/A') {
|
|
336
314
|
return coreVersion;
|
|
337
315
|
}
|
|
338
316
|
const deps = this.getORMPackages();
|
package/utils/Cursor.d.ts
CHANGED
|
@@ -49,13 +49,13 @@ import { type QueryOrder } from '../enums.js';
|
|
|
49
49
|
* }
|
|
50
50
|
* ```
|
|
51
51
|
*/
|
|
52
|
-
export declare class Cursor<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never> {
|
|
52
|
+
export declare class Cursor<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never, IncludeCount extends boolean = true> {
|
|
53
53
|
readonly items: Loaded<Entity, Hint, Fields, Excludes>[];
|
|
54
|
-
readonly totalCount: number;
|
|
54
|
+
readonly totalCount: IncludeCount extends true ? number : undefined;
|
|
55
55
|
readonly hasPrevPage: boolean;
|
|
56
56
|
readonly hasNextPage: boolean;
|
|
57
57
|
private readonly definition;
|
|
58
|
-
constructor(items: Loaded<Entity, Hint, Fields, Excludes>[], totalCount: number, options: FindByCursorOptions<Entity, Hint, Fields, Excludes>, meta: EntityMetadata<Entity>);
|
|
58
|
+
constructor(items: Loaded<Entity, Hint, Fields, Excludes>[], totalCount: IncludeCount extends true ? number : undefined, options: FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>, meta: EntityMetadata<Entity>);
|
|
59
59
|
get startCursor(): string | null;
|
|
60
60
|
get endCursor(): string | null;
|
|
61
61
|
/**
|
package/utils/Cursor.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type DataLoader from 'dataloader';
|
|
1
2
|
import type { Primary, Ref } from '../typings.js';
|
|
2
3
|
import { Collection, type InitCollectionOptions } from '../entity/Collection.js';
|
|
3
4
|
import { type EntityManager } from '../EntityManager.js';
|
|
4
|
-
import type DataLoader from 'dataloader';
|
|
5
5
|
import { type LoadReferenceOptions } from '../entity/Reference.js';
|
|
6
6
|
export declare class DataloaderUtils {
|
|
7
7
|
/**
|
|
@@ -34,8 +34,13 @@ export declare class DataloaderUtils {
|
|
|
34
34
|
*/
|
|
35
35
|
static getColFilter<T, S extends T>(collection: Collection<any>): (result: T) => result is S;
|
|
36
36
|
/**
|
|
37
|
-
* Returns the collection dataloader batchLoadFn, which aggregates collections by entity,
|
|
37
|
+
* Returns the 1:M collection dataloader batchLoadFn, which aggregates collections by entity,
|
|
38
38
|
* makes one query per entity and maps each input collection to the corresponding result.
|
|
39
39
|
*/
|
|
40
40
|
static getColBatchLoadFn(em: EntityManager): DataLoader.BatchLoadFn<[Collection<any>, Omit<InitCollectionOptions<any, any>, 'dataloader'>?], any>;
|
|
41
|
+
/**
|
|
42
|
+
* Returns the M:N collection dataloader batchLoadFn, which aggregates collections by entity,
|
|
43
|
+
* makes one query per entity and maps each input collection to the corresponding result.
|
|
44
|
+
*/
|
|
45
|
+
static getManyToManyColBatchLoadFn(em: EntityManager): DataLoader.BatchLoadFn<[Collection<any>, Omit<InitCollectionOptions<any, any>, 'dataloader'>?], any>;
|
|
41
46
|
}
|
package/utils/DataloaderUtils.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Collection } from '../entity/Collection.js';
|
|
2
2
|
import { helper } from '../entity/wrap.js';
|
|
3
|
-
import { ReferenceKind } from '../enums.js';
|
|
4
3
|
import { Reference } from '../entity/Reference.js';
|
|
4
|
+
import { Utils } from './Utils.js';
|
|
5
5
|
export class DataloaderUtils {
|
|
6
6
|
/**
|
|
7
7
|
* Groups identified references by entity and returns a Map with the
|
|
@@ -118,7 +118,6 @@ export class DataloaderUtils {
|
|
|
118
118
|
// We need to populate the inverse side of the relationship in order to be able to later retrieve the PK(s) from its item(s)
|
|
119
119
|
populate: [
|
|
120
120
|
...(opts.populate === false ? [] : opts.populate ?? []),
|
|
121
|
-
...(opts.ref ? [':ref'] : []),
|
|
122
121
|
...Array.from(filterMap.keys()).filter(
|
|
123
122
|
// We need to do so only if the inverse side is a collection, because we can already retrieve the PK from a reference without having to load it
|
|
124
123
|
prop => em.getMetadata(className).properties[prop]?.ref !== true),
|
|
@@ -149,15 +148,11 @@ export class DataloaderUtils {
|
|
|
149
148
|
else if (target) {
|
|
150
149
|
return target === collection.owner;
|
|
151
150
|
}
|
|
152
|
-
// FIXME https://github.com/mikro-orm/mikro-orm/issues/6031
|
|
153
|
-
if (!target && collection.property.kind === ReferenceKind.MANY_TO_MANY) {
|
|
154
|
-
throw new Error(`Inverse side is required for M:N relations with dataloader: ${collection.owner.constructor.name}.${collection.property.name}`);
|
|
155
|
-
}
|
|
156
151
|
return false;
|
|
157
152
|
};
|
|
158
153
|
}
|
|
159
154
|
/**
|
|
160
|
-
* Returns the collection dataloader batchLoadFn, which aggregates collections by entity,
|
|
155
|
+
* Returns the 1:M collection dataloader batchLoadFn, which aggregates collections by entity,
|
|
161
156
|
* makes one query per entity and maps each input collection to the corresponding result.
|
|
162
157
|
*/
|
|
163
158
|
static getColBatchLoadFn(em) {
|
|
@@ -179,4 +174,40 @@ export class DataloaderUtils {
|
|
|
179
174
|
});
|
|
180
175
|
};
|
|
181
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* Returns the M:N collection dataloader batchLoadFn, which aggregates collections by entity,
|
|
179
|
+
* makes one query per entity and maps each input collection to the corresponding result.
|
|
180
|
+
*/
|
|
181
|
+
static getManyToManyColBatchLoadFn(em) {
|
|
182
|
+
return async (collsWithOpts) => {
|
|
183
|
+
const groups = new Map();
|
|
184
|
+
for (const [col, opts] of collsWithOpts) {
|
|
185
|
+
const key = `${col.property.targetMeta.className}.${col.property.name}|${JSON.stringify(opts ?? {})}`;
|
|
186
|
+
const value = groups.get(key) ?? [];
|
|
187
|
+
value.push([col, opts ?? {}]);
|
|
188
|
+
groups.set(key, value);
|
|
189
|
+
}
|
|
190
|
+
const ret = [];
|
|
191
|
+
for (const group of groups.values()) {
|
|
192
|
+
const prop = group[0][0].property;
|
|
193
|
+
const options = {};
|
|
194
|
+
const wrap = (cond) => ({ [prop.name]: cond });
|
|
195
|
+
const orderBy = Utils.asArray(group[0][1]?.orderBy).map(o => wrap(o));
|
|
196
|
+
const populate = wrap(group[0][1]?.populate);
|
|
197
|
+
const owners = group.map(c => c[0].owner);
|
|
198
|
+
const $or = [];
|
|
199
|
+
// a bit of a hack, but we need to prefix the key, since we have only a column name, not a property name
|
|
200
|
+
const alias = em.config.getNamingStrategy().aliasName(prop.pivotEntity, 0);
|
|
201
|
+
const fk = `${alias}.${Utils.getPrimaryKeyHash(prop.joinColumns)}`;
|
|
202
|
+
for (const c of group) {
|
|
203
|
+
$or.push({ $and: [c[1]?.where ?? {}, { [fk]: c[0].owner }] });
|
|
204
|
+
options.refresh ??= c[1]?.refresh;
|
|
205
|
+
}
|
|
206
|
+
options.where = wrap({ $or });
|
|
207
|
+
const r = await em.getEntityLoader().findChildrenFromPivotTable(owners, prop, options, orderBy, populate, group[0][1]?.ref);
|
|
208
|
+
ret.push(...r);
|
|
209
|
+
}
|
|
210
|
+
return ret;
|
|
211
|
+
};
|
|
212
|
+
}
|
|
182
213
|
}
|