@mikro-orm/core 7.0.0-dev.42 → 7.0.0-dev.44
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 +2 -14
- package/EntityManager.js +24 -5
- package/MikroORM.d.ts +1 -2
- package/MikroORM.js +21 -58
- package/connections/Connection.d.ts +5 -3
- package/connections/Connection.js +14 -11
- package/decorators/Property.d.ts +0 -6
- package/drivers/DatabaseDriver.d.ts +6 -2
- package/drivers/DatabaseDriver.js +4 -4
- package/drivers/IDatabaseDriver.d.ts +6 -2
- package/entity/ArrayCollection.d.ts +2 -2
- package/entity/ArrayCollection.js +8 -3
- package/entity/BaseEntity.d.ts +0 -1
- package/entity/BaseEntity.js +0 -3
- package/entity/Collection.d.ts +2 -2
- package/entity/Collection.js +18 -7
- package/entity/EntityFactory.js +0 -2
- package/entity/EntityHelper.js +2 -7
- package/entity/WrappedEntity.d.ts +0 -2
- package/entity/WrappedEntity.js +0 -4
- package/entity/defineEntity.d.ts +0 -6
- package/entity/defineEntity.js +0 -8
- package/metadata/MetadataDiscovery.d.ts +1 -1
- package/metadata/MetadataDiscovery.js +2 -7
- package/package.json +2 -2
- package/serialization/EntitySerializer.js +21 -3
- package/serialization/EntityTransformer.js +15 -5
- package/typings.d.ts +4 -6
- package/typings.js +7 -27
- package/unit-of-work/ChangeSetComputer.js +5 -2
- package/unit-of-work/UnitOfWork.js +3 -14
- package/utils/AbstractSchemaGenerator.js +3 -1
- package/utils/Configuration.d.ts +2 -7
- package/utils/Configuration.js +2 -12
- package/utils/ConfigurationLoader.d.ts +2 -18
- package/utils/ConfigurationLoader.js +8 -32
- package/utils/RawQueryFragment.d.ts +0 -2
- package/utils/RawQueryFragment.js +0 -13
- package/utils/TransactionManager.js +8 -3
- package/utils/Utils.d.ts +0 -4
- package/utils/Utils.js +0 -20
package/EntityManager.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { EntityLoader, type EntityLoaderOptions } from './entity/EntityLoader.js
|
|
|
10
10
|
import { Reference } from './entity/Reference.js';
|
|
11
11
|
import { UnitOfWork } from './unit-of-work/UnitOfWork.js';
|
|
12
12
|
import type { CountOptions, DeleteOptions, FilterOptions, FindAllOptions, FindByCursorOptions, FindOneOptions, FindOneOrFailOptions, FindOptions, GetReferenceOptions, IDatabaseDriver, LockOptions, NativeInsertUpdateOptions, StreamOptions, UpdateOptions, UpsertManyOptions, UpsertOptions } from './drivers/IDatabaseDriver.js';
|
|
13
|
-
import type { AnyEntity, AnyString, ArrayElement, AutoPath, ConnectionType, Dictionary, EntityData, EntityDictionary, EntityDTO, EntityMetadata, EntityName, FilterDef, FilterQuery, FromEntityType, GetRepository, IHydrator, IsSubset, Loaded,
|
|
13
|
+
import type { AnyEntity, AnyString, ArrayElement, AutoPath, ConnectionType, Dictionary, EntityData, EntityDictionary, EntityDTO, EntityMetadata, EntityName, FilterDef, FilterQuery, FromEntityType, GetRepository, IHydrator, IsSubset, Loaded, MergeLoaded, MergeSelected, NoInfer, ObjectQuery, Primary, Ref, RequiredEntityData, UnboxArray } from './typings.js';
|
|
14
14
|
import { FlushMode, LockMode, PopulatePath, type TransactionOptions } from './enums.js';
|
|
15
15
|
import type { MetadataStorage } from './metadata/MetadataStorage.js';
|
|
16
16
|
import type { Transaction } from './connections/Connection.js';
|
|
@@ -109,19 +109,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
109
109
|
/**
|
|
110
110
|
* Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
|
|
111
111
|
*/
|
|
112
|
-
addFilter<
|
|
113
|
-
/**
|
|
114
|
-
* Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
|
|
115
|
-
*/
|
|
116
|
-
addFilter<T1, T2>(name: string, cond: FilterQuery<T1 | T2> | ((args: Dictionary) => MaybePromise<FilterQuery<T1 | T2>>), entityName?: [EntityName<T1>, EntityName<T2>], options?: boolean | Partial<FilterDef>): void;
|
|
117
|
-
/**
|
|
118
|
-
* Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
|
|
119
|
-
*/
|
|
120
|
-
addFilter<T1, T2, T3>(name: string, cond: FilterQuery<T1 | T2 | T3> | ((args: Dictionary) => MaybePromise<FilterQuery<T1 | T2 | T3>>), entityName?: [EntityName<T1>, EntityName<T2>, EntityName<T3>], options?: boolean | Partial<FilterDef>): void;
|
|
121
|
-
/**
|
|
122
|
-
* Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
|
|
123
|
-
*/
|
|
124
|
-
addFilter(name: string, cond: Dictionary | ((args: Dictionary) => MaybePromise<FilterQuery<AnyEntity>>), entityName?: EntityName<AnyEntity> | EntityName<AnyEntity>[], options?: boolean | Partial<FilterDef>): void;
|
|
112
|
+
addFilter<T extends object>(options: FilterDef<T>): void;
|
|
125
113
|
/**
|
|
126
114
|
* Sets filter parameter values globally inside context defined by this entity manager.
|
|
127
115
|
* If you want to set shared value for all contexts, be sure to use the root entity manager.
|
package/EntityManager.js
CHANGED
|
@@ -256,15 +256,34 @@ export class EntityManager {
|
|
|
256
256
|
}
|
|
257
257
|
return { where: options.populateWhere };
|
|
258
258
|
}
|
|
259
|
+
// /**
|
|
260
|
+
// * Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
|
|
261
|
+
// */
|
|
262
|
+
// addFilter<T1>(name: string, cond: FilterQuery<T1> | ((args: Dictionary) => MaybePromise<FilterQuery<T1>>), entityName?: EntityName<T1> | [EntityName<T1>], options?: boolean | Partial<FilterDef>): void;
|
|
263
|
+
//
|
|
264
|
+
// /**
|
|
265
|
+
// * Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
|
|
266
|
+
// */
|
|
267
|
+
// addFilter<T1, T2>(name: string, cond: FilterQuery<T1 | T2> | ((args: Dictionary) => MaybePromise<FilterQuery<T1 | T2>>), entityName?: [EntityName<T1>, EntityName<T2>], options?: boolean | Partial<FilterDef>): void;
|
|
268
|
+
//
|
|
269
|
+
// /**
|
|
270
|
+
// * Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
|
|
271
|
+
// */
|
|
272
|
+
// addFilter<T1, T2, T3>(name: string, cond: FilterQuery<T1 | T2 | T3> | ((args: Dictionary) => MaybePromise<FilterQuery<T1 | T2 | T3>>), entityName?: [EntityName<T1>, EntityName<T2>, EntityName<T3>], options?: boolean | Partial<FilterDef>): void;
|
|
273
|
+
//
|
|
274
|
+
// /**
|
|
275
|
+
// * Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
|
|
276
|
+
// */
|
|
277
|
+
// addFilter(name: string, cond: Dictionary | ((args: Dictionary) => MaybePromise<FilterQuery<AnyEntity>>), entityName?: EntityName<AnyEntity> | EntityName<AnyEntity>[], options?: boolean | Partial<FilterDef>): void;
|
|
259
278
|
/**
|
|
260
279
|
* Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
|
|
261
280
|
*/
|
|
262
|
-
addFilter(
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
options.entity = Utils.asArray(entityName).map(n => Utils.className(n));
|
|
281
|
+
addFilter(options) {
|
|
282
|
+
if (options.entity) {
|
|
283
|
+
options.entity = Utils.asArray(options.entity).map(n => Utils.className(n));
|
|
266
284
|
}
|
|
267
|
-
|
|
285
|
+
options.default ??= true;
|
|
286
|
+
this.getContext(false).filters[options.name] = options;
|
|
268
287
|
}
|
|
269
288
|
/**
|
|
270
289
|
* Sets filter parameter values globally inside context defined by this entity manager.
|
package/MikroORM.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export declare class MikroORM<Driver extends IDatabaseDriver = IDatabaseDriver,
|
|
|
21
21
|
* Initialize the ORM, load entity metadata, create EntityManager and connect to the database.
|
|
22
22
|
* If you omit the `options` parameter, your CLI config will be used.
|
|
23
23
|
*/
|
|
24
|
-
static init<D extends IDatabaseDriver = IDatabaseDriver, EM extends EntityManager = D[typeof EntityManagerType] & EntityManager, Entities extends (string | EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[]>(options
|
|
24
|
+
static init<D extends IDatabaseDriver = IDatabaseDriver, EM extends EntityManager = D[typeof EntityManagerType] & EntityManager, Entities extends (string | EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[]>(options: Options<D, EM, Entities>): Promise<MikroORM<D, EM, Entities>>;
|
|
25
25
|
/**
|
|
26
26
|
* Synchronous variant of the `init` method with some limitations:
|
|
27
27
|
* - database connection will be established when you first interact with the database (or you can use `orm.connect()` explicitly)
|
|
@@ -29,7 +29,6 @@ export declare class MikroORM<Driver extends IDatabaseDriver = IDatabaseDriver,
|
|
|
29
29
|
* - no support for folder based discovery
|
|
30
30
|
* - no check for mismatched package versions
|
|
31
31
|
*/
|
|
32
|
-
static initSync<D extends IDatabaseDriver = IDatabaseDriver, EM extends EntityManager = D[typeof EntityManagerType] & EntityManager, Entities extends (string | EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[]>(options: Options<D, EM, Entities>): MikroORM<D, EM, Entities>;
|
|
33
32
|
constructor(options: Options<Driver, EM>);
|
|
34
33
|
/**
|
|
35
34
|
* Connects to the database.
|
package/MikroORM.js
CHANGED
|
@@ -23,22 +23,14 @@ export class MikroORM {
|
|
|
23
23
|
* If you omit the `options` parameter, your CLI config will be used.
|
|
24
24
|
*/
|
|
25
25
|
static async init(options) {
|
|
26
|
-
|
|
27
|
-
const coreVersion = ConfigurationLoader.checkPackageVersion();
|
|
28
|
-
const env = await ConfigurationLoader.loadEnvironmentVars();
|
|
26
|
+
/* v8 ignore next 3 */
|
|
29
27
|
if (!options) {
|
|
30
|
-
|
|
31
|
-
const config = (await ConfigurationLoader.getConfiguration(process.env.MIKRO_ORM_CONTEXT_NAME ?? 'default', configPathFromArg ?? ConfigurationLoader.getConfigPaths()));
|
|
32
|
-
options = config.getAll();
|
|
33
|
-
if (configPathFromArg) {
|
|
34
|
-
config.getLogger().warn('deprecated', 'Path for config file was inferred from the command line arguments. Instead, you should set the MIKRO_ORM_CLI_CONFIG environment variable to specify the path, or if you really must use the command line arguments, import the config manually based on them, and pass it to init.', { label: 'D0001' });
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
options = Utils.mergeConfig(options, env);
|
|
38
|
-
if ('DRIVER' in this && !options.driver) {
|
|
39
|
-
options.driver = this.DRIVER;
|
|
28
|
+
throw new Error(`options parameter is required`);
|
|
40
29
|
}
|
|
41
|
-
const
|
|
30
|
+
const coreVersion = ConfigurationLoader.checkPackageVersion();
|
|
31
|
+
options.discovery ??= {};
|
|
32
|
+
options.discovery.skipSyncDiscovery ??= true;
|
|
33
|
+
const orm = new this(options);
|
|
42
34
|
orm.logger.log('info', `MikroORM version: ${colors.green(coreVersion)}`);
|
|
43
35
|
// we need to allow global context here as we are not in a scope of requests yet
|
|
44
36
|
const allowGlobalContext = orm.config.get('allowGlobalContext');
|
|
@@ -46,15 +38,6 @@ export class MikroORM {
|
|
|
46
38
|
await orm.discoverEntities();
|
|
47
39
|
orm.config.set('allowGlobalContext', allowGlobalContext);
|
|
48
40
|
orm.driver.getPlatform().init(orm);
|
|
49
|
-
if (orm.config.get('connect')) {
|
|
50
|
-
await orm.connect();
|
|
51
|
-
}
|
|
52
|
-
for (const extension of orm.config.get('extensions')) {
|
|
53
|
-
extension.register(orm);
|
|
54
|
-
}
|
|
55
|
-
if (orm.config.get('connect') && orm.config.get('ensureIndexes')) {
|
|
56
|
-
await orm.getSchemaGenerator().ensureIndexes();
|
|
57
|
-
}
|
|
58
41
|
return orm;
|
|
59
42
|
}
|
|
60
43
|
/**
|
|
@@ -64,26 +47,10 @@ export class MikroORM {
|
|
|
64
47
|
* - no support for folder based discovery
|
|
65
48
|
* - no check for mismatched package versions
|
|
66
49
|
*/
|
|
67
|
-
|
|
50
|
+
constructor(options) {
|
|
68
51
|
ConfigurationLoader.registerDotenv(options);
|
|
69
52
|
const env = ConfigurationLoader.loadEnvironmentVarsSync();
|
|
70
53
|
options = Utils.merge(options, env);
|
|
71
|
-
if ('DRIVER' in this && !options.driver) {
|
|
72
|
-
options.driver = this.DRIVER;
|
|
73
|
-
}
|
|
74
|
-
const orm = new MikroORM(options);
|
|
75
|
-
// we need to allow global context here as we are not in a scope of requests yet
|
|
76
|
-
const allowGlobalContext = orm.config.get('allowGlobalContext');
|
|
77
|
-
orm.config.set('allowGlobalContext', true);
|
|
78
|
-
orm.discoverEntitiesSync();
|
|
79
|
-
orm.config.set('allowGlobalContext', allowGlobalContext);
|
|
80
|
-
orm.driver.getPlatform().init(orm);
|
|
81
|
-
for (const extension of orm.config.get('extensions')) {
|
|
82
|
-
extension.register(orm);
|
|
83
|
-
}
|
|
84
|
-
return orm;
|
|
85
|
-
}
|
|
86
|
-
constructor(options) {
|
|
87
54
|
this.config = new Configuration(options);
|
|
88
55
|
const discovery = this.config.get('discovery');
|
|
89
56
|
if (discovery.disableDynamicFileAccess) {
|
|
@@ -94,25 +61,23 @@ export class MikroORM {
|
|
|
94
61
|
this.driver = this.config.getDriver();
|
|
95
62
|
this.logger = this.config.getLogger();
|
|
96
63
|
this.discovery = new MetadataDiscovery(new MetadataStorage(), this.driver.getPlatform(), this.config);
|
|
64
|
+
if (!discovery.skipSyncDiscovery) {
|
|
65
|
+
// we need to allow global context here as we are not in a scope of requests yet
|
|
66
|
+
const allowGlobalContext = this.config.get('allowGlobalContext');
|
|
67
|
+
this.config.set('allowGlobalContext', true);
|
|
68
|
+
this.discoverEntitiesSync();
|
|
69
|
+
this.config.set('allowGlobalContext', allowGlobalContext);
|
|
70
|
+
this.driver.getPlatform().init(this);
|
|
71
|
+
}
|
|
72
|
+
for (const extension of this.config.get('extensions')) {
|
|
73
|
+
extension.register(this);
|
|
74
|
+
}
|
|
97
75
|
}
|
|
98
76
|
/**
|
|
99
77
|
* Connects to the database.
|
|
100
78
|
*/
|
|
101
79
|
async connect() {
|
|
102
|
-
|
|
103
|
-
const clientUrl = connection.getClientUrl();
|
|
104
|
-
const dbName = this.config.get('dbName');
|
|
105
|
-
const db = dbName + (clientUrl ? ' on ' + clientUrl : '');
|
|
106
|
-
if (this.config.get('ensureDatabase')) {
|
|
107
|
-
const options = this.config.get('ensureDatabase');
|
|
108
|
-
await this.schema.ensureDatabase(typeof options === 'boolean' ? {} : { ...options, forceCheck: true });
|
|
109
|
-
}
|
|
110
|
-
if (await this.isConnected()) {
|
|
111
|
-
this.logger.log('info', `MikroORM successfully connected to database ${colors.green(db)}`);
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
this.logger.error('info', `MikroORM failed to connect to database ${db}`);
|
|
115
|
-
}
|
|
80
|
+
await this.driver.connect();
|
|
116
81
|
return this.driver;
|
|
117
82
|
}
|
|
118
83
|
/**
|
|
@@ -141,9 +106,7 @@ export class MikroORM {
|
|
|
141
106
|
* Closes the database connection.
|
|
142
107
|
*/
|
|
143
108
|
async close(force = false) {
|
|
144
|
-
|
|
145
|
-
await this.driver.close(force);
|
|
146
|
-
}
|
|
109
|
+
await this.driver.close(force);
|
|
147
110
|
if (this.config.getMetadataCacheAdapter()?.close) {
|
|
148
111
|
await this.config.getMetadataCacheAdapter().close();
|
|
149
112
|
}
|
|
@@ -166,7 +129,7 @@ export class MikroORM {
|
|
|
166
129
|
this.createEntityManager();
|
|
167
130
|
}
|
|
168
131
|
discoverEntitiesSync() {
|
|
169
|
-
this.metadata = this.discovery.discoverSync(
|
|
132
|
+
this.metadata = this.discovery.discoverSync();
|
|
170
133
|
this.createEntityManager();
|
|
171
134
|
}
|
|
172
135
|
createEntityManager() {
|
|
@@ -17,7 +17,9 @@ export declare abstract class Connection {
|
|
|
17
17
|
/**
|
|
18
18
|
* Establishes connection to database
|
|
19
19
|
*/
|
|
20
|
-
abstract connect(
|
|
20
|
+
abstract connect(options?: {
|
|
21
|
+
skipOnConnect?: boolean;
|
|
22
|
+
}): void | Promise<void>;
|
|
21
23
|
/**
|
|
22
24
|
* Are we connected to the database
|
|
23
25
|
*/
|
|
@@ -37,9 +39,10 @@ export declare abstract class Connection {
|
|
|
37
39
|
*/
|
|
38
40
|
close(force?: boolean): Promise<void>;
|
|
39
41
|
/**
|
|
40
|
-
* Ensure the connection exists, this is used to support lazy connect when using `MikroORM
|
|
42
|
+
* Ensure the connection exists, this is used to support lazy connect when using `new MikroORM()` instead of the async `init` method.
|
|
41
43
|
*/
|
|
42
44
|
ensureConnection(): Promise<void>;
|
|
45
|
+
protected onConnect(): Promise<void>;
|
|
43
46
|
transactional<T>(cb: (trx: Transaction) => Promise<T>, options?: {
|
|
44
47
|
isolationLevel?: IsolationLevel;
|
|
45
48
|
readOnly?: boolean;
|
|
@@ -58,7 +61,6 @@ export declare abstract class Connection {
|
|
|
58
61
|
rollback(ctx: Transaction, eventBroadcaster?: TransactionEventBroadcaster, loggerContext?: LogContext): Promise<void>;
|
|
59
62
|
abstract execute<T>(query: string, params?: any[], method?: 'all' | 'get' | 'run', ctx?: Transaction): Promise<QueryResult<T> | any | any[]>;
|
|
60
63
|
getConnectionOptions(): ConnectionConfig;
|
|
61
|
-
getClientUrl(): string;
|
|
62
64
|
setMetadata(metadata: MetadataStorage): void;
|
|
63
65
|
setPlatform(platform: Platform): void;
|
|
64
66
|
getPlatform(): Platform;
|
|
@@ -33,13 +33,25 @@ export class Connection {
|
|
|
33
33
|
.forEach(k => delete this.options[k]);
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
|
-
* Ensure the connection exists, this is used to support lazy connect when using `MikroORM
|
|
36
|
+
* Ensure the connection exists, this is used to support lazy connect when using `new MikroORM()` instead of the async `init` method.
|
|
37
37
|
*/
|
|
38
38
|
async ensureConnection() {
|
|
39
39
|
if (!this.connected) {
|
|
40
40
|
await this.connect();
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
+
async onConnect() {
|
|
44
|
+
const schemaGenerator = this.config.getExtension('@mikro-orm/schema-generator');
|
|
45
|
+
if (this.type === 'write' && schemaGenerator) {
|
|
46
|
+
if (this.config.get('ensureDatabase')) {
|
|
47
|
+
const options = this.config.get('ensureDatabase');
|
|
48
|
+
await schemaGenerator.ensureDatabase(typeof options === 'boolean' ? {} : { ...options, forceCheck: true });
|
|
49
|
+
}
|
|
50
|
+
if (this.config.get('ensureIndexes')) {
|
|
51
|
+
await schemaGenerator.ensureIndexes();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
43
55
|
async transactional(cb, options) {
|
|
44
56
|
throw new Error(`Transactions are not supported by current driver`);
|
|
45
57
|
}
|
|
@@ -67,7 +79,7 @@ export class Connection {
|
|
|
67
79
|
}
|
|
68
80
|
}
|
|
69
81
|
else {
|
|
70
|
-
const url = new URL(this.config.
|
|
82
|
+
const url = new URL(this.config.get('clientUrl'));
|
|
71
83
|
this.options.host = ret.host = this.options.host ?? this.config.get('host', decodeURIComponent(url.hostname));
|
|
72
84
|
this.options.port = ret.port = this.options.port ?? this.config.get('port', +url.port);
|
|
73
85
|
this.options.user = ret.user = this.options.user ?? this.config.get('user', decodeURIComponent(url.username));
|
|
@@ -76,15 +88,6 @@ export class Connection {
|
|
|
76
88
|
}
|
|
77
89
|
return ret;
|
|
78
90
|
}
|
|
79
|
-
getClientUrl() {
|
|
80
|
-
const options = this.getConnectionOptions();
|
|
81
|
-
const url = new URL(this.config.getClientUrl(true));
|
|
82
|
-
const password = options.password ? ':*****' : '';
|
|
83
|
-
const schema = options.schema && options.schema !== this.platform.getDefaultSchemaName()
|
|
84
|
-
? `?schema=${options.schema}`
|
|
85
|
-
: '';
|
|
86
|
-
return `${url.protocol}//${options.user}${password}@${options.host}:${options.port}${schema}`;
|
|
87
|
-
}
|
|
88
91
|
setMetadata(metadata) {
|
|
89
92
|
this.metadata = metadata;
|
|
90
93
|
}
|
package/decorators/Property.d.ts
CHANGED
|
@@ -113,12 +113,6 @@ export interface PropertyOptions<Owner> {
|
|
|
113
113
|
* Enable `ScalarReference` wrapper for lazy values. Use this in combination with `lazy: true` to have a type-safe accessor object in place of the value.
|
|
114
114
|
*/
|
|
115
115
|
ref?: boolean;
|
|
116
|
-
/**
|
|
117
|
-
* Set false to disable change tracking on a property level.
|
|
118
|
-
*
|
|
119
|
-
* @see https://mikro-orm.io/docs/unit-of-work#change-tracking-and-performance-considerations
|
|
120
|
-
*/
|
|
121
|
-
trackChanges?: boolean;
|
|
122
116
|
/**
|
|
123
117
|
* Set to true to omit the property when {@link https://mikro-orm.io/docs/serializing Serializing}.
|
|
124
118
|
*/
|
|
@@ -36,8 +36,12 @@ export declare abstract class DatabaseDriver<C extends Connection> implements ID
|
|
|
36
36
|
loadFromPivotTable<T extends object, O extends object>(prop: EntityProperty, owners: Primary<O>[][], where?: FilterQuery<any>, orderBy?: OrderDefinition<T>, ctx?: Transaction, options?: FindOptions<T, any, any, any>, pivotJoin?: boolean): Promise<Dictionary<T[]>>;
|
|
37
37
|
syncCollections<T extends object, O extends object>(collections: Iterable<Collection<T, O>>, options?: DriverMethodOptions): Promise<void>;
|
|
38
38
|
mapResult<T extends object>(result: EntityDictionary<T>, meta?: EntityMetadata<T>, populate?: PopulateOptions<T>[]): EntityData<T> | null;
|
|
39
|
-
connect(
|
|
40
|
-
|
|
39
|
+
connect(options?: {
|
|
40
|
+
skipOnConnect?: boolean;
|
|
41
|
+
}): Promise<C>;
|
|
42
|
+
reconnect(options?: {
|
|
43
|
+
skipOnConnect?: boolean;
|
|
44
|
+
}): Promise<C>;
|
|
41
45
|
getConnection(type?: ConnectionType): C;
|
|
42
46
|
close(force?: boolean): Promise<void>;
|
|
43
47
|
getPlatform(): Platform;
|
|
@@ -65,14 +65,14 @@ export class DatabaseDriver {
|
|
|
65
65
|
}
|
|
66
66
|
return this.comparator.mapResult(meta.className, result);
|
|
67
67
|
}
|
|
68
|
-
async connect() {
|
|
69
|
-
await this.connection.connect();
|
|
68
|
+
async connect(options) {
|
|
69
|
+
await this.connection.connect(options);
|
|
70
70
|
await Promise.all(this.replicas.map(replica => replica.connect()));
|
|
71
71
|
return this.connection;
|
|
72
72
|
}
|
|
73
|
-
async reconnect() {
|
|
73
|
+
async reconnect(options) {
|
|
74
74
|
await this.close(true);
|
|
75
|
-
await this.connect();
|
|
75
|
+
await this.connect(options);
|
|
76
76
|
return this.connection;
|
|
77
77
|
}
|
|
78
78
|
getConnection(type = 'write') {
|
|
@@ -14,9 +14,13 @@ export interface IDatabaseDriver<C extends Connection = Connection> {
|
|
|
14
14
|
[EntityManagerType]: EntityManager<this>;
|
|
15
15
|
readonly config: Configuration;
|
|
16
16
|
createEntityManager(useContext?: boolean): this[typeof EntityManagerType];
|
|
17
|
-
connect(
|
|
17
|
+
connect(options?: {
|
|
18
|
+
skipOnConnect?: boolean;
|
|
19
|
+
}): Promise<C>;
|
|
18
20
|
close(force?: boolean): Promise<void>;
|
|
19
|
-
reconnect(
|
|
21
|
+
reconnect(options?: {
|
|
22
|
+
skipOnConnect?: boolean;
|
|
23
|
+
}): Promise<C>;
|
|
20
24
|
getConnection(type?: ConnectionType): C;
|
|
21
25
|
/**
|
|
22
26
|
* Finds selection of entities
|
|
@@ -16,7 +16,7 @@ export declare class ArrayCollection<T extends object, O extends object> {
|
|
|
16
16
|
toArray<TT extends T>(): EntityDTO<TT>[];
|
|
17
17
|
toJSON(): EntityDTO<T>[];
|
|
18
18
|
getIdentifiers<U extends IPrimaryKey = Primary<T> & IPrimaryKey>(field?: string | string[]): U[];
|
|
19
|
-
add(entity: T | Reference<T> | Iterable<T | Reference<T>>, ...entities: (T | Reference<T>)[]):
|
|
19
|
+
add(entity: T | Reference<T> | Iterable<T | Reference<T>>, ...entities: (T | Reference<T>)[]): number;
|
|
20
20
|
/**
|
|
21
21
|
* @internal
|
|
22
22
|
*/
|
|
@@ -33,7 +33,7 @@ export declare class ArrayCollection<T extends object, O extends object> {
|
|
|
33
33
|
* is not the same as `em.remove()`. If we want to delete the entity by removing it from collection, we need to enable `orphanRemoval: true`,
|
|
34
34
|
* which tells the ORM we don't want orphaned entities to exist, so we know those should be removed.
|
|
35
35
|
*/
|
|
36
|
-
remove(entity: T | Reference<T> | Iterable<T | Reference<T>>, ...entities: (T | Reference<T>)[]):
|
|
36
|
+
remove(entity: T | Reference<T> | Iterable<T | Reference<T>>, ...entities: (T | Reference<T>)[]): number;
|
|
37
37
|
/**
|
|
38
38
|
* Remove all items from the collection. Note that removing items from collection does not necessarily imply deleting the target entity,
|
|
39
39
|
* it means we are disconnecting the relation - removing items from collection, not removing entities from database - `Collection.remove()`
|
|
@@ -61,15 +61,18 @@ export class ArrayCollection {
|
|
|
61
61
|
}
|
|
62
62
|
add(entity, ...entities) {
|
|
63
63
|
entities = Utils.asArray(entity).concat(entities);
|
|
64
|
+
let added = 0;
|
|
64
65
|
for (const item of entities) {
|
|
65
66
|
const entity = Reference.unwrapReference(item);
|
|
66
67
|
if (!this.contains(entity, false)) {
|
|
67
68
|
this.incrementCount(1);
|
|
68
69
|
this[this.items.size] = entity;
|
|
69
70
|
this.items.add(entity);
|
|
71
|
+
added++;
|
|
70
72
|
this.propagate(entity, 'add');
|
|
71
73
|
}
|
|
72
74
|
}
|
|
75
|
+
return added;
|
|
73
76
|
}
|
|
74
77
|
/**
|
|
75
78
|
* @internal
|
|
@@ -127,7 +130,7 @@ export class ArrayCollection {
|
|
|
127
130
|
*/
|
|
128
131
|
remove(entity, ...entities) {
|
|
129
132
|
entities = Utils.asArray(entity).concat(entities);
|
|
130
|
-
let
|
|
133
|
+
let removed = 0;
|
|
131
134
|
for (const item of entities) {
|
|
132
135
|
if (!item) {
|
|
133
136
|
continue;
|
|
@@ -137,12 +140,13 @@ export class ArrayCollection {
|
|
|
137
140
|
this.incrementCount(-1);
|
|
138
141
|
delete this[this.items.size]; // remove last item
|
|
139
142
|
this.propagate(entity, 'remove');
|
|
140
|
-
|
|
143
|
+
removed++;
|
|
141
144
|
}
|
|
142
145
|
}
|
|
143
|
-
if (
|
|
146
|
+
if (removed > 0) {
|
|
144
147
|
Object.assign(this, [...this.items]); // reassign array access
|
|
145
148
|
}
|
|
149
|
+
return removed;
|
|
146
150
|
}
|
|
147
151
|
/**
|
|
148
152
|
* Remove all items from the collection. Note that removing items from collection does not necessarily imply deleting the target entity,
|
|
@@ -156,6 +160,7 @@ export class ArrayCollection {
|
|
|
156
160
|
this.snapshot = undefined;
|
|
157
161
|
}
|
|
158
162
|
this.remove(this.items);
|
|
163
|
+
this.setDirty();
|
|
159
164
|
}
|
|
160
165
|
/**
|
|
161
166
|
* @internal
|
package/entity/BaseEntity.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ import { type SerializeOptions } from '../serialization/EntitySerializer.js';
|
|
|
6
6
|
import type { FindOneOptions } from '../drivers/IDatabaseDriver.js';
|
|
7
7
|
export declare abstract class BaseEntity {
|
|
8
8
|
isInitialized(): boolean;
|
|
9
|
-
isTouched(): boolean;
|
|
10
9
|
populated(populated?: boolean): void;
|
|
11
10
|
populate<Entity extends this = this, Hint extends string = never>(populate: AutoPath<Entity, Hint>[] | false, options?: EntityLoaderOptions<Entity>): Promise<Loaded<Entity, Hint>>;
|
|
12
11
|
toReference<Entity extends this = this>(): Ref<Entity> & LoadedReference<Loaded<Entity, AddEager<Entity>>>;
|
package/entity/BaseEntity.js
CHANGED
package/entity/Collection.d.ts
CHANGED
|
@@ -39,11 +39,11 @@ export declare class Collection<T extends object, O extends object = object> ext
|
|
|
39
39
|
*/
|
|
40
40
|
getItems(check?: boolean): T[];
|
|
41
41
|
toJSON<TT extends T>(): EntityDTO<TT>[];
|
|
42
|
-
add<TT extends T>(entity: TT | Reference<TT> | Iterable<TT | Reference<TT>>, ...entities: (TT | Reference<TT>)[]):
|
|
42
|
+
add<TT extends T>(entity: TT | Reference<TT> | Iterable<TT | Reference<TT>>, ...entities: (TT | Reference<TT>)[]): number;
|
|
43
43
|
/**
|
|
44
44
|
* @inheritDoc
|
|
45
45
|
*/
|
|
46
|
-
remove<TT extends T>(entity: TT | Reference<TT> | Iterable<TT | Reference<TT>> | ((item: TT) => boolean), ...entities: (TT | Reference<TT>)[]):
|
|
46
|
+
remove<TT extends T>(entity: TT | Reference<TT> | Iterable<TT | Reference<TT>> | ((item: TT) => boolean), ...entities: (TT | Reference<TT>)[]): number;
|
|
47
47
|
contains<TT extends T>(item: TT | Reference<TT>, check?: boolean): boolean;
|
|
48
48
|
count(): number;
|
|
49
49
|
isEmpty(): boolean;
|
package/entity/Collection.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ArrayCollection } from './ArrayCollection.js';
|
|
2
2
|
import { Utils } from '../utils/Utils.js';
|
|
3
3
|
import { ValidationError } from '../errors.js';
|
|
4
|
-
import {
|
|
4
|
+
import { DataloaderType, ReferenceKind } from '../enums.js';
|
|
5
5
|
import { Reference } from './Reference.js';
|
|
6
6
|
import { helper } from './wrap.js';
|
|
7
7
|
import { QueryHelper } from '../utils/QueryHelper.js';
|
|
@@ -117,30 +117,33 @@ export class Collection extends ArrayCollection {
|
|
|
117
117
|
entities = Utils.asArray(entity).concat(entities);
|
|
118
118
|
const unwrapped = entities.map(i => Reference.unwrapReference(i));
|
|
119
119
|
unwrapped.forEach(entity => this.validateItemType(entity));
|
|
120
|
-
this.modify('add', unwrapped);
|
|
120
|
+
const added = this.modify('add', unwrapped);
|
|
121
121
|
this.cancelOrphanRemoval(unwrapped);
|
|
122
|
+
return added;
|
|
122
123
|
}
|
|
123
124
|
/**
|
|
124
125
|
* @inheritDoc
|
|
125
126
|
*/
|
|
126
127
|
remove(entity, ...entities) {
|
|
127
128
|
if (entity instanceof Function) {
|
|
129
|
+
let removed = 0;
|
|
128
130
|
for (const item of this.items) {
|
|
129
131
|
if (entity(item)) {
|
|
130
|
-
this.remove(item);
|
|
132
|
+
removed += this.remove(item);
|
|
131
133
|
}
|
|
132
134
|
}
|
|
133
|
-
return;
|
|
135
|
+
return removed;
|
|
134
136
|
}
|
|
135
137
|
entities = Utils.asArray(entity).concat(entities);
|
|
136
138
|
const unwrapped = entities.map(i => Reference.unwrapReference(i));
|
|
137
|
-
this.modify('remove', unwrapped);
|
|
139
|
+
const removed = this.modify('remove', unwrapped);
|
|
138
140
|
const em = this.getEntityManager(unwrapped, false);
|
|
139
141
|
if (this.property.orphanRemoval && em) {
|
|
140
142
|
for (const item of unwrapped) {
|
|
141
143
|
em.getUnitOfWork().scheduleOrphanRemoval(item);
|
|
142
144
|
}
|
|
143
145
|
}
|
|
146
|
+
return removed;
|
|
144
147
|
}
|
|
145
148
|
contains(item, check = true) {
|
|
146
149
|
if (check) {
|
|
@@ -267,8 +270,10 @@ export class Collection extends ArrayCollection {
|
|
|
267
270
|
getEntityManager(items = [], required = true) {
|
|
268
271
|
const wrapped = helper(this.owner);
|
|
269
272
|
let em = wrapped.__em;
|
|
273
|
+
// console.log('wat 1', em, this.owner);
|
|
270
274
|
if (!em) {
|
|
271
275
|
for (const i of items) {
|
|
276
|
+
// console.log('wat 2', i, i && helper(i).__em);
|
|
272
277
|
if (i && helper(i).__em) {
|
|
273
278
|
em = helper(i).__em;
|
|
274
279
|
break;
|
|
@@ -325,8 +330,14 @@ export class Collection extends ArrayCollection {
|
|
|
325
330
|
this.checkInitialized();
|
|
326
331
|
}
|
|
327
332
|
this.validateModification(items);
|
|
328
|
-
super[method](items);
|
|
329
|
-
|
|
333
|
+
const modified = super[method](items);
|
|
334
|
+
if (modified > 0) {
|
|
335
|
+
this.setDirty();
|
|
336
|
+
}
|
|
337
|
+
if (this.property.kind === ReferenceKind.ONE_TO_MANY && (method === 'add' || !this.property.orphanRemoval)) {
|
|
338
|
+
this.getEntityManager(items, false)?.persist(items);
|
|
339
|
+
}
|
|
340
|
+
return modified;
|
|
330
341
|
}
|
|
331
342
|
checkInitialized() {
|
|
332
343
|
if (!this.isInitialized()) {
|
package/entity/EntityFactory.js
CHANGED
|
@@ -84,7 +84,6 @@ export class EntityFactory {
|
|
|
84
84
|
else {
|
|
85
85
|
this.hydrate(entity, meta2, data, options);
|
|
86
86
|
}
|
|
87
|
-
wrapped.__touched = false;
|
|
88
87
|
if (exists && meta.discriminatorColumn && !(entity instanceof meta2.class)) {
|
|
89
88
|
Object.setPrototypeOf(entity, meta2.prototype);
|
|
90
89
|
}
|
|
@@ -161,7 +160,6 @@ export class EntityFactory {
|
|
|
161
160
|
}
|
|
162
161
|
});
|
|
163
162
|
this.unitOfWork.normalizeEntityData(meta, originalEntityData);
|
|
164
|
-
helper(entity).__touched = false;
|
|
165
163
|
}
|
|
166
164
|
createReference(entityName, id, options = {}) {
|
|
167
165
|
options.convertCustomTypes ??= true;
|
package/entity/EntityHelper.js
CHANGED
|
@@ -87,7 +87,7 @@ export class EntityHelper {
|
|
|
87
87
|
});
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
|
-
if (prop.inherited || prop.primary || prop.accessor || prop.persist === false || prop.
|
|
90
|
+
if (prop.inherited || prop.primary || prop.accessor || prop.persist === false || prop.embedded || isCollection) {
|
|
91
91
|
return;
|
|
92
92
|
}
|
|
93
93
|
Object.defineProperty(meta.prototype, prop.name, {
|
|
@@ -98,13 +98,11 @@ export class EntityHelper {
|
|
|
98
98
|
},
|
|
99
99
|
set(val) {
|
|
100
100
|
this.__helper.__data[prop.name] = val;
|
|
101
|
-
this.__helper.__touched = !this.__helper.hydrator.isRunning();
|
|
102
101
|
},
|
|
103
102
|
enumerable: true,
|
|
104
103
|
configurable: true,
|
|
105
104
|
});
|
|
106
105
|
this.__helper.__data[prop.name] = val;
|
|
107
|
-
this.__helper.__touched = !this.__helper.hydrator.isRunning();
|
|
108
106
|
},
|
|
109
107
|
configurable: true,
|
|
110
108
|
});
|
|
@@ -114,7 +112,7 @@ export class EntityHelper {
|
|
|
114
112
|
// @ts-ignore
|
|
115
113
|
meta.prototype[inspect.custom] ??= function (depth = 2) {
|
|
116
114
|
const object = {};
|
|
117
|
-
const keys = new Set(Utils.keys(this));
|
|
115
|
+
const keys = new Set(Utils.keys(this));
|
|
118
116
|
for (const prop of meta.props) {
|
|
119
117
|
if (keys.has(prop.name) || (prop.getter && prop.accessor === prop.name)) {
|
|
120
118
|
object[prop.name] = this[prop.name];
|
|
@@ -165,9 +163,6 @@ export class EntityHelper {
|
|
|
165
163
|
if (val && hydrator.isRunning() && wrapped.__originalEntityData && prop.owner) {
|
|
166
164
|
wrapped.__originalEntityData[prop.name] = Utils.getPrimaryKeyValues(wrapped.__data[prop.name], prop.targetMeta, true);
|
|
167
165
|
}
|
|
168
|
-
else {
|
|
169
|
-
wrapped.__touched = !hydrator.isRunning();
|
|
170
|
-
}
|
|
171
166
|
EntityHelper.propagate(meta, entity, this, prop, Reference.unwrapReference(val), old);
|
|
172
167
|
},
|
|
173
168
|
enumerable: true,
|
|
@@ -11,7 +11,6 @@ import { type SerializeOptions } from '../serialization/EntitySerializer.js';
|
|
|
11
11
|
import type { FindOneOptions, LoadHint } from '../drivers/IDatabaseDriver.js';
|
|
12
12
|
export declare class WrappedEntity<Entity extends object> {
|
|
13
13
|
__initialized: boolean;
|
|
14
|
-
__touched: boolean;
|
|
15
14
|
__populated?: boolean;
|
|
16
15
|
__managed?: boolean;
|
|
17
16
|
__onLoadFired?: boolean;
|
|
@@ -41,7 +40,6 @@ export declare class WrappedEntity<Entity extends object> {
|
|
|
41
40
|
private readonly pkGetterConverted?;
|
|
42
41
|
constructor(entity: Entity, hydrator: IHydrator, pkGetter?: (e: Entity) => Primary<Entity>, pkSerializer?: (e: Entity) => string, pkGetterConverted?: (e: Entity) => Primary<Entity>);
|
|
43
42
|
isInitialized(): boolean;
|
|
44
|
-
isTouched(): boolean;
|
|
45
43
|
isManaged(): boolean;
|
|
46
44
|
populated(populated?: boolean | undefined): void;
|
|
47
45
|
setSerializationContext<Hint extends string = never, Fields extends string = '*', Exclude extends string = never>(options: LoadHint<Entity, Hint, Fields, Exclude>): void;
|
package/entity/WrappedEntity.js
CHANGED
|
@@ -15,7 +15,6 @@ export class WrappedEntity {
|
|
|
15
15
|
this.pkSerializer = pkSerializer;
|
|
16
16
|
this.pkGetterConverted = pkGetterConverted;
|
|
17
17
|
this.__initialized = true;
|
|
18
|
-
this.__touched = false;
|
|
19
18
|
this.__serializationContext = {};
|
|
20
19
|
this.__loadedProperties = new Set();
|
|
21
20
|
this.__data = {};
|
|
@@ -24,9 +23,6 @@ export class WrappedEntity {
|
|
|
24
23
|
isInitialized() {
|
|
25
24
|
return this.__initialized;
|
|
26
25
|
}
|
|
27
|
-
isTouched() {
|
|
28
|
-
return this.__touched;
|
|
29
|
-
}
|
|
30
26
|
isManaged() {
|
|
31
27
|
return !!this.__managed;
|
|
32
28
|
}
|