@mikro-orm/core 7.0.0-dev.23 → 7.0.0-dev.230
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 +91 -59
- package/EntityManager.js +303 -251
- package/MikroORM.d.ts +44 -35
- package/MikroORM.js +109 -143
- package/README.md +2 -0
- package/cache/FileCacheAdapter.d.ts +1 -1
- package/cache/FileCacheAdapter.js +17 -8
- package/cache/GeneratedCacheAdapter.d.ts +0 -1
- package/cache/GeneratedCacheAdapter.js +0 -2
- package/cache/index.d.ts +0 -1
- package/cache/index.js +0 -1
- package/connections/Connection.d.ts +12 -5
- package/connections/Connection.js +21 -12
- package/drivers/DatabaseDriver.d.ts +25 -16
- package/drivers/DatabaseDriver.js +118 -35
- package/drivers/IDatabaseDriver.d.ts +42 -19
- package/entity/BaseEntity.d.ts +61 -2
- package/entity/BaseEntity.js +0 -3
- package/entity/Collection.d.ts +101 -29
- package/entity/Collection.js +436 -104
- package/entity/EntityAssigner.d.ts +1 -1
- package/entity/EntityAssigner.js +26 -18
- package/entity/EntityFactory.d.ts +7 -1
- package/entity/EntityFactory.js +83 -54
- package/entity/EntityHelper.d.ts +2 -2
- package/entity/EntityHelper.js +48 -15
- package/entity/EntityLoader.d.ts +7 -6
- package/entity/EntityLoader.js +215 -89
- package/entity/EntityRepository.d.ts +27 -7
- package/entity/EntityRepository.js +8 -2
- package/entity/PolymorphicRef.d.ts +12 -0
- package/entity/PolymorphicRef.js +18 -0
- package/entity/Reference.d.ts +1 -5
- package/entity/Reference.js +21 -12
- package/entity/WrappedEntity.d.ts +0 -5
- package/entity/WrappedEntity.js +2 -7
- package/entity/defineEntity.d.ts +380 -310
- package/entity/defineEntity.js +124 -273
- package/entity/index.d.ts +2 -2
- package/entity/index.js +2 -2
- package/entity/utils.js +1 -1
- package/entity/validators.d.ts +11 -0
- package/entity/validators.js +65 -0
- package/enums.d.ts +8 -6
- package/enums.js +2 -1
- package/errors.d.ts +20 -10
- package/errors.js +55 -23
- package/events/EventManager.d.ts +2 -1
- package/events/EventManager.js +19 -11
- package/hydration/Hydrator.js +1 -2
- package/hydration/ObjectHydrator.d.ts +4 -4
- package/hydration/ObjectHydrator.js +87 -35
- package/index.d.ts +2 -2
- package/index.js +1 -2
- package/logging/DefaultLogger.d.ts +1 -1
- package/logging/DefaultLogger.js +1 -0
- package/logging/SimpleLogger.d.ts +1 -1
- package/logging/colors.d.ts +1 -1
- package/logging/colors.js +7 -6
- package/logging/index.d.ts +1 -0
- package/logging/index.js +1 -0
- package/logging/inspect.d.ts +2 -0
- package/logging/inspect.js +11 -0
- package/metadata/EntitySchema.d.ts +47 -23
- package/metadata/EntitySchema.js +92 -33
- package/metadata/MetadataDiscovery.d.ts +64 -9
- package/metadata/MetadataDiscovery.js +778 -325
- package/metadata/MetadataProvider.d.ts +11 -2
- package/metadata/MetadataProvider.js +46 -2
- package/metadata/MetadataStorage.d.ts +13 -11
- package/metadata/MetadataStorage.js +70 -37
- package/metadata/MetadataValidator.d.ts +32 -9
- package/metadata/MetadataValidator.js +196 -41
- package/metadata/discover-entities.d.ts +5 -0
- package/metadata/discover-entities.js +40 -0
- package/metadata/index.d.ts +1 -1
- package/metadata/index.js +1 -1
- package/metadata/types.d.ts +526 -0
- package/metadata/types.js +1 -0
- package/naming-strategy/AbstractNamingStrategy.d.ts +16 -4
- package/naming-strategy/AbstractNamingStrategy.js +20 -2
- package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
- package/naming-strategy/EntityCaseNamingStrategy.js +6 -5
- package/naming-strategy/MongoNamingStrategy.d.ts +3 -3
- package/naming-strategy/MongoNamingStrategy.js +6 -6
- package/naming-strategy/NamingStrategy.d.ts +28 -4
- package/naming-strategy/UnderscoreNamingStrategy.d.ts +3 -3
- package/naming-strategy/UnderscoreNamingStrategy.js +6 -6
- package/not-supported.d.ts +2 -0
- package/not-supported.js +4 -0
- package/package.json +19 -11
- package/platforms/ExceptionConverter.js +1 -1
- package/platforms/Platform.d.ts +7 -14
- package/platforms/Platform.js +20 -43
- package/serialization/EntitySerializer.d.ts +5 -0
- package/serialization/EntitySerializer.js +47 -27
- package/serialization/EntityTransformer.js +28 -18
- package/serialization/SerializationContext.d.ts +6 -6
- package/serialization/SerializationContext.js +3 -3
- package/types/ArrayType.d.ts +1 -1
- package/types/ArrayType.js +2 -3
- package/types/BigIntType.d.ts +8 -6
- package/types/BigIntType.js +1 -1
- package/types/BlobType.d.ts +0 -1
- package/types/BlobType.js +0 -3
- package/types/BooleanType.d.ts +1 -0
- package/types/BooleanType.js +3 -0
- package/types/DecimalType.d.ts +6 -4
- package/types/DecimalType.js +2 -2
- package/types/DoubleType.js +1 -1
- package/types/EnumArrayType.js +1 -2
- package/types/JsonType.d.ts +1 -1
- package/types/JsonType.js +7 -2
- package/types/TinyIntType.js +1 -1
- package/types/Type.d.ts +2 -4
- package/types/Type.js +3 -3
- package/types/Uint8ArrayType.d.ts +0 -1
- package/types/Uint8ArrayType.js +1 -4
- package/types/index.d.ts +1 -1
- package/typings.d.ts +381 -171
- package/typings.js +97 -44
- package/unit-of-work/ChangeSet.d.ts +4 -6
- package/unit-of-work/ChangeSet.js +4 -5
- package/unit-of-work/ChangeSetComputer.d.ts +1 -3
- package/unit-of-work/ChangeSetComputer.js +35 -14
- package/unit-of-work/ChangeSetPersister.d.ts +7 -3
- package/unit-of-work/ChangeSetPersister.js +83 -25
- package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
- package/unit-of-work/CommitOrderCalculator.js +13 -13
- package/unit-of-work/IdentityMap.d.ts +12 -0
- package/unit-of-work/IdentityMap.js +39 -1
- package/unit-of-work/UnitOfWork.d.ts +27 -3
- package/unit-of-work/UnitOfWork.js +258 -92
- package/utils/AbstractSchemaGenerator.d.ts +5 -5
- package/utils/AbstractSchemaGenerator.js +28 -17
- package/utils/AsyncContext.d.ts +6 -0
- package/utils/AsyncContext.js +42 -0
- package/utils/Configuration.d.ts +795 -209
- package/utils/Configuration.js +150 -192
- package/utils/ConfigurationLoader.d.ts +1 -54
- package/utils/ConfigurationLoader.js +1 -352
- package/utils/Cursor.d.ts +0 -3
- package/utils/Cursor.js +24 -11
- package/utils/DataloaderUtils.d.ts +10 -5
- package/utils/DataloaderUtils.js +29 -12
- package/utils/EntityComparator.d.ts +16 -9
- package/utils/EntityComparator.js +158 -58
- package/utils/QueryHelper.d.ts +18 -6
- package/utils/QueryHelper.js +76 -23
- package/utils/RawQueryFragment.d.ts +28 -34
- package/utils/RawQueryFragment.js +35 -71
- package/utils/RequestContext.js +2 -2
- package/utils/TransactionContext.js +2 -2
- package/utils/TransactionManager.js +28 -4
- package/utils/Utils.d.ts +14 -127
- package/utils/Utils.js +85 -397
- package/utils/clone.js +8 -23
- package/utils/env-vars.d.ts +7 -0
- package/utils/env-vars.js +97 -0
- package/utils/fs-utils.d.ts +33 -0
- package/utils/fs-utils.js +192 -0
- package/utils/index.d.ts +1 -1
- package/utils/index.js +1 -1
- package/utils/upsert-utils.d.ts +9 -4
- package/utils/upsert-utils.js +46 -3
- package/decorators/Check.d.ts +0 -3
- package/decorators/Check.js +0 -13
- package/decorators/CreateRequestContext.d.ts +0 -3
- package/decorators/CreateRequestContext.js +0 -32
- package/decorators/Embeddable.d.ts +0 -8
- package/decorators/Embeddable.js +0 -11
- package/decorators/Embedded.d.ts +0 -12
- package/decorators/Embedded.js +0 -18
- package/decorators/Entity.d.ts +0 -33
- package/decorators/Entity.js +0 -12
- package/decorators/Enum.d.ts +0 -9
- package/decorators/Enum.js +0 -16
- package/decorators/Filter.d.ts +0 -2
- package/decorators/Filter.js +0 -8
- package/decorators/Formula.d.ts +0 -4
- package/decorators/Formula.js +0 -15
- package/decorators/Indexed.d.ts +0 -19
- package/decorators/Indexed.js +0 -20
- package/decorators/ManyToMany.d.ts +0 -42
- package/decorators/ManyToMany.js +0 -14
- package/decorators/ManyToOne.d.ts +0 -34
- package/decorators/ManyToOne.js +0 -14
- package/decorators/OneToMany.d.ts +0 -28
- package/decorators/OneToMany.js +0 -17
- package/decorators/OneToOne.d.ts +0 -28
- package/decorators/OneToOne.js +0 -7
- package/decorators/PrimaryKey.d.ts +0 -8
- package/decorators/PrimaryKey.js +0 -20
- package/decorators/Property.d.ts +0 -250
- package/decorators/Property.js +0 -32
- package/decorators/Transactional.d.ts +0 -14
- package/decorators/Transactional.js +0 -28
- package/decorators/hooks.d.ts +0 -16
- package/decorators/hooks.js +0 -47
- package/decorators/index.d.ts +0 -17
- package/decorators/index.js +0 -17
- package/entity/ArrayCollection.d.ts +0 -118
- package/entity/ArrayCollection.js +0 -407
- package/entity/EntityValidator.d.ts +0 -19
- package/entity/EntityValidator.js +0 -150
- package/metadata/ReflectMetadataProvider.d.ts +0 -8
- package/metadata/ReflectMetadataProvider.js +0 -44
- package/utils/resolveContextProvider.d.ts +0 -10
- package/utils/resolveContextProvider.js +0 -28
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
1
|
import { Collection } from '../entity/Collection.js';
|
|
3
2
|
import { EntityHelper } from '../entity/EntityHelper.js';
|
|
4
3
|
import { helper } from '../entity/wrap.js';
|
|
@@ -13,8 +12,9 @@ import { Cascade, DeferMode, EventType, LockMode, ReferenceKind } from '../enums
|
|
|
13
12
|
import { OptimisticLockError, ValidationError } from '../errors.js';
|
|
14
13
|
import { TransactionEventBroadcaster } from '../events/TransactionEventBroadcaster.js';
|
|
15
14
|
import { IdentityMap } from './IdentityMap.js';
|
|
15
|
+
import { createAsyncContext } from '../utils/AsyncContext.js';
|
|
16
16
|
// to deal with validation for flush inside flush hooks and `Promise.all`
|
|
17
|
-
const insideFlush =
|
|
17
|
+
const insideFlush = createAsyncContext();
|
|
18
18
|
export class UnitOfWork {
|
|
19
19
|
em;
|
|
20
20
|
/** map of references to managed entities */
|
|
@@ -42,8 +42,8 @@ export class UnitOfWork {
|
|
|
42
42
|
this.identityMap = new IdentityMap(this.platform.getDefaultSchemaName());
|
|
43
43
|
this.eventManager = this.em.getEventManager();
|
|
44
44
|
this.comparator = this.em.getComparator();
|
|
45
|
-
this.changeSetComputer = new ChangeSetComputer(this.
|
|
46
|
-
this.changeSetPersister = new ChangeSetPersister(this.em.getDriver(), this.metadata, this.em.config.getHydrator(this.metadata), this.em.getEntityFactory(), this.em.
|
|
45
|
+
this.changeSetComputer = new ChangeSetComputer(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.config, this.em);
|
|
47
47
|
}
|
|
48
48
|
merge(entity, visited) {
|
|
49
49
|
const wrapped = helper(entity);
|
|
@@ -61,10 +61,46 @@ export class UnitOfWork {
|
|
|
61
61
|
// as there can be some entity with already changed state that is not yet flushed
|
|
62
62
|
if (wrapped.__initialized && (!visited || !wrapped.__originalEntityData)) {
|
|
63
63
|
wrapped.__originalEntityData = this.comparator.prepareEntity(entity);
|
|
64
|
-
wrapped.__touched = false;
|
|
65
64
|
}
|
|
66
65
|
this.cascade(entity, Cascade.MERGE, visited ?? new Set());
|
|
67
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Entity data can wary in its shape, e.g. we might get a deep relation graph with joined strategy, but for diffing,
|
|
69
|
+
* we need to normalize the shape, so relation values are only raw FKs. This method handles that.
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
normalizeEntityData(meta, data) {
|
|
73
|
+
const forceUndefined = this.em.config.get('forceUndefined');
|
|
74
|
+
for (const key of Utils.keys(data)) {
|
|
75
|
+
const prop = meta.properties[key];
|
|
76
|
+
if (!prop) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(data[prop.name])) {
|
|
80
|
+
// Skip polymorphic relations - they use PolymorphicRef wrapper
|
|
81
|
+
if (!prop.polymorphic) {
|
|
82
|
+
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else if (prop.kind === ReferenceKind.EMBEDDED && !prop.object && Utils.isPlainObject(data[prop.name])) {
|
|
86
|
+
for (const p of prop.targetMeta.props) {
|
|
87
|
+
/* v8 ignore next */
|
|
88
|
+
const prefix = prop.prefix === false ? '' : prop.prefix === true ? prop.name + '_' : prop.prefix;
|
|
89
|
+
data[prefix + p.name] = data[prop.name][p.name];
|
|
90
|
+
}
|
|
91
|
+
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
92
|
+
}
|
|
93
|
+
if (prop.hydrate === false && prop.customType?.ensureComparable(meta, prop)) {
|
|
94
|
+
const converted = prop.customType.convertToJSValue(data[key], this.platform, { key, mode: 'hydration', force: true });
|
|
95
|
+
data[key] = prop.customType.convertToDatabaseValue(converted, this.platform, { key, mode: 'hydration' });
|
|
96
|
+
}
|
|
97
|
+
if (forceUndefined) {
|
|
98
|
+
if (data[key] === null) {
|
|
99
|
+
data[key] = undefined;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
68
104
|
/**
|
|
69
105
|
* @internal
|
|
70
106
|
*/
|
|
@@ -82,31 +118,14 @@ export class UnitOfWork {
|
|
|
82
118
|
wrapped.__em ??= this.em;
|
|
83
119
|
wrapped.__managed = true;
|
|
84
120
|
if (data && (options?.refresh || !wrapped.__originalEntityData)) {
|
|
121
|
+
this.normalizeEntityData(wrapped.__meta, data);
|
|
85
122
|
for (const key of Utils.keys(data)) {
|
|
86
123
|
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, 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, true);
|
|
101
|
-
}
|
|
102
|
-
if (forceUndefined) {
|
|
103
|
-
if (data[key] === null) {
|
|
104
|
-
data[key] = undefined;
|
|
105
|
-
}
|
|
124
|
+
if (prop) {
|
|
125
|
+
wrapped.__loadedProperties.add(key);
|
|
106
126
|
}
|
|
107
127
|
}
|
|
108
128
|
wrapped.__originalEntityData = data;
|
|
109
|
-
wrapped.__touched = false;
|
|
110
129
|
}
|
|
111
130
|
return entity;
|
|
112
131
|
}
|
|
@@ -153,6 +172,40 @@ export class UnitOfWork {
|
|
|
153
172
|
}
|
|
154
173
|
return this.identityMap.getByHash(meta, hash);
|
|
155
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Returns entity from the identity map by an alternate key (non-PK property).
|
|
177
|
+
* @param convertCustomTypes - If true, the value is in database format and will be converted to JS format for lookup.
|
|
178
|
+
* If false (default), the value is assumed to be in JS format already.
|
|
179
|
+
*/
|
|
180
|
+
getByKey(entityName, key, value, schema, convertCustomTypes) {
|
|
181
|
+
const meta = this.metadata.find(entityName).root;
|
|
182
|
+
schema ??= meta.schema ?? this.em.config.getSchema();
|
|
183
|
+
const prop = meta.properties[key];
|
|
184
|
+
// Convert from DB format to JS format if needed
|
|
185
|
+
if (convertCustomTypes && prop?.customType) {
|
|
186
|
+
value = prop.customType.convertToJSValue(value, this.platform, { mode: 'hydration' });
|
|
187
|
+
}
|
|
188
|
+
const hash = this.identityMap.getKeyHash(key, '' + value, schema);
|
|
189
|
+
return this.identityMap.getByHash(meta, hash);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Stores an entity in the identity map under an alternate key (non-PK property).
|
|
193
|
+
* Also sets the property value on the entity.
|
|
194
|
+
* @param convertCustomTypes - If true, the value is in database format and will be converted to JS format.
|
|
195
|
+
* If false (default), the value is assumed to be in JS format already.
|
|
196
|
+
*/
|
|
197
|
+
storeByKey(entity, key, value, schema, convertCustomTypes) {
|
|
198
|
+
const meta = entity.__meta.root;
|
|
199
|
+
schema ??= meta.schema ?? this.em.config.getSchema();
|
|
200
|
+
const prop = meta.properties[key];
|
|
201
|
+
// Convert from DB format to JS format if needed
|
|
202
|
+
if (convertCustomTypes && prop?.customType) {
|
|
203
|
+
value = prop.customType.convertToJSValue(value, this.platform, { mode: 'hydration' });
|
|
204
|
+
}
|
|
205
|
+
// Set the property on the entity
|
|
206
|
+
entity[key] = value;
|
|
207
|
+
this.identityMap.storeByKey(entity, key, '' + value, schema);
|
|
208
|
+
}
|
|
156
209
|
tryGetById(entityName, where, schema, strict = true) {
|
|
157
210
|
const pk = Utils.extractPK(where, this.metadata.find(entityName), strict);
|
|
158
211
|
if (!pk) {
|
|
@@ -191,13 +244,11 @@ export class UnitOfWork {
|
|
|
191
244
|
if (insideFlush.getStore()) {
|
|
192
245
|
return false;
|
|
193
246
|
}
|
|
194
|
-
if (this.queuedActions.has(meta.
|
|
247
|
+
if (this.queuedActions.has(meta.class) || this.queuedActions.has(meta.root.class)) {
|
|
195
248
|
return true;
|
|
196
249
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return true;
|
|
200
|
-
}
|
|
250
|
+
if (meta.discriminatorMap && Object.values(meta.discriminatorMap).some(v => this.queuedActions.has(v))) {
|
|
251
|
+
return true;
|
|
201
252
|
}
|
|
202
253
|
return false;
|
|
203
254
|
}
|
|
@@ -206,7 +257,7 @@ export class UnitOfWork {
|
|
|
206
257
|
}
|
|
207
258
|
computeChangeSet(entity, type) {
|
|
208
259
|
const wrapped = helper(entity);
|
|
209
|
-
if (type) {
|
|
260
|
+
if (type === ChangeSetType.DELETE || type === ChangeSetType.DELETE_EARLY) {
|
|
210
261
|
this.changeSets.set(entity, new ChangeSet(entity, type, {}, wrapped.__meta));
|
|
211
262
|
return;
|
|
212
263
|
}
|
|
@@ -214,11 +265,14 @@ export class UnitOfWork {
|
|
|
214
265
|
if (!cs || this.checkUniqueProps(cs)) {
|
|
215
266
|
return;
|
|
216
267
|
}
|
|
268
|
+
/* v8 ignore next */
|
|
269
|
+
if (type) {
|
|
270
|
+
cs.type = type;
|
|
271
|
+
}
|
|
217
272
|
this.initIdentifier(entity);
|
|
218
273
|
this.changeSets.set(entity, cs);
|
|
219
274
|
this.persistStack.delete(entity);
|
|
220
275
|
wrapped.__originalEntityData = this.comparator.prepareEntity(entity);
|
|
221
|
-
wrapped.__touched = false;
|
|
222
276
|
}
|
|
223
277
|
recomputeSingleChangeSet(entity) {
|
|
224
278
|
const changeSet = this.changeSets.get(entity);
|
|
@@ -229,7 +283,6 @@ export class UnitOfWork {
|
|
|
229
283
|
if (cs && !this.checkUniqueProps(cs)) {
|
|
230
284
|
Object.assign(changeSet.payload, cs.payload);
|
|
231
285
|
helper(entity).__originalEntityData = this.comparator.prepareEntity(entity);
|
|
232
|
-
helper(entity).__touched = false;
|
|
233
286
|
}
|
|
234
287
|
}
|
|
235
288
|
persist(entity, visited, options = {}) {
|
|
@@ -239,7 +292,7 @@ export class UnitOfWork {
|
|
|
239
292
|
}
|
|
240
293
|
const wrapped = helper(entity);
|
|
241
294
|
this.persistStack.add(entity);
|
|
242
|
-
this.queuedActions.add(wrapped.__meta.
|
|
295
|
+
this.queuedActions.add(wrapped.__meta.class);
|
|
243
296
|
this.removeStack.delete(entity);
|
|
244
297
|
if (!wrapped.__managed && wrapped.hasPrimaryKey()) {
|
|
245
298
|
this.identityMap.store(entity);
|
|
@@ -252,7 +305,7 @@ export class UnitOfWork {
|
|
|
252
305
|
// allow removing not managed entities if they are not part of the persist stack
|
|
253
306
|
if (helper(entity).__managed || !this.persistStack.has(entity)) {
|
|
254
307
|
this.removeStack.add(entity);
|
|
255
|
-
this.queuedActions.add(helper(entity).__meta.
|
|
308
|
+
this.queuedActions.add(helper(entity).__meta.class);
|
|
256
309
|
}
|
|
257
310
|
else {
|
|
258
311
|
this.persistStack.delete(entity);
|
|
@@ -315,7 +368,8 @@ export class UnitOfWork {
|
|
|
315
368
|
this.filterCollectionUpdates();
|
|
316
369
|
// nothing to do, do not start transaction
|
|
317
370
|
if (this.changeSets.size === 0 && this.collectionUpdates.size === 0 && this.extraUpdates.size === 0) {
|
|
318
|
-
|
|
371
|
+
await this.eventManager.dispatchEvent(EventType.afterFlush, { em: this.em, uow: this });
|
|
372
|
+
return;
|
|
319
373
|
}
|
|
320
374
|
const groups = this.getChangeSetGroups();
|
|
321
375
|
const platform = this.em.getPlatform();
|
|
@@ -342,10 +396,10 @@ export class UnitOfWork {
|
|
|
342
396
|
}
|
|
343
397
|
}
|
|
344
398
|
async lock(entity, options) {
|
|
345
|
-
if (!this.getById(entity.constructor
|
|
399
|
+
if (!this.getById(entity.constructor, helper(entity).__primaryKeys, helper(entity).__schema)) {
|
|
346
400
|
throw ValidationError.entityNotManaged(entity);
|
|
347
401
|
}
|
|
348
|
-
const meta = this.metadata.find(entity.constructor
|
|
402
|
+
const meta = this.metadata.find(entity.constructor);
|
|
349
403
|
if (options.lockMode === LockMode.OPTIMISTIC) {
|
|
350
404
|
await this.lockOptimistic(entity, meta, options.lockVersion);
|
|
351
405
|
}
|
|
@@ -369,7 +423,7 @@ export class UnitOfWork {
|
|
|
369
423
|
if (Utils.isCollection(rel)) {
|
|
370
424
|
rel.removeWithoutPropagation(entity);
|
|
371
425
|
}
|
|
372
|
-
else if (rel && (prop.mapToPk ? helper(this.em.getReference(prop.
|
|
426
|
+
else if (rel && (prop.mapToPk ? helper(this.em.getReference(prop.targetMeta.class, rel)).getSerializedPrimaryKey() === serializedPK : rel === entity)) {
|
|
373
427
|
if (prop.formula) {
|
|
374
428
|
delete referrer[prop.name];
|
|
375
429
|
}
|
|
@@ -381,7 +435,6 @@ export class UnitOfWork {
|
|
|
381
435
|
}
|
|
382
436
|
delete wrapped.__identifier;
|
|
383
437
|
delete wrapped.__originalEntityData;
|
|
384
|
-
wrapped.__touched = false;
|
|
385
438
|
wrapped.__managed = false;
|
|
386
439
|
}
|
|
387
440
|
computeChangeSets() {
|
|
@@ -391,14 +444,14 @@ export class UnitOfWork {
|
|
|
391
444
|
this.cascade(entity, Cascade.REMOVE, visited);
|
|
392
445
|
}
|
|
393
446
|
visited.clear();
|
|
394
|
-
for (const entity of this.persistStack) {
|
|
395
|
-
this.cascade(entity, Cascade.PERSIST, visited, { checkRemoveStack: true });
|
|
396
|
-
}
|
|
397
447
|
for (const entity of this.identityMap) {
|
|
398
448
|
if (!this.removeStack.has(entity) && !this.persistStack.has(entity) && !this.orphanRemoveStack.has(entity)) {
|
|
399
449
|
this.cascade(entity, Cascade.PERSIST, visited, { checkRemoveStack: true });
|
|
400
450
|
}
|
|
401
451
|
}
|
|
452
|
+
for (const entity of this.persistStack) {
|
|
453
|
+
this.cascade(entity, Cascade.PERSIST, visited, { checkRemoveStack: true });
|
|
454
|
+
}
|
|
402
455
|
visited.clear();
|
|
403
456
|
for (const entity of this.persistStack) {
|
|
404
457
|
this.findNewEntities(entity, visited);
|
|
@@ -412,24 +465,24 @@ export class UnitOfWork {
|
|
|
412
465
|
const inserts = {};
|
|
413
466
|
for (const cs of this.changeSets.values()) {
|
|
414
467
|
if (cs.type === ChangeSetType.CREATE) {
|
|
415
|
-
inserts[cs.meta.
|
|
416
|
-
inserts[cs.meta.
|
|
468
|
+
inserts[cs.meta.uniqueName] ??= [];
|
|
469
|
+
inserts[cs.meta.uniqueName].push(cs);
|
|
417
470
|
}
|
|
418
471
|
}
|
|
419
472
|
for (const cs of this.changeSets.values()) {
|
|
420
473
|
if (cs.type === ChangeSetType.UPDATE) {
|
|
421
|
-
this.findEarlyUpdates(cs, inserts[cs.meta.
|
|
474
|
+
this.findEarlyUpdates(cs, inserts[cs.meta.uniqueName]);
|
|
422
475
|
}
|
|
423
476
|
}
|
|
424
477
|
for (const entity of this.removeStack) {
|
|
425
478
|
const wrapped = helper(entity);
|
|
426
|
-
/* v8 ignore next
|
|
479
|
+
/* v8 ignore next */
|
|
427
480
|
if (wrapped.__processing) {
|
|
428
481
|
continue;
|
|
429
482
|
}
|
|
430
483
|
const deletePkHash = [wrapped.getSerializedPrimaryKey(), ...this.expandUniqueProps(entity)];
|
|
431
484
|
let type = ChangeSetType.DELETE;
|
|
432
|
-
for (const cs of inserts[wrapped.__meta.
|
|
485
|
+
for (const cs of inserts[wrapped.__meta.uniqueName] ?? []) {
|
|
433
486
|
if (deletePkHash.some(hash => hash === cs.getSerializedPrimaryKey() || this.expandUniqueProps(cs.entity).find(child => hash === child))) {
|
|
434
487
|
type = ChangeSetType.DELETE_EARLY;
|
|
435
488
|
}
|
|
@@ -448,7 +501,7 @@ export class UnitOfWork {
|
|
|
448
501
|
}
|
|
449
502
|
for (const cs of this.changeSets.values()) {
|
|
450
503
|
for (const prop of props) {
|
|
451
|
-
if (prop.name in cs.payload && cs.
|
|
504
|
+
if (prop.name in cs.payload && cs.rootMeta === changeSet.rootMeta && cs.type === changeSet.type) {
|
|
452
505
|
conflicts = true;
|
|
453
506
|
if (changeSet.payload[prop.name] == null) {
|
|
454
507
|
type = ChangeSetType.UPDATE_EARLY;
|
|
@@ -467,9 +520,10 @@ export class UnitOfWork {
|
|
|
467
520
|
}
|
|
468
521
|
scheduleOrphanRemoval(entity, visited) {
|
|
469
522
|
if (entity) {
|
|
470
|
-
helper(entity)
|
|
523
|
+
const wrapped = helper(entity);
|
|
524
|
+
wrapped.__em = this.em;
|
|
471
525
|
this.orphanRemoveStack.add(entity);
|
|
472
|
-
this.queuedActions.add(
|
|
526
|
+
this.queuedActions.add(wrapped.__meta.class);
|
|
473
527
|
this.cascade(entity, Cascade.SCHEDULE_ORPHAN_REMOVAL, visited);
|
|
474
528
|
}
|
|
475
529
|
}
|
|
@@ -505,7 +559,68 @@ export class UnitOfWork {
|
|
|
505
559
|
}
|
|
506
560
|
const changeSet = this.changeSetComputer.computeChangeSet(entity);
|
|
507
561
|
if (changeSet && !this.checkUniqueProps(changeSet)) {
|
|
508
|
-
|
|
562
|
+
// For TPT child entities, create changesets for each table in hierarchy
|
|
563
|
+
if (wrapped.__meta.inheritanceType === 'tpt' && wrapped.__meta.tptParent) {
|
|
564
|
+
this.createTPTChangeSets(entity, changeSet);
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
this.changeSets.set(entity, changeSet);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* For TPT inheritance, creates separate changesets for each table in the hierarchy.
|
|
573
|
+
* Uses the same entity instance for all changesets - only the metadata and payload differ.
|
|
574
|
+
*/
|
|
575
|
+
createTPTChangeSets(entity, originalChangeSet) {
|
|
576
|
+
const meta = helper(entity).__meta;
|
|
577
|
+
const isCreate = originalChangeSet.type === ChangeSetType.CREATE;
|
|
578
|
+
let current = meta;
|
|
579
|
+
let leafCs;
|
|
580
|
+
const parentChangeSets = [];
|
|
581
|
+
while (current) {
|
|
582
|
+
const isRoot = !current.tptParent;
|
|
583
|
+
const payload = {};
|
|
584
|
+
for (const prop of current.ownProps) {
|
|
585
|
+
if (prop.name in originalChangeSet.payload) {
|
|
586
|
+
payload[prop.name] = originalChangeSet.payload[prop.name];
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
// For CREATE on non-root tables, include the PK (EntityIdentifier for deferred resolution)
|
|
590
|
+
if (isCreate && !isRoot) {
|
|
591
|
+
const wrapped = helper(entity);
|
|
592
|
+
const identifier = wrapped.__identifier;
|
|
593
|
+
const identifiers = Array.isArray(identifier) ? identifier : [identifier];
|
|
594
|
+
for (let i = 0; i < current.primaryKeys.length; i++) {
|
|
595
|
+
const pk = current.primaryKeys[i];
|
|
596
|
+
payload[pk] = identifiers[i] ?? originalChangeSet.payload[pk];
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
if (!isCreate && Object.keys(payload).length === 0) {
|
|
600
|
+
current = current.tptParent;
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
603
|
+
const cs = new ChangeSet(entity, originalChangeSet.type, payload, current);
|
|
604
|
+
if (current === meta) {
|
|
605
|
+
cs.originalEntity = originalChangeSet.originalEntity;
|
|
606
|
+
leafCs = cs;
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
parentChangeSets.push(cs);
|
|
610
|
+
}
|
|
611
|
+
current = current.tptParent;
|
|
612
|
+
}
|
|
613
|
+
// When only parent properties changed (UPDATE), leaf payload is empty—create a stub anchor
|
|
614
|
+
if (!leafCs && parentChangeSets.length > 0) {
|
|
615
|
+
leafCs = new ChangeSet(entity, originalChangeSet.type, {}, meta);
|
|
616
|
+
leafCs.originalEntity = originalChangeSet.originalEntity;
|
|
617
|
+
}
|
|
618
|
+
// Store the leaf changeset in the main map (entity as key), with parent CSs attached
|
|
619
|
+
if (leafCs) {
|
|
620
|
+
if (parentChangeSets.length > 0) {
|
|
621
|
+
leafCs.tptChangeSets = parentChangeSets;
|
|
622
|
+
}
|
|
623
|
+
this.changeSets.set(entity, leafCs);
|
|
509
624
|
}
|
|
510
625
|
}
|
|
511
626
|
/**
|
|
@@ -618,7 +733,7 @@ export class UnitOfWork {
|
|
|
618
733
|
const copy = this.comparator.prepareEntity(changeSet.entity);
|
|
619
734
|
await this.eventManager.dispatchEvent(type, { entity: changeSet.entity, meta, em: this.em, changeSet });
|
|
620
735
|
const current = this.comparator.prepareEntity(changeSet.entity);
|
|
621
|
-
const diff = this.comparator.diffEntities(changeSet.
|
|
736
|
+
const diff = this.comparator.diffEntities(changeSet.meta.class, copy, current);
|
|
622
737
|
Object.assign(changeSet.payload, diff);
|
|
623
738
|
const wrapped = helper(changeSet.entity);
|
|
624
739
|
if (wrapped.__identifier) {
|
|
@@ -713,7 +828,7 @@ export class UnitOfWork {
|
|
|
713
828
|
if (!meta.versionProperty) {
|
|
714
829
|
throw OptimisticLockError.notVersioned(meta);
|
|
715
830
|
}
|
|
716
|
-
if (
|
|
831
|
+
if (typeof version === 'undefined') {
|
|
717
832
|
return;
|
|
718
833
|
}
|
|
719
834
|
const wrapped = helper(entity);
|
|
@@ -727,26 +842,26 @@ export class UnitOfWork {
|
|
|
727
842
|
}
|
|
728
843
|
fixMissingReference(entity, prop) {
|
|
729
844
|
const reference = entity[prop.name];
|
|
730
|
-
const
|
|
731
|
-
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
732
|
-
if (!Utils.isEntity(
|
|
733
|
-
entity[prop.name] = this.em.getReference(prop.
|
|
845
|
+
const target = Reference.unwrapReference(reference);
|
|
846
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && target && !prop.mapToPk) {
|
|
847
|
+
if (!Utils.isEntity(target)) {
|
|
848
|
+
entity[prop.name] = this.em.getReference(prop.targetMeta.class, target, { wrapped: !!prop.ref });
|
|
734
849
|
}
|
|
735
|
-
else if (!helper(
|
|
736
|
-
const pk = helper(
|
|
737
|
-
entity[prop.name] = this.em.getReference(prop.
|
|
850
|
+
else if (!helper(target).__initialized && !helper(target).__em) {
|
|
851
|
+
const pk = helper(target).getPrimaryKey();
|
|
852
|
+
entity[prop.name] = this.em.getReference(prop.targetMeta.class, pk, { wrapped: !!prop.ref });
|
|
738
853
|
}
|
|
739
854
|
}
|
|
740
|
-
// perf: set the `Collection._property` to skip the getter, as it can be slow when there
|
|
741
|
-
if (Utils.isCollection(
|
|
742
|
-
|
|
855
|
+
// perf: set the `Collection._property` to skip the getter, as it can be slow when there are a lot of relations
|
|
856
|
+
if (Utils.isCollection(target)) {
|
|
857
|
+
target.property = prop;
|
|
743
858
|
}
|
|
744
859
|
const isCollection = [ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind);
|
|
745
|
-
if (isCollection && Array.isArray(
|
|
860
|
+
if (isCollection && Array.isArray(target)) {
|
|
746
861
|
const collection = new Collection(entity);
|
|
747
862
|
collection.property = prop;
|
|
748
863
|
entity[prop.name] = collection;
|
|
749
|
-
collection.set(
|
|
864
|
+
collection.set(target);
|
|
750
865
|
}
|
|
751
866
|
}
|
|
752
867
|
async persistToDatabase(groups, ctx) {
|
|
@@ -756,30 +871,30 @@ export class UnitOfWork {
|
|
|
756
871
|
const commitOrder = this.getCommitOrder();
|
|
757
872
|
const commitOrderReversed = [...commitOrder].reverse();
|
|
758
873
|
// early delete - when we recreate entity in the same UoW, we need to issue those delete queries before inserts
|
|
759
|
-
for (const
|
|
760
|
-
await this.commitDeleteChangeSets(groups[ChangeSetType.DELETE_EARLY].get(
|
|
874
|
+
for (const meta of commitOrderReversed) {
|
|
875
|
+
await this.commitDeleteChangeSets(groups[ChangeSetType.DELETE_EARLY].get(meta) ?? [], ctx);
|
|
761
876
|
}
|
|
762
877
|
// early update - when we recreate entity in the same UoW, we need to issue those delete queries before inserts
|
|
763
|
-
for (const
|
|
764
|
-
await this.commitUpdateChangeSets(groups[ChangeSetType.UPDATE_EARLY].get(
|
|
878
|
+
for (const meta of commitOrder) {
|
|
879
|
+
await this.commitUpdateChangeSets(groups[ChangeSetType.UPDATE_EARLY].get(meta) ?? [], ctx);
|
|
765
880
|
}
|
|
766
881
|
// extra updates
|
|
767
882
|
await this.commitExtraUpdates(ChangeSetType.UPDATE_EARLY, ctx);
|
|
768
883
|
// create
|
|
769
|
-
for (const
|
|
770
|
-
await this.commitCreateChangeSets(groups[ChangeSetType.CREATE].get(
|
|
884
|
+
for (const meta of commitOrder) {
|
|
885
|
+
await this.commitCreateChangeSets(groups[ChangeSetType.CREATE].get(meta) ?? [], ctx);
|
|
771
886
|
}
|
|
772
887
|
// update
|
|
773
|
-
for (const
|
|
774
|
-
await this.commitUpdateChangeSets(groups[ChangeSetType.UPDATE].get(
|
|
888
|
+
for (const meta of commitOrder) {
|
|
889
|
+
await this.commitUpdateChangeSets(groups[ChangeSetType.UPDATE].get(meta) ?? [], ctx);
|
|
775
890
|
}
|
|
776
891
|
// extra updates
|
|
777
892
|
await this.commitExtraUpdates(ChangeSetType.UPDATE, ctx);
|
|
778
893
|
// collection updates
|
|
779
894
|
await this.commitCollectionUpdates(ctx);
|
|
780
895
|
// delete - entity deletions need to be in reverse commit order
|
|
781
|
-
for (const
|
|
782
|
-
await this.commitDeleteChangeSets(groups[ChangeSetType.DELETE].get(
|
|
896
|
+
for (const meta of commitOrderReversed) {
|
|
897
|
+
await this.commitDeleteChangeSets(groups[ChangeSetType.DELETE].get(meta) ?? [], ctx);
|
|
783
898
|
}
|
|
784
899
|
// take snapshots of all persisted collections
|
|
785
900
|
const visited = new Set();
|
|
@@ -815,16 +930,28 @@ export class UnitOfWork {
|
|
|
815
930
|
if (Utils.isCollection(ref)) {
|
|
816
931
|
ref.getItems(false).some(item => {
|
|
817
932
|
const cs = this.changeSets.get(Reference.unwrapReference(item));
|
|
818
|
-
const isScheduledForInsert = cs
|
|
933
|
+
const isScheduledForInsert = cs?.type === ChangeSetType.CREATE && !cs.persisted;
|
|
819
934
|
if (isScheduledForInsert) {
|
|
820
935
|
this.scheduleExtraUpdate(changeSet, [prop]);
|
|
821
936
|
return true;
|
|
822
937
|
}
|
|
823
938
|
return false;
|
|
824
939
|
});
|
|
940
|
+
continue;
|
|
941
|
+
}
|
|
942
|
+
const refEntity = Reference.unwrapReference(ref);
|
|
943
|
+
// For mapToPk properties, the value is a primitive (string/array), not an entity
|
|
944
|
+
if (!Utils.isEntity(refEntity)) {
|
|
945
|
+
continue;
|
|
825
946
|
}
|
|
826
|
-
|
|
827
|
-
|
|
947
|
+
// For TPT entities, check if the ROOT table's changeset has been persisted
|
|
948
|
+
// (since the FK is to the root table, not the concrete entity's table)
|
|
949
|
+
let cs = this.changeSets.get(refEntity);
|
|
950
|
+
if (cs?.tptChangeSets?.length) {
|
|
951
|
+
// Root table changeset is the last one (ordered immediate parent → root)
|
|
952
|
+
cs = cs.tptChangeSets[cs.tptChangeSets.length - 1];
|
|
953
|
+
}
|
|
954
|
+
const isScheduledForInsert = cs?.type === ChangeSetType.CREATE && !cs.persisted;
|
|
828
955
|
if (isScheduledForInsert) {
|
|
829
956
|
this.scheduleExtraUpdate(changeSet, [prop]);
|
|
830
957
|
}
|
|
@@ -853,9 +980,16 @@ export class UnitOfWork {
|
|
|
853
980
|
}
|
|
854
981
|
await this.changeSetPersister.executeUpdates(changeSets, batched, { ctx });
|
|
855
982
|
for (const changeSet of changeSets) {
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
983
|
+
const wrapped = helper(changeSet.entity);
|
|
984
|
+
wrapped.__originalEntityData = this.comparator.prepareEntity(changeSet.entity);
|
|
985
|
+
if (!wrapped.__initialized) {
|
|
986
|
+
for (const prop of changeSet.meta.relations) {
|
|
987
|
+
if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) && changeSet.entity[prop.name] == null) {
|
|
988
|
+
changeSet.entity[prop.name] = Collection.create(changeSet.entity, prop.name, undefined, wrapped.isInitialized());
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
wrapped.__initialized = true;
|
|
992
|
+
}
|
|
859
993
|
await this.runHooks(EventType.afterUpdate, changeSet);
|
|
860
994
|
}
|
|
861
995
|
}
|
|
@@ -939,12 +1073,23 @@ export class UnitOfWork {
|
|
|
939
1073
|
[ChangeSetType.UPDATE_EARLY]: new Map(),
|
|
940
1074
|
[ChangeSetType.DELETE_EARLY]: new Map(),
|
|
941
1075
|
};
|
|
942
|
-
|
|
1076
|
+
const addToGroup = (cs) => {
|
|
1077
|
+
// 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) && !Utils.hasObjectKeys(cs.payload)) {
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
943
1081
|
const group = groups[cs.type];
|
|
944
|
-
const
|
|
1082
|
+
const groupKey = cs.meta.inheritanceType === 'tpt' ? cs.meta : cs.rootMeta;
|
|
1083
|
+
const classGroup = group.get(groupKey) ?? [];
|
|
945
1084
|
classGroup.push(cs);
|
|
946
|
-
if (!group.has(
|
|
947
|
-
group.set(
|
|
1085
|
+
if (!group.has(groupKey)) {
|
|
1086
|
+
group.set(groupKey, classGroup);
|
|
1087
|
+
}
|
|
1088
|
+
};
|
|
1089
|
+
for (const cs of this.changeSets.values()) {
|
|
1090
|
+
addToGroup(cs);
|
|
1091
|
+
for (const parentCs of cs.tptChangeSets ?? []) {
|
|
1092
|
+
addToGroup(parentCs);
|
|
948
1093
|
}
|
|
949
1094
|
}
|
|
950
1095
|
return groups;
|
|
@@ -952,14 +1097,35 @@ export class UnitOfWork {
|
|
|
952
1097
|
getCommitOrder() {
|
|
953
1098
|
const calc = new CommitOrderCalculator();
|
|
954
1099
|
const set = new Set();
|
|
955
|
-
this.changeSets.forEach(cs =>
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1100
|
+
this.changeSets.forEach(cs => {
|
|
1101
|
+
if (cs.meta.inheritanceType === 'tpt') {
|
|
1102
|
+
set.add(cs.meta);
|
|
1103
|
+
for (const parentCs of cs.tptChangeSets ?? []) {
|
|
1104
|
+
set.add(parentCs.meta);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
else {
|
|
1108
|
+
set.add(cs.rootMeta);
|
|
1109
|
+
}
|
|
1110
|
+
});
|
|
1111
|
+
set.forEach(meta => calc.addNode(meta._id));
|
|
1112
|
+
for (const meta of set) {
|
|
1113
|
+
for (const prop of meta.relations) {
|
|
1114
|
+
if (prop.polymorphTargets) {
|
|
1115
|
+
for (const targetMeta of prop.polymorphTargets) {
|
|
1116
|
+
calc.discoverProperty({ ...prop, targetMeta }, meta._id);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
else {
|
|
1120
|
+
calc.discoverProperty(prop, meta._id);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
// For TPT, parent table must be inserted BEFORE child tables
|
|
1124
|
+
if (meta.inheritanceType === 'tpt' && meta.tptParent && set.has(meta.tptParent)) {
|
|
1125
|
+
calc.addDependency(meta.tptParent._id, meta._id, 1);
|
|
960
1126
|
}
|
|
961
1127
|
}
|
|
962
|
-
return calc.sort();
|
|
1128
|
+
return calc.sort().map(id => this.metadata.getById(id));
|
|
963
1129
|
}
|
|
964
1130
|
resetTransaction(oldTx) {
|
|
965
1131
|
if (oldTx) {
|
|
@@ -10,18 +10,18 @@ export declare abstract class AbstractSchemaGenerator<D extends IDatabaseDriver>
|
|
|
10
10
|
protected readonly platform: ReturnType<D['getPlatform']>;
|
|
11
11
|
protected readonly connection: ReturnType<D['getConnection']>;
|
|
12
12
|
constructor(em: D | D[typeof EntityManagerType]);
|
|
13
|
-
|
|
13
|
+
create(options?: CreateSchemaOptions): Promise<void>;
|
|
14
14
|
/**
|
|
15
15
|
* Returns true if the database was created.
|
|
16
16
|
*/
|
|
17
17
|
ensureDatabase(options?: EnsureDatabaseOptions): Promise<boolean>;
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
refresh(options?: RefreshDatabaseOptions): Promise<void>;
|
|
19
|
+
clear(options?: ClearDatabaseOptions): Promise<void>;
|
|
20
20
|
protected clearIdentityMap(): void;
|
|
21
21
|
getCreateSchemaSQL(options?: CreateSchemaOptions): Promise<string>;
|
|
22
|
-
|
|
22
|
+
drop(options?: DropSchemaOptions): Promise<void>;
|
|
23
23
|
getDropSchemaSQL(options?: Omit<DropSchemaOptions, 'dropDb'>): Promise<string>;
|
|
24
|
-
|
|
24
|
+
update(options?: UpdateSchemaOptions): Promise<void>;
|
|
25
25
|
getUpdateSchemaSQL(options?: UpdateSchemaOptions): Promise<string>;
|
|
26
26
|
getUpdateSchemaMigrationSQL(options?: UpdateSchemaOptions): Promise<{
|
|
27
27
|
up: string;
|