@mikro-orm/core 7.0.0-dev.11 → 7.0.0-dev.111
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 +77 -48
- package/EntityManager.js +285 -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 +8 -7
- package/cache/GeneratedCacheAdapter.d.ts +0 -1
- package/cache/GeneratedCacheAdapter.js +0 -2
- package/cache/index.d.ts +0 -1
- package/cache/index.js +0 -1
- package/connections/Connection.d.ts +16 -7
- package/connections/Connection.js +23 -14
- package/drivers/DatabaseDriver.d.ts +14 -5
- package/drivers/DatabaseDriver.js +28 -11
- package/drivers/IDatabaseDriver.d.ts +25 -4
- package/entity/BaseEntity.d.ts +0 -1
- package/entity/BaseEntity.js +0 -3
- package/entity/Collection.d.ts +95 -30
- package/entity/Collection.js +432 -93
- package/entity/EntityAssigner.d.ts +1 -1
- package/entity/EntityAssigner.js +17 -9
- package/entity/EntityFactory.d.ts +7 -0
- package/entity/EntityFactory.js +63 -41
- package/entity/EntityHelper.js +28 -13
- package/entity/EntityLoader.d.ts +5 -4
- package/entity/EntityLoader.js +63 -38
- package/entity/EntityRepository.d.ts +1 -1
- package/entity/Reference.d.ts +6 -5
- package/entity/Reference.js +34 -9
- package/entity/WrappedEntity.d.ts +2 -7
- package/entity/WrappedEntity.js +2 -7
- package/entity/defineEntity.d.ts +568 -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 +10 -2
- package/errors.js +29 -10
- package/events/EventManager.d.ts +2 -1
- package/events/EventManager.js +19 -11
- package/hydration/Hydrator.js +1 -2
- package/hydration/ObjectHydrator.d.ts +4 -4
- package/hydration/ObjectHydrator.js +35 -25
- package/index.d.ts +2 -2
- package/index.js +1 -2
- package/logging/DefaultLogger.d.ts +1 -1
- package/logging/DefaultLogger.js +1 -0
- package/logging/SimpleLogger.d.ts +1 -1
- package/logging/colors.d.ts +1 -1
- package/logging/colors.js +7 -6
- package/logging/index.d.ts +1 -0
- package/logging/index.js +1 -0
- package/logging/inspect.d.ts +2 -0
- package/logging/inspect.js +11 -0
- package/metadata/EntitySchema.d.ts +9 -13
- package/metadata/EntitySchema.js +44 -26
- package/metadata/MetadataDiscovery.d.ts +6 -9
- package/metadata/MetadataDiscovery.js +170 -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 +0 -10
- 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 +19 -11
- package/platforms/ExceptionConverter.js +1 -1
- package/platforms/Platform.d.ts +6 -13
- package/platforms/Platform.js +15 -41
- 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/EnumArrayType.js +1 -2
- package/types/JsonType.d.ts +1 -1
- package/types/JsonType.js +7 -2
- package/types/TinyIntType.js +1 -1
- package/types/Type.d.ts +2 -4
- package/types/Type.js +3 -3
- package/types/Uint8ArrayType.d.ts +0 -1
- package/types/Uint8ArrayType.js +1 -4
- package/types/index.d.ts +1 -1
- package/typings.d.ts +109 -73
- package/typings.js +38 -35
- package/unit-of-work/ChangeSet.d.ts +0 -3
- package/unit-of-work/ChangeSet.js +2 -2
- 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 +51 -19
- package/unit-of-work/UnitOfWork.d.ts +8 -1
- package/unit-of-work/UnitOfWork.js +93 -51
- package/utils/AbstractSchemaGenerator.d.ts +5 -5
- package/utils/AbstractSchemaGenerator.js +11 -9
- package/utils/AsyncContext.d.ts +6 -0
- package/utils/AsyncContext.js +42 -0
- package/utils/Configuration.d.ts +757 -206
- package/utils/Configuration.js +145 -190
- package/utils/ConfigurationLoader.d.ts +1 -54
- package/utils/ConfigurationLoader.js +1 -352
- package/utils/Cursor.d.ts +0 -3
- package/utils/Cursor.js +6 -3
- package/utils/DataloaderUtils.d.ts +15 -5
- package/utils/DataloaderUtils.js +54 -8
- package/utils/EntityComparator.d.ts +8 -4
- package/utils/EntityComparator.js +52 -17
- package/utils/QueryHelper.d.ts +9 -1
- package/utils/QueryHelper.js +70 -9
- package/utils/RawQueryFragment.d.ts +36 -13
- package/utils/RawQueryFragment.js +38 -18
- package/utils/RequestContext.js +2 -2
- package/utils/TransactionContext.js +2 -2
- package/utils/TransactionManager.d.ts +65 -0
- package/utils/TransactionManager.js +223 -0
- package/utils/Utils.d.ts +9 -118
- package/utils/Utils.js +88 -372
- package/utils/clone.js +2 -3
- package/utils/env-vars.d.ts +7 -0
- package/utils/env-vars.js +98 -0
- package/utils/fs-utils.d.ts +32 -0
- package/utils/fs-utils.js +178 -0
- package/utils/index.d.ts +2 -1
- package/utils/index.js +2 -1
- package/utils/upsert-utils.d.ts +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,31 @@ 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 paths =
|
|
133
|
-
const
|
|
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
|
+
const paths = [];
|
|
157
|
+
for (const entity of targets) {
|
|
158
|
+
if (typeof entity === 'string') {
|
|
159
|
+
paths.push(entity);
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
165
|
+
if (paths.length > 0) {
|
|
166
|
+
const { discoverEntities } = await import('@mikro-orm/core/file-discovery');
|
|
167
|
+
processed.push(...await discoverEntities(paths, { baseDir }));
|
|
168
|
+
}
|
|
169
|
+
return this.discoverReferences(processed);
|
|
149
170
|
}
|
|
150
171
|
discoverMissingTargets() {
|
|
151
172
|
const unwrap = (type) => type
|
|
@@ -173,50 +194,20 @@ export class MetadataDiscovery {
|
|
|
173
194
|
}
|
|
174
195
|
tryDiscoverTargets(targets) {
|
|
175
196
|
for (const target of targets) {
|
|
176
|
-
|
|
177
|
-
|
|
197
|
+
const isDiscoverable = typeof target === 'function' || target instanceof EntitySchema;
|
|
198
|
+
if (isDiscoverable && target.name && !this.metadata.has(target.name)) {
|
|
199
|
+
this.discoverReferences([target], false);
|
|
178
200
|
this.discoverMissingTargets();
|
|
179
201
|
}
|
|
180
202
|
}
|
|
181
203
|
}
|
|
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) {
|
|
204
|
+
discoverReferences(refs, validate = true) {
|
|
217
205
|
const found = [];
|
|
218
206
|
for (const entity of refs) {
|
|
219
|
-
|
|
207
|
+
if (typeof entity === 'string') {
|
|
208
|
+
throw new Error('Folder based discovery requires the async `MikroORM.init()` method.');
|
|
209
|
+
}
|
|
210
|
+
const schema = this.getSchema(entity);
|
|
220
211
|
const meta = schema.init().meta;
|
|
221
212
|
this.metadata.set(meta.className, meta);
|
|
222
213
|
found.push(schema);
|
|
@@ -225,20 +216,27 @@ export class MetadataDiscovery {
|
|
|
225
216
|
for (const meta of this.metadata) {
|
|
226
217
|
let parent = meta.extends;
|
|
227
218
|
if (parent instanceof EntitySchema && !this.metadata.has(parent.meta.className)) {
|
|
228
|
-
this.discoverReferences([parent]);
|
|
219
|
+
this.discoverReferences([parent], false);
|
|
220
|
+
}
|
|
221
|
+
if (typeof parent === 'function' && parent.name && !this.metadata.has(parent.name)) {
|
|
222
|
+
this.discoverReferences([parent], false);
|
|
229
223
|
}
|
|
230
|
-
/* v8 ignore next
|
|
224
|
+
/* v8 ignore next */
|
|
231
225
|
if (!meta.class) {
|
|
232
226
|
continue;
|
|
233
227
|
}
|
|
234
228
|
parent = Object.getPrototypeOf(meta.class);
|
|
235
229
|
if (parent.name !== '' && !this.metadata.has(parent.name)) {
|
|
236
|
-
this.discoverReferences([parent]);
|
|
230
|
+
this.discoverReferences([parent], false);
|
|
237
231
|
}
|
|
238
232
|
}
|
|
239
233
|
for (const schema of found) {
|
|
240
234
|
this.discoverEntity(schema);
|
|
241
235
|
}
|
|
236
|
+
this.discoverMissingTargets();
|
|
237
|
+
if (validate) {
|
|
238
|
+
this.validateDiscovered(this.discovered);
|
|
239
|
+
}
|
|
242
240
|
return this.discovered.filter(meta => found.find(m => m.name === meta.className));
|
|
243
241
|
}
|
|
244
242
|
reset(className) {
|
|
@@ -248,28 +246,18 @@ export class MetadataDiscovery {
|
|
|
248
246
|
this.discovered.splice(exists, 1);
|
|
249
247
|
}
|
|
250
248
|
}
|
|
251
|
-
|
|
252
|
-
/* v8 ignore next 3 */
|
|
253
|
-
if ('schema' in entity && entity.schema instanceof EntitySchema) {
|
|
254
|
-
return entity.schema;
|
|
255
|
-
}
|
|
249
|
+
getSchema(entity) {
|
|
256
250
|
if (EntitySchema.REGISTRY.has(entity)) {
|
|
257
|
-
|
|
251
|
+
entity = EntitySchema.REGISTRY.get(entity);
|
|
258
252
|
}
|
|
259
|
-
return entity;
|
|
260
|
-
}
|
|
261
|
-
getSchema(entity, filepath) {
|
|
262
253
|
if (entity instanceof EntitySchema) {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
MetadataStorage.getMetadata(entity.meta.className, filepath);
|
|
266
|
-
}
|
|
267
|
-
return entity;
|
|
254
|
+
const meta = Utils.copy(entity.meta, false);
|
|
255
|
+
return EntitySchema.fromMetadata(meta);
|
|
268
256
|
}
|
|
269
257
|
const path = entity[MetadataStorage.PATH_SYMBOL];
|
|
270
258
|
if (path) {
|
|
271
259
|
const meta = Utils.copy(MetadataStorage.getMetadata(entity.name, path), false);
|
|
272
|
-
meta.path =
|
|
260
|
+
meta.path = path;
|
|
273
261
|
this.metadata.set(entity.name, meta);
|
|
274
262
|
}
|
|
275
263
|
const exists = this.metadata.has(entity.name);
|
|
@@ -279,16 +267,26 @@ export class MetadataDiscovery {
|
|
|
279
267
|
schema.setClass(entity);
|
|
280
268
|
return schema;
|
|
281
269
|
}
|
|
282
|
-
|
|
283
|
-
|
|
270
|
+
getRootEntity(meta) {
|
|
271
|
+
const base = meta.extends && this.metadata.find(Utils.className(meta.extends));
|
|
272
|
+
if (!base || base === meta) { // make sure we do not fall into infinite loop
|
|
273
|
+
return meta;
|
|
274
|
+
}
|
|
275
|
+
const root = this.getRootEntity(base);
|
|
276
|
+
if (root.discriminatorColumn) {
|
|
277
|
+
return root;
|
|
278
|
+
}
|
|
279
|
+
return meta;
|
|
280
|
+
}
|
|
281
|
+
discoverEntity(schema) {
|
|
284
282
|
const meta = schema.meta;
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
const
|
|
283
|
+
const path = meta.path;
|
|
284
|
+
this.logger.log('discovery', `- processing entity ${colors.cyan(meta.className)}${colors.grey(path ? ` (${path})` : '')}`);
|
|
285
|
+
const root = this.getRootEntity(meta);
|
|
286
|
+
schema.meta.path = meta.path;
|
|
287
|
+
const cache = this.metadataProvider.getCachedMetadata(meta, root);
|
|
288
288
|
if (cache) {
|
|
289
289
|
this.logger.log('discovery', `- using cached metadata for entity ${colors.cyan(meta.className)}`);
|
|
290
|
-
this.metadataProvider.loadFromCache(meta, cache);
|
|
291
|
-
meta.root = root;
|
|
292
290
|
this.discovered.push(meta);
|
|
293
291
|
return;
|
|
294
292
|
}
|
|
@@ -297,50 +295,18 @@ export class MetadataDiscovery {
|
|
|
297
295
|
this.inferDefaultValue(meta, prop);
|
|
298
296
|
}
|
|
299
297
|
// 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
|
|
298
|
+
this.metadataProvider.loadEntityMetadata(meta);
|
|
301
299
|
if (!meta.collection && meta.name) {
|
|
302
300
|
const entityName = root.discriminatorColumn ? root.name : meta.name;
|
|
303
301
|
meta.collection = this.namingStrategy.classToTableName(entityName);
|
|
304
302
|
}
|
|
305
|
-
|
|
306
|
-
this.saveToCache(meta);
|
|
303
|
+
this.metadataProvider.saveToCache(meta);
|
|
307
304
|
meta.root = root;
|
|
308
305
|
this.discovered.push(meta);
|
|
309
306
|
}
|
|
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
307
|
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
308
|
if (prop.kind === ReferenceKind.ONE_TO_ONE) {
|
|
343
|
-
return Utils.defaultValue(prop, 'nullable', prop.optional || !prop.owner
|
|
309
|
+
return Utils.defaultValue(prop, 'nullable', prop.optional || !prop.owner);
|
|
344
310
|
}
|
|
345
311
|
return Utils.defaultValue(prop, 'nullable', prop.optional);
|
|
346
312
|
}
|
|
@@ -375,7 +341,7 @@ export class MetadataDiscovery {
|
|
|
375
341
|
if (prop.joinColumns.length !== prop.columnTypes.length) {
|
|
376
342
|
prop.columnTypes = prop.joinColumns.flatMap(field => {
|
|
377
343
|
const matched = meta.props.find(p => p.fieldNames?.includes(field));
|
|
378
|
-
/* v8 ignore next
|
|
344
|
+
/* v8 ignore next */
|
|
379
345
|
if (!matched) {
|
|
380
346
|
throw MetadataError.fromWrongForeignKey(meta, prop, 'columnTypes');
|
|
381
347
|
}
|
|
@@ -497,10 +463,9 @@ export class MetadataDiscovery {
|
|
|
497
463
|
}
|
|
498
464
|
this.initOwnColumns(meta);
|
|
499
465
|
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;
|
|
466
|
+
meta.serializedPrimaryKey ??= meta.props.find(prop => prop.serializedPrimaryKey)?.name;
|
|
467
|
+
if (meta.serializedPrimaryKey && meta.serializedPrimaryKey !== meta.primaryKeys[0]) {
|
|
468
|
+
meta.properties[meta.serializedPrimaryKey].persist ??= false;
|
|
504
469
|
}
|
|
505
470
|
if (this.platform.usesPivotTable()) {
|
|
506
471
|
return Object.values(meta.properties)
|
|
@@ -539,7 +504,7 @@ export class MetadataDiscovery {
|
|
|
539
504
|
}
|
|
540
505
|
else if (fks.length >= 2) {
|
|
541
506
|
[first, second] = fks;
|
|
542
|
-
/* v8 ignore next
|
|
507
|
+
/* v8 ignore next */
|
|
543
508
|
}
|
|
544
509
|
else {
|
|
545
510
|
return [];
|
|
@@ -618,7 +583,7 @@ export class MetadataDiscovery {
|
|
|
618
583
|
}
|
|
619
584
|
data.properties[meta.name + '_owner'] = this.definePivotProperty(prop, meta.name + '_owner', meta.className, targetType + '_inverse', true, meta.className === targetType);
|
|
620
585
|
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);
|
|
586
|
+
return this.metadata.set(data.className, EntitySchema.fromMetadata(data).init().meta);
|
|
622
587
|
}
|
|
623
588
|
defineFixedOrderProperty(prop, targetType) {
|
|
624
589
|
const pk = prop.fixedOrderColumn || this.namingStrategy.referenceColumnName();
|
|
@@ -653,6 +618,7 @@ export class MetadataDiscovery {
|
|
|
653
618
|
autoincrement: false,
|
|
654
619
|
updateRule: prop.updateRule,
|
|
655
620
|
deleteRule: prop.deleteRule,
|
|
621
|
+
createForeignKeyConstraint: prop.createForeignKeyConstraint,
|
|
656
622
|
};
|
|
657
623
|
if (selfReferencing && !this.platform.supportsMultipleCascadePaths()) {
|
|
658
624
|
ret.updateRule ??= 'no action';
|
|
@@ -739,12 +705,9 @@ export class MetadataDiscovery {
|
|
|
739
705
|
Utils.keys(base.hooks).forEach(type => {
|
|
740
706
|
meta.hooks[type] = Utils.unique([...base.hooks[type], ...(meta.hooks[type] || [])]);
|
|
741
707
|
});
|
|
742
|
-
if (meta.constructorParams
|
|
708
|
+
if ((meta.constructorParams?.length ?? 0) === 0 && (base.constructorParams?.length ?? 0) > 0) {
|
|
743
709
|
meta.constructorParams = [...base.constructorParams];
|
|
744
710
|
}
|
|
745
|
-
if (meta.toJsonParams.length === 0 && base.toJsonParams.length > 0) {
|
|
746
|
-
meta.toJsonParams = [...base.toJsonParams];
|
|
747
|
-
}
|
|
748
711
|
return order;
|
|
749
712
|
}
|
|
750
713
|
initPolyEmbeddables(embeddedProp, discovered, visited = new Set()) {
|
|
@@ -820,9 +783,16 @@ export class MetadataDiscovery {
|
|
|
820
783
|
}
|
|
821
784
|
return prop.embedded ? isParentObject(meta.properties[prop.embedded[0]]) : false;
|
|
822
785
|
};
|
|
786
|
+
const isParentArray = (prop) => {
|
|
787
|
+
if (prop.array) {
|
|
788
|
+
return true;
|
|
789
|
+
}
|
|
790
|
+
return prop.embedded ? isParentArray(meta.properties[prop.embedded[0]]) : false;
|
|
791
|
+
};
|
|
823
792
|
const rootProperty = getRootProperty(embeddedProp);
|
|
824
793
|
const parentProperty = meta.properties[embeddedProp.embedded?.[0] ?? ''];
|
|
825
794
|
const object = isParentObject(embeddedProp);
|
|
795
|
+
const array = isParentArray(embeddedProp);
|
|
826
796
|
this.initFieldName(embeddedProp, rootProperty !== embeddedProp && object);
|
|
827
797
|
// the prefix of the parent cannot be a boolean; it already passed here
|
|
828
798
|
const prefix = this.getPrefix(embeddedProp, parentProperty);
|
|
@@ -835,7 +805,8 @@ export class MetadataDiscovery {
|
|
|
835
805
|
meta.propertyOrder.set(name, (order += 0.01));
|
|
836
806
|
embeddedProp.embeddedProps[prop.name] = meta.properties[name];
|
|
837
807
|
meta.properties[name].persist ??= embeddedProp.persist;
|
|
838
|
-
|
|
808
|
+
const refInArray = array && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && prop.owner;
|
|
809
|
+
if (embeddedProp.nullable || refInArray) {
|
|
839
810
|
meta.properties[name].nullable = true;
|
|
840
811
|
}
|
|
841
812
|
if (meta.properties[name].fieldNames) {
|
|
@@ -873,6 +844,7 @@ export class MetadataDiscovery {
|
|
|
873
844
|
meta.properties[name].persist = false; // only virtual as we store the whole object
|
|
874
845
|
meta.properties[name].userDefined = false; // mark this as a generated/internal property, so we can distinguish from user-defined non-persist properties
|
|
875
846
|
meta.properties[name].object = true;
|
|
847
|
+
this.initCustomType(meta, meta.properties[name], false, true);
|
|
876
848
|
}
|
|
877
849
|
this.initEmbeddables(meta, meta.properties[name], visited);
|
|
878
850
|
}
|
|
@@ -941,7 +913,7 @@ export class MetadataDiscovery {
|
|
|
941
913
|
newProp.items = Utils.unique([...meta.root.properties[prop.name].items, ...prop.items]);
|
|
942
914
|
}
|
|
943
915
|
newProp.nullable = true;
|
|
944
|
-
newProp.inherited =
|
|
916
|
+
newProp.inherited = !meta.root.properties[prop.name];
|
|
945
917
|
meta.root.addProperty(newProp);
|
|
946
918
|
});
|
|
947
919
|
meta.collection = meta.root.collection;
|
|
@@ -966,7 +938,7 @@ export class MetadataDiscovery {
|
|
|
966
938
|
}
|
|
967
939
|
}
|
|
968
940
|
initCheckConstraints(meta) {
|
|
969
|
-
const map =
|
|
941
|
+
const map = meta.createColumnMappingObject();
|
|
970
942
|
for (const check of meta.checks) {
|
|
971
943
|
const columns = check.property ? meta.properties[check.property].fieldNames : [];
|
|
972
944
|
check.name ??= this.namingStrategy.indexName(meta.tableName, columns, 'check');
|
|
@@ -976,7 +948,7 @@ export class MetadataDiscovery {
|
|
|
976
948
|
}
|
|
977
949
|
if (this.platform.usesEnumCheckConstraints() && !meta.embeddable) {
|
|
978
950
|
for (const prop of meta.props) {
|
|
979
|
-
if (prop.enum && !prop.nativeEnumName && prop.items?.every(item =>
|
|
951
|
+
if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => typeof item === 'string')) {
|
|
980
952
|
this.initFieldName(prop);
|
|
981
953
|
meta.checks.push({
|
|
982
954
|
name: this.namingStrategy.indexName(meta.tableName, prop.fieldNames, 'check'),
|
|
@@ -1001,35 +973,28 @@ export class MetadataDiscovery {
|
|
|
1001
973
|
}
|
|
1002
974
|
return;
|
|
1003
975
|
}
|
|
1004
|
-
const map =
|
|
976
|
+
const map = meta.createColumnMappingObject();
|
|
1005
977
|
if (prop.generated instanceof Function) {
|
|
1006
978
|
prop.generated = prop.generated(map);
|
|
1007
979
|
}
|
|
1008
980
|
}
|
|
1009
|
-
|
|
1010
|
-
return Object.values(meta.properties).reduce((o, prop) => {
|
|
1011
|
-
if (prop.fieldNames) {
|
|
1012
|
-
o[prop.name] = prop.fieldNames[0];
|
|
1013
|
-
}
|
|
1014
|
-
return o;
|
|
1015
|
-
}, {});
|
|
1016
|
-
}
|
|
1017
|
-
getDefaultVersionValue(prop) {
|
|
981
|
+
getDefaultVersionValue(meta, prop) {
|
|
1018
982
|
if (typeof prop.defaultRaw !== 'undefined') {
|
|
1019
983
|
return prop.defaultRaw;
|
|
1020
984
|
}
|
|
1021
|
-
/* v8 ignore next
|
|
985
|
+
/* v8 ignore next */
|
|
1022
986
|
if (prop.default != null) {
|
|
1023
987
|
return '' + this.platform.quoteVersionValue(prop.default, prop);
|
|
1024
988
|
}
|
|
1025
|
-
|
|
989
|
+
this.initCustomType(meta, prop, true);
|
|
990
|
+
const type = prop.customType?.runtimeType ?? prop.runtimeType ?? prop.type;
|
|
991
|
+
if (type === 'Date') {
|
|
1026
992
|
prop.length ??= this.platform.getDefaultVersionLength();
|
|
1027
993
|
return this.platform.getCurrentTimestampSQL(prop.length);
|
|
1028
994
|
}
|
|
1029
995
|
return '1';
|
|
1030
996
|
}
|
|
1031
997
|
inferDefaultValue(meta, prop) {
|
|
1032
|
-
/* v8 ignore next 3 */
|
|
1033
998
|
if (!meta.class) {
|
|
1034
999
|
return;
|
|
1035
1000
|
}
|
|
@@ -1065,7 +1030,7 @@ export class MetadataDiscovery {
|
|
|
1065
1030
|
prop.defaultRaw = this.platform.formatQuery(raw.sql, raw.params);
|
|
1066
1031
|
return;
|
|
1067
1032
|
}
|
|
1068
|
-
if (
|
|
1033
|
+
if (Array.isArray(prop.default) && prop.customType) {
|
|
1069
1034
|
val = prop.customType.convertToDatabaseValue(prop.default, this.platform);
|
|
1070
1035
|
}
|
|
1071
1036
|
prop.defaultRaw = typeof val === 'string' ? `'${val}'` : '' + val;
|
|
@@ -1093,13 +1058,13 @@ export class MetadataDiscovery {
|
|
|
1093
1058
|
if (prop.version) {
|
|
1094
1059
|
this.initDefaultValue(prop);
|
|
1095
1060
|
meta.versionProperty = prop.name;
|
|
1096
|
-
prop.defaultRaw = this.getDefaultVersionValue(prop);
|
|
1061
|
+
prop.defaultRaw = this.getDefaultVersionValue(meta, prop);
|
|
1097
1062
|
}
|
|
1098
1063
|
if (prop.concurrencyCheck && !prop.primary) {
|
|
1099
1064
|
meta.concurrencyCheckKeys.add(prop.name);
|
|
1100
1065
|
}
|
|
1101
1066
|
}
|
|
1102
|
-
initCustomType(meta, prop) {
|
|
1067
|
+
initCustomType(meta, prop, simple = false, objectEmbeddable = false) {
|
|
1103
1068
|
// `prop.type` might be actually instance of custom type class
|
|
1104
1069
|
if (Type.isMappedType(prop.type) && !prop.customType) {
|
|
1105
1070
|
prop.customType = prop.type;
|
|
@@ -1107,47 +1072,70 @@ export class MetadataDiscovery {
|
|
|
1107
1072
|
}
|
|
1108
1073
|
// `prop.type` might also be custom type class (not instance), so `typeof MyType` will give us `function`, not `object`
|
|
1109
1074
|
if (typeof prop.type === 'function' && Type.isMappedType(prop.type.prototype) && !prop.customType) {
|
|
1110
|
-
|
|
1111
|
-
|
|
1075
|
+
// if the type is an ORM defined mapped type without `ensureComparable: true`,
|
|
1076
|
+
// we use just the type name, to have more performant hydration code
|
|
1077
|
+
const type = Utils.keys(t).find(type => {
|
|
1078
|
+
return !Type.getType(t[type]).ensureComparable(meta, prop) && prop.type === t[type];
|
|
1079
|
+
});
|
|
1080
|
+
if (type) {
|
|
1081
|
+
prop.type = type === 'datetime' ? 'Date' : type;
|
|
1082
|
+
}
|
|
1083
|
+
else {
|
|
1084
|
+
prop.customType = new prop.type();
|
|
1085
|
+
prop.type = prop.customType.constructor.name;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
if (simple) {
|
|
1089
|
+
return;
|
|
1112
1090
|
}
|
|
1113
1091
|
if (!prop.customType && ['json', 'jsonb'].includes(prop.type?.toLowerCase())) {
|
|
1114
|
-
prop.customType = new
|
|
1092
|
+
prop.customType = new t.json();
|
|
1115
1093
|
}
|
|
1116
1094
|
if (prop.kind === ReferenceKind.SCALAR && !prop.customType && prop.columnTypes && ['json', 'jsonb'].includes(prop.columnTypes[0])) {
|
|
1117
|
-
prop.customType = new
|
|
1095
|
+
prop.customType = new t.json();
|
|
1096
|
+
}
|
|
1097
|
+
if (prop.kind === ReferenceKind.EMBEDDED && !prop.customType && (prop.object || prop.array)) {
|
|
1098
|
+
prop.customType = new t.json();
|
|
1118
1099
|
}
|
|
1119
1100
|
if (!prop.customType && prop.array && prop.items) {
|
|
1120
|
-
prop.customType = new
|
|
1101
|
+
prop.customType = new t.enumArray(`${meta.className}.${prop.name}`, prop.items);
|
|
1102
|
+
}
|
|
1103
|
+
const isArray = prop.type?.toLowerCase() === 'array' || prop.type?.toString().endsWith('[]');
|
|
1104
|
+
if (objectEmbeddable && !prop.customType && isArray) {
|
|
1105
|
+
prop.customType = new t.json();
|
|
1121
1106
|
}
|
|
1122
1107
|
// for number arrays we make sure to convert the items to numbers
|
|
1123
1108
|
if (!prop.customType && prop.type === 'number[]') {
|
|
1124
|
-
prop.customType = new
|
|
1109
|
+
prop.customType = new t.array(i => +i);
|
|
1125
1110
|
}
|
|
1126
1111
|
// `string[]` can be returned via ts-morph, while reflect metadata will give us just `array`
|
|
1127
|
-
if (!prop.customType &&
|
|
1128
|
-
prop.customType = new
|
|
1112
|
+
if (!prop.customType && isArray) {
|
|
1113
|
+
prop.customType = new t.array();
|
|
1129
1114
|
}
|
|
1130
1115
|
if (!prop.customType && prop.type?.toLowerCase() === 'buffer') {
|
|
1131
|
-
prop.customType = new
|
|
1116
|
+
prop.customType = new t.blob();
|
|
1132
1117
|
}
|
|
1133
1118
|
if (!prop.customType && prop.type?.toLowerCase() === 'uint8array') {
|
|
1134
|
-
prop.customType = new
|
|
1119
|
+
prop.customType = new t.uint8array();
|
|
1135
1120
|
}
|
|
1136
1121
|
const mappedType = this.getMappedType(prop);
|
|
1137
1122
|
if (prop.fieldNames?.length === 1 && !prop.customType) {
|
|
1138
|
-
[
|
|
1123
|
+
[t.bigint, t.double, t.decimal, t.interval, t.date]
|
|
1139
1124
|
.filter(type => mappedType instanceof type)
|
|
1140
|
-
.forEach(type => prop.customType = new type());
|
|
1125
|
+
.forEach((type) => prop.customType = new type());
|
|
1141
1126
|
}
|
|
1142
1127
|
if (prop.customType && !prop.columnTypes) {
|
|
1143
1128
|
const mappedType = this.getMappedType({ columnTypes: [prop.customType.getColumnType(prop, this.platform)] });
|
|
1144
|
-
if (prop.customType.compareAsType() === 'any' && ![
|
|
1129
|
+
if (prop.customType.compareAsType() === 'any' && ![t.json].some(t => prop.customType instanceof t)) {
|
|
1145
1130
|
prop.runtimeType ??= mappedType.runtimeType;
|
|
1146
1131
|
}
|
|
1147
1132
|
else {
|
|
1148
1133
|
prop.runtimeType ??= prop.customType.runtimeType;
|
|
1149
1134
|
}
|
|
1150
1135
|
}
|
|
1136
|
+
else if (prop.runtimeType === 'object') {
|
|
1137
|
+
prop.runtimeType = mappedType.runtimeType;
|
|
1138
|
+
}
|
|
1151
1139
|
else {
|
|
1152
1140
|
prop.runtimeType ??= mappedType.runtimeType;
|
|
1153
1141
|
}
|
|
@@ -1158,11 +1146,11 @@ export class MetadataDiscovery {
|
|
|
1158
1146
|
prop.columnTypes ??= [prop.customType.getColumnType(prop, this.platform)];
|
|
1159
1147
|
prop.hasConvertToJSValueSQL = !!prop.customType.convertToJSValueSQL && prop.customType.convertToJSValueSQL('', this.platform) !== '';
|
|
1160
1148
|
prop.hasConvertToDatabaseValueSQL = !!prop.customType.convertToDatabaseValueSQL && prop.customType.convertToDatabaseValueSQL('', this.platform) !== '';
|
|
1161
|
-
if (prop.customType instanceof
|
|
1149
|
+
if (prop.customType instanceof t.bigint && ['string', 'bigint', 'number'].includes(prop.runtimeType.toLowerCase())) {
|
|
1162
1150
|
prop.customType.mode = prop.runtimeType.toLowerCase();
|
|
1163
1151
|
}
|
|
1164
1152
|
}
|
|
1165
|
-
if (Type.isMappedType(prop.customType) && prop.kind === ReferenceKind.SCALAR && !
|
|
1153
|
+
if (Type.isMappedType(prop.customType) && prop.kind === ReferenceKind.SCALAR && !isArray) {
|
|
1166
1154
|
prop.type = prop.customType.name;
|
|
1167
1155
|
}
|
|
1168
1156
|
if (!prop.customType && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind) && this.metadata.get(prop.type).compositePK) {
|
|
@@ -1179,7 +1167,7 @@ export class MetadataDiscovery {
|
|
|
1179
1167
|
}
|
|
1180
1168
|
}
|
|
1181
1169
|
}
|
|
1182
|
-
if (prop.kind === ReferenceKind.SCALAR && !(mappedType instanceof
|
|
1170
|
+
if (prop.kind === ReferenceKind.SCALAR && !(mappedType instanceof t.unknown)) {
|
|
1183
1171
|
if (!prop.columnTypes && prop.nativeEnumName && meta.schema !== this.platform.getDefaultSchemaName() && meta.schema && !prop.nativeEnumName.includes('.')) {
|
|
1184
1172
|
prop.columnTypes = [`${meta.schema}.${prop.nativeEnumName}`];
|
|
1185
1173
|
}
|
|
@@ -1222,7 +1210,7 @@ export class MetadataDiscovery {
|
|
|
1222
1210
|
if (prop.kind === ReferenceKind.SCALAR) {
|
|
1223
1211
|
const mappedType = this.getMappedType(prop);
|
|
1224
1212
|
const SCALAR_TYPES = ['string', 'number', 'boolean', 'bigint', 'Date', 'Buffer', 'RegExp', 'any', 'unknown'];
|
|
1225
|
-
if (mappedType instanceof
|
|
1213
|
+
if (mappedType instanceof t.unknown
|
|
1226
1214
|
&& !prop.columnTypes
|
|
1227
1215
|
// it could be a runtime type from reflect-metadata
|
|
1228
1216
|
&& !SCALAR_TYPES.includes(prop.type)
|
|
@@ -1266,7 +1254,7 @@ export class MetadataDiscovery {
|
|
|
1266
1254
|
t = 'enum';
|
|
1267
1255
|
}
|
|
1268
1256
|
else if (prop.enum) {
|
|
1269
|
-
t = prop.items?.every(item =>
|
|
1257
|
+
t = prop.items?.every(item => typeof item === 'string') ? 'enum' : 'tinyint';
|
|
1270
1258
|
}
|
|
1271
1259
|
if (t === 'Date') {
|
|
1272
1260
|
t = 'datetime';
|
|
@@ -1305,30 +1293,6 @@ export class MetadataDiscovery {
|
|
|
1305
1293
|
prop.index ??= true;
|
|
1306
1294
|
}
|
|
1307
1295
|
}
|
|
1308
|
-
async getEntityClassOrSchema(path, name) {
|
|
1309
|
-
const exports = await Utils.dynamicImport(path);
|
|
1310
|
-
const targets = Object.values(exports)
|
|
1311
|
-
.filter(item => item instanceof EntitySchema || (item instanceof Function && MetadataStorage.isKnownEntity(item.name)));
|
|
1312
|
-
// ignore class implementations that are linked from an EntitySchema
|
|
1313
|
-
for (const item of targets) {
|
|
1314
|
-
if (item instanceof EntitySchema) {
|
|
1315
|
-
targets.forEach((item2, idx) => {
|
|
1316
|
-
if (item.meta.class === item2) {
|
|
1317
|
-
targets.splice(idx, 1);
|
|
1318
|
-
}
|
|
1319
|
-
});
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
if (targets.length > 0) {
|
|
1323
|
-
return targets;
|
|
1324
|
-
}
|
|
1325
|
-
const target = exports.default ?? exports[name];
|
|
1326
|
-
/* v8 ignore next 3 */
|
|
1327
|
-
if (!target) {
|
|
1328
|
-
throw MetadataError.entityNotFound(name, path.replace(this.config.get('baseDir'), '.'));
|
|
1329
|
-
}
|
|
1330
|
-
return [target];
|
|
1331
|
-
}
|
|
1332
1296
|
shouldForceConstructorUsage(meta) {
|
|
1333
1297
|
const forceConstructor = this.config.get('forceEntityConstructor');
|
|
1334
1298
|
if (Array.isArray(forceConstructor)) {
|