@mikro-orm/core 6.3.14-dev.6 → 6.3.14-dev.60
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 +5 -5
- package/MikroORM.d.ts +4 -2
- package/MikroORM.js +6 -1
- package/connections/Connection.d.ts +4 -2
- package/decorators/CreateRequestContext.d.ts +3 -9
- package/decorators/CreateRequestContext.js +16 -43
- package/decorators/ManyToOne.d.ts +2 -0
- package/decorators/Property.d.ts +13 -0
- package/decorators/Transactional.d.ts +13 -0
- package/decorators/Transactional.js +31 -0
- package/decorators/index.d.ts +1 -0
- package/decorators/index.js +1 -0
- package/drivers/DatabaseDriver.js +4 -9
- package/entity/BaseEntity.d.ts +1 -1
- package/entity/EntityFactory.js +7 -1
- package/entity/EntityHelper.js +8 -6
- package/index.d.ts +1 -1
- package/index.mjs +1 -0
- package/logging/DefaultLogger.js +6 -0
- package/logging/Logger.d.ts +2 -1
- package/metadata/MetadataDiscovery.d.ts +1 -0
- package/metadata/MetadataDiscovery.js +17 -0
- package/package.json +2 -2
- package/serialization/EntitySerializer.js +19 -12
- package/serialization/EntityTransformer.js +24 -13
- package/types/DecimalType.d.ts +2 -0
- package/types/DecimalType.js +11 -0
- package/typings.d.ts +18 -1
- package/utils/Configuration.d.ts +6 -0
- package/utils/Configuration.js +4 -0
- package/utils/ConfigurationLoader.d.ts +2 -1
- package/utils/ConfigurationLoader.js +5 -5
- package/utils/DataloaderUtils.d.ts +2 -2
- package/utils/DataloaderUtils.js +13 -11
- package/utils/resolveContextProvider.d.ts +10 -0
- package/utils/resolveContextProvider.js +31 -0
package/EntityManager.js
CHANGED
|
@@ -623,7 +623,7 @@ class EntityManager {
|
|
|
623
623
|
const convertCustomTypes = !utils_1.Utils.isEntity(data);
|
|
624
624
|
if (utils_1.Utils.isEntity(data)) {
|
|
625
625
|
entity = data;
|
|
626
|
-
if ((0, entity_1.helper)(entity).__managed && (0, entity_1.helper)(entity).__em === em) {
|
|
626
|
+
if ((0, entity_1.helper)(entity).__managed && (0, entity_1.helper)(entity).__em === em && !this.config.get('upsertManaged')) {
|
|
627
627
|
em.entityFactory.mergeData(meta, entity, data, { initialized: true });
|
|
628
628
|
return entity;
|
|
629
629
|
}
|
|
@@ -633,7 +633,7 @@ class EntityManager {
|
|
|
633
633
|
else {
|
|
634
634
|
data = utils_1.Utils.copy(utils_1.QueryHelper.processParams(data));
|
|
635
635
|
where = utils_1.Utils.extractPK(data, meta);
|
|
636
|
-
if (where) {
|
|
636
|
+
if (where && !this.config.get('upsertManaged')) {
|
|
637
637
|
const exists = em.unitOfWork.getById(entityName, where, options.schema);
|
|
638
638
|
if (exists) {
|
|
639
639
|
return em.assign(exists, data);
|
|
@@ -763,7 +763,7 @@ class EntityManager {
|
|
|
763
763
|
let where;
|
|
764
764
|
if (utils_1.Utils.isEntity(row)) {
|
|
765
765
|
const entity = row;
|
|
766
|
-
if ((0, entity_1.helper)(entity).__managed && (0, entity_1.helper)(entity).__em === em) {
|
|
766
|
+
if ((0, entity_1.helper)(entity).__managed && (0, entity_1.helper)(entity).__em === em && !this.config.get('upsertManaged')) {
|
|
767
767
|
em.entityFactory.mergeData(meta, entity, row, { initialized: true });
|
|
768
768
|
entities.set(entity, row);
|
|
769
769
|
entitiesByData.set(row, entity);
|
|
@@ -775,7 +775,7 @@ class EntityManager {
|
|
|
775
775
|
else {
|
|
776
776
|
row = data[i] = utils_1.Utils.copy(utils_1.QueryHelper.processParams(row));
|
|
777
777
|
where = utils_1.Utils.extractPK(row, meta);
|
|
778
|
-
if (where) {
|
|
778
|
+
if (where && !this.config.get('upsertManaged')) {
|
|
779
779
|
const exists = em.unitOfWork.getById(entityName, where, options.schema);
|
|
780
780
|
if (exists) {
|
|
781
781
|
em.assign(exists, row);
|
|
@@ -1103,7 +1103,7 @@ class EntityManager {
|
|
|
1103
1103
|
em.prepareOptions(options);
|
|
1104
1104
|
entityName = utils_1.Utils.className(entityName);
|
|
1105
1105
|
data = utils_1.QueryHelper.processObjectParams(data);
|
|
1106
|
-
where = await em.processWhere(entityName, where, options, 'update');
|
|
1106
|
+
where = await em.processWhere(entityName, where, { ...options, convertCustomTypes: false }, 'update');
|
|
1107
1107
|
em.validator.validateParams(data, 'update data');
|
|
1108
1108
|
em.validator.validateParams(where, 'update condition');
|
|
1109
1109
|
const res = await em.driver.nativeUpdate(entityName, where, data, { ctx: em.transactionContext, ...options });
|
package/MikroORM.d.ts
CHANGED
|
@@ -44,8 +44,10 @@ export declare class MikroORM<D extends IDatabaseDriver = IDatabaseDriver, EM ex
|
|
|
44
44
|
* Checks whether the database connection is active, returns .
|
|
45
45
|
*/
|
|
46
46
|
checkConnection(): Promise<{
|
|
47
|
-
ok:
|
|
48
|
-
|
|
47
|
+
ok: true;
|
|
48
|
+
} | {
|
|
49
|
+
ok: false;
|
|
50
|
+
reason: string;
|
|
49
51
|
error?: Error;
|
|
50
52
|
}>;
|
|
51
53
|
/**
|
package/MikroORM.js
CHANGED
|
@@ -29,7 +29,12 @@ class MikroORM {
|
|
|
29
29
|
const coreVersion = await utils_1.ConfigurationLoader.checkPackageVersion();
|
|
30
30
|
const env = utils_1.ConfigurationLoader.loadEnvironmentVars();
|
|
31
31
|
if (!options) {
|
|
32
|
-
|
|
32
|
+
const configPathFromArg = utils_1.ConfigurationLoader.configPathsFromArg();
|
|
33
|
+
const config = (await utils_1.ConfigurationLoader.getConfiguration(configPathFromArg ?? utils_1.ConfigurationLoader.getConfigPaths()));
|
|
34
|
+
options = config.getAll();
|
|
35
|
+
if (configPathFromArg) {
|
|
36
|
+
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' });
|
|
37
|
+
}
|
|
33
38
|
}
|
|
34
39
|
options = utils_1.Utils.mergeConfig(options, env);
|
|
35
40
|
await utils_1.ConfigurationLoader.commonJSCompat(options);
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export declare function CreateRequestContext<T>(getContext?: MikroORM | Promise<MikroORM> | ((type: T) => MikroORM | Promise<MikroORM> | EntityManager | EntityRepository<any> | {
|
|
5
|
-
getEntityManager(): EntityManager;
|
|
6
|
-
}), respectExistingContext?: boolean): MethodDecorator;
|
|
7
|
-
export declare function EnsureRequestContext<T>(getContext?: MikroORM | Promise<MikroORM> | ((type: T) => MikroORM | Promise<MikroORM> | EntityManager | EntityRepository<any> | {
|
|
8
|
-
getEntityManager(): EntityManager;
|
|
9
|
-
})): MethodDecorator;
|
|
1
|
+
import type { ContextProvider } from '../typings';
|
|
2
|
+
export declare function CreateRequestContext<T extends object>(context?: ContextProvider<T>, respectExistingContext?: boolean): MethodDecorator;
|
|
3
|
+
export declare function EnsureRequestContext<T extends object>(context?: ContextProvider<T>): MethodDecorator;
|
|
@@ -2,59 +2,32 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CreateRequestContext = CreateRequestContext;
|
|
4
4
|
exports.EnsureRequestContext = EnsureRequestContext;
|
|
5
|
-
const MikroORM_1 = require("../MikroORM");
|
|
6
5
|
const RequestContext_1 = require("../utils/RequestContext");
|
|
7
|
-
const
|
|
8
|
-
const EntityRepository_1 = require("../entity/EntityRepository");
|
|
6
|
+
const resolveContextProvider_1 = require("../utils/resolveContextProvider");
|
|
9
7
|
const TransactionContext_1 = require("../utils/TransactionContext");
|
|
10
|
-
function CreateRequestContext(
|
|
8
|
+
function CreateRequestContext(context, respectExistingContext = false) {
|
|
11
9
|
return function (target, propertyKey, descriptor) {
|
|
12
10
|
const originalMethod = descriptor.value;
|
|
13
11
|
descriptor.value = async function (...args) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const provider = txContext ? TransactionContext_1.TransactionContext : RequestContext_1.RequestContext;
|
|
17
|
-
let orm;
|
|
18
|
-
let em;
|
|
19
|
-
if (typeof getContext === 'function') {
|
|
20
|
-
const context = await getContext(this);
|
|
21
|
-
orm = context ?? await this.orm;
|
|
22
|
-
em = context ?? await this.em;
|
|
23
|
-
}
|
|
24
|
-
else if (getContext) {
|
|
25
|
-
orm = em = await getContext;
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
orm = await this.orm;
|
|
29
|
-
em = await this.em;
|
|
30
|
-
}
|
|
31
|
-
const create = async (em) => {
|
|
32
|
-
// reuse existing context if available for given respect `contextName`
|
|
33
|
-
if (respectExistingContext && RequestContext_1.RequestContext.getEntityManager(em.name)) {
|
|
34
|
-
return originalMethod.apply(this, args);
|
|
35
|
-
}
|
|
36
|
-
if (txContext) {
|
|
37
|
-
em = em.fork({ useContext: true });
|
|
38
|
-
}
|
|
39
|
-
return await provider.create(em, () => {
|
|
40
|
-
return originalMethod.apply(this, args);
|
|
41
|
-
});
|
|
42
|
-
};
|
|
43
|
-
if (em instanceof EntityManager_1.EntityManager) {
|
|
44
|
-
return await create(em);
|
|
45
|
-
}
|
|
46
|
-
if (orm instanceof EntityRepository_1.EntityRepository) {
|
|
47
|
-
return await create(orm.getEntityManager());
|
|
48
|
-
}
|
|
49
|
-
if (!(orm instanceof MikroORM_1.MikroORM)) {
|
|
12
|
+
const em = await (0, resolveContextProvider_1.resolveContextProvider)(this, context);
|
|
13
|
+
if (!em) {
|
|
50
14
|
const name = respectExistingContext ? 'EnsureRequestContext' : 'CreateRequestContext';
|
|
51
15
|
throw new Error(`@${name}() decorator can only be applied to methods of classes with \`orm: MikroORM\` property, \`em: EntityManager\` property, or with a callback parameter like \`@${name}(() => orm)\` that returns one of those types. The parameter will contain a reference to current \`this\`. Returning an EntityRepository from it is also supported.`);
|
|
52
16
|
}
|
|
53
|
-
|
|
17
|
+
// reuse existing context if available for given respect `contextName`
|
|
18
|
+
if (respectExistingContext && RequestContext_1.RequestContext.getEntityManager(em.name)) {
|
|
19
|
+
return originalMethod.apply(this, args);
|
|
20
|
+
}
|
|
21
|
+
// Otherwise, the outer tx context would be preferred.
|
|
22
|
+
const txContext = TransactionContext_1.TransactionContext.currentTransactionContext();
|
|
23
|
+
const provider = txContext ? TransactionContext_1.TransactionContext : RequestContext_1.RequestContext;
|
|
24
|
+
return txContext
|
|
25
|
+
? provider.create(em.fork({ useContext: true }), () => originalMethod.apply(this, args))
|
|
26
|
+
: provider.create(em, () => originalMethod.apply(this, args));
|
|
54
27
|
};
|
|
55
28
|
return descriptor;
|
|
56
29
|
};
|
|
57
30
|
}
|
|
58
|
-
function EnsureRequestContext(
|
|
59
|
-
return CreateRequestContext(
|
|
31
|
+
function EnsureRequestContext(context) {
|
|
32
|
+
return CreateRequestContext(context, true);
|
|
60
33
|
}
|
|
@@ -15,6 +15,8 @@ export interface ManyToOneOptions<Owner, Target> extends ReferenceOptions<Owner,
|
|
|
15
15
|
joinColumn?: string;
|
|
16
16
|
/** Override the default database column name on the owning side (see {@doclink naming-strategy | Naming Strategy}). This option is suitable for composite keys, where one property is represented by multiple columns. */
|
|
17
17
|
joinColumns?: string[];
|
|
18
|
+
/** When a part of a composite column is shared in other properties, use this option to specify what columns are considered as owned by this property. This is useful when your composite property is nullable, but parts of it are not. */
|
|
19
|
+
ownColumns?: string[];
|
|
18
20
|
/** Override the default database column name on the target entity (see {@doclink naming-strategy | Naming Strategy}). This option is only for simple properties represented by a single column. */
|
|
19
21
|
referenceColumnName?: string;
|
|
20
22
|
/** Override the default database column name on the target entity (see {@doclink naming-strategy | Naming Strategy}). This option is suitable for composite keys, where one property is represented by multiple columns. */
|
package/decorators/Property.d.ts
CHANGED
|
@@ -177,6 +177,19 @@ export interface PropertyOptions<Owner> {
|
|
|
177
177
|
* ```
|
|
178
178
|
*/
|
|
179
179
|
getter?: boolean;
|
|
180
|
+
/**
|
|
181
|
+
* When defining a property over a method (not a getter, a regular function), you can use this option to point
|
|
182
|
+
* to the method name.
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```
|
|
186
|
+
* @Property({ getter: true })
|
|
187
|
+
* getFullName() {
|
|
188
|
+
* return this.firstName + this.lastName;
|
|
189
|
+
* }
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
getterName?: keyof Owner;
|
|
180
193
|
/**
|
|
181
194
|
* Set to define serialized primary key for MongoDB. (virtual)
|
|
182
195
|
* Alias for `@SerializedPrimaryKey()` decorator.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TransactionOptions } from '../enums';
|
|
2
|
+
import type { ContextProvider } from '../typings';
|
|
3
|
+
type TransactionalOptions<T> = TransactionOptions & {
|
|
4
|
+
context?: ContextProvider<T>;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* This decorator wraps the method with `em.transactional()`, so you can provide `TransactionOptions` just like with `em.transactional()`.
|
|
8
|
+
* The difference is that you can specify the context in which the transaction begins by providing `context` option,
|
|
9
|
+
* and if omitted, the transaction will begin in the current context implicitly.
|
|
10
|
+
* It works on async functions and can be nested with `em.transactional()`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function Transactional<T extends object>(options?: TransactionalOptions<T>): MethodDecorator;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Transactional = Transactional;
|
|
4
|
+
const RequestContext_1 = require("../utils/RequestContext");
|
|
5
|
+
const resolveContextProvider_1 = require("../utils/resolveContextProvider");
|
|
6
|
+
const TransactionContext_1 = require("../utils/TransactionContext");
|
|
7
|
+
/**
|
|
8
|
+
* This decorator wraps the method with `em.transactional()`, so you can provide `TransactionOptions` just like with `em.transactional()`.
|
|
9
|
+
* The difference is that you can specify the context in which the transaction begins by providing `context` option,
|
|
10
|
+
* and if omitted, the transaction will begin in the current context implicitly.
|
|
11
|
+
* It works on async functions and can be nested with `em.transactional()`.
|
|
12
|
+
*/
|
|
13
|
+
function Transactional(options = {}) {
|
|
14
|
+
return function (target, propertyKey, descriptor) {
|
|
15
|
+
const originalMethod = descriptor.value;
|
|
16
|
+
if (originalMethod.constructor.name !== 'AsyncFunction') {
|
|
17
|
+
throw new Error('@Transactional() should be use with async functions');
|
|
18
|
+
}
|
|
19
|
+
descriptor.value = async function (...args) {
|
|
20
|
+
const { context, ...txOptions } = options;
|
|
21
|
+
const em = await (0, resolveContextProvider_1.resolveContextProvider)(this, context)
|
|
22
|
+
|| TransactionContext_1.TransactionContext.getEntityManager()
|
|
23
|
+
|| RequestContext_1.RequestContext.getEntityManager();
|
|
24
|
+
if (!em) {
|
|
25
|
+
throw new Error(`@Transactional() decorator can only be applied to methods of classes with \`orm: MikroORM\` property, \`em: EntityManager\` property, or with a callback parameter like \`@Transactional(() => orm)\` that returns one of those types. The parameter will contain a reference to current \`this\`. Returning an EntityRepository from it is also supported.`);
|
|
26
|
+
}
|
|
27
|
+
return em.transactional(() => originalMethod.apply(this, args), txOptions);
|
|
28
|
+
};
|
|
29
|
+
return descriptor;
|
|
30
|
+
};
|
|
31
|
+
}
|
package/decorators/index.d.ts
CHANGED
package/decorators/index.js
CHANGED
|
@@ -223,7 +223,7 @@ class DatabaseDriver {
|
|
|
223
223
|
}
|
|
224
224
|
if (prop.joinColumns?.length > 1 && data[k] == null) {
|
|
225
225
|
delete data[k];
|
|
226
|
-
prop.
|
|
226
|
+
prop.ownColumns.forEach(joinColumn => data[joinColumn] = null);
|
|
227
227
|
return;
|
|
228
228
|
}
|
|
229
229
|
if (prop.customType && convertCustomTypes && !(prop.customType instanceof JsonType_1.JsonType && object) && !this.platform.isRaw(data[k])) {
|
|
@@ -354,16 +354,11 @@ class DatabaseDriver {
|
|
|
354
354
|
*/
|
|
355
355
|
getTableName(meta, options, quote = true) {
|
|
356
356
|
const schema = this.getSchemaName(meta, options);
|
|
357
|
-
|
|
358
|
-
if (quote) {
|
|
359
|
-
return this.platform.quoteIdentifier(schema + '.' + meta.tableName);
|
|
360
|
-
}
|
|
361
|
-
return schema + '.' + meta.tableName;
|
|
362
|
-
}
|
|
357
|
+
const tableName = schema ? `${schema}.${meta.tableName}` : meta.tableName;
|
|
363
358
|
if (quote) {
|
|
364
|
-
return this.platform.quoteIdentifier(
|
|
359
|
+
return this.platform.quoteIdentifier(tableName);
|
|
365
360
|
}
|
|
366
|
-
return
|
|
361
|
+
return tableName;
|
|
367
362
|
}
|
|
368
363
|
/**
|
|
369
364
|
* @internal
|
package/entity/BaseEntity.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export declare abstract class BaseEntity {
|
|
|
14
14
|
toObject<Entity extends this = this>(ignoreFields: never[]): EntityDTO<Entity>;
|
|
15
15
|
toObject<Entity extends this = this, Ignored extends EntityKey<Entity> = never>(ignoreFields: Ignored[]): Omit<EntityDTO<Entity>, Ignored>;
|
|
16
16
|
toPOJO<Entity extends this = this>(): EntityDTO<Entity>;
|
|
17
|
-
serialize<Entity extends this = this, Hint extends string = never, Exclude extends string = never>(options?: SerializeOptions<
|
|
17
|
+
serialize<Entity extends this = this, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Hint extends string = never, Exclude extends string = never>(options?: SerializeOptions<Naked, Hint, Exclude>): EntityDTO<Loaded<Naked, Hint>>;
|
|
18
18
|
assign<Entity extends this, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Convert extends boolean = false, Data extends EntityData<Naked, Convert> | Partial<EntityDTO<Naked>> = EntityData<Naked, Convert> | Partial<EntityDTO<Naked>>>(data: Data & IsSubset<EntityData<Naked>, Data>, options?: AssignOptions<Convert>): MergeSelected<Entity, Naked, keyof Data & string>;
|
|
19
19
|
init<Entity extends this = this, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(options?: FindOneOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
|
|
20
20
|
getSchema(): string | undefined;
|
package/entity/EntityFactory.js
CHANGED
|
@@ -69,6 +69,12 @@ class EntityFactory {
|
|
|
69
69
|
if (options.convertCustomTypes) {
|
|
70
70
|
for (const prop of meta.props) {
|
|
71
71
|
if (prop.customType?.ensureComparable(meta, prop) && data[prop.name]) {
|
|
72
|
+
if ([enums_1.ReferenceKind.ONE_TO_MANY, enums_1.ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if ([enums_1.ReferenceKind.MANY_TO_ONE, enums_1.ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils_1.Utils.isPlainObject(data[prop.name])) {
|
|
76
|
+
data[prop.name] = Utils_1.Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta.primaryKeys, true);
|
|
77
|
+
}
|
|
72
78
|
data[prop.name] = prop.customType.convertToDatabaseValue(data[prop.name], this.platform, { key: prop.name, mode: 'hydration' });
|
|
73
79
|
}
|
|
74
80
|
}
|
|
@@ -244,7 +250,7 @@ class EntityFactory {
|
|
|
244
250
|
if (!Array.isArray(data) && meta.primaryKeys.some(pk => data[pk] == null)) {
|
|
245
251
|
return undefined;
|
|
246
252
|
}
|
|
247
|
-
const pks = Utils_1.Utils.getOrderedPrimaryKeys(data, meta, this.platform
|
|
253
|
+
const pks = Utils_1.Utils.getOrderedPrimaryKeys(data, meta, this.platform);
|
|
248
254
|
return this.unitOfWork.getById(meta.className, pks, schema);
|
|
249
255
|
}
|
|
250
256
|
processDiscriminatorColumn(meta, data) {
|
package/entity/EntityHelper.js
CHANGED
|
@@ -176,10 +176,15 @@ class EntityHelper {
|
|
|
176
176
|
inverse.addWithoutPropagation(owner);
|
|
177
177
|
(0, wrap_1.helper)(owner).__em?.getUnitOfWork().cancelOrphanRemoval(owner);
|
|
178
178
|
}
|
|
179
|
-
if (prop.kind === enums_1.ReferenceKind.ONE_TO_ONE
|
|
179
|
+
if (prop.kind === enums_1.ReferenceKind.ONE_TO_ONE) {
|
|
180
180
|
if ((value != null && Reference_1.Reference.unwrapReference(inverse) !== owner) ||
|
|
181
|
-
(value == null && entity[prop2.name] != null)) {
|
|
182
|
-
|
|
181
|
+
(value == null && entity?.[prop2.name] != null)) {
|
|
182
|
+
if (entity && (!prop.owner || (0, wrap_1.helper)(entity).__initialized)) {
|
|
183
|
+
EntityHelper.propagateOneToOne(entity, owner, prop, prop2, value, old);
|
|
184
|
+
}
|
|
185
|
+
if (old && prop.orphanRemoval) {
|
|
186
|
+
(0, wrap_1.helper)(old).__em?.getUnitOfWork().scheduleOrphanRemoval(old);
|
|
187
|
+
}
|
|
183
188
|
}
|
|
184
189
|
}
|
|
185
190
|
}
|
|
@@ -203,9 +208,6 @@ class EntityHelper {
|
|
|
203
208
|
else {
|
|
204
209
|
entity[prop2.name] = Reference_1.Reference.wrapReference(owner, prop);
|
|
205
210
|
}
|
|
206
|
-
if (old && prop.orphanRemoval) {
|
|
207
|
-
(0, wrap_1.helper)(old).__em?.getUnitOfWork().scheduleOrphanRemoval(old);
|
|
208
|
-
}
|
|
209
211
|
if (old?.[prop2.name] != null) {
|
|
210
212
|
delete (0, wrap_1.helper)(old).__data[prop2.name];
|
|
211
213
|
}
|
package/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
* @module core
|
|
4
4
|
*/
|
|
5
|
-
export { Constructor, ConnectionType, Dictionary, PrimaryKeyProp, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, AnyEntity, EntityClass, EntityProperty, EntityMetadata, QBFilterQuery, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, GetRepository, EntityRepositoryType, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, EntityClassGroup, OptionalProps, EagerProps, HiddenProps, RequiredEntityData, CheckCallback, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, FilterKey, Opt, EntityType, FromEntityType, Selected, IsSubset, NoInfer, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, Hidden, FilterValue, MergeLoaded, MergeSelected, Config, DefineConfig, TypeConfig, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, } from './typings';
|
|
5
|
+
export { Constructor, ConnectionType, Dictionary, PrimaryKeyProp, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, EntityMetadata, QBFilterQuery, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, EntityRepositoryType, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, EntityClassGroup, OptionalProps, EagerProps, HiddenProps, RequiredEntityData, CheckCallback, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, FilterKey, Opt, EntityType, FromEntityType, Selected, IsSubset, NoInfer, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, Hidden, FilterValue, MergeLoaded, MergeSelected, Config, DefineConfig, TypeConfig, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, } from './typings';
|
|
6
6
|
export * from './enums';
|
|
7
7
|
export * from './errors';
|
|
8
8
|
export * from './exceptions';
|
package/index.mjs
CHANGED
|
@@ -162,6 +162,7 @@ export const TimeType = mod.TimeType;
|
|
|
162
162
|
export const TinyIntType = mod.TinyIntType;
|
|
163
163
|
export const TransactionContext = mod.TransactionContext;
|
|
164
164
|
export const TransactionEventBroadcaster = mod.TransactionEventBroadcaster;
|
|
165
|
+
export const Transactional = mod.Transactional;
|
|
165
166
|
export const Type = mod.Type;
|
|
166
167
|
export const Uint8ArrayType = mod.Uint8ArrayType;
|
|
167
168
|
export const UnderscoreNamingStrategy = mod.UnderscoreNamingStrategy;
|
package/logging/DefaultLogger.js
CHANGED
|
@@ -60,6 +60,12 @@ class DefaultLogger {
|
|
|
60
60
|
return context.enabled;
|
|
61
61
|
}
|
|
62
62
|
const debugMode = context?.debugMode ?? this.debugMode;
|
|
63
|
+
if (namespace === 'deprecated') {
|
|
64
|
+
const { ignoreDeprecations = false } = this.options;
|
|
65
|
+
return Array.isArray(ignoreDeprecations)
|
|
66
|
+
? !ignoreDeprecations.includes(context?.label ?? '')
|
|
67
|
+
: !ignoreDeprecations;
|
|
68
|
+
}
|
|
63
69
|
return !!debugMode && (!Array.isArray(debugMode) || debugMode.includes(namespace));
|
|
64
70
|
}
|
|
65
71
|
/**
|
package/logging/Logger.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export interface Logger {
|
|
|
22
22
|
setDebugMode(debugMode: boolean | LoggerNamespace[]): void;
|
|
23
23
|
isEnabled(namespace: LoggerNamespace, context?: LogContext): boolean;
|
|
24
24
|
}
|
|
25
|
-
export type LoggerNamespace = 'query' | 'query-params' | 'schema' | 'discovery' | 'info';
|
|
25
|
+
export type LoggerNamespace = 'query' | 'query-params' | 'schema' | 'discovery' | 'info' | 'deprecated';
|
|
26
26
|
export interface LogContext extends Dictionary {
|
|
27
27
|
query?: string;
|
|
28
28
|
label?: string;
|
|
@@ -41,6 +41,7 @@ export interface LogContext extends Dictionary {
|
|
|
41
41
|
export interface LoggerOptions {
|
|
42
42
|
writer: (message: string) => void;
|
|
43
43
|
debugMode?: boolean | LoggerNamespace[];
|
|
44
|
+
ignoreDeprecations?: boolean | string[];
|
|
44
45
|
highlighter?: Highlighter;
|
|
45
46
|
usesReplicas?: boolean;
|
|
46
47
|
}
|
|
@@ -361,6 +361,22 @@ class MetadataDiscovery {
|
|
|
361
361
|
this.initOneToManyFields(prop);
|
|
362
362
|
}
|
|
363
363
|
}
|
|
364
|
+
initOwnColumns(meta) {
|
|
365
|
+
meta.sync();
|
|
366
|
+
for (const prop of meta.props) {
|
|
367
|
+
if (!prop.joinColumns || prop.ownColumns) {
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
if (prop.joinColumns.length > 1) {
|
|
371
|
+
prop.ownColumns = prop.joinColumns.filter(col => {
|
|
372
|
+
return !meta.props.find(p => p.name !== prop.name && (!p.fieldNames || p.fieldNames.includes(col)));
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
if (!prop.ownColumns || prop.ownColumns.length === 0) {
|
|
376
|
+
prop.ownColumns = prop.joinColumns;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
364
380
|
initFieldName(prop, object = false) {
|
|
365
381
|
if (prop.fieldNames && prop.fieldNames.length > 0) {
|
|
366
382
|
return;
|
|
@@ -469,6 +485,7 @@ class MetadataDiscovery {
|
|
|
469
485
|
this.initColumnType(prop);
|
|
470
486
|
this.initRelation(prop);
|
|
471
487
|
}
|
|
488
|
+
this.initOwnColumns(meta);
|
|
472
489
|
meta.simplePK = pks.length === 1 && pks[0].kind === enums_1.ReferenceKind.SCALAR && !pks[0].customType && pks[0].runtimeType !== 'Date';
|
|
473
490
|
meta.serializedPrimaryKey = this.platform.getSerializedPrimaryKeyField(meta.primaryKeys[0]);
|
|
474
491
|
const serializedPKProp = meta.properties[meta.serializedPrimaryKey];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
|
-
"version": "6.3.14-dev.
|
|
3
|
+
"version": "6.3.14-dev.60",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"esprima": "4.0.1",
|
|
65
65
|
"fs-extra": "11.2.0",
|
|
66
66
|
"globby": "11.1.0",
|
|
67
|
-
"mikro-orm": "6.3.14-dev.
|
|
67
|
+
"mikro-orm": "6.3.14-dev.60",
|
|
68
68
|
"reflect-metadata": "0.2.2"
|
|
69
69
|
}
|
|
70
70
|
}
|
|
@@ -111,7 +111,7 @@ class EntitySerializer {
|
|
|
111
111
|
const parts = prop.split('.');
|
|
112
112
|
prop = parts[0];
|
|
113
113
|
const wrapped = (0, wrap_1.helper)(entity);
|
|
114
|
-
const property = wrapped.__meta.properties[prop];
|
|
114
|
+
const property = wrapped.__meta.properties[prop] ?? { name: prop };
|
|
115
115
|
const serializer = property?.serializer;
|
|
116
116
|
const value = entity[prop];
|
|
117
117
|
// getter method
|
|
@@ -127,10 +127,10 @@ class EntitySerializer {
|
|
|
127
127
|
return serializer(value);
|
|
128
128
|
}
|
|
129
129
|
if (Utils_1.Utils.isCollection(value)) {
|
|
130
|
-
return this.processCollection(
|
|
130
|
+
return this.processCollection(property, entity, options);
|
|
131
131
|
}
|
|
132
132
|
if (Utils_1.Utils.isEntity(value, true)) {
|
|
133
|
-
return this.processEntity(
|
|
133
|
+
return this.processEntity(property, entity, wrapped.__platform, options);
|
|
134
134
|
}
|
|
135
135
|
if (Utils_1.Utils.isScalarReference(value)) {
|
|
136
136
|
return value.unwrap();
|
|
@@ -158,17 +158,20 @@ class EntitySerializer {
|
|
|
158
158
|
};
|
|
159
159
|
}
|
|
160
160
|
static processEntity(prop, entity, platform, options) {
|
|
161
|
-
const child = Reference_1.Reference.unwrapReference(entity[prop]);
|
|
161
|
+
const child = Reference_1.Reference.unwrapReference(entity[prop.name]);
|
|
162
162
|
const wrapped = (0, wrap_1.helper)(child);
|
|
163
|
-
const populated = isPopulated(prop, options) && wrapped.isInitialized();
|
|
163
|
+
const populated = isPopulated(prop.name, options) && wrapped.isInitialized();
|
|
164
164
|
const expand = populated || !wrapped.__managed;
|
|
165
165
|
const meta = wrapped.__meta;
|
|
166
|
-
const childOptions = this.extractChildOptions(options, prop);
|
|
166
|
+
const childOptions = this.extractChildOptions(options, prop.name);
|
|
167
167
|
const visible = meta.primaryKeys.filter(prop => isVisible(meta, prop, childOptions));
|
|
168
168
|
if (expand) {
|
|
169
169
|
return this.serialize(child, childOptions);
|
|
170
170
|
}
|
|
171
|
-
|
|
171
|
+
let pk = wrapped.getPrimaryKey();
|
|
172
|
+
if (prop.customType) {
|
|
173
|
+
pk = prop.customType.toJSON(pk, wrapped.__platform);
|
|
174
|
+
}
|
|
172
175
|
if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
|
|
173
176
|
return Utils_1.Utils.primaryKeyToObject(meta, pk, visible);
|
|
174
177
|
}
|
|
@@ -182,20 +185,24 @@ class EntitySerializer {
|
|
|
182
185
|
return platform.normalizePrimaryKey(pk);
|
|
183
186
|
}
|
|
184
187
|
static processCollection(prop, entity, options) {
|
|
185
|
-
const col = entity[prop];
|
|
188
|
+
const col = entity[prop.name];
|
|
186
189
|
if (!col.isInitialized()) {
|
|
187
190
|
return undefined;
|
|
188
191
|
}
|
|
189
192
|
return col.getItems(false).map(item => {
|
|
190
|
-
const populated = isPopulated(prop, options);
|
|
193
|
+
const populated = isPopulated(prop.name, options);
|
|
191
194
|
const wrapped = (0, wrap_1.helper)(item);
|
|
192
195
|
if (populated || !wrapped.__managed) {
|
|
193
|
-
return this.serialize(item, this.extractChildOptions(options, prop));
|
|
196
|
+
return this.serialize(item, this.extractChildOptions(options, prop.name));
|
|
197
|
+
}
|
|
198
|
+
let pk = wrapped.getPrimaryKey();
|
|
199
|
+
if (prop.customType) {
|
|
200
|
+
pk = prop.customType.toJSON(pk, wrapped.__platform);
|
|
194
201
|
}
|
|
195
202
|
if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
|
|
196
|
-
return Utils_1.Utils.primaryKeyToObject(wrapped.__meta,
|
|
203
|
+
return Utils_1.Utils.primaryKeyToObject(wrapped.__meta, pk);
|
|
197
204
|
}
|
|
198
|
-
return
|
|
205
|
+
return pk;
|
|
199
206
|
});
|
|
200
207
|
}
|
|
201
208
|
}
|
|
@@ -18,6 +18,9 @@ class EntityTransformer {
|
|
|
18
18
|
}
|
|
19
19
|
const wrapped = (0, wrap_1.helper)(entity);
|
|
20
20
|
let contextCreated = false;
|
|
21
|
+
if (!wrapped) {
|
|
22
|
+
return entity;
|
|
23
|
+
}
|
|
21
24
|
if (!wrapped.__serializationContext.root) {
|
|
22
25
|
const root = new SerializationContext_1.SerializationContext(wrapped.__config, wrapped.__serializationContext.populate, wrapped.__serializationContext.fields, wrapped.__serializationContext.exclude);
|
|
23
26
|
SerializationContext_1.SerializationContext.propagate(root, entity, isVisible);
|
|
@@ -108,7 +111,7 @@ class EntityTransformer {
|
|
|
108
111
|
}
|
|
109
112
|
static processProperty(prop, entity, raw, populated) {
|
|
110
113
|
const wrapped = (0, wrap_1.helper)(entity);
|
|
111
|
-
const property = wrapped.__meta.properties[prop];
|
|
114
|
+
const property = wrapped.__meta.properties[prop] ?? { name: prop };
|
|
112
115
|
const serializer = property?.serializer;
|
|
113
116
|
const value = entity[prop];
|
|
114
117
|
// getter method
|
|
@@ -123,10 +126,10 @@ class EntityTransformer {
|
|
|
123
126
|
return serializer(value);
|
|
124
127
|
}
|
|
125
128
|
if (Utils_1.Utils.isCollection(value)) {
|
|
126
|
-
return EntityTransformer.processCollection(
|
|
129
|
+
return EntityTransformer.processCollection(property, entity, raw, populated);
|
|
127
130
|
}
|
|
128
131
|
if (Utils_1.Utils.isEntity(value, true)) {
|
|
129
|
-
return EntityTransformer.processEntity(
|
|
132
|
+
return EntityTransformer.processEntity(property, entity, wrapped.__platform, raw, populated);
|
|
130
133
|
}
|
|
131
134
|
if (Utils_1.Utils.isScalarReference(value)) {
|
|
132
135
|
return value.unwrap();
|
|
@@ -151,7 +154,7 @@ class EntityTransformer {
|
|
|
151
154
|
return value;
|
|
152
155
|
}
|
|
153
156
|
static processEntity(prop, entity, platform, raw, populated) {
|
|
154
|
-
const child = entity[prop];
|
|
157
|
+
const child = entity[prop.name];
|
|
155
158
|
const wrapped = (0, wrap_1.helper)(child);
|
|
156
159
|
const meta = wrapped.__meta;
|
|
157
160
|
const visible = meta.primaryKeys.filter(prop => isVisible(meta, prop));
|
|
@@ -170,7 +173,10 @@ class EntityTransformer {
|
|
|
170
173
|
if (wrapped.isInitialized() && isPopulated() && child !== entity) {
|
|
171
174
|
return (0, wrap_1.wrap)(child).toJSON();
|
|
172
175
|
}
|
|
173
|
-
|
|
176
|
+
let pk = wrapped.getPrimaryKey();
|
|
177
|
+
if (prop.customType) {
|
|
178
|
+
pk = prop.customType.toJSON(pk, wrapped.__platform);
|
|
179
|
+
}
|
|
174
180
|
if (wrapped.__config.get('serialization').forceObject) {
|
|
175
181
|
return Utils_1.Utils.primaryKeyToObject(meta, pk, visible);
|
|
176
182
|
}
|
|
@@ -184,7 +190,7 @@ class EntityTransformer {
|
|
|
184
190
|
return platform.normalizePrimaryKey(pk);
|
|
185
191
|
}
|
|
186
192
|
static processCollection(prop, entity, raw, populated) {
|
|
187
|
-
const col = entity[prop];
|
|
193
|
+
const col = entity[prop.name];
|
|
188
194
|
if (raw && col.isInitialized(true)) {
|
|
189
195
|
return col.map(item => (0, wrap_1.helper)(item).toPOJO());
|
|
190
196
|
}
|
|
@@ -193,13 +199,18 @@ class EntityTransformer {
|
|
|
193
199
|
}
|
|
194
200
|
if (col.isInitialized()) {
|
|
195
201
|
const wrapped = (0, wrap_1.helper)(entity);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
202
|
+
const forceObject = wrapped.__config.get('serialization').forceObject;
|
|
203
|
+
return col.map(item => {
|
|
204
|
+
const wrapped = (0, wrap_1.helper)(item);
|
|
205
|
+
const pk = wrapped.getPrimaryKey();
|
|
206
|
+
if (prop.customType) {
|
|
207
|
+
return prop.customType.toJSON(pk, wrapped.__platform);
|
|
208
|
+
}
|
|
209
|
+
if (forceObject) {
|
|
210
|
+
return Utils_1.Utils.primaryKeyToObject(wrapped.__meta, pk);
|
|
211
|
+
}
|
|
212
|
+
return pk;
|
|
213
|
+
});
|
|
203
214
|
}
|
|
204
215
|
return undefined;
|
|
205
216
|
}
|
package/types/DecimalType.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export declare class DecimalType extends Type<string | number, string> {
|
|
|
8
8
|
mode?: ("number" | "string") | undefined;
|
|
9
9
|
constructor(mode?: ("number" | "string") | undefined);
|
|
10
10
|
convertToJSValue(value: string): number | string;
|
|
11
|
+
compareValues(a: string, b: string): boolean;
|
|
12
|
+
private format;
|
|
11
13
|
getColumnType(prop: EntityProperty, platform: Platform): string;
|
|
12
14
|
compareAsType(): string;
|
|
13
15
|
}
|
package/types/DecimalType.js
CHANGED
|
@@ -17,6 +17,17 @@ class DecimalType extends Type_1.Type {
|
|
|
17
17
|
}
|
|
18
18
|
return value;
|
|
19
19
|
}
|
|
20
|
+
compareValues(a, b) {
|
|
21
|
+
return this.format(a) === this.format(b);
|
|
22
|
+
}
|
|
23
|
+
format(val) {
|
|
24
|
+
/* istanbul ignore next */
|
|
25
|
+
if (this.prop?.scale == null) {
|
|
26
|
+
return +val;
|
|
27
|
+
}
|
|
28
|
+
const base = Math.pow(10, this.prop.scale);
|
|
29
|
+
return Math.round((+val + Number.EPSILON) * base) / base;
|
|
30
|
+
}
|
|
20
31
|
getColumnType(prop, platform) {
|
|
21
32
|
return platform.getDecimalTypeDeclarationSQL(prop);
|
|
22
33
|
}
|
package/typings.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Transaction } from './connections';
|
|
2
2
|
import { type Cascade, type DeferMode, type EventType, type LoadStrategy, type PopulatePath, type QueryOrderMap, ReferenceKind } from './enums';
|
|
3
3
|
import { type AssignOptions, type Collection, type EntityFactory, type EntityIdentifier, type EntityLoaderOptions, type EntityRepository, Reference, type ScalarReference } from './entity';
|
|
4
|
+
import type { MikroORM } from './MikroORM';
|
|
4
5
|
import type { SerializationContext, SerializeOptions } from './serialization';
|
|
5
6
|
import type { EntitySchema, MetadataStorage } from './metadata';
|
|
6
7
|
import type { Type, types } from './types';
|
|
@@ -143,7 +144,7 @@ export interface IWrappedEntity<Entity extends object> {
|
|
|
143
144
|
toObject<Ignored extends EntityKey<Entity>>(ignoreFields: Ignored[]): Omit<EntityDTO<Entity>, Ignored>;
|
|
144
145
|
toJSON(...args: any[]): EntityDTO<Entity>;
|
|
145
146
|
toPOJO(): EntityDTO<Entity>;
|
|
146
|
-
serialize<Hint extends string = never, Exclude extends string = never>(options?: SerializeOptions<
|
|
147
|
+
serialize<Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Hint extends string = never, Exclude extends string = never>(options?: SerializeOptions<Naked, Hint, Exclude>): EntityDTO<Loaded<Naked, Hint>>;
|
|
147
148
|
setSerializationContext<Hint extends string = never, Fields extends string = '*', Exclude extends string = never>(options: LoadHint<Entity, Hint, Fields, Exclude>): void;
|
|
148
149
|
assign<Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Convert extends boolean = false, Data extends EntityData<Naked, Convert> | Partial<EntityDTO<Naked>> = EntityData<Naked, Convert> | Partial<EntityDTO<Naked>>>(data: Data & IsSubset<EntityData<Naked, Convert>, Data>, options?: AssignOptions<Convert>): MergeSelected<Entity, Naked, keyof Data & string>;
|
|
149
150
|
getSchema(): string | undefined;
|
|
@@ -364,6 +365,7 @@ export interface EntityProperty<Owner = any, Target = any> {
|
|
|
364
365
|
pivotTable: string;
|
|
365
366
|
pivotEntity: string;
|
|
366
367
|
joinColumns: string[];
|
|
368
|
+
ownColumns: string[];
|
|
367
369
|
inverseJoinColumns: string[];
|
|
368
370
|
referencedColumnNames: string[];
|
|
369
371
|
referencedTableName: string;
|
|
@@ -626,11 +628,20 @@ export interface IMigrator {
|
|
|
626
628
|
* Executes down migrations to the given point. Without parameter it will migrate one version down.
|
|
627
629
|
*/
|
|
628
630
|
down(options?: string | string[] | MigrateOptions): Promise<UmzugMigration[]>;
|
|
631
|
+
/**
|
|
632
|
+
* Registers event handler.
|
|
633
|
+
*/
|
|
634
|
+
on(event: MigratorEvent, listener: (event: UmzugMigration) => MaybePromise<void>): IMigrator;
|
|
635
|
+
/**
|
|
636
|
+
* Removes event handler.
|
|
637
|
+
*/
|
|
638
|
+
off(event: MigratorEvent, listener: (event: UmzugMigration) => MaybePromise<void>): IMigrator;
|
|
629
639
|
/**
|
|
630
640
|
* @internal
|
|
631
641
|
*/
|
|
632
642
|
getStorage(): IMigratorStorage;
|
|
633
643
|
}
|
|
644
|
+
export type MigratorEvent = 'migrating' | 'migrated' | 'reverting' | 'reverted';
|
|
634
645
|
export interface MigrationDiff {
|
|
635
646
|
up: string[];
|
|
636
647
|
down: string[];
|
|
@@ -786,4 +797,10 @@ export interface Seeder<T extends Dictionary = Dictionary> {
|
|
|
786
797
|
}
|
|
787
798
|
export type ConnectionType = 'read' | 'write';
|
|
788
799
|
export type MetadataProcessor = (metadata: EntityMetadata[], platform: Platform) => MaybePromise<void>;
|
|
800
|
+
/**
|
|
801
|
+
* The type of context that the user intends to inject.
|
|
802
|
+
*/
|
|
803
|
+
export type ContextProvider<T> = MaybePromise<MikroORM> | ((type: T) => MaybePromise<MikroORM | EntityManager | EntityRepository<any> | {
|
|
804
|
+
getEntityManager(): EntityManager;
|
|
805
|
+
}>);
|
|
789
806
|
export {};
|
package/utils/Configuration.d.ts
CHANGED
|
@@ -57,6 +57,7 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
57
57
|
populateWhere: PopulateHint.ALL;
|
|
58
58
|
connect: true;
|
|
59
59
|
ignoreUndefinedInQuery: false;
|
|
60
|
+
onQuery: (sql: string) => string;
|
|
60
61
|
autoJoinOneToOneOwner: true;
|
|
61
62
|
autoJoinRefsForFilters: true;
|
|
62
63
|
propagationOnPrototype: true;
|
|
@@ -71,12 +72,14 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
|
|
|
71
72
|
mergeEmbeddedProperties: true;
|
|
72
73
|
};
|
|
73
74
|
persistOnCreate: true;
|
|
75
|
+
upsertManaged: true;
|
|
74
76
|
forceEntityConstructor: false;
|
|
75
77
|
forceUndefined: false;
|
|
76
78
|
ensureDatabase: true;
|
|
77
79
|
ensureIndexes: false;
|
|
78
80
|
batchSize: number;
|
|
79
81
|
debug: false;
|
|
82
|
+
ignoreDeprecations: false;
|
|
80
83
|
verbose: false;
|
|
81
84
|
driverOptions: {};
|
|
82
85
|
migrations: {
|
|
@@ -322,6 +325,7 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
322
325
|
connect: boolean;
|
|
323
326
|
verbose: boolean;
|
|
324
327
|
ignoreUndefinedInQuery?: boolean;
|
|
328
|
+
onQuery: (sql: string, params: unknown[]) => string;
|
|
325
329
|
autoJoinOneToOneOwner: boolean;
|
|
326
330
|
autoJoinRefsForFilters: boolean;
|
|
327
331
|
propagationOnPrototype: boolean;
|
|
@@ -333,6 +337,7 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
333
337
|
};
|
|
334
338
|
assign: AssignOptions<boolean>;
|
|
335
339
|
persistOnCreate: boolean;
|
|
340
|
+
upsertManaged: boolean;
|
|
336
341
|
forceEntityConstructor: boolean | (Constructor<AnyEntity> | string)[];
|
|
337
342
|
forceUndefined: boolean;
|
|
338
343
|
forceUtcTimezone?: boolean;
|
|
@@ -363,6 +368,7 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
|
|
|
363
368
|
findOneOrFailHandler: (entityName: string, where: Dictionary | IPrimaryKey) => Error;
|
|
364
369
|
findExactlyOneOrFailHandler: (entityName: string, where: Dictionary | IPrimaryKey) => Error;
|
|
365
370
|
debug: boolean | LoggerNamespace[];
|
|
371
|
+
ignoreDeprecations: boolean | string[];
|
|
366
372
|
highlighter: Highlighter;
|
|
367
373
|
tsNode?: boolean;
|
|
368
374
|
baseDir: string;
|
package/utils/Configuration.js
CHANGED
|
@@ -51,6 +51,7 @@ class Configuration {
|
|
|
51
51
|
populateWhere: enums_1.PopulateHint.ALL,
|
|
52
52
|
connect: true,
|
|
53
53
|
ignoreUndefinedInQuery: false,
|
|
54
|
+
onQuery: sql => sql,
|
|
54
55
|
autoJoinOneToOneOwner: true,
|
|
55
56
|
autoJoinRefsForFilters: true,
|
|
56
57
|
propagationOnPrototype: true,
|
|
@@ -65,12 +66,14 @@ class Configuration {
|
|
|
65
66
|
mergeEmbeddedProperties: true,
|
|
66
67
|
},
|
|
67
68
|
persistOnCreate: true,
|
|
69
|
+
upsertManaged: true,
|
|
68
70
|
forceEntityConstructor: false,
|
|
69
71
|
forceUndefined: false,
|
|
70
72
|
ensureDatabase: true,
|
|
71
73
|
ensureIndexes: false,
|
|
72
74
|
batchSize: 300,
|
|
73
75
|
debug: false,
|
|
76
|
+
ignoreDeprecations: false,
|
|
74
77
|
verbose: false,
|
|
75
78
|
driverOptions: {},
|
|
76
79
|
migrations: {
|
|
@@ -148,6 +151,7 @@ class Configuration {
|
|
|
148
151
|
this.options.loggerFactory ??= logging_1.DefaultLogger.create;
|
|
149
152
|
this.logger = this.options.loggerFactory({
|
|
150
153
|
debugMode: this.options.debug,
|
|
154
|
+
ignoreDeprecations: this.options.ignoreDeprecations,
|
|
151
155
|
usesReplicas: (this.options.replicas?.length ?? 0) > 0,
|
|
152
156
|
highlighter: this.options.highlighter,
|
|
153
157
|
writer: this.options.logger,
|
|
@@ -6,9 +6,10 @@ import { Configuration, type Options } from './Configuration';
|
|
|
6
6
|
* @internal
|
|
7
7
|
*/
|
|
8
8
|
export declare class ConfigurationLoader {
|
|
9
|
-
static getConfiguration<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager = EntityManager>(
|
|
9
|
+
static getConfiguration<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager = EntityManager>(paths: string[], options?: Partial<Options>, validate?: boolean): Promise<Configuration<D, EM>>;
|
|
10
10
|
static getPackageConfig(basePath?: string): Dictionary;
|
|
11
11
|
static getSettings(): Settings;
|
|
12
|
+
static configPathsFromArg(): string[] | undefined;
|
|
12
13
|
static getConfigPaths(): string[];
|
|
13
14
|
static isESM(): boolean;
|
|
14
15
|
static registerTsNode(configPath?: string): boolean;
|
|
@@ -16,10 +16,7 @@ const Utils_1 = require("./Utils");
|
|
|
16
16
|
* @internal
|
|
17
17
|
*/
|
|
18
18
|
class ConfigurationLoader {
|
|
19
|
-
static async getConfiguration(
|
|
20
|
-
this.commonJSCompat(options);
|
|
21
|
-
this.registerDotenv(options);
|
|
22
|
-
const paths = this.getConfigPaths();
|
|
19
|
+
static async getConfiguration(paths, options = {}, validate = true) {
|
|
23
20
|
const env = this.loadEnvironmentVars();
|
|
24
21
|
for (let path of paths) {
|
|
25
22
|
path = Utils_1.Utils.absolutePath(path);
|
|
@@ -73,12 +70,15 @@ class ConfigurationLoader {
|
|
|
73
70
|
}
|
|
74
71
|
return settings;
|
|
75
72
|
}
|
|
76
|
-
static
|
|
73
|
+
static configPathsFromArg() {
|
|
77
74
|
const options = Utils_1.Utils.parseArgs();
|
|
78
75
|
const configArgName = process.env.MIKRO_ORM_CONFIG_ARG_NAME ?? 'config';
|
|
79
76
|
if (options[configArgName]) {
|
|
80
77
|
return [options[configArgName]];
|
|
81
78
|
}
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
static getConfigPaths() {
|
|
82
82
|
const paths = [];
|
|
83
83
|
const settings = ConfigurationLoader.getSettings();
|
|
84
84
|
if (process.env.MIKRO_ORM_CLI_CONFIG) {
|
|
@@ -23,7 +23,7 @@ export declare class DataloaderUtils {
|
|
|
23
23
|
static groupInversedOrMappedKeysByEntityAndOpts(collsWithOpts: readonly [Collection<any>, Omit<InitCollectionOptions<any, any>, 'dataloader'>?][]): Map<string, Map<string, Set<Primary<any>>>>;
|
|
24
24
|
/**
|
|
25
25
|
* Turn the entity+options map into actual queries.
|
|
26
|
-
* The keys are the entity names + a
|
|
26
|
+
* The keys are the entity names + a stringified version of the options and the values are filter Maps which will be used as the values of an $or operator so we end up with a query per entity+opts.
|
|
27
27
|
* We must populate the inverse side of the relationship in order to be able to later retrieve the PK(s) from its item(s).
|
|
28
28
|
* Together with the query the promises will also return the key which can be used to narrow down the results pertaining to a certain set of options.
|
|
29
29
|
*/
|
|
@@ -33,7 +33,7 @@ export declare class DataloaderUtils {
|
|
|
33
33
|
* First checks if the Entity type matches, then retrieves the inverse side of the relationship
|
|
34
34
|
* where the filtering will be done in order to match the target collection.
|
|
35
35
|
*/
|
|
36
|
-
static getColFilter<T, S extends T>(collection: Collection<any
|
|
36
|
+
static getColFilter<T, S extends T>(collection: Collection<any>): (result: T) => result is S;
|
|
37
37
|
/**
|
|
38
38
|
* Returns the collection dataloader batchLoadFn, which aggregates collections by entity,
|
|
39
39
|
* makes one query per entity and maps each input collection to the corresponding result.
|
package/utils/DataloaderUtils.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.DataloaderUtils = void 0;
|
|
|
4
4
|
const Collection_1 = require("../entity/Collection");
|
|
5
5
|
const wrap_1 = require("../entity/wrap");
|
|
6
6
|
const enums_1 = require("../enums");
|
|
7
|
+
const Reference_1 = require("../entity/Reference");
|
|
7
8
|
class DataloaderUtils {
|
|
8
9
|
/**
|
|
9
10
|
* Groups identified references by entity and returns a Map with the
|
|
@@ -92,7 +93,7 @@ class DataloaderUtils {
|
|
|
92
93
|
}
|
|
93
94
|
/**
|
|
94
95
|
* Turn the entity+options map into actual queries.
|
|
95
|
-
* The keys are the entity names + a
|
|
96
|
+
* The keys are the entity names + a stringified version of the options and the values are filter Maps which will be used as the values of an $or operator so we end up with a query per entity+opts.
|
|
96
97
|
* We must populate the inverse side of the relationship in order to be able to later retrieve the PK(s) from its item(s).
|
|
97
98
|
* Together with the query the promises will also return the key which can be used to narrow down the results pertaining to a certain set of options.
|
|
98
99
|
*/
|
|
@@ -139,20 +140,21 @@ class DataloaderUtils {
|
|
|
139
140
|
// There is no need to check if Entity matches because we already matched the key which is entity+options.
|
|
140
141
|
// This is the inverse side of the relationship where the filtering will be done in order to match the target collection
|
|
141
142
|
// Either inversedBy or mappedBy exist because we already checked in groupInversedOrMappedKeysByEntity
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if ((0, wrap_1.helper)(item).getSerializedPrimaryKey() === (0, wrap_1.helper)(collection.owner).getSerializedPrimaryKey()) {
|
|
143
|
+
const inverseProp = collection.property.inversedBy ?? collection.property.mappedBy;
|
|
144
|
+
const target = Reference_1.Reference.unwrapReference(result[inverseProp]);
|
|
145
|
+
if (target instanceof Collection_1.Collection) {
|
|
146
|
+
for (const item of target) {
|
|
147
|
+
if (item === collection.owner) {
|
|
148
148
|
return true;
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
|
-
else {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
152
|
+
else if (target) {
|
|
153
|
+
return target === collection.owner;
|
|
154
|
+
}
|
|
155
|
+
// FIXME https://github.com/mikro-orm/mikro-orm/issues/6031
|
|
156
|
+
if (!target && collection.property.kind === enums_1.ReferenceKind.MANY_TO_MANY) {
|
|
157
|
+
throw new Error(`Inverse side is required for M:N relations with dataloader: ${collection.owner.constructor.name}.${collection.property.name}`);
|
|
156
158
|
}
|
|
157
159
|
return false;
|
|
158
160
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EntityManager } from '../EntityManager';
|
|
2
|
+
import { MikroORM } from '../MikroORM';
|
|
3
|
+
import type { ContextProvider, MaybePromise } from '../typings';
|
|
4
|
+
/**
|
|
5
|
+
* Find `EntityManager` in provided context, or else in instance's `orm` or `em` properties.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveContextProvider<T>(caller: T & {
|
|
8
|
+
orm?: MaybePromise<MikroORM>;
|
|
9
|
+
em?: MaybePromise<EntityManager>;
|
|
10
|
+
}, provider?: ContextProvider<T>): Promise<EntityManager | undefined>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveContextProvider = resolveContextProvider;
|
|
4
|
+
const EntityRepository_1 = require("../entity/EntityRepository");
|
|
5
|
+
const EntityManager_1 = require("../EntityManager");
|
|
6
|
+
const MikroORM_1 = require("../MikroORM");
|
|
7
|
+
function getEntityManager(caller, context) {
|
|
8
|
+
if (context instanceof EntityManager_1.EntityManager) {
|
|
9
|
+
return context;
|
|
10
|
+
}
|
|
11
|
+
if (context instanceof EntityRepository_1.EntityRepository) {
|
|
12
|
+
return context.getEntityManager();
|
|
13
|
+
}
|
|
14
|
+
if (context instanceof MikroORM_1.MikroORM) {
|
|
15
|
+
return context.em;
|
|
16
|
+
}
|
|
17
|
+
if (caller.em instanceof EntityManager_1.EntityManager) {
|
|
18
|
+
return caller.em;
|
|
19
|
+
}
|
|
20
|
+
if (caller.orm instanceof MikroORM_1.MikroORM) {
|
|
21
|
+
return caller.orm.em;
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Find `EntityManager` in provided context, or else in instance's `orm` or `em` properties.
|
|
27
|
+
*/
|
|
28
|
+
async function resolveContextProvider(caller, provider) {
|
|
29
|
+
const context = typeof provider === 'function' ? await provider(caller) : await provider;
|
|
30
|
+
return getEntityManager({ orm: await caller.orm, em: await caller.em }, context);
|
|
31
|
+
}
|