@mikro-orm/core 7.0.0-dev.7 → 7.0.0-dev.71
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 +85 -42
- package/EntityManager.js +282 -194
- package/MikroORM.d.ts +11 -29
- package/MikroORM.js +33 -127
- package/README.md +3 -2
- package/cache/FileCacheAdapter.js +1 -2
- package/connections/Connection.d.ts +11 -7
- package/connections/Connection.js +16 -14
- package/drivers/DatabaseDriver.d.ts +11 -5
- package/drivers/DatabaseDriver.js +13 -4
- package/drivers/IDatabaseDriver.d.ts +27 -5
- package/entity/BaseEntity.d.ts +0 -1
- package/entity/BaseEntity.js +0 -3
- package/entity/Collection.d.ts +98 -30
- package/entity/Collection.js +432 -93
- package/entity/EntityAssigner.d.ts +1 -1
- package/entity/EntityAssigner.js +9 -1
- package/entity/EntityFactory.d.ts +7 -0
- package/entity/EntityFactory.js +63 -40
- package/entity/EntityHelper.js +26 -9
- package/entity/EntityLoader.d.ts +5 -4
- package/entity/EntityLoader.js +69 -36
- package/entity/EntityRepository.d.ts +1 -1
- package/entity/EntityValidator.js +4 -4
- package/entity/Reference.d.ts +9 -7
- package/entity/Reference.js +32 -5
- package/entity/WrappedEntity.d.ts +0 -2
- package/entity/WrappedEntity.js +1 -5
- package/entity/defineEntity.d.ts +549 -0
- package/entity/defineEntity.js +529 -0
- package/entity/index.d.ts +2 -1
- package/entity/index.js +2 -1
- package/entity/utils.d.ts +7 -0
- package/entity/utils.js +15 -3
- package/enums.d.ts +20 -5
- package/enums.js +13 -0
- package/errors.d.ts +6 -1
- package/errors.js +14 -4
- package/events/EventSubscriber.d.ts +3 -1
- package/hydration/ObjectHydrator.d.ts +4 -4
- package/hydration/ObjectHydrator.js +35 -24
- package/index.d.ts +2 -2
- package/index.js +1 -2
- package/logging/DefaultLogger.d.ts +1 -1
- package/logging/SimpleLogger.d.ts +1 -1
- package/metadata/EntitySchema.d.ts +9 -13
- package/metadata/EntitySchema.js +44 -26
- package/metadata/MetadataDiscovery.d.ts +6 -7
- package/metadata/MetadataDiscovery.js +161 -162
- package/metadata/MetadataProvider.d.ts +2 -2
- package/metadata/MetadataProvider.js +15 -0
- package/metadata/MetadataStorage.d.ts +0 -4
- package/metadata/MetadataStorage.js +6 -10
- package/metadata/MetadataValidator.d.ts +0 -7
- package/metadata/MetadataValidator.js +4 -13
- package/metadata/discover-entities.d.ts +5 -0
- package/metadata/discover-entities.js +39 -0
- package/metadata/index.d.ts +1 -1
- package/metadata/index.js +1 -1
- package/metadata/types.d.ts +480 -0
- package/metadata/types.js +1 -0
- package/naming-strategy/AbstractNamingStrategy.d.ts +5 -1
- package/naming-strategy/AbstractNamingStrategy.js +7 -1
- package/naming-strategy/NamingStrategy.d.ts +11 -1
- package/package.json +11 -10
- package/platforms/Platform.d.ts +6 -10
- package/platforms/Platform.js +6 -22
- package/serialization/EntitySerializer.d.ts +2 -0
- package/serialization/EntitySerializer.js +29 -11
- package/serialization/EntityTransformer.js +22 -12
- package/serialization/SerializationContext.js +14 -11
- package/types/ArrayType.d.ts +1 -1
- package/types/ArrayType.js +1 -2
- package/types/BigIntType.d.ts +8 -6
- package/types/BlobType.d.ts +0 -1
- package/types/BlobType.js +0 -3
- package/types/BooleanType.d.ts +2 -1
- package/types/BooleanType.js +3 -0
- package/types/DecimalType.d.ts +6 -4
- package/types/DecimalType.js +1 -1
- package/types/DoubleType.js +1 -1
- package/types/JsonType.d.ts +1 -1
- package/types/JsonType.js +7 -2
- package/types/Type.d.ts +2 -1
- package/types/Type.js +1 -1
- package/types/Uint8ArrayType.d.ts +0 -1
- package/types/Uint8ArrayType.js +0 -3
- package/types/index.d.ts +1 -1
- package/typings.d.ts +112 -77
- package/typings.js +32 -32
- package/unit-of-work/ChangeSetComputer.js +8 -3
- package/unit-of-work/ChangeSetPersister.d.ts +4 -2
- package/unit-of-work/ChangeSetPersister.js +37 -16
- package/unit-of-work/UnitOfWork.d.ts +8 -1
- package/unit-of-work/UnitOfWork.js +111 -54
- package/utils/AbstractSchemaGenerator.d.ts +5 -5
- package/utils/AbstractSchemaGenerator.js +10 -8
- package/utils/Configuration.d.ts +200 -191
- package/utils/Configuration.js +141 -152
- package/utils/ConfigurationLoader.d.ts +3 -44
- package/utils/ConfigurationLoader.js +26 -239
- package/utils/Cursor.d.ts +3 -3
- package/utils/Cursor.js +3 -0
- package/utils/DataloaderUtils.d.ts +15 -5
- package/utils/DataloaderUtils.js +53 -7
- package/utils/EntityComparator.d.ts +8 -4
- package/utils/EntityComparator.js +107 -60
- package/utils/QueryHelper.d.ts +9 -1
- package/utils/QueryHelper.js +69 -8
- package/utils/RawQueryFragment.d.ts +36 -4
- package/utils/RawQueryFragment.js +34 -13
- package/utils/TransactionManager.d.ts +65 -0
- package/utils/TransactionManager.js +223 -0
- package/utils/Utils.d.ts +17 -84
- package/utils/Utils.js +132 -252
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/upsert-utils.d.ts +7 -2
- package/utils/upsert-utils.js +52 -1
- 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 -18
- package/decorators/Embedded.js +0 -18
- package/decorators/Entity.d.ts +0 -18
- 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 -40
- package/decorators/ManyToMany.js +0 -14
- package/decorators/ManyToOne.d.ts +0 -30
- 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 -24
- 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 -13
- 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 -116
- package/entity/ArrayCollection.js +0 -402
- 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/EntityFactory.js
CHANGED
|
@@ -4,6 +4,7 @@ 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
|
em;
|
|
9
10
|
driver;
|
|
@@ -37,14 +38,15 @@ export class EntityFactory {
|
|
|
37
38
|
this.hydrate(entity, meta, data, options);
|
|
38
39
|
return entity;
|
|
39
40
|
}
|
|
40
|
-
if (
|
|
41
|
-
|
|
41
|
+
if (meta.serializedPrimaryKey) {
|
|
42
|
+
this.denormalizePrimaryKey(meta, data);
|
|
42
43
|
}
|
|
43
44
|
const meta2 = this.processDiscriminatorColumn(meta, data);
|
|
44
45
|
const exists = this.findEntity(data, meta2, options);
|
|
45
46
|
let wrapped = exists && helper(exists);
|
|
46
47
|
if (wrapped && !options.refresh) {
|
|
47
48
|
wrapped.__processing = true;
|
|
49
|
+
Utils.dropUndefinedProperties(data);
|
|
48
50
|
this.mergeData(meta2, exists, data, options);
|
|
49
51
|
wrapped.__processing = false;
|
|
50
52
|
if (wrapped.isInitialized()) {
|
|
@@ -58,7 +60,7 @@ export class EntityFactory {
|
|
|
58
60
|
wrapped.__initialized = options.initialized;
|
|
59
61
|
if (options.newEntity || meta.forceConstructor || meta.virtual) {
|
|
60
62
|
const tmp = { ...data };
|
|
61
|
-
meta.constructorParams
|
|
63
|
+
meta.constructorParams?.forEach(prop => delete tmp[prop]);
|
|
62
64
|
this.hydrate(entity, meta2, tmp, options);
|
|
63
65
|
// since we now process only a copy of the `data` via hydrator, but later we register the state with the full snapshot,
|
|
64
66
|
// we need to go through all props with custom types that have `ensureComparable: true` and ensure they are comparable
|
|
@@ -70,9 +72,11 @@ export class EntityFactory {
|
|
|
70
72
|
continue;
|
|
71
73
|
}
|
|
72
74
|
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(data[prop.name])) {
|
|
73
|
-
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta
|
|
75
|
+
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
76
|
+
}
|
|
77
|
+
if (prop.customType instanceof JsonType && this.platform.convertsJsonAutomatically()) {
|
|
78
|
+
data[prop.name] = prop.customType.convertToDatabaseValue(data[prop.name], this.platform, { key: prop.name, mode: 'hydration' });
|
|
74
79
|
}
|
|
75
|
-
data[prop.name] = prop.customType.convertToDatabaseValue(data[prop.name], this.platform, { key: prop.name, mode: 'hydration' });
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
}
|
|
@@ -80,7 +84,6 @@ export class EntityFactory {
|
|
|
80
84
|
else {
|
|
81
85
|
this.hydrate(entity, meta2, data, options);
|
|
82
86
|
}
|
|
83
|
-
wrapped.__touched = false;
|
|
84
87
|
if (exists && meta.discriminatorColumn && !(entity instanceof meta2.class)) {
|
|
85
88
|
Object.setPrototypeOf(entity, meta2.prototype);
|
|
86
89
|
}
|
|
@@ -112,7 +115,7 @@ export class EntityFactory {
|
|
|
112
115
|
if (meta.versionProperty && data[meta.versionProperty] && data[meta.versionProperty] !== originalEntityData[meta.versionProperty]) {
|
|
113
116
|
diff[meta.versionProperty] = data[meta.versionProperty];
|
|
114
117
|
}
|
|
115
|
-
const diff2 = this.comparator.diffEntities(meta.className, existsData, data);
|
|
118
|
+
const diff2 = this.comparator.diffEntities(meta.className, existsData, data, { includeInverseSides: true });
|
|
116
119
|
// do not override values changed by user
|
|
117
120
|
Utils.keys(diff).forEach(key => delete diff2[key]);
|
|
118
121
|
Utils.keys(diff2).filter(key => {
|
|
@@ -135,6 +138,10 @@ export class EntityFactory {
|
|
|
135
138
|
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(data[prop.name])) {
|
|
136
139
|
diff2[key] = entity[prop.name] ? helper(entity[prop.name]).getPrimaryKey(options.convertCustomTypes) : null;
|
|
137
140
|
}
|
|
141
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE, ReferenceKind.SCALAR].includes(prop.kind) && prop.customType?.ensureComparable(meta, prop) && diff2[key] != null) {
|
|
142
|
+
const converted = prop.customType.convertToJSValue(diff2[key], this.platform, { force: true });
|
|
143
|
+
diff2[key] = prop.customType.convertToDatabaseValue(converted, this.platform, { fromQuery: true });
|
|
144
|
+
}
|
|
138
145
|
originalEntityData[key] = diff2[key] === null ? nullVal : diff2[key];
|
|
139
146
|
helper(entity).__loadedProperties.add(key);
|
|
140
147
|
});
|
|
@@ -152,7 +159,7 @@ export class EntityFactory {
|
|
|
152
159
|
this.create(prop.type, data[prop.name], options); // we can ignore the value, we just care about the `mergeData` call
|
|
153
160
|
}
|
|
154
161
|
});
|
|
155
|
-
|
|
162
|
+
this.unitOfWork.normalizeEntityData(meta, originalEntityData);
|
|
156
163
|
}
|
|
157
164
|
createReference(entityName, id, options = {}) {
|
|
158
165
|
options.convertCustomTypes ??= true;
|
|
@@ -170,8 +177,8 @@ export class EntityFactory {
|
|
|
170
177
|
if (Array.isArray(id)) {
|
|
171
178
|
id = Utils.getPrimaryKeyCondFromArray(id, meta);
|
|
172
179
|
}
|
|
173
|
-
const pks = Utils.getOrderedPrimaryKeys(id, meta, this.platform
|
|
174
|
-
const exists = this.unitOfWork.getById(entityName, pks, schema);
|
|
180
|
+
const pks = Utils.getOrderedPrimaryKeys(id, meta, this.platform);
|
|
181
|
+
const exists = this.unitOfWork.getById(entityName, pks, schema, options.convertCustomTypes);
|
|
175
182
|
if (exists) {
|
|
176
183
|
return exists;
|
|
177
184
|
}
|
|
@@ -230,17 +237,28 @@ export class EntityFactory {
|
|
|
230
237
|
}
|
|
231
238
|
return entity;
|
|
232
239
|
}
|
|
240
|
+
assignDefaultValues(entity, meta) {
|
|
241
|
+
for (const prop of meta.props) {
|
|
242
|
+
if (prop.onCreate) {
|
|
243
|
+
entity[prop.name] ??= prop.onCreate(entity, this.em);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
233
247
|
hydrate(entity, meta, data, options) {
|
|
234
248
|
if (options.initialized) {
|
|
235
|
-
this.hydrator.hydrate(entity, meta, data, this, 'full', options.newEntity, options.convertCustomTypes, options.schema, this.driver.getSchemaName(meta, options));
|
|
249
|
+
this.hydrator.hydrate(entity, meta, data, this, 'full', options.newEntity, options.convertCustomTypes, options.schema, this.driver.getSchemaName(meta, options), options.normalizeAccessors);
|
|
236
250
|
}
|
|
237
251
|
else {
|
|
238
|
-
this.hydrator.hydrateReference(entity, meta, data, this, options.convertCustomTypes, options.schema, this.driver.getSchemaName(meta, options));
|
|
252
|
+
this.hydrator.hydrateReference(entity, meta, data, this, options.convertCustomTypes, options.schema, this.driver.getSchemaName(meta, options), options.normalizeAccessors);
|
|
239
253
|
}
|
|
240
254
|
Utils.keys(data).forEach(key => {
|
|
241
255
|
helper(entity)?.__loadedProperties.add(key);
|
|
242
256
|
helper(entity)?.__serializationContext.fields?.add(key);
|
|
243
257
|
});
|
|
258
|
+
const processOnCreateHooksEarly = options.processOnCreateHooksEarly ?? this.config.get('processOnCreateHooksEarly');
|
|
259
|
+
if (options.newEntity && processOnCreateHooksEarly) {
|
|
260
|
+
this.assignDefaultValues(entity, meta);
|
|
261
|
+
}
|
|
244
262
|
}
|
|
245
263
|
findEntity(data, meta, options) {
|
|
246
264
|
const schema = this.driver.getSchemaName(meta, options);
|
|
@@ -250,7 +268,7 @@ export class EntityFactory {
|
|
|
250
268
|
if (!Array.isArray(data) && meta.primaryKeys.some(pk => data[pk] == null)) {
|
|
251
269
|
return undefined;
|
|
252
270
|
}
|
|
253
|
-
const pks = Utils.getOrderedPrimaryKeys(data, meta, this.platform);
|
|
271
|
+
const pks = Utils.getOrderedPrimaryKeys(data, meta, this.platform, options.convertCustomTypes);
|
|
254
272
|
return this.unitOfWork.getById(meta.className, pks, schema);
|
|
255
273
|
}
|
|
256
274
|
processDiscriminatorColumn(meta, data) {
|
|
@@ -266,47 +284,52 @@ export class EntityFactory {
|
|
|
266
284
|
/**
|
|
267
285
|
* denormalize PK to value required by driver (e.g. ObjectId)
|
|
268
286
|
*/
|
|
269
|
-
denormalizePrimaryKey(
|
|
270
|
-
const pk =
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
data[
|
|
287
|
+
denormalizePrimaryKey(meta, data) {
|
|
288
|
+
const pk = meta.getPrimaryProp();
|
|
289
|
+
const spk = meta.properties[meta.serializedPrimaryKey];
|
|
290
|
+
if (!spk?.serializedPrimaryKey) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
if (pk.type === 'ObjectId' && (data[pk.name] != null || data[spk.name] != null)) {
|
|
294
|
+
data[pk.name] = this.platform.denormalizePrimaryKey((data[spk.name] || data[pk.name]));
|
|
295
|
+
delete data[spk.name];
|
|
278
296
|
}
|
|
279
297
|
}
|
|
280
298
|
/**
|
|
281
299
|
* returns parameters for entity constructor, creating references from plain ids
|
|
282
300
|
*/
|
|
283
301
|
extractConstructorParams(meta, data, options) {
|
|
302
|
+
if (!meta.constructorParams) {
|
|
303
|
+
return [data];
|
|
304
|
+
}
|
|
284
305
|
return meta.constructorParams.map(k => {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
306
|
+
const prop = meta.properties[k];
|
|
307
|
+
const value = data[k];
|
|
308
|
+
if (prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && value) {
|
|
309
|
+
const pk = Reference.unwrapReference(value);
|
|
310
|
+
const entity = this.unitOfWork.getById(prop.type, pk, options.schema, true);
|
|
288
311
|
if (entity) {
|
|
289
312
|
return entity;
|
|
290
313
|
}
|
|
291
|
-
if (Utils.isEntity(
|
|
292
|
-
return
|
|
314
|
+
if (Utils.isEntity(value)) {
|
|
315
|
+
return value;
|
|
293
316
|
}
|
|
294
|
-
const nakedPk = Utils.extractPK(
|
|
295
|
-
if (Utils.isObject(
|
|
296
|
-
return this.create(
|
|
317
|
+
const nakedPk = Utils.extractPK(value, prop.targetMeta, true);
|
|
318
|
+
if (Utils.isObject(value) && !nakedPk) {
|
|
319
|
+
return this.create(prop.type, value, options);
|
|
297
320
|
}
|
|
298
321
|
const { newEntity, initialized, ...rest } = options;
|
|
299
|
-
const target = this.createReference(
|
|
300
|
-
return Reference.wrapReference(target,
|
|
322
|
+
const target = this.createReference(prop.type, nakedPk, rest);
|
|
323
|
+
return Reference.wrapReference(target, prop);
|
|
301
324
|
}
|
|
302
|
-
if (
|
|
325
|
+
if (prop?.kind === ReferenceKind.EMBEDDED && value) {
|
|
303
326
|
/* v8 ignore next 3 */
|
|
304
|
-
if (Utils.isEntity(
|
|
305
|
-
return
|
|
327
|
+
if (Utils.isEntity(value)) {
|
|
328
|
+
return value;
|
|
306
329
|
}
|
|
307
|
-
return this.createEmbeddable(
|
|
330
|
+
return this.createEmbeddable(prop.type, value, options);
|
|
308
331
|
}
|
|
309
|
-
if (!
|
|
332
|
+
if (!prop) {
|
|
310
333
|
const tmp = { ...data };
|
|
311
334
|
for (const prop of meta.props) {
|
|
312
335
|
if (!options.convertCustomTypes || !prop.customType || tmp[prop.name] == null) {
|
|
@@ -321,10 +344,10 @@ export class EntityFactory {
|
|
|
321
344
|
}
|
|
322
345
|
return tmp;
|
|
323
346
|
}
|
|
324
|
-
if (options.convertCustomTypes &&
|
|
325
|
-
return
|
|
347
|
+
if (options.convertCustomTypes && prop.customType && value != null) {
|
|
348
|
+
return prop.customType.convertToJSValue(value, this.platform);
|
|
326
349
|
}
|
|
327
|
-
return
|
|
350
|
+
return value;
|
|
328
351
|
});
|
|
329
352
|
}
|
|
330
353
|
get unitOfWork() {
|
package/entity/EntityHelper.js
CHANGED
|
@@ -32,7 +32,7 @@ export class EntityHelper {
|
|
|
32
32
|
const prototype = meta.prototype;
|
|
33
33
|
if (!prototype.toJSON) { // toJSON can be overridden
|
|
34
34
|
prototype.toJSON = function (...args) {
|
|
35
|
-
return EntityTransformer.toObject(this, ...args
|
|
35
|
+
return EntityTransformer.toObject(this, ...args);
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -87,7 +87,7 @@ export class EntityHelper {
|
|
|
87
87
|
});
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
|
-
if (prop.inherited || prop.primary || prop.
|
|
90
|
+
if (prop.inherited || prop.primary || prop.accessor || prop.persist === false || prop.embedded || isCollection) {
|
|
91
91
|
return;
|
|
92
92
|
}
|
|
93
93
|
Object.defineProperty(meta.prototype, prop.name, {
|
|
@@ -98,13 +98,11 @@ export class EntityHelper {
|
|
|
98
98
|
},
|
|
99
99
|
set(val) {
|
|
100
100
|
this.__helper.__data[prop.name] = val;
|
|
101
|
-
this.__helper.__touched = !this.__helper.hydrator.isRunning();
|
|
102
101
|
},
|
|
103
102
|
enumerable: true,
|
|
104
103
|
configurable: true,
|
|
105
104
|
});
|
|
106
105
|
this.__helper.__data[prop.name] = val;
|
|
107
|
-
this.__helper.__touched = !this.__helper.hydrator.isRunning();
|
|
108
106
|
},
|
|
109
107
|
configurable: true,
|
|
110
108
|
});
|
|
@@ -113,7 +111,18 @@ export class EntityHelper {
|
|
|
113
111
|
static defineCustomInspect(meta) {
|
|
114
112
|
// @ts-ignore
|
|
115
113
|
meta.prototype[inspect.custom] ??= function (depth = 2) {
|
|
116
|
-
const object = {
|
|
114
|
+
const object = {};
|
|
115
|
+
const keys = new Set(Utils.keys(this));
|
|
116
|
+
for (const prop of meta.props) {
|
|
117
|
+
if (keys.has(prop.name) || (prop.getter && prop.accessor === prop.name)) {
|
|
118
|
+
object[prop.name] = this[prop.name];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
for (const key of keys) {
|
|
122
|
+
if (!meta.properties[key]) {
|
|
123
|
+
object[key] = this[key];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
117
126
|
// ensure we dont have internal symbols in the POJO
|
|
118
127
|
[OptionalProps, EntityRepositoryType, PrimaryKeyProp, EagerProps, HiddenProps].forEach(sym => delete object[sym]);
|
|
119
128
|
meta.props
|
|
@@ -146,13 +155,13 @@ export class EntityHelper {
|
|
|
146
155
|
set(val) {
|
|
147
156
|
const entity = Reference.unwrapReference(val ?? wrapped.__data[prop.name]);
|
|
148
157
|
const old = Reference.unwrapReference(wrapped.__data[prop.name]);
|
|
158
|
+
if (old && old !== entity && prop.kind === ReferenceKind.MANY_TO_ONE && prop.inversedBy && old[prop.inversedBy]) {
|
|
159
|
+
old[prop.inversedBy].removeWithoutPropagation(this);
|
|
160
|
+
}
|
|
149
161
|
wrapped.__data[prop.name] = Reference.wrapReference(val, prop);
|
|
150
162
|
// when propagation from inside hydration, we set the FK to the entity data immediately
|
|
151
163
|
if (val && hydrator.isRunning() && wrapped.__originalEntityData && prop.owner) {
|
|
152
|
-
wrapped.__originalEntityData[prop.name] = Utils.getPrimaryKeyValues(wrapped.__data[prop.name], prop.targetMeta
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
wrapped.__touched = !hydrator.isRunning();
|
|
164
|
+
wrapped.__originalEntityData[prop.name] = Utils.getPrimaryKeyValues(wrapped.__data[prop.name], prop.targetMeta, true);
|
|
156
165
|
}
|
|
157
166
|
EntityHelper.propagate(meta, entity, this, prop, Reference.unwrapReference(val), old);
|
|
158
167
|
},
|
|
@@ -169,6 +178,13 @@ export class EntityHelper {
|
|
|
169
178
|
continue;
|
|
170
179
|
}
|
|
171
180
|
const inverse = value?.[prop2.name];
|
|
181
|
+
if (prop.ref && owner[prop.name]) {
|
|
182
|
+
// eslint-disable-next-line dot-notation
|
|
183
|
+
owner[prop.name]['property'] = prop;
|
|
184
|
+
}
|
|
185
|
+
if (Utils.isCollection(inverse) && inverse.isPartial()) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
172
188
|
if (prop.kind === ReferenceKind.MANY_TO_ONE && Utils.isCollection(inverse) && inverse.isInitialized()) {
|
|
173
189
|
inverse.addWithoutPropagation(owner);
|
|
174
190
|
helper(owner).__em?.getUnitOfWork().cancelOrphanRemoval(owner);
|
|
@@ -207,6 +223,7 @@ export class EntityHelper {
|
|
|
207
223
|
}
|
|
208
224
|
if (old?.[prop2.name] != null) {
|
|
209
225
|
delete helper(old).__data[prop2.name];
|
|
226
|
+
old[prop2.name] = null;
|
|
210
227
|
}
|
|
211
228
|
}
|
|
212
229
|
static ensurePropagation(entity) {
|
package/entity/EntityLoader.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { ConnectionType,
|
|
1
|
+
import type { AnyEntity, ConnectionType, EntityProperty, FilterQuery, PopulateOptions } from '../typings.js';
|
|
2
2
|
import type { EntityManager } from '../EntityManager.js';
|
|
3
3
|
import { LoadStrategy, type LockMode, type PopulateHint, PopulatePath, type QueryOrderMap } from '../enums.js';
|
|
4
|
-
import type { EntityField } from '../drivers/IDatabaseDriver.js';
|
|
4
|
+
import type { EntityField, FilterOptions } from '../drivers/IDatabaseDriver.js';
|
|
5
5
|
import type { LoggingOptions } from '../logging/Logger.js';
|
|
6
6
|
export type EntityLoaderOptions<Entity, Fields extends string = PopulatePath.ALL, Excludes extends string = never> = {
|
|
7
7
|
where?: FilterQuery<Entity>;
|
|
@@ -14,7 +14,7 @@ export type EntityLoaderOptions<Entity, Fields extends string = PopulatePath.ALL
|
|
|
14
14
|
lookup?: boolean;
|
|
15
15
|
convertCustomTypes?: boolean;
|
|
16
16
|
ignoreLazyScalarProperties?: boolean;
|
|
17
|
-
filters?:
|
|
17
|
+
filters?: FilterOptions;
|
|
18
18
|
strategy?: LoadStrategy;
|
|
19
19
|
lockMode?: Exclude<LockMode, LockMode.OPTIMISTIC>;
|
|
20
20
|
schema?: string;
|
|
@@ -49,7 +49,8 @@ export declare class EntityLoader {
|
|
|
49
49
|
private findChildren;
|
|
50
50
|
private mergePrimaryCondition;
|
|
51
51
|
private populateField;
|
|
52
|
-
|
|
52
|
+
/** @internal */
|
|
53
|
+
findChildrenFromPivotTable<Entity extends object>(filtered: Entity[], prop: EntityProperty<Entity>, options: Required<EntityLoaderOptions<Entity>>, orderBy?: QueryOrderMap<Entity>[], populate?: PopulateOptions<Entity>, pivotJoin?: boolean): Promise<AnyEntity[][]>;
|
|
53
54
|
private extractChildCondition;
|
|
54
55
|
private buildFields;
|
|
55
56
|
private getChildReferences;
|
package/entity/EntityLoader.js
CHANGED
|
@@ -32,13 +32,12 @@ export class EntityLoader {
|
|
|
32
32
|
const visited = options.visited ??= new Set();
|
|
33
33
|
options.where ??= {};
|
|
34
34
|
options.orderBy ??= {};
|
|
35
|
-
options.filters ??= {};
|
|
36
35
|
options.lookup ??= true;
|
|
37
36
|
options.validate ??= true;
|
|
38
37
|
options.refresh ??= false;
|
|
39
38
|
options.convertCustomTypes ??= true;
|
|
40
39
|
if (references.length > 0) {
|
|
41
|
-
await this.populateScalar(meta, references, options);
|
|
40
|
+
await this.populateScalar(meta, references, { ...options, populateWhere: undefined });
|
|
42
41
|
}
|
|
43
42
|
populate = this.normalizePopulate(entityName, populate, options.strategy, options.lookup);
|
|
44
43
|
const invalid = populate.find(({ field }) => !this.em.canPopulate(entityName, field));
|
|
@@ -140,17 +139,22 @@ export class EntityLoader {
|
|
|
140
139
|
const innerOrderBy = Utils.asArray(options.orderBy)
|
|
141
140
|
.filter(orderBy => (Array.isArray(orderBy[prop.name]) && orderBy[prop.name].length > 0) || Utils.isObject(orderBy[prop.name]))
|
|
142
141
|
.flatMap(orderBy => orderBy[prop.name]);
|
|
142
|
+
const where = await this.extractChildCondition(options, prop);
|
|
143
143
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && this.driver.getPlatform().usesPivotTable()) {
|
|
144
|
-
|
|
144
|
+
const res = await this.findChildrenFromPivotTable(filtered, prop, options, innerOrderBy, populate, !!ref);
|
|
145
|
+
return Utils.flatten(res);
|
|
145
146
|
}
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
const { items, partial } = await this.findChildren(options.filtered ?? entities, prop, populate, {
|
|
148
|
+
...options,
|
|
149
|
+
where,
|
|
150
|
+
orderBy: innerOrderBy,
|
|
151
|
+
}, !!(ref || prop.mapToPk));
|
|
152
|
+
this.initializeCollections(filtered, prop, field, items, innerOrderBy.length > 0, partial);
|
|
153
|
+
return items;
|
|
150
154
|
}
|
|
151
155
|
async populateScalar(meta, filtered, options) {
|
|
152
156
|
const pk = Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
153
|
-
const ids = Utils.unique(filtered.map(e => Utils.getPrimaryKeyValues(e, meta
|
|
157
|
+
const ids = Utils.unique(filtered.map(e => Utils.getPrimaryKeyValues(e, meta, true)));
|
|
154
158
|
const where = this.mergePrimaryCondition(ids, pk, options, meta, this.metadata, this.driver.getPlatform());
|
|
155
159
|
const { filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging, fields } = options;
|
|
156
160
|
await this.em.find(meta.className, where, {
|
|
@@ -159,15 +163,15 @@ export class EntityLoader {
|
|
|
159
163
|
populate: [],
|
|
160
164
|
});
|
|
161
165
|
}
|
|
162
|
-
initializeCollections(filtered, prop, field, children, customOrder) {
|
|
166
|
+
initializeCollections(filtered, prop, field, children, customOrder, partial) {
|
|
163
167
|
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
164
|
-
this.initializeOneToMany(filtered, children, prop, field);
|
|
168
|
+
this.initializeOneToMany(filtered, children, prop, field, partial);
|
|
165
169
|
}
|
|
166
170
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && !this.driver.getPlatform().usesPivotTable()) {
|
|
167
|
-
this.initializeManyToMany(filtered, children, prop, field, customOrder);
|
|
171
|
+
this.initializeManyToMany(filtered, children, prop, field, customOrder, partial);
|
|
168
172
|
}
|
|
169
173
|
}
|
|
170
|
-
initializeOneToMany(filtered, children, prop, field) {
|
|
174
|
+
initializeOneToMany(filtered, children, prop, field, partial) {
|
|
171
175
|
const mapToPk = prop.targetMeta.properties[prop.mappedBy].mapToPk;
|
|
172
176
|
const map = {};
|
|
173
177
|
for (const entity of filtered) {
|
|
@@ -183,14 +187,14 @@ export class EntityLoader {
|
|
|
183
187
|
}
|
|
184
188
|
for (const entity of filtered) {
|
|
185
189
|
const key = helper(entity).getSerializedPrimaryKey();
|
|
186
|
-
entity[field].hydrate(map[key]);
|
|
190
|
+
entity[field].hydrate(map[key], undefined, partial);
|
|
187
191
|
}
|
|
188
192
|
}
|
|
189
|
-
initializeManyToMany(filtered, children, prop, field, customOrder) {
|
|
193
|
+
initializeManyToMany(filtered, children, prop, field, customOrder, partial) {
|
|
190
194
|
if (prop.mappedBy) {
|
|
191
195
|
for (const entity of filtered) {
|
|
192
196
|
const items = children.filter(child => child[prop.mappedBy].contains(entity, false));
|
|
193
|
-
entity[field].hydrate(items, true);
|
|
197
|
+
entity[field].hydrate(items, true, partial);
|
|
194
198
|
}
|
|
195
199
|
}
|
|
196
200
|
else { // owning side of M:N without pivot table needs to be reordered
|
|
@@ -200,15 +204,16 @@ export class EntityLoader {
|
|
|
200
204
|
if (!customOrder) {
|
|
201
205
|
items.sort((a, b) => order.indexOf(a) - order.indexOf(b));
|
|
202
206
|
}
|
|
203
|
-
entity[field].hydrate(items, true);
|
|
207
|
+
entity[field].hydrate(items, true, partial);
|
|
204
208
|
}
|
|
205
209
|
}
|
|
206
210
|
}
|
|
207
211
|
async findChildren(entities, prop, populate, options, ref) {
|
|
208
|
-
const children = this.getChildReferences(entities, prop, options, ref);
|
|
212
|
+
const children = Utils.unique(this.getChildReferences(entities, prop, options, ref));
|
|
209
213
|
const meta = prop.targetMeta;
|
|
210
214
|
let fk = Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
211
215
|
let schema = options.schema;
|
|
216
|
+
const partial = !Utils.isEmpty(prop.where) || !Utils.isEmpty(options.where);
|
|
212
217
|
if (prop.kind === ReferenceKind.ONE_TO_MANY || (prop.kind === ReferenceKind.MANY_TO_MANY && !prop.owner)) {
|
|
213
218
|
fk = meta.properties[prop.mappedBy].name;
|
|
214
219
|
}
|
|
@@ -218,7 +223,7 @@ export class EntityLoader {
|
|
|
218
223
|
children.push(...this.filterByReferences(entities, prop.name, options.refresh));
|
|
219
224
|
}
|
|
220
225
|
if (children.length === 0) {
|
|
221
|
-
return [];
|
|
226
|
+
return { items: [], partial };
|
|
222
227
|
}
|
|
223
228
|
if (!schema && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind)) {
|
|
224
229
|
schema = children.find(e => e.__helper.__schema)?.__helper.__schema;
|
|
@@ -227,7 +232,7 @@ export class EntityLoader {
|
|
|
227
232
|
let where = this.mergePrimaryCondition(ids, fk, options, meta, this.metadata, this.driver.getPlatform());
|
|
228
233
|
const fields = this.buildFields(options.fields, prop, ref);
|
|
229
234
|
/* eslint-disable prefer-const */
|
|
230
|
-
let { refresh, filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging, } = options;
|
|
235
|
+
let { refresh, filters, convertCustomTypes, lockMode, strategy, populateWhere = 'infer', connectionType, logging, } = options;
|
|
231
236
|
/* eslint-enable prefer-const */
|
|
232
237
|
if (typeof populateWhere === 'object') {
|
|
233
238
|
populateWhere = await this.extractChildCondition({ where: populateWhere }, prop);
|
|
@@ -264,6 +269,24 @@ export class EntityLoader {
|
|
|
264
269
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
265
270
|
visited: options.visited,
|
|
266
271
|
});
|
|
272
|
+
if ([ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind) && items.length !== children.length) {
|
|
273
|
+
const nullVal = this.em.config.get('forceUndefined') ? undefined : null;
|
|
274
|
+
const itemsMap = new Set();
|
|
275
|
+
const childrenMap = new Set();
|
|
276
|
+
for (const item of items) {
|
|
277
|
+
itemsMap.add(helper(item).getSerializedPrimaryKey());
|
|
278
|
+
}
|
|
279
|
+
for (const child of children) {
|
|
280
|
+
childrenMap.add(helper(child).getSerializedPrimaryKey());
|
|
281
|
+
}
|
|
282
|
+
for (const entity of entities) {
|
|
283
|
+
const key = helper(entity[prop.name] ?? {})?.getSerializedPrimaryKey();
|
|
284
|
+
if (childrenMap.has(key) && !itemsMap.has(key)) {
|
|
285
|
+
entity[prop.name] = nullVal;
|
|
286
|
+
helper(entity).__originalEntityData[prop.name] = null;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
267
290
|
for (const item of items) {
|
|
268
291
|
if (ref && !helper(item).__onLoadFired) {
|
|
269
292
|
helper(item).__initialized = false;
|
|
@@ -271,7 +294,7 @@ export class EntityLoader {
|
|
|
271
294
|
this.em.getUnitOfWork()['loadedEntities'].delete(item);
|
|
272
295
|
}
|
|
273
296
|
}
|
|
274
|
-
return items;
|
|
297
|
+
return { items, partial };
|
|
275
298
|
}
|
|
276
299
|
mergePrimaryCondition(ids, pk, options, meta, metadata, platform) {
|
|
277
300
|
const cond1 = QueryHelper.processWhere({ where: { [pk]: { $in: ids } }, entityName: meta.className, metadata, platform, convertCustomTypes: !options.convertCustomTypes });
|
|
@@ -287,6 +310,7 @@ export class EntityLoader {
|
|
|
287
310
|
if (prop.kind === ReferenceKind.SCALAR && !prop.lazy) {
|
|
288
311
|
return;
|
|
289
312
|
}
|
|
313
|
+
options = { ...options, filters: QueryHelper.mergePropertyFilters(prop.filters, options.filters) };
|
|
290
314
|
const populated = await this.populateMany(entityName, entities, populate, options);
|
|
291
315
|
if (!populate.children && !populate.all) {
|
|
292
316
|
return;
|
|
@@ -314,10 +338,18 @@ export class EntityLoader {
|
|
|
314
338
|
const innerOrderBy = Utils.asArray(options.orderBy)
|
|
315
339
|
.filter(orderBy => Utils.isObject(orderBy[prop.name]))
|
|
316
340
|
.map(orderBy => orderBy[prop.name]);
|
|
317
|
-
const { refresh, filters, ignoreLazyScalarProperties, populateWhere, connectionType, logging } = options;
|
|
341
|
+
const { refresh, filters, ignoreLazyScalarProperties, populateWhere, connectionType, logging, schema } = options;
|
|
318
342
|
const exclude = Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude;
|
|
319
|
-
const
|
|
320
|
-
|
|
343
|
+
const visited = options.visited;
|
|
344
|
+
for (const entity of entities) {
|
|
345
|
+
visited.delete(entity);
|
|
346
|
+
}
|
|
347
|
+
const unique = Utils.unique(children);
|
|
348
|
+
const filtered = unique.filter(e => !visited.has(e));
|
|
349
|
+
for (const entity of entities) {
|
|
350
|
+
visited.add(entity);
|
|
351
|
+
}
|
|
352
|
+
await this.populate(prop.type, unique, populate.children ?? populate.all, {
|
|
321
353
|
where: await this.extractChildCondition(options, prop, false),
|
|
322
354
|
orderBy: innerOrderBy,
|
|
323
355
|
fields,
|
|
@@ -329,12 +361,16 @@ export class EntityLoader {
|
|
|
329
361
|
populateWhere,
|
|
330
362
|
connectionType,
|
|
331
363
|
logging,
|
|
364
|
+
schema,
|
|
332
365
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
333
366
|
refresh: refresh && !filtered.every(item => options.visited.has(item)),
|
|
334
367
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
335
368
|
visited: options.visited,
|
|
369
|
+
// @ts-ignore not a public option
|
|
370
|
+
filtered,
|
|
336
371
|
});
|
|
337
372
|
}
|
|
373
|
+
/** @internal */
|
|
338
374
|
async findChildrenFromPivotTable(filtered, prop, options, orderBy, populate, pivotJoin) {
|
|
339
375
|
const ids = filtered.map(e => e.__helper.__primaryKeys);
|
|
340
376
|
const refresh = options.refresh;
|
|
@@ -372,7 +408,7 @@ export class EntityLoader {
|
|
|
372
408
|
return this.em.getUnitOfWork().register(entity, item, { refresh, loaded: true });
|
|
373
409
|
});
|
|
374
410
|
entity[prop.name].hydrate(items, true);
|
|
375
|
-
children.push(
|
|
411
|
+
children.push(items);
|
|
376
412
|
}
|
|
377
413
|
return children;
|
|
378
414
|
}
|
|
@@ -448,23 +484,20 @@ export class EntityLoader {
|
|
|
448
484
|
}
|
|
449
485
|
getChildReferences(entities, prop, options, ref) {
|
|
450
486
|
const filtered = this.filterCollections(entities, prop.name, options, ref);
|
|
451
|
-
const children = [];
|
|
452
487
|
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
453
|
-
|
|
488
|
+
return filtered.map(e => e[prop.name].owner);
|
|
454
489
|
}
|
|
455
|
-
|
|
456
|
-
|
|
490
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner) {
|
|
491
|
+
return filtered.reduce((a, b) => {
|
|
457
492
|
a.push(...b[prop.name].getItems());
|
|
458
493
|
return a;
|
|
459
|
-
}, [])
|
|
494
|
+
}, []);
|
|
460
495
|
}
|
|
461
|
-
|
|
462
|
-
|
|
496
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY) { // inverse side
|
|
497
|
+
return filtered;
|
|
463
498
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
}
|
|
467
|
-
return children;
|
|
499
|
+
// MANY_TO_ONE or ONE_TO_ONE
|
|
500
|
+
return this.filterReferences(entities, prop.name, options, ref);
|
|
468
501
|
}
|
|
469
502
|
filterCollections(entities, field, options, ref) {
|
|
470
503
|
if (options.refresh) {
|
|
@@ -518,7 +551,7 @@ export class EntityLoader {
|
|
|
518
551
|
if (refresh) {
|
|
519
552
|
return entities;
|
|
520
553
|
}
|
|
521
|
-
return entities.filter(e => !e[field]?.__helper?.__initialized);
|
|
554
|
+
return entities.filter(e => e[field] !== null && !e[field]?.__helper?.__initialized);
|
|
522
555
|
}
|
|
523
556
|
lookupAllRelationships(entityName) {
|
|
524
557
|
const ret = [];
|
|
@@ -80,7 +80,7 @@ export declare class EntityRepository<Entity extends object> {
|
|
|
80
80
|
/**
|
|
81
81
|
* @inheritDoc EntityManager.findByCursor
|
|
82
82
|
*/
|
|
83
|
-
findByCursor<Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(where: FilterQuery<Entity>, options: FindByCursorOptions<Entity, Hint, Fields, Excludes>): Promise<Cursor<Entity, Hint, Fields, Excludes>>;
|
|
83
|
+
findByCursor<Hint extends string = never, Fields extends string = '*', Excludes extends string = never, IncludeCount extends boolean = true>(where: FilterQuery<Entity>, options: FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>): Promise<Cursor<Entity, Hint, Fields, Excludes, IncludeCount>>;
|
|
84
84
|
/**
|
|
85
85
|
* Finds all entities of given type. You can pass additional options via the `options` parameter.
|
|
86
86
|
*/
|
|
@@ -11,7 +11,7 @@ export class EntityValidator {
|
|
|
11
11
|
}
|
|
12
12
|
validate(entity, payload, meta) {
|
|
13
13
|
meta.props.forEach(prop => {
|
|
14
|
-
if (prop.inherited) {
|
|
14
|
+
if (prop.inherited || (prop.persist === false && prop.userDefined !== false)) {
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
17
|
if ([ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
|
|
@@ -43,7 +43,7 @@ export class EntityValidator {
|
|
|
43
43
|
!prop.embedded &&
|
|
44
44
|
![ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind) &&
|
|
45
45
|
prop.name !== wrapped.__meta.root.discriminatorColumn &&
|
|
46
|
-
prop.type
|
|
46
|
+
prop.type !== 'ObjectId' &&
|
|
47
47
|
prop.persist !== false &&
|
|
48
48
|
entity[prop.name] == null) {
|
|
49
49
|
throw ValidationError.propertyRequired(entity, prop);
|
|
@@ -89,7 +89,7 @@ export class EntityValidator {
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
validatePrimaryKey(entity, meta) {
|
|
92
|
-
const pkExists = meta.primaryKeys.every(pk => entity[pk] != null) || entity[meta.serializedPrimaryKey] != null;
|
|
92
|
+
const pkExists = meta.primaryKeys.every(pk => entity[pk] != null) || (meta.serializedPrimaryKey && entity[meta.serializedPrimaryKey] != null);
|
|
93
93
|
if (!entity || !pkExists) {
|
|
94
94
|
throw ValidationError.fromMergeWithoutPK(meta);
|
|
95
95
|
}
|
|
@@ -131,7 +131,7 @@ export class EntityValidator {
|
|
|
131
131
|
}
|
|
132
132
|
fixDateType(givenValue) {
|
|
133
133
|
let date;
|
|
134
|
-
if (
|
|
134
|
+
if (typeof givenValue === 'string' && givenValue.match(/^-?\d+(\.\d+)?$/)) {
|
|
135
135
|
date = new Date(+givenValue);
|
|
136
136
|
}
|
|
137
137
|
else {
|