@mikro-orm/core 7.0.0-rc.1 → 7.0.0-rc.3
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 +3 -2
- package/EntityManager.js +107 -43
- package/MikroORM.js +4 -4
- package/cache/FileCacheAdapter.js +1 -3
- package/connections/Connection.js +16 -3
- package/drivers/DatabaseDriver.js +26 -8
- package/drivers/IDatabaseDriver.d.ts +49 -1
- package/entity/BaseEntity.d.ts +3 -3
- package/entity/Collection.js +43 -17
- package/entity/EntityAssigner.js +23 -11
- package/entity/EntityFactory.js +36 -13
- package/entity/EntityHelper.js +27 -18
- package/entity/EntityLoader.d.ts +6 -6
- package/entity/EntityLoader.js +55 -22
- package/entity/EntityRepository.d.ts +1 -1
- package/entity/Reference.d.ts +1 -1
- package/entity/Reference.js +37 -8
- package/entity/WrappedEntity.d.ts +3 -3
- package/entity/WrappedEntity.js +5 -1
- package/entity/defineEntity.d.ts +202 -58
- package/entity/defineEntity.js +20 -24
- package/entity/utils.js +28 -26
- package/entity/validators.js +2 -1
- package/enums.js +12 -17
- package/errors.js +18 -8
- package/events/EventManager.js +1 -1
- package/exceptions.js +7 -2
- package/hydration/ObjectHydrator.js +27 -13
- package/index.d.ts +2 -2
- package/index.js +1 -1
- package/logging/DefaultLogger.js +3 -5
- package/logging/colors.js +3 -6
- package/metadata/EntitySchema.d.ts +2 -2
- package/metadata/EntitySchema.js +12 -2
- package/metadata/MetadataDiscovery.js +107 -48
- package/metadata/MetadataProvider.js +26 -1
- package/metadata/MetadataStorage.js +2 -4
- package/metadata/MetadataValidator.js +20 -5
- package/metadata/types.d.ts +2 -2
- package/naming-strategy/AbstractNamingStrategy.js +5 -2
- package/not-supported.js +5 -1
- package/package.json +40 -37
- package/platforms/Platform.d.ts +4 -1
- package/platforms/Platform.js +50 -24
- package/serialization/EntitySerializer.d.ts +3 -3
- package/serialization/EntitySerializer.js +7 -3
- package/serialization/EntityTransformer.js +6 -4
- package/serialization/SerializationContext.js +1 -1
- package/typings.d.ts +73 -33
- package/typings.js +11 -9
- package/unit-of-work/ChangeSet.js +4 -4
- package/unit-of-work/ChangeSetComputer.js +8 -6
- package/unit-of-work/ChangeSetPersister.js +15 -10
- package/unit-of-work/CommitOrderCalculator.js +4 -2
- package/unit-of-work/UnitOfWork.d.ts +7 -1
- package/unit-of-work/UnitOfWork.js +51 -22
- package/utils/AbstractMigrator.d.ts +101 -0
- package/utils/AbstractMigrator.js +303 -0
- package/utils/AbstractSchemaGenerator.js +2 -1
- package/utils/AsyncContext.js +1 -1
- package/utils/Configuration.d.ts +3 -1
- package/utils/Configuration.js +8 -4
- package/utils/Cursor.js +4 -2
- package/utils/DataloaderUtils.js +15 -12
- package/utils/EntityComparator.js +51 -43
- package/utils/QueryHelper.js +38 -26
- package/utils/RawQueryFragment.js +3 -2
- package/utils/TransactionManager.js +2 -1
- package/utils/Utils.d.ts +1 -1
- package/utils/Utils.js +36 -30
- package/utils/env-vars.js +6 -5
- package/utils/fs-utils.d.ts +1 -0
- package/utils/fs-utils.js +6 -5
- package/utils/index.d.ts +0 -2
- package/utils/index.js +0 -2
- package/utils/upsert-utils.js +6 -3
|
@@ -31,7 +31,8 @@ export class ChangeSetComputer {
|
|
|
31
31
|
const map = new Map();
|
|
32
32
|
// Execute `onCreate` and `onUpdate` on properties recursively, saves `onUpdate` results
|
|
33
33
|
// to the `map` as we want to apply those only if something else changed.
|
|
34
|
-
if (type === ChangeSetType.CREATE) {
|
|
34
|
+
if (type === ChangeSetType.CREATE) {
|
|
35
|
+
// run update hooks only after we know there are other changes
|
|
35
36
|
for (const prop of meta.hydrateProps) {
|
|
36
37
|
this.processPropertyInitializers(entity, prop, type, map);
|
|
37
38
|
}
|
|
@@ -74,10 +75,10 @@ export class ChangeSetComputer {
|
|
|
74
75
|
* Traverses entity graph and executes `onCreate` and `onUpdate` methods, assigning the values to given properties.
|
|
75
76
|
*/
|
|
76
77
|
processPropertyInitializers(entity, prop, type, map, nested) {
|
|
77
|
-
if (prop.onCreate
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
if (prop.onCreate &&
|
|
79
|
+
type === ChangeSetType.CREATE &&
|
|
80
|
+
(entity[prop.name] == null ||
|
|
81
|
+
(Utils.isScalarReference(entity[prop.name]) && entity[prop.name].unwrap() == null))) {
|
|
81
82
|
entity[prop.name] = prop.onCreate(entity, this.em);
|
|
82
83
|
}
|
|
83
84
|
if (prop.onUpdate && type === ChangeSetType.UPDATE) {
|
|
@@ -120,7 +121,8 @@ export class ChangeSetComputer {
|
|
|
120
121
|
targets.forEach(([t]) => this.processProperty(changeSet, prop, t));
|
|
121
122
|
return;
|
|
122
123
|
}
|
|
123
|
-
if (Utils.isCollection(target)) {
|
|
124
|
+
if (Utils.isCollection(target)) {
|
|
125
|
+
// m:n or 1:m
|
|
124
126
|
this.processToMany(prop, changeSet);
|
|
125
127
|
}
|
|
126
128
|
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
|
|
@@ -49,7 +49,10 @@ export class ChangeSetPersister {
|
|
|
49
49
|
// For STI with conflicting fieldNames (renamedFrom properties), we can't batch mixed child types
|
|
50
50
|
const hasSTIConflicts = meta.root.props.some(p => p.renamedFrom);
|
|
51
51
|
const hasMixedTypes = hasSTIConflicts && changeSets.some(cs => cs.meta.class !== meta.class);
|
|
52
|
-
if (batched &&
|
|
52
|
+
if (batched &&
|
|
53
|
+
changeSets.length > 1 &&
|
|
54
|
+
!hasMixedTypes &&
|
|
55
|
+
this.config.get('useBatchUpdates', this.platform.usesBatchUpdates())) {
|
|
53
56
|
return this.persistManagedEntities(meta, changeSets, options);
|
|
54
57
|
}
|
|
55
58
|
for (const changeSet of changeSets) {
|
|
@@ -238,7 +241,9 @@ export class ChangeSetPersister {
|
|
|
238
241
|
// some drivers might be returning bigint PKs as numbers when the number is small enough,
|
|
239
242
|
// but we need to have it as string so comparison works in change set tracking, so instead
|
|
240
243
|
// of using the raw value from db, we convert it back to the db value explicitly
|
|
241
|
-
value = prop.customType
|
|
244
|
+
value = prop.customType
|
|
245
|
+
? prop.customType.convertToDatabaseValue(insertId, this.platform, { mode: 'serialization' })
|
|
246
|
+
: value;
|
|
242
247
|
changeSet.payload[wrapped.__meta.primaryKeys[0]] = value;
|
|
243
248
|
if (wrapped.__identifier && !Array.isArray(wrapped.__identifier)) {
|
|
244
249
|
wrapped.__identifier.setValue(value);
|
|
@@ -268,17 +273,19 @@ export class ChangeSetPersister {
|
|
|
268
273
|
options = this.prepareOptions(meta, options, {
|
|
269
274
|
convertCustomTypes: false,
|
|
270
275
|
});
|
|
271
|
-
if (meta.concurrencyCheckKeys.size === 0 &&
|
|
276
|
+
if (meta.concurrencyCheckKeys.size === 0 &&
|
|
277
|
+
(!meta.versionProperty || changeSet.entity[meta.versionProperty] == null)) {
|
|
272
278
|
return this.driver.nativeUpdate(changeSet.meta.class, cond, changeSet.payload, options);
|
|
273
279
|
}
|
|
274
280
|
if (meta.versionProperty) {
|
|
275
|
-
cond[meta.versionProperty] = this.platform.
|
|
281
|
+
cond[meta.versionProperty] = this.platform.convertVersionValue(changeSet.entity[meta.versionProperty], meta.properties[meta.versionProperty]);
|
|
276
282
|
}
|
|
277
283
|
this.checkConcurrencyKeys(meta, changeSet, cond);
|
|
278
284
|
return this.driver.nativeUpdate(changeSet.meta.class, cond, changeSet.payload, options);
|
|
279
285
|
}
|
|
280
286
|
async checkOptimisticLocks(meta, changeSets, options) {
|
|
281
|
-
if (meta.concurrencyCheckKeys.size === 0 &&
|
|
287
|
+
if (meta.concurrencyCheckKeys.size === 0 &&
|
|
288
|
+
(!meta.versionProperty || changeSets.every(cs => cs.entity[meta.versionProperty] == null))) {
|
|
282
289
|
return;
|
|
283
290
|
}
|
|
284
291
|
// skip entity references as they don't have version values loaded
|
|
@@ -287,7 +294,7 @@ export class ChangeSetPersister {
|
|
|
287
294
|
const cond = Utils.getPrimaryKeyCond(cs.originalEntity, meta.primaryKeys.concat(...meta.concurrencyCheckKeys));
|
|
288
295
|
if (meta.versionProperty) {
|
|
289
296
|
// @ts-ignore
|
|
290
|
-
cond[meta.versionProperty] = this.platform.
|
|
297
|
+
cond[meta.versionProperty] = this.platform.convertVersionValue(cs.entity[meta.versionProperty], meta.properties[meta.versionProperty]);
|
|
291
298
|
}
|
|
292
299
|
return cond;
|
|
293
300
|
});
|
|
@@ -344,9 +351,7 @@ export class ChangeSetPersister {
|
|
|
344
351
|
});
|
|
345
352
|
// reload generated columns
|
|
346
353
|
if (!this.usesReturningStatement) {
|
|
347
|
-
meta.props
|
|
348
|
-
.filter(prop => prop.generated && !prop.primary)
|
|
349
|
-
.forEach(prop => reloadProps.push(prop));
|
|
354
|
+
meta.props.filter(prop => prop.generated && !prop.primary).forEach(prop => reloadProps.push(prop));
|
|
350
355
|
reloadProps.push(...returning);
|
|
351
356
|
}
|
|
352
357
|
}
|
|
@@ -407,7 +412,7 @@ export class ChangeSetPersister {
|
|
|
407
412
|
return;
|
|
408
413
|
}
|
|
409
414
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && Array.isArray(value)) {
|
|
410
|
-
changeSet.payload[prop.name] = value.map(val => val instanceof EntityIdentifier ? val.getValue() : val);
|
|
415
|
+
changeSet.payload[prop.name] = value.map(val => (val instanceof EntityIdentifier ? val.getValue() : val));
|
|
411
416
|
return;
|
|
412
417
|
}
|
|
413
418
|
if (prop.name in changeSet.payload) {
|
|
@@ -78,11 +78,13 @@ export class CommitOrderCalculator {
|
|
|
78
78
|
for (const edge of node.dependencies.values()) {
|
|
79
79
|
const target = this.nodes.get(edge.to);
|
|
80
80
|
switch (target.state) {
|
|
81
|
-
case 2 /* NodeState.VISITED */:
|
|
81
|
+
case 2 /* NodeState.VISITED */:
|
|
82
|
+
break; // Do nothing, since node was already visited
|
|
82
83
|
case 1 /* NodeState.IN_PROGRESS */:
|
|
83
84
|
this.visitOpenNode(node, target, edge);
|
|
84
85
|
break;
|
|
85
|
-
case 0 /* NodeState.NOT_VISITED */:
|
|
86
|
+
case 0 /* NodeState.NOT_VISITED */:
|
|
87
|
+
this.visit(target);
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
if (node.state !== 2 /* NodeState.VISITED */) {
|
|
@@ -72,7 +72,13 @@ export declare class UnitOfWork {
|
|
|
72
72
|
getRemoveStack(): Set<AnyEntity>;
|
|
73
73
|
getChangeSets(): ChangeSet<AnyEntity>[];
|
|
74
74
|
getCollectionUpdates(): Collection<AnyEntity>[];
|
|
75
|
-
getExtraUpdates(): Set<[
|
|
75
|
+
getExtraUpdates(): Set<[
|
|
76
|
+
AnyEntity,
|
|
77
|
+
string | string[],
|
|
78
|
+
AnyEntity | AnyEntity[] | Reference<any> | Collection<any>,
|
|
79
|
+
ChangeSet<any> | undefined,
|
|
80
|
+
ChangeSetType
|
|
81
|
+
]>;
|
|
76
82
|
shouldAutoFlush<T extends object>(meta: EntityMetadata<T>): boolean;
|
|
77
83
|
clearActionsQueue(): void;
|
|
78
84
|
computeChangeSet<T extends object>(entity: T, type?: ChangeSetType): void;
|
|
@@ -76,7 +76,8 @@ export class UnitOfWork {
|
|
|
76
76
|
if (!prop) {
|
|
77
77
|
continue;
|
|
78
78
|
}
|
|
79
|
-
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
79
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
80
|
+
Utils.isPlainObject(data[prop.name])) {
|
|
80
81
|
// Skip polymorphic relations - they use PolymorphicRef wrapper
|
|
81
82
|
if (!prop.polymorphic) {
|
|
82
83
|
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
@@ -86,12 +87,16 @@ export class UnitOfWork {
|
|
|
86
87
|
for (const p of prop.targetMeta.props) {
|
|
87
88
|
/* v8 ignore next */
|
|
88
89
|
const prefix = prop.prefix === false ? '' : prop.prefix === true ? prop.name + '_' : prop.prefix;
|
|
89
|
-
data[prefix + p.name] = data[prop.name][p.name];
|
|
90
|
+
data[(prefix + p.name)] = data[prop.name][p.name];
|
|
90
91
|
}
|
|
91
92
|
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
92
93
|
}
|
|
93
94
|
if (prop.hydrate === false && prop.customType?.ensureComparable(meta, prop)) {
|
|
94
|
-
const converted = prop.customType.convertToJSValue(data[key], this.platform, {
|
|
95
|
+
const converted = prop.customType.convertToJSValue(data[key], this.platform, {
|
|
96
|
+
key,
|
|
97
|
+
mode: 'hydration',
|
|
98
|
+
force: true,
|
|
99
|
+
});
|
|
95
100
|
data[key] = prop.customType.convertToDatabaseValue(converted, this.platform, { key, mode: 'hydration' });
|
|
96
101
|
}
|
|
97
102
|
if (forceUndefined) {
|
|
@@ -423,7 +428,10 @@ export class UnitOfWork {
|
|
|
423
428
|
if (Utils.isCollection(rel)) {
|
|
424
429
|
rel.removeWithoutPropagation(entity);
|
|
425
430
|
}
|
|
426
|
-
else if (rel &&
|
|
431
|
+
else if (rel &&
|
|
432
|
+
(prop.mapToPk
|
|
433
|
+
? helper(this.em.getReference(prop.targetMeta.class, rel)).getSerializedPrimaryKey() === serializedPK
|
|
434
|
+
: rel === entity)) {
|
|
427
435
|
if (prop.formula) {
|
|
428
436
|
delete referrer[prop.name];
|
|
429
437
|
}
|
|
@@ -512,7 +520,13 @@ export class UnitOfWork {
|
|
|
512
520
|
if (!conflicts) {
|
|
513
521
|
return;
|
|
514
522
|
}
|
|
515
|
-
this.extraUpdates.add([
|
|
523
|
+
this.extraUpdates.add([
|
|
524
|
+
changeSet.entity,
|
|
525
|
+
props.map(p => p.name),
|
|
526
|
+
props.map(p => changeSet.entity[p.name]),
|
|
527
|
+
changeSet,
|
|
528
|
+
type,
|
|
529
|
+
]);
|
|
516
530
|
for (const p of props) {
|
|
517
531
|
delete changeSet.entity[p.name];
|
|
518
532
|
delete changeSet.payload[p.name];
|
|
@@ -633,7 +647,7 @@ export class UnitOfWork {
|
|
|
633
647
|
// when changing a unique nullable property (or a 1:1 relation), we can't do it in a single
|
|
634
648
|
// query as it would cause unique constraint violations
|
|
635
649
|
const uniqueProps = changeSet.meta.uniqueProps.filter(prop => {
|
|
636
|
-
return
|
|
650
|
+
return prop.nullable || changeSet.type !== ChangeSetType.CREATE;
|
|
637
651
|
});
|
|
638
652
|
this.scheduleExtraUpdate(changeSet, uniqueProps);
|
|
639
653
|
return changeSet.type === ChangeSetType.UPDATE && !Utils.hasObjectKeys(changeSet.payload);
|
|
@@ -643,25 +657,33 @@ export class UnitOfWork {
|
|
|
643
657
|
if (!wrapped.__meta.hasUniqueProps) {
|
|
644
658
|
return [];
|
|
645
659
|
}
|
|
646
|
-
const simpleUniqueHashes = wrapped.__meta.uniqueProps
|
|
660
|
+
const simpleUniqueHashes = wrapped.__meta.uniqueProps
|
|
661
|
+
.map(prop => {
|
|
647
662
|
if (entity[prop.name] != null) {
|
|
648
|
-
return prop.kind === ReferenceKind.SCALAR || prop.mapToPk
|
|
663
|
+
return prop.kind === ReferenceKind.SCALAR || prop.mapToPk
|
|
664
|
+
? entity[prop.name]
|
|
665
|
+
: helper(entity[prop.name]).getSerializedPrimaryKey();
|
|
649
666
|
}
|
|
650
667
|
if (wrapped.__originalEntityData?.[prop.name] != null) {
|
|
651
668
|
return Utils.getPrimaryKeyHash(Utils.asArray(wrapped.__originalEntityData[prop.name]));
|
|
652
669
|
}
|
|
653
670
|
return undefined;
|
|
654
|
-
})
|
|
655
|
-
|
|
671
|
+
})
|
|
672
|
+
.filter(i => i);
|
|
673
|
+
const compoundUniqueHashes = wrapped.__meta.uniques
|
|
674
|
+
.map(unique => {
|
|
656
675
|
const props = Utils.asArray(unique.properties);
|
|
657
676
|
if (props.every(prop => entity[prop] != null)) {
|
|
658
677
|
return Utils.getPrimaryKeyHash(props.map(p => {
|
|
659
678
|
const prop = wrapped.__meta.properties[p];
|
|
660
|
-
return prop.kind === ReferenceKind.SCALAR || prop.mapToPk
|
|
679
|
+
return prop.kind === ReferenceKind.SCALAR || prop.mapToPk
|
|
680
|
+
? entity[prop.name]
|
|
681
|
+
: helper(entity[prop.name]).getSerializedPrimaryKey();
|
|
661
682
|
}));
|
|
662
683
|
}
|
|
663
684
|
return undefined;
|
|
664
|
-
})
|
|
685
|
+
})
|
|
686
|
+
.filter(i => i);
|
|
665
687
|
return simpleUniqueHashes.concat(compoundUniqueHashes);
|
|
666
688
|
}
|
|
667
689
|
initIdentifier(entity) {
|
|
@@ -693,7 +715,8 @@ export class UnitOfWork {
|
|
|
693
715
|
return this.processToOneReference(kind, visited, processed, idx);
|
|
694
716
|
}
|
|
695
717
|
if (Utils.isCollection(kind)) {
|
|
696
|
-
kind
|
|
718
|
+
kind
|
|
719
|
+
.getItems(false)
|
|
697
720
|
.filter(item => !item.__helper.__originalEntityData)
|
|
698
721
|
.forEach(item => {
|
|
699
722
|
// propagate schema from parent
|
|
@@ -717,7 +740,8 @@ export class UnitOfWork {
|
|
|
717
740
|
parent[prop.name] = coll;
|
|
718
741
|
return;
|
|
719
742
|
}
|
|
720
|
-
collection
|
|
743
|
+
collection
|
|
744
|
+
.getItems(false)
|
|
721
745
|
.filter(item => !item.__helper.__originalEntityData)
|
|
722
746
|
.forEach(item => this.findNewEntities(item, visited, 0, processed));
|
|
723
747
|
}
|
|
@@ -809,7 +833,8 @@ export class UnitOfWork {
|
|
|
809
833
|
return filtered.some(items => processed.has(items));
|
|
810
834
|
}
|
|
811
835
|
shouldCascade(prop, type) {
|
|
812
|
-
if ([Cascade.REMOVE, Cascade.SCHEDULE_ORPHAN_REMOVAL, Cascade.CANCEL_ORPHAN_REMOVAL, Cascade.ALL].includes(type) &&
|
|
836
|
+
if ([Cascade.REMOVE, Cascade.SCHEDULE_ORPHAN_REMOVAL, Cascade.CANCEL_ORPHAN_REMOVAL, Cascade.ALL].includes(type) &&
|
|
837
|
+
prop.orphanRemoval) {
|
|
813
838
|
return true;
|
|
814
839
|
}
|
|
815
840
|
// ignore user settings for merge, it is kept only for back compatibility, this should have never been configurable
|
|
@@ -845,7 +870,9 @@ export class UnitOfWork {
|
|
|
845
870
|
const target = Reference.unwrapReference(reference);
|
|
846
871
|
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && target && !prop.mapToPk) {
|
|
847
872
|
if (!Utils.isEntity(target)) {
|
|
848
|
-
entity[prop.name] = this.em.getReference(prop.targetMeta.class, target, {
|
|
873
|
+
entity[prop.name] = this.em.getReference(prop.targetMeta.class, target, {
|
|
874
|
+
wrapped: !!prop.ref,
|
|
875
|
+
});
|
|
849
876
|
}
|
|
850
877
|
else if (!helper(target).__initialized && !helper(target).__em) {
|
|
851
878
|
const pk = helper(target).getPrimaryKey();
|
|
@@ -907,9 +934,9 @@ export class UnitOfWork {
|
|
|
907
934
|
return;
|
|
908
935
|
}
|
|
909
936
|
const props = changeSets[0].meta.root.relations.filter(prop => {
|
|
910
|
-
return (prop.kind === ReferenceKind.ONE_TO_ONE && prop.owner)
|
|
911
|
-
|
|
912
|
-
|
|
937
|
+
return ((prop.kind === ReferenceKind.ONE_TO_ONE && prop.owner) ||
|
|
938
|
+
prop.kind === ReferenceKind.MANY_TO_ONE ||
|
|
939
|
+
(prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner && !this.platform.usesPivotTable()));
|
|
913
940
|
});
|
|
914
941
|
for (const changeSet of changeSets) {
|
|
915
942
|
this.findExtraUpdates(changeSet, props);
|
|
@@ -984,7 +1011,8 @@ export class UnitOfWork {
|
|
|
984
1011
|
wrapped.__originalEntityData = this.comparator.prepareEntity(changeSet.entity);
|
|
985
1012
|
if (!wrapped.__initialized) {
|
|
986
1013
|
for (const prop of changeSet.meta.relations) {
|
|
987
|
-
if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) &&
|
|
1014
|
+
if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) &&
|
|
1015
|
+
changeSet.entity[prop.name] == null) {
|
|
988
1016
|
changeSet.entity[prop.name] = Collection.create(changeSet.entity, prop.name, undefined, wrapped.isInitialized());
|
|
989
1017
|
}
|
|
990
1018
|
}
|
|
@@ -1013,7 +1041,7 @@ export class UnitOfWork {
|
|
|
1013
1041
|
continue;
|
|
1014
1042
|
}
|
|
1015
1043
|
if (Array.isArray(extraUpdate[1])) {
|
|
1016
|
-
extraUpdate[1].forEach((p, i) => extraUpdate[0][p] = extraUpdate[2][i]);
|
|
1044
|
+
extraUpdate[1].forEach((p, i) => (extraUpdate[0][p] = extraUpdate[2][i]));
|
|
1017
1045
|
}
|
|
1018
1046
|
else {
|
|
1019
1047
|
extraUpdate[0][extraUpdate[1]] = extraUpdate[2];
|
|
@@ -1075,7 +1103,8 @@ export class UnitOfWork {
|
|
|
1075
1103
|
};
|
|
1076
1104
|
const addToGroup = (cs) => {
|
|
1077
1105
|
// Skip stub TPT changesets with empty payload (e.g. leaf with no own-property changes on UPDATE)
|
|
1078
|
-
if ((cs.type === ChangeSetType.UPDATE || cs.type === ChangeSetType.UPDATE_EARLY) &&
|
|
1106
|
+
if ((cs.type === ChangeSetType.UPDATE || cs.type === ChangeSetType.UPDATE_EARLY) &&
|
|
1107
|
+
!Utils.hasObjectKeys(cs.payload)) {
|
|
1079
1108
|
return;
|
|
1080
1109
|
}
|
|
1081
1110
|
const group = groups[cs.type];
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { Constructor, IMigrationGenerator, IMigrationRunner, IMigrator, IMigratorStorage, MaybePromise, Migration, MigrationInfo, MigrationRow, MigratorEvent } from '../typings.js';
|
|
2
|
+
import type { Transaction } from '../connections/Connection.js';
|
|
3
|
+
import type { Configuration, MigrationsOptions } from './Configuration.js';
|
|
4
|
+
import type { EntityManagerType, IDatabaseDriver } from '../drivers/IDatabaseDriver.js';
|
|
5
|
+
interface RunnableMigration {
|
|
6
|
+
name: string;
|
|
7
|
+
path?: string;
|
|
8
|
+
up: () => MaybePromise<void>;
|
|
9
|
+
down: () => MaybePromise<void>;
|
|
10
|
+
}
|
|
11
|
+
type MigrateOptions = {
|
|
12
|
+
from?: string | number;
|
|
13
|
+
to?: string | number;
|
|
14
|
+
migrations?: string[];
|
|
15
|
+
transaction?: Transaction;
|
|
16
|
+
};
|
|
17
|
+
export declare abstract class AbstractMigrator<D extends IDatabaseDriver> implements IMigrator {
|
|
18
|
+
protected readonly em: D[typeof EntityManagerType];
|
|
19
|
+
protected runner: IMigrationRunner;
|
|
20
|
+
protected storage: IMigratorStorage;
|
|
21
|
+
protected generator: IMigrationGenerator;
|
|
22
|
+
protected readonly driver: D;
|
|
23
|
+
protected readonly config: Configuration;
|
|
24
|
+
protected readonly options: MigrationsOptions;
|
|
25
|
+
protected absolutePath: string;
|
|
26
|
+
protected initialized: boolean;
|
|
27
|
+
private readonly listeners;
|
|
28
|
+
constructor(em: D[typeof EntityManagerType]);
|
|
29
|
+
protected abstract createRunner(): IMigrationRunner;
|
|
30
|
+
protected abstract createStorage(): IMigratorStorage;
|
|
31
|
+
protected abstract getDefaultGenerator(): IMigrationGenerator;
|
|
32
|
+
abstract create(path?: string, blank?: boolean, initial?: boolean, name?: string): Promise<{
|
|
33
|
+
fileName: string;
|
|
34
|
+
code: string;
|
|
35
|
+
diff: {
|
|
36
|
+
up: string[];
|
|
37
|
+
down: string[];
|
|
38
|
+
};
|
|
39
|
+
}>;
|
|
40
|
+
abstract checkSchema(): Promise<boolean>;
|
|
41
|
+
abstract createInitial(path?: string, name?: string, blank?: boolean): Promise<{
|
|
42
|
+
fileName: string;
|
|
43
|
+
code: string;
|
|
44
|
+
diff: {
|
|
45
|
+
up: string[];
|
|
46
|
+
down: string[];
|
|
47
|
+
};
|
|
48
|
+
}>;
|
|
49
|
+
/**
|
|
50
|
+
* @inheritDoc
|
|
51
|
+
*/
|
|
52
|
+
on(eventName: MigratorEvent, listener: (event: MigrationInfo) => MaybePromise<void>): this;
|
|
53
|
+
/**
|
|
54
|
+
* @inheritDoc
|
|
55
|
+
*/
|
|
56
|
+
off(eventName: MigratorEvent, listener: (event: MigrationInfo) => MaybePromise<void>): this;
|
|
57
|
+
/**
|
|
58
|
+
* @inheritDoc
|
|
59
|
+
*/
|
|
60
|
+
getExecuted(): Promise<MigrationRow[]>;
|
|
61
|
+
/**
|
|
62
|
+
* @inheritDoc
|
|
63
|
+
*/
|
|
64
|
+
getPending(): Promise<MigrationInfo[]>;
|
|
65
|
+
/**
|
|
66
|
+
* @inheritDoc
|
|
67
|
+
*/
|
|
68
|
+
up(options?: string | string[] | MigrateOptions): Promise<MigrationInfo[]>;
|
|
69
|
+
/**
|
|
70
|
+
* @inheritDoc
|
|
71
|
+
*/
|
|
72
|
+
down(options?: string | string[] | Omit<MigrateOptions, 'from'>): Promise<MigrationInfo[]>;
|
|
73
|
+
abstract getStorage(): IMigratorStorage;
|
|
74
|
+
protected init(): Promise<void>;
|
|
75
|
+
protected initServices(): void;
|
|
76
|
+
protected resolve(params: {
|
|
77
|
+
name: string;
|
|
78
|
+
path: string;
|
|
79
|
+
}): RunnableMigration;
|
|
80
|
+
protected initialize(MigrationClass: Constructor<Migration>, name: string): RunnableMigration;
|
|
81
|
+
/**
|
|
82
|
+
* Checks if `src` folder exists, it so, tries to adjust the migrations and seeders paths automatically to use it.
|
|
83
|
+
* If there is a `dist` or `build` folder, it will be used for the JS variant (`path` option), while the `src` folder will be
|
|
84
|
+
* used for the TS variant (`pathTs` option).
|
|
85
|
+
*
|
|
86
|
+
* If the default folder exists (e.g. `/migrations`), the config will respect that, so this auto-detection should not
|
|
87
|
+
* break existing projects, only help with the new ones.
|
|
88
|
+
*/
|
|
89
|
+
private detectSourceFolder;
|
|
90
|
+
private registerDefaultListeners;
|
|
91
|
+
private emit;
|
|
92
|
+
private discoverMigrations;
|
|
93
|
+
private executeMigrations;
|
|
94
|
+
private filterUp;
|
|
95
|
+
private filterDown;
|
|
96
|
+
private getMigrationFilename;
|
|
97
|
+
private prefix;
|
|
98
|
+
protected runMigrations(method: 'up' | 'down', options?: string | string[] | MigrateOptions): Promise<MigrationInfo[]>;
|
|
99
|
+
private runInTransaction;
|
|
100
|
+
}
|
|
101
|
+
export {};
|