@mikro-orm/core 7.0.0-dev.76 → 7.0.0-dev.78
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.js +4 -4
- package/MikroORM.d.ts +29 -2
- package/MikroORM.js +69 -14
- package/cache/FileCacheAdapter.d.ts +1 -1
- package/cache/FileCacheAdapter.js +6 -4
- 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/drivers/DatabaseDriver.js +4 -4
- package/entity/Collection.js +2 -2
- package/entity/EntityAssigner.js +2 -2
- package/entity/EntityFactory.js +1 -1
- package/entity/EntityLoader.js +4 -4
- package/entity/Reference.js +1 -1
- package/entity/WrappedEntity.d.ts +2 -2
- package/entity/utils.js +1 -1
- package/entity/validators.js +1 -1
- package/hydration/Hydrator.js +1 -2
- package/hydration/ObjectHydrator.js +1 -1
- package/metadata/MetadataDiscovery.d.ts +0 -2
- package/metadata/MetadataDiscovery.js +7 -45
- package/metadata/MetadataProvider.d.ts +9 -0
- package/metadata/MetadataProvider.js +29 -2
- package/metadata/discover-entities.js +2 -1
- package/naming-strategy/AbstractNamingStrategy.js +1 -1
- package/not-supported.d.ts +1 -0
- package/not-supported.js +2 -1
- package/package.json +5 -1
- package/platforms/ExceptionConverter.js +1 -1
- package/platforms/Platform.js +8 -17
- package/serialization/EntitySerializer.js +3 -3
- package/serialization/SerializationContext.js +2 -2
- package/types/ArrayType.js +1 -1
- package/types/BigIntType.js +1 -1
- package/types/DecimalType.js +2 -2
- package/types/DoubleType.js +1 -1
- package/types/TinyIntType.js +1 -1
- package/types/Uint8ArrayType.js +1 -1
- package/typings.js +3 -3
- package/unit-of-work/UnitOfWork.js +1 -1
- package/utils/AbstractSchemaGenerator.js +1 -1
- package/utils/Configuration.d.ts +4 -24
- package/utils/Configuration.js +13 -50
- package/utils/ConfigurationLoader.d.ts +1 -13
- package/utils/ConfigurationLoader.js +1 -149
- package/utils/Cursor.js +1 -1
- package/utils/DataloaderUtils.js +2 -2
- package/utils/EntityComparator.js +4 -4
- package/utils/QueryHelper.js +1 -1
- package/utils/RawQueryFragment.js +1 -1
- package/utils/Utils.d.ts +0 -16
- package/utils/Utils.js +9 -89
- package/utils/clone.js +1 -1
- 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 +1 -1
- package/utils/index.js +1 -1
- package/utils/upsert-utils.js +3 -3
package/EntityManager.js
CHANGED
|
@@ -239,7 +239,7 @@ export class EntityManager {
|
|
|
239
239
|
if (options.populateWhere === PopulateHint.ALL) {
|
|
240
240
|
return { where: {}, populateWhere: options.populateWhere };
|
|
241
241
|
}
|
|
242
|
-
/* v8 ignore next
|
|
242
|
+
/* v8 ignore next */
|
|
243
243
|
if (options.populateWhere === PopulateHint.INFER) {
|
|
244
244
|
return { where, populateWhere: options.populateWhere };
|
|
245
245
|
}
|
|
@@ -977,7 +977,7 @@ export class EntityManager {
|
|
|
977
977
|
});
|
|
978
978
|
return this.comparator.matching(entityName, cond, tmp);
|
|
979
979
|
});
|
|
980
|
-
/* v8 ignore next
|
|
980
|
+
/* v8 ignore next */
|
|
981
981
|
if (!row) {
|
|
982
982
|
throw new Error(`Cannot find matching entity for condition ${JSON.stringify(cond)}`);
|
|
983
983
|
}
|
|
@@ -1000,7 +1000,7 @@ export class EntityManager {
|
|
|
1000
1000
|
}, {});
|
|
1001
1001
|
return this.comparator.matching(entityName, cond, pk);
|
|
1002
1002
|
});
|
|
1003
|
-
/* v8 ignore next
|
|
1003
|
+
/* v8 ignore next */
|
|
1004
1004
|
if (!row) {
|
|
1005
1005
|
throw new Error(`Cannot find matching entity for condition ${JSON.stringify(cond)}`);
|
|
1006
1006
|
}
|
|
@@ -1674,7 +1674,7 @@ export class EntityManager {
|
|
|
1674
1674
|
}
|
|
1675
1675
|
if (typeof options.populate !== 'boolean') {
|
|
1676
1676
|
options.populate = Utils.asArray(options.populate).map(field => {
|
|
1677
|
-
/* v8 ignore next
|
|
1677
|
+
/* v8 ignore next */
|
|
1678
1678
|
if (typeof field === 'boolean' || field === PopulatePath.ALL) {
|
|
1679
1679
|
return [{ field: meta.primaryKeys[0], strategy: options.strategy, all: !!field }]; //
|
|
1680
1680
|
}
|
package/MikroORM.d.ts
CHANGED
|
@@ -4,8 +4,35 @@ import { MetadataStorage } from './metadata/MetadataStorage.js';
|
|
|
4
4
|
import { Configuration, type Options } from './utils/Configuration.js';
|
|
5
5
|
import type { EntityManager } from './EntityManager.js';
|
|
6
6
|
import type { AnyEntity, Constructor, EntityClass, EntityMetadata, EntityName, IEntityGenerator, IMigrator, ISeedManager } from './typings.js';
|
|
7
|
+
/** @internal */
|
|
8
|
+
export declare function lookupExtensions(options: Options): Promise<void>;
|
|
7
9
|
/**
|
|
8
|
-
*
|
|
10
|
+
* The main class used to configure and bootstrap the ORM.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* // import from driver package
|
|
15
|
+
* import { MikroORM, defineEntity, p } from '@mikro-orm/sqlite';
|
|
16
|
+
*
|
|
17
|
+
* const User = defineEntity({
|
|
18
|
+
* name: 'User',
|
|
19
|
+
* properties: {
|
|
20
|
+
* id: p.integer().primary(),
|
|
21
|
+
* name: p.string(),
|
|
22
|
+
* },
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* const orm = new MikroORM({
|
|
26
|
+
* entities: [User],
|
|
27
|
+
* dbName: 'my.db',
|
|
28
|
+
* });
|
|
29
|
+
* await orm.schema.update();
|
|
30
|
+
*
|
|
31
|
+
* const em = orm.em.fork();
|
|
32
|
+
* const u1 = em.create(User, { name: 'John' });
|
|
33
|
+
* const u2 = em.create(User, { name: 'Ben' });
|
|
34
|
+
* await em.flush();
|
|
35
|
+
* ```
|
|
9
36
|
*/
|
|
10
37
|
export declare class MikroORM<Driver extends IDatabaseDriver = IDatabaseDriver, EM extends Driver[typeof EntityManagerType] & EntityManager<Driver> = Driver[typeof EntityManagerType] & EntityManager<Driver>, Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]> {
|
|
11
38
|
/** The global EntityManager instance. If you are using `RequestContext` helper, it will automatically pick the request specific context under the hood */
|
|
@@ -42,7 +69,7 @@ export declare class MikroORM<Driver extends IDatabaseDriver = IDatabaseDriver,
|
|
|
42
69
|
*/
|
|
43
70
|
isConnected(): Promise<boolean>;
|
|
44
71
|
/**
|
|
45
|
-
* Checks whether the database connection is active, returns .
|
|
72
|
+
* Checks whether the database connection is active, returns the reason if not.
|
|
46
73
|
*/
|
|
47
74
|
checkConnection(): Promise<{
|
|
48
75
|
ok: true;
|
package/MikroORM.js
CHANGED
|
@@ -1,11 +1,69 @@
|
|
|
1
1
|
import { MetadataDiscovery } from './metadata/MetadataDiscovery.js';
|
|
2
2
|
import { MetadataStorage } from './metadata/MetadataStorage.js';
|
|
3
3
|
import { Configuration } from './utils/Configuration.js';
|
|
4
|
-
import {
|
|
4
|
+
import { loadEnvironmentVars } from './utils/env-vars.js';
|
|
5
5
|
import { Utils } from './utils/Utils.js';
|
|
6
6
|
import { colors } from './logging/colors.js';
|
|
7
|
+
async function registerExtension(name, mod, extensions) {
|
|
8
|
+
/* v8 ignore next */
|
|
9
|
+
const resolved = await mod.catch(() => null);
|
|
10
|
+
const module = resolved?.[name];
|
|
11
|
+
/* v8 ignore else */
|
|
12
|
+
if (module) {
|
|
13
|
+
extensions.push(module);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** @internal */
|
|
17
|
+
export async function lookupExtensions(options) {
|
|
18
|
+
const extensions = options.extensions ?? [];
|
|
19
|
+
const exists = (name) => extensions.some(ext => ext.name === name);
|
|
20
|
+
if (!exists('SeedManager')) {
|
|
21
|
+
await registerExtension('SeedManager', import('@mikro-orm/seeder' + ''), extensions);
|
|
22
|
+
}
|
|
23
|
+
if (!exists('Migrator')) {
|
|
24
|
+
await registerExtension('Migrator', import('@mikro-orm/migrations' + ''), extensions);
|
|
25
|
+
}
|
|
26
|
+
/* v8 ignore if */
|
|
27
|
+
if (!exists('Migrator')) {
|
|
28
|
+
await registerExtension('Migrator', import('@mikro-orm/migrations-mongodb' + ''), extensions);
|
|
29
|
+
}
|
|
30
|
+
if (!exists('EntityGenerator')) {
|
|
31
|
+
await registerExtension('EntityGenerator', import('@mikro-orm/entity-generator' + ''), extensions);
|
|
32
|
+
}
|
|
33
|
+
options.extensions = extensions;
|
|
34
|
+
const metadataCacheEnabled = options.metadataCache?.enabled || options.metadataProvider?.useCache?.();
|
|
35
|
+
if (metadataCacheEnabled) {
|
|
36
|
+
options.metadataCache ??= {};
|
|
37
|
+
options.metadataCache.adapter ??= await import('@mikro-orm/core/fs-utils').then(m => m.FileCacheAdapter);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
7
40
|
/**
|
|
8
|
-
*
|
|
41
|
+
* The main class used to configure and bootstrap the ORM.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* // import from driver package
|
|
46
|
+
* import { MikroORM, defineEntity, p } from '@mikro-orm/sqlite';
|
|
47
|
+
*
|
|
48
|
+
* const User = defineEntity({
|
|
49
|
+
* name: 'User',
|
|
50
|
+
* properties: {
|
|
51
|
+
* id: p.integer().primary(),
|
|
52
|
+
* name: p.string(),
|
|
53
|
+
* },
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* const orm = new MikroORM({
|
|
57
|
+
* entities: [User],
|
|
58
|
+
* dbName: 'my.db',
|
|
59
|
+
* });
|
|
60
|
+
* await orm.schema.update();
|
|
61
|
+
*
|
|
62
|
+
* const em = orm.em.fork();
|
|
63
|
+
* const u1 = em.create(User, { name: 'John' });
|
|
64
|
+
* const u2 = em.create(User, { name: 'Ben' });
|
|
65
|
+
* await em.flush();
|
|
66
|
+
* ```
|
|
9
67
|
*/
|
|
10
68
|
export class MikroORM {
|
|
11
69
|
/** The global EntityManager instance. If you are using `RequestContext` helper, it will automatically pick the request specific context under the hood */
|
|
@@ -20,12 +78,14 @@ export class MikroORM {
|
|
|
20
78
|
* If you omit the `options` parameter, your CLI config will be used.
|
|
21
79
|
*/
|
|
22
80
|
static async init(options) {
|
|
23
|
-
/* v8 ignore next
|
|
81
|
+
/* v8 ignore next */
|
|
24
82
|
if (!options) {
|
|
25
83
|
throw new Error(`options parameter is required`);
|
|
26
84
|
}
|
|
85
|
+
options = { ...options };
|
|
27
86
|
options.discovery ??= {};
|
|
28
87
|
options.discovery.skipSyncDiscovery ??= true;
|
|
88
|
+
await lookupExtensions(options);
|
|
29
89
|
const orm = new this(options);
|
|
30
90
|
const preferTs = orm.config.get('preferTs', Utils.detectTypeScriptSupport());
|
|
31
91
|
orm.metadata = await orm.discovery.discover(preferTs);
|
|
@@ -39,14 +99,13 @@ export class MikroORM {
|
|
|
39
99
|
* - no support for folder based discovery
|
|
40
100
|
*/
|
|
41
101
|
constructor(options) {
|
|
42
|
-
const env =
|
|
43
|
-
const coreVersion = ConfigurationLoader.checkPackageVersion();
|
|
102
|
+
const env = loadEnvironmentVars();
|
|
44
103
|
options = Utils.merge(options, env);
|
|
45
104
|
this.config = new Configuration(options);
|
|
46
105
|
const discovery = this.config.get('discovery');
|
|
47
106
|
this.driver = this.config.getDriver();
|
|
48
107
|
this.logger = this.config.getLogger();
|
|
49
|
-
this.logger.log('info', `MikroORM version: ${colors.green(
|
|
108
|
+
this.logger.log('info', `MikroORM version: ${colors.green(Utils.getORMVersion())}`);
|
|
50
109
|
this.discovery = new MetadataDiscovery(new MetadataStorage(), this.driver.getPlatform(), this.config);
|
|
51
110
|
this.driver.getPlatform().init(this);
|
|
52
111
|
for (const extension of this.config.get('extensions')) {
|
|
@@ -68,7 +127,7 @@ export class MikroORM {
|
|
|
68
127
|
* Reconnects, possibly to a different database.
|
|
69
128
|
*/
|
|
70
129
|
async reconnect(options = {}) {
|
|
71
|
-
/* v8 ignore next
|
|
130
|
+
/* v8 ignore next */
|
|
72
131
|
for (const key of Utils.keys(options)) {
|
|
73
132
|
this.config.set(key, options[key]);
|
|
74
133
|
}
|
|
@@ -81,7 +140,7 @@ export class MikroORM {
|
|
|
81
140
|
return this.driver.getConnection().isConnected();
|
|
82
141
|
}
|
|
83
142
|
/**
|
|
84
|
-
* Checks whether the database connection is active, returns .
|
|
143
|
+
* Checks whether the database connection is active, returns the reason if not.
|
|
85
144
|
*/
|
|
86
145
|
async checkConnection() {
|
|
87
146
|
return this.driver.getConnection().checkConnection();
|
|
@@ -91,12 +150,8 @@ export class MikroORM {
|
|
|
91
150
|
*/
|
|
92
151
|
async close(force = false) {
|
|
93
152
|
await this.driver.close(force);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
if (this.config.getResultCacheAdapter()?.close) {
|
|
98
|
-
await this.config.getResultCacheAdapter().close();
|
|
99
|
-
}
|
|
153
|
+
await this.config.getMetadataCacheAdapter().close?.();
|
|
154
|
+
await this.config.getResultCacheAdapter().close?.();
|
|
100
155
|
}
|
|
101
156
|
/**
|
|
102
157
|
* Gets the `MetadataStorage` (without parameters) or `EntityMetadata` instance when provided with the `entityName` parameter.
|
|
@@ -8,7 +8,7 @@ export declare class FileCacheAdapter implements SyncCacheAdapter {
|
|
|
8
8
|
constructor(options: {
|
|
9
9
|
cacheDir: string;
|
|
10
10
|
combined?: boolean | string;
|
|
11
|
-
}, baseDir: string, pretty?: boolean);
|
|
11
|
+
} | undefined, baseDir: string, pretty?: boolean);
|
|
12
12
|
/**
|
|
13
13
|
* @inheritDoc
|
|
14
14
|
*/
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';
|
|
2
|
+
import { fs } from '../utils/fs-utils.js';
|
|
2
3
|
import { Utils } from '../utils/Utils.js';
|
|
3
4
|
export class FileCacheAdapter {
|
|
4
5
|
options;
|
|
@@ -6,10 +7,11 @@ export class FileCacheAdapter {
|
|
|
6
7
|
pretty;
|
|
7
8
|
VERSION = Utils.getORMVersion();
|
|
8
9
|
cache = {};
|
|
9
|
-
constructor(options, baseDir, pretty = false) {
|
|
10
|
+
constructor(options = {}, baseDir, pretty = false) {
|
|
10
11
|
this.options = options;
|
|
11
12
|
this.baseDir = baseDir;
|
|
12
13
|
this.pretty = pretty;
|
|
14
|
+
this.options.cacheDir ??= process.cwd() + '/temp';
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* @inheritDoc
|
|
@@ -19,7 +21,7 @@ export class FileCacheAdapter {
|
|
|
19
21
|
if (!existsSync(path)) {
|
|
20
22
|
return null;
|
|
21
23
|
}
|
|
22
|
-
const payload =
|
|
24
|
+
const payload = fs.readJSONSync(path);
|
|
23
25
|
const hash = this.getHash(payload.origin);
|
|
24
26
|
if (!hash || payload.hash !== hash) {
|
|
25
27
|
return null;
|
|
@@ -50,7 +52,7 @@ export class FileCacheAdapter {
|
|
|
50
52
|
*/
|
|
51
53
|
clear() {
|
|
52
54
|
const path = this.path('*');
|
|
53
|
-
const files =
|
|
55
|
+
const files = fs.glob(path);
|
|
54
56
|
files.forEach(file => unlinkSync(file));
|
|
55
57
|
this.cache = {};
|
|
56
58
|
}
|
|
@@ -67,7 +69,7 @@ export class FileCacheAdapter {
|
|
|
67
69
|
return path;
|
|
68
70
|
}
|
|
69
71
|
path(name) {
|
|
70
|
-
|
|
72
|
+
fs.ensureDir(this.options.cacheDir);
|
|
71
73
|
return `${this.options.cacheDir}/${name}.json`;
|
|
72
74
|
}
|
|
73
75
|
getHash(origin) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { CacheAdapter } from './CacheAdapter.js';
|
|
2
2
|
import type { Dictionary } from '../typings.js';
|
|
3
3
|
export declare class GeneratedCacheAdapter implements CacheAdapter {
|
|
4
|
-
private readonly options;
|
|
5
4
|
private readonly data;
|
|
6
5
|
constructor(options: {
|
|
7
6
|
data: Dictionary;
|
package/cache/index.d.ts
CHANGED
package/cache/index.js
CHANGED
|
@@ -31,11 +31,11 @@ export class DatabaseDriver {
|
|
|
31
31
|
const EntityManagerClass = this.config.get('entityManager', EntityManager);
|
|
32
32
|
return new EntityManagerClass(this.config, this, this.metadata, useContext);
|
|
33
33
|
}
|
|
34
|
-
/* v8 ignore next
|
|
34
|
+
/* v8 ignore next */
|
|
35
35
|
async findVirtual(entityName, where, options) {
|
|
36
36
|
throw new Error(`Virtual entities are not supported by ${this.constructor.name} driver.`);
|
|
37
37
|
}
|
|
38
|
-
/* v8 ignore next
|
|
38
|
+
/* v8 ignore next */
|
|
39
39
|
async countVirtual(entityName, where, options) {
|
|
40
40
|
throw new Error(`Counting virtual entities is not supported by ${this.constructor.name} driver.`);
|
|
41
41
|
}
|
|
@@ -53,7 +53,7 @@ export class DatabaseDriver {
|
|
|
53
53
|
}
|
|
54
54
|
continue;
|
|
55
55
|
}
|
|
56
|
-
/* v8 ignore next
|
|
56
|
+
/* v8 ignore next */
|
|
57
57
|
const pk = coll.property.targetMeta.primaryKeys[0];
|
|
58
58
|
const data = { [coll.property.name]: coll.getIdentifiers(pk) };
|
|
59
59
|
await this.nativeUpdate(coll.owner.constructor.name, helper(coll.owner).getPrimaryKey(), data, options);
|
|
@@ -253,7 +253,7 @@ export class DatabaseDriver {
|
|
|
253
253
|
return data;
|
|
254
254
|
}
|
|
255
255
|
inlineEmbeddables(meta, data, where) {
|
|
256
|
-
/* v8 ignore next
|
|
256
|
+
/* v8 ignore next */
|
|
257
257
|
if (data == null) {
|
|
258
258
|
return;
|
|
259
259
|
}
|
package/entity/Collection.js
CHANGED
|
@@ -18,7 +18,7 @@ export class Collection {
|
|
|
18
18
|
_populated;
|
|
19
19
|
constructor(owner, items, initialized = true) {
|
|
20
20
|
this.owner = owner;
|
|
21
|
-
/* v8 ignore next
|
|
21
|
+
/* v8 ignore next */
|
|
22
22
|
if (items) {
|
|
23
23
|
let i = 0;
|
|
24
24
|
this.items = new Set(items);
|
|
@@ -619,7 +619,7 @@ export class Collection {
|
|
|
619
619
|
get property() {
|
|
620
620
|
if (!this._property) {
|
|
621
621
|
const meta = wrap(this.owner, true).__meta;
|
|
622
|
-
/* v8 ignore next
|
|
622
|
+
/* v8 ignore next */
|
|
623
623
|
if (!meta) {
|
|
624
624
|
throw MetadataError.fromUnknownEntity(this.owner.constructor.name, 'Collection.property getter, maybe you just forgot to initialize the ORM?');
|
|
625
625
|
}
|
package/entity/EntityAssigner.js
CHANGED
|
@@ -120,7 +120,7 @@ export class EntityAssigner {
|
|
|
120
120
|
}
|
|
121
121
|
const meta2 = helper(ref).__meta;
|
|
122
122
|
const prop2 = meta2.properties[prop.inversedBy || prop.mappedBy];
|
|
123
|
-
/* v8 ignore next
|
|
123
|
+
/* v8 ignore next */
|
|
124
124
|
if (prop2 && !ref[prop2.name]) {
|
|
125
125
|
if (Reference.isReference(ref)) {
|
|
126
126
|
ref.unwrap()[prop2.name] = Reference.wrapReference(entity, prop2);
|
|
@@ -173,7 +173,7 @@ export class EntityAssigner {
|
|
|
173
173
|
}
|
|
174
174
|
return this.createCollectionItem(item, em, prop, invalid, options);
|
|
175
175
|
}
|
|
176
|
-
/* v8 ignore next
|
|
176
|
+
/* v8 ignore next */
|
|
177
177
|
if (options.updateNestedEntities && !options.updateByPrimaryKey && collection[idx] && helper(collection[idx])?.isInitialized()) {
|
|
178
178
|
return EntityAssigner.assign(collection[idx], item, options);
|
|
179
179
|
}
|
package/entity/EntityFactory.js
CHANGED
package/entity/EntityLoader.js
CHANGED
|
@@ -41,7 +41,7 @@ export class EntityLoader {
|
|
|
41
41
|
}
|
|
42
42
|
populate = this.normalizePopulate(entityName, populate, options.strategy, options.lookup);
|
|
43
43
|
const invalid = populate.find(({ field }) => !this.em.canPopulate(entityName, field));
|
|
44
|
-
/* v8 ignore next
|
|
44
|
+
/* v8 ignore next */
|
|
45
45
|
if (options.validate && invalid) {
|
|
46
46
|
throw ValidationError.invalidPropertyName(entityName, invalid.field);
|
|
47
47
|
}
|
|
@@ -463,7 +463,7 @@ export class EntityLoader {
|
|
|
463
463
|
const parts = f.toString().split('.');
|
|
464
464
|
const propName = parts.shift();
|
|
465
465
|
const childPropName = parts.join('.');
|
|
466
|
-
/* v8 ignore next
|
|
466
|
+
/* v8 ignore next */
|
|
467
467
|
if (propName === prop.name) {
|
|
468
468
|
ret.push(childPropName);
|
|
469
469
|
}
|
|
@@ -514,7 +514,7 @@ export class EntityLoader {
|
|
|
514
514
|
return wrapped.__loadedProperties.has(field);
|
|
515
515
|
}
|
|
516
516
|
const [f, ...r] = field.split('.');
|
|
517
|
-
/* v8 ignore next
|
|
517
|
+
/* v8 ignore next */
|
|
518
518
|
if (!wrapped.__loadedProperties.has(f) || !wrapped.__meta.properties[f]?.targetMeta) {
|
|
519
519
|
return false;
|
|
520
520
|
}
|
|
@@ -547,7 +547,7 @@ export class EntityLoader {
|
|
|
547
547
|
.map(e => Reference.unwrapReference(e[field]));
|
|
548
548
|
}
|
|
549
549
|
filterByReferences(entities, field, refresh) {
|
|
550
|
-
/* v8 ignore next
|
|
550
|
+
/* v8 ignore next */
|
|
551
551
|
if (refresh) {
|
|
552
552
|
return entities;
|
|
553
553
|
}
|
package/entity/Reference.js
CHANGED
|
@@ -213,8 +213,8 @@ export class ScalarReference {
|
|
|
213
213
|
isInitialized() {
|
|
214
214
|
return this.initialized;
|
|
215
215
|
}
|
|
216
|
-
/* v8 ignore next 4 */
|
|
217
216
|
/** @ignore */
|
|
217
|
+
/* v8 ignore next */
|
|
218
218
|
[inspect.custom]() {
|
|
219
219
|
return this.initialized ? `Ref<${inspect(this.value)}>` : `Ref<?>`;
|
|
220
220
|
}
|
|
@@ -59,8 +59,8 @@ export declare class WrappedEntity<Entity extends object> {
|
|
|
59
59
|
setPrimaryKey(id: Primary<Entity> | null): void;
|
|
60
60
|
getSerializedPrimaryKey(): string;
|
|
61
61
|
get __meta(): EntityMetadata<Entity>;
|
|
62
|
-
get __platform(): import("
|
|
63
|
-
get __config(): import("
|
|
62
|
+
get __platform(): import("@mikro-orm/knex").Platform;
|
|
63
|
+
get __config(): import("@mikro-orm/knex").Configuration<import("../drivers/IDatabaseDriver.js").IDatabaseDriver<import("@mikro-orm/knex").Connection>, EntityManager<import("../drivers/IDatabaseDriver.js").IDatabaseDriver<import("@mikro-orm/knex").Connection>>>;
|
|
64
64
|
get __primaryKeys(): Primary<Entity>[];
|
|
65
65
|
/** @ignore */
|
|
66
66
|
[inspect.custom](): string;
|
package/entity/utils.js
CHANGED
|
@@ -21,7 +21,7 @@ export function expandDotPaths(meta, populate, normalized = false) {
|
|
|
21
21
|
if (typeof field === 'string') {
|
|
22
22
|
return { field };
|
|
23
23
|
}
|
|
24
|
-
/* v8 ignore next
|
|
24
|
+
/* v8 ignore next */
|
|
25
25
|
return typeof field === 'boolean' || field.field === PopulatePath.ALL
|
|
26
26
|
? { all: !!field, field: meta.primaryKeys[0] }
|
|
27
27
|
: field;
|
package/entity/validators.js
CHANGED
|
@@ -11,7 +11,7 @@ export function validateProperty(prop, givenValue, entity) {
|
|
|
11
11
|
const propName = prop.embedded ? prop.name.replace(/~/g, '.') : prop.name;
|
|
12
12
|
const givenType = Utils.getObjectType(givenValue);
|
|
13
13
|
if (prop.enum && prop.items) {
|
|
14
|
-
/* v8 ignore next
|
|
14
|
+
/* v8 ignore next */
|
|
15
15
|
if (!prop.items.some(it => it === givenValue)) {
|
|
16
16
|
throw ValidationError.fromWrongPropertyType(entity, propName, expectedType, givenType, givenValue);
|
|
17
17
|
}
|
package/hydration/Hydrator.js
CHANGED
|
@@ -51,7 +51,7 @@ export class ObjectHydrator extends Hydrator {
|
|
|
51
51
|
context.set('Reference', Reference);
|
|
52
52
|
const registerCustomType = (prop, convertorKey, method, context) => {
|
|
53
53
|
context.set(`${method}_${convertorKey}`, (val) => {
|
|
54
|
-
/* v8 ignore next
|
|
54
|
+
/* v8 ignore next */
|
|
55
55
|
if (RawQueryFragment.isKnownFragment(val)) {
|
|
56
56
|
return val;
|
|
57
57
|
}
|
|
@@ -9,7 +9,6 @@ export declare class MetadataDiscovery {
|
|
|
9
9
|
private readonly config;
|
|
10
10
|
private readonly namingStrategy;
|
|
11
11
|
private readonly metadataProvider;
|
|
12
|
-
private readonly cache;
|
|
13
12
|
private readonly logger;
|
|
14
13
|
private readonly schemaHelper;
|
|
15
14
|
private readonly validator;
|
|
@@ -29,7 +28,6 @@ export declare class MetadataDiscovery {
|
|
|
29
28
|
private getSchema;
|
|
30
29
|
private getRootEntity;
|
|
31
30
|
private discoverEntity;
|
|
32
|
-
private saveToCache;
|
|
33
31
|
private initNullability;
|
|
34
32
|
private applyNamingStrategy;
|
|
35
33
|
private initOwnColumns;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { extname } from 'node:path';
|
|
2
1
|
import { EntityMetadata, } from '../typings.js';
|
|
3
2
|
import { Utils } from '../utils/Utils.js';
|
|
4
3
|
import { MetadataValidator } from './MetadataValidator.js';
|
|
@@ -15,7 +14,6 @@ export class MetadataDiscovery {
|
|
|
15
14
|
config;
|
|
16
15
|
namingStrategy;
|
|
17
16
|
metadataProvider;
|
|
18
|
-
cache;
|
|
19
17
|
logger;
|
|
20
18
|
schemaHelper;
|
|
21
19
|
validator = new MetadataValidator();
|
|
@@ -26,7 +24,6 @@ export class MetadataDiscovery {
|
|
|
26
24
|
this.config = config;
|
|
27
25
|
this.namingStrategy = this.config.getNamingStrategy();
|
|
28
26
|
this.metadataProvider = this.config.getMetadataProvider();
|
|
29
|
-
this.cache = this.config.getMetadataCacheAdapter();
|
|
30
27
|
this.logger = this.config.getLogger();
|
|
31
28
|
this.schemaHelper = this.platform.getSchemaHelper();
|
|
32
29
|
}
|
|
@@ -145,11 +142,7 @@ export class MetadataDiscovery {
|
|
|
145
142
|
discovered.push(...this.processEntity(meta));
|
|
146
143
|
}
|
|
147
144
|
discovered.forEach(meta => meta.sync(true));
|
|
148
|
-
|
|
149
|
-
// override the path in the options, so we can log it from the CLI in `cache:generate` command
|
|
150
|
-
if (combinedCachePath) {
|
|
151
|
-
this.config.get('metadataCache').combined = combinedCachePath;
|
|
152
|
-
}
|
|
145
|
+
this.metadataProvider.combineCache();
|
|
153
146
|
return discovered.map(meta => {
|
|
154
147
|
meta = this.metadata.get(meta.className);
|
|
155
148
|
meta.sync(true);
|
|
@@ -224,7 +217,7 @@ export class MetadataDiscovery {
|
|
|
224
217
|
if (typeof parent === 'function' && parent.name && !this.metadata.has(parent.name)) {
|
|
225
218
|
this.discoverReferences([parent], false);
|
|
226
219
|
}
|
|
227
|
-
/* v8 ignore next
|
|
220
|
+
/* v8 ignore next */
|
|
228
221
|
if (!meta.class) {
|
|
229
222
|
continue;
|
|
230
223
|
}
|
|
@@ -287,11 +280,9 @@ export class MetadataDiscovery {
|
|
|
287
280
|
this.logger.log('discovery', `- processing entity ${colors.cyan(meta.className)}${colors.grey(path ? ` (${path})` : '')}`);
|
|
288
281
|
const root = this.getRootEntity(meta);
|
|
289
282
|
schema.meta.path = Utils.relativePath(meta.path, this.config.get('baseDir'));
|
|
290
|
-
const cache = this.metadataProvider.
|
|
283
|
+
const cache = this.metadataProvider.getCachedMetadata(meta, root);
|
|
291
284
|
if (cache) {
|
|
292
285
|
this.logger.log('discovery', `- using cached metadata for entity ${colors.cyan(meta.className)}`);
|
|
293
|
-
this.metadataProvider.loadFromCache(meta, cache);
|
|
294
|
-
meta.root = root;
|
|
295
286
|
this.discovered.push(meta);
|
|
296
287
|
return;
|
|
297
288
|
}
|
|
@@ -305,39 +296,10 @@ export class MetadataDiscovery {
|
|
|
305
296
|
const entityName = root.discriminatorColumn ? root.name : meta.name;
|
|
306
297
|
meta.collection = this.namingStrategy.classToTableName(entityName);
|
|
307
298
|
}
|
|
308
|
-
|
|
309
|
-
this.saveToCache(meta);
|
|
299
|
+
this.metadataProvider.saveToCache(meta);
|
|
310
300
|
meta.root = root;
|
|
311
301
|
this.discovered.push(meta);
|
|
312
302
|
}
|
|
313
|
-
saveToCache(meta) {
|
|
314
|
-
if (!this.metadataProvider.useCache()) {
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
const copy = Utils.copy(meta, false);
|
|
318
|
-
for (const prop of copy.props) {
|
|
319
|
-
if (Type.isMappedType(prop.type)) {
|
|
320
|
-
Reflect.deleteProperty(prop, 'type');
|
|
321
|
-
Reflect.deleteProperty(prop, 'customType');
|
|
322
|
-
}
|
|
323
|
-
if (prop.default) {
|
|
324
|
-
const raw = RawQueryFragment.getKnownFragment(prop.default);
|
|
325
|
-
if (raw) {
|
|
326
|
-
prop.defaultRaw ??= this.platform.formatQuery(raw.sql, raw.params);
|
|
327
|
-
Reflect.deleteProperty(prop, 'default');
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
Reflect.deleteProperty(prop, 'targetMeta');
|
|
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 + extname(meta.path), copy, meta.path);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
303
|
initNullability(prop) {
|
|
342
304
|
if (prop.kind === ReferenceKind.ONE_TO_ONE) {
|
|
343
305
|
return Utils.defaultValue(prop, 'nullable', prop.optional || !prop.owner);
|
|
@@ -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
|
}
|
|
@@ -538,7 +500,7 @@ export class MetadataDiscovery {
|
|
|
538
500
|
}
|
|
539
501
|
else if (fks.length >= 2) {
|
|
540
502
|
[first, second] = fks;
|
|
541
|
-
/* v8 ignore next
|
|
503
|
+
/* v8 ignore next */
|
|
542
504
|
}
|
|
543
505
|
else {
|
|
544
506
|
return [];
|
|
@@ -1016,7 +978,7 @@ export class MetadataDiscovery {
|
|
|
1016
978
|
if (typeof prop.defaultRaw !== 'undefined') {
|
|
1017
979
|
return prop.defaultRaw;
|
|
1018
980
|
}
|
|
1019
|
-
/* v8 ignore next
|
|
981
|
+
/* v8 ignore next */
|
|
1020
982
|
if (prop.default != null) {
|
|
1021
983
|
return '' + this.platform.quoteVersionValue(prop.default, prop);
|
|
1022
984
|
}
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import type { EntityMetadata } from '../typings.js';
|
|
2
2
|
import type { Logger } from '../logging/Logger.js';
|
|
3
|
+
import type { SyncCacheAdapter } from '../cache/CacheAdapter.js';
|
|
4
|
+
import type { Platform } from '../platforms/Platform.js';
|
|
3
5
|
export interface IConfiguration {
|
|
4
6
|
get(key: string, defaultValue?: any): any;
|
|
5
7
|
getLogger(): Logger;
|
|
8
|
+
getMetadataCacheAdapter(): SyncCacheAdapter;
|
|
9
|
+
getPlatform(): Platform;
|
|
6
10
|
}
|
|
7
11
|
export declare class MetadataProvider {
|
|
8
12
|
protected readonly config: IConfiguration;
|
|
9
13
|
constructor(config: IConfiguration);
|
|
10
14
|
loadEntityMetadata(meta: EntityMetadata): void;
|
|
11
15
|
loadFromCache(meta: EntityMetadata, cache: EntityMetadata): void;
|
|
16
|
+
static useCache(): boolean;
|
|
12
17
|
useCache(): boolean;
|
|
18
|
+
saveToCache(meta: EntityMetadata): void;
|
|
19
|
+
getCachedMetadata<T>(meta: Pick<EntityMetadata<T>, 'className' | 'path' | 'root'>, root: EntityMetadata<T>): EntityMetadata<T> | undefined;
|
|
20
|
+
combineCache(): void;
|
|
21
|
+
getCacheKey(meta: Pick<EntityMetadata, 'className' | 'path'>): string;
|
|
13
22
|
}
|