@mikro-orm/core 7.0.0-dev.32 → 7.0.0-dev.321
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 +71 -63
- package/EntityManager.js +365 -283
- package/MikroORM.d.ts +44 -35
- package/MikroORM.js +109 -142
- package/README.md +7 -4
- package/cache/FileCacheAdapter.d.ts +1 -2
- package/cache/FileCacheAdapter.js +19 -14
- package/cache/GeneratedCacheAdapter.d.ts +0 -1
- package/cache/GeneratedCacheAdapter.js +0 -2
- 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 +101 -29
- package/entity/Collection.js +473 -115
- package/entity/EntityAssigner.js +37 -25
- package/entity/EntityFactory.d.ts +7 -1
- package/entity/EntityFactory.js +116 -64
- package/entity/EntityHelper.d.ts +2 -2
- package/entity/EntityHelper.js +69 -27
- package/entity/EntityLoader.d.ts +11 -10
- package/entity/EntityLoader.js +264 -102
- 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 +2 -6
- package/entity/Reference.js +52 -19
- package/entity/WrappedEntity.d.ts +3 -8
- package/entity/WrappedEntity.js +6 -7
- package/entity/defineEntity.d.ts +525 -311
- 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 +20 -10
- package/errors.js +63 -31
- package/events/EventManager.d.ts +2 -1
- package/events/EventManager.js +24 -13
- 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 +4 -4
- package/hydration/ObjectHydrator.js +105 -46
- 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 +5 -7
- 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 +64 -9
- package/metadata/MetadataDiscovery.js +867 -354
- package/metadata/MetadataProvider.d.ts +11 -2
- package/metadata/MetadataProvider.js +71 -2
- package/metadata/MetadataStorage.d.ts +13 -11
- package/metadata/MetadataStorage.js +72 -41
- 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 +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/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 +53 -29
- package/serialization/EntityTransformer.js +33 -21
- package/serialization/SerializationContext.d.ts +6 -6
- package/serialization/SerializationContext.js +4 -4
- 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 +3 -8
- package/unit-of-work/ChangeSetComputer.js +49 -26
- package/unit-of-work/ChangeSetPersister.d.ts +13 -12
- package/unit-of-work/ChangeSetPersister.js +107 -44
- package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
- package/unit-of-work/CommitOrderCalculator.js +17 -15
- package/unit-of-work/IdentityMap.d.ts +12 -0
- package/unit-of-work/IdentityMap.js +39 -1
- package/unit-of-work/UnitOfWork.d.ts +34 -4
- package/unit-of-work/UnitOfWork.js +294 -107
- 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 +796 -211
- package/utils/Configuration.js +160 -197
- package/utils/ConfigurationLoader.d.ts +1 -52
- package/utils/ConfigurationLoader.js +1 -330
- package/utils/Cursor.d.ts +0 -3
- package/utils/Cursor.js +29 -14
- package/utils/DataloaderUtils.d.ts +10 -5
- package/utils/DataloaderUtils.js +42 -22
- package/utils/EntityComparator.d.ts +16 -9
- package/utils/EntityComparator.js +202 -96
- 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 -7
- package/utils/Utils.d.ts +16 -127
- package/utils/Utils.js +106 -401
- 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 +34 -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
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { EntityData, EntityDictionary, EntityMetadata, EntityProperty, IMetadataStorage } from '../typings.js';
|
|
1
|
+
import type { EntityData, EntityDictionary, EntityMetadata, EntityName, EntityProperty, IMetadataStorage } from '../typings.js';
|
|
2
2
|
import type { Platform } from '../platforms/Platform.js';
|
|
3
|
+
import type { Configuration } from './Configuration.js';
|
|
3
4
|
type Comparator<T> = (a: T, b: T, options?: {
|
|
4
5
|
includeInverseSides?: boolean;
|
|
5
6
|
}) => EntityData<T>;
|
|
@@ -9,6 +10,7 @@ type CompositeKeyPart = string | CompositeKeyPart[];
|
|
|
9
10
|
export declare class EntityComparator {
|
|
10
11
|
private readonly metadata;
|
|
11
12
|
private readonly platform;
|
|
13
|
+
private readonly config?;
|
|
12
14
|
private readonly comparators;
|
|
13
15
|
private readonly mappers;
|
|
14
16
|
private readonly snapshotGenerators;
|
|
@@ -16,23 +18,23 @@ export declare class EntityComparator {
|
|
|
16
18
|
private readonly pkGettersConverted;
|
|
17
19
|
private readonly pkSerializers;
|
|
18
20
|
private tmpIndex;
|
|
19
|
-
constructor(metadata: IMetadataStorage, platform: Platform);
|
|
21
|
+
constructor(metadata: IMetadataStorage, platform: Platform, config?: Configuration | undefined);
|
|
20
22
|
/**
|
|
21
23
|
* Computes difference between two entities.
|
|
22
24
|
*/
|
|
23
|
-
diffEntities<T>(entityName:
|
|
25
|
+
diffEntities<T extends object>(entityName: EntityName<T>, a: EntityData<T>, b: EntityData<T>, options?: {
|
|
24
26
|
includeInverseSides?: boolean;
|
|
25
27
|
}): EntityData<T>;
|
|
26
|
-
matching<T>(entityName:
|
|
28
|
+
matching<T extends object>(entityName: EntityName<T>, a: EntityData<T>, b: EntityData<T>): boolean;
|
|
27
29
|
/**
|
|
28
30
|
* Removes ORM specific code from entities and prepares it for serializing. Used before change set computation.
|
|
29
31
|
* References will be mapped to primary keys, collections to arrays of primary keys.
|
|
30
32
|
*/
|
|
31
|
-
prepareEntity<T>(entity: T): EntityData<T>;
|
|
33
|
+
prepareEntity<T extends object>(entity: T): EntityData<T>;
|
|
32
34
|
/**
|
|
33
35
|
* Maps database columns to properties.
|
|
34
36
|
*/
|
|
35
|
-
mapResult<T>(
|
|
37
|
+
mapResult<T>(meta: EntityMetadata<T>, result: EntityDictionary<T>): EntityData<T>;
|
|
36
38
|
/**
|
|
37
39
|
* @internal Highly performance-sensitive method.
|
|
38
40
|
*/
|
|
@@ -48,7 +50,7 @@ export declare class EntityComparator {
|
|
|
48
50
|
/**
|
|
49
51
|
* @internal Highly performance-sensitive method.
|
|
50
52
|
*/
|
|
51
|
-
getSnapshotGenerator<T>(entityName:
|
|
53
|
+
getSnapshotGenerator<T>(entityName: EntityName<T>): SnapshotGenerator<T>;
|
|
52
54
|
/**
|
|
53
55
|
* @internal
|
|
54
56
|
*/
|
|
@@ -64,7 +66,7 @@ export declare class EntityComparator {
|
|
|
64
66
|
/**
|
|
65
67
|
* @internal Highly performance-sensitive method.
|
|
66
68
|
*/
|
|
67
|
-
getResultMapper<T>(
|
|
69
|
+
getResultMapper<T>(meta: EntityMetadata<T>): ResultMapper<T>;
|
|
68
70
|
private getPropertyCondition;
|
|
69
71
|
private getEmbeddedArrayPropertySnapshot;
|
|
70
72
|
/**
|
|
@@ -78,11 +80,16 @@ export declare class EntityComparator {
|
|
|
78
80
|
/**
|
|
79
81
|
* @internal Highly performance-sensitive method.
|
|
80
82
|
*/
|
|
81
|
-
getEntityComparator<T extends object>(entityName:
|
|
83
|
+
getEntityComparator<T extends object>(entityName: EntityName<T>): Comparator<T>;
|
|
82
84
|
private getGenericComparator;
|
|
83
85
|
private getPropertyComparator;
|
|
84
86
|
private wrap;
|
|
85
87
|
private safeKey;
|
|
88
|
+
/**
|
|
89
|
+
* Sets the toArray helper in the context if not already set.
|
|
90
|
+
* Used for converting composite PKs to arrays.
|
|
91
|
+
*/
|
|
92
|
+
private setToArrayHelper;
|
|
86
93
|
/**
|
|
87
94
|
* perf: used to generate list of comparable properties during discovery, so we speed up the runtime comparison
|
|
88
95
|
*/
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { clone } from './clone.js';
|
|
2
2
|
import { ReferenceKind } from '../enums.js';
|
|
3
|
-
import { compareArrays, compareBooleans, compareBuffers, compareObjects, equals, parseJsonSafe, Utils } from './Utils.js';
|
|
3
|
+
import { compareArrays, compareBooleans, compareBuffers, compareObjects, equals, parseJsonSafe, Utils, } from './Utils.js';
|
|
4
4
|
import { JsonType } from '../types/JsonType.js';
|
|
5
|
-
import {
|
|
5
|
+
import { Raw } from './RawQueryFragment.js';
|
|
6
|
+
import { EntityIdentifier } from '../entity/EntityIdentifier.js';
|
|
7
|
+
import { PolymorphicRef } from '../entity/PolymorphicRef.js';
|
|
6
8
|
export class EntityComparator {
|
|
7
9
|
metadata;
|
|
8
10
|
platform;
|
|
11
|
+
config;
|
|
9
12
|
comparators = new Map();
|
|
10
13
|
mappers = new Map();
|
|
11
14
|
snapshotGenerators = new Map();
|
|
@@ -13,9 +16,10 @@ export class EntityComparator {
|
|
|
13
16
|
pkGettersConverted = new Map();
|
|
14
17
|
pkSerializers = new Map();
|
|
15
18
|
tmpIndex = 0;
|
|
16
|
-
constructor(metadata, platform) {
|
|
19
|
+
constructor(metadata, platform, config) {
|
|
17
20
|
this.metadata = metadata;
|
|
18
21
|
this.platform = platform;
|
|
22
|
+
this.config = config;
|
|
19
23
|
}
|
|
20
24
|
/**
|
|
21
25
|
* Computes difference between two entities.
|
|
@@ -33,22 +37,22 @@ export class EntityComparator {
|
|
|
33
37
|
* References will be mapped to primary keys, collections to arrays of primary keys.
|
|
34
38
|
*/
|
|
35
39
|
prepareEntity(entity) {
|
|
36
|
-
const generator = this.getSnapshotGenerator(entity.constructor
|
|
40
|
+
const generator = this.getSnapshotGenerator(entity.constructor);
|
|
37
41
|
return Utils.callCompiledFunction(generator, entity);
|
|
38
42
|
}
|
|
39
43
|
/**
|
|
40
44
|
* Maps database columns to properties.
|
|
41
45
|
*/
|
|
42
|
-
mapResult(
|
|
43
|
-
const mapper = this.getResultMapper(
|
|
46
|
+
mapResult(meta, result) {
|
|
47
|
+
const mapper = this.getResultMapper(meta);
|
|
44
48
|
return Utils.callCompiledFunction(mapper, result);
|
|
45
49
|
}
|
|
46
50
|
/**
|
|
47
51
|
* @internal Highly performance-sensitive method.
|
|
48
52
|
*/
|
|
49
53
|
getPkGetter(meta) {
|
|
50
|
-
const exists = this.pkGetters.get(meta
|
|
51
|
-
/* v8 ignore next
|
|
54
|
+
const exists = this.pkGetters.get(meta);
|
|
55
|
+
/* v8 ignore next */
|
|
52
56
|
if (exists) {
|
|
53
57
|
return exists;
|
|
54
58
|
}
|
|
@@ -87,18 +91,18 @@ export class EntityComparator {
|
|
|
87
91
|
}
|
|
88
92
|
lines.push(` return entity${this.wrap(pk)};`);
|
|
89
93
|
}
|
|
90
|
-
const code = `// compiled pk
|
|
91
|
-
|
|
92
|
-
const pkSerializer = Utils.createFunction(context, code);
|
|
93
|
-
this.pkGetters.set(meta
|
|
94
|
+
const code = `// compiled pk getter for entity ${meta.className}\n` + `return function(entity) {\n${lines.join('\n')}\n}`;
|
|
95
|
+
const fnKey = `pkGetter-${meta.uniqueName}`;
|
|
96
|
+
const pkSerializer = Utils.createFunction(context, code, this.config?.get('compiledFunctions'), fnKey);
|
|
97
|
+
this.pkGetters.set(meta, pkSerializer);
|
|
94
98
|
return pkSerializer;
|
|
95
99
|
}
|
|
96
100
|
/**
|
|
97
101
|
* @internal Highly performance-sensitive method.
|
|
98
102
|
*/
|
|
99
103
|
getPkGetterConverted(meta) {
|
|
100
|
-
const exists = this.pkGettersConverted.get(meta
|
|
101
|
-
/* v8 ignore next
|
|
104
|
+
const exists = this.pkGettersConverted.get(meta);
|
|
105
|
+
/* v8 ignore next */
|
|
102
106
|
if (exists) {
|
|
103
107
|
return exists;
|
|
104
108
|
}
|
|
@@ -137,18 +141,19 @@ export class EntityComparator {
|
|
|
137
141
|
lines.push(` return entity${this.wrap(pk)};`);
|
|
138
142
|
}
|
|
139
143
|
}
|
|
140
|
-
const code = `// compiled pk getter (with converted custom types) for entity ${meta.className}\n`
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
this.
|
|
144
|
+
const code = `// compiled pk getter (with converted custom types) for entity ${meta.className}\n` +
|
|
145
|
+
`return function(entity) {\n${lines.join('\n')}\n}`;
|
|
146
|
+
const fnKey = `pkGetterConverted-${meta.uniqueName}`;
|
|
147
|
+
const pkSerializer = Utils.createFunction(context, code, this.config?.get('compiledFunctions'), fnKey);
|
|
148
|
+
this.pkGettersConverted.set(meta, pkSerializer);
|
|
144
149
|
return pkSerializer;
|
|
145
150
|
}
|
|
146
151
|
/**
|
|
147
152
|
* @internal Highly performance-sensitive method.
|
|
148
153
|
*/
|
|
149
154
|
getPkSerializer(meta) {
|
|
150
|
-
const exists = this.pkSerializers.get(meta
|
|
151
|
-
/* v8 ignore next
|
|
155
|
+
const exists = this.pkSerializers.get(meta);
|
|
156
|
+
/* v8 ignore next */
|
|
152
157
|
if (exists) {
|
|
153
158
|
return exists;
|
|
154
159
|
}
|
|
@@ -189,26 +194,26 @@ export class EntityComparator {
|
|
|
189
194
|
lines.push(` return '' + entity${this.wrap(pk)};`);
|
|
190
195
|
}
|
|
191
196
|
}
|
|
192
|
-
const code = `// compiled pk serializer for entity ${meta.className}\n`
|
|
193
|
-
|
|
194
|
-
const pkSerializer = Utils.createFunction(context, code);
|
|
195
|
-
this.pkSerializers.set(meta
|
|
197
|
+
const code = `// compiled pk serializer for entity ${meta.className}\n` + `return function(entity) {\n${lines.join('\n')}\n}`;
|
|
198
|
+
const fnKey = `pkSerializer-${meta.uniqueName}`;
|
|
199
|
+
const pkSerializer = Utils.createFunction(context, code, this.config?.get('compiledFunctions'), fnKey);
|
|
200
|
+
this.pkSerializers.set(meta, pkSerializer);
|
|
196
201
|
return pkSerializer;
|
|
197
202
|
}
|
|
198
203
|
/**
|
|
199
204
|
* @internal Highly performance-sensitive method.
|
|
200
205
|
*/
|
|
201
206
|
getSnapshotGenerator(entityName) {
|
|
202
|
-
const
|
|
207
|
+
const meta = this.metadata.find(entityName);
|
|
208
|
+
const exists = this.snapshotGenerators.get(meta);
|
|
203
209
|
if (exists) {
|
|
204
210
|
return exists;
|
|
205
211
|
}
|
|
206
|
-
const meta = this.metadata.find(entityName);
|
|
207
212
|
const lines = [];
|
|
208
213
|
const context = new Map();
|
|
209
214
|
context.set('clone', clone);
|
|
210
215
|
context.set('cloneEmbeddable', (o) => this.platform.cloneEmbeddable(o)); // do not clone prototypes
|
|
211
|
-
if (meta.discriminatorValue) {
|
|
216
|
+
if (meta.root.inheritanceType === 'sti' && meta.discriminatorValue) {
|
|
212
217
|
lines.push(` ret${this.wrap(meta.root.discriminatorColumn)} = '${meta.discriminatorValue}'`);
|
|
213
218
|
}
|
|
214
219
|
const getRootProperty = (prop) => prop.embedded ? getRootProperty(meta.properties[prop.embedded[0]]) : prop;
|
|
@@ -220,8 +225,9 @@ export class EntityComparator {
|
|
|
220
225
|
})
|
|
221
226
|
.forEach(prop => lines.push(this.getPropertySnapshot(meta, prop, context, this.wrap(prop.name), this.wrap(prop.name), [prop.name])));
|
|
222
227
|
const code = `return function(entity) {\n const ret = {};\n${lines.join('\n')}\n return ret;\n}`;
|
|
223
|
-
const
|
|
224
|
-
this.
|
|
228
|
+
const fnKey = `snapshotGenerator-${meta.uniqueName}`;
|
|
229
|
+
const snapshotGenerator = Utils.createFunction(context, code, this.config?.get('compiledFunctions'), fnKey);
|
|
230
|
+
this.snapshotGenerators.set(meta, snapshotGenerator);
|
|
225
231
|
return snapshotGenerator;
|
|
226
232
|
}
|
|
227
233
|
/**
|
|
@@ -265,29 +271,33 @@ export class EntityComparator {
|
|
|
265
271
|
if (part.length === 1) {
|
|
266
272
|
return this.formatCompositeKeyPart(part[0]);
|
|
267
273
|
}
|
|
268
|
-
const formatted = part.map(this.formatCompositeKeyPart).join(', ');
|
|
274
|
+
const formatted = part.map(p => this.formatCompositeKeyPart(p)).join(', ');
|
|
269
275
|
return `[${formatted}]`;
|
|
270
276
|
}
|
|
271
277
|
/**
|
|
272
278
|
* @internal Highly performance-sensitive method.
|
|
273
279
|
*/
|
|
274
|
-
getResultMapper(
|
|
275
|
-
const exists = this.mappers.get(
|
|
280
|
+
getResultMapper(meta) {
|
|
281
|
+
const exists = this.mappers.get(meta);
|
|
276
282
|
if (exists) {
|
|
277
283
|
return exists;
|
|
278
284
|
}
|
|
279
|
-
const meta = this.metadata.get(entityName);
|
|
280
285
|
const lines = [];
|
|
281
286
|
const context = new Map();
|
|
287
|
+
context.set('PolymorphicRef', PolymorphicRef);
|
|
282
288
|
const tz = this.platform.getTimezone();
|
|
283
289
|
const parseDate = (key, value, padding = '') => {
|
|
284
290
|
lines.push(`${padding} if (${value} == null || ${value} instanceof Date) {`);
|
|
285
291
|
lines.push(`${padding} ${key} = ${value};`);
|
|
286
292
|
if (!tz || tz === 'local') {
|
|
293
|
+
lines.push(`${padding} } else if (typeof ${value} === 'bigint') {`);
|
|
294
|
+
lines.push(`${padding} ${key} = parseDate(Number(${value}));`);
|
|
287
295
|
lines.push(`${padding} } else {`);
|
|
288
296
|
lines.push(`${padding} ${key} = parseDate(${value});`);
|
|
289
297
|
}
|
|
290
298
|
else {
|
|
299
|
+
lines.push(`${padding} } else if (typeof ${value} === 'bigint') {`);
|
|
300
|
+
lines.push(`${padding} ${key} = parseDate(Number(${value}));`);
|
|
291
301
|
lines.push(`${padding} } else if (typeof ${value} === 'number' || ${value}.includes('+') || ${value}.lastIndexOf('-') > 10 || ${value}.endsWith('Z')) {`);
|
|
292
302
|
lines.push(`${padding} ${key} = parseDate(${value});`);
|
|
293
303
|
lines.push(`${padding} } else {`);
|
|
@@ -301,12 +311,28 @@ export class EntityComparator {
|
|
|
301
311
|
if (!prop.fieldNames) {
|
|
302
312
|
continue;
|
|
303
313
|
}
|
|
314
|
+
if (prop.polymorphic && prop.fieldNames.length >= 2) {
|
|
315
|
+
const discriminatorField = prop.fieldNames[0];
|
|
316
|
+
const idFields = prop.fieldNames.slice(1);
|
|
317
|
+
lines.push(`${padding} if (${prop.fieldNames.map(field => `typeof ${this.propName(field)} === 'undefined'`).join(' && ')}) {`);
|
|
318
|
+
lines.push(`${padding} } else if (${prop.fieldNames.map(field => `${this.propName(field)} != null`).join(' && ')}) {`);
|
|
319
|
+
if (idFields.length === 1) {
|
|
320
|
+
lines.push(`${padding} ret${this.wrap(prop.name)} = new PolymorphicRef(${this.propName(discriminatorField)}, ${this.propName(idFields[0])});`);
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
lines.push(`${padding} ret${this.wrap(prop.name)} = new PolymorphicRef(${this.propName(discriminatorField)}, [${idFields.map(f => this.propName(f)).join(', ')}]);`);
|
|
324
|
+
}
|
|
325
|
+
lines.push(...prop.fieldNames.map(field => `${padding} ${this.propName(field, 'mapped')} = true;`));
|
|
326
|
+
lines.push(`${padding} } else if (${prop.fieldNames.map(field => `${this.propName(field)} == null`).join(' && ')}) {\n${padding} ret${this.wrap(prop.name)} = null;`);
|
|
327
|
+
lines.push(...prop.fieldNames.map(field => `${padding} ${this.propName(field, 'mapped')} = true;`), ' }');
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
304
330
|
if (prop.targetMeta && prop.fieldNames.length > 1) {
|
|
305
331
|
lines.push(`${padding} if (${prop.fieldNames.map(field => `typeof ${this.propName(field)} === 'undefined'`).join(' && ')}) {`);
|
|
306
332
|
lines.push(`${padding} } else if (${prop.fieldNames.map(field => `${this.propName(field)} != null`).join(' && ')}) {`);
|
|
307
333
|
lines.push(`${padding} ret${this.wrap(prop.name)} = ${this.createCompositeKeyArray(prop)};`);
|
|
308
334
|
lines.push(...prop.fieldNames.map(field => `${padding} ${this.propName(field, 'mapped')} = true;`));
|
|
309
|
-
lines.push(`${padding} } else if (${prop.fieldNames.map(field => `${this.propName(field)} == null`).join(' && ')}) {\n ret${this.wrap(prop.name)} = null;`);
|
|
335
|
+
lines.push(`${padding} } else if (${prop.fieldNames.map(field => `${this.propName(field)} == null`).join(' && ')}) {\n${padding} ret${this.wrap(prop.name)} = null;`);
|
|
310
336
|
lines.push(...prop.fieldNames.map(field => `${padding} ${this.propName(field, 'mapped')} = true;`), ' }');
|
|
311
337
|
continue;
|
|
312
338
|
}
|
|
@@ -331,9 +357,9 @@ export class EntityComparator {
|
|
|
331
357
|
context.set(`mapEmbeddedResult_${idx}`, (data) => {
|
|
332
358
|
const item = parseJsonSafe(data);
|
|
333
359
|
if (Array.isArray(item)) {
|
|
334
|
-
return item.map(row => row == null ? row : this.getResultMapper(prop.
|
|
360
|
+
return item.map(row => (row == null ? row : this.getResultMapper(prop.targetMeta)(row)));
|
|
335
361
|
}
|
|
336
|
-
return item == null ? item : this.getResultMapper(prop.
|
|
362
|
+
return item == null ? item : this.getResultMapper(prop.targetMeta)(item);
|
|
337
363
|
});
|
|
338
364
|
lines.push(`${padding} if (typeof ${this.propName(prop.fieldNames[0])} !== 'undefined') {`);
|
|
339
365
|
lines.push(`${padding} ret${this.wrap(prop.name)} = ${this.propName(prop.fieldNames[0])} == null ? ${this.propName(prop.fieldNames[0])} : mapEmbeddedResult_${idx}(${this.propName(prop.fieldNames[0])});`);
|
|
@@ -363,10 +389,11 @@ export class EntityComparator {
|
|
|
363
389
|
mapEntityProperties(meta);
|
|
364
390
|
}
|
|
365
391
|
lines.push(` for (let k in result) { if (Object.hasOwn(result, k) && !mapped[k] && ret[k] === undefined) ret[k] = result[k]; }`);
|
|
366
|
-
const code = `// compiled mapper for entity ${meta.className}\n`
|
|
367
|
-
|
|
368
|
-
const
|
|
369
|
-
this.
|
|
392
|
+
const code = `// compiled mapper for entity ${meta.className}\n` +
|
|
393
|
+
`return function(result) {\n const ret = {};\n${lines.join('\n')}\n return ret;\n}`;
|
|
394
|
+
const fnKey = `resultMapper-${meta.uniqueName}`;
|
|
395
|
+
const resultMapper = Utils.createFunction(context, code, this.config?.get('compiledFunctions'), fnKey);
|
|
396
|
+
this.mappers.set(meta, resultMapper);
|
|
370
397
|
return resultMapper;
|
|
371
398
|
}
|
|
372
399
|
getPropertyCondition(path) {
|
|
@@ -377,12 +404,12 @@ export class EntityComparator {
|
|
|
377
404
|
let tail = '';
|
|
378
405
|
return parts
|
|
379
406
|
.map(k => {
|
|
380
|
-
if (
|
|
407
|
+
if (/^\[idx_\d+]$/.exec(k)) {
|
|
381
408
|
tail += k;
|
|
382
409
|
return '';
|
|
383
410
|
}
|
|
384
411
|
const mapped = `typeof entity${tail ? '.' + tail : ''}${this.wrap(k)} !== 'undefined'`;
|
|
385
|
-
tail += tail ?
|
|
412
|
+
tail += tail ? '.' + k : k;
|
|
386
413
|
return mapped;
|
|
387
414
|
})
|
|
388
415
|
.filter(k => k)
|
|
@@ -417,11 +444,25 @@ export class EntityComparator {
|
|
|
417
444
|
}
|
|
418
445
|
getEmbeddedPropertySnapshot(meta, prop, context, level, path, dataKey, object = prop.object) {
|
|
419
446
|
const padding = ' '.repeat(level * 2);
|
|
420
|
-
|
|
447
|
+
const nullCond = `entity${path.map(k => this.wrap(k)).join('')} === null`;
|
|
448
|
+
let ret = level === 1 ? '' : '\n';
|
|
421
449
|
if (object) {
|
|
422
|
-
const nullCond = `entity${path.map(k => this.wrap(k)).join('')} === null`;
|
|
423
450
|
ret += `${padding}if (${nullCond}) ret${dataKey} = null;\n`;
|
|
424
451
|
}
|
|
452
|
+
else {
|
|
453
|
+
ret += `${padding}if (${nullCond}) {\n`;
|
|
454
|
+
ret +=
|
|
455
|
+
meta.props
|
|
456
|
+
.filter(p => p.embedded?.[0] === prop.name &&
|
|
457
|
+
// object for JSON embeddable
|
|
458
|
+
(p.object || p.persist !== false))
|
|
459
|
+
.map(childProp => {
|
|
460
|
+
const childDataKey = meta.embeddable || prop.object ? dataKey + this.wrap(childProp.embedded[1]) : this.wrap(childProp.name);
|
|
461
|
+
return `${padding} ret${childDataKey} = null;`;
|
|
462
|
+
})
|
|
463
|
+
.join('\n') + `\n`;
|
|
464
|
+
ret += `${padding}}\n`;
|
|
465
|
+
}
|
|
425
466
|
const cond = `entity${path.map(k => this.wrap(k)).join('')} != null`;
|
|
426
467
|
ret += `${padding}if (${cond}) {\n`;
|
|
427
468
|
if (object) {
|
|
@@ -436,28 +477,34 @@ export class EntityComparator {
|
|
|
436
477
|
}
|
|
437
478
|
return true;
|
|
438
479
|
}
|
|
439
|
-
ret +=
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
.split('\n').map(l => padding + l).join('\n');
|
|
451
|
-
}
|
|
452
|
-
if (shouldProcessCustomType(childProp)) {
|
|
453
|
-
const convertorKey = this.registerCustomType(childProp, context);
|
|
454
|
-
if (['number', 'string', 'boolean', 'bigint'].includes(childProp.customType.compareAsType().toLowerCase())) {
|
|
455
|
-
return `${padding} if (${childCond}) ret${childDataKey} = convertToDatabaseValue_${convertorKey}(entity${childEntityKey});`;
|
|
480
|
+
ret +=
|
|
481
|
+
meta.props
|
|
482
|
+
.filter(p => p.embedded?.[0] === prop.name &&
|
|
483
|
+
// object for JSON embeddable
|
|
484
|
+
(p.object || p.persist !== false))
|
|
485
|
+
.map(childProp => {
|
|
486
|
+
const childDataKey = meta.embeddable || prop.object ? dataKey + this.wrap(childProp.embedded[1]) : this.wrap(childProp.name);
|
|
487
|
+
const childEntityKey = [...path, childProp.embedded[1]].map(k => this.wrap(k)).join('');
|
|
488
|
+
const childCond = `typeof entity${childEntityKey} !== 'undefined'`;
|
|
489
|
+
if (childProp.kind === ReferenceKind.EMBEDDED) {
|
|
490
|
+
return this.getPropertySnapshot(meta, childProp, context, childDataKey, childEntityKey, [...path, childProp.embedded[1]], level + 1, prop.object);
|
|
456
491
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
492
|
+
if (childProp.kind !== ReferenceKind.SCALAR) {
|
|
493
|
+
return this.getPropertySnapshot(meta, childProp, context, childDataKey, childEntityKey, [...path, childProp.embedded[1]], level, prop.object)
|
|
494
|
+
.split('\n')
|
|
495
|
+
.map(l => padding + l)
|
|
496
|
+
.join('\n');
|
|
497
|
+
}
|
|
498
|
+
if (shouldProcessCustomType(childProp)) {
|
|
499
|
+
const convertorKey = this.registerCustomType(childProp, context);
|
|
500
|
+
if (['number', 'string', 'boolean', 'bigint'].includes(childProp.customType.compareAsType().toLowerCase())) {
|
|
501
|
+
return `${padding} if (${childCond}) ret${childDataKey} = convertToDatabaseValue_${convertorKey}(entity${childEntityKey});`;
|
|
502
|
+
}
|
|
503
|
+
return `${padding} if (${childCond}) ret${childDataKey} = clone(convertToDatabaseValue_${convertorKey}(entity${childEntityKey}));`;
|
|
504
|
+
}
|
|
505
|
+
return `${padding} if (${childCond}) ret${childDataKey} = clone(entity${childEntityKey});`;
|
|
506
|
+
})
|
|
507
|
+
.join('\n') + `\n`;
|
|
461
508
|
if (this.shouldSerialize(prop, dataKey)) {
|
|
462
509
|
return `${ret + padding} ret${dataKey} = cloneEmbeddable(ret${dataKey});\n${padding}}`;
|
|
463
510
|
}
|
|
@@ -466,8 +513,8 @@ export class EntityComparator {
|
|
|
466
513
|
registerCustomType(prop, context) {
|
|
467
514
|
const convertorKey = this.safeKey(prop.name);
|
|
468
515
|
context.set(`convertToDatabaseValue_${convertorKey}`, (val) => {
|
|
469
|
-
/* v8 ignore next
|
|
470
|
-
if (
|
|
516
|
+
/* v8 ignore next */
|
|
517
|
+
if (Raw.isKnownFragment(val)) {
|
|
471
518
|
return val;
|
|
472
519
|
}
|
|
473
520
|
return prop.customType.convertToDatabaseValue(val, this.platform, { mode: 'serialization' });
|
|
@@ -496,16 +543,51 @@ export class EntityComparator {
|
|
|
496
543
|
ret += ` ret${dataKey} = entity${entityKey};\n`;
|
|
497
544
|
}
|
|
498
545
|
}
|
|
546
|
+
else if (prop.polymorphic) {
|
|
547
|
+
const discriminatorMapKey = `discriminatorMapReverse_${prop.name}`;
|
|
548
|
+
const reverseMap = new Map();
|
|
549
|
+
for (const [key, value] of Object.entries(prop.discriminatorMap)) {
|
|
550
|
+
reverseMap.set(value, key);
|
|
551
|
+
}
|
|
552
|
+
context.set(discriminatorMapKey, reverseMap);
|
|
553
|
+
this.setToArrayHelper(context);
|
|
554
|
+
context.set('EntityIdentifier', EntityIdentifier);
|
|
555
|
+
context.set('PolymorphicRef', PolymorphicRef);
|
|
556
|
+
ret += ` if (entity${entityKey} === null) {\n`;
|
|
557
|
+
ret += ` ret${dataKey} = null;\n`;
|
|
558
|
+
ret += ` } else if (typeof entity${entityKey} !== 'undefined') {\n`;
|
|
559
|
+
ret += ` const val${level} = entity${entityKey}${unwrap};\n`;
|
|
560
|
+
ret += ` const discriminator = ${discriminatorMapKey}.get(val${level}?.constructor);\n`;
|
|
561
|
+
ret += ` const pk = val${level}?.__helper?.__identifier && !val${level}?.__helper?.hasPrimaryKey()\n`;
|
|
562
|
+
ret += ` ? val${level}.__helper.__identifier\n`;
|
|
563
|
+
ret += ` : toArray(val${level}?.__helper?.getPrimaryKey(true));\n`;
|
|
564
|
+
ret += ` ret${dataKey} = new PolymorphicRef(discriminator, pk);\n`;
|
|
565
|
+
ret += ` }\n`;
|
|
566
|
+
}
|
|
567
|
+
else if (prop.targetKey) {
|
|
568
|
+
// When targetKey is set, extract that property value instead of the PK
|
|
569
|
+
const targetProp = prop.targetMeta?.properties[prop.targetKey];
|
|
570
|
+
ret += ` if (entity${entityKey} === null) {\n`;
|
|
571
|
+
ret += ` ret${dataKey} = null;\n`;
|
|
572
|
+
ret += ` } else if (typeof entity${entityKey} !== 'undefined') {\n`;
|
|
573
|
+
ret += ` const val${level} = entity${entityKey}${unwrap};\n`;
|
|
574
|
+
if (targetProp?.customType) {
|
|
575
|
+
// If targetKey property has a custom type, convert to database value
|
|
576
|
+
const convertorKey = this.registerCustomType(targetProp, context);
|
|
577
|
+
ret += ` ret${dataKey} = convertToDatabaseValue_${convertorKey}(val${level}?.${prop.targetKey});\n`;
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
ret += ` ret${dataKey} = val${level}?.${prop.targetKey};\n`;
|
|
581
|
+
}
|
|
582
|
+
ret += ` }\n`;
|
|
583
|
+
}
|
|
499
584
|
else {
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
return Object.values(val).map(v => toArray(v));
|
|
503
|
-
}
|
|
504
|
-
return val;
|
|
505
|
-
};
|
|
506
|
-
context.set('toArray', toArray);
|
|
585
|
+
this.setToArrayHelper(context);
|
|
586
|
+
context.set('EntityIdentifier', EntityIdentifier);
|
|
507
587
|
ret += ` if (entity${entityKey} === null) {\n`;
|
|
508
588
|
ret += ` ret${dataKey} = null;\n`;
|
|
589
|
+
ret += ` } else if (entity${entityKey}?.__helper.__identifier && !entity${entityKey}.__helper.hasPrimaryKey()) {\n`;
|
|
590
|
+
ret += ` ret${dataKey} = entity${entityKey}?.__helper.__identifier;\n`;
|
|
509
591
|
ret += ` } else if (typeof entity${entityKey} !== 'undefined') {\n`;
|
|
510
592
|
ret += ` ret${dataKey} = toArray(entity${entityKey}.__helper.getPrimaryKey(true));\n`;
|
|
511
593
|
ret += ` }\n`;
|
|
@@ -517,7 +599,7 @@ export class EntityComparator {
|
|
|
517
599
|
if (['number', 'string', 'boolean', 'bigint'].includes(prop.customType.compareAsType().toLowerCase())) {
|
|
518
600
|
return ret + ` ret${dataKey} = convertToDatabaseValue_${convertorKey}(entity${entityKey}${unwrap});\n }\n`;
|
|
519
601
|
}
|
|
520
|
-
return ret + ` ret${dataKey} = clone(convertToDatabaseValue_${convertorKey}(entity${entityKey}${unwrap}));\n }\n
|
|
602
|
+
return (ret + ` ret${dataKey} = clone(convertToDatabaseValue_${convertorKey}(entity${entityKey}${unwrap}));\n }\n`);
|
|
521
603
|
}
|
|
522
604
|
if (prop.runtimeType === 'Date') {
|
|
523
605
|
context.set('processDateProperty', this.platform.processDateProperty.bind(this.platform));
|
|
@@ -529,11 +611,11 @@ export class EntityComparator {
|
|
|
529
611
|
* @internal Highly performance-sensitive method.
|
|
530
612
|
*/
|
|
531
613
|
getEntityComparator(entityName) {
|
|
532
|
-
const
|
|
614
|
+
const meta = this.metadata.find(entityName);
|
|
615
|
+
const exists = this.comparators.get(meta);
|
|
533
616
|
if (exists) {
|
|
534
617
|
return exists;
|
|
535
618
|
}
|
|
536
|
-
const meta = this.metadata.find(entityName);
|
|
537
619
|
const lines = [];
|
|
538
620
|
const context = new Map();
|
|
539
621
|
context.set('compareArrays', compareArrays);
|
|
@@ -542,10 +624,7 @@ export class EntityComparator {
|
|
|
542
624
|
context.set('compareObjects', compareObjects);
|
|
543
625
|
context.set('equals', equals);
|
|
544
626
|
for (const prop of meta.comparableProps) {
|
|
545
|
-
|
|
546
|
-
if (prop.hydrate !== false) {
|
|
547
|
-
lines.push(this.getPropertyComparator(prop, context));
|
|
548
|
-
}
|
|
627
|
+
lines.push(this.getPropertyComparator(prop, context));
|
|
549
628
|
}
|
|
550
629
|
// also compare 1:1 inverse sides, important for `factory.mergeData`
|
|
551
630
|
lines.push(`if (options?.includeInverseSides) {`);
|
|
@@ -555,37 +634,48 @@ export class EntityComparator {
|
|
|
555
634
|
}
|
|
556
635
|
}
|
|
557
636
|
lines.push(`}`);
|
|
558
|
-
const code = `// compiled comparator for entity ${meta.className}\n`
|
|
559
|
-
|
|
560
|
-
const
|
|
561
|
-
this.
|
|
637
|
+
const code = `// compiled comparator for entity ${meta.className}\n` +
|
|
638
|
+
`return function(last, current, options) {\n const diff = {};\n${lines.join('\n')}\n return diff;\n}`;
|
|
639
|
+
const fnKey = `comparator-${meta.uniqueName}`;
|
|
640
|
+
const comparator = Utils.createFunction(context, code, this.config?.get('compiledFunctions'), fnKey);
|
|
641
|
+
this.comparators.set(meta, comparator);
|
|
562
642
|
return comparator;
|
|
563
643
|
}
|
|
564
644
|
getGenericComparator(prop, cond) {
|
|
565
|
-
return ` if (current${prop} === null && last${prop} === undefined) {\n` +
|
|
645
|
+
return (` if (current${prop} === null && last${prop} === undefined) {\n` +
|
|
566
646
|
` diff${prop} = current${prop};\n` +
|
|
567
647
|
` } else if (current${prop} == null && last${prop} == null) {\n\n` +
|
|
568
648
|
` } else if ((current${prop} != null && last${prop} == null) || (current${prop} == null && last${prop} != null)) {\n` +
|
|
569
649
|
` diff${prop} = current${prop};\n` +
|
|
570
650
|
` } else if (${cond}) {\n` +
|
|
571
651
|
` diff${prop} = current${prop};\n` +
|
|
572
|
-
` }\n
|
|
652
|
+
` }\n`);
|
|
573
653
|
}
|
|
574
654
|
getPropertyComparator(prop, context) {
|
|
575
655
|
let type = prop.type.toLowerCase();
|
|
576
656
|
if (prop.kind !== ReferenceKind.SCALAR && prop.kind !== ReferenceKind.EMBEDDED) {
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
type = 'array';
|
|
657
|
+
if (prop.polymorphic) {
|
|
658
|
+
type = 'object';
|
|
580
659
|
}
|
|
581
660
|
else {
|
|
582
|
-
|
|
661
|
+
const meta2 = prop.targetMeta;
|
|
662
|
+
if (meta2.primaryKeys.length > 1) {
|
|
663
|
+
type = 'array';
|
|
664
|
+
}
|
|
665
|
+
else {
|
|
666
|
+
type = meta2.getPrimaryProp().type.toLowerCase();
|
|
667
|
+
}
|
|
583
668
|
}
|
|
584
669
|
}
|
|
585
670
|
if (prop.customType) {
|
|
586
671
|
if (prop.customType.compareValues) {
|
|
587
672
|
const idx = this.tmpIndex++;
|
|
588
|
-
context.set(`compareValues_${idx}`, (a, b) =>
|
|
673
|
+
context.set(`compareValues_${idx}`, (a, b) => {
|
|
674
|
+
if (Raw.isKnownFragment(a) || Raw.isKnownFragment(b)) {
|
|
675
|
+
return Raw.getKnownFragment(a) === Raw.getKnownFragment(b);
|
|
676
|
+
}
|
|
677
|
+
return prop.customType.compareValues(a, b);
|
|
678
|
+
});
|
|
589
679
|
return this.getGenericComparator(this.wrap(prop.name), `!compareValues_${idx}(last${this.wrap(prop.name)}, current${this.wrap(prop.name)})`);
|
|
590
680
|
}
|
|
591
681
|
type = prop.customType.compareAsType().toLowerCase();
|
|
@@ -605,10 +695,10 @@ export class EntityComparator {
|
|
|
605
695
|
if (['buffer', 'uint8array'].includes(type)) {
|
|
606
696
|
return this.getGenericComparator(this.wrap(prop.name), `!compareBuffers(last${this.wrap(prop.name)}, current${this.wrap(prop.name)})`);
|
|
607
697
|
}
|
|
608
|
-
if (
|
|
698
|
+
if (type === 'date') {
|
|
609
699
|
return this.getGenericComparator(this.wrap(prop.name), `last${this.wrap(prop.name)}.valueOf() !== current${this.wrap(prop.name)}.valueOf()`);
|
|
610
700
|
}
|
|
611
|
-
if (
|
|
701
|
+
if (type === 'objectid') {
|
|
612
702
|
// We might be comparing PK to object, in case we compare with cached data of populated entity
|
|
613
703
|
// in such case we just ignore the comparison and fallback to `equals()` (which will still mark
|
|
614
704
|
// it as not equal as we compare PK to plain object).
|
|
@@ -618,14 +708,30 @@ export class EntityComparator {
|
|
|
618
708
|
return this.getGenericComparator(this.wrap(prop.name), `!equals(last${this.wrap(prop.name)}, current${this.wrap(prop.name)})`);
|
|
619
709
|
}
|
|
620
710
|
wrap(key) {
|
|
621
|
-
if (
|
|
711
|
+
if (/^\[.*]$/.exec(key)) {
|
|
622
712
|
return key;
|
|
623
713
|
}
|
|
624
|
-
return
|
|
714
|
+
return /^\w+$/.exec(key) ? `.${key}` : `['${key}']`;
|
|
625
715
|
}
|
|
626
716
|
safeKey(key) {
|
|
627
717
|
return key.replace(/\W/g, '_');
|
|
628
718
|
}
|
|
719
|
+
/**
|
|
720
|
+
* Sets the toArray helper in the context if not already set.
|
|
721
|
+
* Used for converting composite PKs to arrays.
|
|
722
|
+
*/
|
|
723
|
+
setToArrayHelper(context) {
|
|
724
|
+
if (context.has('toArray')) {
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
const toArray = (val) => {
|
|
728
|
+
if (Utils.isPlainObject(val)) {
|
|
729
|
+
return Object.values(val).map(v => toArray(v));
|
|
730
|
+
}
|
|
731
|
+
return val;
|
|
732
|
+
};
|
|
733
|
+
context.set('toArray', toArray);
|
|
734
|
+
}
|
|
629
735
|
/**
|
|
630
736
|
* perf: used to generate list of comparable properties during discovery, so we speed up the runtime comparison
|
|
631
737
|
*/
|