@mikro-orm/core 7.0.0-dev.3 → 7.0.0-dev.31
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 +50 -7
- package/EntityManager.js +141 -97
- package/MikroORM.js +0 -1
- package/README.md +1 -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 +20 -5
- package/decorators/Entity.js +0 -1
- package/decorators/Enum.d.ts +1 -1
- package/decorators/Formula.d.ts +1 -2
- package/decorators/Indexed.d.ts +10 -8
- package/decorators/Indexed.js +1 -1
- 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 +1 -1
- package/decorators/Transactional.d.ts +1 -0
- package/decorators/Transactional.js +3 -3
- package/drivers/IDatabaseDriver.d.ts +8 -1
- package/entity/ArrayCollection.d.ts +4 -2
- package/entity/ArrayCollection.js +18 -6
- package/entity/Collection.d.ts +1 -2
- package/entity/Collection.js +16 -10
- package/entity/EntityAssigner.d.ts +1 -1
- package/entity/EntityAssigner.js +9 -1
- package/entity/EntityFactory.d.ts +6 -0
- package/entity/EntityFactory.js +21 -7
- package/entity/EntityHelper.js +8 -1
- package/entity/EntityLoader.d.ts +3 -2
- package/entity/EntityLoader.js +54 -35
- package/entity/EntityRepository.d.ts +1 -1
- package/entity/EntityValidator.js +1 -1
- package/entity/Reference.d.ts +8 -7
- package/entity/Reference.js +22 -1
- package/entity/WrappedEntity.js +1 -1
- package/entity/defineEntity.d.ts +537 -0
- package/entity/defineEntity.js +693 -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.js +10 -2
- package/index.d.ts +1 -1
- package/metadata/EntitySchema.d.ts +6 -4
- package/metadata/EntitySchema.js +33 -19
- package/metadata/MetadataDiscovery.d.ts +0 -1
- package/metadata/MetadataDiscovery.js +51 -29
- package/metadata/MetadataStorage.js +1 -1
- package/metadata/MetadataValidator.js +4 -3
- package/package.json +5 -5
- package/platforms/Platform.d.ts +3 -1
- package/serialization/EntitySerializer.d.ts +2 -0
- package/serialization/EntitySerializer.js +1 -1
- package/serialization/SerializationContext.js +13 -10
- 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/typings.d.ts +72 -35
- 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 +21 -11
- package/unit-of-work/UnitOfWork.d.ts +2 -1
- package/unit-of-work/UnitOfWork.js +71 -24
- package/utils/AbstractSchemaGenerator.js +5 -2
- package/utils/Configuration.d.ts +15 -5
- package/utils/Configuration.js +7 -7
- 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 +98 -59
- package/utils/QueryHelper.d.ts +6 -0
- package/utils/QueryHelper.js +48 -5
- package/utils/RawQueryFragment.d.ts +34 -0
- package/utils/RawQueryFragment.js +40 -1
- package/utils/TransactionManager.d.ts +65 -0
- package/utils/TransactionManager.js +220 -0
- package/utils/Utils.d.ts +11 -7
- package/utils/Utils.js +67 -33
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/upsert-utils.js +9 -1
|
@@ -12,16 +12,18 @@ export class ChangeSetPersister {
|
|
|
12
12
|
factory;
|
|
13
13
|
validator;
|
|
14
14
|
config;
|
|
15
|
+
em;
|
|
15
16
|
platform;
|
|
16
17
|
comparator;
|
|
17
18
|
usesReturningStatement;
|
|
18
|
-
constructor(driver, metadata, hydrator, factory, validator, config) {
|
|
19
|
+
constructor(driver, metadata, hydrator, factory, validator, config, em) {
|
|
19
20
|
this.driver = driver;
|
|
20
21
|
this.metadata = metadata;
|
|
21
22
|
this.hydrator = hydrator;
|
|
22
23
|
this.factory = factory;
|
|
23
24
|
this.validator = validator;
|
|
24
25
|
this.config = config;
|
|
26
|
+
this.em = em;
|
|
25
27
|
this.platform = this.driver.getPlatform();
|
|
26
28
|
this.comparator = this.config.getComparator(this.metadata);
|
|
27
29
|
this.usesReturningStatement = this.platform.usesReturningStatement() || this.platform.usesOutputStatement();
|
|
@@ -62,7 +64,7 @@ export class ChangeSetPersister {
|
|
|
62
64
|
for (let i = 0; i < changeSets.length; i += size) {
|
|
63
65
|
const chunk = changeSets.slice(i, i + size);
|
|
64
66
|
const pks = chunk.map(cs => cs.getPrimaryKey());
|
|
65
|
-
options = this.
|
|
67
|
+
options = this.prepareOptions(meta, options);
|
|
66
68
|
await this.driver.nativeDelete(meta.root.className, { [pk]: { $in: pks } }, options);
|
|
67
69
|
}
|
|
68
70
|
}
|
|
@@ -90,7 +92,7 @@ export class ChangeSetPersister {
|
|
|
90
92
|
}
|
|
91
93
|
async persistNewEntity(meta, changeSet, options) {
|
|
92
94
|
const wrapped = helper(changeSet.entity);
|
|
93
|
-
options = this.
|
|
95
|
+
options = this.prepareOptions(meta, options, {
|
|
94
96
|
convertCustomTypes: false,
|
|
95
97
|
});
|
|
96
98
|
const res = await this.driver.nativeInsertMany(meta.className, [changeSet.payload], options);
|
|
@@ -116,15 +118,17 @@ export class ChangeSetPersister {
|
|
|
116
118
|
}
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
|
-
|
|
121
|
+
prepareOptions(meta, options, additionalOptions) {
|
|
122
|
+
const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
|
|
120
123
|
return {
|
|
121
124
|
...options,
|
|
122
125
|
...additionalOptions,
|
|
123
126
|
schema: options?.schema ?? meta.schema,
|
|
127
|
+
loggerContext,
|
|
124
128
|
};
|
|
125
129
|
}
|
|
126
130
|
async persistNewEntitiesBatch(meta, changeSets, options) {
|
|
127
|
-
options = this.
|
|
131
|
+
options = this.prepareOptions(meta, options, {
|
|
128
132
|
convertCustomTypes: false,
|
|
129
133
|
processCollections: false,
|
|
130
134
|
});
|
|
@@ -175,7 +179,7 @@ export class ChangeSetPersister {
|
|
|
175
179
|
}
|
|
176
180
|
async persistManagedEntitiesBatch(meta, changeSets, options) {
|
|
177
181
|
await this.checkOptimisticLocks(meta, changeSets, options);
|
|
178
|
-
options = this.
|
|
182
|
+
options = this.prepareOptions(meta, options, {
|
|
179
183
|
convertCustomTypes: false,
|
|
180
184
|
processCollections: false,
|
|
181
185
|
});
|
|
@@ -210,7 +214,9 @@ export class ChangeSetPersister {
|
|
|
210
214
|
// of using the raw value from db, we convert it back to the db value explicitly
|
|
211
215
|
value = prop.customType ? prop.customType.convertToDatabaseValue(insertId, this.platform, { mode: 'serialization' }) : value;
|
|
212
216
|
changeSet.payload[wrapped.__meta.primaryKeys[0]] = value;
|
|
213
|
-
wrapped.__identifier
|
|
217
|
+
if (wrapped.__identifier && !Array.isArray(wrapped.__identifier)) {
|
|
218
|
+
wrapped.__identifier.setValue(value);
|
|
219
|
+
}
|
|
214
220
|
}
|
|
215
221
|
/**
|
|
216
222
|
* Sets populate flag to new entities so they are serialized like if they were loaded from the db
|
|
@@ -233,7 +239,7 @@ export class ChangeSetPersister {
|
|
|
233
239
|
}
|
|
234
240
|
async updateEntity(meta, changeSet, options) {
|
|
235
241
|
const cond = changeSet.getPrimaryKey(true);
|
|
236
|
-
options = this.
|
|
242
|
+
options = this.prepareOptions(meta, options, {
|
|
237
243
|
convertCustomTypes: false,
|
|
238
244
|
});
|
|
239
245
|
if (meta.concurrencyCheckKeys.size === 0 && (!meta.versionProperty || changeSet.entity[meta.versionProperty] == null)) {
|
|
@@ -260,7 +266,7 @@ export class ChangeSetPersister {
|
|
|
260
266
|
return cond;
|
|
261
267
|
});
|
|
262
268
|
const primaryKeys = meta.primaryKeys.concat(...meta.concurrencyCheckKeys);
|
|
263
|
-
options = this.
|
|
269
|
+
options = this.prepareOptions(meta, options, {
|
|
264
270
|
fields: primaryKeys,
|
|
265
271
|
});
|
|
266
272
|
const res = await this.driver.find(meta.root.className, { $or }, options);
|
|
@@ -319,12 +325,12 @@ export class ChangeSetPersister {
|
|
|
319
325
|
}
|
|
320
326
|
return val;
|
|
321
327
|
});
|
|
322
|
-
options = this.
|
|
328
|
+
options = this.prepareOptions(meta, options, {
|
|
323
329
|
fields: Utils.unique(reloadProps.map(prop => prop.name)),
|
|
324
330
|
});
|
|
325
331
|
const data = await this.driver.find(meta.className, { [pk]: { $in: pks } }, options);
|
|
326
332
|
const map = new Map();
|
|
327
|
-
data.forEach(item => map.set(Utils.getCompositeKeyHash(item, meta,
|
|
333
|
+
data.forEach(item => map.set(Utils.getCompositeKeyHash(item, meta, false, this.platform, true), item));
|
|
328
334
|
for (const changeSet of changeSets) {
|
|
329
335
|
const data = map.get(helper(changeSet.entity).getSerializedPrimaryKey());
|
|
330
336
|
this.hydrator.hydrate(changeSet.entity, meta, data, this.factory, 'full', false, true);
|
|
@@ -338,6 +344,10 @@ export class ChangeSetPersister {
|
|
|
338
344
|
changeSet.payload[prop.name] = value.getValue();
|
|
339
345
|
return;
|
|
340
346
|
}
|
|
347
|
+
if (Array.isArray(value) && value.every(item => item instanceof EntityIdentifier)) {
|
|
348
|
+
changeSet.payload[prop.name] = value.map(item => item.getValue());
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
341
351
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && Array.isArray(value)) {
|
|
342
352
|
changeSet.payload[prop.name] = value.map(val => val instanceof EntityIdentifier ? val.getValue() : val);
|
|
343
353
|
return;
|
|
@@ -39,7 +39,7 @@ export declare class UnitOfWork {
|
|
|
39
39
|
/**
|
|
40
40
|
* 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
41
|
*/
|
|
42
|
-
getById<T extends object>(entityName: string, id: Primary<T> | Primary<T>[], schema?: string): T | undefined;
|
|
42
|
+
getById<T extends object>(entityName: string, id: Primary<T> | Primary<T>[], schema?: string, convertCustomTypes?: boolean): T | undefined;
|
|
43
43
|
tryGetById<T extends object>(entityName: string, where: FilterQuery<T>, schema?: string, strict?: boolean): T | null;
|
|
44
44
|
/**
|
|
45
45
|
* Returns map of all managed entities.
|
|
@@ -103,6 +103,7 @@ export declare class UnitOfWork {
|
|
|
103
103
|
private commitDeleteChangeSets;
|
|
104
104
|
private commitExtraUpdates;
|
|
105
105
|
private commitCollectionUpdates;
|
|
106
|
+
private filterCollectionUpdates;
|
|
106
107
|
/**
|
|
107
108
|
* Orders change sets so FK constrains are maintained, ensures stable order (needed for node < 11)
|
|
108
109
|
*/
|
|
@@ -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);
|
|
@@ -89,7 +89,7 @@ export class UnitOfWork {
|
|
|
89
89
|
}
|
|
90
90
|
wrapped.__loadedProperties.add(key);
|
|
91
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
|
|
92
|
+
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
93
93
|
}
|
|
94
94
|
else if (prop.kind === ReferenceKind.EMBEDDED && !prop.object && Utils.isPlainObject(data[prop.name])) {
|
|
95
95
|
for (const p of prop.targetMeta.props) {
|
|
@@ -97,7 +97,7 @@ export class UnitOfWork {
|
|
|
97
97
|
const prefix = prop.prefix === false ? '' : prop.prefix === true ? prop.name + '_' : prop.prefix;
|
|
98
98
|
data[prefix + p.name] = data[prop.name][p.name];
|
|
99
99
|
}
|
|
100
|
-
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta
|
|
100
|
+
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
101
101
|
}
|
|
102
102
|
if (forceUndefined) {
|
|
103
103
|
if (data[key] === null) {
|
|
@@ -125,7 +125,7 @@ export class UnitOfWork {
|
|
|
125
125
|
/**
|
|
126
126
|
* 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
127
|
*/
|
|
128
|
-
getById(entityName, id, schema) {
|
|
128
|
+
getById(entityName, id, schema, convertCustomTypes) {
|
|
129
129
|
if (id == null || (Array.isArray(id) && id.length === 0)) {
|
|
130
130
|
return undefined;
|
|
131
131
|
}
|
|
@@ -135,7 +135,16 @@ export class UnitOfWork {
|
|
|
135
135
|
hash = '' + id;
|
|
136
136
|
}
|
|
137
137
|
else {
|
|
138
|
-
|
|
138
|
+
let keys = Array.isArray(id) ? Utils.flatten(id) : [id];
|
|
139
|
+
keys = meta.getPrimaryProps(true).map((p, i) => {
|
|
140
|
+
if (!convertCustomTypes && p.customType) {
|
|
141
|
+
return p.customType.convertToDatabaseValue(keys[i], this.platform, {
|
|
142
|
+
key: p.name,
|
|
143
|
+
mode: 'hydration',
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return keys[i];
|
|
147
|
+
});
|
|
139
148
|
hash = Utils.getPrimaryKeyHash(keys);
|
|
140
149
|
}
|
|
141
150
|
schema ??= meta.schema ?? this.em.config.getSchema();
|
|
@@ -303,6 +312,7 @@ export class UnitOfWork {
|
|
|
303
312
|
cs.entity.__helper.__processing = true;
|
|
304
313
|
}
|
|
305
314
|
await this.eventManager.dispatchEvent(EventType.onFlush, { em: this.em, uow: this });
|
|
315
|
+
this.filterCollectionUpdates();
|
|
306
316
|
// nothing to do, do not start transaction
|
|
307
317
|
if (this.changeSets.size === 0 && this.collectionUpdates.size === 0 && this.extraUpdates.size === 0) {
|
|
308
318
|
return void (await this.eventManager.dispatchEvent(EventType.afterFlush, { em: this.em, uow: this }));
|
|
@@ -311,9 +321,11 @@ export class UnitOfWork {
|
|
|
311
321
|
const platform = this.em.getPlatform();
|
|
312
322
|
const runInTransaction = !this.em.isInTransaction() && platform.supportsTransactions() && this.em.config.get('implicitTransactions');
|
|
313
323
|
if (runInTransaction) {
|
|
324
|
+
const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
|
|
314
325
|
await this.em.getConnection('write').transactional(trx => this.persistToDatabase(groups, trx), {
|
|
315
326
|
ctx: oldTx,
|
|
316
327
|
eventBroadcaster: new TransactionEventBroadcaster(this.em),
|
|
328
|
+
loggerContext,
|
|
317
329
|
});
|
|
318
330
|
}
|
|
319
331
|
else {
|
|
@@ -542,13 +554,22 @@ export class UnitOfWork {
|
|
|
542
554
|
if (!wrapped || wrapped.__identifier || wrapped.hasPrimaryKey()) {
|
|
543
555
|
return;
|
|
544
556
|
}
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
557
|
+
const pks = wrapped.__meta.getPrimaryProps();
|
|
558
|
+
const idents = [];
|
|
559
|
+
for (const pk of pks) {
|
|
560
|
+
if (pk.kind === ReferenceKind.SCALAR) {
|
|
561
|
+
idents.push(new EntityIdentifier(entity[pk.name]));
|
|
562
|
+
}
|
|
563
|
+
else if (entity[pk.name]) {
|
|
564
|
+
this.initIdentifier(entity[pk.name]);
|
|
565
|
+
idents.push(helper(entity[pk.name])?.__identifier);
|
|
566
|
+
}
|
|
548
567
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
568
|
+
if (pks.length === 1) {
|
|
569
|
+
wrapped.__identifier = idents[0];
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
wrapped.__identifier = idents;
|
|
552
573
|
}
|
|
553
574
|
}
|
|
554
575
|
processReference(parent, prop, kind, visited, processed, idx) {
|
|
@@ -600,8 +621,15 @@ export class UnitOfWork {
|
|
|
600
621
|
const diff = this.comparator.diffEntities(changeSet.name, copy, current);
|
|
601
622
|
Object.assign(changeSet.payload, diff);
|
|
602
623
|
const wrapped = helper(changeSet.entity);
|
|
603
|
-
if (wrapped.__identifier
|
|
604
|
-
|
|
624
|
+
if (wrapped.__identifier) {
|
|
625
|
+
const idents = Utils.asArray(wrapped.__identifier);
|
|
626
|
+
let i = 0;
|
|
627
|
+
for (const pk of wrapped.__meta.primaryKeys) {
|
|
628
|
+
if (diff[pk]) {
|
|
629
|
+
idents[i].setValue(diff[pk]);
|
|
630
|
+
}
|
|
631
|
+
i++;
|
|
632
|
+
}
|
|
605
633
|
}
|
|
606
634
|
}
|
|
607
635
|
postCommitCleanup() {
|
|
@@ -825,9 +853,17 @@ export class UnitOfWork {
|
|
|
825
853
|
}
|
|
826
854
|
await this.changeSetPersister.executeUpdates(changeSets, batched, { ctx });
|
|
827
855
|
for (const changeSet of changeSets) {
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
856
|
+
const wrapped = helper(changeSet.entity);
|
|
857
|
+
wrapped.__originalEntityData = this.comparator.prepareEntity(changeSet.entity);
|
|
858
|
+
wrapped.__touched = false;
|
|
859
|
+
if (!wrapped.__initialized) {
|
|
860
|
+
for (const prop of changeSet.meta.relations) {
|
|
861
|
+
if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) && changeSet.entity[prop.name] == null) {
|
|
862
|
+
changeSet.entity[prop.name] = Collection.create(changeSet.entity, prop.name, undefined, wrapped.isInitialized());
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
wrapped.__initialized = true;
|
|
866
|
+
}
|
|
831
867
|
await this.runHooks(EventType.afterUpdate, changeSet);
|
|
832
868
|
}
|
|
833
869
|
}
|
|
@@ -870,23 +906,34 @@ export class UnitOfWork {
|
|
|
870
906
|
}
|
|
871
907
|
}
|
|
872
908
|
async commitCollectionUpdates(ctx) {
|
|
873
|
-
|
|
909
|
+
this.filterCollectionUpdates();
|
|
910
|
+
const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
|
|
911
|
+
await this.em.getDriver().syncCollections(this.collectionUpdates, {
|
|
912
|
+
ctx,
|
|
913
|
+
schema: this.em.schema,
|
|
914
|
+
loggerContext,
|
|
915
|
+
});
|
|
874
916
|
for (const coll of this.collectionUpdates) {
|
|
917
|
+
coll.takeSnapshot();
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
filterCollectionUpdates() {
|
|
921
|
+
for (const coll of this.collectionUpdates) {
|
|
922
|
+
let skip = true;
|
|
875
923
|
if (coll.property.owner || coll.getItems(false).filter(item => !item.__helper.__initialized).length > 0) {
|
|
876
924
|
if (this.platform.usesPivotTable()) {
|
|
877
|
-
|
|
925
|
+
skip = false;
|
|
878
926
|
}
|
|
879
927
|
}
|
|
880
928
|
else if (coll.property.kind === ReferenceKind.ONE_TO_MANY && coll.getSnapshot() === undefined) {
|
|
881
|
-
|
|
929
|
+
skip = false;
|
|
882
930
|
}
|
|
883
931
|
else if (coll.property.kind === ReferenceKind.MANY_TO_MANY && !coll.property.owner) {
|
|
884
|
-
|
|
932
|
+
skip = false;
|
|
933
|
+
}
|
|
934
|
+
if (skip) {
|
|
935
|
+
this.collectionUpdates.delete(coll);
|
|
885
936
|
}
|
|
886
|
-
}
|
|
887
|
-
await this.em.getDriver().syncCollections(collectionUpdates, { ctx });
|
|
888
|
-
for (const coll of this.collectionUpdates) {
|
|
889
|
-
coll.takeSnapshot();
|
|
890
937
|
}
|
|
891
938
|
}
|
|
892
939
|
/**
|
|
@@ -32,7 +32,7 @@ export class AbstractSchemaGenerator {
|
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
34
34
|
await this.ensureDatabase();
|
|
35
|
-
await this.dropSchema();
|
|
35
|
+
await this.dropSchema(options);
|
|
36
36
|
}
|
|
37
37
|
if (options?.createSchema !== false) {
|
|
38
38
|
await this.createSchema(options);
|
|
@@ -103,7 +103,10 @@ export class AbstractSchemaGenerator {
|
|
|
103
103
|
}
|
|
104
104
|
return calc.sort()
|
|
105
105
|
.map(cls => this.metadata.find(cls))
|
|
106
|
-
.filter(meta =>
|
|
106
|
+
.filter(meta => {
|
|
107
|
+
const targetSchema = meta.schema ?? this.config.get('schema', this.platform.getDefaultSchemaName());
|
|
108
|
+
return schema ? [schema, '*'].includes(targetSchema) : meta.schema !== '*';
|
|
109
|
+
});
|
|
107
110
|
}
|
|
108
111
|
notImplemented() {
|
|
109
112
|
throw new Error(`This method is not supported by ${this.driver.constructor.name} driver`);
|
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;
|
|
@@ -78,9 +78,11 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
78
78
|
upsertManaged: true;
|
|
79
79
|
forceEntityConstructor: false;
|
|
80
80
|
forceUndefined: false;
|
|
81
|
+
processOnCreateHooksEarly: false;
|
|
81
82
|
ensureDatabase: true;
|
|
82
83
|
ensureIndexes: false;
|
|
83
84
|
batchSize: number;
|
|
85
|
+
hashAlgorithm: "md5";
|
|
84
86
|
debug: false;
|
|
85
87
|
ignoreDeprecations: false;
|
|
86
88
|
verbose: false;
|
|
@@ -103,9 +105,11 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
103
105
|
disableForeignKeys: false;
|
|
104
106
|
createForeignKeyConstraints: true;
|
|
105
107
|
ignoreSchema: never[];
|
|
108
|
+
skipTables: never[];
|
|
109
|
+
skipColumns: {};
|
|
106
110
|
};
|
|
107
111
|
embeddables: {
|
|
108
|
-
prefixMode: "
|
|
112
|
+
prefixMode: "relative";
|
|
109
113
|
};
|
|
110
114
|
entityGenerator: {
|
|
111
115
|
forceUndefined: true;
|
|
@@ -142,7 +146,6 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
142
146
|
fileName: (className: string) => string;
|
|
143
147
|
};
|
|
144
148
|
preferReadReplicas: true;
|
|
145
|
-
dynamicImportProvider: (id: string) => Promise<any>;
|
|
146
149
|
};
|
|
147
150
|
private readonly options;
|
|
148
151
|
private readonly logger;
|
|
@@ -332,6 +335,11 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
332
335
|
upsertManaged: boolean;
|
|
333
336
|
forceEntityConstructor: boolean | (Constructor<AnyEntity> | string)[];
|
|
334
337
|
forceUndefined: boolean;
|
|
338
|
+
/**
|
|
339
|
+
* Property `onCreate` hooks are normally executed during `flush` operation.
|
|
340
|
+
* With this option, they will be processed early inside `em.create()` method.
|
|
341
|
+
*/
|
|
342
|
+
processOnCreateHooksEarly: boolean;
|
|
335
343
|
forceUtcTimezone?: boolean;
|
|
336
344
|
timezone?: string;
|
|
337
345
|
ensureDatabase: boolean | EnsureDatabaseOptions;
|
|
@@ -340,7 +348,7 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
340
348
|
useBatchUpdates?: boolean;
|
|
341
349
|
batchSize: number;
|
|
342
350
|
hydrator: HydratorConstructor;
|
|
343
|
-
loadStrategy: LoadStrategy |
|
|
351
|
+
loadStrategy: LoadStrategy | `${LoadStrategy}`;
|
|
344
352
|
dataloader: DataloaderType | boolean;
|
|
345
353
|
populateWhere?: PopulateHint | `${PopulateHint}`;
|
|
346
354
|
flushMode: FlushMode | 'commit' | 'auto' | 'always';
|
|
@@ -374,6 +382,8 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
374
382
|
disableForeignKeys?: boolean;
|
|
375
383
|
createForeignKeyConstraints?: boolean;
|
|
376
384
|
ignoreSchema?: string[];
|
|
385
|
+
skipTables?: (string | RegExp)[];
|
|
386
|
+
skipColumns?: Dictionary<(string | RegExp)[]>;
|
|
377
387
|
managementDbName?: string;
|
|
378
388
|
};
|
|
379
389
|
embeddables: {
|
|
@@ -402,6 +412,6 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
402
412
|
};
|
|
403
413
|
seeder: SeederOptions;
|
|
404
414
|
preferReadReplicas: boolean;
|
|
405
|
-
|
|
415
|
+
hashAlgorithm: 'md5' | 'sha256';
|
|
406
416
|
}
|
|
407
417
|
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,
|
|
@@ -68,9 +68,11 @@ export class Configuration {
|
|
|
68
68
|
upsertManaged: true,
|
|
69
69
|
forceEntityConstructor: false,
|
|
70
70
|
forceUndefined: false,
|
|
71
|
+
processOnCreateHooksEarly: false,
|
|
71
72
|
ensureDatabase: true,
|
|
72
73
|
ensureIndexes: false,
|
|
73
74
|
batchSize: 300,
|
|
75
|
+
hashAlgorithm: 'md5',
|
|
74
76
|
debug: false,
|
|
75
77
|
ignoreDeprecations: false,
|
|
76
78
|
verbose: false,
|
|
@@ -93,9 +95,11 @@ export class Configuration {
|
|
|
93
95
|
disableForeignKeys: false,
|
|
94
96
|
createForeignKeyConstraints: true,
|
|
95
97
|
ignoreSchema: [],
|
|
98
|
+
skipTables: [],
|
|
99
|
+
skipColumns: {},
|
|
96
100
|
},
|
|
97
101
|
embeddables: {
|
|
98
|
-
prefixMode: '
|
|
102
|
+
prefixMode: 'relative',
|
|
99
103
|
},
|
|
100
104
|
entityGenerator: {
|
|
101
105
|
forceUndefined: true,
|
|
@@ -130,7 +134,6 @@ export class Configuration {
|
|
|
130
134
|
fileName: (className) => className,
|
|
131
135
|
},
|
|
132
136
|
preferReadReplicas: true,
|
|
133
|
-
dynamicImportProvider: /* v8 ignore next */ (id) => import(id),
|
|
134
137
|
};
|
|
135
138
|
options;
|
|
136
139
|
logger;
|
|
@@ -139,9 +142,6 @@ export class Configuration {
|
|
|
139
142
|
cache = new Map();
|
|
140
143
|
extensions = new Map();
|
|
141
144
|
constructor(options, validate = true) {
|
|
142
|
-
if (options.dynamicImportProvider) {
|
|
143
|
-
Utils.setDynamicImportProvider(options.dynamicImportProvider);
|
|
144
|
-
}
|
|
145
145
|
this.options = Utils.mergeConfig({}, Configuration.DEFAULTS, options);
|
|
146
146
|
this.options.baseDir = Utils.absolutePath(this.options.baseDir);
|
|
147
147
|
this.options.preferTs ??= options.preferTs;
|
|
@@ -268,7 +268,7 @@ export class Configuration {
|
|
|
268
268
|
* Gets instance of metadata CacheAdapter. (cached)
|
|
269
269
|
*/
|
|
270
270
|
getMetadataCacheAdapter() {
|
|
271
|
-
return this.getCachedService(this.options.metadataCache.adapter, this.options.metadataCache.options, this.options.baseDir, this.options.metadataCache.pretty);
|
|
271
|
+
return this.getCachedService(this.options.metadataCache.adapter, this.options.metadataCache.options, this.options.baseDir, this.options.metadataCache.pretty, this.options.hashAlgorithm);
|
|
272
272
|
}
|
|
273
273
|
/**
|
|
274
274
|
* Gets instance of CacheAdapter for result cache. (cached)
|
|
@@ -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
|
}
|