@mikro-orm/core 7.0.0-dev.29 → 7.0.0-dev.291
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 +67 -60
- package/EntityManager.js +275 -257
- package/MikroORM.d.ts +44 -35
- package/MikroORM.js +109 -142
- package/README.md +2 -0
- package/cache/FileCacheAdapter.d.ts +1 -2
- package/cache/FileCacheAdapter.js +18 -11
- 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 +75 -23
- package/entity/BaseEntity.d.ts +63 -4
- package/entity/BaseEntity.js +0 -3
- package/entity/Collection.d.ts +101 -29
- package/entity/Collection.js +436 -104
- package/entity/EntityAssigner.js +17 -17
- package/entity/EntityFactory.d.ts +7 -1
- package/entity/EntityFactory.js +87 -55
- package/entity/EntityHelper.d.ts +2 -2
- package/entity/EntityHelper.js +50 -17
- package/entity/EntityLoader.d.ts +11 -10
- package/entity/EntityLoader.js +213 -82
- package/entity/EntityRepository.d.ts +28 -8
- 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 +15 -11
- package/entity/WrappedEntity.d.ts +3 -8
- package/entity/WrappedEntity.js +2 -7
- package/entity/defineEntity.d.ts +526 -310
- package/entity/defineEntity.js +134 -290
- package/entity/index.d.ts +2 -2
- package/entity/index.js +2 -2
- package/entity/utils.d.ts +6 -1
- package/entity/utils.js +34 -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 +79 -34
- 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 +782 -325
- package/metadata/MetadataProvider.d.ts +11 -2
- package/metadata/MetadataProvider.js +66 -2
- package/metadata/MetadataStorage.d.ts +13 -11
- package/metadata/MetadataStorage.js +72 -39
- 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 +577 -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 +22 -11
- package/platforms/ExceptionConverter.js +1 -1
- package/platforms/Platform.d.ts +10 -15
- package/platforms/Platform.js +21 -44
- package/serialization/EntitySerializer.d.ts +6 -3
- package/serialization/EntitySerializer.js +46 -26
- package/serialization/EntityTransformer.js +33 -21
- 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.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.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 +412 -155
- package/typings.js +99 -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 +3 -8
- package/unit-of-work/ChangeSetComputer.js +41 -20
- package/unit-of-work/ChangeSetPersister.d.ts +13 -12
- package/unit-of-work/ChangeSetPersister.js +94 -36
- 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 +248 -90
- package/utils/AbstractMigrator.d.ts +101 -0
- package/utils/AbstractMigrator.js +305 -0
- 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 -211
- package/utils/Configuration.js +153 -194
- package/utils/ConfigurationLoader.d.ts +1 -52
- package/utils/ConfigurationLoader.js +1 -330
- 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 +154 -56
- 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 +9 -6
- package/utils/Utils.d.ts +15 -126
- package/utils/Utils.js +80 -382
- 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 +34 -0
- package/utils/fs-utils.js +196 -0
- package/utils/index.d.ts +1 -3
- package/utils/index.js +1 -3
- 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
package/typings.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { ReferenceKind, } from './enums.js';
|
|
2
2
|
import { Reference } from './entity/Reference.js';
|
|
3
3
|
import { EntityHelper } from './entity/EntityHelper.js';
|
|
4
|
+
import { helper } from './entity/wrap.js';
|
|
4
5
|
import { Utils } from './utils/Utils.js';
|
|
5
6
|
import { EntityComparator } from './utils/EntityComparator.js';
|
|
7
|
+
import { BaseEntity } from './entity/BaseEntity.js';
|
|
6
8
|
export const EntityRepositoryType = Symbol('EntityRepositoryType');
|
|
7
9
|
export const PrimaryKeyProp = Symbol('PrimaryKeyProp');
|
|
8
10
|
export const OptionalProps = Symbol('OptionalProps');
|
|
9
11
|
export const EagerProps = Symbol('EagerProps');
|
|
10
12
|
export const HiddenProps = Symbol('HiddenProps');
|
|
11
13
|
export const Config = Symbol('Config');
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
15
|
+
export const EntityName = Symbol('EntityName');
|
|
12
16
|
export class EntityMetadata {
|
|
13
17
|
static counter = 0;
|
|
14
18
|
_id = 1000 * EntityMetadata.counter++; // keep the id >= 1000 to allow computing cache keys by simple addition
|
|
@@ -25,22 +29,24 @@ export class EntityMetadata {
|
|
|
25
29
|
this.referencingProperties = [];
|
|
26
30
|
this.concurrencyCheckKeys = new Set();
|
|
27
31
|
Object.assign(this, meta);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
const name = meta.className ?? meta.name;
|
|
33
|
+
if (!this.class && name) {
|
|
34
|
+
const Class = this.extends === BaseEntity
|
|
35
|
+
? ({ [name]: class extends BaseEntity {
|
|
36
|
+
} })[name]
|
|
37
|
+
: ({ [name]: class {
|
|
38
|
+
} })[name];
|
|
39
|
+
this.class = Class;
|
|
32
40
|
}
|
|
41
|
+
}
|
|
42
|
+
addProperty(prop) {
|
|
33
43
|
this.properties[prop.name] = prop;
|
|
34
44
|
this.propertyOrder.set(prop.name, this.props.length);
|
|
35
|
-
|
|
36
|
-
if (sync) {
|
|
37
|
-
this.sync();
|
|
38
|
-
}
|
|
45
|
+
this.sync();
|
|
39
46
|
}
|
|
40
47
|
removeProperty(name, sync = true) {
|
|
41
48
|
delete this.properties[name];
|
|
42
49
|
this.propertyOrder.delete(name);
|
|
43
|
-
/* v8 ignore next 3 */
|
|
44
50
|
if (sync) {
|
|
45
51
|
this.sync();
|
|
46
52
|
}
|
|
@@ -60,8 +66,52 @@ export class EntityMetadata {
|
|
|
60
66
|
getPrimaryProp() {
|
|
61
67
|
return this.properties[this.primaryKeys[0]];
|
|
62
68
|
}
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Creates a mapping from property names to field names.
|
|
71
|
+
* @param alias - Optional alias to prefix field names. Can be a string (same for all) or a function (per-property).
|
|
72
|
+
* When provided, also adds toString() returning the alias for backwards compatibility with formulas.
|
|
73
|
+
* @param toStringAlias - Optional alias to return from toString(). Defaults to `alias` when it's a string.
|
|
74
|
+
*/
|
|
75
|
+
createColumnMappingObject(alias, toStringAlias) {
|
|
76
|
+
const resolveAlias = typeof alias === 'function' ? alias : () => alias;
|
|
77
|
+
const defaultAlias = toStringAlias ?? (typeof alias === 'string' ? alias : undefined);
|
|
78
|
+
const result = Object.values(this.properties).reduce((o, prop) => {
|
|
79
|
+
if (prop.fieldNames) {
|
|
80
|
+
const propAlias = resolveAlias(prop);
|
|
81
|
+
o[prop.name] = propAlias ? `${propAlias}.${prop.fieldNames[0]}` : prop.fieldNames[0];
|
|
82
|
+
}
|
|
83
|
+
return o;
|
|
84
|
+
}, {});
|
|
85
|
+
// Add toString() for backwards compatibility when alias is provided
|
|
86
|
+
Object.defineProperty(result, 'toString', {
|
|
87
|
+
value: () => defaultAlias ?? '',
|
|
88
|
+
enumerable: false,
|
|
89
|
+
});
|
|
90
|
+
// Wrap in Proxy to detect old formula signature usage where the first param was FormulaTable.
|
|
91
|
+
// If user accesses `.alias` or `.qualifiedName` (FormulaTable-only properties), warn them.
|
|
92
|
+
const warnedProps = new Set(['alias', 'qualifiedName']);
|
|
93
|
+
return new Proxy(result, {
|
|
94
|
+
get(target, prop, receiver) {
|
|
95
|
+
if (typeof prop === 'string' && warnedProps.has(prop) && !(prop in target)) {
|
|
96
|
+
// eslint-disable-next-line no-console
|
|
97
|
+
console.warn(`[MikroORM] Detected old formula callback signature. The first parameter is now 'columns', not 'table'. ` +
|
|
98
|
+
`Accessing '.${prop}' on the columns object will return undefined. ` +
|
|
99
|
+
`Update your formula: formula(cols => quote\`\${cols.propName} ...\`). See the v7 upgrade guide.`);
|
|
100
|
+
}
|
|
101
|
+
return Reflect.get(target, prop, receiver);
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Creates a column mapping for schema callbacks (indexes, checks, generated columns).
|
|
107
|
+
* For TPT entities, only includes properties that belong to the current table (ownProps).
|
|
108
|
+
*/
|
|
109
|
+
createSchemaColumnMappingObject() {
|
|
110
|
+
// For TPT entities, only include properties that belong to this entity's table
|
|
111
|
+
const props = this.inheritanceType === 'tpt' && this.ownProps
|
|
112
|
+
? this.ownProps
|
|
113
|
+
: Object.values(this.properties);
|
|
114
|
+
return props.reduce((o, prop) => {
|
|
65
115
|
if (prop.fieldNames) {
|
|
66
116
|
o[prop.name] = prop.fieldNames[0];
|
|
67
117
|
}
|
|
@@ -74,6 +124,9 @@ export class EntityMetadata {
|
|
|
74
124
|
set tableName(name) {
|
|
75
125
|
this.collection = name;
|
|
76
126
|
}
|
|
127
|
+
get uniqueName() {
|
|
128
|
+
return this.tableName + '_' + this._id;
|
|
129
|
+
}
|
|
77
130
|
sync(initIndexes = false, config) {
|
|
78
131
|
this.root ??= this;
|
|
79
132
|
const props = Object.values(this.properties).sort((a, b) => this.propertyOrder.get(a.name) - this.propertyOrder.get(b.name));
|
|
@@ -83,6 +136,12 @@ export class EntityMetadata {
|
|
|
83
136
|
this.uniqueProps = this.props.filter(prop => prop.unique);
|
|
84
137
|
this.getterProps = this.props.filter(prop => prop.getter);
|
|
85
138
|
this.comparableProps = this.props.filter(prop => EntityComparator.isComparable(prop, this));
|
|
139
|
+
this.validateProps = this.props.filter(prop => {
|
|
140
|
+
if (prop.inherited || (prop.persist === false && prop.userDefined !== false)) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
return prop.kind === ReferenceKind.SCALAR && ['string', 'number', 'boolean', 'Date'].includes(prop.type);
|
|
144
|
+
});
|
|
86
145
|
this.hydrateProps = this.props.filter(prop => {
|
|
87
146
|
// `prop.userDefined` is either `undefined` or `false`
|
|
88
147
|
const discriminator = this.root.discriminatorColumn === prop.name && prop.userDefined === false;
|
|
@@ -90,16 +149,26 @@ export class EntityMetadata {
|
|
|
90
149
|
const onlyGetter = prop.getter && !prop.setter && prop.persist === false;
|
|
91
150
|
return !prop.inherited && prop.hydrate !== false && !discriminator && !prop.embedded && !onlyGetter;
|
|
92
151
|
});
|
|
93
|
-
this.trackingProps = this.hydrateProps
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
152
|
+
this.trackingProps = this.hydrateProps.filter(prop => {
|
|
153
|
+
return !prop.getter && !prop.setter && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind);
|
|
154
|
+
});
|
|
155
|
+
this.selfReferencing = this.relations.some(prop => {
|
|
156
|
+
return this.root.uniqueName === prop.targetMeta?.root.uniqueName;
|
|
157
|
+
});
|
|
98
158
|
this.hasUniqueProps = this.uniques.length + this.uniqueProps.length > 0;
|
|
99
|
-
|
|
159
|
+
// Normalize object-form `view` option: `view: { materialized: true, withData: false }`
|
|
160
|
+
// into flat metadata fields (`view: true`, `materialized: true`, `withData: false`).
|
|
161
|
+
if (typeof this.view === 'object') {
|
|
162
|
+
this.materialized = this.view.materialized;
|
|
163
|
+
this.withData = this.view.withData;
|
|
164
|
+
this.view = true;
|
|
165
|
+
}
|
|
166
|
+
// If `view` is set, this is a database view entity (not a virtual entity).
|
|
167
|
+
// Virtual entities evaluate expressions at query time, view entities create actual database views.
|
|
168
|
+
this.virtual = !!this.expression && !this.view;
|
|
100
169
|
if (config) {
|
|
101
170
|
for (const prop of this.props) {
|
|
102
|
-
if (prop.enum && !prop.nativeEnumName && prop.items?.every(item =>
|
|
171
|
+
if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => typeof item === 'string')) {
|
|
103
172
|
const name = config.getNamingStrategy().indexName(this.tableName, prop.fieldNames, 'check');
|
|
104
173
|
const exists = this.checks.findIndex(check => check.name === name);
|
|
105
174
|
if (exists !== -1) {
|
|
@@ -119,16 +188,15 @@ export class EntityMetadata {
|
|
|
119
188
|
for (const hook of Utils.keys(this.hooks)) {
|
|
120
189
|
this.hooks[hook] = Utils.removeDuplicates(this.hooks[hook]);
|
|
121
190
|
}
|
|
122
|
-
if (this.virtual) {
|
|
191
|
+
if (this.virtual || this.view) {
|
|
123
192
|
this.readonly = true;
|
|
124
193
|
}
|
|
125
194
|
if (initIndexes && this.name) {
|
|
126
195
|
this.props.forEach(prop => this.initIndexes(prop));
|
|
127
196
|
}
|
|
128
197
|
this.definedProperties = this.trackingProps.reduce((o, prop) => {
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
if (isReference) {
|
|
198
|
+
const hasInverse = (prop.inversedBy || prop.mappedBy) && !prop.mapToPk;
|
|
199
|
+
if (hasInverse) {
|
|
132
200
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
133
201
|
const meta = this;
|
|
134
202
|
o[prop.name] = {
|
|
@@ -146,10 +214,10 @@ export class EntityMetadata {
|
|
|
146
214
|
wrapped.__data[prop.name] = Reference.wrapReference(val, prop);
|
|
147
215
|
// when propagation from inside hydration, we set the FK to the entity data immediately
|
|
148
216
|
if (val && hydrator.isRunning() && wrapped.__originalEntityData && prop.owner) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
217
|
+
const targetMeta = prop.targetMeta ?? helper(entity)?.__meta;
|
|
218
|
+
if (targetMeta) {
|
|
219
|
+
wrapped.__originalEntityData[prop.name] = Utils.getPrimaryKeyValues(val, targetMeta, true);
|
|
220
|
+
}
|
|
153
221
|
}
|
|
154
222
|
EntityHelper.propagate(meta, entity, this, prop, Reference.unwrapReference(val), old);
|
|
155
223
|
},
|
|
@@ -157,23 +225,6 @@ export class EntityMetadata {
|
|
|
157
225
|
configurable: true,
|
|
158
226
|
};
|
|
159
227
|
}
|
|
160
|
-
if (prop.inherited || prop.primary || isCollection || prop.persist === false || prop.trackChanges === false || isReference || prop.embedded) {
|
|
161
|
-
return o;
|
|
162
|
-
}
|
|
163
|
-
o[prop.name] = {
|
|
164
|
-
get() {
|
|
165
|
-
return this.__helper.__data[prop.name];
|
|
166
|
-
},
|
|
167
|
-
set(val) {
|
|
168
|
-
if (typeof val === 'object' && !!val && '__raw' in val) {
|
|
169
|
-
val.assign();
|
|
170
|
-
}
|
|
171
|
-
this.__helper.__data[prop.name] = val;
|
|
172
|
-
this.__helper.__touched = !this.__helper.hydrator.isRunning();
|
|
173
|
-
},
|
|
174
|
-
enumerable: true,
|
|
175
|
-
configurable: true,
|
|
176
|
-
};
|
|
177
228
|
return o;
|
|
178
229
|
}, { __gettersDefined: { value: true, enumerable: false } });
|
|
179
230
|
}
|
|
@@ -195,7 +246,7 @@ export class EntityMetadata {
|
|
|
195
246
|
this.indexes.push({ properties: prop.name });
|
|
196
247
|
prop.index = false;
|
|
197
248
|
}
|
|
198
|
-
/* v8 ignore next
|
|
249
|
+
/* v8 ignore next */
|
|
199
250
|
if (owner && prop.fieldNames.length > 1 && prop.unique) {
|
|
200
251
|
this.uniques.push({ properties: prop.name });
|
|
201
252
|
prop.unique = false;
|
|
@@ -205,4 +256,8 @@ export class EntityMetadata {
|
|
|
205
256
|
clone() {
|
|
206
257
|
return this;
|
|
207
258
|
}
|
|
259
|
+
/** @ignore */
|
|
260
|
+
[Symbol.for('nodejs.util.inspect.custom')]() {
|
|
261
|
+
return `[${this.constructor.name}<${this.className}>]`;
|
|
262
|
+
}
|
|
208
263
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { inspect } from 'node:util';
|
|
2
1
|
import type { EntityData, EntityMetadata, EntityDictionary, Primary } from '../typings.js';
|
|
3
2
|
export declare class ChangeSet<T extends object> {
|
|
4
3
|
entity: T;
|
|
@@ -10,19 +9,18 @@ export declare class ChangeSet<T extends object> {
|
|
|
10
9
|
constructor(entity: T, type: ChangeSetType, payload: EntityDictionary<T>, meta: EntityMetadata<T>);
|
|
11
10
|
getPrimaryKey(object?: boolean): Primary<T> | null;
|
|
12
11
|
getSerializedPrimaryKey(): string | null;
|
|
13
|
-
/** @ignore */
|
|
14
|
-
[inspect.custom](depth?: number): string;
|
|
15
12
|
}
|
|
16
13
|
export interface ChangeSet<T> {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
collection: string;
|
|
14
|
+
meta: EntityMetadata<T>;
|
|
15
|
+
rootMeta: EntityMetadata<T>;
|
|
20
16
|
schema?: string;
|
|
21
17
|
type: ChangeSetType;
|
|
22
18
|
entity: T;
|
|
23
19
|
payload: EntityDictionary<T>;
|
|
24
20
|
persisted: boolean;
|
|
25
21
|
originalEntity?: EntityData<T>;
|
|
22
|
+
/** For TPT: changesets for parent tables, ordered from immediate parent to root */
|
|
23
|
+
tptChangeSets?: ChangeSet<T>[];
|
|
26
24
|
}
|
|
27
25
|
export declare enum ChangeSetType {
|
|
28
26
|
CREATE = "create",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { inspect } from 'node:util';
|
|
2
1
|
import { helper } from '../entity/wrap.js';
|
|
3
2
|
import { Utils } from '../utils/Utils.js';
|
|
3
|
+
import { inspect } from '../logging/inspect.js';
|
|
4
4
|
export class ChangeSet {
|
|
5
5
|
entity;
|
|
6
6
|
type;
|
|
@@ -13,9 +13,8 @@ export class ChangeSet {
|
|
|
13
13
|
this.type = type;
|
|
14
14
|
this.payload = payload;
|
|
15
15
|
this.meta = meta;
|
|
16
|
-
this.
|
|
17
|
-
this.
|
|
18
|
-
this.collection = meta.root.collection;
|
|
16
|
+
this.meta = meta;
|
|
17
|
+
this.rootMeta = meta.root;
|
|
19
18
|
this.schema = helper(entity).__schema ?? meta.root.schema;
|
|
20
19
|
}
|
|
21
20
|
getPrimaryKey(object = false) {
|
|
@@ -46,7 +45,7 @@ export class ChangeSet {
|
|
|
46
45
|
return this.serializedPrimaryKey;
|
|
47
46
|
}
|
|
48
47
|
/** @ignore */
|
|
49
|
-
[inspect.custom](depth = 2) {
|
|
48
|
+
[Symbol.for('nodejs.util.inspect.custom')](depth = 2) {
|
|
50
49
|
const object = { ...this };
|
|
51
50
|
const hidden = ['meta', 'serializedPrimaryKey'];
|
|
52
51
|
hidden.forEach(k => delete object[k]);
|
|
@@ -1,20 +1,15 @@
|
|
|
1
|
-
import { type Configuration } from '../utils/Configuration.js';
|
|
2
|
-
import type { MetadataStorage } from '../metadata/MetadataStorage.js';
|
|
3
1
|
import type { AnyEntity } from '../typings.js';
|
|
4
2
|
import { ChangeSet } from './ChangeSet.js';
|
|
5
|
-
import { type EntityValidator } from '../entity/EntityValidator.js';
|
|
6
3
|
import { type Collection } from '../entity/Collection.js';
|
|
7
|
-
import type { Platform } from '../platforms/Platform.js';
|
|
8
4
|
import type { EntityManager } from '../EntityManager.js';
|
|
9
5
|
export declare class ChangeSetComputer {
|
|
10
|
-
private readonly
|
|
6
|
+
private readonly em;
|
|
11
7
|
private readonly collectionUpdates;
|
|
8
|
+
private readonly comparator;
|
|
12
9
|
private readonly metadata;
|
|
13
10
|
private readonly platform;
|
|
14
11
|
private readonly config;
|
|
15
|
-
|
|
16
|
-
private readonly comparator;
|
|
17
|
-
constructor(validator: EntityValidator, collectionUpdates: Set<Collection<AnyEntity>>, metadata: MetadataStorage, platform: Platform, config: Configuration, em: EntityManager);
|
|
12
|
+
constructor(em: EntityManager, collectionUpdates: Set<Collection<AnyEntity>>);
|
|
18
13
|
computeChangeSet<T extends object>(entity: T): ChangeSet<T> | null;
|
|
19
14
|
/**
|
|
20
15
|
* Traverses entity graph and executes `onCreate` and `onUpdate` methods, assigning the values to given properties.
|
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
import { Utils } from '../utils/Utils.js';
|
|
2
|
+
import { QueryHelper } from '../utils/QueryHelper.js';
|
|
2
3
|
import { ChangeSet, ChangeSetType } from './ChangeSet.js';
|
|
3
4
|
import { helper } from '../entity/wrap.js';
|
|
5
|
+
import { validateEntity } from '../entity/validators.js';
|
|
6
|
+
import { Reference } from '../entity/Reference.js';
|
|
7
|
+
import { PolymorphicRef } from '../entity/PolymorphicRef.js';
|
|
4
8
|
import { ReferenceKind } from '../enums.js';
|
|
5
9
|
export class ChangeSetComputer {
|
|
6
|
-
|
|
10
|
+
em;
|
|
7
11
|
collectionUpdates;
|
|
12
|
+
comparator;
|
|
8
13
|
metadata;
|
|
9
14
|
platform;
|
|
10
15
|
config;
|
|
11
|
-
em
|
|
12
|
-
comparator;
|
|
13
|
-
constructor(validator, collectionUpdates, metadata, platform, config, em) {
|
|
14
|
-
this.validator = validator;
|
|
15
|
-
this.collectionUpdates = collectionUpdates;
|
|
16
|
-
this.metadata = metadata;
|
|
17
|
-
this.platform = platform;
|
|
18
|
-
this.config = config;
|
|
16
|
+
constructor(em, collectionUpdates) {
|
|
19
17
|
this.em = em;
|
|
18
|
+
this.collectionUpdates = collectionUpdates;
|
|
19
|
+
this.config = this.em.config;
|
|
20
|
+
this.metadata = this.em.getMetadata();
|
|
21
|
+
this.platform = this.em.getPlatform();
|
|
20
22
|
this.comparator = this.config.getComparator(this.metadata);
|
|
21
23
|
}
|
|
22
24
|
computeChangeSet(entity) {
|
|
23
|
-
const meta = this.metadata.get(entity.constructor
|
|
25
|
+
const meta = this.metadata.get(entity.constructor);
|
|
24
26
|
if (meta.readonly) {
|
|
25
27
|
return null;
|
|
26
28
|
}
|
|
@@ -34,20 +36,21 @@ export class ChangeSetComputer {
|
|
|
34
36
|
this.processPropertyInitializers(entity, prop, type, map);
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
|
-
if (type === ChangeSetType.UPDATE && !wrapped.__initialized
|
|
38
|
-
|
|
39
|
+
if (type === ChangeSetType.UPDATE && !wrapped.__initialized) {
|
|
40
|
+
const data = this.comparator.prepareEntity(entity);
|
|
41
|
+
if (Utils.equals(data, wrapped.__originalEntityData)) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
39
44
|
}
|
|
40
45
|
const changeSet = new ChangeSet(entity, type, this.computePayload(entity), meta);
|
|
41
46
|
changeSet.originalEntity = wrapped.__originalEntityData;
|
|
42
|
-
if (this.config.get('validate')) {
|
|
43
|
-
this.validator.validate(changeSet.entity, changeSet.payload, meta);
|
|
44
|
-
}
|
|
45
47
|
for (const prop of meta.relations.filter(prop => prop.persist !== false || prop.userDefined === false)) {
|
|
46
48
|
this.processProperty(changeSet, prop);
|
|
47
49
|
}
|
|
48
50
|
if (changeSet.type === ChangeSetType.UPDATE && !Utils.hasObjectKeys(changeSet.payload)) {
|
|
49
51
|
return null;
|
|
50
52
|
}
|
|
53
|
+
validateEntity(changeSet.entity, meta);
|
|
51
54
|
// Execute `onCreate` and `onUpdate` on properties recursively, saves `onUpdate` results
|
|
52
55
|
// to the `map` as we want to apply those only if something else changed.
|
|
53
56
|
if (type === ChangeSetType.UPDATE) {
|
|
@@ -91,7 +94,7 @@ export class ChangeSetComputer {
|
|
|
91
94
|
computePayload(entity, ignoreUndefined = false) {
|
|
92
95
|
const data = this.comparator.prepareEntity(entity);
|
|
93
96
|
const wrapped = helper(entity);
|
|
94
|
-
const entityName = wrapped.__meta.
|
|
97
|
+
const entityName = wrapped.__meta.class;
|
|
95
98
|
const originalEntityData = wrapped.__originalEntityData;
|
|
96
99
|
if (!wrapped.__initialized) {
|
|
97
100
|
for (const prop of wrapped.__meta.primaryKeys) {
|
|
@@ -130,9 +133,25 @@ export class ChangeSetComputer {
|
|
|
130
133
|
return;
|
|
131
134
|
}
|
|
132
135
|
const targets = Utils.unwrapProperty(changeSet.entity, changeSet.meta, prop);
|
|
133
|
-
targets.forEach(([
|
|
134
|
-
|
|
135
|
-
|
|
136
|
+
targets.forEach(([rawTarget, idx]) => {
|
|
137
|
+
const target = Reference.unwrapReference(rawTarget);
|
|
138
|
+
const needsProcessing = target != null && (prop.targetKey != null || !target.__helper.hasPrimaryKey());
|
|
139
|
+
if (needsProcessing) {
|
|
140
|
+
let value = prop.targetKey ? target[prop.targetKey] : target.__helper.__identifier;
|
|
141
|
+
/* v8 ignore next */
|
|
142
|
+
if (prop.targetKey && prop.targetMeta) {
|
|
143
|
+
const targetProp = prop.targetMeta.properties[prop.targetKey];
|
|
144
|
+
if (targetProp?.customType) {
|
|
145
|
+
value = targetProp.customType.convertToDatabaseValue(value, this.platform, { mode: 'serialization' });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (prop.polymorphic) {
|
|
149
|
+
const discriminator = QueryHelper.findDiscriminatorValue(prop.discriminatorMap, target.constructor);
|
|
150
|
+
Utils.setPayloadProperty(changeSet.payload, changeSet.meta, prop, new PolymorphicRef(discriminator, value), idx);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
Utils.setPayloadProperty(changeSet.payload, changeSet.meta, prop, value, idx);
|
|
154
|
+
}
|
|
136
155
|
}
|
|
137
156
|
});
|
|
138
157
|
}
|
|
@@ -145,7 +164,9 @@ export class ChangeSetComputer {
|
|
|
145
164
|
this.collectionUpdates.add(target);
|
|
146
165
|
}
|
|
147
166
|
if (prop.owner && !this.platform.usesPivotTable()) {
|
|
148
|
-
changeSet.payload[prop.name] = target.getItems(false).map((item) =>
|
|
167
|
+
changeSet.payload[prop.name] = target.getItems(false).map((item) => {
|
|
168
|
+
return item.__helper.__identifier ?? item.__helper.getPrimaryKey();
|
|
169
|
+
});
|
|
149
170
|
}
|
|
150
171
|
}
|
|
151
172
|
}
|
|
@@ -1,27 +1,23 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Dictionary, EntityDictionary, EntityMetadata, IHydrator } from '../typings.js';
|
|
3
|
-
import { type EntityFactory } from '../entity/EntityFactory.js';
|
|
4
|
-
import { type EntityValidator } from '../entity/EntityValidator.js';
|
|
1
|
+
import type { Dictionary, EntityDictionary, EntityMetadata } from '../typings.js';
|
|
5
2
|
import { type ChangeSet } from './ChangeSet.js';
|
|
6
|
-
import {
|
|
7
|
-
import type { DriverMethodOptions, IDatabaseDriver } from '../drivers/IDatabaseDriver.js';
|
|
3
|
+
import type { DriverMethodOptions } from '../drivers/IDatabaseDriver.js';
|
|
8
4
|
import type { EntityManager } from '../EntityManager.js';
|
|
9
5
|
export declare class ChangeSetPersister {
|
|
6
|
+
private readonly em;
|
|
7
|
+
private readonly platform;
|
|
8
|
+
private readonly comparator;
|
|
9
|
+
private readonly usesReturningStatement;
|
|
10
10
|
private readonly driver;
|
|
11
11
|
private readonly metadata;
|
|
12
12
|
private readonly hydrator;
|
|
13
13
|
private readonly factory;
|
|
14
|
-
private readonly validator;
|
|
15
14
|
private readonly config;
|
|
16
|
-
|
|
17
|
-
private readonly platform;
|
|
18
|
-
private readonly comparator;
|
|
19
|
-
private readonly usesReturningStatement;
|
|
20
|
-
constructor(driver: IDatabaseDriver, metadata: MetadataStorage, hydrator: IHydrator, factory: EntityFactory, validator: EntityValidator, config: Configuration, em: EntityManager);
|
|
15
|
+
constructor(em: EntityManager);
|
|
21
16
|
executeInserts<T extends object>(changeSets: ChangeSet<T>[], options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
|
|
22
17
|
executeUpdates<T extends object>(changeSets: ChangeSet<T>[], batched: boolean, options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
|
|
23
18
|
executeDeletes<T extends object>(changeSets: ChangeSet<T>[], options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
|
|
24
19
|
private runForEachSchema;
|
|
20
|
+
private validateRequired;
|
|
25
21
|
private processProperties;
|
|
26
22
|
private persistNewEntity;
|
|
27
23
|
private persistNewEntities;
|
|
@@ -44,6 +40,11 @@ export declare class ChangeSetPersister {
|
|
|
44
40
|
* so we use a single query in case of both versioning and default values is used.
|
|
45
41
|
*/
|
|
46
42
|
private reloadVersionValues;
|
|
43
|
+
/**
|
|
44
|
+
* For TPT child tables, resolve EntityIdentifier values in PK fields.
|
|
45
|
+
* The parent table insert assigns the actual PK value, which the child table references.
|
|
46
|
+
*/
|
|
47
|
+
private resolveTPTIdentifiers;
|
|
47
48
|
private processProperty;
|
|
48
49
|
/**
|
|
49
50
|
* Maps values returned via `returning` statement (postgres) or the inserted id (other sql drivers).
|