@mikro-orm/core 7.0.0-dev.31 → 7.0.0-dev.311
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 +69 -61
- package/EntityManager.js +365 -283
- package/MikroORM.d.ts +44 -35
- package/MikroORM.js +109 -142
- package/README.md +5 -3
- 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 -16
- package/drivers/DatabaseDriver.js +144 -43
- 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 +262 -98
- 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 +7 -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 +866 -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 +11 -15
- package/platforms/Platform.js +72 -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/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 +106 -43
- 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 +795 -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 -6
- package/utils/QueryHelper.js +181 -48
- 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 +8 -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
package/platforms/Platform.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { inspect } from 'node:util';
|
|
2
1
|
import { clone } from '../utils/clone.js';
|
|
3
2
|
import { EntityRepository } from '../entity/EntityRepository.js';
|
|
4
3
|
import { UnderscoreNamingStrategy } from '../naming-strategy/UnderscoreNamingStrategy.js';
|
|
5
4
|
import { ExceptionConverter } from './ExceptionConverter.js';
|
|
6
|
-
import { ArrayType, BigIntType, BlobType,
|
|
7
|
-
import { parseJsonSafe
|
|
5
|
+
import { ArrayType, BigIntType, BlobType, BooleanType, CharacterType, DateTimeType, DateType, DecimalType, DoubleType, EnumType, FloatType, IntegerType, IntervalType, JsonType, MediumIntType, SmallIntType, StringType, TextType, TimeType, TinyIntType, Type, Uint8ArrayType, UnknownType, UuidType, } from '../types/index.js';
|
|
6
|
+
import { parseJsonSafe } from '../utils/Utils.js';
|
|
8
7
|
import { ReferenceKind } from '../enums.js';
|
|
9
|
-
import {
|
|
8
|
+
import { Raw } from '../utils/RawQueryFragment.js';
|
|
10
9
|
export const JsonProperty = Symbol('JsonProperty');
|
|
11
10
|
export class Platform {
|
|
12
11
|
exceptionConverter = new ExceptionConverter();
|
|
@@ -42,15 +41,15 @@ export class Platform {
|
|
|
42
41
|
usesEnumCheckConstraints() {
|
|
43
42
|
return false;
|
|
44
43
|
}
|
|
44
|
+
supportsMaterializedViews() {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
45
47
|
getSchemaHelper() {
|
|
46
48
|
return undefined;
|
|
47
49
|
}
|
|
48
50
|
indexForeignKeys() {
|
|
49
51
|
return false;
|
|
50
52
|
}
|
|
51
|
-
allowsMultiInsert() {
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
53
|
/**
|
|
55
54
|
* Whether or not the driver supports retuning list of created PKs back when multi-inserting
|
|
56
55
|
*/
|
|
@@ -78,15 +77,6 @@ export class Platform {
|
|
|
78
77
|
denormalizePrimaryKey(data) {
|
|
79
78
|
return data;
|
|
80
79
|
}
|
|
81
|
-
/**
|
|
82
|
-
* Used when serializing via toObject and toJSON methods, allows to use different PK field name (like `id` instead of `_id`)
|
|
83
|
-
*/
|
|
84
|
-
getSerializedPrimaryKeyField(field) {
|
|
85
|
-
return field;
|
|
86
|
-
}
|
|
87
|
-
usesDifferentSerializedPrimaryKey() {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
80
|
/**
|
|
91
81
|
* Returns the SQL specific for the platform to get the current timestamp
|
|
92
82
|
*/
|
|
@@ -123,7 +113,7 @@ export class Platform {
|
|
|
123
113
|
isAllowedTopLevelOperator(operator) {
|
|
124
114
|
return operator === '$not';
|
|
125
115
|
}
|
|
126
|
-
|
|
116
|
+
convertVersionValue(value, prop) {
|
|
127
117
|
return value;
|
|
128
118
|
}
|
|
129
119
|
getDefaultVersionLength() {
|
|
@@ -133,7 +123,7 @@ export class Platform {
|
|
|
133
123
|
return true;
|
|
134
124
|
}
|
|
135
125
|
isBigIntProperty(prop) {
|
|
136
|
-
return prop.columnTypes
|
|
126
|
+
return prop.columnTypes?.[0] === 'bigint';
|
|
137
127
|
}
|
|
138
128
|
getDefaultSchemaName() {
|
|
139
129
|
return undefined;
|
|
@@ -169,7 +159,7 @@ export class Platform {
|
|
|
169
159
|
return `text`;
|
|
170
160
|
}
|
|
171
161
|
getEnumTypeDeclarationSQL(column) {
|
|
172
|
-
if (column.items?.every(item =>
|
|
162
|
+
if (column.items?.every(item => typeof item === 'string')) {
|
|
173
163
|
return `enum('${column.items.join("','")}')`;
|
|
174
164
|
}
|
|
175
165
|
return this.getTinyIntTypeDeclarationSQL(column);
|
|
@@ -190,7 +180,7 @@ export class Platform {
|
|
|
190
180
|
return this.getVarcharTypeDeclarationSQL(column);
|
|
191
181
|
}
|
|
192
182
|
extractSimpleType(type) {
|
|
193
|
-
return
|
|
183
|
+
return /[^(), ]+/.exec(type.toLowerCase())[0];
|
|
194
184
|
}
|
|
195
185
|
/**
|
|
196
186
|
* This should be used only to compare types, it can strip some information like the length.
|
|
@@ -208,35 +198,58 @@ export class Platform {
|
|
|
208
198
|
}
|
|
209
199
|
switch (this.extractSimpleType(type)) {
|
|
210
200
|
case 'character':
|
|
211
|
-
case 'char':
|
|
201
|
+
case 'char':
|
|
202
|
+
return Type.getType(CharacterType);
|
|
212
203
|
case 'string':
|
|
213
|
-
case 'varchar':
|
|
214
|
-
|
|
215
|
-
case '
|
|
204
|
+
case 'varchar':
|
|
205
|
+
return Type.getType(StringType);
|
|
206
|
+
case 'interval':
|
|
207
|
+
return Type.getType(IntervalType);
|
|
208
|
+
case 'text':
|
|
209
|
+
return Type.getType(TextType);
|
|
216
210
|
case 'int':
|
|
217
|
-
case 'number':
|
|
218
|
-
|
|
219
|
-
case '
|
|
220
|
-
|
|
221
|
-
case '
|
|
222
|
-
|
|
223
|
-
case '
|
|
224
|
-
|
|
211
|
+
case 'number':
|
|
212
|
+
return Type.getType(IntegerType);
|
|
213
|
+
case 'bigint':
|
|
214
|
+
return Type.getType(BigIntType);
|
|
215
|
+
case 'smallint':
|
|
216
|
+
return Type.getType(SmallIntType);
|
|
217
|
+
case 'tinyint':
|
|
218
|
+
return Type.getType(TinyIntType);
|
|
219
|
+
case 'mediumint':
|
|
220
|
+
return Type.getType(MediumIntType);
|
|
221
|
+
case 'float':
|
|
222
|
+
return Type.getType(FloatType);
|
|
223
|
+
case 'double':
|
|
224
|
+
return Type.getType(DoubleType);
|
|
225
|
+
case 'integer':
|
|
226
|
+
return Type.getType(IntegerType);
|
|
225
227
|
case 'decimal':
|
|
226
|
-
case 'numeric':
|
|
227
|
-
|
|
228
|
+
case 'numeric':
|
|
229
|
+
return Type.getType(DecimalType);
|
|
230
|
+
case 'boolean':
|
|
231
|
+
return Type.getType(BooleanType);
|
|
228
232
|
case 'blob':
|
|
229
|
-
case 'buffer':
|
|
230
|
-
|
|
231
|
-
case '
|
|
232
|
-
|
|
233
|
+
case 'buffer':
|
|
234
|
+
return Type.getType(BlobType);
|
|
235
|
+
case 'uint8array':
|
|
236
|
+
return Type.getType(Uint8ArrayType);
|
|
237
|
+
case 'uuid':
|
|
238
|
+
return Type.getType(UuidType);
|
|
239
|
+
case 'date':
|
|
240
|
+
return Type.getType(DateType);
|
|
233
241
|
case 'datetime':
|
|
234
|
-
case 'timestamp':
|
|
235
|
-
|
|
242
|
+
case 'timestamp':
|
|
243
|
+
return Type.getType(DateTimeType);
|
|
244
|
+
case 'time':
|
|
245
|
+
return Type.getType(TimeType);
|
|
236
246
|
case 'object':
|
|
237
|
-
case 'json':
|
|
238
|
-
|
|
239
|
-
|
|
247
|
+
case 'json':
|
|
248
|
+
return Type.getType(JsonType);
|
|
249
|
+
case 'enum':
|
|
250
|
+
return Type.getType(EnumType);
|
|
251
|
+
default:
|
|
252
|
+
return Type.getType(UnknownType);
|
|
240
253
|
}
|
|
241
254
|
}
|
|
242
255
|
supportsMultipleCascadePaths() {
|
|
@@ -245,6 +258,9 @@ export class Platform {
|
|
|
245
258
|
supportsMultipleStatements() {
|
|
246
259
|
return this.config.get('multipleStatements');
|
|
247
260
|
}
|
|
261
|
+
supportsUnionWhere() {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
248
264
|
getArrayDeclarationSQL() {
|
|
249
265
|
return 'text';
|
|
250
266
|
}
|
|
@@ -269,7 +285,7 @@ export class Platform {
|
|
|
269
285
|
getSearchJsonPropertyKey(path, type, aliased, value) {
|
|
270
286
|
return path.join('.');
|
|
271
287
|
}
|
|
272
|
-
/* v8 ignore next
|
|
288
|
+
/* v8 ignore next */
|
|
273
289
|
getJsonIndexDefinition(index) {
|
|
274
290
|
return index.columnNames;
|
|
275
291
|
}
|
|
@@ -288,11 +304,7 @@ export class Platform {
|
|
|
288
304
|
convertJsonToDatabaseValue(value, context) {
|
|
289
305
|
return JSON.stringify(value);
|
|
290
306
|
}
|
|
291
|
-
convertJsonToJSValue(value,
|
|
292
|
-
const isObjectEmbedded = prop.embedded && prop.object;
|
|
293
|
-
if ((this.convertsJsonAutomatically() || isObjectEmbedded) && ['json', 'jsonb', this.getJsonDeclarationSQL()].includes(prop.columnTypes[0])) {
|
|
294
|
-
return value;
|
|
295
|
-
}
|
|
307
|
+
convertJsonToJSValue(value, context) {
|
|
296
308
|
return parseJsonSafe(value);
|
|
297
309
|
}
|
|
298
310
|
convertDateToJSValue(value) {
|
|
@@ -306,7 +318,7 @@ export class Platform {
|
|
|
306
318
|
}
|
|
307
319
|
parseDate(value) {
|
|
308
320
|
const date = new Date(value);
|
|
309
|
-
/* v8 ignore next
|
|
321
|
+
/* v8 ignore next */
|
|
310
322
|
if (isNaN(date.getTime())) {
|
|
311
323
|
return value;
|
|
312
324
|
}
|
|
@@ -336,19 +348,10 @@ export class Platform {
|
|
|
336
348
|
if (extension) {
|
|
337
349
|
return extension;
|
|
338
350
|
}
|
|
339
|
-
/* v8 ignore next
|
|
340
|
-
|
|
341
|
-
module: moduleName,
|
|
342
|
-
warning: `Please install ${moduleName} package.`,
|
|
343
|
-
});
|
|
344
|
-
/* v8 ignore next 3 */
|
|
345
|
-
if (module) {
|
|
346
|
-
return this.config.getCachedService(module[extensionName], em);
|
|
347
|
-
}
|
|
348
|
-
/* v8 ignore next 2 */
|
|
349
|
-
throw new Error(`${extensionName} extension not registered.`);
|
|
351
|
+
/* v8 ignore next */
|
|
352
|
+
throw new Error(`${extensionName} extension not registered. Provide it in the ORM config, or use the async \`MikroORM.init()\` method to load extensions automatically.`);
|
|
350
353
|
}
|
|
351
|
-
/* v8 ignore next
|
|
354
|
+
/* v8 ignore next: kept for type inference only */
|
|
352
355
|
getSchemaGenerator(driver, em) {
|
|
353
356
|
throw new Error(`${driver.constructor.name} does not support SchemaGenerator`);
|
|
354
357
|
}
|
|
@@ -356,7 +359,7 @@ export class Platform {
|
|
|
356
359
|
return value;
|
|
357
360
|
}
|
|
358
361
|
quoteIdentifier(id, quote = '`') {
|
|
359
|
-
const raw =
|
|
362
|
+
const raw = Raw.getKnownFragment(id);
|
|
360
363
|
if (raw) {
|
|
361
364
|
return this.formatQuery(raw.sql, raw.params);
|
|
362
365
|
}
|
|
@@ -365,7 +368,7 @@ export class Platform {
|
|
|
365
368
|
quoteValue(value) {
|
|
366
369
|
return value;
|
|
367
370
|
}
|
|
368
|
-
/* v8 ignore next
|
|
371
|
+
/* v8 ignore next */
|
|
369
372
|
escape(value) {
|
|
370
373
|
return value;
|
|
371
374
|
}
|
|
@@ -377,7 +380,7 @@ export class Platform {
|
|
|
377
380
|
let j = 0;
|
|
378
381
|
let pos = 0;
|
|
379
382
|
let ret = '';
|
|
380
|
-
if (sql
|
|
383
|
+
if (sql.startsWith('?')) {
|
|
381
384
|
if (sql[1] === '?') {
|
|
382
385
|
ret += this.quoteIdentifier(params[j++]);
|
|
383
386
|
pos = 2;
|
|
@@ -455,7 +458,7 @@ export class Platform {
|
|
|
455
458
|
isPopulated(key, populate) {
|
|
456
459
|
return populate === true || (populate !== false && populate.some(p => p.field === key || p.all));
|
|
457
460
|
}
|
|
458
|
-
shouldHaveColumn(prop, populate, exclude, includeFormulas = true) {
|
|
461
|
+
shouldHaveColumn(prop, populate, exclude, includeFormulas = true, ignoreInlineEmbeddables = true) {
|
|
459
462
|
if (exclude?.includes(prop.name)) {
|
|
460
463
|
return false;
|
|
461
464
|
}
|
|
@@ -475,7 +478,7 @@ export class Platform {
|
|
|
475
478
|
return true;
|
|
476
479
|
}
|
|
477
480
|
if (prop.kind === ReferenceKind.EMBEDDED) {
|
|
478
|
-
return
|
|
481
|
+
return prop.object || ignoreInlineEmbeddables;
|
|
479
482
|
}
|
|
480
483
|
return prop.kind === ReferenceKind.ONE_TO_ONE && prop.owner;
|
|
481
484
|
}
|
|
@@ -522,9 +525,9 @@ export class Platform {
|
|
|
522
525
|
clone() {
|
|
523
526
|
return this;
|
|
524
527
|
}
|
|
525
|
-
/* v8 ignore next 4 */
|
|
526
528
|
/** @ignore */
|
|
527
|
-
|
|
529
|
+
/* v8 ignore next */
|
|
530
|
+
[Symbol.for('nodejs.util.inspect.custom')]() {
|
|
528
531
|
return `[${this.constructor.name}]`;
|
|
529
532
|
}
|
|
530
533
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { ArrayElement, AutoPath, CleanTypeConfig,
|
|
1
|
+
import type { ArrayElement, AutoPath, CleanTypeConfig, SerializeDTO, FromEntityType, TypeConfig, UnboxArray } from '../typings.js';
|
|
2
2
|
import { type PopulatePath } from '../enums.js';
|
|
3
3
|
export declare class EntitySerializer {
|
|
4
|
-
static serialize<T extends object, P extends string = never, E extends string = never>(entity: T, options?: SerializeOptions<T, P, E>):
|
|
4
|
+
static serialize<T extends object, P extends string = never, E extends string = never>(entity: T, options?: SerializeOptions<T, P, E>): SerializeDTO<T, P, E>;
|
|
5
5
|
private static propertyName;
|
|
6
6
|
private static processProperty;
|
|
7
|
+
private static processCustomType;
|
|
7
8
|
private static extractChildOptions;
|
|
8
9
|
private static processEntity;
|
|
9
10
|
private static processCollection;
|
|
@@ -23,6 +24,8 @@ export interface SerializeOptions<T, P extends string = never, E extends string
|
|
|
23
24
|
skipNull?: boolean;
|
|
24
25
|
/** Only include properties for a specific group. If a property does not specify any group, it will be included, otherwise only properties with a matching group are included. */
|
|
25
26
|
groups?: string[];
|
|
27
|
+
/** Convert custom types to their database representation. By default, the `Type.toJSON` method is invoked instead. */
|
|
28
|
+
convertCustomTypes?: boolean;
|
|
26
29
|
}
|
|
27
30
|
/**
|
|
28
31
|
* Converts entity instance to POJO, converting the `Collection`s to arrays and unwrapping the `Reference` wrapper, while respecting the serialization options.
|
|
@@ -36,4 +39,4 @@ export interface SerializeOptions<T, P extends string = never, E extends string
|
|
|
36
39
|
* const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true });
|
|
37
40
|
* ```
|
|
38
41
|
*/
|
|
39
|
-
export declare function serialize<Entity extends object, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Populate extends string = never, Exclude extends string = never, Config extends TypeConfig = never>(entity: Entity, options?: Config & SerializeOptions<UnboxArray<Entity>, Populate, Exclude>): Naked extends object[] ?
|
|
42
|
+
export declare function serialize<Entity extends object, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Populate extends string = never, Exclude extends string = never, Config extends TypeConfig = never>(entity: Entity, options?: Config & SerializeOptions<UnboxArray<Entity>, Populate, Exclude>): Naked extends object[] ? SerializeDTO<ArrayElement<Naked>, Populate, Exclude, CleanTypeConfig<Config>>[] : SerializeDTO<Naked, Populate, Exclude, CleanTypeConfig<Config>>;
|
|
@@ -9,18 +9,20 @@ function isVisible(meta, propName, options) {
|
|
|
9
9
|
if (options.groups && prop?.groups) {
|
|
10
10
|
return prop.groups.some(g => options.groups.includes(g));
|
|
11
11
|
}
|
|
12
|
-
if (Array.isArray(options.populate) &&
|
|
12
|
+
if (Array.isArray(options.populate) &&
|
|
13
|
+
options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
|
|
13
14
|
return true;
|
|
14
15
|
}
|
|
15
16
|
if (options.exclude?.find(item => item === propName)) {
|
|
16
17
|
return false;
|
|
17
18
|
}
|
|
18
19
|
const visible = prop && !(prop.hidden && !options.includeHidden);
|
|
19
|
-
const prefixed = prop && !prop.primary && propName.startsWith('_'); // ignore prefixed properties, if it's not a PK
|
|
20
|
+
const prefixed = prop && !prop.primary && !prop.accessor && propName.startsWith('_'); // ignore prefixed properties, if it's not a PK
|
|
20
21
|
return visible && !prefixed;
|
|
21
22
|
}
|
|
22
23
|
function isPopulated(propName, options) {
|
|
23
|
-
if (typeof options.populate !== 'boolean' &&
|
|
24
|
+
if (typeof options.populate !== 'boolean' &&
|
|
25
|
+
options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
|
|
24
26
|
return true;
|
|
25
27
|
}
|
|
26
28
|
if (typeof options.populate === 'boolean') {
|
|
@@ -41,23 +43,41 @@ export class EntitySerializer {
|
|
|
41
43
|
}
|
|
42
44
|
const root = wrapped.__serializationContext.root;
|
|
43
45
|
const ret = {};
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
+
const props = new Set();
|
|
47
|
+
if (meta.serializedPrimaryKey && !meta.compositePK) {
|
|
48
|
+
props.add(meta.serializedPrimaryKey);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
meta.primaryKeys.forEach(pk => props.add(pk));
|
|
52
|
+
}
|
|
53
|
+
if (wrapped.isInitialized() || !wrapped.hasPrimaryKey()) {
|
|
54
|
+
const entityKeys = new Set(Object.keys(entity));
|
|
55
|
+
for (const prop of meta.props) {
|
|
56
|
+
if (entityKeys.has(prop.name) || (prop.getter && prop.accessor === prop.name)) {
|
|
57
|
+
props.add(prop.name);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
for (const key of entityKeys) {
|
|
61
|
+
if (!meta.properties[key]) {
|
|
62
|
+
props.add(key);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
46
66
|
const visited = root.visited.has(entity);
|
|
47
67
|
if (!visited) {
|
|
48
68
|
root.visited.add(entity);
|
|
49
69
|
}
|
|
50
|
-
for (const prop of
|
|
70
|
+
for (const prop of props) {
|
|
51
71
|
if (!isVisible(meta, prop, options)) {
|
|
52
72
|
continue;
|
|
53
73
|
}
|
|
54
|
-
const cycle = root.visit(meta.
|
|
74
|
+
const cycle = root.visit(meta.class, prop);
|
|
55
75
|
if (cycle && visited) {
|
|
56
76
|
continue;
|
|
57
77
|
}
|
|
58
78
|
const val = this.processProperty(prop, entity, options);
|
|
59
79
|
if (!cycle) {
|
|
60
|
-
root.leave(meta.
|
|
80
|
+
root.leave(meta.class, prop);
|
|
61
81
|
}
|
|
62
82
|
if (options.skipNull && Utils.isPlainObject(val)) {
|
|
63
83
|
Utils.dropUndefinedProperties(val, null);
|
|
@@ -67,7 +87,7 @@ export class EntitySerializer {
|
|
|
67
87
|
}
|
|
68
88
|
const visible = typeof val !== 'undefined' && !(val === null && options.skipNull);
|
|
69
89
|
if (visible) {
|
|
70
|
-
ret[this.propertyName(meta, prop
|
|
90
|
+
ret[this.propertyName(meta, prop)] = val;
|
|
71
91
|
}
|
|
72
92
|
}
|
|
73
93
|
if (contextCreated) {
|
|
@@ -81,26 +101,26 @@ export class EntitySerializer {
|
|
|
81
101
|
if (prop.getterName != null) {
|
|
82
102
|
const visible = entity[prop.getterName] instanceof Function && isVisible(meta, prop.name, options);
|
|
83
103
|
if (visible) {
|
|
84
|
-
ret[this.propertyName(meta, prop.name
|
|
104
|
+
ret[this.propertyName(meta, prop.name)] = this.processProperty(prop.getterName, entity, options);
|
|
85
105
|
}
|
|
86
106
|
}
|
|
87
107
|
else {
|
|
88
108
|
// decorated getters
|
|
89
109
|
const visible = typeof entity[prop.name] !== 'undefined' && isVisible(meta, prop.name, options);
|
|
90
110
|
if (visible) {
|
|
91
|
-
ret[this.propertyName(meta, prop.name
|
|
111
|
+
ret[this.propertyName(meta, prop.name)] = this.processProperty(prop.name, entity, options);
|
|
92
112
|
}
|
|
93
113
|
}
|
|
94
114
|
}
|
|
95
115
|
return ret;
|
|
96
116
|
}
|
|
97
|
-
static propertyName(meta, prop
|
|
98
|
-
/* v8 ignore next
|
|
117
|
+
static propertyName(meta, prop) {
|
|
118
|
+
/* v8 ignore next */
|
|
99
119
|
if (meta.properties[prop]?.serializedName) {
|
|
100
120
|
return meta.properties[prop].serializedName;
|
|
101
121
|
}
|
|
102
|
-
if (meta.properties[prop]?.primary &&
|
|
103
|
-
return
|
|
122
|
+
if (meta.properties[prop]?.primary && meta.serializedPrimaryKey) {
|
|
123
|
+
return meta.serializedPrimaryKey;
|
|
104
124
|
}
|
|
105
125
|
return prop;
|
|
106
126
|
}
|
|
@@ -119,7 +139,7 @@ export class EntitySerializer {
|
|
|
119
139
|
}
|
|
120
140
|
return returnValue;
|
|
121
141
|
}
|
|
122
|
-
/* v8 ignore next
|
|
142
|
+
/* v8 ignore next */
|
|
123
143
|
if (!options.ignoreSerializers && serializer) {
|
|
124
144
|
return serializer(value);
|
|
125
145
|
}
|
|
@@ -132,7 +152,7 @@ export class EntitySerializer {
|
|
|
132
152
|
if (Utils.isScalarReference(value)) {
|
|
133
153
|
return value.unwrap();
|
|
134
154
|
}
|
|
135
|
-
/* v8 ignore next
|
|
155
|
+
/* v8 ignore next */
|
|
136
156
|
if (property?.kind === ReferenceKind.EMBEDDED) {
|
|
137
157
|
if (Array.isArray(value)) {
|
|
138
158
|
return value.map(item => helper(item).toJSON());
|
|
@@ -141,16 +161,26 @@ export class EntitySerializer {
|
|
|
141
161
|
return helper(value).toJSON();
|
|
142
162
|
}
|
|
143
163
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return customType.toJSON(value, wrapped.__platform);
|
|
164
|
+
if (property.customType) {
|
|
165
|
+
return this.processCustomType(value, property, wrapped.__platform, options.convertCustomTypes);
|
|
147
166
|
}
|
|
148
167
|
return wrapped.__platform.normalizePrimaryKey(value);
|
|
149
168
|
}
|
|
169
|
+
static processCustomType(value, prop, platform, convertCustomTypes) {
|
|
170
|
+
if (!prop.customType) {
|
|
171
|
+
return value;
|
|
172
|
+
}
|
|
173
|
+
if (convertCustomTypes) {
|
|
174
|
+
return prop.customType.convertToDatabaseValue(value, platform, { mode: 'serialization' });
|
|
175
|
+
}
|
|
176
|
+
return prop.customType.toJSON(value, platform);
|
|
177
|
+
}
|
|
150
178
|
static extractChildOptions(options, prop) {
|
|
151
179
|
return {
|
|
152
180
|
...options,
|
|
153
|
-
populate: Array.isArray(options.populate)
|
|
181
|
+
populate: Array.isArray(options.populate)
|
|
182
|
+
? Utils.extractChildElements(options.populate, prop, '*')
|
|
183
|
+
: options.populate,
|
|
154
184
|
exclude: Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop) : options.exclude,
|
|
155
185
|
};
|
|
156
186
|
}
|
|
@@ -165,10 +195,7 @@ export class EntitySerializer {
|
|
|
165
195
|
if (expand) {
|
|
166
196
|
return this.serialize(child, childOptions);
|
|
167
197
|
}
|
|
168
|
-
|
|
169
|
-
if (prop.customType) {
|
|
170
|
-
pk = prop.customType.toJSON(pk, wrapped.__platform);
|
|
171
|
-
}
|
|
198
|
+
const pk = this.processCustomType(wrapped.getPrimaryKey(), prop, wrapped.__platform, options.convertCustomTypes);
|
|
172
199
|
if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
|
|
173
200
|
return Utils.primaryKeyToObject(meta, pk, visible);
|
|
174
201
|
}
|
|
@@ -192,10 +219,7 @@ export class EntitySerializer {
|
|
|
192
219
|
if (populated || !wrapped.__managed) {
|
|
193
220
|
return this.serialize(item, this.extractChildOptions(options, prop.name));
|
|
194
221
|
}
|
|
195
|
-
|
|
196
|
-
if (prop.customType) {
|
|
197
|
-
pk = prop.customType.toJSON(pk, wrapped.__platform);
|
|
198
|
-
}
|
|
222
|
+
const pk = this.processCustomType(wrapped.getPrimaryKey(), prop, wrapped.__platform, options.convertCustomTypes);
|
|
199
223
|
if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
|
|
200
224
|
return Utils.primaryKeyToObject(wrapped.__meta, pk);
|
|
201
225
|
}
|
|
@@ -6,7 +6,7 @@ import { isRaw } from '../utils/RawQueryFragment.js';
|
|
|
6
6
|
function isVisible(meta, propName, ignoreFields = []) {
|
|
7
7
|
const prop = meta.properties[propName];
|
|
8
8
|
const visible = prop && !prop.hidden;
|
|
9
|
-
const prefixed = prop && !prop.primary && propName.startsWith('_'); // ignore prefixed properties, if it's not a PK
|
|
9
|
+
const prefixed = prop && !prop.primary && !prop.accessor && propName.startsWith('_'); // ignore prefixed properties, if it's not a PK
|
|
10
10
|
return visible && !prefixed && !ignoreFields.includes(propName);
|
|
11
11
|
}
|
|
12
12
|
export class EntityTransformer {
|
|
@@ -27,39 +27,51 @@ export class EntityTransformer {
|
|
|
27
27
|
const root = wrapped.__serializationContext.root;
|
|
28
28
|
const meta = wrapped.__meta;
|
|
29
29
|
const ret = {};
|
|
30
|
-
const
|
|
30
|
+
const props = new Set();
|
|
31
31
|
if (meta.serializedPrimaryKey && !meta.compositePK) {
|
|
32
|
-
|
|
32
|
+
props.add(meta.serializedPrimaryKey);
|
|
33
33
|
}
|
|
34
34
|
else {
|
|
35
|
-
meta.primaryKeys.forEach(pk =>
|
|
35
|
+
meta.primaryKeys.forEach(pk => props.add(pk));
|
|
36
36
|
}
|
|
37
37
|
if (wrapped.isInitialized() || !wrapped.hasPrimaryKey()) {
|
|
38
|
-
|
|
38
|
+
const entityKeys = new Set(Object.keys(entity));
|
|
39
|
+
for (const prop of meta.props) {
|
|
40
|
+
if (entityKeys.has(prop.name) || (prop.getter && prop.accessor === prop.name)) {
|
|
41
|
+
props.add(prop.name);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
for (const key of entityKeys) {
|
|
45
|
+
if (!meta.properties[key]) {
|
|
46
|
+
props.add(key);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
39
49
|
}
|
|
40
50
|
const visited = root.visited.has(entity);
|
|
41
51
|
const includePrimaryKeys = wrapped.__config.get('serialization').includePrimaryKeys;
|
|
42
52
|
if (!visited) {
|
|
43
53
|
root.visited.add(entity);
|
|
44
54
|
}
|
|
45
|
-
for (const prop of
|
|
55
|
+
for (const prop of props) {
|
|
46
56
|
const visible = raw ? meta.properties[prop] : isVisible(meta, prop, ignoreFields);
|
|
47
57
|
if (!visible) {
|
|
48
58
|
continue;
|
|
49
59
|
}
|
|
50
|
-
const populated = root.isMarkedAsPopulated(meta.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
const populated = root.isMarkedAsPopulated(meta.class, prop);
|
|
61
|
+
if (!raw) {
|
|
62
|
+
const partiallyLoaded = root.isPartiallyLoaded(meta.class, prop);
|
|
63
|
+
const isPrimary = includePrimaryKeys && meta.properties[prop].primary;
|
|
64
|
+
if (!partiallyLoaded && !populated && !isPrimary) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
55
67
|
}
|
|
56
|
-
const cycle = root.visit(meta.
|
|
68
|
+
const cycle = root.visit(meta.class, prop);
|
|
57
69
|
if (cycle && visited) {
|
|
58
70
|
continue;
|
|
59
71
|
}
|
|
60
72
|
const val = EntityTransformer.processProperty(prop, entity, raw, populated);
|
|
61
73
|
if (!cycle) {
|
|
62
|
-
root.leave(meta.
|
|
74
|
+
root.leave(meta.class, prop);
|
|
63
75
|
}
|
|
64
76
|
if (isRaw(val)) {
|
|
65
77
|
throw new Error(`Trying to serialize raw SQL fragment: '${val.sql}'`);
|
|
@@ -67,7 +79,7 @@ export class EntityTransformer {
|
|
|
67
79
|
if (typeof val === 'undefined') {
|
|
68
80
|
continue;
|
|
69
81
|
}
|
|
70
|
-
ret[this.propertyName(meta, prop,
|
|
82
|
+
ret[this.propertyName(meta, prop, raw)] = val;
|
|
71
83
|
}
|
|
72
84
|
if (!wrapped.isInitialized() && wrapped.hasPrimaryKey()) {
|
|
73
85
|
return ret;
|
|
@@ -76,17 +88,17 @@ export class EntityTransformer {
|
|
|
76
88
|
// decorated get methods
|
|
77
89
|
if (prop.getterName != null) {
|
|
78
90
|
const visible = !prop.hidden && entity[prop.getterName] instanceof Function;
|
|
79
|
-
const populated = root.isMarkedAsPopulated(meta.
|
|
91
|
+
const populated = root.isMarkedAsPopulated(meta.class, prop.name);
|
|
80
92
|
if (visible) {
|
|
81
|
-
ret[this.propertyName(meta, prop.name,
|
|
93
|
+
ret[this.propertyName(meta, prop.name, raw)] = this.processProperty(prop.getterName, entity, raw, populated);
|
|
82
94
|
}
|
|
83
95
|
}
|
|
84
96
|
else {
|
|
85
97
|
// decorated getters
|
|
86
98
|
const visible = !prop.hidden && typeof entity[prop.name] !== 'undefined';
|
|
87
|
-
const populated = root.isMarkedAsPopulated(meta.
|
|
99
|
+
const populated = root.isMarkedAsPopulated(meta.class, prop.name);
|
|
88
100
|
if (visible) {
|
|
89
|
-
ret[this.propertyName(meta, prop.name,
|
|
101
|
+
ret[this.propertyName(meta, prop.name, raw)] = this.processProperty(prop.name, entity, raw, populated);
|
|
90
102
|
}
|
|
91
103
|
}
|
|
92
104
|
}
|
|
@@ -95,15 +107,15 @@ export class EntityTransformer {
|
|
|
95
107
|
}
|
|
96
108
|
return ret;
|
|
97
109
|
}
|
|
98
|
-
static propertyName(meta, prop,
|
|
110
|
+
static propertyName(meta, prop, raw) {
|
|
99
111
|
if (raw) {
|
|
100
112
|
return prop;
|
|
101
113
|
}
|
|
102
114
|
if (meta.properties[prop].serializedName) {
|
|
103
115
|
return meta.properties[prop].serializedName;
|
|
104
116
|
}
|
|
105
|
-
if (meta.properties[prop].primary &&
|
|
106
|
-
return
|
|
117
|
+
if (meta.properties[prop].primary && meta.serializedPrimaryKey) {
|
|
118
|
+
return meta.serializedPrimaryKey;
|
|
107
119
|
}
|
|
108
120
|
return prop;
|
|
109
121
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyEntity, EntityMetadata, PopulateOptions } from '../typings.js';
|
|
1
|
+
import type { AnyEntity, EntityMetadata, EntityName, PopulateOptions } from '../typings.js';
|
|
2
2
|
import type { Configuration } from '../utils/Configuration.js';
|
|
3
3
|
/**
|
|
4
4
|
* Helper that allows to keep track of where we are currently at when serializing complex entity graph with cycles.
|
|
@@ -10,21 +10,21 @@ export declare class SerializationContext<T extends object> {
|
|
|
10
10
|
private readonly populate;
|
|
11
11
|
private readonly fields?;
|
|
12
12
|
private readonly exclude?;
|
|
13
|
-
readonly path: [
|
|
13
|
+
readonly path: [EntityName, string][];
|
|
14
14
|
readonly visited: Set<Partial<any>>;
|
|
15
15
|
private entities;
|
|
16
16
|
constructor(config: Configuration, populate?: PopulateOptions<T>[], fields?: Set<string> | undefined, exclude?: string[] | undefined);
|
|
17
17
|
/**
|
|
18
18
|
* Returns true when there is a cycle detected.
|
|
19
19
|
*/
|
|
20
|
-
visit(entityName:
|
|
21
|
-
leave
|
|
20
|
+
visit(entityName: EntityName, prop: string): boolean;
|
|
21
|
+
leave(entityName: EntityName, prop: string): void;
|
|
22
22
|
close(): void;
|
|
23
23
|
/**
|
|
24
24
|
* When initializing new context, we need to propagate it to the whole entity graph recursively.
|
|
25
25
|
*/
|
|
26
26
|
static propagate(root: SerializationContext<any>, entity: AnyEntity, isVisible: (meta: EntityMetadata, prop: string) => boolean): void;
|
|
27
|
-
isMarkedAsPopulated(entityName:
|
|
28
|
-
isPartiallyLoaded(entityName:
|
|
27
|
+
isMarkedAsPopulated(entityName: EntityName, prop: string): boolean;
|
|
28
|
+
isPartiallyLoaded(entityName: EntityName, prop: string): boolean;
|
|
29
29
|
private register;
|
|
30
30
|
}
|