@mikro-orm/core 7.0.0-dev.1 → 7.0.0-dev.100
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 +96 -58
- package/EntityManager.js +465 -395
- package/MikroORM.d.ts +45 -35
- package/MikroORM.js +109 -160
- package/README.md +3 -2
- package/cache/CacheAdapter.js +1 -2
- package/cache/FileCacheAdapter.d.ts +2 -2
- package/cache/FileCacheAdapter.js +20 -27
- package/cache/GeneratedCacheAdapter.d.ts +2 -3
- package/cache/GeneratedCacheAdapter.js +1 -7
- package/cache/MemoryCacheAdapter.d.ts +1 -1
- package/cache/MemoryCacheAdapter.js +1 -5
- package/cache/NullCacheAdapter.d.ts +1 -1
- package/cache/NullCacheAdapter.js +1 -5
- package/cache/index.d.ts +4 -5
- package/cache/index.js +4 -21
- package/connections/Connection.d.ts +22 -14
- package/connections/Connection.js +27 -23
- package/connections/index.d.ts +1 -1
- package/connections/index.js +1 -17
- package/drivers/DatabaseDriver.d.ts +25 -15
- package/drivers/DatabaseDriver.js +77 -64
- package/drivers/IDatabaseDriver.d.ts +40 -16
- package/drivers/IDatabaseDriver.js +1 -4
- package/drivers/index.d.ts +2 -2
- package/drivers/index.js +2 -18
- package/entity/BaseEntity.d.ts +6 -7
- package/entity/BaseEntity.js +16 -23
- package/entity/Collection.d.ts +98 -34
- package/entity/Collection.js +466 -131
- package/entity/EntityAssigner.d.ts +3 -3
- package/entity/EntityAssigner.js +67 -64
- package/entity/EntityFactory.d.ts +10 -3
- package/entity/EntityFactory.js +112 -91
- package/entity/EntityHelper.d.ts +2 -2
- package/entity/EntityHelper.js +66 -53
- package/entity/EntityIdentifier.d.ts +1 -1
- package/entity/EntityIdentifier.js +1 -5
- package/entity/EntityLoader.d.ts +8 -7
- package/entity/EntityLoader.js +161 -128
- package/entity/EntityRepository.d.ts +8 -8
- package/entity/EntityRepository.js +7 -11
- package/entity/Reference.d.ts +10 -13
- package/entity/Reference.js +64 -46
- package/entity/WrappedEntity.d.ts +12 -17
- package/entity/WrappedEntity.js +22 -31
- package/entity/defineEntity.d.ts +568 -0
- package/entity/defineEntity.js +529 -0
- package/entity/index.d.ts +14 -13
- package/entity/index.js +14 -29
- package/entity/utils.d.ts +8 -1
- package/entity/utils.js +22 -13
- package/entity/validators.d.ts +11 -0
- package/entity/validators.js +65 -0
- package/entity/wrap.d.ts +1 -1
- package/entity/wrap.js +2 -6
- package/enums.d.ts +24 -9
- package/enums.js +50 -41
- package/errors.d.ts +11 -3
- package/errors.js +42 -32
- package/events/EventManager.d.ts +5 -4
- package/events/EventManager.js +26 -22
- package/events/EventSubscriber.d.ts +8 -5
- package/events/EventSubscriber.js +1 -2
- package/events/TransactionEventBroadcaster.d.ts +3 -3
- package/events/TransactionEventBroadcaster.js +1 -5
- package/events/index.d.ts +3 -3
- package/events/index.js +3 -19
- package/exceptions.js +18 -39
- package/hydration/Hydrator.d.ts +5 -5
- package/hydration/Hydrator.js +2 -6
- package/hydration/ObjectHydrator.d.ts +7 -7
- package/hydration/ObjectHydrator.js +58 -50
- package/hydration/index.d.ts +2 -2
- package/hydration/index.js +2 -18
- package/index.d.ts +21 -21
- package/index.js +20 -46
- package/logging/DefaultLogger.d.ts +2 -2
- package/logging/DefaultLogger.js +10 -13
- package/logging/Logger.d.ts +1 -1
- package/logging/Logger.js +1 -2
- package/logging/SimpleLogger.d.ts +3 -3
- package/logging/SimpleLogger.js +2 -6
- package/logging/colors.js +1 -5
- package/logging/index.d.ts +5 -4
- package/logging/index.js +5 -20
- package/logging/inspect.d.ts +2 -0
- package/logging/inspect.js +16 -0
- package/metadata/EntitySchema.d.ts +14 -10
- package/metadata/EntitySchema.js +78 -64
- package/metadata/MetadataDiscovery.d.ts +11 -14
- package/metadata/MetadataDiscovery.js +278 -317
- package/metadata/MetadataProvider.d.ts +13 -4
- package/metadata/MetadataProvider.js +47 -8
- package/metadata/MetadataStorage.d.ts +2 -7
- package/metadata/MetadataStorage.js +19 -35
- package/metadata/MetadataValidator.d.ts +3 -10
- package/metadata/MetadataValidator.js +51 -64
- package/metadata/discover-entities.d.ts +5 -0
- package/metadata/discover-entities.js +40 -0
- package/metadata/index.d.ts +6 -6
- package/metadata/index.js +6 -22
- package/metadata/types.d.ts +480 -0
- package/metadata/types.js +1 -0
- package/naming-strategy/AbstractNamingStrategy.d.ts +7 -3
- package/naming-strategy/AbstractNamingStrategy.js +11 -9
- package/naming-strategy/EntityCaseNamingStrategy.d.ts +1 -1
- package/naming-strategy/EntityCaseNamingStrategy.js +2 -6
- package/naming-strategy/MongoNamingStrategy.d.ts +1 -1
- package/naming-strategy/MongoNamingStrategy.js +2 -6
- package/naming-strategy/NamingStrategy.d.ts +12 -2
- package/naming-strategy/NamingStrategy.js +1 -2
- package/naming-strategy/UnderscoreNamingStrategy.d.ts +1 -1
- package/naming-strategy/UnderscoreNamingStrategy.js +2 -6
- package/naming-strategy/index.d.ts +5 -5
- package/naming-strategy/index.js +5 -21
- package/not-supported.d.ts +2 -0
- package/not-supported.js +4 -0
- package/package.json +19 -20
- package/platforms/ExceptionConverter.d.ts +2 -2
- package/platforms/ExceptionConverter.js +4 -8
- package/platforms/Platform.d.ts +15 -22
- package/platforms/Platform.js +58 -88
- package/platforms/index.d.ts +2 -2
- package/platforms/index.js +2 -18
- package/serialization/EntitySerializer.d.ts +4 -2
- package/serialization/EntitySerializer.js +64 -51
- package/serialization/EntityTransformer.d.ts +1 -1
- package/serialization/EntityTransformer.js +48 -42
- package/serialization/SerializationContext.d.ts +2 -2
- package/serialization/SerializationContext.js +24 -25
- package/serialization/index.d.ts +3 -3
- package/serialization/index.js +3 -19
- package/types/ArrayType.d.ts +3 -3
- package/types/ArrayType.js +6 -11
- package/types/BigIntType.d.ts +12 -9
- package/types/BigIntType.js +6 -6
- package/types/BlobType.d.ts +3 -4
- package/types/BlobType.js +2 -11
- package/types/BooleanType.d.ts +5 -4
- package/types/BooleanType.js +5 -6
- package/types/CharacterType.d.ts +3 -3
- package/types/CharacterType.js +2 -6
- package/types/DateTimeType.d.ts +3 -3
- package/types/DateTimeType.js +2 -6
- package/types/DateType.d.ts +3 -3
- package/types/DateType.js +2 -6
- package/types/DecimalType.d.ts +9 -7
- package/types/DecimalType.js +5 -8
- package/types/DoubleType.d.ts +3 -3
- package/types/DoubleType.js +4 -7
- package/types/EnumArrayType.d.ts +4 -4
- package/types/EnumArrayType.js +4 -10
- package/types/EnumType.d.ts +3 -3
- package/types/EnumType.js +2 -6
- package/types/FloatType.d.ts +3 -3
- package/types/FloatType.js +2 -6
- package/types/IntegerType.d.ts +3 -3
- package/types/IntegerType.js +2 -6
- package/types/IntervalType.d.ts +3 -3
- package/types/IntervalType.js +2 -6
- package/types/JsonType.d.ts +4 -4
- package/types/JsonType.js +9 -8
- package/types/MediumIntType.d.ts +3 -3
- package/types/MediumIntType.js +2 -6
- package/types/SmallIntType.d.ts +3 -3
- package/types/SmallIntType.js +2 -6
- package/types/StringType.d.ts +3 -3
- package/types/StringType.js +2 -6
- package/types/TextType.d.ts +3 -3
- package/types/TextType.js +2 -6
- package/types/TimeType.d.ts +3 -3
- package/types/TimeType.js +4 -8
- package/types/TinyIntType.d.ts +3 -3
- package/types/TinyIntType.js +3 -6
- package/types/Type.d.ts +4 -6
- package/types/Type.js +6 -10
- package/types/Uint8ArrayType.d.ts +3 -4
- package/types/Uint8ArrayType.js +3 -12
- package/types/UnknownType.d.ts +3 -3
- package/types/UnknownType.js +2 -6
- package/types/UuidType.d.ts +3 -3
- package/types/UuidType.js +2 -6
- package/types/index.d.ts +25 -25
- package/types/index.js +52 -79
- package/typings.d.ts +134 -93
- package/typings.js +67 -65
- package/unit-of-work/ChangeSet.d.ts +1 -4
- package/unit-of-work/ChangeSet.js +13 -17
- package/unit-of-work/ChangeSetComputer.d.ts +8 -9
- package/unit-of-work/ChangeSetComputer.js +36 -38
- package/unit-of-work/ChangeSetPersister.d.ts +11 -9
- package/unit-of-work/ChangeSetPersister.js +100 -65
- package/unit-of-work/CommitOrderCalculator.d.ts +1 -1
- package/unit-of-work/CommitOrderCalculator.js +6 -10
- package/unit-of-work/IdentityMap.d.ts +1 -1
- package/unit-of-work/IdentityMap.js +1 -5
- package/unit-of-work/UnitOfWork.d.ts +16 -8
- package/unit-of-work/UnitOfWork.js +266 -209
- package/unit-of-work/index.d.ts +6 -6
- package/unit-of-work/index.js +6 -22
- package/utils/AbstractSchemaGenerator.d.ts +11 -11
- package/utils/AbstractSchemaGenerator.js +21 -20
- package/utils/Configuration.d.ts +774 -224
- package/utils/Configuration.js +166 -216
- package/utils/ConfigurationLoader.d.ts +1 -53
- package/utils/ConfigurationLoader.js +1 -367
- package/utils/Cursor.d.ts +6 -9
- package/utils/Cursor.js +25 -25
- package/utils/DataloaderUtils.d.ts +18 -8
- package/utils/DataloaderUtils.js +63 -21
- package/utils/EntityComparator.d.ts +9 -5
- package/utils/EntityComparator.js +155 -108
- package/utils/NullHighlighter.d.ts +1 -1
- package/utils/NullHighlighter.js +1 -5
- package/utils/QueryHelper.d.ts +12 -4
- package/utils/QueryHelper.js +110 -53
- package/utils/RawQueryFragment.d.ts +37 -14
- package/utils/RawQueryFragment.js +50 -33
- package/utils/RequestContext.d.ts +2 -2
- package/utils/RequestContext.js +3 -7
- package/utils/TransactionContext.d.ts +1 -1
- package/utils/TransactionContext.js +4 -8
- package/utils/TransactionManager.d.ts +65 -0
- package/utils/TransactionManager.js +223 -0
- package/utils/Utils.d.ts +16 -100
- package/utils/Utils.js +114 -332
- package/utils/clone.js +7 -11
- package/utils/env-vars.d.ts +3 -0
- package/utils/env-vars.js +87 -0
- package/utils/fs-utils.d.ts +12 -0
- package/utils/fs-utils.js +97 -0
- package/utils/index.d.ts +14 -13
- package/utils/index.js +14 -29
- package/utils/upsert-utils.d.ts +8 -3
- package/utils/upsert-utils.js +57 -10
- package/decorators/Check.d.ts +0 -3
- package/decorators/Check.js +0 -16
- package/decorators/CreateRequestContext.d.ts +0 -3
- package/decorators/CreateRequestContext.js +0 -33
- package/decorators/Embeddable.d.ts +0 -8
- package/decorators/Embeddable.js +0 -14
- package/decorators/Embedded.d.ts +0 -18
- package/decorators/Embedded.js +0 -20
- package/decorators/Entity.d.ts +0 -18
- package/decorators/Entity.js +0 -16
- package/decorators/Enum.d.ts +0 -9
- package/decorators/Enum.js +0 -19
- package/decorators/Filter.d.ts +0 -2
- package/decorators/Filter.js +0 -11
- package/decorators/Formula.d.ts +0 -5
- package/decorators/Formula.js +0 -18
- package/decorators/Indexed.d.ts +0 -17
- package/decorators/Indexed.js +0 -24
- package/decorators/ManyToMany.d.ts +0 -40
- package/decorators/ManyToMany.js +0 -16
- package/decorators/ManyToOne.d.ts +0 -30
- package/decorators/ManyToOne.js +0 -16
- package/decorators/OneToMany.d.ts +0 -28
- package/decorators/OneToMany.js +0 -20
- package/decorators/OneToOne.d.ts +0 -24
- package/decorators/OneToOne.js +0 -10
- package/decorators/PrimaryKey.d.ts +0 -9
- package/decorators/PrimaryKey.js +0 -23
- package/decorators/Property.d.ts +0 -250
- package/decorators/Property.js +0 -34
- package/decorators/Transactional.d.ts +0 -13
- package/decorators/Transactional.js +0 -31
- package/decorators/hooks.d.ts +0 -16
- package/decorators/hooks.js +0 -59
- package/decorators/index.d.ts +0 -17
- package/decorators/index.js +0 -36
- package/entity/ArrayCollection.d.ts +0 -116
- package/entity/ArrayCollection.js +0 -399
- package/entity/EntityValidator.d.ts +0 -19
- package/entity/EntityValidator.js +0 -154
- package/index.mjs +0 -199
- package/metadata/ReflectMetadataProvider.d.ts +0 -8
- package/metadata/ReflectMetadataProvider.js +0 -48
- package/utils/resolveContextProvider.d.ts +0 -10
- package/utils/resolveContextProvider.js +0 -31
|
@@ -1,31 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const MetadataStorage_1 = require("./MetadataStorage");
|
|
13
|
-
const EntitySchema_1 = require("./EntitySchema");
|
|
14
|
-
const enums_1 = require("../enums");
|
|
15
|
-
const errors_1 = require("../errors");
|
|
16
|
-
const types_1 = require("../types");
|
|
17
|
-
const colors_1 = require("../logging/colors");
|
|
18
|
-
const RawQueryFragment_1 = require("../utils/RawQueryFragment");
|
|
19
|
-
class MetadataDiscovery {
|
|
1
|
+
import { EntityMetadata, } from '../typings.js';
|
|
2
|
+
import { Utils } from '../utils/Utils.js';
|
|
3
|
+
import { MetadataValidator } from './MetadataValidator.js';
|
|
4
|
+
import { MetadataStorage } from './MetadataStorage.js';
|
|
5
|
+
import { EntitySchema } from './EntitySchema.js';
|
|
6
|
+
import { Cascade, ReferenceKind } from '../enums.js';
|
|
7
|
+
import { MetadataError } from '../errors.js';
|
|
8
|
+
import { t, Type } from '../types/index.js';
|
|
9
|
+
import { colors } from '../logging/colors.js';
|
|
10
|
+
import { raw, RawQueryFragment } from '../utils/RawQueryFragment.js';
|
|
11
|
+
export class MetadataDiscovery {
|
|
20
12
|
metadata;
|
|
21
13
|
platform;
|
|
22
14
|
config;
|
|
23
15
|
namingStrategy;
|
|
24
16
|
metadataProvider;
|
|
25
|
-
cache;
|
|
26
17
|
logger;
|
|
27
18
|
schemaHelper;
|
|
28
|
-
validator = new
|
|
19
|
+
validator = new MetadataValidator();
|
|
29
20
|
discovered = [];
|
|
30
21
|
constructor(metadata, platform, config) {
|
|
31
22
|
this.metadata = metadata;
|
|
@@ -33,40 +24,49 @@ class MetadataDiscovery {
|
|
|
33
24
|
this.config = config;
|
|
34
25
|
this.namingStrategy = this.config.getNamingStrategy();
|
|
35
26
|
this.metadataProvider = this.config.getMetadataProvider();
|
|
36
|
-
this.cache = this.config.getMetadataCacheAdapter();
|
|
37
27
|
this.logger = this.config.getLogger();
|
|
38
28
|
this.schemaHelper = this.platform.getSchemaHelper();
|
|
39
29
|
}
|
|
40
|
-
async discover(
|
|
30
|
+
async discover(preferTs = true) {
|
|
31
|
+
this.discovered.length = 0;
|
|
41
32
|
const startTime = Date.now();
|
|
42
|
-
this.logger.log('discovery', `ORM entity discovery started, using ${
|
|
43
|
-
await this.findEntities(
|
|
33
|
+
this.logger.log('discovery', `ORM entity discovery started, using ${colors.cyan(this.metadataProvider.constructor.name)}`);
|
|
34
|
+
await this.findEntities(preferTs);
|
|
44
35
|
for (const meta of this.discovered) {
|
|
36
|
+
/* v8 ignore next */
|
|
45
37
|
await this.config.get('discovery').onMetadata?.(meta, this.platform);
|
|
46
38
|
}
|
|
47
39
|
this.processDiscoveredEntities(this.discovered);
|
|
48
40
|
const diff = Date.now() - startTime;
|
|
49
|
-
this.logger.log('discovery', `- entity discovery finished, found ${
|
|
41
|
+
this.logger.log('discovery', `- entity discovery finished, found ${colors.green('' + this.discovered.length)} entities, took ${colors.green(`${diff} ms`)}`);
|
|
50
42
|
const storage = this.mapDiscoveredEntities();
|
|
43
|
+
/* v8 ignore next */
|
|
51
44
|
await this.config.get('discovery').afterDiscovered?.(storage, this.platform);
|
|
52
45
|
return storage;
|
|
53
46
|
}
|
|
54
|
-
discoverSync(
|
|
47
|
+
discoverSync() {
|
|
48
|
+
this.discovered.length = 0;
|
|
55
49
|
const startTime = Date.now();
|
|
56
|
-
this.logger.log('discovery', `ORM entity discovery started, using ${
|
|
57
|
-
this.
|
|
50
|
+
this.logger.log('discovery', `ORM entity discovery started, using ${colors.cyan(this.metadataProvider.constructor.name)} in sync mode`);
|
|
51
|
+
const refs = this.config.get('entities');
|
|
52
|
+
this.discoverReferences(refs);
|
|
58
53
|
for (const meta of this.discovered) {
|
|
54
|
+
/* v8 ignore next */
|
|
59
55
|
void this.config.get('discovery').onMetadata?.(meta, this.platform);
|
|
60
56
|
}
|
|
61
57
|
this.processDiscoveredEntities(this.discovered);
|
|
62
58
|
const diff = Date.now() - startTime;
|
|
63
|
-
this.logger.log('discovery', `- entity discovery finished, found ${
|
|
59
|
+
this.logger.log('discovery', `- entity discovery finished, found ${colors.green('' + this.discovered.length)} entities, took ${colors.green(`${diff} ms`)}`);
|
|
64
60
|
const storage = this.mapDiscoveredEntities();
|
|
61
|
+
/* v8 ignore next */
|
|
65
62
|
void this.config.get('discovery').afterDiscovered?.(storage, this.platform);
|
|
66
63
|
return storage;
|
|
67
64
|
}
|
|
65
|
+
validateDiscovered(metadata) {
|
|
66
|
+
return this.validator.validateDiscovered(metadata, this.config.get('discovery'));
|
|
67
|
+
}
|
|
68
68
|
mapDiscoveredEntities() {
|
|
69
|
-
const discovered = new
|
|
69
|
+
const discovered = new MetadataStorage();
|
|
70
70
|
this.discovered
|
|
71
71
|
.filter(meta => meta.root.name)
|
|
72
72
|
.sort((a, b) => b.root.name.localeCompare(a.root.name))
|
|
@@ -76,11 +76,41 @@ class MetadataDiscovery {
|
|
|
76
76
|
});
|
|
77
77
|
return discovered;
|
|
78
78
|
}
|
|
79
|
+
initAccessors(meta) {
|
|
80
|
+
for (const prop of Object.values(meta.properties)) {
|
|
81
|
+
if (!prop.accessor || meta.properties[prop.accessor]) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const desc = Object.getOwnPropertyDescriptor(meta.prototype, prop.name);
|
|
85
|
+
if (desc?.get || desc?.set) {
|
|
86
|
+
this.initFieldName(prop);
|
|
87
|
+
const accessor = prop.name;
|
|
88
|
+
prop.name = typeof prop.accessor === 'string' ? prop.accessor : prop.name;
|
|
89
|
+
if (prop.accessor === true) {
|
|
90
|
+
prop.getter = prop.setter = true;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
prop.getter = prop.setter = false;
|
|
94
|
+
}
|
|
95
|
+
prop.accessor = accessor;
|
|
96
|
+
prop.serializedName ??= accessor;
|
|
97
|
+
Utils.renameKey(meta.properties, accessor, prop.name);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
const name = prop.name;
|
|
101
|
+
prop.name = prop.accessor;
|
|
102
|
+
this.initFieldName(prop);
|
|
103
|
+
prop.serializedName ??= prop.accessor;
|
|
104
|
+
prop.name = name;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
79
108
|
processDiscoveredEntities(discovered) {
|
|
80
109
|
for (const meta of discovered) {
|
|
81
110
|
let i = 1;
|
|
82
111
|
Object.values(meta.properties).forEach(prop => meta.propertyOrder.set(prop.name, i++));
|
|
83
112
|
Object.values(meta.properties).forEach(prop => this.initPolyEmbeddables(prop, discovered));
|
|
113
|
+
this.initAccessors(meta);
|
|
84
114
|
}
|
|
85
115
|
// ignore base entities (not annotated with @Entity)
|
|
86
116
|
const filtered = discovered.filter(meta => meta.root.name);
|
|
@@ -88,7 +118,7 @@ class MetadataDiscovery {
|
|
|
88
118
|
filtered.sort((a, b) => !a.embeddable === !b.embeddable ? 0 : (a.embeddable ? 1 : -1));
|
|
89
119
|
filtered.forEach(meta => this.initSingleTableInheritance(meta, filtered));
|
|
90
120
|
filtered.forEach(meta => this.defineBaseEntityProperties(meta));
|
|
91
|
-
filtered.forEach(meta => this.metadata.set(meta.className,
|
|
121
|
+
filtered.forEach(meta => this.metadata.set(meta.className, EntitySchema.fromMetadata(meta).init().meta));
|
|
92
122
|
filtered.forEach(meta => this.initAutoincrement(meta));
|
|
93
123
|
filtered.forEach(meta => Object.values(meta.properties).forEach(prop => this.initEmbeddables(meta, prop)));
|
|
94
124
|
filtered.forEach(meta => Object.values(meta.properties).forEach(prop => this.initFactoryField(meta, prop)));
|
|
@@ -103,10 +133,6 @@ class MetadataDiscovery {
|
|
|
103
133
|
this.initDefaultValue(prop);
|
|
104
134
|
this.inferTypeFromDefault(prop);
|
|
105
135
|
this.initColumnType(prop);
|
|
106
|
-
// change tracking on scalars is used only for "auto" flushMode
|
|
107
|
-
if (this.config.get('flushMode') !== 'auto' && [enums_1.ReferenceKind.SCALAR, enums_1.ReferenceKind.EMBEDDED].includes(prop.kind)) {
|
|
108
|
-
prop.trackChanges = false;
|
|
109
|
-
}
|
|
110
136
|
}
|
|
111
137
|
}
|
|
112
138
|
filtered.forEach(meta => Object.values(meta.properties).forEach(prop => this.initIndexes(meta, prop)));
|
|
@@ -116,38 +142,27 @@ class MetadataDiscovery {
|
|
|
116
142
|
discovered.push(...this.processEntity(meta));
|
|
117
143
|
}
|
|
118
144
|
discovered.forEach(meta => meta.sync(true));
|
|
119
|
-
|
|
120
|
-
// override the path in the options, so we can log it from the CLI in `cache:generate` command
|
|
121
|
-
if (combinedCachePath) {
|
|
122
|
-
this.config.get('metadataCache').combined = combinedCachePath;
|
|
123
|
-
}
|
|
145
|
+
this.metadataProvider.combineCache();
|
|
124
146
|
return discovered.map(meta => {
|
|
125
147
|
meta = this.metadata.get(meta.className);
|
|
126
148
|
meta.sync(true);
|
|
127
149
|
return meta;
|
|
128
150
|
});
|
|
129
151
|
}
|
|
130
|
-
findEntities(preferTs
|
|
131
|
-
this.
|
|
132
|
-
const
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
152
|
+
async findEntities(preferTs) {
|
|
153
|
+
const { entities, entitiesTs, baseDir } = this.config.getAll();
|
|
154
|
+
const targets = (preferTs && entitiesTs.length > 0) ? entitiesTs : entities;
|
|
155
|
+
const processed = [];
|
|
156
|
+
for (const entity of targets) {
|
|
157
|
+
if (typeof entity === 'string') {
|
|
158
|
+
const { discoverEntities } = await import('@mikro-orm/core/file-discovery');
|
|
159
|
+
processed.push(...await discoverEntities(entity, { baseDir }));
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
processed.push(entity);
|
|
139
163
|
}
|
|
140
|
-
return this.discoverDirectories(paths).then(() => {
|
|
141
|
-
this.discoverReferences(refs);
|
|
142
|
-
this.discoverMissingTargets();
|
|
143
|
-
this.validator.validateDiscovered(this.discovered, options);
|
|
144
|
-
return this.discovered;
|
|
145
|
-
});
|
|
146
164
|
}
|
|
147
|
-
this.discoverReferences(
|
|
148
|
-
this.discoverMissingTargets();
|
|
149
|
-
this.validator.validateDiscovered(this.discovered, options);
|
|
150
|
-
return this.discovered;
|
|
165
|
+
return this.discoverReferences(processed);
|
|
151
166
|
}
|
|
152
167
|
discoverMissingTargets() {
|
|
153
168
|
const unwrap = (type) => type
|
|
@@ -156,17 +171,17 @@ class MetadataDiscovery {
|
|
|
156
171
|
.replace(/\((.*)\)/, '$1'); // unwrap union types
|
|
157
172
|
const missing = [];
|
|
158
173
|
this.discovered.forEach(meta => Object.values(meta.properties).forEach(prop => {
|
|
159
|
-
if (prop.kind ===
|
|
174
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.pivotEntity && !this.discovered.find(m => m.className === Utils.className(prop.pivotEntity))) {
|
|
160
175
|
const target = typeof prop.pivotEntity === 'function'
|
|
161
176
|
? prop.pivotEntity()
|
|
162
177
|
: prop.pivotEntity;
|
|
163
178
|
missing.push(target);
|
|
164
179
|
}
|
|
165
|
-
if (prop.kind !==
|
|
180
|
+
if (prop.kind !== ReferenceKind.SCALAR && !unwrap(prop.type).split(/ ?\| ?/).every(type => this.discovered.find(m => m.className === type))) {
|
|
166
181
|
const target = typeof prop.entity === 'function'
|
|
167
182
|
? prop.entity()
|
|
168
183
|
: prop.type;
|
|
169
|
-
missing.push(...
|
|
184
|
+
missing.push(...Utils.asArray(target));
|
|
170
185
|
}
|
|
171
186
|
}));
|
|
172
187
|
if (missing.length > 0) {
|
|
@@ -175,50 +190,20 @@ class MetadataDiscovery {
|
|
|
175
190
|
}
|
|
176
191
|
tryDiscoverTargets(targets) {
|
|
177
192
|
for (const target of targets) {
|
|
178
|
-
|
|
179
|
-
|
|
193
|
+
const isDiscoverable = typeof target === 'function' || target instanceof EntitySchema;
|
|
194
|
+
if (isDiscoverable && target.name && !this.metadata.has(target.name)) {
|
|
195
|
+
this.discoverReferences([target], false);
|
|
180
196
|
this.discoverMissingTargets();
|
|
181
197
|
}
|
|
182
198
|
}
|
|
183
199
|
}
|
|
184
|
-
|
|
185
|
-
paths = paths.map(path => Utils_1.Utils.normalizePath(path));
|
|
186
|
-
const files = await (0, globby_1.default)(paths, { cwd: Utils_1.Utils.normalizePath(this.config.get('baseDir')) });
|
|
187
|
-
this.logger.log('discovery', `- processing ${colors_1.colors.cyan('' + files.length)} files`);
|
|
188
|
-
const found = [];
|
|
189
|
-
for (const filepath of files) {
|
|
190
|
-
const filename = (0, node_path_1.basename)(filepath);
|
|
191
|
-
if (!filename.match(/\.[cm]?[jt]s$/) ||
|
|
192
|
-
filename.endsWith('.js.map') ||
|
|
193
|
-
filename.match(/\.d\.[cm]?ts/) ||
|
|
194
|
-
filename.startsWith('.') ||
|
|
195
|
-
filename.match(/index\.[cm]?[jt]s$/)) {
|
|
196
|
-
this.logger.log('discovery', `- ignoring file ${filename}`);
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
199
|
-
const name = this.namingStrategy.getClassName(filename);
|
|
200
|
-
const path = Utils_1.Utils.normalizePath(this.config.get('baseDir'), filepath);
|
|
201
|
-
const targets = await this.getEntityClassOrSchema(path, name);
|
|
202
|
-
for (const target of targets) {
|
|
203
|
-
if (!(target instanceof Function) && !(target instanceof EntitySchema_1.EntitySchema)) {
|
|
204
|
-
this.logger.log('discovery', `- ignoring file ${filename}`);
|
|
205
|
-
continue;
|
|
206
|
-
}
|
|
207
|
-
const entity = this.prepare(target);
|
|
208
|
-
const schema = this.getSchema(entity, path);
|
|
209
|
-
const meta = schema.init().meta;
|
|
210
|
-
this.metadata.set(meta.className, meta);
|
|
211
|
-
found.push([schema, path]);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
for (const [schema, path] of found) {
|
|
215
|
-
this.discoverEntity(schema, path);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
discoverReferences(refs) {
|
|
200
|
+
discoverReferences(refs, validate = true) {
|
|
219
201
|
const found = [];
|
|
220
202
|
for (const entity of refs) {
|
|
221
|
-
|
|
203
|
+
if (typeof entity === 'string') {
|
|
204
|
+
throw new Error('Folder based discovery requires the async `MikroORM.init()` method.');
|
|
205
|
+
}
|
|
206
|
+
const schema = this.getSchema(entity);
|
|
222
207
|
const meta = schema.init().meta;
|
|
223
208
|
this.metadata.set(meta.className, meta);
|
|
224
209
|
found.push(schema);
|
|
@@ -226,20 +211,28 @@ class MetadataDiscovery {
|
|
|
226
211
|
// discover parents (base entities) automatically
|
|
227
212
|
for (const meta of this.metadata) {
|
|
228
213
|
let parent = meta.extends;
|
|
229
|
-
if (parent instanceof
|
|
230
|
-
this.discoverReferences([parent]);
|
|
214
|
+
if (parent instanceof EntitySchema && !this.metadata.has(parent.meta.className)) {
|
|
215
|
+
this.discoverReferences([parent], false);
|
|
231
216
|
}
|
|
217
|
+
if (typeof parent === 'function' && parent.name && !this.metadata.has(parent.name)) {
|
|
218
|
+
this.discoverReferences([parent], false);
|
|
219
|
+
}
|
|
220
|
+
/* v8 ignore next */
|
|
232
221
|
if (!meta.class) {
|
|
233
222
|
continue;
|
|
234
223
|
}
|
|
235
224
|
parent = Object.getPrototypeOf(meta.class);
|
|
236
225
|
if (parent.name !== '' && !this.metadata.has(parent.name)) {
|
|
237
|
-
this.discoverReferences([parent]);
|
|
226
|
+
this.discoverReferences([parent], false);
|
|
238
227
|
}
|
|
239
228
|
}
|
|
240
229
|
for (const schema of found) {
|
|
241
230
|
this.discoverEntity(schema);
|
|
242
231
|
}
|
|
232
|
+
this.discoverMissingTargets();
|
|
233
|
+
if (validate) {
|
|
234
|
+
this.validateDiscovered(this.discovered);
|
|
235
|
+
}
|
|
243
236
|
return this.discovered.filter(meta => found.find(m => m.name === meta.className));
|
|
244
237
|
}
|
|
245
238
|
reset(className) {
|
|
@@ -249,47 +242,47 @@ class MetadataDiscovery {
|
|
|
249
242
|
this.discovered.splice(exists, 1);
|
|
250
243
|
}
|
|
251
244
|
}
|
|
252
|
-
|
|
253
|
-
if (
|
|
254
|
-
|
|
245
|
+
getSchema(entity) {
|
|
246
|
+
if (EntitySchema.REGISTRY.has(entity)) {
|
|
247
|
+
entity = EntitySchema.REGISTRY.get(entity);
|
|
255
248
|
}
|
|
256
|
-
if (
|
|
257
|
-
|
|
249
|
+
if (entity instanceof EntitySchema) {
|
|
250
|
+
const meta = Utils.copy(entity.meta, false);
|
|
251
|
+
return EntitySchema.fromMetadata(meta);
|
|
258
252
|
}
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
getSchema(entity, filepath) {
|
|
262
|
-
if (entity instanceof EntitySchema_1.EntitySchema) {
|
|
263
|
-
if (filepath) {
|
|
264
|
-
// initialize global metadata for given entity
|
|
265
|
-
MetadataStorage_1.MetadataStorage.getMetadata(entity.meta.className, filepath);
|
|
266
|
-
}
|
|
267
|
-
return entity;
|
|
268
|
-
}
|
|
269
|
-
const path = entity[MetadataStorage_1.MetadataStorage.PATH_SYMBOL];
|
|
253
|
+
const path = entity[MetadataStorage.PATH_SYMBOL];
|
|
270
254
|
if (path) {
|
|
271
|
-
const meta =
|
|
272
|
-
meta.path =
|
|
255
|
+
const meta = Utils.copy(MetadataStorage.getMetadata(entity.name, path), false);
|
|
256
|
+
meta.path = Utils.relativePath(path, this.config.get('baseDir'));
|
|
273
257
|
this.metadata.set(entity.name, meta);
|
|
274
258
|
}
|
|
275
259
|
const exists = this.metadata.has(entity.name);
|
|
276
260
|
const meta = this.metadata.get(entity.name, true);
|
|
277
261
|
meta.abstract ??= !(exists && meta.name);
|
|
278
|
-
const schema =
|
|
262
|
+
const schema = EntitySchema.fromMetadata(meta);
|
|
279
263
|
schema.setClass(entity);
|
|
280
|
-
schema.meta.useCache = this.metadataProvider.useCache();
|
|
281
264
|
return schema;
|
|
282
265
|
}
|
|
283
|
-
|
|
284
|
-
|
|
266
|
+
getRootEntity(meta) {
|
|
267
|
+
const base = meta.extends && this.metadata.find(Utils.className(meta.extends));
|
|
268
|
+
if (!base || base === meta) { // make sure we do not fall into infinite loop
|
|
269
|
+
return meta;
|
|
270
|
+
}
|
|
271
|
+
const root = this.getRootEntity(base);
|
|
272
|
+
if (root.discriminatorColumn) {
|
|
273
|
+
return root;
|
|
274
|
+
}
|
|
275
|
+
return meta;
|
|
276
|
+
}
|
|
277
|
+
discoverEntity(schema) {
|
|
285
278
|
const meta = schema.meta;
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
const
|
|
279
|
+
const path = meta.path;
|
|
280
|
+
this.logger.log('discovery', `- processing entity ${colors.cyan(meta.className)}${colors.grey(path ? ` (${path})` : '')}`);
|
|
281
|
+
const root = this.getRootEntity(meta);
|
|
282
|
+
schema.meta.path = Utils.relativePath(meta.path, this.config.get('baseDir'));
|
|
283
|
+
const cache = this.metadataProvider.getCachedMetadata(meta, root);
|
|
289
284
|
if (cache) {
|
|
290
|
-
this.logger.log('discovery', `- using cached metadata for entity ${
|
|
291
|
-
this.metadataProvider.loadFromCache(meta, cache);
|
|
292
|
-
meta.root = root;
|
|
285
|
+
this.logger.log('discovery', `- using cached metadata for entity ${colors.cyan(meta.className)}`);
|
|
293
286
|
this.discovered.push(meta);
|
|
294
287
|
return;
|
|
295
288
|
}
|
|
@@ -298,73 +291,39 @@ class MetadataDiscovery {
|
|
|
298
291
|
this.inferDefaultValue(meta, prop);
|
|
299
292
|
}
|
|
300
293
|
// if the definition is using EntitySchema we still want it to go through the metadata provider to validate no types are missing
|
|
301
|
-
this.metadataProvider.loadEntityMetadata(meta
|
|
294
|
+
this.metadataProvider.loadEntityMetadata(meta);
|
|
302
295
|
if (!meta.collection && meta.name) {
|
|
303
296
|
const entityName = root.discriminatorColumn ? root.name : meta.name;
|
|
304
297
|
meta.collection = this.namingStrategy.classToTableName(entityName);
|
|
305
298
|
}
|
|
306
|
-
|
|
307
|
-
this.saveToCache(meta);
|
|
299
|
+
this.metadataProvider.saveToCache(meta);
|
|
308
300
|
meta.root = root;
|
|
309
301
|
this.discovered.push(meta);
|
|
310
302
|
}
|
|
311
|
-
saveToCache(meta) {
|
|
312
|
-
if (!meta.useCache) {
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
const copy = Utils_1.Utils.copy(meta, false);
|
|
316
|
-
copy.props
|
|
317
|
-
.filter(prop => types_1.Type.isMappedType(prop.type))
|
|
318
|
-
.forEach(prop => {
|
|
319
|
-
['type', 'customType']
|
|
320
|
-
.filter(k => types_1.Type.isMappedType(prop[k]))
|
|
321
|
-
.forEach(k => delete prop[k]);
|
|
322
|
-
});
|
|
323
|
-
copy.props
|
|
324
|
-
.filter(prop => prop.default)
|
|
325
|
-
.forEach(prop => {
|
|
326
|
-
const raw = RawQueryFragment_1.RawQueryFragment.getKnownFragment(prop.default);
|
|
327
|
-
if (raw) {
|
|
328
|
-
prop.defaultRaw ??= this.platform.formatQuery(raw.sql, raw.params);
|
|
329
|
-
delete prop.default;
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
[
|
|
333
|
-
'prototype', 'props', 'referencingProperties', 'propertyOrder', 'relations',
|
|
334
|
-
'concurrencyCheckKeys', 'checks',
|
|
335
|
-
].forEach(key => delete copy[key]);
|
|
336
|
-
// base entity without properties might not have path, but nothing to cache there
|
|
337
|
-
if (meta.path) {
|
|
338
|
-
this.cache.set(meta.className + (0, node_path_1.extname)(meta.path), copy, meta.path);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
303
|
initNullability(prop) {
|
|
342
|
-
if (prop.kind ===
|
|
343
|
-
return
|
|
304
|
+
if (prop.kind === ReferenceKind.ONE_TO_ONE) {
|
|
305
|
+
return Utils.defaultValue(prop, 'nullable', prop.optional || !prop.owner);
|
|
344
306
|
}
|
|
345
|
-
|
|
346
|
-
return Utils_1.Utils.defaultValue(prop, 'nullable', prop.optional || !prop.owner || prop.cascade.includes(enums_1.Cascade.REMOVE) || prop.cascade.includes(enums_1.Cascade.ALL));
|
|
347
|
-
}
|
|
348
|
-
return Utils_1.Utils.defaultValue(prop, 'nullable', prop.optional);
|
|
307
|
+
return Utils.defaultValue(prop, 'nullable', prop.optional);
|
|
349
308
|
}
|
|
350
309
|
applyNamingStrategy(meta, prop) {
|
|
351
310
|
if (!prop.fieldNames) {
|
|
352
311
|
this.initFieldName(prop);
|
|
353
312
|
}
|
|
354
|
-
if (prop.kind ===
|
|
313
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
355
314
|
this.initManyToManyFields(meta, prop);
|
|
356
315
|
}
|
|
357
|
-
if ([
|
|
316
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
|
|
358
317
|
this.initManyToOneFields(prop);
|
|
359
318
|
}
|
|
360
|
-
if (prop.kind ===
|
|
319
|
+
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
361
320
|
this.initOneToManyFields(prop);
|
|
362
321
|
}
|
|
363
322
|
}
|
|
364
323
|
initOwnColumns(meta) {
|
|
365
324
|
meta.sync();
|
|
366
325
|
for (const prop of meta.props) {
|
|
367
|
-
if (!prop.joinColumns || !prop.columnTypes || prop.ownColumns || ![
|
|
326
|
+
if (!prop.joinColumns || !prop.columnTypes || prop.ownColumns || ![ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
|
|
368
327
|
continue;
|
|
369
328
|
}
|
|
370
329
|
if (prop.joinColumns.length > 1) {
|
|
@@ -378,15 +337,15 @@ class MetadataDiscovery {
|
|
|
378
337
|
if (prop.joinColumns.length !== prop.columnTypes.length) {
|
|
379
338
|
prop.columnTypes = prop.joinColumns.flatMap(field => {
|
|
380
339
|
const matched = meta.props.find(p => p.fieldNames?.includes(field));
|
|
381
|
-
|
|
382
|
-
|
|
340
|
+
/* v8 ignore next */
|
|
341
|
+
if (!matched) {
|
|
342
|
+
throw MetadataError.fromWrongForeignKey(meta, prop, 'columnTypes');
|
|
383
343
|
}
|
|
384
|
-
|
|
385
|
-
throw errors_1.MetadataError.fromWrongForeignKey(meta, prop, 'columnTypes');
|
|
344
|
+
return matched.columnTypes;
|
|
386
345
|
});
|
|
387
346
|
}
|
|
388
347
|
if (prop.joinColumns.length !== prop.referencedColumnNames.length) {
|
|
389
|
-
throw
|
|
348
|
+
throw MetadataError.fromWrongForeignKey(meta, prop, 'referencedColumnNames');
|
|
390
349
|
}
|
|
391
350
|
}
|
|
392
351
|
}
|
|
@@ -394,13 +353,13 @@ class MetadataDiscovery {
|
|
|
394
353
|
if (prop.fieldNames && prop.fieldNames.length > 0) {
|
|
395
354
|
return;
|
|
396
355
|
}
|
|
397
|
-
if (prop.kind ===
|
|
356
|
+
if (prop.kind === ReferenceKind.SCALAR || prop.kind === ReferenceKind.EMBEDDED) {
|
|
398
357
|
prop.fieldNames = [this.namingStrategy.propertyToColumnName(prop.name, object)];
|
|
399
358
|
}
|
|
400
|
-
else if ([
|
|
359
|
+
else if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
|
|
401
360
|
prop.fieldNames = this.initManyToOneFieldName(prop, prop.name);
|
|
402
361
|
}
|
|
403
|
-
else if (prop.kind ===
|
|
362
|
+
else if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner) {
|
|
404
363
|
prop.fieldNames = this.initManyToManyFieldName(prop, prop.name);
|
|
405
364
|
}
|
|
406
365
|
}
|
|
@@ -421,11 +380,11 @@ class MetadataDiscovery {
|
|
|
421
380
|
}
|
|
422
381
|
initManyToManyFields(meta, prop) {
|
|
423
382
|
const meta2 = this.metadata.get(prop.type);
|
|
424
|
-
|
|
383
|
+
Utils.defaultValue(prop, 'fixedOrder', !!prop.fixedOrderColumn);
|
|
425
384
|
const pivotMeta = this.metadata.find(prop.pivotEntity);
|
|
426
385
|
const props = Object.values(pivotMeta?.properties ?? {});
|
|
427
386
|
const pks = props.filter(p => p.primary);
|
|
428
|
-
const fks = props.filter(p => p.kind ===
|
|
387
|
+
const fks = props.filter(p => p.kind === ReferenceKind.MANY_TO_ONE);
|
|
429
388
|
if (pivotMeta) {
|
|
430
389
|
pivotMeta.pivotTable = true;
|
|
431
390
|
prop.pivotTable = pivotMeta.tableName;
|
|
@@ -453,14 +412,14 @@ class MetadataDiscovery {
|
|
|
453
412
|
prop.joinColumns = prop2.inverseJoinColumns;
|
|
454
413
|
prop.inverseJoinColumns = prop2.joinColumns;
|
|
455
414
|
}
|
|
456
|
-
prop.referencedColumnNames ??=
|
|
415
|
+
prop.referencedColumnNames ??= Utils.flatten(meta.primaryKeys.map(primaryKey => meta.properties[primaryKey].fieldNames));
|
|
457
416
|
prop.joinColumns ??= prop.referencedColumnNames.map(referencedColumnName => this.namingStrategy.joinKeyColumnName(meta.root.className, referencedColumnName, meta.compositePK));
|
|
458
417
|
prop.inverseJoinColumns ??= this.initManyToOneFieldName(prop, meta2.root.className);
|
|
459
418
|
}
|
|
460
419
|
initManyToOneFields(prop) {
|
|
461
420
|
const meta2 = this.metadata.get(prop.type);
|
|
462
|
-
const fieldNames =
|
|
463
|
-
|
|
421
|
+
const fieldNames = Utils.flatten(meta2.primaryKeys.map(primaryKey => meta2.properties[primaryKey].fieldNames));
|
|
422
|
+
Utils.defaultValue(prop, 'referencedTableName', meta2.collection);
|
|
464
423
|
if (!prop.joinColumns) {
|
|
465
424
|
prop.joinColumns = fieldNames.map(fieldName => this.namingStrategy.joinKeyColumnName(prop.name, fieldName, fieldNames.length > 1));
|
|
466
425
|
}
|
|
@@ -475,7 +434,7 @@ class MetadataDiscovery {
|
|
|
475
434
|
}
|
|
476
435
|
if (!prop.referencedColumnNames) {
|
|
477
436
|
meta2.getPrimaryProps().forEach(pk => this.applyNamingStrategy(meta2, pk));
|
|
478
|
-
prop.referencedColumnNames =
|
|
437
|
+
prop.referencedColumnNames = Utils.flatten(meta2.getPrimaryProps().map(pk => pk.fieldNames));
|
|
479
438
|
}
|
|
480
439
|
}
|
|
481
440
|
processEntity(meta) {
|
|
@@ -483,7 +442,7 @@ class MetadataDiscovery {
|
|
|
483
442
|
meta.primaryKeys = pks.map(prop => prop.name);
|
|
484
443
|
meta.compositePK = pks.length > 1;
|
|
485
444
|
// FK used as PK, we need to cascade
|
|
486
|
-
if (pks.length === 1 && pks[0].kind !==
|
|
445
|
+
if (pks.length === 1 && pks[0].kind !== ReferenceKind.SCALAR) {
|
|
487
446
|
pks[0].deleteRule ??= 'cascade';
|
|
488
447
|
}
|
|
489
448
|
meta.forceConstructor ??= this.shouldForceConstructorUsage(meta);
|
|
@@ -499,15 +458,14 @@ class MetadataDiscovery {
|
|
|
499
458
|
this.initRelation(prop);
|
|
500
459
|
}
|
|
501
460
|
this.initOwnColumns(meta);
|
|
502
|
-
meta.simplePK = pks.length === 1 && pks[0].kind ===
|
|
503
|
-
meta.serializedPrimaryKey
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
serializedPKProp.persist = false;
|
|
461
|
+
meta.simplePK = pks.length === 1 && pks[0].kind === ReferenceKind.SCALAR && !pks[0].customType && pks[0].runtimeType !== 'Date';
|
|
462
|
+
meta.serializedPrimaryKey ??= meta.props.find(prop => prop.serializedPrimaryKey)?.name;
|
|
463
|
+
if (meta.serializedPrimaryKey && meta.serializedPrimaryKey !== meta.primaryKeys[0]) {
|
|
464
|
+
meta.properties[meta.serializedPrimaryKey].persist ??= false;
|
|
507
465
|
}
|
|
508
466
|
if (this.platform.usesPivotTable()) {
|
|
509
467
|
return Object.values(meta.properties)
|
|
510
|
-
.filter(prop => prop.kind ===
|
|
468
|
+
.filter(prop => prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner && prop.pivotTable)
|
|
511
469
|
.map(prop => this.definePivotTableEntity(meta, prop));
|
|
512
470
|
}
|
|
513
471
|
return [];
|
|
@@ -515,7 +473,7 @@ class MetadataDiscovery {
|
|
|
515
473
|
findReferencingProperties(meta, metadata) {
|
|
516
474
|
for (const meta2 of metadata) {
|
|
517
475
|
for (const prop2 of meta2.relations) {
|
|
518
|
-
if (prop2.kind !==
|
|
476
|
+
if (prop2.kind !== ReferenceKind.SCALAR && prop2.type === meta.className) {
|
|
519
477
|
meta.referencingProperties.push({ meta: meta2, prop: prop2 });
|
|
520
478
|
}
|
|
521
479
|
}
|
|
@@ -528,23 +486,23 @@ class MetadataDiscovery {
|
|
|
528
486
|
const meta2 = this.metadata.get(prop.type);
|
|
529
487
|
prop[type] = value(meta2.properties)?.name;
|
|
530
488
|
if (prop[type] == null) {
|
|
531
|
-
throw
|
|
489
|
+
throw MetadataError.fromWrongReference(meta, prop, type);
|
|
532
490
|
}
|
|
533
491
|
}
|
|
534
492
|
});
|
|
535
493
|
}
|
|
536
494
|
ensureCorrectFKOrderInPivotEntity(meta, owner) {
|
|
537
495
|
const pks = Object.values(meta.properties).filter(p => p.primary);
|
|
538
|
-
const fks = Object.values(meta.properties).filter(p => p.kind ===
|
|
496
|
+
const fks = Object.values(meta.properties).filter(p => p.kind === ReferenceKind.MANY_TO_ONE);
|
|
539
497
|
let first, second;
|
|
540
498
|
if (pks.length === 2) {
|
|
541
499
|
[first, second] = pks;
|
|
542
500
|
}
|
|
543
501
|
else if (fks.length >= 2) {
|
|
544
502
|
[first, second] = fks;
|
|
503
|
+
/* v8 ignore next */
|
|
545
504
|
}
|
|
546
505
|
else {
|
|
547
|
-
/* istanbul ignore next */
|
|
548
506
|
return [];
|
|
549
507
|
}
|
|
550
508
|
// wrong FK order, first FK needs to point to the owning side
|
|
@@ -565,7 +523,7 @@ class MetadataDiscovery {
|
|
|
565
523
|
prop.inversedBy = inverseName;
|
|
566
524
|
const inverseProp = {
|
|
567
525
|
name: inverseName,
|
|
568
|
-
kind:
|
|
526
|
+
kind: ReferenceKind.MANY_TO_MANY,
|
|
569
527
|
type: meta.className,
|
|
570
528
|
mappedBy: prop.name,
|
|
571
529
|
pivotEntity: prop.pivotEntity,
|
|
@@ -594,7 +552,7 @@ class MetadataDiscovery {
|
|
|
594
552
|
}
|
|
595
553
|
schemaName ??= meta.schema;
|
|
596
554
|
const targetType = prop.targetMeta.className;
|
|
597
|
-
const data = new
|
|
555
|
+
const data = new EntityMetadata({
|
|
598
556
|
name: prop.pivotTable,
|
|
599
557
|
className: prop.pivotTable,
|
|
600
558
|
collection: tableName,
|
|
@@ -621,14 +579,14 @@ class MetadataDiscovery {
|
|
|
621
579
|
}
|
|
622
580
|
data.properties[meta.name + '_owner'] = this.definePivotProperty(prop, meta.name + '_owner', meta.className, targetType + '_inverse', true, meta.className === targetType);
|
|
623
581
|
data.properties[targetType + '_inverse'] = this.definePivotProperty(prop, targetType + '_inverse', targetType, meta.name + '_owner', false, meta.className === targetType);
|
|
624
|
-
return this.metadata.set(data.className, data);
|
|
582
|
+
return this.metadata.set(data.className, EntitySchema.fromMetadata(data).init().meta);
|
|
625
583
|
}
|
|
626
584
|
defineFixedOrderProperty(prop, targetType) {
|
|
627
585
|
const pk = prop.fixedOrderColumn || this.namingStrategy.referenceColumnName();
|
|
628
586
|
const primaryProp = {
|
|
629
587
|
name: pk,
|
|
630
588
|
type: 'number',
|
|
631
|
-
kind:
|
|
589
|
+
kind: ReferenceKind.SCALAR,
|
|
632
590
|
primary: true,
|
|
633
591
|
autoincrement: true,
|
|
634
592
|
unsigned: this.platform.supportsUnsigned(),
|
|
@@ -647,8 +605,8 @@ class MetadataDiscovery {
|
|
|
647
605
|
const ret = {
|
|
648
606
|
name,
|
|
649
607
|
type,
|
|
650
|
-
kind:
|
|
651
|
-
cascade: [
|
|
608
|
+
kind: ReferenceKind.MANY_TO_ONE,
|
|
609
|
+
cascade: [Cascade.ALL],
|
|
652
610
|
fixedOrder: prop.fixedOrder,
|
|
653
611
|
fixedOrderColumn: prop.fixedOrderColumn,
|
|
654
612
|
index: this.platform.indexForeignKeys(),
|
|
@@ -656,6 +614,7 @@ class MetadataDiscovery {
|
|
|
656
614
|
autoincrement: false,
|
|
657
615
|
updateRule: prop.updateRule,
|
|
658
616
|
deleteRule: prop.deleteRule,
|
|
617
|
+
createForeignKeyConstraint: prop.createForeignKeyConstraint,
|
|
659
618
|
};
|
|
660
619
|
if (selfReferencing && !this.platform.supportsMultipleCascadePaths()) {
|
|
661
620
|
ret.updateRule ??= 'no action';
|
|
@@ -701,7 +660,7 @@ class MetadataDiscovery {
|
|
|
701
660
|
}
|
|
702
661
|
autoWireBidirectionalProperties(meta) {
|
|
703
662
|
Object.values(meta.properties)
|
|
704
|
-
.filter(prop => prop.kind !==
|
|
663
|
+
.filter(prop => prop.kind !== ReferenceKind.SCALAR && !prop.owner && prop.mappedBy)
|
|
705
664
|
.forEach(prop => {
|
|
706
665
|
const meta2 = this.metadata.get(prop.type);
|
|
707
666
|
const prop2 = meta2.properties[prop.mappedBy];
|
|
@@ -711,7 +670,7 @@ class MetadataDiscovery {
|
|
|
711
670
|
});
|
|
712
671
|
}
|
|
713
672
|
defineBaseEntityProperties(meta) {
|
|
714
|
-
const base = meta.extends && this.metadata.get(
|
|
673
|
+
const base = meta.extends && this.metadata.get(Utils.className(meta.extends));
|
|
715
674
|
if (!base || base === meta) { // make sure we do not fall into infinite loop
|
|
716
675
|
return 0;
|
|
717
676
|
}
|
|
@@ -732,26 +691,23 @@ class MetadataDiscovery {
|
|
|
732
691
|
meta.propertyOrder.set(prop.name, (order += 0.01));
|
|
733
692
|
});
|
|
734
693
|
}
|
|
735
|
-
meta.indexes =
|
|
736
|
-
meta.uniques =
|
|
737
|
-
meta.checks =
|
|
694
|
+
meta.indexes = Utils.unique([...base.indexes, ...meta.indexes]);
|
|
695
|
+
meta.uniques = Utils.unique([...base.uniques, ...meta.uniques]);
|
|
696
|
+
meta.checks = Utils.unique([...base.checks, ...meta.checks]);
|
|
738
697
|
const pks = Object.values(meta.properties).filter(p => p.primary).map(p => p.name);
|
|
739
698
|
if (pks.length > 0 && meta.primaryKeys.length === 0) {
|
|
740
699
|
meta.primaryKeys = pks;
|
|
741
700
|
}
|
|
742
|
-
|
|
743
|
-
meta.hooks[type] =
|
|
701
|
+
Utils.keys(base.hooks).forEach(type => {
|
|
702
|
+
meta.hooks[type] = Utils.unique([...base.hooks[type], ...(meta.hooks[type] || [])]);
|
|
744
703
|
});
|
|
745
|
-
if (meta.constructorParams
|
|
704
|
+
if ((meta.constructorParams?.length ?? 0) === 0 && (base.constructorParams?.length ?? 0) > 0) {
|
|
746
705
|
meta.constructorParams = [...base.constructorParams];
|
|
747
706
|
}
|
|
748
|
-
if (meta.toJsonParams.length === 0 && base.toJsonParams.length > 0) {
|
|
749
|
-
meta.toJsonParams = [...base.toJsonParams];
|
|
750
|
-
}
|
|
751
707
|
return order;
|
|
752
708
|
}
|
|
753
709
|
initPolyEmbeddables(embeddedProp, discovered, visited = new Set()) {
|
|
754
|
-
if (embeddedProp.kind !==
|
|
710
|
+
if (embeddedProp.kind !== ReferenceKind.EMBEDDED || visited.has(embeddedProp)) {
|
|
755
711
|
return;
|
|
756
712
|
}
|
|
757
713
|
visited.add(embeddedProp);
|
|
@@ -768,6 +724,7 @@ class MetadataDiscovery {
|
|
|
768
724
|
delete prop.default;
|
|
769
725
|
if (properties[prop.name] && properties[prop.name].type !== prop.type) {
|
|
770
726
|
properties[prop.name].type = `${properties[prop.name].type} | ${prop.type}`;
|
|
727
|
+
properties[prop.name].runtimeType = 'any';
|
|
771
728
|
return properties[prop.name];
|
|
772
729
|
}
|
|
773
730
|
return properties[prop.name] = prop;
|
|
@@ -775,7 +732,7 @@ class MetadataDiscovery {
|
|
|
775
732
|
};
|
|
776
733
|
const processExtensions = (meta) => {
|
|
777
734
|
const parent = this.discovered.find(m => {
|
|
778
|
-
return meta.extends &&
|
|
735
|
+
return meta.extends && Utils.className(meta.extends) === m.className;
|
|
779
736
|
});
|
|
780
737
|
if (!parent) {
|
|
781
738
|
return;
|
|
@@ -789,7 +746,7 @@ class MetadataDiscovery {
|
|
|
789
746
|
processExtensions(meta);
|
|
790
747
|
});
|
|
791
748
|
const name = polymorphs.map(t => t.className).sort().join(' | ');
|
|
792
|
-
embeddable = new
|
|
749
|
+
embeddable = new EntityMetadata({
|
|
793
750
|
name,
|
|
794
751
|
className: name,
|
|
795
752
|
embeddable: true,
|
|
@@ -804,13 +761,13 @@ class MetadataDiscovery {
|
|
|
804
761
|
}
|
|
805
762
|
}
|
|
806
763
|
initEmbeddables(meta, embeddedProp, visited = new Set()) {
|
|
807
|
-
if (embeddedProp.kind !==
|
|
764
|
+
if (embeddedProp.kind !== ReferenceKind.EMBEDDED || visited.has(embeddedProp)) {
|
|
808
765
|
return;
|
|
809
766
|
}
|
|
810
767
|
visited.add(embeddedProp);
|
|
811
768
|
const embeddable = this.discovered.find(m => m.name === embeddedProp.type);
|
|
812
769
|
if (!embeddable) {
|
|
813
|
-
throw
|
|
770
|
+
throw MetadataError.fromUnknownEntity(embeddedProp.type, `${meta.className}.${embeddedProp.name}`);
|
|
814
771
|
}
|
|
815
772
|
embeddedProp.embeddable = embeddable.class;
|
|
816
773
|
embeddedProp.embeddedProps = {};
|
|
@@ -822,22 +779,30 @@ class MetadataDiscovery {
|
|
|
822
779
|
}
|
|
823
780
|
return prop.embedded ? isParentObject(meta.properties[prop.embedded[0]]) : false;
|
|
824
781
|
};
|
|
782
|
+
const isParentArray = (prop) => {
|
|
783
|
+
if (prop.array) {
|
|
784
|
+
return true;
|
|
785
|
+
}
|
|
786
|
+
return prop.embedded ? isParentArray(meta.properties[prop.embedded[0]]) : false;
|
|
787
|
+
};
|
|
825
788
|
const rootProperty = getRootProperty(embeddedProp);
|
|
826
789
|
const parentProperty = meta.properties[embeddedProp.embedded?.[0] ?? ''];
|
|
827
790
|
const object = isParentObject(embeddedProp);
|
|
791
|
+
const array = isParentArray(embeddedProp);
|
|
828
792
|
this.initFieldName(embeddedProp, rootProperty !== embeddedProp && object);
|
|
829
793
|
// the prefix of the parent cannot be a boolean; it already passed here
|
|
830
794
|
const prefix = this.getPrefix(embeddedProp, parentProperty);
|
|
831
795
|
const glue = object ? '~' : '_';
|
|
832
796
|
for (const prop of Object.values(embeddable.properties)) {
|
|
833
797
|
const name = (embeddedProp.embeddedPath?.join(glue) ?? embeddedProp.fieldNames[0] + glue) + prop.name;
|
|
834
|
-
meta.properties[name] =
|
|
798
|
+
meta.properties[name] = Utils.copy(prop, false);
|
|
835
799
|
meta.properties[name].name = name;
|
|
836
800
|
meta.properties[name].embedded = [embeddedProp.name, prop.name];
|
|
837
801
|
meta.propertyOrder.set(name, (order += 0.01));
|
|
838
802
|
embeddedProp.embeddedProps[prop.name] = meta.properties[name];
|
|
839
803
|
meta.properties[name].persist ??= embeddedProp.persist;
|
|
840
|
-
|
|
804
|
+
const refInArray = array && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && prop.owner;
|
|
805
|
+
if (embeddedProp.nullable || refInArray) {
|
|
841
806
|
meta.properties[name].nullable = true;
|
|
842
807
|
}
|
|
843
808
|
if (meta.properties[name].fieldNames) {
|
|
@@ -870,18 +835,19 @@ class MetadataDiscovery {
|
|
|
870
835
|
path.push(prop.fieldNames[0]);
|
|
871
836
|
meta.properties[name].fieldNames = prop.fieldNames;
|
|
872
837
|
meta.properties[name].embeddedPath = path;
|
|
873
|
-
const fieldName =
|
|
838
|
+
const fieldName = raw(this.platform.getSearchJsonPropertySQL(path.join('->'), prop.runtimeType ?? prop.type, true));
|
|
874
839
|
meta.properties[name].fieldNameRaw = fieldName.sql; // for querying in SQL drivers
|
|
875
840
|
meta.properties[name].persist = false; // only virtual as we store the whole object
|
|
876
841
|
meta.properties[name].userDefined = false; // mark this as a generated/internal property, so we can distinguish from user-defined non-persist properties
|
|
877
842
|
meta.properties[name].object = true;
|
|
843
|
+
this.initCustomType(meta, meta.properties[name], false, true);
|
|
878
844
|
}
|
|
879
845
|
this.initEmbeddables(meta, meta.properties[name], visited);
|
|
880
846
|
}
|
|
881
847
|
for (const index of embeddable.indexes) {
|
|
882
848
|
meta.indexes.push({
|
|
883
849
|
...index,
|
|
884
|
-
properties:
|
|
850
|
+
properties: Utils.asArray(index.properties).map(p => {
|
|
885
851
|
return embeddedProp.embeddedProps[p].name;
|
|
886
852
|
}),
|
|
887
853
|
});
|
|
@@ -889,7 +855,7 @@ class MetadataDiscovery {
|
|
|
889
855
|
for (const unique of embeddable.uniques) {
|
|
890
856
|
meta.uniques.push({
|
|
891
857
|
...unique,
|
|
892
|
-
properties:
|
|
858
|
+
properties: Utils.asArray(unique.properties).map(p => {
|
|
893
859
|
return embeddedProp.embeddedProps[p].name;
|
|
894
860
|
}),
|
|
895
861
|
});
|
|
@@ -908,24 +874,26 @@ class MetadataDiscovery {
|
|
|
908
874
|
}
|
|
909
875
|
if (!meta.root.discriminatorMap) {
|
|
910
876
|
meta.root.discriminatorMap = {};
|
|
911
|
-
const children = metadata
|
|
912
|
-
|
|
877
|
+
const children = metadata
|
|
878
|
+
.filter(m => m.root.className === meta.root.className && !m.abstract)
|
|
879
|
+
.sort((a, b) => a.className.localeCompare(b.className));
|
|
880
|
+
for (const m of children) {
|
|
913
881
|
const name = m.discriminatorValue ?? this.namingStrategy.classToTableName(m.className);
|
|
914
882
|
meta.root.discriminatorMap[name] = m.className;
|
|
915
|
-
}
|
|
883
|
+
}
|
|
916
884
|
}
|
|
917
885
|
meta.discriminatorValue = Object.entries(meta.root.discriminatorMap).find(([, className]) => className === meta.className)?.[0];
|
|
918
886
|
if (!meta.root.properties[meta.root.discriminatorColumn]) {
|
|
919
887
|
this.createDiscriminatorProperty(meta.root);
|
|
920
888
|
}
|
|
921
|
-
|
|
922
|
-
|
|
889
|
+
Utils.defaultValue(meta.root.properties[meta.root.discriminatorColumn], 'items', Object.keys(meta.root.discriminatorMap));
|
|
890
|
+
Utils.defaultValue(meta.root.properties[meta.root.discriminatorColumn], 'index', true);
|
|
923
891
|
if (meta.root === meta) {
|
|
924
892
|
return;
|
|
925
893
|
}
|
|
926
894
|
let i = 1;
|
|
927
895
|
Object.values(meta.properties).forEach(prop => {
|
|
928
|
-
const newProp =
|
|
896
|
+
const newProp = { ...prop };
|
|
929
897
|
if (meta.root.properties[prop.name] && meta.root.properties[prop.name].type !== prop.type) {
|
|
930
898
|
const name = newProp.name;
|
|
931
899
|
this.initFieldName(newProp, newProp.object);
|
|
@@ -938,34 +906,35 @@ class MetadataDiscovery {
|
|
|
938
906
|
return;
|
|
939
907
|
}
|
|
940
908
|
if (prop.enum && prop.items && meta.root.properties[prop.name]?.items) {
|
|
941
|
-
newProp.items =
|
|
909
|
+
newProp.items = Utils.unique([...meta.root.properties[prop.name].items, ...prop.items]);
|
|
942
910
|
}
|
|
943
911
|
newProp.nullable = true;
|
|
944
|
-
newProp.inherited =
|
|
912
|
+
newProp.inherited = !meta.root.properties[prop.name];
|
|
945
913
|
meta.root.addProperty(newProp);
|
|
946
914
|
});
|
|
947
915
|
meta.collection = meta.root.collection;
|
|
948
|
-
meta.root.indexes =
|
|
949
|
-
meta.root.uniques =
|
|
916
|
+
meta.root.indexes = Utils.unique([...meta.root.indexes, ...meta.indexes]);
|
|
917
|
+
meta.root.uniques = Utils.unique([...meta.root.uniques, ...meta.uniques]);
|
|
918
|
+
meta.root.checks = Utils.unique([...meta.root.checks, ...meta.checks]);
|
|
950
919
|
}
|
|
951
920
|
createDiscriminatorProperty(meta) {
|
|
952
921
|
meta.addProperty({
|
|
953
922
|
name: meta.discriminatorColumn,
|
|
954
923
|
type: 'string',
|
|
955
924
|
enum: true,
|
|
956
|
-
kind:
|
|
925
|
+
kind: ReferenceKind.SCALAR,
|
|
957
926
|
userDefined: false,
|
|
958
927
|
});
|
|
959
928
|
}
|
|
960
929
|
initAutoincrement(meta) {
|
|
961
930
|
const pks = meta.getPrimaryProps();
|
|
962
931
|
if (pks.length === 1 && this.platform.isNumericProperty(pks[0])) {
|
|
963
|
-
/*
|
|
932
|
+
/* v8 ignore next */
|
|
964
933
|
pks[0].autoincrement ??= true;
|
|
965
934
|
}
|
|
966
935
|
}
|
|
967
936
|
initCheckConstraints(meta) {
|
|
968
|
-
const map =
|
|
937
|
+
const map = meta.createColumnMappingObject();
|
|
969
938
|
for (const check of meta.checks) {
|
|
970
939
|
const columns = check.property ? meta.properties[check.property].fieldNames : [];
|
|
971
940
|
check.name ??= this.namingStrategy.indexName(meta.tableName, columns, 'check');
|
|
@@ -975,7 +944,7 @@ class MetadataDiscovery {
|
|
|
975
944
|
}
|
|
976
945
|
if (this.platform.usesEnumCheckConstraints() && !meta.embeddable) {
|
|
977
946
|
for (const prop of meta.props) {
|
|
978
|
-
if (prop.enum && !prop.nativeEnumName && prop.items?.every(item =>
|
|
947
|
+
if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => typeof item === 'string')) {
|
|
979
948
|
this.initFieldName(prop);
|
|
980
949
|
meta.checks.push({
|
|
981
950
|
name: this.namingStrategy.indexName(meta.tableName, prop.fieldNames, 'check'),
|
|
@@ -1000,35 +969,28 @@ class MetadataDiscovery {
|
|
|
1000
969
|
}
|
|
1001
970
|
return;
|
|
1002
971
|
}
|
|
1003
|
-
const map =
|
|
972
|
+
const map = meta.createColumnMappingObject();
|
|
1004
973
|
if (prop.generated instanceof Function) {
|
|
1005
974
|
prop.generated = prop.generated(map);
|
|
1006
975
|
}
|
|
1007
976
|
}
|
|
1008
|
-
|
|
1009
|
-
return Object.values(meta.properties).reduce((o, prop) => {
|
|
1010
|
-
if (prop.fieldNames) {
|
|
1011
|
-
o[prop.name] = prop.fieldNames[0];
|
|
1012
|
-
}
|
|
1013
|
-
return o;
|
|
1014
|
-
}, {});
|
|
1015
|
-
}
|
|
1016
|
-
getDefaultVersionValue(prop) {
|
|
977
|
+
getDefaultVersionValue(meta, prop) {
|
|
1017
978
|
if (typeof prop.defaultRaw !== 'undefined') {
|
|
1018
979
|
return prop.defaultRaw;
|
|
1019
980
|
}
|
|
1020
|
-
/*
|
|
981
|
+
/* v8 ignore next */
|
|
1021
982
|
if (prop.default != null) {
|
|
1022
983
|
return '' + this.platform.quoteVersionValue(prop.default, prop);
|
|
1023
984
|
}
|
|
1024
|
-
|
|
985
|
+
this.initCustomType(meta, prop, true);
|
|
986
|
+
const type = prop.customType?.runtimeType ?? prop.runtimeType ?? prop.type;
|
|
987
|
+
if (type === 'Date') {
|
|
1025
988
|
prop.length ??= this.platform.getDefaultVersionLength();
|
|
1026
989
|
return this.platform.getCurrentTimestampSQL(prop.length);
|
|
1027
990
|
}
|
|
1028
991
|
return '1';
|
|
1029
992
|
}
|
|
1030
993
|
inferDefaultValue(meta, prop) {
|
|
1031
|
-
/* istanbul ignore next */
|
|
1032
994
|
if (!meta.class) {
|
|
1033
995
|
return;
|
|
1034
996
|
}
|
|
@@ -1046,8 +1008,8 @@ class MetadataDiscovery {
|
|
|
1046
1008
|
prop.nullable ??= true;
|
|
1047
1009
|
}
|
|
1048
1010
|
// but still use object values for type inference if not explicitly set, e.g. `createdAt = new Date()`
|
|
1049
|
-
if (prop.kind ===
|
|
1050
|
-
prop.type = prop.runtimeType =
|
|
1011
|
+
if (prop.kind === ReferenceKind.SCALAR && prop.type == null && entity1[prop.name] != null) {
|
|
1012
|
+
prop.type = prop.runtimeType = Utils.getObjectType(entity1[prop.name]);
|
|
1051
1013
|
}
|
|
1052
1014
|
}
|
|
1053
1015
|
catch {
|
|
@@ -1059,12 +1021,12 @@ class MetadataDiscovery {
|
|
|
1059
1021
|
return;
|
|
1060
1022
|
}
|
|
1061
1023
|
let val = prop.default;
|
|
1062
|
-
const raw =
|
|
1024
|
+
const raw = RawQueryFragment.getKnownFragment(val);
|
|
1063
1025
|
if (raw) {
|
|
1064
1026
|
prop.defaultRaw = this.platform.formatQuery(raw.sql, raw.params);
|
|
1065
1027
|
return;
|
|
1066
1028
|
}
|
|
1067
|
-
if (
|
|
1029
|
+
if (Array.isArray(prop.default) && prop.customType) {
|
|
1068
1030
|
val = prop.customType.convertToDatabaseValue(prop.default, this.platform);
|
|
1069
1031
|
}
|
|
1070
1032
|
prop.defaultRaw = typeof val === 'string' ? `'${val}'` : '' + val;
|
|
@@ -1092,61 +1054,84 @@ class MetadataDiscovery {
|
|
|
1092
1054
|
if (prop.version) {
|
|
1093
1055
|
this.initDefaultValue(prop);
|
|
1094
1056
|
meta.versionProperty = prop.name;
|
|
1095
|
-
prop.defaultRaw = this.getDefaultVersionValue(prop);
|
|
1057
|
+
prop.defaultRaw = this.getDefaultVersionValue(meta, prop);
|
|
1096
1058
|
}
|
|
1097
1059
|
if (prop.concurrencyCheck && !prop.primary) {
|
|
1098
1060
|
meta.concurrencyCheckKeys.add(prop.name);
|
|
1099
1061
|
}
|
|
1100
1062
|
}
|
|
1101
|
-
initCustomType(meta, prop) {
|
|
1063
|
+
initCustomType(meta, prop, simple = false, objectEmbeddable = false) {
|
|
1102
1064
|
// `prop.type` might be actually instance of custom type class
|
|
1103
|
-
if (
|
|
1065
|
+
if (Type.isMappedType(prop.type) && !prop.customType) {
|
|
1104
1066
|
prop.customType = prop.type;
|
|
1105
1067
|
prop.type = prop.customType.constructor.name;
|
|
1106
1068
|
}
|
|
1107
1069
|
// `prop.type` might also be custom type class (not instance), so `typeof MyType` will give us `function`, not `object`
|
|
1108
|
-
if (typeof prop.type === 'function' &&
|
|
1109
|
-
|
|
1110
|
-
|
|
1070
|
+
if (typeof prop.type === 'function' && Type.isMappedType(prop.type.prototype) && !prop.customType) {
|
|
1071
|
+
// if the type is an ORM defined mapped type without `ensureComparable: true`,
|
|
1072
|
+
// we use just the type name, to have more performant hydration code
|
|
1073
|
+
const type = Utils.keys(t).find(type => {
|
|
1074
|
+
return !Type.getType(t[type]).ensureComparable(meta, prop) && prop.type === t[type];
|
|
1075
|
+
});
|
|
1076
|
+
if (type) {
|
|
1077
|
+
prop.type = type === 'datetime' ? 'Date' : type;
|
|
1078
|
+
}
|
|
1079
|
+
else {
|
|
1080
|
+
prop.customType = new prop.type();
|
|
1081
|
+
prop.type = prop.customType.constructor.name;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
if (simple) {
|
|
1085
|
+
return;
|
|
1111
1086
|
}
|
|
1112
1087
|
if (!prop.customType && ['json', 'jsonb'].includes(prop.type?.toLowerCase())) {
|
|
1113
|
-
prop.customType = new
|
|
1088
|
+
prop.customType = new t.json();
|
|
1089
|
+
}
|
|
1090
|
+
if (prop.kind === ReferenceKind.SCALAR && !prop.customType && prop.columnTypes && ['json', 'jsonb'].includes(prop.columnTypes[0])) {
|
|
1091
|
+
prop.customType = new t.json();
|
|
1114
1092
|
}
|
|
1115
|
-
if (prop.kind ===
|
|
1116
|
-
prop.customType = new
|
|
1093
|
+
if (prop.kind === ReferenceKind.EMBEDDED && !prop.customType && (prop.object || prop.array)) {
|
|
1094
|
+
prop.customType = new t.json();
|
|
1117
1095
|
}
|
|
1118
1096
|
if (!prop.customType && prop.array && prop.items) {
|
|
1119
|
-
prop.customType = new
|
|
1097
|
+
prop.customType = new t.enumArray(`${meta.className}.${prop.name}`, prop.items);
|
|
1098
|
+
}
|
|
1099
|
+
const isArray = prop.type?.toLowerCase() === 'array' || prop.type?.toString().endsWith('[]');
|
|
1100
|
+
if (objectEmbeddable && !prop.customType && isArray) {
|
|
1101
|
+
prop.customType = new t.json();
|
|
1120
1102
|
}
|
|
1121
1103
|
// for number arrays we make sure to convert the items to numbers
|
|
1122
1104
|
if (!prop.customType && prop.type === 'number[]') {
|
|
1123
|
-
prop.customType = new
|
|
1105
|
+
prop.customType = new t.array(i => +i);
|
|
1124
1106
|
}
|
|
1125
1107
|
// `string[]` can be returned via ts-morph, while reflect metadata will give us just `array`
|
|
1126
|
-
if (!prop.customType &&
|
|
1127
|
-
prop.customType = new
|
|
1108
|
+
if (!prop.customType && isArray) {
|
|
1109
|
+
prop.customType = new t.array();
|
|
1128
1110
|
}
|
|
1129
1111
|
if (!prop.customType && prop.type?.toLowerCase() === 'buffer') {
|
|
1130
|
-
prop.customType = new
|
|
1112
|
+
prop.customType = new t.blob();
|
|
1131
1113
|
}
|
|
1132
1114
|
if (!prop.customType && prop.type?.toLowerCase() === 'uint8array') {
|
|
1133
|
-
prop.customType = new
|
|
1115
|
+
prop.customType = new t.uint8array();
|
|
1134
1116
|
}
|
|
1135
1117
|
const mappedType = this.getMappedType(prop);
|
|
1136
1118
|
if (prop.fieldNames?.length === 1 && !prop.customType) {
|
|
1137
|
-
[
|
|
1119
|
+
[t.bigint, t.double, t.decimal, t.interval, t.date]
|
|
1138
1120
|
.filter(type => mappedType instanceof type)
|
|
1139
|
-
.forEach(type => prop.customType = new type());
|
|
1121
|
+
.forEach((type) => prop.customType = new type());
|
|
1140
1122
|
}
|
|
1141
1123
|
if (prop.customType && !prop.columnTypes) {
|
|
1142
1124
|
const mappedType = this.getMappedType({ columnTypes: [prop.customType.getColumnType(prop, this.platform)] });
|
|
1143
|
-
if (prop.customType.compareAsType() === 'any' && ![
|
|
1125
|
+
if (prop.customType.compareAsType() === 'any' && ![t.json].some(t => prop.customType instanceof t)) {
|
|
1144
1126
|
prop.runtimeType ??= mappedType.runtimeType;
|
|
1145
1127
|
}
|
|
1146
1128
|
else {
|
|
1147
1129
|
prop.runtimeType ??= prop.customType.runtimeType;
|
|
1148
1130
|
}
|
|
1149
1131
|
}
|
|
1132
|
+
else if (prop.runtimeType === 'object') {
|
|
1133
|
+
prop.runtimeType = mappedType.runtimeType;
|
|
1134
|
+
}
|
|
1150
1135
|
else {
|
|
1151
1136
|
prop.runtimeType ??= mappedType.runtimeType;
|
|
1152
1137
|
}
|
|
@@ -1157,19 +1142,20 @@ class MetadataDiscovery {
|
|
|
1157
1142
|
prop.columnTypes ??= [prop.customType.getColumnType(prop, this.platform)];
|
|
1158
1143
|
prop.hasConvertToJSValueSQL = !!prop.customType.convertToJSValueSQL && prop.customType.convertToJSValueSQL('', this.platform) !== '';
|
|
1159
1144
|
prop.hasConvertToDatabaseValueSQL = !!prop.customType.convertToDatabaseValueSQL && prop.customType.convertToDatabaseValueSQL('', this.platform) !== '';
|
|
1160
|
-
if (prop.customType instanceof
|
|
1145
|
+
if (prop.customType instanceof t.bigint && ['string', 'bigint', 'number'].includes(prop.runtimeType.toLowerCase())) {
|
|
1161
1146
|
prop.customType.mode = prop.runtimeType.toLowerCase();
|
|
1162
1147
|
}
|
|
1163
1148
|
}
|
|
1164
|
-
if (
|
|
1149
|
+
if (Type.isMappedType(prop.customType) && prop.kind === ReferenceKind.SCALAR && !isArray) {
|
|
1165
1150
|
prop.type = prop.customType.name;
|
|
1166
1151
|
}
|
|
1167
|
-
if (!prop.customType && [
|
|
1152
|
+
if (!prop.customType && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind) && this.metadata.get(prop.type).compositePK) {
|
|
1168
1153
|
prop.customTypes = [];
|
|
1169
1154
|
for (const pk of this.metadata.get(prop.type).getPrimaryProps()) {
|
|
1170
1155
|
if (pk.customType) {
|
|
1171
1156
|
prop.customTypes.push(pk.customType);
|
|
1172
1157
|
prop.hasConvertToJSValueSQL ||= !!pk.customType.convertToJSValueSQL && pk.customType.convertToJSValueSQL('', this.platform) !== '';
|
|
1158
|
+
/* v8 ignore next */
|
|
1173
1159
|
prop.hasConvertToDatabaseValueSQL ||= !!pk.customType.convertToDatabaseValueSQL && pk.customType.convertToDatabaseValueSQL('', this.platform) !== '';
|
|
1174
1160
|
}
|
|
1175
1161
|
else {
|
|
@@ -1177,7 +1163,7 @@ class MetadataDiscovery {
|
|
|
1177
1163
|
}
|
|
1178
1164
|
}
|
|
1179
1165
|
}
|
|
1180
|
-
if (prop.kind ===
|
|
1166
|
+
if (prop.kind === ReferenceKind.SCALAR && !(mappedType instanceof t.unknown)) {
|
|
1181
1167
|
if (!prop.columnTypes && prop.nativeEnumName && meta.schema !== this.platform.getDefaultSchemaName() && meta.schema && !prop.nativeEnumName.includes('.')) {
|
|
1182
1168
|
prop.columnTypes = [`${meta.schema}.${prop.nativeEnumName}`];
|
|
1183
1169
|
}
|
|
@@ -1186,19 +1172,19 @@ class MetadataDiscovery {
|
|
|
1186
1172
|
}
|
|
1187
1173
|
// use only custom types provided by user, we don't need to use the ones provided by ORM,
|
|
1188
1174
|
// with exception for ArrayType and JsonType, those two are handled in
|
|
1189
|
-
if (!Object.values(
|
|
1175
|
+
if (!Object.values(t).some(type => type === mappedType.constructor)) {
|
|
1190
1176
|
prop.customType ??= mappedType;
|
|
1191
1177
|
}
|
|
1192
1178
|
}
|
|
1193
1179
|
}
|
|
1194
1180
|
initRelation(prop) {
|
|
1195
|
-
if (prop.kind ===
|
|
1181
|
+
if (prop.kind === ReferenceKind.SCALAR) {
|
|
1196
1182
|
return;
|
|
1197
1183
|
}
|
|
1198
1184
|
const meta2 = this.discovered.find(m => m.className === prop.type);
|
|
1199
1185
|
prop.referencedPKs = meta2.primaryKeys;
|
|
1200
1186
|
prop.targetMeta = meta2;
|
|
1201
|
-
if (!prop.formula && prop.persist === false && [
|
|
1187
|
+
if (!prop.formula && prop.persist === false && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && !prop.embedded) {
|
|
1202
1188
|
prop.formula = a => `${a}.${this.platform.quoteIdentifier(prop.fieldNames[0])}`;
|
|
1203
1189
|
}
|
|
1204
1190
|
}
|
|
@@ -1209,7 +1195,7 @@ class MetadataDiscovery {
|
|
|
1209
1195
|
prop.precision ??= pk.precision;
|
|
1210
1196
|
prop.scale ??= pk.scale;
|
|
1211
1197
|
});
|
|
1212
|
-
if (prop.kind ===
|
|
1198
|
+
if (prop.kind === ReferenceKind.SCALAR && (prop.type == null || prop.type === 'object') && prop.columnTypes?.[0]) {
|
|
1213
1199
|
delete prop.type;
|
|
1214
1200
|
const mappedType = this.getMappedType(prop);
|
|
1215
1201
|
prop.type = mappedType.compareAsType();
|
|
@@ -1217,10 +1203,10 @@ class MetadataDiscovery {
|
|
|
1217
1203
|
if (prop.columnTypes || !this.schemaHelper) {
|
|
1218
1204
|
return;
|
|
1219
1205
|
}
|
|
1220
|
-
if (prop.kind ===
|
|
1206
|
+
if (prop.kind === ReferenceKind.SCALAR) {
|
|
1221
1207
|
const mappedType = this.getMappedType(prop);
|
|
1222
1208
|
const SCALAR_TYPES = ['string', 'number', 'boolean', 'bigint', 'Date', 'Buffer', 'RegExp', 'any', 'unknown'];
|
|
1223
|
-
if (mappedType instanceof
|
|
1209
|
+
if (mappedType instanceof t.unknown
|
|
1224
1210
|
&& !prop.columnTypes
|
|
1225
1211
|
// it could be a runtime type from reflect-metadata
|
|
1226
1212
|
&& !SCALAR_TYPES.includes(prop.type)
|
|
@@ -1234,7 +1220,7 @@ class MetadataDiscovery {
|
|
|
1234
1220
|
}
|
|
1235
1221
|
return;
|
|
1236
1222
|
}
|
|
1237
|
-
if (prop.kind ===
|
|
1223
|
+
if (prop.kind === ReferenceKind.EMBEDDED && prop.object && !prop.columnTypes) {
|
|
1238
1224
|
prop.columnTypes = [this.platform.getJsonDeclarationSQL()];
|
|
1239
1225
|
return;
|
|
1240
1226
|
}
|
|
@@ -1258,13 +1244,13 @@ class MetadataDiscovery {
|
|
|
1258
1244
|
if (prop.customType) {
|
|
1259
1245
|
return prop.customType;
|
|
1260
1246
|
}
|
|
1261
|
-
/*
|
|
1247
|
+
/* v8 ignore next */
|
|
1262
1248
|
let t = prop.columnTypes?.[0] ?? prop.type ?? '';
|
|
1263
1249
|
if (prop.nativeEnumName) {
|
|
1264
1250
|
t = 'enum';
|
|
1265
1251
|
}
|
|
1266
1252
|
else if (prop.enum) {
|
|
1267
|
-
t = prop.items?.every(item =>
|
|
1253
|
+
t = prop.items?.every(item => typeof item === 'string') ? 'enum' : 'tinyint';
|
|
1268
1254
|
}
|
|
1269
1255
|
if (t === 'Date') {
|
|
1270
1256
|
t = 'datetime';
|
|
@@ -1287,7 +1273,7 @@ class MetadataDiscovery {
|
|
|
1287
1273
|
if (prop.unsigned != null) {
|
|
1288
1274
|
return;
|
|
1289
1275
|
}
|
|
1290
|
-
if ([
|
|
1276
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
|
|
1291
1277
|
const meta2 = this.metadata.get(prop.type);
|
|
1292
1278
|
prop.unsigned = meta2.getPrimaryProps().some(pk => {
|
|
1293
1279
|
this.initUnsigned(pk);
|
|
@@ -1299,40 +1285,15 @@ class MetadataDiscovery {
|
|
|
1299
1285
|
}
|
|
1300
1286
|
initIndexes(meta, prop) {
|
|
1301
1287
|
const hasIndex = meta.indexes.some(idx => idx.properties?.length === 1 && idx.properties[0] === prop.name);
|
|
1302
|
-
if (prop.kind ===
|
|
1288
|
+
if (prop.kind === ReferenceKind.MANY_TO_ONE && this.platform.indexForeignKeys() && !hasIndex) {
|
|
1303
1289
|
prop.index ??= true;
|
|
1304
1290
|
}
|
|
1305
1291
|
}
|
|
1306
|
-
async getEntityClassOrSchema(path, name) {
|
|
1307
|
-
const exports = await Utils_1.Utils.dynamicImport(path);
|
|
1308
|
-
const targets = Object.values(exports)
|
|
1309
|
-
.filter(item => item instanceof EntitySchema_1.EntitySchema || (item instanceof Function && MetadataStorage_1.MetadataStorage.isKnownEntity(item.name)));
|
|
1310
|
-
// ignore class implementations that are linked from an EntitySchema
|
|
1311
|
-
for (const item of targets) {
|
|
1312
|
-
if (item instanceof EntitySchema_1.EntitySchema) {
|
|
1313
|
-
targets.forEach((item2, idx) => {
|
|
1314
|
-
if (item.meta.class === item2) {
|
|
1315
|
-
targets.splice(idx, 1);
|
|
1316
|
-
}
|
|
1317
|
-
});
|
|
1318
|
-
}
|
|
1319
|
-
}
|
|
1320
|
-
if (targets.length > 0) {
|
|
1321
|
-
return targets;
|
|
1322
|
-
}
|
|
1323
|
-
const target = exports.default ?? exports[name];
|
|
1324
|
-
/* istanbul ignore next */
|
|
1325
|
-
if (!target) {
|
|
1326
|
-
throw errors_1.MetadataError.entityNotFound(name, path.replace(this.config.get('baseDir'), '.'));
|
|
1327
|
-
}
|
|
1328
|
-
return [target];
|
|
1329
|
-
}
|
|
1330
1292
|
shouldForceConstructorUsage(meta) {
|
|
1331
1293
|
const forceConstructor = this.config.get('forceEntityConstructor');
|
|
1332
1294
|
if (Array.isArray(forceConstructor)) {
|
|
1333
|
-
return forceConstructor.some(cls =>
|
|
1295
|
+
return forceConstructor.some(cls => Utils.className(cls) === meta.className);
|
|
1334
1296
|
}
|
|
1335
1297
|
return forceConstructor;
|
|
1336
1298
|
}
|
|
1337
1299
|
}
|
|
1338
|
-
exports.MetadataDiscovery = MetadataDiscovery;
|