@mikro-orm/core 7.0.0-dev.8 → 7.0.0-dev.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EntityManager.d.ts +85 -48
- package/EntityManager.js +300 -225
- package/MikroORM.d.ts +40 -31
- package/MikroORM.js +98 -137
- package/README.md +3 -2
- package/cache/FileCacheAdapter.d.ts +1 -1
- package/cache/FileCacheAdapter.js +6 -5
- package/cache/GeneratedCacheAdapter.d.ts +0 -1
- package/cache/GeneratedCacheAdapter.js +0 -2
- package/cache/index.d.ts +0 -1
- package/cache/index.js +0 -1
- package/connections/Connection.d.ts +11 -7
- package/connections/Connection.js +16 -14
- package/drivers/DatabaseDriver.d.ts +11 -5
- package/drivers/DatabaseDriver.js +23 -11
- package/drivers/IDatabaseDriver.d.ts +27 -5
- package/entity/BaseEntity.d.ts +0 -1
- package/entity/BaseEntity.js +0 -3
- package/entity/Collection.d.ts +98 -30
- package/entity/Collection.js +432 -93
- package/entity/EntityAssigner.d.ts +1 -1
- package/entity/EntityAssigner.js +15 -7
- package/entity/EntityFactory.d.ts +7 -0
- package/entity/EntityFactory.js +64 -41
- package/entity/EntityHelper.js +26 -9
- package/entity/EntityLoader.d.ts +5 -4
- package/entity/EntityLoader.js +73 -40
- package/entity/EntityRepository.d.ts +1 -1
- package/entity/Reference.d.ts +9 -7
- package/entity/Reference.js +33 -6
- package/entity/WrappedEntity.d.ts +2 -4
- package/entity/WrappedEntity.js +1 -5
- package/entity/defineEntity.d.ts +549 -0
- package/entity/defineEntity.js +529 -0
- package/entity/index.d.ts +3 -2
- package/entity/index.js +3 -2
- package/entity/utils.d.ts +7 -0
- package/entity/utils.js +16 -4
- package/entity/validators.d.ts +11 -0
- package/entity/validators.js +65 -0
- package/enums.d.ts +21 -6
- package/enums.js +14 -1
- package/errors.d.ts +6 -2
- package/errors.js +14 -9
- package/events/EventSubscriber.d.ts +3 -1
- package/hydration/Hydrator.js +1 -2
- package/hydration/ObjectHydrator.d.ts +4 -4
- package/hydration/ObjectHydrator.js +36 -25
- package/index.d.ts +2 -2
- package/index.js +1 -2
- package/logging/DefaultLogger.d.ts +1 -1
- package/logging/SimpleLogger.d.ts +1 -1
- package/metadata/EntitySchema.d.ts +9 -13
- package/metadata/EntitySchema.js +44 -26
- package/metadata/MetadataDiscovery.d.ts +6 -9
- package/metadata/MetadataDiscovery.js +167 -206
- package/metadata/MetadataProvider.d.ts +11 -2
- package/metadata/MetadataProvider.js +44 -2
- package/metadata/MetadataStorage.d.ts +1 -6
- package/metadata/MetadataStorage.js +6 -18
- package/metadata/MetadataValidator.d.ts +0 -7
- package/metadata/MetadataValidator.js +4 -13
- package/metadata/discover-entities.d.ts +5 -0
- package/metadata/discover-entities.js +40 -0
- package/metadata/index.d.ts +1 -1
- package/metadata/index.js +1 -1
- package/metadata/types.d.ts +480 -0
- package/metadata/types.js +1 -0
- package/naming-strategy/AbstractNamingStrategy.d.ts +5 -1
- package/naming-strategy/AbstractNamingStrategy.js +8 -2
- package/naming-strategy/NamingStrategy.d.ts +11 -1
- package/not-supported.d.ts +2 -0
- package/not-supported.js +4 -0
- package/package.json +18 -10
- package/platforms/ExceptionConverter.js +1 -1
- package/platforms/Platform.d.ts +6 -10
- package/platforms/Platform.js +14 -39
- package/serialization/EntitySerializer.d.ts +2 -0
- package/serialization/EntitySerializer.js +32 -14
- package/serialization/EntityTransformer.js +22 -12
- package/serialization/SerializationContext.js +16 -13
- package/types/ArrayType.d.ts +1 -1
- package/types/ArrayType.js +2 -3
- package/types/BigIntType.d.ts +8 -6
- package/types/BigIntType.js +1 -1
- package/types/BlobType.d.ts +0 -1
- package/types/BlobType.js +0 -3
- package/types/BooleanType.d.ts +2 -1
- package/types/BooleanType.js +3 -0
- package/types/DecimalType.d.ts +6 -4
- package/types/DecimalType.js +3 -3
- package/types/DoubleType.js +2 -2
- package/types/JsonType.d.ts +1 -1
- package/types/JsonType.js +7 -2
- package/types/TinyIntType.js +1 -1
- package/types/Type.d.ts +2 -1
- package/types/Type.js +1 -1
- package/types/Uint8ArrayType.d.ts +0 -1
- package/types/Uint8ArrayType.js +1 -4
- package/types/index.d.ts +1 -1
- package/typings.d.ts +113 -77
- package/typings.js +41 -35
- package/unit-of-work/ChangeSetComputer.d.ts +1 -3
- package/unit-of-work/ChangeSetComputer.js +11 -9
- package/unit-of-work/ChangeSetPersister.d.ts +5 -4
- package/unit-of-work/ChangeSetPersister.js +58 -20
- package/unit-of-work/UnitOfWork.d.ts +8 -1
- package/unit-of-work/UnitOfWork.js +115 -57
- package/utils/AbstractSchemaGenerator.d.ts +5 -5
- package/utils/AbstractSchemaGenerator.js +11 -9
- package/utils/Configuration.d.ts +757 -206
- package/utils/Configuration.js +139 -187
- package/utils/ConfigurationLoader.d.ts +1 -54
- package/utils/ConfigurationLoader.js +1 -352
- package/utils/Cursor.d.ts +3 -3
- package/utils/Cursor.js +4 -1
- package/utils/DataloaderUtils.d.ts +15 -5
- package/utils/DataloaderUtils.js +54 -8
- package/utils/EntityComparator.d.ts +8 -4
- package/utils/EntityComparator.js +111 -64
- package/utils/QueryHelper.d.ts +9 -1
- package/utils/QueryHelper.js +70 -9
- package/utils/RawQueryFragment.d.ts +36 -4
- package/utils/RawQueryFragment.js +35 -14
- package/utils/TransactionManager.d.ts +65 -0
- package/utils/TransactionManager.js +223 -0
- package/utils/Utils.d.ts +8 -97
- package/utils/Utils.js +88 -303
- package/utils/clone.js +2 -3
- 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 +96 -0
- package/utils/index.d.ts +2 -1
- package/utils/index.js +2 -1
- package/utils/upsert-utils.d.ts +7 -2
- package/utils/upsert-utils.js +55 -4
- package/decorators/Check.d.ts +0 -3
- package/decorators/Check.js +0 -13
- package/decorators/CreateRequestContext.d.ts +0 -3
- package/decorators/CreateRequestContext.js +0 -32
- package/decorators/Embeddable.d.ts +0 -8
- package/decorators/Embeddable.js +0 -11
- package/decorators/Embedded.d.ts +0 -18
- package/decorators/Embedded.js +0 -18
- package/decorators/Entity.d.ts +0 -18
- package/decorators/Entity.js +0 -12
- package/decorators/Enum.d.ts +0 -9
- package/decorators/Enum.js +0 -16
- package/decorators/Filter.d.ts +0 -2
- package/decorators/Filter.js +0 -8
- package/decorators/Formula.d.ts +0 -4
- package/decorators/Formula.js +0 -15
- package/decorators/Indexed.d.ts +0 -19
- package/decorators/Indexed.js +0 -20
- package/decorators/ManyToMany.d.ts +0 -40
- package/decorators/ManyToMany.js +0 -14
- package/decorators/ManyToOne.d.ts +0 -30
- package/decorators/ManyToOne.js +0 -14
- package/decorators/OneToMany.d.ts +0 -28
- package/decorators/OneToMany.js +0 -17
- package/decorators/OneToOne.d.ts +0 -24
- package/decorators/OneToOne.js +0 -7
- package/decorators/PrimaryKey.d.ts +0 -8
- package/decorators/PrimaryKey.js +0 -20
- package/decorators/Property.d.ts +0 -250
- package/decorators/Property.js +0 -32
- package/decorators/Transactional.d.ts +0 -13
- package/decorators/Transactional.js +0 -28
- package/decorators/hooks.d.ts +0 -16
- package/decorators/hooks.js +0 -47
- package/decorators/index.d.ts +0 -17
- package/decorators/index.js +0 -17
- package/entity/ArrayCollection.d.ts +0 -116
- package/entity/ArrayCollection.js +0 -402
- package/entity/EntityValidator.d.ts +0 -19
- package/entity/EntityValidator.js +0 -150
- package/metadata/ReflectMetadataProvider.d.ts +0 -8
- package/metadata/ReflectMetadataProvider.js +0 -44
- package/utils/resolveContextProvider.d.ts +0 -10
- package/utils/resolveContextProvider.js +0 -28
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { basename, extname } from 'node:path';
|
|
2
|
-
import globby from 'globby';
|
|
3
1
|
import { EntityMetadata, } from '../typings.js';
|
|
4
2
|
import { Utils } from '../utils/Utils.js';
|
|
5
3
|
import { MetadataValidator } from './MetadataValidator.js';
|
|
@@ -7,7 +5,7 @@ import { MetadataStorage } from './MetadataStorage.js';
|
|
|
7
5
|
import { EntitySchema } from './EntitySchema.js';
|
|
8
6
|
import { Cascade, ReferenceKind } from '../enums.js';
|
|
9
7
|
import { MetadataError } from '../errors.js';
|
|
10
|
-
import {
|
|
8
|
+
import { t, Type } from '../types/index.js';
|
|
11
9
|
import { colors } from '../logging/colors.js';
|
|
12
10
|
import { raw, RawQueryFragment } from '../utils/RawQueryFragment.js';
|
|
13
11
|
export class MetadataDiscovery {
|
|
@@ -16,7 +14,6 @@ export class MetadataDiscovery {
|
|
|
16
14
|
config;
|
|
17
15
|
namingStrategy;
|
|
18
16
|
metadataProvider;
|
|
19
|
-
cache;
|
|
20
17
|
logger;
|
|
21
18
|
schemaHelper;
|
|
22
19
|
validator = new MetadataValidator();
|
|
@@ -27,11 +24,11 @@ export class MetadataDiscovery {
|
|
|
27
24
|
this.config = config;
|
|
28
25
|
this.namingStrategy = this.config.getNamingStrategy();
|
|
29
26
|
this.metadataProvider = this.config.getMetadataProvider();
|
|
30
|
-
this.cache = this.config.getMetadataCacheAdapter();
|
|
31
27
|
this.logger = this.config.getLogger();
|
|
32
28
|
this.schemaHelper = this.platform.getSchemaHelper();
|
|
33
29
|
}
|
|
34
30
|
async discover(preferTs = true) {
|
|
31
|
+
this.discovered.length = 0;
|
|
35
32
|
const startTime = Date.now();
|
|
36
33
|
this.logger.log('discovery', `ORM entity discovery started, using ${colors.cyan(this.metadataProvider.constructor.name)}`);
|
|
37
34
|
await this.findEntities(preferTs);
|
|
@@ -47,10 +44,12 @@ export class MetadataDiscovery {
|
|
|
47
44
|
await this.config.get('discovery').afterDiscovered?.(storage, this.platform);
|
|
48
45
|
return storage;
|
|
49
46
|
}
|
|
50
|
-
discoverSync(
|
|
47
|
+
discoverSync() {
|
|
48
|
+
this.discovered.length = 0;
|
|
51
49
|
const startTime = Date.now();
|
|
52
50
|
this.logger.log('discovery', `ORM entity discovery started, using ${colors.cyan(this.metadataProvider.constructor.name)} in sync mode`);
|
|
53
|
-
this.
|
|
51
|
+
const refs = this.config.get('entities');
|
|
52
|
+
this.discoverReferences(refs);
|
|
54
53
|
for (const meta of this.discovered) {
|
|
55
54
|
/* v8 ignore next */
|
|
56
55
|
void this.config.get('discovery').onMetadata?.(meta, this.platform);
|
|
@@ -63,6 +62,9 @@ export class MetadataDiscovery {
|
|
|
63
62
|
void this.config.get('discovery').afterDiscovered?.(storage, this.platform);
|
|
64
63
|
return storage;
|
|
65
64
|
}
|
|
65
|
+
validateDiscovered(metadata) {
|
|
66
|
+
return this.validator.validateDiscovered(metadata, this.config.get('discovery'));
|
|
67
|
+
}
|
|
66
68
|
mapDiscoveredEntities() {
|
|
67
69
|
const discovered = new MetadataStorage();
|
|
68
70
|
this.discovered
|
|
@@ -74,11 +76,41 @@ export class MetadataDiscovery {
|
|
|
74
76
|
});
|
|
75
77
|
return discovered;
|
|
76
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
|
+
}
|
|
77
108
|
processDiscoveredEntities(discovered) {
|
|
78
109
|
for (const meta of discovered) {
|
|
79
110
|
let i = 1;
|
|
80
111
|
Object.values(meta.properties).forEach(prop => meta.propertyOrder.set(prop.name, i++));
|
|
81
112
|
Object.values(meta.properties).forEach(prop => this.initPolyEmbeddables(prop, discovered));
|
|
113
|
+
this.initAccessors(meta);
|
|
82
114
|
}
|
|
83
115
|
// ignore base entities (not annotated with @Entity)
|
|
84
116
|
const filtered = discovered.filter(meta => meta.root.name);
|
|
@@ -101,10 +133,6 @@ export class MetadataDiscovery {
|
|
|
101
133
|
this.initDefaultValue(prop);
|
|
102
134
|
this.inferTypeFromDefault(prop);
|
|
103
135
|
this.initColumnType(prop);
|
|
104
|
-
// change tracking on scalars is used only for "auto" flushMode
|
|
105
|
-
if (this.config.get('flushMode') !== 'auto' && [ReferenceKind.SCALAR, ReferenceKind.EMBEDDED].includes(prop.kind)) {
|
|
106
|
-
prop.trackChanges = false;
|
|
107
|
-
}
|
|
108
136
|
}
|
|
109
137
|
}
|
|
110
138
|
filtered.forEach(meta => Object.values(meta.properties).forEach(prop => this.initIndexes(meta, prop)));
|
|
@@ -114,38 +142,27 @@ export class MetadataDiscovery {
|
|
|
114
142
|
discovered.push(...this.processEntity(meta));
|
|
115
143
|
}
|
|
116
144
|
discovered.forEach(meta => meta.sync(true));
|
|
117
|
-
|
|
118
|
-
// override the path in the options, so we can log it from the CLI in `cache:generate` command
|
|
119
|
-
if (combinedCachePath) {
|
|
120
|
-
this.config.get('metadataCache').combined = combinedCachePath;
|
|
121
|
-
}
|
|
145
|
+
this.metadataProvider.combineCache();
|
|
122
146
|
return discovered.map(meta => {
|
|
123
147
|
meta = this.metadata.get(meta.className);
|
|
124
148
|
meta.sync(true);
|
|
125
149
|
return meta;
|
|
126
150
|
});
|
|
127
151
|
}
|
|
128
|
-
findEntities(preferTs
|
|
129
|
-
this.
|
|
130
|
-
const
|
|
131
|
-
const
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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);
|
|
137
163
|
}
|
|
138
|
-
return this.discoverDirectories(paths).then(() => {
|
|
139
|
-
this.discoverReferences(refs);
|
|
140
|
-
this.discoverMissingTargets();
|
|
141
|
-
this.validator.validateDiscovered(this.discovered, options);
|
|
142
|
-
return this.discovered;
|
|
143
|
-
});
|
|
144
164
|
}
|
|
145
|
-
this.discoverReferences(
|
|
146
|
-
this.discoverMissingTargets();
|
|
147
|
-
this.validator.validateDiscovered(this.discovered, options);
|
|
148
|
-
return this.discovered;
|
|
165
|
+
return this.discoverReferences(processed);
|
|
149
166
|
}
|
|
150
167
|
discoverMissingTargets() {
|
|
151
168
|
const unwrap = (type) => type
|
|
@@ -173,50 +190,20 @@ export class MetadataDiscovery {
|
|
|
173
190
|
}
|
|
174
191
|
tryDiscoverTargets(targets) {
|
|
175
192
|
for (const target of targets) {
|
|
176
|
-
|
|
177
|
-
|
|
193
|
+
const isDiscoverable = typeof target === 'function' || target instanceof EntitySchema;
|
|
194
|
+
if (isDiscoverable && target.name && !this.metadata.has(target.name)) {
|
|
195
|
+
this.discoverReferences([target], false);
|
|
178
196
|
this.discoverMissingTargets();
|
|
179
197
|
}
|
|
180
198
|
}
|
|
181
199
|
}
|
|
182
|
-
|
|
183
|
-
paths = paths.map(path => Utils.normalizePath(path));
|
|
184
|
-
const files = await globby(paths, { cwd: Utils.normalizePath(this.config.get('baseDir')) });
|
|
185
|
-
this.logger.log('discovery', `- processing ${colors.cyan('' + files.length)} files`);
|
|
186
|
-
const found = [];
|
|
187
|
-
for (const filepath of files) {
|
|
188
|
-
const filename = basename(filepath);
|
|
189
|
-
if (!filename.match(/\.[cm]?[jt]s$/) ||
|
|
190
|
-
filename.endsWith('.js.map') ||
|
|
191
|
-
filename.match(/\.d\.[cm]?ts/) ||
|
|
192
|
-
filename.startsWith('.') ||
|
|
193
|
-
filename.match(/index\.[cm]?[jt]s$/)) {
|
|
194
|
-
this.logger.log('discovery', `- ignoring file ${filename}`);
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
const name = this.namingStrategy.getClassName(filename);
|
|
198
|
-
const path = Utils.normalizePath(this.config.get('baseDir'), filepath);
|
|
199
|
-
const targets = await this.getEntityClassOrSchema(path, name);
|
|
200
|
-
for (const target of targets) {
|
|
201
|
-
if (!(target instanceof Function) && !(target instanceof EntitySchema)) {
|
|
202
|
-
this.logger.log('discovery', `- ignoring file ${filename}`);
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
const entity = this.prepare(target);
|
|
206
|
-
const schema = this.getSchema(entity, path);
|
|
207
|
-
const meta = schema.init().meta;
|
|
208
|
-
this.metadata.set(meta.className, meta);
|
|
209
|
-
found.push([schema, path]);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
for (const [schema, path] of found) {
|
|
213
|
-
this.discoverEntity(schema, path);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
discoverReferences(refs) {
|
|
200
|
+
discoverReferences(refs, validate = true) {
|
|
217
201
|
const found = [];
|
|
218
202
|
for (const entity of refs) {
|
|
219
|
-
|
|
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);
|
|
220
207
|
const meta = schema.init().meta;
|
|
221
208
|
this.metadata.set(meta.className, meta);
|
|
222
209
|
found.push(schema);
|
|
@@ -225,20 +212,27 @@ export class MetadataDiscovery {
|
|
|
225
212
|
for (const meta of this.metadata) {
|
|
226
213
|
let parent = meta.extends;
|
|
227
214
|
if (parent instanceof EntitySchema && !this.metadata.has(parent.meta.className)) {
|
|
228
|
-
this.discoverReferences([parent]);
|
|
215
|
+
this.discoverReferences([parent], false);
|
|
229
216
|
}
|
|
230
|
-
|
|
217
|
+
if (typeof parent === 'function' && parent.name && !this.metadata.has(parent.name)) {
|
|
218
|
+
this.discoverReferences([parent], false);
|
|
219
|
+
}
|
|
220
|
+
/* v8 ignore next */
|
|
231
221
|
if (!meta.class) {
|
|
232
222
|
continue;
|
|
233
223
|
}
|
|
234
224
|
parent = Object.getPrototypeOf(meta.class);
|
|
235
225
|
if (parent.name !== '' && !this.metadata.has(parent.name)) {
|
|
236
|
-
this.discoverReferences([parent]);
|
|
226
|
+
this.discoverReferences([parent], false);
|
|
237
227
|
}
|
|
238
228
|
}
|
|
239
229
|
for (const schema of found) {
|
|
240
230
|
this.discoverEntity(schema);
|
|
241
231
|
}
|
|
232
|
+
this.discoverMissingTargets();
|
|
233
|
+
if (validate) {
|
|
234
|
+
this.validateDiscovered(this.discovered);
|
|
235
|
+
}
|
|
242
236
|
return this.discovered.filter(meta => found.find(m => m.name === meta.className));
|
|
243
237
|
}
|
|
244
238
|
reset(className) {
|
|
@@ -248,23 +242,13 @@ export class MetadataDiscovery {
|
|
|
248
242
|
this.discovered.splice(exists, 1);
|
|
249
243
|
}
|
|
250
244
|
}
|
|
251
|
-
|
|
252
|
-
/* v8 ignore next 3 */
|
|
253
|
-
if ('schema' in entity && entity.schema instanceof EntitySchema) {
|
|
254
|
-
return entity.schema;
|
|
255
|
-
}
|
|
245
|
+
getSchema(entity) {
|
|
256
246
|
if (EntitySchema.REGISTRY.has(entity)) {
|
|
257
|
-
|
|
247
|
+
entity = EntitySchema.REGISTRY.get(entity);
|
|
258
248
|
}
|
|
259
|
-
return entity;
|
|
260
|
-
}
|
|
261
|
-
getSchema(entity, filepath) {
|
|
262
249
|
if (entity instanceof EntitySchema) {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
MetadataStorage.getMetadata(entity.meta.className, filepath);
|
|
266
|
-
}
|
|
267
|
-
return entity;
|
|
250
|
+
const meta = Utils.copy(entity.meta, false);
|
|
251
|
+
return EntitySchema.fromMetadata(meta);
|
|
268
252
|
}
|
|
269
253
|
const path = entity[MetadataStorage.PATH_SYMBOL];
|
|
270
254
|
if (path) {
|
|
@@ -279,16 +263,26 @@ export class MetadataDiscovery {
|
|
|
279
263
|
schema.setClass(entity);
|
|
280
264
|
return schema;
|
|
281
265
|
}
|
|
282
|
-
|
|
283
|
-
|
|
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) {
|
|
284
278
|
const meta = schema.meta;
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
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);
|
|
288
284
|
if (cache) {
|
|
289
285
|
this.logger.log('discovery', `- using cached metadata for entity ${colors.cyan(meta.className)}`);
|
|
290
|
-
this.metadataProvider.loadFromCache(meta, cache);
|
|
291
|
-
meta.root = root;
|
|
292
286
|
this.discovered.push(meta);
|
|
293
287
|
return;
|
|
294
288
|
}
|
|
@@ -297,50 +291,18 @@ export class MetadataDiscovery {
|
|
|
297
291
|
this.inferDefaultValue(meta, prop);
|
|
298
292
|
}
|
|
299
293
|
// if the definition is using EntitySchema we still want it to go through the metadata provider to validate no types are missing
|
|
300
|
-
this.metadataProvider.loadEntityMetadata(meta
|
|
294
|
+
this.metadataProvider.loadEntityMetadata(meta);
|
|
301
295
|
if (!meta.collection && meta.name) {
|
|
302
296
|
const entityName = root.discriminatorColumn ? root.name : meta.name;
|
|
303
297
|
meta.collection = this.namingStrategy.classToTableName(entityName);
|
|
304
298
|
}
|
|
305
|
-
|
|
306
|
-
this.saveToCache(meta);
|
|
299
|
+
this.metadataProvider.saveToCache(meta);
|
|
307
300
|
meta.root = root;
|
|
308
301
|
this.discovered.push(meta);
|
|
309
302
|
}
|
|
310
|
-
saveToCache(meta) {
|
|
311
|
-
if (!this.metadataProvider.useCache()) {
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
const copy = Utils.copy(meta, false);
|
|
315
|
-
for (const prop of copy.props) {
|
|
316
|
-
if (Type.isMappedType(prop.type)) {
|
|
317
|
-
Reflect.deleteProperty(prop, 'type');
|
|
318
|
-
Reflect.deleteProperty(prop, 'customType');
|
|
319
|
-
}
|
|
320
|
-
if (prop.default) {
|
|
321
|
-
const raw = RawQueryFragment.getKnownFragment(prop.default);
|
|
322
|
-
if (raw) {
|
|
323
|
-
prop.defaultRaw ??= this.platform.formatQuery(raw.sql, raw.params);
|
|
324
|
-
Reflect.deleteProperty(prop, 'default');
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
Reflect.deleteProperty(prop, 'targetMeta');
|
|
328
|
-
}
|
|
329
|
-
[
|
|
330
|
-
'prototype', 'props', 'referencingProperties', 'propertyOrder', 'relations',
|
|
331
|
-
'concurrencyCheckKeys', 'checks',
|
|
332
|
-
].forEach(key => delete copy[key]);
|
|
333
|
-
// base entity without properties might not have path, but nothing to cache there
|
|
334
|
-
if (meta.path) {
|
|
335
|
-
this.cache.set(meta.className + extname(meta.path), copy, meta.path);
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
303
|
initNullability(prop) {
|
|
339
|
-
if (prop.kind === ReferenceKind.MANY_TO_ONE) {
|
|
340
|
-
return Utils.defaultValue(prop, 'nullable', prop.optional || prop.cascade.includes(Cascade.REMOVE) || prop.cascade.includes(Cascade.ALL));
|
|
341
|
-
}
|
|
342
304
|
if (prop.kind === ReferenceKind.ONE_TO_ONE) {
|
|
343
|
-
return Utils.defaultValue(prop, 'nullable', prop.optional || !prop.owner
|
|
305
|
+
return Utils.defaultValue(prop, 'nullable', prop.optional || !prop.owner);
|
|
344
306
|
}
|
|
345
307
|
return Utils.defaultValue(prop, 'nullable', prop.optional);
|
|
346
308
|
}
|
|
@@ -375,7 +337,7 @@ export class MetadataDiscovery {
|
|
|
375
337
|
if (prop.joinColumns.length !== prop.columnTypes.length) {
|
|
376
338
|
prop.columnTypes = prop.joinColumns.flatMap(field => {
|
|
377
339
|
const matched = meta.props.find(p => p.fieldNames?.includes(field));
|
|
378
|
-
/* v8 ignore next
|
|
340
|
+
/* v8 ignore next */
|
|
379
341
|
if (!matched) {
|
|
380
342
|
throw MetadataError.fromWrongForeignKey(meta, prop, 'columnTypes');
|
|
381
343
|
}
|
|
@@ -497,10 +459,9 @@ export class MetadataDiscovery {
|
|
|
497
459
|
}
|
|
498
460
|
this.initOwnColumns(meta);
|
|
499
461
|
meta.simplePK = pks.length === 1 && pks[0].kind === ReferenceKind.SCALAR && !pks[0].customType && pks[0].runtimeType !== 'Date';
|
|
500
|
-
meta.serializedPrimaryKey
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
serializedPKProp.persist = false;
|
|
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;
|
|
504
465
|
}
|
|
505
466
|
if (this.platform.usesPivotTable()) {
|
|
506
467
|
return Object.values(meta.properties)
|
|
@@ -539,7 +500,7 @@ export class MetadataDiscovery {
|
|
|
539
500
|
}
|
|
540
501
|
else if (fks.length >= 2) {
|
|
541
502
|
[first, second] = fks;
|
|
542
|
-
/* v8 ignore next
|
|
503
|
+
/* v8 ignore next */
|
|
543
504
|
}
|
|
544
505
|
else {
|
|
545
506
|
return [];
|
|
@@ -618,7 +579,7 @@ export class MetadataDiscovery {
|
|
|
618
579
|
}
|
|
619
580
|
data.properties[meta.name + '_owner'] = this.definePivotProperty(prop, meta.name + '_owner', meta.className, targetType + '_inverse', true, meta.className === targetType);
|
|
620
581
|
data.properties[targetType + '_inverse'] = this.definePivotProperty(prop, targetType + '_inverse', targetType, meta.name + '_owner', false, meta.className === targetType);
|
|
621
|
-
return this.metadata.set(data.className, data);
|
|
582
|
+
return this.metadata.set(data.className, EntitySchema.fromMetadata(data).init().meta);
|
|
622
583
|
}
|
|
623
584
|
defineFixedOrderProperty(prop, targetType) {
|
|
624
585
|
const pk = prop.fixedOrderColumn || this.namingStrategy.referenceColumnName();
|
|
@@ -653,6 +614,7 @@ export class MetadataDiscovery {
|
|
|
653
614
|
autoincrement: false,
|
|
654
615
|
updateRule: prop.updateRule,
|
|
655
616
|
deleteRule: prop.deleteRule,
|
|
617
|
+
createForeignKeyConstraint: prop.createForeignKeyConstraint,
|
|
656
618
|
};
|
|
657
619
|
if (selfReferencing && !this.platform.supportsMultipleCascadePaths()) {
|
|
658
620
|
ret.updateRule ??= 'no action';
|
|
@@ -739,12 +701,9 @@ export class MetadataDiscovery {
|
|
|
739
701
|
Utils.keys(base.hooks).forEach(type => {
|
|
740
702
|
meta.hooks[type] = Utils.unique([...base.hooks[type], ...(meta.hooks[type] || [])]);
|
|
741
703
|
});
|
|
742
|
-
if (meta.constructorParams
|
|
704
|
+
if ((meta.constructorParams?.length ?? 0) === 0 && (base.constructorParams?.length ?? 0) > 0) {
|
|
743
705
|
meta.constructorParams = [...base.constructorParams];
|
|
744
706
|
}
|
|
745
|
-
if (meta.toJsonParams.length === 0 && base.toJsonParams.length > 0) {
|
|
746
|
-
meta.toJsonParams = [...base.toJsonParams];
|
|
747
|
-
}
|
|
748
707
|
return order;
|
|
749
708
|
}
|
|
750
709
|
initPolyEmbeddables(embeddedProp, discovered, visited = new Set()) {
|
|
@@ -765,6 +724,7 @@ export class MetadataDiscovery {
|
|
|
765
724
|
delete prop.default;
|
|
766
725
|
if (properties[prop.name] && properties[prop.name].type !== prop.type) {
|
|
767
726
|
properties[prop.name].type = `${properties[prop.name].type} | ${prop.type}`;
|
|
727
|
+
properties[prop.name].runtimeType = 'any';
|
|
768
728
|
return properties[prop.name];
|
|
769
729
|
}
|
|
770
730
|
return properties[prop.name] = prop;
|
|
@@ -819,9 +779,16 @@ export class MetadataDiscovery {
|
|
|
819
779
|
}
|
|
820
780
|
return prop.embedded ? isParentObject(meta.properties[prop.embedded[0]]) : false;
|
|
821
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
|
+
};
|
|
822
788
|
const rootProperty = getRootProperty(embeddedProp);
|
|
823
789
|
const parentProperty = meta.properties[embeddedProp.embedded?.[0] ?? ''];
|
|
824
790
|
const object = isParentObject(embeddedProp);
|
|
791
|
+
const array = isParentArray(embeddedProp);
|
|
825
792
|
this.initFieldName(embeddedProp, rootProperty !== embeddedProp && object);
|
|
826
793
|
// the prefix of the parent cannot be a boolean; it already passed here
|
|
827
794
|
const prefix = this.getPrefix(embeddedProp, parentProperty);
|
|
@@ -834,7 +801,8 @@ export class MetadataDiscovery {
|
|
|
834
801
|
meta.propertyOrder.set(name, (order += 0.01));
|
|
835
802
|
embeddedProp.embeddedProps[prop.name] = meta.properties[name];
|
|
836
803
|
meta.properties[name].persist ??= embeddedProp.persist;
|
|
837
|
-
|
|
804
|
+
const refInArray = array && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && prop.owner;
|
|
805
|
+
if (embeddedProp.nullable || refInArray) {
|
|
838
806
|
meta.properties[name].nullable = true;
|
|
839
807
|
}
|
|
840
808
|
if (meta.properties[name].fieldNames) {
|
|
@@ -872,6 +840,7 @@ export class MetadataDiscovery {
|
|
|
872
840
|
meta.properties[name].persist = false; // only virtual as we store the whole object
|
|
873
841
|
meta.properties[name].userDefined = false; // mark this as a generated/internal property, so we can distinguish from user-defined non-persist properties
|
|
874
842
|
meta.properties[name].object = true;
|
|
843
|
+
this.initCustomType(meta, meta.properties[name], false, true);
|
|
875
844
|
}
|
|
876
845
|
this.initEmbeddables(meta, meta.properties[name], visited);
|
|
877
846
|
}
|
|
@@ -924,7 +893,7 @@ export class MetadataDiscovery {
|
|
|
924
893
|
}
|
|
925
894
|
let i = 1;
|
|
926
895
|
Object.values(meta.properties).forEach(prop => {
|
|
927
|
-
const newProp =
|
|
896
|
+
const newProp = { ...prop };
|
|
928
897
|
if (meta.root.properties[prop.name] && meta.root.properties[prop.name].type !== prop.type) {
|
|
929
898
|
const name = newProp.name;
|
|
930
899
|
this.initFieldName(newProp, newProp.object);
|
|
@@ -940,7 +909,7 @@ export class MetadataDiscovery {
|
|
|
940
909
|
newProp.items = Utils.unique([...meta.root.properties[prop.name].items, ...prop.items]);
|
|
941
910
|
}
|
|
942
911
|
newProp.nullable = true;
|
|
943
|
-
newProp.inherited =
|
|
912
|
+
newProp.inherited = !meta.root.properties[prop.name];
|
|
944
913
|
meta.root.addProperty(newProp);
|
|
945
914
|
});
|
|
946
915
|
meta.collection = meta.root.collection;
|
|
@@ -965,7 +934,7 @@ export class MetadataDiscovery {
|
|
|
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 @@ export 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 @@ export 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
|
-
/* v8 ignore next
|
|
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
|
-
/* v8 ignore next 3 */
|
|
1032
994
|
if (!meta.class) {
|
|
1033
995
|
return;
|
|
1034
996
|
}
|
|
@@ -1064,7 +1026,7 @@ export class MetadataDiscovery {
|
|
|
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,13 +1054,13 @@ export 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
1065
|
if (Type.isMappedType(prop.type) && !prop.customType) {
|
|
1104
1066
|
prop.customType = prop.type;
|
|
@@ -1106,47 +1068,70 @@ export class MetadataDiscovery {
|
|
|
1106
1068
|
}
|
|
1107
1069
|
// `prop.type` might also be custom type class (not instance), so `typeof MyType` will give us `function`, not `object`
|
|
1108
1070
|
if (typeof prop.type === 'function' && Type.isMappedType(prop.type.prototype) && !prop.customType) {
|
|
1109
|
-
|
|
1110
|
-
|
|
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();
|
|
1114
1089
|
}
|
|
1115
1090
|
if (prop.kind === ReferenceKind.SCALAR && !prop.customType && prop.columnTypes && ['json', 'jsonb'].includes(prop.columnTypes[0])) {
|
|
1116
|
-
prop.customType = new
|
|
1091
|
+
prop.customType = new t.json();
|
|
1092
|
+
}
|
|
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,11 +1142,11 @@ export 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 (Type.isMappedType(prop.customType) && prop.kind === ReferenceKind.SCALAR && !
|
|
1149
|
+
if (Type.isMappedType(prop.customType) && prop.kind === ReferenceKind.SCALAR && !isArray) {
|
|
1165
1150
|
prop.type = prop.customType.name;
|
|
1166
1151
|
}
|
|
1167
1152
|
if (!prop.customType && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind) && this.metadata.get(prop.type).compositePK) {
|
|
@@ -1178,7 +1163,7 @@ export class MetadataDiscovery {
|
|
|
1178
1163
|
}
|
|
1179
1164
|
}
|
|
1180
1165
|
}
|
|
1181
|
-
if (prop.kind === ReferenceKind.SCALAR && !(mappedType instanceof
|
|
1166
|
+
if (prop.kind === ReferenceKind.SCALAR && !(mappedType instanceof t.unknown)) {
|
|
1182
1167
|
if (!prop.columnTypes && prop.nativeEnumName && meta.schema !== this.platform.getDefaultSchemaName() && meta.schema && !prop.nativeEnumName.includes('.')) {
|
|
1183
1168
|
prop.columnTypes = [`${meta.schema}.${prop.nativeEnumName}`];
|
|
1184
1169
|
}
|
|
@@ -1221,7 +1206,7 @@ export class MetadataDiscovery {
|
|
|
1221
1206
|
if (prop.kind === ReferenceKind.SCALAR) {
|
|
1222
1207
|
const mappedType = this.getMappedType(prop);
|
|
1223
1208
|
const SCALAR_TYPES = ['string', 'number', 'boolean', 'bigint', 'Date', 'Buffer', 'RegExp', 'any', 'unknown'];
|
|
1224
|
-
if (mappedType instanceof
|
|
1209
|
+
if (mappedType instanceof t.unknown
|
|
1225
1210
|
&& !prop.columnTypes
|
|
1226
1211
|
// it could be a runtime type from reflect-metadata
|
|
1227
1212
|
&& !SCALAR_TYPES.includes(prop.type)
|
|
@@ -1265,7 +1250,7 @@ export class MetadataDiscovery {
|
|
|
1265
1250
|
t = 'enum';
|
|
1266
1251
|
}
|
|
1267
1252
|
else if (prop.enum) {
|
|
1268
|
-
t = prop.items?.every(item =>
|
|
1253
|
+
t = prop.items?.every(item => typeof item === 'string') ? 'enum' : 'tinyint';
|
|
1269
1254
|
}
|
|
1270
1255
|
if (t === 'Date') {
|
|
1271
1256
|
t = 'datetime';
|
|
@@ -1304,30 +1289,6 @@ export class MetadataDiscovery {
|
|
|
1304
1289
|
prop.index ??= true;
|
|
1305
1290
|
}
|
|
1306
1291
|
}
|
|
1307
|
-
async getEntityClassOrSchema(path, name) {
|
|
1308
|
-
const exports = await Utils.dynamicImport(path);
|
|
1309
|
-
const targets = Object.values(exports)
|
|
1310
|
-
.filter(item => item instanceof EntitySchema || (item instanceof Function && MetadataStorage.isKnownEntity(item.name)));
|
|
1311
|
-
// ignore class implementations that are linked from an EntitySchema
|
|
1312
|
-
for (const item of targets) {
|
|
1313
|
-
if (item instanceof EntitySchema) {
|
|
1314
|
-
targets.forEach((item2, idx) => {
|
|
1315
|
-
if (item.meta.class === item2) {
|
|
1316
|
-
targets.splice(idx, 1);
|
|
1317
|
-
}
|
|
1318
|
-
});
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
if (targets.length > 0) {
|
|
1322
|
-
return targets;
|
|
1323
|
-
}
|
|
1324
|
-
const target = exports.default ?? exports[name];
|
|
1325
|
-
/* v8 ignore next 3 */
|
|
1326
|
-
if (!target) {
|
|
1327
|
-
throw MetadataError.entityNotFound(name, path.replace(this.config.get('baseDir'), '.'));
|
|
1328
|
-
}
|
|
1329
|
-
return [target];
|
|
1330
|
-
}
|
|
1331
1292
|
shouldForceConstructorUsage(meta) {
|
|
1332
1293
|
const forceConstructor = this.config.get('forceEntityConstructor');
|
|
1333
1294
|
if (Array.isArray(forceConstructor)) {
|