@mikro-orm/core 7.0.0-dev.2 → 7.0.0-dev.200
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 +111 -61
- package/EntityManager.js +346 -300
- package/MikroORM.d.ts +44 -35
- package/MikroORM.js +103 -143
- package/README.md +3 -2
- package/cache/FileCacheAdapter.d.ts +1 -1
- package/cache/FileCacheAdapter.js +8 -7
- package/cache/GeneratedCacheAdapter.d.ts +0 -1
- package/cache/GeneratedCacheAdapter.js +0 -2
- package/cache/index.d.ts +0 -1
- package/cache/index.js +0 -1
- package/connections/Connection.d.ts +16 -7
- package/connections/Connection.js +23 -14
- package/drivers/DatabaseDriver.d.ts +25 -16
- package/drivers/DatabaseDriver.js +80 -35
- package/drivers/IDatabaseDriver.d.ts +47 -17
- package/entity/BaseEntity.d.ts +2 -2
- package/entity/BaseEntity.js +0 -3
- package/entity/Collection.d.ts +95 -31
- package/entity/Collection.js +444 -102
- package/entity/EntityAssigner.d.ts +1 -1
- package/entity/EntityAssigner.js +26 -18
- package/entity/EntityFactory.d.ts +13 -1
- package/entity/EntityFactory.js +88 -54
- package/entity/EntityHelper.d.ts +2 -2
- package/entity/EntityHelper.js +38 -15
- package/entity/EntityLoader.d.ts +8 -7
- package/entity/EntityLoader.js +134 -80
- package/entity/EntityRepository.d.ts +24 -4
- package/entity/EntityRepository.js +8 -2
- package/entity/Reference.d.ts +9 -12
- package/entity/Reference.js +34 -9
- package/entity/WrappedEntity.d.ts +2 -7
- package/entity/WrappedEntity.js +3 -8
- package/entity/defineEntity.d.ts +585 -0
- package/entity/defineEntity.js +533 -0
- package/entity/index.d.ts +3 -2
- package/entity/index.js +3 -2
- package/entity/utils.d.ts +7 -0
- package/entity/utils.js +16 -4
- package/entity/validators.d.ts +11 -0
- package/entity/validators.js +65 -0
- package/enums.d.ts +22 -6
- package/enums.js +15 -1
- package/errors.d.ts +23 -9
- package/errors.js +59 -21
- package/events/EventManager.d.ts +2 -1
- package/events/EventManager.js +19 -11
- package/events/EventSubscriber.d.ts +3 -1
- package/hydration/Hydrator.js +1 -2
- package/hydration/ObjectHydrator.d.ts +4 -4
- package/hydration/ObjectHydrator.js +53 -33
- package/index.d.ts +2 -2
- package/index.js +1 -2
- package/logging/DefaultLogger.d.ts +1 -1
- package/logging/DefaultLogger.js +1 -0
- package/logging/SimpleLogger.d.ts +1 -1
- package/logging/colors.d.ts +1 -1
- package/logging/colors.js +7 -6
- package/logging/index.d.ts +1 -0
- package/logging/index.js +1 -0
- package/logging/inspect.d.ts +2 -0
- package/logging/inspect.js +11 -0
- package/metadata/EntitySchema.d.ts +26 -26
- package/metadata/EntitySchema.js +82 -51
- package/metadata/MetadataDiscovery.d.ts +7 -10
- package/metadata/MetadataDiscovery.js +408 -335
- package/metadata/MetadataProvider.d.ts +11 -2
- package/metadata/MetadataProvider.js +46 -2
- package/metadata/MetadataStorage.d.ts +13 -11
- package/metadata/MetadataStorage.js +70 -37
- package/metadata/MetadataValidator.d.ts +17 -9
- package/metadata/MetadataValidator.js +100 -42
- package/metadata/discover-entities.d.ts +5 -0
- package/metadata/discover-entities.js +40 -0
- package/metadata/index.d.ts +1 -1
- package/metadata/index.js +1 -1
- package/metadata/types.d.ts +502 -0
- package/metadata/types.js +1 -0
- package/naming-strategy/AbstractNamingStrategy.d.ts +12 -4
- package/naming-strategy/AbstractNamingStrategy.js +14 -2
- package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
- package/naming-strategy/EntityCaseNamingStrategy.js +6 -5
- package/naming-strategy/MongoNamingStrategy.d.ts +3 -3
- package/naming-strategy/MongoNamingStrategy.js +6 -6
- package/naming-strategy/NamingStrategy.d.ts +24 -4
- package/naming-strategy/UnderscoreNamingStrategy.d.ts +3 -3
- package/naming-strategy/UnderscoreNamingStrategy.js +6 -6
- package/not-supported.d.ts +2 -0
- package/not-supported.js +4 -0
- package/package.json +19 -11
- package/platforms/ExceptionConverter.js +1 -1
- package/platforms/Platform.d.ts +7 -13
- package/platforms/Platform.js +20 -43
- package/serialization/EntitySerializer.d.ts +5 -0
- package/serialization/EntitySerializer.js +47 -27
- package/serialization/EntityTransformer.js +28 -18
- package/serialization/SerializationContext.d.ts +6 -6
- package/serialization/SerializationContext.js +16 -13
- package/types/ArrayType.d.ts +1 -1
- package/types/ArrayType.js +2 -3
- package/types/BigIntType.d.ts +9 -6
- package/types/BigIntType.js +4 -1
- 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 +3 -3
- package/types/DoubleType.js +2 -2
- package/types/EnumArrayType.js +1 -2
- package/types/JsonType.d.ts +1 -1
- package/types/JsonType.js +7 -2
- package/types/TinyIntType.js +1 -1
- package/types/Type.d.ts +2 -4
- package/types/Type.js +3 -3
- package/types/Uint8ArrayType.d.ts +0 -1
- package/types/Uint8ArrayType.js +1 -4
- package/types/index.d.ts +1 -1
- package/typings.d.ts +300 -140
- package/typings.js +62 -44
- package/unit-of-work/ChangeSet.d.ts +2 -6
- package/unit-of-work/ChangeSet.js +4 -5
- package/unit-of-work/ChangeSetComputer.d.ts +1 -3
- package/unit-of-work/ChangeSetComputer.js +26 -13
- package/unit-of-work/ChangeSetPersister.d.ts +5 -4
- package/unit-of-work/ChangeSetPersister.js +77 -35
- package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
- package/unit-of-work/CommitOrderCalculator.js +13 -13
- package/unit-of-work/IdentityMap.d.ts +12 -0
- package/unit-of-work/IdentityMap.js +39 -1
- package/unit-of-work/UnitOfWork.d.ts +23 -3
- package/unit-of-work/UnitOfWork.js +199 -106
- package/utils/AbstractSchemaGenerator.d.ts +5 -5
- package/utils/AbstractSchemaGenerator.js +22 -17
- package/utils/AsyncContext.d.ts +6 -0
- package/utils/AsyncContext.js +42 -0
- package/utils/Configuration.d.ts +779 -207
- package/utils/Configuration.js +146 -190
- package/utils/ConfigurationLoader.d.ts +1 -54
- package/utils/ConfigurationLoader.js +1 -352
- package/utils/Cursor.d.ts +3 -6
- package/utils/Cursor.js +27 -11
- package/utils/DataloaderUtils.d.ts +15 -5
- package/utils/DataloaderUtils.js +65 -17
- package/utils/EntityComparator.d.ts +13 -9
- package/utils/EntityComparator.js +164 -89
- package/utils/QueryHelper.d.ts +14 -6
- package/utils/QueryHelper.js +88 -26
- package/utils/RawQueryFragment.d.ts +48 -25
- package/utils/RawQueryFragment.js +67 -66
- package/utils/RequestContext.js +2 -2
- package/utils/TransactionContext.js +2 -2
- package/utils/TransactionManager.d.ts +65 -0
- package/utils/TransactionManager.js +223 -0
- package/utils/Utils.d.ts +13 -120
- package/utils/Utils.js +104 -375
- package/utils/clone.js +8 -23
- package/utils/env-vars.d.ts +7 -0
- package/utils/env-vars.js +97 -0
- package/utils/fs-utils.d.ts +32 -0
- package/utils/fs-utils.js +178 -0
- package/utils/index.d.ts +2 -1
- package/utils/index.js +2 -1
- package/utils/upsert-utils.d.ts +9 -4
- package/utils/upsert-utils.js +55 -4
- 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 -29
- 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 -13
- 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 -5
- package/decorators/Formula.js +0 -15
- package/decorators/Indexed.d.ts +0 -17
- 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 -9
- 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 -395
- 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
|
@@ -2,7 +2,8 @@ import { clone } from './clone.js';
|
|
|
2
2
|
import { ReferenceKind } from '../enums.js';
|
|
3
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';
|
|
6
7
|
export class EntityComparator {
|
|
7
8
|
metadata;
|
|
8
9
|
platform;
|
|
@@ -20,9 +21,9 @@ export class EntityComparator {
|
|
|
20
21
|
/**
|
|
21
22
|
* Computes difference between two entities.
|
|
22
23
|
*/
|
|
23
|
-
diffEntities(entityName, a, b) {
|
|
24
|
+
diffEntities(entityName, a, b, options) {
|
|
24
25
|
const comparator = this.getEntityComparator(entityName);
|
|
25
|
-
return Utils.callCompiledFunction(comparator, a, b);
|
|
26
|
+
return Utils.callCompiledFunction(comparator, a, b, options);
|
|
26
27
|
}
|
|
27
28
|
matching(entityName, a, b) {
|
|
28
29
|
const diff = this.diffEntities(entityName, a, b);
|
|
@@ -33,22 +34,22 @@ export class EntityComparator {
|
|
|
33
34
|
* References will be mapped to primary keys, collections to arrays of primary keys.
|
|
34
35
|
*/
|
|
35
36
|
prepareEntity(entity) {
|
|
36
|
-
const generator = this.getSnapshotGenerator(entity.constructor
|
|
37
|
+
const generator = this.getSnapshotGenerator(entity.constructor);
|
|
37
38
|
return Utils.callCompiledFunction(generator, entity);
|
|
38
39
|
}
|
|
39
40
|
/**
|
|
40
41
|
* Maps database columns to properties.
|
|
41
42
|
*/
|
|
42
|
-
mapResult(
|
|
43
|
-
const mapper = this.getResultMapper(
|
|
43
|
+
mapResult(meta, result) {
|
|
44
|
+
const mapper = this.getResultMapper(meta);
|
|
44
45
|
return Utils.callCompiledFunction(mapper, result);
|
|
45
46
|
}
|
|
46
47
|
/**
|
|
47
48
|
* @internal Highly performance-sensitive method.
|
|
48
49
|
*/
|
|
49
50
|
getPkGetter(meta) {
|
|
50
|
-
const exists = this.pkGetters.get(meta
|
|
51
|
-
/* v8 ignore next
|
|
51
|
+
const exists = this.pkGetters.get(meta);
|
|
52
|
+
/* v8 ignore next */
|
|
52
53
|
if (exists) {
|
|
53
54
|
return exists;
|
|
54
55
|
}
|
|
@@ -74,7 +75,7 @@ export class EntityComparator {
|
|
|
74
75
|
lines.push(` if (entity${this.wrap(pk)} != null && (entity${this.wrap(pk)}.__entity || entity${this.wrap(pk)}.__reference)) {`);
|
|
75
76
|
lines.push(` const pk = entity${this.wrap(pk)}.__helper.getPrimaryKey();`);
|
|
76
77
|
if (meta.properties[pk].targetMeta.compositePK) {
|
|
77
|
-
lines.push(` if (typeof pk === 'object') {`);
|
|
78
|
+
lines.push(` if (typeof pk === 'object' && pk != null) {`);
|
|
78
79
|
lines.push(` return [`);
|
|
79
80
|
for (const childPK of meta.properties[pk].targetMeta.primaryKeys) {
|
|
80
81
|
lines.push(` pk${this.wrap(childPK)},`);
|
|
@@ -90,15 +91,15 @@ export class EntityComparator {
|
|
|
90
91
|
const code = `// compiled pk serializer for entity ${meta.className}\n`
|
|
91
92
|
+ `return function(entity) {\n${lines.join('\n')}\n}`;
|
|
92
93
|
const pkSerializer = Utils.createFunction(context, code);
|
|
93
|
-
this.pkGetters.set(meta
|
|
94
|
+
this.pkGetters.set(meta, pkSerializer);
|
|
94
95
|
return pkSerializer;
|
|
95
96
|
}
|
|
96
97
|
/**
|
|
97
98
|
* @internal Highly performance-sensitive method.
|
|
98
99
|
*/
|
|
99
100
|
getPkGetterConverted(meta) {
|
|
100
|
-
const exists = this.pkGettersConverted.get(meta
|
|
101
|
-
/* v8 ignore next
|
|
101
|
+
const exists = this.pkGettersConverted.get(meta);
|
|
102
|
+
/* v8 ignore next */
|
|
102
103
|
if (exists) {
|
|
103
104
|
return exists;
|
|
104
105
|
}
|
|
@@ -140,21 +141,22 @@ export class EntityComparator {
|
|
|
140
141
|
const code = `// compiled pk getter (with converted custom types) for entity ${meta.className}\n`
|
|
141
142
|
+ `return function(entity) {\n${lines.join('\n')}\n}`;
|
|
142
143
|
const pkSerializer = Utils.createFunction(context, code);
|
|
143
|
-
this.pkGettersConverted.set(meta
|
|
144
|
+
this.pkGettersConverted.set(meta, pkSerializer);
|
|
144
145
|
return pkSerializer;
|
|
145
146
|
}
|
|
146
147
|
/**
|
|
147
148
|
* @internal Highly performance-sensitive method.
|
|
148
149
|
*/
|
|
149
150
|
getPkSerializer(meta) {
|
|
150
|
-
const exists = this.pkSerializers.get(meta
|
|
151
|
-
/* v8 ignore next
|
|
151
|
+
const exists = this.pkSerializers.get(meta);
|
|
152
|
+
/* v8 ignore next */
|
|
152
153
|
if (exists) {
|
|
153
154
|
return exists;
|
|
154
155
|
}
|
|
155
156
|
const lines = [];
|
|
156
157
|
const context = new Map();
|
|
157
158
|
context.set('getCompositeKeyValue', (val) => Utils.flatten(Utils.getCompositeKeyValue(val, meta, 'convertToDatabaseValue', this.platform)));
|
|
159
|
+
context.set('getPrimaryKeyHash', (val) => Utils.getPrimaryKeyHash(Utils.asArray(val)));
|
|
158
160
|
if (meta.primaryKeys.length > 1) {
|
|
159
161
|
lines.push(` const pks = entity.__helper.__pk ? getCompositeKeyValue(entity.__helper.__pk) : [`);
|
|
160
162
|
meta.primaryKeys.forEach(pk => {
|
|
@@ -170,30 +172,39 @@ export class EntityComparator {
|
|
|
170
172
|
}
|
|
171
173
|
else {
|
|
172
174
|
const pk = meta.primaryKeys[0];
|
|
173
|
-
|
|
175
|
+
const prop = meta.properties[pk];
|
|
176
|
+
if (prop.kind !== ReferenceKind.SCALAR) {
|
|
174
177
|
lines.push(` if (entity${this.wrap(pk)} != null && (entity${this.wrap(pk)}.__entity || entity${this.wrap(pk)}.__reference)) return entity${this.wrap(pk)}.__helper.getSerializedPrimaryKey();`);
|
|
175
178
|
}
|
|
176
179
|
const serializedPrimaryKey = meta.props.find(p => p.serializedPrimaryKey);
|
|
177
180
|
if (serializedPrimaryKey) {
|
|
178
181
|
lines.push(` return '' + entity.${serializedPrimaryKey.name};`);
|
|
179
182
|
}
|
|
180
|
-
|
|
183
|
+
else if (prop.customType) {
|
|
184
|
+
const convertorKey = this.registerCustomType(meta.properties[pk], context);
|
|
185
|
+
const idx = this.tmpIndex++;
|
|
186
|
+
lines.push(` const val_${idx} = convertToDatabaseValue_${convertorKey}(entity${this.wrap(pk)});`);
|
|
187
|
+
lines.push(` return getPrimaryKeyHash(val_${idx});`);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
lines.push(` return '' + entity${this.wrap(pk)};`);
|
|
191
|
+
}
|
|
181
192
|
}
|
|
182
193
|
const code = `// compiled pk serializer for entity ${meta.className}\n`
|
|
183
194
|
+ `return function(entity) {\n${lines.join('\n')}\n}`;
|
|
184
195
|
const pkSerializer = Utils.createFunction(context, code);
|
|
185
|
-
this.pkSerializers.set(meta
|
|
196
|
+
this.pkSerializers.set(meta, pkSerializer);
|
|
186
197
|
return pkSerializer;
|
|
187
198
|
}
|
|
188
199
|
/**
|
|
189
200
|
* @internal Highly performance-sensitive method.
|
|
190
201
|
*/
|
|
191
202
|
getSnapshotGenerator(entityName) {
|
|
192
|
-
const
|
|
203
|
+
const meta = this.metadata.find(entityName);
|
|
204
|
+
const exists = this.snapshotGenerators.get(meta);
|
|
193
205
|
if (exists) {
|
|
194
206
|
return exists;
|
|
195
207
|
}
|
|
196
|
-
const meta = this.metadata.find(entityName);
|
|
197
208
|
const lines = [];
|
|
198
209
|
const context = new Map();
|
|
199
210
|
context.set('clone', clone);
|
|
@@ -211,7 +222,7 @@ export class EntityComparator {
|
|
|
211
222
|
.forEach(prop => lines.push(this.getPropertySnapshot(meta, prop, context, this.wrap(prop.name), this.wrap(prop.name), [prop.name])));
|
|
212
223
|
const code = `return function(entity) {\n const ret = {};\n${lines.join('\n')}\n return ret;\n}`;
|
|
213
224
|
const snapshotGenerator = Utils.createFunction(context, code);
|
|
214
|
-
this.snapshotGenerators.set(
|
|
225
|
+
this.snapshotGenerators.set(meta, snapshotGenerator);
|
|
215
226
|
return snapshotGenerator;
|
|
216
227
|
}
|
|
217
228
|
/**
|
|
@@ -261,12 +272,11 @@ export class EntityComparator {
|
|
|
261
272
|
/**
|
|
262
273
|
* @internal Highly performance-sensitive method.
|
|
263
274
|
*/
|
|
264
|
-
getResultMapper(
|
|
265
|
-
const exists = this.mappers.get(
|
|
275
|
+
getResultMapper(meta) {
|
|
276
|
+
const exists = this.mappers.get(meta);
|
|
266
277
|
if (exists) {
|
|
267
278
|
return exists;
|
|
268
279
|
}
|
|
269
|
-
const meta = this.metadata.get(entityName);
|
|
270
280
|
const lines = [];
|
|
271
281
|
const context = new Map();
|
|
272
282
|
const tz = this.platform.getTimezone();
|
|
@@ -274,10 +284,14 @@ export class EntityComparator {
|
|
|
274
284
|
lines.push(`${padding} if (${value} == null || ${value} instanceof Date) {`);
|
|
275
285
|
lines.push(`${padding} ${key} = ${value};`);
|
|
276
286
|
if (!tz || tz === 'local') {
|
|
287
|
+
lines.push(`${padding} } else if (typeof ${value} === 'bigint') {`);
|
|
288
|
+
lines.push(`${padding} ${key} = parseDate(Number(${value}));`);
|
|
277
289
|
lines.push(`${padding} } else {`);
|
|
278
290
|
lines.push(`${padding} ${key} = parseDate(${value});`);
|
|
279
291
|
}
|
|
280
292
|
else {
|
|
293
|
+
lines.push(`${padding} } else if (typeof ${value} === 'bigint') {`);
|
|
294
|
+
lines.push(`${padding} ${key} = parseDate(Number(${value}));`);
|
|
281
295
|
lines.push(`${padding} } else if (typeof ${value} === 'number' || ${value}.includes('+') || ${value}.lastIndexOf('-') > 10 || ${value}.endsWith('Z')) {`);
|
|
282
296
|
lines.push(`${padding} ${key} = parseDate(${value});`);
|
|
283
297
|
lines.push(`${padding} } else {`);
|
|
@@ -286,61 +300,77 @@ export class EntityComparator {
|
|
|
286
300
|
lines.push(`${padding} }`);
|
|
287
301
|
};
|
|
288
302
|
lines.push(` const mapped = {};`);
|
|
289
|
-
meta
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
303
|
+
const mapEntityProperties = (meta, padding = '') => {
|
|
304
|
+
for (const prop of meta.props) {
|
|
305
|
+
if (!prop.fieldNames) {
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
if (prop.targetMeta && prop.fieldNames.length > 1) {
|
|
309
|
+
lines.push(`${padding} if (${prop.fieldNames.map(field => `typeof ${this.propName(field)} === 'undefined'`).join(' && ')}) {`);
|
|
310
|
+
lines.push(`${padding} } else if (${prop.fieldNames.map(field => `${this.propName(field)} != null`).join(' && ')}) {`);
|
|
311
|
+
lines.push(`${padding} ret${this.wrap(prop.name)} = ${this.createCompositeKeyArray(prop)};`);
|
|
312
|
+
lines.push(...prop.fieldNames.map(field => `${padding} ${this.propName(field, 'mapped')} = true;`));
|
|
313
|
+
lines.push(`${padding} } else if (${prop.fieldNames.map(field => `${this.propName(field)} == null`).join(' && ')}) {\n ret${this.wrap(prop.name)} = null;`);
|
|
314
|
+
lines.push(...prop.fieldNames.map(field => `${padding} ${this.propName(field, 'mapped')} = true;`), ' }');
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
if (prop.embedded && (meta.embeddable || meta.properties[prop.embedded[0]].object)) {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
if (prop.runtimeType === 'boolean') {
|
|
321
|
+
lines.push(`${padding} if (typeof ${this.propName(prop.fieldNames[0])} !== 'undefined') {`);
|
|
322
|
+
lines.push(`${padding} ret${this.wrap(prop.name)} = ${this.propName(prop.fieldNames[0])} == null ? ${this.propName(prop.fieldNames[0])} : !!${this.propName(prop.fieldNames[0])};`);
|
|
323
|
+
lines.push(`${padding} ${this.propName(prop.fieldNames[0], 'mapped')} = true;`);
|
|
324
|
+
lines.push(`${padding} }`);
|
|
325
|
+
}
|
|
326
|
+
else if (prop.runtimeType === 'Date' && !this.platform.isNumericProperty(prop)) {
|
|
327
|
+
lines.push(`${padding} if (typeof ${this.propName(prop.fieldNames[0])} !== 'undefined') {`);
|
|
328
|
+
context.set('parseDate', (value) => this.platform.parseDate(value));
|
|
329
|
+
parseDate('ret' + this.wrap(prop.name), this.propName(prop.fieldNames[0]), padding);
|
|
330
|
+
lines.push(`${padding} ${this.propName(prop.fieldNames[0], 'mapped')} = true;`);
|
|
331
|
+
lines.push(`${padding} }`);
|
|
332
|
+
}
|
|
333
|
+
else if (prop.kind === ReferenceKind.EMBEDDED && (prop.object || meta.embeddable)) {
|
|
334
|
+
const idx = this.tmpIndex++;
|
|
335
|
+
context.set(`mapEmbeddedResult_${idx}`, (data) => {
|
|
336
|
+
const item = parseJsonSafe(data);
|
|
337
|
+
if (Array.isArray(item)) {
|
|
338
|
+
return item.map(row => row == null ? row : this.getResultMapper(prop.targetMeta)(row));
|
|
339
|
+
}
|
|
340
|
+
return item == null ? item : this.getResultMapper(prop.targetMeta)(item);
|
|
341
|
+
});
|
|
342
|
+
lines.push(`${padding} if (typeof ${this.propName(prop.fieldNames[0])} !== 'undefined') {`);
|
|
343
|
+
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])});`);
|
|
344
|
+
lines.push(`${padding} ${this.propName(prop.fieldNames[0], 'mapped')} = true;`);
|
|
345
|
+
lines.push(`${padding} }`);
|
|
346
|
+
}
|
|
347
|
+
else if (prop.kind !== ReferenceKind.EMBEDDED) {
|
|
348
|
+
lines.push(`${padding} if (typeof ${this.propName(prop.fieldNames[0])} !== 'undefined') {`);
|
|
349
|
+
lines.push(`${padding} ret${this.wrap(prop.name)} = ${this.propName(prop.fieldNames[0])};`);
|
|
350
|
+
lines.push(`${padding} ${this.propName(prop.fieldNames[0], 'mapped')} = true;`);
|
|
351
|
+
lines.push(`${padding} }`);
|
|
352
|
+
}
|
|
331
353
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
354
|
+
};
|
|
355
|
+
if (meta.polymorphs && meta.discriminatorColumn) {
|
|
356
|
+
for (const polymorph of meta.polymorphs) {
|
|
357
|
+
const first = polymorph === meta.polymorphs[0];
|
|
358
|
+
lines.push(` ${first ? '' : 'else '}if (${this.propName(meta.discriminatorColumn)} == '${polymorph.discriminatorValue}') {`);
|
|
359
|
+
mapEntityProperties(polymorph, ' ');
|
|
336
360
|
lines.push(` }`);
|
|
337
361
|
}
|
|
338
|
-
|
|
339
|
-
|
|
362
|
+
lines.push(` else {`);
|
|
363
|
+
mapEntityProperties(meta, ' ');
|
|
364
|
+
lines.push(` }`);
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
mapEntityProperties(meta);
|
|
368
|
+
}
|
|
369
|
+
lines.push(` for (let k in result) { if (Object.hasOwn(result, k) && !mapped[k] && ret[k] === undefined) ret[k] = result[k]; }`);
|
|
340
370
|
const code = `// compiled mapper for entity ${meta.className}\n`
|
|
341
371
|
+ `return function(result) {\n const ret = {};\n${lines.join('\n')}\n return ret;\n}`;
|
|
342
372
|
const resultMapper = Utils.createFunction(context, code);
|
|
343
|
-
this.mappers.set(
|
|
373
|
+
this.mappers.set(meta, resultMapper);
|
|
344
374
|
return resultMapper;
|
|
345
375
|
}
|
|
346
376
|
getPropertyCondition(path) {
|
|
@@ -391,11 +421,21 @@ export class EntityComparator {
|
|
|
391
421
|
}
|
|
392
422
|
getEmbeddedPropertySnapshot(meta, prop, context, level, path, dataKey, object = prop.object) {
|
|
393
423
|
const padding = ' '.repeat(level * 2);
|
|
424
|
+
const nullCond = `entity${path.map(k => this.wrap(k)).join('')} === null`;
|
|
394
425
|
let ret = `${level === 1 ? '' : '\n'}`;
|
|
395
426
|
if (object) {
|
|
396
|
-
const nullCond = `entity${path.map(k => this.wrap(k)).join('')} === null`;
|
|
397
427
|
ret += `${padding}if (${nullCond}) ret${dataKey} = null;\n`;
|
|
398
428
|
}
|
|
429
|
+
else {
|
|
430
|
+
ret += `${padding}if (${nullCond}) {\n`;
|
|
431
|
+
ret += meta.props.filter(p => p.embedded?.[0] === prop.name
|
|
432
|
+
// object for JSON embeddable
|
|
433
|
+
&& (p.object || (p.persist !== false))).map(childProp => {
|
|
434
|
+
const childDataKey = meta.embeddable || prop.object ? dataKey + this.wrap(childProp.embedded[1]) : this.wrap(childProp.name);
|
|
435
|
+
return `${padding} ret${childDataKey} = null;`;
|
|
436
|
+
}).join('\n') + `\n`;
|
|
437
|
+
ret += `${padding}}\n`;
|
|
438
|
+
}
|
|
399
439
|
const cond = `entity${path.map(k => this.wrap(k)).join('')} != null`;
|
|
400
440
|
ret += `${padding}if (${cond}) {\n`;
|
|
401
441
|
if (object) {
|
|
@@ -440,8 +480,8 @@ export class EntityComparator {
|
|
|
440
480
|
registerCustomType(prop, context) {
|
|
441
481
|
const convertorKey = this.safeKey(prop.name);
|
|
442
482
|
context.set(`convertToDatabaseValue_${convertorKey}`, (val) => {
|
|
443
|
-
/* v8 ignore next
|
|
444
|
-
if (
|
|
483
|
+
/* v8 ignore next */
|
|
484
|
+
if (Raw.isKnownFragment(val)) {
|
|
445
485
|
return val;
|
|
446
486
|
}
|
|
447
487
|
return prop.customType.convertToDatabaseValue(val, this.platform, { mode: 'serialization' });
|
|
@@ -470,6 +510,23 @@ export class EntityComparator {
|
|
|
470
510
|
ret += ` ret${dataKey} = entity${entityKey};\n`;
|
|
471
511
|
}
|
|
472
512
|
}
|
|
513
|
+
else if (prop.targetKey) {
|
|
514
|
+
// When targetKey is set, extract that property value instead of the PK
|
|
515
|
+
const targetProp = prop.targetMeta?.properties[prop.targetKey];
|
|
516
|
+
ret += ` if (entity${entityKey} === null) {\n`;
|
|
517
|
+
ret += ` ret${dataKey} = null;\n`;
|
|
518
|
+
ret += ` } else if (typeof entity${entityKey} !== 'undefined') {\n`;
|
|
519
|
+
ret += ` const val${level} = entity${entityKey}${unwrap};\n`;
|
|
520
|
+
if (targetProp?.customType) {
|
|
521
|
+
// If targetKey property has a custom type, convert to database value
|
|
522
|
+
const convertorKey = this.registerCustomType(targetProp, context);
|
|
523
|
+
ret += ` ret${dataKey} = convertToDatabaseValue_${convertorKey}(val${level}?.${prop.targetKey});\n`;
|
|
524
|
+
}
|
|
525
|
+
else {
|
|
526
|
+
ret += ` ret${dataKey} = val${level}?.${prop.targetKey};\n`;
|
|
527
|
+
}
|
|
528
|
+
ret += ` }\n`;
|
|
529
|
+
}
|
|
473
530
|
else {
|
|
474
531
|
const toArray = (val) => {
|
|
475
532
|
if (Utils.isPlainObject(val)) {
|
|
@@ -478,8 +535,11 @@ export class EntityComparator {
|
|
|
478
535
|
return val;
|
|
479
536
|
};
|
|
480
537
|
context.set('toArray', toArray);
|
|
538
|
+
context.set('EntityIdentifier', EntityIdentifier);
|
|
481
539
|
ret += ` if (entity${entityKey} === null) {\n`;
|
|
482
540
|
ret += ` ret${dataKey} = null;\n`;
|
|
541
|
+
ret += ` } else if (entity${entityKey}?.__helper.__identifier && !entity${entityKey}.__helper.hasPrimaryKey()) {\n`;
|
|
542
|
+
ret += ` ret${dataKey} = entity${entityKey}?.__helper.__identifier;\n`;
|
|
483
543
|
ret += ` } else if (typeof entity${entityKey} !== 'undefined') {\n`;
|
|
484
544
|
ret += ` ret${dataKey} = toArray(entity${entityKey}.__helper.getPrimaryKey(true));\n`;
|
|
485
545
|
ret += ` }\n`;
|
|
@@ -503,11 +563,11 @@ export class EntityComparator {
|
|
|
503
563
|
* @internal Highly performance-sensitive method.
|
|
504
564
|
*/
|
|
505
565
|
getEntityComparator(entityName) {
|
|
506
|
-
const
|
|
566
|
+
const meta = this.metadata.find(entityName);
|
|
567
|
+
const exists = this.comparators.get(meta);
|
|
507
568
|
if (exists) {
|
|
508
569
|
return exists;
|
|
509
570
|
}
|
|
510
|
-
const meta = this.metadata.find(entityName);
|
|
511
571
|
const lines = [];
|
|
512
572
|
const context = new Map();
|
|
513
573
|
context.set('compareArrays', compareArrays);
|
|
@@ -515,17 +575,27 @@ export class EntityComparator {
|
|
|
515
575
|
context.set('compareBuffers', compareBuffers);
|
|
516
576
|
context.set('compareObjects', compareObjects);
|
|
517
577
|
context.set('equals', equals);
|
|
518
|
-
meta.comparableProps
|
|
578
|
+
for (const prop of meta.comparableProps) {
|
|
519
579
|
lines.push(this.getPropertyComparator(prop, context));
|
|
520
|
-
}
|
|
580
|
+
}
|
|
581
|
+
// also compare 1:1 inverse sides, important for `factory.mergeData`
|
|
582
|
+
lines.push(`if (options?.includeInverseSides) {`);
|
|
583
|
+
for (const prop of meta.bidirectionalRelations) {
|
|
584
|
+
if (prop.kind === ReferenceKind.ONE_TO_ONE && !prop.owner && prop.hydrate !== false) {
|
|
585
|
+
lines.push(this.getPropertyComparator(prop, context));
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
lines.push(`}`);
|
|
521
589
|
const code = `// compiled comparator for entity ${meta.className}\n`
|
|
522
|
-
+ `return function(last, current) {\n const diff = {};\n${lines.join('\n')}\n return diff;\n}`;
|
|
590
|
+
+ `return function(last, current, options) {\n const diff = {};\n${lines.join('\n')}\n return diff;\n}`;
|
|
523
591
|
const comparator = Utils.createFunction(context, code);
|
|
524
|
-
this.comparators.set(
|
|
592
|
+
this.comparators.set(meta, comparator);
|
|
525
593
|
return comparator;
|
|
526
594
|
}
|
|
527
595
|
getGenericComparator(prop, cond) {
|
|
528
|
-
return ` if (current${prop}
|
|
596
|
+
return ` if (current${prop} === null && last${prop} === undefined) {\n` +
|
|
597
|
+
` diff${prop} = current${prop};\n` +
|
|
598
|
+
` } else if (current${prop} == null && last${prop} == null) {\n\n` +
|
|
529
599
|
` } else if ((current${prop} != null && last${prop} == null) || (current${prop} == null && last${prop} != null)) {\n` +
|
|
530
600
|
` diff${prop} = current${prop};\n` +
|
|
531
601
|
` } else if (${cond}) {\n` +
|
|
@@ -535,18 +605,23 @@ export class EntityComparator {
|
|
|
535
605
|
getPropertyComparator(prop, context) {
|
|
536
606
|
let type = prop.type.toLowerCase();
|
|
537
607
|
if (prop.kind !== ReferenceKind.SCALAR && prop.kind !== ReferenceKind.EMBEDDED) {
|
|
538
|
-
const meta2 =
|
|
608
|
+
const meta2 = prop.targetMeta;
|
|
539
609
|
if (meta2.primaryKeys.length > 1) {
|
|
540
610
|
type = 'array';
|
|
541
611
|
}
|
|
542
612
|
else {
|
|
543
|
-
type = meta2.
|
|
613
|
+
type = meta2.getPrimaryProp().type.toLowerCase();
|
|
544
614
|
}
|
|
545
615
|
}
|
|
546
616
|
if (prop.customType) {
|
|
547
617
|
if (prop.customType.compareValues) {
|
|
548
618
|
const idx = this.tmpIndex++;
|
|
549
|
-
context.set(`compareValues_${idx}`, (a, b) =>
|
|
619
|
+
context.set(`compareValues_${idx}`, (a, b) => {
|
|
620
|
+
if (Raw.isKnownFragment(a) || Raw.isKnownFragment(b)) {
|
|
621
|
+
return Raw.getKnownFragment(a) === Raw.getKnownFragment(b);
|
|
622
|
+
}
|
|
623
|
+
return prop.customType.compareValues(a, b);
|
|
624
|
+
});
|
|
550
625
|
return this.getGenericComparator(this.wrap(prop.name), `!compareValues_${idx}(last${this.wrap(prop.name)}, current${this.wrap(prop.name)})`);
|
|
551
626
|
}
|
|
552
627
|
type = prop.customType.compareAsType().toLowerCase();
|
|
@@ -566,10 +641,10 @@ export class EntityComparator {
|
|
|
566
641
|
if (['buffer', 'uint8array'].includes(type)) {
|
|
567
642
|
return this.getGenericComparator(this.wrap(prop.name), `!compareBuffers(last${this.wrap(prop.name)}, current${this.wrap(prop.name)})`);
|
|
568
643
|
}
|
|
569
|
-
if (
|
|
644
|
+
if (type === 'date') {
|
|
570
645
|
return this.getGenericComparator(this.wrap(prop.name), `last${this.wrap(prop.name)}.valueOf() !== current${this.wrap(prop.name)}.valueOf()`);
|
|
571
646
|
}
|
|
572
|
-
if (
|
|
647
|
+
if (type === 'objectid') {
|
|
573
648
|
// We might be comparing PK to object, in case we compare with cached data of populated entity
|
|
574
649
|
// in such case we just ignore the comparison and fallback to `equals()` (which will still mark
|
|
575
650
|
// it as not equal as we compare PK to plain object).
|
|
@@ -591,7 +666,7 @@ export class EntityComparator {
|
|
|
591
666
|
* perf: used to generate list of comparable properties during discovery, so we speed up the runtime comparison
|
|
592
667
|
*/
|
|
593
668
|
static isComparable(prop, root) {
|
|
594
|
-
const virtual = prop.persist === false || prop.generated;
|
|
669
|
+
const virtual = prop.persist === false || (prop.generated && !prop.primary);
|
|
595
670
|
const inverse = prop.kind === ReferenceKind.ONE_TO_ONE && !prop.owner;
|
|
596
671
|
const discriminator = prop.name === root.discriminatorColumn;
|
|
597
672
|
const collection = prop.kind === ReferenceKind.ONE_TO_MANY || prop.kind === ReferenceKind.MANY_TO_MANY;
|
package/utils/QueryHelper.d.ts
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
import type { Dictionary, EntityMetadata, EntityProperty, FilterDef, FilterQuery } from '../typings.js';
|
|
1
|
+
import type { Dictionary, EntityMetadata, EntityName, EntityProperty, FilterDef, FilterQuery } from '../typings.js';
|
|
2
2
|
import type { Platform } from '../platforms/Platform.js';
|
|
3
3
|
import type { MetadataStorage } from '../metadata/MetadataStorage.js';
|
|
4
|
+
import type { FilterOptions } from '../drivers/IDatabaseDriver.js';
|
|
5
|
+
/** @internal */
|
|
4
6
|
export declare class QueryHelper {
|
|
5
7
|
static readonly SUPPORTED_OPERATORS: string[];
|
|
6
8
|
static processParams(params: unknown): any;
|
|
7
|
-
static processObjectParams<T extends
|
|
9
|
+
static processObjectParams<T extends Dictionary>(params?: T): T;
|
|
10
|
+
/**
|
|
11
|
+
* converts `{ account: { $or: [ [Object], [Object] ] } }`
|
|
12
|
+
* to `{ $or: [ { account: [Object] }, { account: [Object] } ] }`
|
|
13
|
+
*/
|
|
14
|
+
static liftGroupOperators<T extends object>(where: Dictionary, meta: EntityMetadata<T>, metadata: MetadataStorage, key?: string): string | undefined;
|
|
8
15
|
static inlinePrimaryKeyObjects<T extends object>(where: Dictionary, meta: EntityMetadata<T>, metadata: MetadataStorage, key?: string): boolean;
|
|
9
16
|
static processWhere<T extends object>(options: ProcessWhereOptions<T>): FilterQuery<T>;
|
|
10
|
-
static getActiveFilters(
|
|
11
|
-
static
|
|
17
|
+
static getActiveFilters<T>(meta: EntityMetadata<T>, options: FilterOptions | undefined, filters: Dictionary<FilterDef>): FilterDef[];
|
|
18
|
+
static mergePropertyFilters(propFilters: FilterOptions | undefined, options: FilterOptions | undefined): FilterOptions | undefined;
|
|
19
|
+
static isFilterActive<T>(meta: EntityMetadata<T>, filterName: string, filter: FilterDef, options: Dictionary<boolean | Dictionary>): boolean;
|
|
12
20
|
static processCustomType<T extends object>(prop: EntityProperty<T>, cond: FilterQuery<T>, platform: Platform, key?: string, fromQuery?: boolean): FilterQuery<T>;
|
|
13
21
|
private static isSupportedOperator;
|
|
14
22
|
private static processJsonCondition;
|
|
@@ -17,11 +25,11 @@ export declare class QueryHelper {
|
|
|
17
25
|
}
|
|
18
26
|
interface ProcessWhereOptions<T> {
|
|
19
27
|
where: FilterQuery<T>;
|
|
20
|
-
entityName:
|
|
28
|
+
entityName: EntityName<T>;
|
|
21
29
|
metadata: MetadataStorage;
|
|
22
30
|
platform: Platform;
|
|
23
31
|
aliased?: boolean;
|
|
24
|
-
aliasMap?: Dictionary<
|
|
32
|
+
aliasMap?: Dictionary<EntityName>;
|
|
25
33
|
convertCustomTypes?: boolean;
|
|
26
34
|
root?: boolean;
|
|
27
35
|
type?: 'where' | 'orderBy';
|