@mikro-orm/core 7.0.0-dev.33 → 7.0.0-dev.331
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 +70 -75
- package/EntityManager.js +487 -402
- package/MikroORM.d.ts +45 -38
- package/MikroORM.js +123 -156
- package/README.md +7 -4
- package/cache/FileCacheAdapter.d.ts +2 -7
- package/cache/FileCacheAdapter.js +35 -30
- package/cache/GeneratedCacheAdapter.d.ts +1 -2
- package/cache/GeneratedCacheAdapter.js +6 -8
- package/cache/MemoryCacheAdapter.d.ts +1 -2
- package/cache/MemoryCacheAdapter.js +8 -8
- package/cache/index.d.ts +1 -2
- package/cache/index.js +0 -2
- package/connections/Connection.d.ts +12 -5
- package/connections/Connection.js +37 -15
- package/drivers/DatabaseDriver.d.ts +25 -18
- package/drivers/DatabaseDriver.js +144 -45
- package/drivers/IDatabaseDriver.d.ts +118 -23
- package/entity/BaseEntity.d.ts +63 -4
- package/entity/BaseEntity.js +0 -3
- package/entity/Collection.d.ts +95 -31
- package/entity/Collection.js +487 -139
- package/entity/EntityAssigner.js +37 -25
- package/entity/EntityFactory.d.ts +8 -9
- package/entity/EntityFactory.js +152 -100
- package/entity/EntityHelper.d.ts +2 -2
- package/entity/EntityHelper.js +69 -27
- package/entity/EntityLoader.d.ts +12 -13
- package/entity/EntityLoader.js +286 -125
- 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 +3 -8
- package/entity/Reference.js +62 -29
- package/entity/WrappedEntity.d.ts +7 -10
- package/entity/WrappedEntity.js +6 -7
- package/entity/defineEntity.d.ts +472 -313
- 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 +46 -11
- package/entity/validators.d.ts +11 -0
- package/entity/validators.js +66 -0
- package/enums.d.ts +8 -6
- package/enums.js +13 -17
- package/errors.d.ts +26 -16
- package/errors.js +63 -31
- package/events/EventManager.d.ts +3 -5
- package/events/EventManager.js +37 -26
- package/events/index.d.ts +1 -1
- package/events/index.js +0 -1
- package/exceptions.js +9 -2
- package/hydration/Hydrator.js +1 -2
- package/hydration/ObjectHydrator.d.ts +5 -6
- package/hydration/ObjectHydrator.js +109 -50
- package/index.d.ts +2 -2
- package/index.js +1 -2
- package/logging/DefaultLogger.d.ts +1 -1
- package/logging/DefaultLogger.js +3 -4
- package/logging/SimpleLogger.d.ts +1 -1
- package/logging/colors.d.ts +1 -1
- package/logging/colors.js +4 -6
- package/logging/index.d.ts +2 -1
- package/logging/index.js +1 -1
- package/logging/inspect.d.ts +2 -0
- package/logging/inspect.js +11 -0
- package/metadata/EntitySchema.d.ts +47 -23
- package/metadata/EntitySchema.js +103 -34
- package/metadata/MetadataDiscovery.d.ts +65 -18
- package/metadata/MetadataDiscovery.js +940 -424
- package/metadata/MetadataProvider.d.ts +11 -2
- package/metadata/MetadataProvider.js +71 -2
- package/metadata/MetadataStorage.d.ts +11 -13
- package/metadata/MetadataStorage.js +79 -48
- package/metadata/MetadataValidator.d.ts +32 -9
- package/metadata/MetadataValidator.js +214 -44
- 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 +0 -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 +26 -5
- package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
- package/naming-strategy/EntityCaseNamingStrategy.js +7 -6
- 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/naming-strategy/index.d.ts +1 -1
- package/naming-strategy/index.js +0 -1
- package/not-supported.d.ts +2 -0
- package/not-supported.js +8 -0
- package/package.json +47 -36
- package/platforms/ExceptionConverter.js +1 -1
- package/platforms/Platform.d.ts +33 -15
- package/platforms/Platform.js +125 -69
- package/serialization/EntitySerializer.d.ts +6 -3
- package/serialization/EntitySerializer.js +54 -30
- package/serialization/EntityTransformer.js +37 -22
- package/serialization/SerializationContext.d.ts +10 -14
- package/serialization/SerializationContext.js +24 -19
- 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/UuidType.d.ts +2 -0
- package/types/UuidType.js +14 -2
- package/types/index.d.ts +3 -2
- package/typings.d.ts +427 -170
- package/typings.js +100 -45
- package/unit-of-work/ChangeSet.d.ts +4 -6
- package/unit-of-work/ChangeSet.js +8 -9
- package/unit-of-work/ChangeSetComputer.d.ts +2 -12
- package/unit-of-work/ChangeSetComputer.js +61 -38
- package/unit-of-work/ChangeSetPersister.d.ts +10 -17
- package/unit-of-work/ChangeSetPersister.js +136 -73
- package/unit-of-work/CommitOrderCalculator.d.ts +13 -14
- package/unit-of-work/CommitOrderCalculator.js +22 -20
- package/unit-of-work/IdentityMap.d.ts +12 -3
- package/unit-of-work/IdentityMap.js +51 -13
- package/unit-of-work/UnitOfWork.d.ts +39 -23
- package/unit-of-work/UnitOfWork.js +441 -246
- package/utils/AbstractMigrator.d.ts +101 -0
- package/utils/AbstractMigrator.js +303 -0
- package/utils/AbstractSchemaGenerator.d.ts +5 -5
- package/utils/AbstractSchemaGenerator.js +30 -18
- package/utils/AsyncContext.d.ts +6 -0
- package/utils/AsyncContext.js +42 -0
- package/utils/Configuration.d.ts +647 -185
- package/utils/Configuration.js +215 -252
- package/utils/ConfigurationLoader.d.ts +1 -52
- package/utils/ConfigurationLoader.js +1 -330
- package/utils/Cursor.d.ts +3 -6
- package/utils/Cursor.js +32 -17
- package/utils/DataloaderUtils.d.ts +10 -5
- package/utils/DataloaderUtils.js +42 -22
- package/utils/EntityComparator.d.ts +21 -21
- package/utils/EntityComparator.js +224 -118
- package/utils/QueryHelper.d.ts +34 -7
- package/utils/QueryHelper.js +183 -72
- package/utils/RawQueryFragment.d.ts +28 -34
- package/utils/RawQueryFragment.js +37 -72
- package/utils/RequestContext.js +2 -2
- package/utils/TransactionContext.js +2 -2
- package/utils/TransactionManager.js +11 -8
- package/utils/Utils.d.ts +16 -127
- package/utils/Utils.js +104 -402
- package/utils/clone.js +13 -23
- package/utils/env-vars.d.ts +7 -0
- package/utils/env-vars.js +98 -0
- package/utils/fs-utils.d.ts +20 -0
- package/utils/fs-utils.js +193 -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 +51 -5
- 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/entity/EntityAssigner.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { inspect } from 'node:util';
|
|
2
1
|
import { Collection } from './Collection.js';
|
|
3
2
|
import { Utils } from '../utils/Utils.js';
|
|
4
3
|
import { Reference } from './Reference.js';
|
|
5
4
|
import { ReferenceKind, SCALAR_TYPES } from '../enums.js';
|
|
6
|
-
import {
|
|
5
|
+
import { validateProperty } from './validators.js';
|
|
7
6
|
import { helper, wrap } from './wrap.js';
|
|
8
7
|
import { EntityHelper } from './EntityHelper.js';
|
|
9
|
-
|
|
8
|
+
import { ValidationError } from '../errors.js';
|
|
10
9
|
export class EntityAssigner {
|
|
11
10
|
static assign(entity, data, options = {}) {
|
|
12
11
|
let opts = options;
|
|
@@ -72,13 +71,16 @@ export class EntityAssigner {
|
|
|
72
71
|
value = customType.convertToJSValue(value, options.platform);
|
|
73
72
|
}
|
|
74
73
|
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop?.kind) && value != null) {
|
|
75
|
-
if (options.updateNestedEntities &&
|
|
74
|
+
if (options.updateNestedEntities &&
|
|
75
|
+
Object.hasOwn(entity, propName) &&
|
|
76
|
+
Utils.isEntity(entity[propName], true) &&
|
|
77
|
+
Utils.isPlainObject(value)) {
|
|
76
78
|
const unwrappedEntity = Reference.unwrapReference(entity[propName]);
|
|
77
79
|
const wrapped = helper(unwrappedEntity);
|
|
78
80
|
if (options.updateByPrimaryKey) {
|
|
79
81
|
const pk = Utils.extractPK(value, prop.targetMeta);
|
|
80
82
|
if (pk) {
|
|
81
|
-
const ref = options.em.getReference(prop.
|
|
83
|
+
const ref = options.em.getReference(prop.targetMeta.class, pk, options);
|
|
82
84
|
// if the PK differs, we want to change the target entity, not update it
|
|
83
85
|
const wrappedChild = helper(ref);
|
|
84
86
|
const sameTarget = wrappedChild.getSerializedPrimaryKey() === wrapped.getSerializedPrimaryKey();
|
|
@@ -94,13 +96,16 @@ export class EntityAssigner {
|
|
|
94
96
|
}
|
|
95
97
|
return EntityAssigner.assignReference(entity, value, prop, options.em, options);
|
|
96
98
|
}
|
|
97
|
-
if (prop.kind === ReferenceKind.SCALAR && SCALAR_TYPES.
|
|
98
|
-
|
|
99
|
+
if (prop.kind === ReferenceKind.SCALAR && SCALAR_TYPES.has(prop.runtimeType) && (prop.setter || !prop.getter)) {
|
|
100
|
+
validateProperty(prop, value, entity);
|
|
101
|
+
return (entity[prop.name] = value);
|
|
99
102
|
}
|
|
100
103
|
if (prop.kind === ReferenceKind.EMBEDDED && EntityAssigner.validateEM(options.em)) {
|
|
101
104
|
return EntityAssigner.assignEmbeddable(entity, value, prop, options.em, options);
|
|
102
105
|
}
|
|
103
|
-
if (options.mergeObjectProperties &&
|
|
106
|
+
if (options.mergeObjectProperties &&
|
|
107
|
+
Utils.isPlainObject(entity[propName]) &&
|
|
108
|
+
Utils.isPlainObject(value)) {
|
|
104
109
|
entity[propName] ??= {};
|
|
105
110
|
entity[propName] = Utils.merge({}, entity[propName], value);
|
|
106
111
|
}
|
|
@@ -120,7 +125,7 @@ export class EntityAssigner {
|
|
|
120
125
|
}
|
|
121
126
|
const meta2 = helper(ref).__meta;
|
|
122
127
|
const prop2 = meta2.properties[prop.inversedBy || prop.mappedBy];
|
|
123
|
-
/* v8 ignore next
|
|
128
|
+
/* v8 ignore next */
|
|
124
129
|
if (prop2 && !ref[prop2.name]) {
|
|
125
130
|
if (Reference.isReference(ref)) {
|
|
126
131
|
ref.unwrap()[prop2.name] = Reference.wrapReference(entity, prop2);
|
|
@@ -141,13 +146,15 @@ export class EntityAssigner {
|
|
|
141
146
|
entity[prop.name] = Reference.wrapReference(value, prop);
|
|
142
147
|
}
|
|
143
148
|
else if (Utils.isPrimaryKey(value, true) && EntityAssigner.validateEM(em)) {
|
|
144
|
-
entity[prop.name] = prop.mapToPk
|
|
149
|
+
entity[prop.name] = prop.mapToPk
|
|
150
|
+
? value
|
|
151
|
+
: Reference.wrapReference(em.getReference(prop.targetMeta.class, value, options), prop);
|
|
145
152
|
}
|
|
146
153
|
else if (Utils.isPlainObject(value) && options.merge && EntityAssigner.validateEM(em)) {
|
|
147
|
-
entity[prop.name] = Reference.wrapReference(em.merge(prop.
|
|
154
|
+
entity[prop.name] = Reference.wrapReference(em.merge(prop.targetMeta.class, value, options), prop);
|
|
148
155
|
}
|
|
149
156
|
else if (Utils.isPlainObject(value) && EntityAssigner.validateEM(em)) {
|
|
150
|
-
entity[prop.name] = Reference.wrapReference(em.create(prop.
|
|
157
|
+
entity[prop.name] = Reference.wrapReference(em.create(prop.targetMeta.class, value, options), prop);
|
|
151
158
|
}
|
|
152
159
|
else {
|
|
153
160
|
const name = entity.constructor.name;
|
|
@@ -166,27 +173,31 @@ export class EntityAssigner {
|
|
|
166
173
|
if (options.updateNestedEntities && options.updateByPrimaryKey && Utils.isPlainObject(item)) {
|
|
167
174
|
const pk = Utils.extractPK(item, prop.targetMeta);
|
|
168
175
|
if (pk && EntityAssigner.validateEM(em)) {
|
|
169
|
-
const ref = em.getUnitOfWork().getById(prop.
|
|
176
|
+
const ref = em.getUnitOfWork().getById(prop.targetMeta.class, pk, options.schema);
|
|
170
177
|
if (ref) {
|
|
171
178
|
return EntityAssigner.assign(ref, item, options);
|
|
172
179
|
}
|
|
173
180
|
}
|
|
174
181
|
return this.createCollectionItem(item, em, prop, invalid, options);
|
|
175
182
|
}
|
|
176
|
-
/* v8 ignore next
|
|
177
|
-
if (options.updateNestedEntities &&
|
|
183
|
+
/* v8 ignore next */
|
|
184
|
+
if (options.updateNestedEntities &&
|
|
185
|
+
!options.updateByPrimaryKey &&
|
|
186
|
+
collection[idx] &&
|
|
187
|
+
helper(collection[idx])?.isInitialized()) {
|
|
178
188
|
return EntityAssigner.assign(collection[idx], item, options);
|
|
179
189
|
}
|
|
180
190
|
return this.createCollectionItem(item, em, prop, invalid, options);
|
|
181
191
|
});
|
|
182
192
|
if (invalid.length > 0) {
|
|
183
193
|
const name = entity.constructor.name;
|
|
184
|
-
throw
|
|
194
|
+
throw ValidationError.invalidCollectionValues(name, prop.name, invalid);
|
|
185
195
|
}
|
|
186
196
|
if (Array.isArray(value)) {
|
|
187
197
|
collection.set(items);
|
|
188
198
|
}
|
|
189
|
-
else {
|
|
199
|
+
else {
|
|
200
|
+
// append to the collection in case of assigning a single value instead of array
|
|
190
201
|
collection.add(items);
|
|
191
202
|
}
|
|
192
203
|
}
|
|
@@ -207,11 +218,12 @@ export class EntityAssigner {
|
|
|
207
218
|
entity[propName].push(...Object.values(tmp));
|
|
208
219
|
});
|
|
209
220
|
}
|
|
210
|
-
const create = () => EntityAssigner.validateEM(em) &&
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
221
|
+
const create = () => EntityAssigner.validateEM(em) &&
|
|
222
|
+
em.getEntityFactory().createEmbeddable(prop.targetMeta.class, value, {
|
|
223
|
+
convertCustomTypes: options.convertCustomTypes,
|
|
224
|
+
newEntity: options.mergeEmbeddedProperties ? !('propName' in entity) : true,
|
|
225
|
+
});
|
|
226
|
+
entity[propName] = (options.mergeEmbeddedProperties ? entity[propName] || create() : create());
|
|
215
227
|
Object.keys(value).forEach(key => {
|
|
216
228
|
EntityAssigner.assignProperty(entity[propName], key, prop.embeddedProps, value, options);
|
|
217
229
|
});
|
|
@@ -221,13 +233,13 @@ export class EntityAssigner {
|
|
|
221
233
|
return item;
|
|
222
234
|
}
|
|
223
235
|
if (Utils.isPrimaryKey(item) && EntityAssigner.validateEM(em)) {
|
|
224
|
-
return em.getReference(prop.
|
|
236
|
+
return em.getReference(prop.targetMeta.class, item, options);
|
|
225
237
|
}
|
|
226
238
|
if (Utils.isPlainObject(item) && options.merge && EntityAssigner.validateEM(em)) {
|
|
227
|
-
return em.merge(prop.
|
|
239
|
+
return em.merge(prop.targetMeta.class, item, options);
|
|
228
240
|
}
|
|
229
241
|
if (Utils.isPlainObject(item) && EntityAssigner.validateEM(em)) {
|
|
230
|
-
return em.create(prop.
|
|
242
|
+
return em.create(prop.targetMeta.class, item, options);
|
|
231
243
|
}
|
|
232
244
|
invalid.push(item);
|
|
233
245
|
return item;
|
|
@@ -15,20 +15,19 @@ export interface FactoryOptions {
|
|
|
15
15
|
recomputeSnapshot?: boolean;
|
|
16
16
|
schema?: string;
|
|
17
17
|
parentSchema?: string;
|
|
18
|
+
normalizeAccessors?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Property name to use for identity map lookup instead of the primary key.
|
|
21
|
+
* This is useful for creating references by unique non-PK properties.
|
|
22
|
+
*/
|
|
23
|
+
key?: string;
|
|
18
24
|
}
|
|
19
25
|
export declare class EntityFactory {
|
|
20
|
-
private
|
|
21
|
-
private readonly driver;
|
|
22
|
-
private readonly platform;
|
|
23
|
-
private readonly config;
|
|
24
|
-
private readonly metadata;
|
|
25
|
-
private readonly hydrator;
|
|
26
|
-
private readonly eventManager;
|
|
27
|
-
private readonly comparator;
|
|
26
|
+
#private;
|
|
28
27
|
constructor(em: EntityManager);
|
|
29
28
|
create<T extends object, P extends string = string>(entityName: EntityName<T>, data: EntityData<T>, options?: FactoryOptions): New<T, P>;
|
|
30
29
|
mergeData<T extends object>(meta: EntityMetadata<T>, entity: T, data: EntityData<T>, options?: FactoryOptions): void;
|
|
31
|
-
createReference<T extends object>(entityName: EntityName<T>, id: Primary<T> | Primary<T>[] | Record<string, Primary<T>>, options?: Pick<FactoryOptions, 'merge' | 'convertCustomTypes' | 'schema'>): T;
|
|
30
|
+
createReference<T extends object>(entityName: EntityName<T>, id: Primary<T> | Primary<T>[] | Record<string, Primary<T>>, options?: Pick<FactoryOptions, 'merge' | 'convertCustomTypes' | 'schema' | 'key'>): T;
|
|
32
31
|
createEmbeddable<T extends object>(entityName: EntityName<T>, data: EntityData<T>, options?: Pick<FactoryOptions, 'newEntity' | 'convertCustomTypes'>): T;
|
|
33
32
|
getComparator(): EntityComparator;
|
|
34
33
|
private createEntity;
|
package/entity/EntityFactory.js
CHANGED
|
@@ -4,24 +4,25 @@ import { EventType, ReferenceKind } from '../enums.js';
|
|
|
4
4
|
import { Reference } from './Reference.js';
|
|
5
5
|
import { helper } from './wrap.js';
|
|
6
6
|
import { EntityHelper } from './EntityHelper.js';
|
|
7
|
+
import { JsonType } from '../types/JsonType.js';
|
|
7
8
|
export class EntityFactory {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
#driver;
|
|
10
|
+
#platform;
|
|
11
|
+
#config;
|
|
12
|
+
#metadata;
|
|
13
|
+
#hydrator;
|
|
14
|
+
#eventManager;
|
|
15
|
+
#comparator;
|
|
16
|
+
#em;
|
|
16
17
|
constructor(em) {
|
|
17
|
-
this
|
|
18
|
-
this
|
|
19
|
-
this
|
|
20
|
-
this
|
|
21
|
-
this
|
|
22
|
-
this
|
|
23
|
-
this
|
|
24
|
-
this
|
|
18
|
+
this.#em = em;
|
|
19
|
+
this.#driver = this.#em.getDriver();
|
|
20
|
+
this.#platform = this.#driver.getPlatform();
|
|
21
|
+
this.#config = this.#em.config;
|
|
22
|
+
this.#metadata = this.#em.getMetadata();
|
|
23
|
+
this.#hydrator = this.#config.getHydrator(this.#metadata);
|
|
24
|
+
this.#eventManager = this.#em.getEventManager();
|
|
25
|
+
this.#comparator = this.#em.getComparator();
|
|
25
26
|
}
|
|
26
27
|
create(entityName, data, options = {}) {
|
|
27
28
|
data = Reference.unwrapReference(data);
|
|
@@ -29,16 +30,15 @@ export class EntityFactory {
|
|
|
29
30
|
if (data.__entity) {
|
|
30
31
|
return data;
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
-
const meta = this.metadata.get(entityName);
|
|
33
|
+
const meta = this.#metadata.get(entityName);
|
|
34
34
|
if (meta.virtual) {
|
|
35
35
|
data = { ...data };
|
|
36
36
|
const entity = this.createEntity(data, meta, options);
|
|
37
37
|
this.hydrate(entity, meta, data, options);
|
|
38
38
|
return entity;
|
|
39
39
|
}
|
|
40
|
-
if (
|
|
41
|
-
|
|
40
|
+
if (meta.serializedPrimaryKey) {
|
|
41
|
+
this.denormalizePrimaryKey(meta, data);
|
|
42
42
|
}
|
|
43
43
|
const meta2 = this.processDiscriminatorColumn(meta, data);
|
|
44
44
|
const exists = this.findEntity(data, meta2, options);
|
|
@@ -59,7 +59,7 @@ export class EntityFactory {
|
|
|
59
59
|
wrapped.__initialized = options.initialized;
|
|
60
60
|
if (options.newEntity || meta.forceConstructor || meta.virtual) {
|
|
61
61
|
const tmp = { ...data };
|
|
62
|
-
meta.constructorParams
|
|
62
|
+
meta.constructorParams?.forEach(prop => delete tmp[prop]);
|
|
63
63
|
this.hydrate(entity, meta2, tmp, options);
|
|
64
64
|
// since we now process only a copy of the `data` via hydrator, but later we register the state with the full snapshot,
|
|
65
65
|
// we need to go through all props with custom types that have `ensureComparable: true` and ensure they are comparable
|
|
@@ -70,10 +70,16 @@ export class EntityFactory {
|
|
|
70
70
|
if ([ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
|
|
71
71
|
continue;
|
|
72
72
|
}
|
|
73
|
-
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
73
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
74
|
+
Utils.isPlainObject(data[prop.name])) {
|
|
74
75
|
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
75
76
|
}
|
|
76
|
-
|
|
77
|
+
if (prop.customType instanceof JsonType && this.#platform.convertsJsonAutomatically()) {
|
|
78
|
+
data[prop.name] = prop.customType.convertToDatabaseValue(data[prop.name], this.#platform, {
|
|
79
|
+
key: prop.name,
|
|
80
|
+
mode: 'hydration',
|
|
81
|
+
});
|
|
82
|
+
}
|
|
77
83
|
}
|
|
78
84
|
}
|
|
79
85
|
}
|
|
@@ -81,8 +87,7 @@ export class EntityFactory {
|
|
|
81
87
|
else {
|
|
82
88
|
this.hydrate(entity, meta2, data, options);
|
|
83
89
|
}
|
|
84
|
-
|
|
85
|
-
if (exists && meta.discriminatorColumn && !(entity instanceof meta2.class)) {
|
|
90
|
+
if (exists && meta.root.inheritanceType && !(entity instanceof meta2.class)) {
|
|
86
91
|
Object.setPrototypeOf(entity, meta2.prototype);
|
|
87
92
|
}
|
|
88
93
|
if (options.merge && wrapped.hasPrimaryKey()) {
|
|
@@ -94,11 +99,11 @@ export class EntityFactory {
|
|
|
94
99
|
loaded: options.initialized,
|
|
95
100
|
});
|
|
96
101
|
if (options.recomputeSnapshot) {
|
|
97
|
-
wrapped.__originalEntityData = this
|
|
102
|
+
wrapped.__originalEntityData = this.#comparator.prepareEntity(entity);
|
|
98
103
|
}
|
|
99
104
|
}
|
|
100
|
-
if (this
|
|
101
|
-
this
|
|
105
|
+
if (this.#eventManager.hasListeners(EventType.onInit, meta2)) {
|
|
106
|
+
this.#eventManager.dispatchEvent(EventType.onInit, { entity, meta: meta2, em: this.#em });
|
|
102
107
|
}
|
|
103
108
|
wrapped.__processing = false;
|
|
104
109
|
return entity;
|
|
@@ -106,60 +111,92 @@ export class EntityFactory {
|
|
|
106
111
|
mergeData(meta, entity, data, options = {}) {
|
|
107
112
|
// merge unchanged properties automatically
|
|
108
113
|
data = QueryHelper.processParams(data);
|
|
109
|
-
const existsData = this
|
|
114
|
+
const existsData = this.#comparator.prepareEntity(entity);
|
|
110
115
|
const originalEntityData = helper(entity).__originalEntityData ?? {};
|
|
111
|
-
const diff = this
|
|
116
|
+
const diff = this.#comparator.diffEntities(meta.class, originalEntityData, existsData);
|
|
112
117
|
// version properties are not part of entity snapshots
|
|
113
|
-
if (meta.versionProperty &&
|
|
118
|
+
if (meta.versionProperty &&
|
|
119
|
+
data[meta.versionProperty] &&
|
|
120
|
+
data[meta.versionProperty] !== originalEntityData[meta.versionProperty]) {
|
|
114
121
|
diff[meta.versionProperty] = data[meta.versionProperty];
|
|
115
122
|
}
|
|
116
|
-
const diff2 = this
|
|
123
|
+
const diff2 = this.#comparator.diffEntities(meta.class, existsData, data, { includeInverseSides: true });
|
|
117
124
|
// do not override values changed by user
|
|
118
125
|
Utils.keys(diff).forEach(key => delete diff2[key]);
|
|
119
|
-
Utils.keys(diff2)
|
|
126
|
+
Utils.keys(diff2)
|
|
127
|
+
.filter(key => {
|
|
120
128
|
// ignore null values if there is already present non-null value
|
|
121
129
|
if (existsData[key] != null) {
|
|
122
130
|
return diff2[key] == null;
|
|
123
131
|
}
|
|
124
132
|
return diff2[key] === undefined;
|
|
125
|
-
})
|
|
133
|
+
})
|
|
134
|
+
.forEach(key => delete diff2[key]);
|
|
126
135
|
// but always add collection properties and formulas if they are part of the `data`
|
|
127
136
|
Utils.keys(data)
|
|
128
|
-
.filter(key => meta.properties[key]?.formula ||
|
|
129
|
-
.
|
|
137
|
+
.filter(key => meta.properties[key]?.formula ||
|
|
138
|
+
[ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(meta.properties[key]?.kind))
|
|
139
|
+
.forEach(key => (diff2[key] = data[key]));
|
|
130
140
|
// rehydrated with the new values, skip those changed by user
|
|
131
|
-
|
|
141
|
+
// use full hydration if the entity is already initialized, even if the caller used `initialized: false`
|
|
142
|
+
// (e.g. from createReference), otherwise scalar properties in diff2 won't be applied
|
|
143
|
+
const initialized = options.initialized || helper(entity).__initialized;
|
|
144
|
+
this.hydrate(entity, meta, diff2, initialized ? { ...options, initialized } : options);
|
|
132
145
|
// we need to update the entity data only with keys that were not present before
|
|
133
|
-
const nullVal = this
|
|
146
|
+
const nullVal = this.#config.get('forceUndefined') ? undefined : null;
|
|
134
147
|
Utils.keys(diff2).forEach(key => {
|
|
135
148
|
const prop = meta.properties[key];
|
|
136
|
-
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
149
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
150
|
+
Utils.isPlainObject(data[prop.name])) {
|
|
151
|
+
// oxfmt-ignore
|
|
137
152
|
diff2[key] = entity[prop.name] ? helper(entity[prop.name]).getPrimaryKey(options.convertCustomTypes) : null;
|
|
138
153
|
}
|
|
154
|
+
if (!options.convertCustomTypes &&
|
|
155
|
+
[ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE, ReferenceKind.SCALAR].includes(prop.kind) &&
|
|
156
|
+
prop.customType?.ensureComparable(meta, prop) &&
|
|
157
|
+
diff2[key] != null) {
|
|
158
|
+
const converted = prop.customType.convertToJSValue(diff2[key], this.#platform, { force: true });
|
|
159
|
+
diff2[key] = prop.customType.convertToDatabaseValue(converted, this.#platform, { fromQuery: true });
|
|
160
|
+
}
|
|
139
161
|
originalEntityData[key] = diff2[key] === null ? nullVal : diff2[key];
|
|
140
162
|
helper(entity).__loadedProperties.add(key);
|
|
141
163
|
});
|
|
142
164
|
// in case of joined loading strategy, we need to cascade the merging to possibly loaded relations manually
|
|
143
165
|
meta.relations.forEach(prop => {
|
|
144
|
-
if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) &&
|
|
166
|
+
if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) &&
|
|
167
|
+
Array.isArray(data[prop.name])) {
|
|
145
168
|
// instead of trying to match the collection items (which could easily fail if the collection was loaded with different ordering),
|
|
146
169
|
// we just create the entity from scratch, which will automatically pick the right one from the identity map and call `mergeData` on it
|
|
147
170
|
data[prop.name]
|
|
148
171
|
.filter(child => Utils.isPlainObject(child)) // objects with prototype can be PKs (e.g. `ObjectId`)
|
|
149
|
-
.forEach(child => this.create(prop.
|
|
172
|
+
.forEach(child => this.create(prop.targetMeta.class, child, options)); // we can ignore the value, we just care about the `mergeData` call
|
|
150
173
|
return;
|
|
151
174
|
}
|
|
152
|
-
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
153
|
-
|
|
175
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
176
|
+
Utils.isPlainObject(data[prop.name]) &&
|
|
177
|
+
entity[prop.name] &&
|
|
178
|
+
helper(entity[prop.name]).__initialized) {
|
|
179
|
+
this.create(prop.targetMeta.class, data[prop.name], options); // we can ignore the value, we just care about the `mergeData` call
|
|
154
180
|
}
|
|
155
181
|
});
|
|
156
|
-
|
|
182
|
+
this.unitOfWork.normalizeEntityData(meta, originalEntityData);
|
|
157
183
|
}
|
|
158
184
|
createReference(entityName, id, options = {}) {
|
|
159
185
|
options.convertCustomTypes ??= true;
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
|
|
186
|
+
const meta = this.#metadata.get(entityName);
|
|
187
|
+
const schema = this.#driver.getSchemaName(meta, options);
|
|
188
|
+
// Handle alternate key lookup
|
|
189
|
+
if (options.key) {
|
|
190
|
+
const value = '' + (Array.isArray(id) ? id[0] : Utils.isPlainObject(id) ? id[options.key] : id);
|
|
191
|
+
const exists = this.unitOfWork.getByKey(entityName, options.key, value, schema, options.convertCustomTypes);
|
|
192
|
+
if (exists) {
|
|
193
|
+
return exists;
|
|
194
|
+
}
|
|
195
|
+
// Create entity stub - storeByKey will set the alternate key property and store in identity map
|
|
196
|
+
const entity = this.create(entityName, {}, { ...options, initialized: false });
|
|
197
|
+
this.unitOfWork.storeByKey(entity, options.key, value, schema, options.convertCustomTypes);
|
|
198
|
+
return entity;
|
|
199
|
+
}
|
|
163
200
|
if (meta.simplePK) {
|
|
164
201
|
const exists = this.unitOfWork.getById(entityName, id, schema);
|
|
165
202
|
if (exists) {
|
|
@@ -171,7 +208,7 @@ export class EntityFactory {
|
|
|
171
208
|
if (Array.isArray(id)) {
|
|
172
209
|
id = Utils.getPrimaryKeyCondFromArray(id, meta);
|
|
173
210
|
}
|
|
174
|
-
const pks = Utils.getOrderedPrimaryKeys(id, meta, this
|
|
211
|
+
const pks = Utils.getOrderedPrimaryKeys(id, meta, this.#platform);
|
|
175
212
|
const exists = this.unitOfWork.getById(entityName, pks, schema, options.convertCustomTypes);
|
|
176
213
|
if (exists) {
|
|
177
214
|
return exists;
|
|
@@ -182,19 +219,18 @@ export class EntityFactory {
|
|
|
182
219
|
return this.create(entityName, id, { ...options, initialized: false });
|
|
183
220
|
}
|
|
184
221
|
createEmbeddable(entityName, data, options = {}) {
|
|
185
|
-
entityName = Utils.className(entityName);
|
|
186
222
|
data = { ...data };
|
|
187
|
-
const meta = this
|
|
223
|
+
const meta = this.#metadata.get(entityName);
|
|
188
224
|
const meta2 = this.processDiscriminatorColumn(meta, data);
|
|
189
225
|
return this.createEntity(data, meta2, options);
|
|
190
226
|
}
|
|
191
227
|
getComparator() {
|
|
192
|
-
return this
|
|
228
|
+
return this.#comparator;
|
|
193
229
|
}
|
|
194
230
|
createEntity(data, meta, options) {
|
|
195
|
-
const schema = this
|
|
231
|
+
const schema = this.#driver.getSchemaName(meta, options);
|
|
196
232
|
if (options.newEntity || meta.forceConstructor || meta.virtual) {
|
|
197
|
-
if (
|
|
233
|
+
if (meta.polymorphs) {
|
|
198
234
|
throw new Error(`Cannot create entity ${meta.className}, class prototype is unknown`);
|
|
199
235
|
}
|
|
200
236
|
const params = this.extractConstructorParams(meta, data, options);
|
|
@@ -203,7 +239,7 @@ export class EntityFactory {
|
|
|
203
239
|
const entity = new Entity(...params);
|
|
204
240
|
// creating managed entity instance when `forceEntityConstructor` is enabled,
|
|
205
241
|
// we need to wipe all the values as they would cause update queries on next flush
|
|
206
|
-
if (!options.newEntity && (meta.forceConstructor || this
|
|
242
|
+
if (!options.newEntity && (meta.forceConstructor || this.#config.get('forceEntityConstructor'))) {
|
|
207
243
|
meta.props
|
|
208
244
|
.filter(prop => prop.persist !== false && !prop.primary && data[prop.name] === undefined)
|
|
209
245
|
.forEach(prop => delete entity[prop.name]);
|
|
@@ -223,7 +259,7 @@ export class EntityFactory {
|
|
|
223
259
|
helper(entity).__processing = !meta.embeddable && !meta.virtual;
|
|
224
260
|
helper(entity).__schema = schema;
|
|
225
261
|
if (options.merge && !options.newEntity) {
|
|
226
|
-
this
|
|
262
|
+
this.#hydrator.hydrateReference(entity, meta, data, this, options.convertCustomTypes, options.schema, options.parentSchema);
|
|
227
263
|
this.unitOfWork.register(entity);
|
|
228
264
|
}
|
|
229
265
|
if (options.initialized) {
|
|
@@ -234,112 +270,128 @@ export class EntityFactory {
|
|
|
234
270
|
assignDefaultValues(entity, meta) {
|
|
235
271
|
for (const prop of meta.props) {
|
|
236
272
|
if (prop.onCreate) {
|
|
237
|
-
entity[prop.name] ??= prop.onCreate(entity, this
|
|
273
|
+
entity[prop.name] ??= prop.onCreate(entity, this.#em);
|
|
238
274
|
}
|
|
239
275
|
}
|
|
240
276
|
}
|
|
241
277
|
hydrate(entity, meta, data, options) {
|
|
242
278
|
if (options.initialized) {
|
|
243
|
-
this
|
|
279
|
+
this.#hydrator.hydrate(entity, meta, data, this, 'full', options.newEntity, options.convertCustomTypes, options.schema, this.#driver.getSchemaName(meta, options), options.normalizeAccessors);
|
|
244
280
|
}
|
|
245
281
|
else {
|
|
246
|
-
this
|
|
282
|
+
this.#hydrator.hydrateReference(entity, meta, data, this, options.convertCustomTypes, options.schema, this.#driver.getSchemaName(meta, options), options.normalizeAccessors);
|
|
247
283
|
}
|
|
248
284
|
Utils.keys(data).forEach(key => {
|
|
249
285
|
helper(entity)?.__loadedProperties.add(key);
|
|
250
286
|
helper(entity)?.__serializationContext.fields?.add(key);
|
|
251
287
|
});
|
|
252
|
-
const processOnCreateHooksEarly = options.processOnCreateHooksEarly ?? this
|
|
288
|
+
const processOnCreateHooksEarly = options.processOnCreateHooksEarly ?? this.#config.get('processOnCreateHooksEarly');
|
|
253
289
|
if (options.newEntity && processOnCreateHooksEarly) {
|
|
254
290
|
this.assignDefaultValues(entity, meta);
|
|
255
291
|
}
|
|
256
292
|
}
|
|
257
293
|
findEntity(data, meta, options) {
|
|
258
|
-
const schema = this
|
|
294
|
+
const schema = this.#driver.getSchemaName(meta, options);
|
|
259
295
|
if (meta.simplePK) {
|
|
260
|
-
return this.unitOfWork.getById(meta.
|
|
296
|
+
return this.unitOfWork.getById(meta.class, data[meta.primaryKeys[0]], schema);
|
|
261
297
|
}
|
|
262
298
|
if (!Array.isArray(data) && meta.primaryKeys.some(pk => data[pk] == null)) {
|
|
263
299
|
return undefined;
|
|
264
300
|
}
|
|
265
|
-
const pks = Utils.getOrderedPrimaryKeys(data, meta, this
|
|
266
|
-
return this.unitOfWork.getById(meta.
|
|
301
|
+
const pks = Utils.getOrderedPrimaryKeys(data, meta, this.#platform, options.convertCustomTypes);
|
|
302
|
+
return this.unitOfWork.getById(meta.class, pks, schema);
|
|
267
303
|
}
|
|
268
304
|
processDiscriminatorColumn(meta, data) {
|
|
269
|
-
|
|
305
|
+
// Handle STI discriminator (persisted column)
|
|
306
|
+
if (meta.root.inheritanceType === 'sti') {
|
|
307
|
+
const prop = meta.properties[meta.root.discriminatorColumn];
|
|
308
|
+
const value = data[prop.name];
|
|
309
|
+
const type = meta.root.discriminatorMap[value];
|
|
310
|
+
meta = type ? this.#metadata.get(type) : meta;
|
|
270
311
|
return meta;
|
|
271
312
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
313
|
+
// Handle TPT discriminator (computed at query time)
|
|
314
|
+
if (meta.root.inheritanceType === 'tpt' && meta.root.discriminatorMap) {
|
|
315
|
+
const value = data[meta.root.tptDiscriminatorColumn];
|
|
316
|
+
if (value) {
|
|
317
|
+
const type = meta.root.discriminatorMap[value];
|
|
318
|
+
meta = type ? this.#metadata.get(type) : meta;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
276
321
|
return meta;
|
|
277
322
|
}
|
|
278
323
|
/**
|
|
279
324
|
* denormalize PK to value required by driver (e.g. ObjectId)
|
|
280
325
|
*/
|
|
281
|
-
denormalizePrimaryKey(
|
|
282
|
-
const pk =
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
data[
|
|
326
|
+
denormalizePrimaryKey(meta, data) {
|
|
327
|
+
const pk = meta.getPrimaryProp();
|
|
328
|
+
const spk = meta.properties[meta.serializedPrimaryKey];
|
|
329
|
+
if (!spk?.serializedPrimaryKey) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
if (pk.type === 'ObjectId' && (data[pk.name] != null || data[spk.name] != null)) {
|
|
333
|
+
data[pk.name] = this.#platform.denormalizePrimaryKey((data[spk.name] || data[pk.name]));
|
|
334
|
+
delete data[spk.name];
|
|
290
335
|
}
|
|
291
336
|
}
|
|
292
337
|
/**
|
|
293
338
|
* returns parameters for entity constructor, creating references from plain ids
|
|
294
339
|
*/
|
|
295
340
|
extractConstructorParams(meta, data, options) {
|
|
341
|
+
if (!meta.constructorParams) {
|
|
342
|
+
return [data];
|
|
343
|
+
}
|
|
296
344
|
return meta.constructorParams.map(k => {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
345
|
+
const prop = meta.properties[k];
|
|
346
|
+
const value = data[k];
|
|
347
|
+
if (prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && value) {
|
|
348
|
+
const pk = Reference.unwrapReference(value);
|
|
349
|
+
const entity = this.unitOfWork.getById(prop.targetMeta.class, pk, options.schema, true);
|
|
300
350
|
if (entity) {
|
|
301
351
|
return entity;
|
|
302
352
|
}
|
|
303
|
-
if (Utils.isEntity(
|
|
304
|
-
return
|
|
353
|
+
if (Utils.isEntity(value)) {
|
|
354
|
+
return value;
|
|
305
355
|
}
|
|
306
|
-
const nakedPk = Utils.extractPK(
|
|
307
|
-
if (Utils.isObject(
|
|
308
|
-
return this.create(
|
|
356
|
+
const nakedPk = Utils.extractPK(value, prop.targetMeta, true);
|
|
357
|
+
if (Utils.isObject(value) && !nakedPk) {
|
|
358
|
+
return this.create(prop.targetMeta.class, value, options);
|
|
309
359
|
}
|
|
310
360
|
const { newEntity, initialized, ...rest } = options;
|
|
311
|
-
const target = this.createReference(
|
|
312
|
-
return Reference.wrapReference(target,
|
|
361
|
+
const target = this.createReference(prop.targetMeta.class, nakedPk, rest);
|
|
362
|
+
return Reference.wrapReference(target, prop);
|
|
313
363
|
}
|
|
314
|
-
if (
|
|
315
|
-
/* v8 ignore next
|
|
316
|
-
if (Utils.isEntity(
|
|
317
|
-
return
|
|
364
|
+
if (prop?.kind === ReferenceKind.EMBEDDED && value) {
|
|
365
|
+
/* v8 ignore next */
|
|
366
|
+
if (Utils.isEntity(value)) {
|
|
367
|
+
return value;
|
|
318
368
|
}
|
|
319
|
-
return this.createEmbeddable(
|
|
369
|
+
return this.createEmbeddable(prop.targetMeta.class, value, options);
|
|
320
370
|
}
|
|
321
|
-
if (!
|
|
371
|
+
if (!prop) {
|
|
322
372
|
const tmp = { ...data };
|
|
323
373
|
for (const prop of meta.props) {
|
|
324
374
|
if (!options.convertCustomTypes || !prop.customType || tmp[prop.name] == null) {
|
|
325
375
|
continue;
|
|
326
376
|
}
|
|
327
|
-
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
328
|
-
|
|
377
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
378
|
+
Utils.isPlainObject(tmp[prop.name]) &&
|
|
379
|
+
!Utils.extractPK(tmp[prop.name], prop.targetMeta, true)) {
|
|
380
|
+
tmp[prop.name] = Reference.wrapReference(this.create(prop.targetMeta.class, tmp[prop.name], options), prop);
|
|
329
381
|
}
|
|
330
382
|
else if (prop.kind === ReferenceKind.SCALAR) {
|
|
331
|
-
tmp[prop.name] = prop.customType.convertToJSValue(tmp[prop.name], this
|
|
383
|
+
tmp[prop.name] = prop.customType.convertToJSValue(tmp[prop.name], this.#platform);
|
|
332
384
|
}
|
|
333
385
|
}
|
|
334
386
|
return tmp;
|
|
335
387
|
}
|
|
336
|
-
if (options.convertCustomTypes &&
|
|
337
|
-
return
|
|
388
|
+
if (options.convertCustomTypes && prop.customType && value != null) {
|
|
389
|
+
return prop.customType.convertToJSValue(value, this.#platform);
|
|
338
390
|
}
|
|
339
|
-
return
|
|
391
|
+
return value;
|
|
340
392
|
});
|
|
341
393
|
}
|
|
342
394
|
get unitOfWork() {
|
|
343
|
-
return this
|
|
395
|
+
return this.#em.getUnitOfWork(false);
|
|
344
396
|
}
|
|
345
397
|
}
|