@mikro-orm/core 7.0.0-dev.14 → 7.0.0-dev.15
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 +6 -2
- package/EntityManager.js +43 -33
- package/decorators/Embedded.d.ts +5 -11
- package/decorators/ManyToOne.d.ts +2 -0
- package/decorators/OneToOne.d.ts +2 -0
- package/entity/Collection.d.ts +1 -1
- package/entity/Collection.js +7 -2
- package/entity/EntityLoader.d.ts +3 -2
- package/entity/EntityLoader.js +4 -2
- package/enums.d.ts +1 -1
- package/exports.d.ts +24 -0
- package/exports.js +23 -0
- package/metadata/EntitySchema.d.ts +4 -2
- package/metadata/EntitySchema.js +23 -17
- package/metadata/MetadataDiscovery.js +5 -1
- package/package.json +4 -3
- package/typings.d.ts +6 -2
- package/utils/DataloaderUtils.d.ts +1 -1
- package/utils/DataloaderUtils.js +19 -5
- package/utils/EntityComparator.js +1 -1
package/EntityManager.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { EntityFactory } from './entity/EntityFactory.js';
|
|
|
6
6
|
import { type AssignOptions } from './entity/EntityAssigner.js';
|
|
7
7
|
import { EntityValidator } from './entity/EntityValidator.js';
|
|
8
8
|
import { type EntityRepository } from './entity/EntityRepository.js';
|
|
9
|
-
import { type EntityLoaderOptions } from './entity/EntityLoader.js';
|
|
9
|
+
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, FindAllOptions, FindByCursorOptions, FindOneOptions, FindOneOrFailOptions, FindOptions, GetReferenceOptions, IDatabaseDriver, LockOptions, NativeInsertUpdateOptions, UpdateOptions, UpsertManyOptions, UpsertOptions } from './drivers/IDatabaseDriver.js';
|
|
@@ -436,6 +436,10 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
436
436
|
* Gets the EntityFactory used by the EntityManager.
|
|
437
437
|
*/
|
|
438
438
|
getEntityFactory(): EntityFactory;
|
|
439
|
+
/**
|
|
440
|
+
* @internal use `em.populate()` as the user facing API, this is exposed only for internal usage
|
|
441
|
+
*/
|
|
442
|
+
getEntityLoader(): EntityLoader;
|
|
439
443
|
/**
|
|
440
444
|
* Gets the Hydrator used by the EntityManager.
|
|
441
445
|
*/
|
|
@@ -492,7 +496,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
492
496
|
* @internal
|
|
493
497
|
*/
|
|
494
498
|
tryCache<T extends object, R>(entityName: string, config: boolean | number | [string, number] | undefined, key: unknown, refresh?: boolean, merge?: boolean): Promise<{
|
|
495
|
-
data?: R;
|
|
499
|
+
data?: R | null;
|
|
496
500
|
key: string;
|
|
497
501
|
} | undefined>;
|
|
498
502
|
/**
|
package/EntityManager.js
CHANGED
|
@@ -536,14 +536,16 @@ export class EntityManager {
|
|
|
536
536
|
options.populate = await em.preparePopulate(entityName, options);
|
|
537
537
|
const cacheKey = em.cacheKey(entityName, options, 'em.findOne', where);
|
|
538
538
|
const cached = await em.tryCache(entityName, options.cache, cacheKey, options.refresh, true);
|
|
539
|
-
if (cached?.data) {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
539
|
+
if (cached?.data !== undefined) {
|
|
540
|
+
if (cached.data) {
|
|
541
|
+
await em.entityLoader.populate(entityName, [cached.data], options.populate, {
|
|
542
|
+
...options,
|
|
543
|
+
...em.getPopulateWhere(where, options),
|
|
544
|
+
convertCustomTypes: false,
|
|
545
|
+
ignoreLazyScalarProperties: true,
|
|
546
|
+
lookup: false,
|
|
547
|
+
});
|
|
548
|
+
}
|
|
547
549
|
return cached.data;
|
|
548
550
|
}
|
|
549
551
|
options = { ...options };
|
|
@@ -723,6 +725,7 @@ export class EntityManager {
|
|
|
723
725
|
ctx: em.transactionContext,
|
|
724
726
|
convertCustomTypes: true,
|
|
725
727
|
connectionType: 'write',
|
|
728
|
+
schema: options.schema,
|
|
726
729
|
});
|
|
727
730
|
em.getHydrator().hydrate(entity, meta, data2, em.entityFactory, 'full', false, true);
|
|
728
731
|
}
|
|
@@ -903,6 +906,7 @@ export class EntityManager {
|
|
|
903
906
|
ctx: em.transactionContext,
|
|
904
907
|
convertCustomTypes: true,
|
|
905
908
|
connectionType: 'write',
|
|
909
|
+
schema: options.schema,
|
|
906
910
|
});
|
|
907
911
|
for (const [entity, cond] of loadPK.entries()) {
|
|
908
912
|
const row = data2.find(row => {
|
|
@@ -1273,7 +1277,7 @@ export class EntityManager {
|
|
|
1273
1277
|
delete options.orderBy;
|
|
1274
1278
|
const cacheKey = em.cacheKey(entityName, options, 'em.count', where);
|
|
1275
1279
|
const cached = await em.tryCache(entityName, options.cache, cacheKey);
|
|
1276
|
-
if (cached?.data) {
|
|
1280
|
+
if (cached?.data !== undefined) {
|
|
1277
1281
|
return cached.data;
|
|
1278
1282
|
}
|
|
1279
1283
|
const count = await em.driver.count(entityName, where, { ctx: em.transactionContext, ...options });
|
|
@@ -1462,6 +1466,12 @@ export class EntityManager {
|
|
|
1462
1466
|
getEntityFactory() {
|
|
1463
1467
|
return this.getContext().entityFactory;
|
|
1464
1468
|
}
|
|
1469
|
+
/**
|
|
1470
|
+
* @internal use `em.populate()` as the user facing API, this is exposed only for internal usage
|
|
1471
|
+
*/
|
|
1472
|
+
getEntityLoader() {
|
|
1473
|
+
return this.getContext().entityLoader;
|
|
1474
|
+
}
|
|
1465
1475
|
/**
|
|
1466
1476
|
* Gets the Hydrator used by the EntityManager.
|
|
1467
1477
|
*/
|
|
@@ -1705,31 +1715,31 @@ export class EntityManager {
|
|
|
1705
1715
|
const em = this.getContext();
|
|
1706
1716
|
const cacheKey = Array.isArray(config) ? config[0] : JSON.stringify(key);
|
|
1707
1717
|
const cached = await em.resultCache.get(cacheKey);
|
|
1708
|
-
if (cached) {
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
data = em.entityFactory.create(entityName, cached, {
|
|
1720
|
-
merge: true,
|
|
1721
|
-
convertCustomTypes: true,
|
|
1722
|
-
refresh,
|
|
1723
|
-
recomputeSnapshot: true,
|
|
1724
|
-
});
|
|
1725
|
-
}
|
|
1726
|
-
else {
|
|
1727
|
-
data = cached;
|
|
1728
|
-
}
|
|
1729
|
-
await em.unitOfWork.dispatchOnLoadEvent();
|
|
1730
|
-
return { key: cacheKey, data };
|
|
1718
|
+
if (!cached) {
|
|
1719
|
+
return { key: cacheKey, data: cached };
|
|
1720
|
+
}
|
|
1721
|
+
let data;
|
|
1722
|
+
if (Array.isArray(cached) && merge) {
|
|
1723
|
+
data = cached.map(item => em.entityFactory.create(entityName, item, {
|
|
1724
|
+
merge: true,
|
|
1725
|
+
convertCustomTypes: true,
|
|
1726
|
+
refresh,
|
|
1727
|
+
recomputeSnapshot: true,
|
|
1728
|
+
}));
|
|
1731
1729
|
}
|
|
1732
|
-
|
|
1730
|
+
else if (Utils.isObject(cached) && merge) {
|
|
1731
|
+
data = em.entityFactory.create(entityName, cached, {
|
|
1732
|
+
merge: true,
|
|
1733
|
+
convertCustomTypes: true,
|
|
1734
|
+
refresh,
|
|
1735
|
+
recomputeSnapshot: true,
|
|
1736
|
+
});
|
|
1737
|
+
}
|
|
1738
|
+
else {
|
|
1739
|
+
data = cached;
|
|
1740
|
+
}
|
|
1741
|
+
await em.unitOfWork.dispatchOnLoadEvent();
|
|
1742
|
+
return { key: cacheKey, data };
|
|
1733
1743
|
}
|
|
1734
1744
|
/**
|
|
1735
1745
|
* @internal
|
package/decorators/Embedded.d.ts
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
import type { AnyEntity } from '../typings.js';
|
|
2
|
-
|
|
1
|
+
import type { AnyEntity, EntityName } from '../typings.js';
|
|
2
|
+
import type { PropertyOptions } from './Property.js';
|
|
3
|
+
export declare function Embedded<Owner extends object, Target>(type?: EmbeddedOptions<Owner, Target> | (() => EntityName<Target> | EntityName<Target>[]), options?: EmbeddedOptions<Owner, Target>): (target: AnyEntity, propertyName: string) => any;
|
|
3
4
|
/** With `absolute` the prefix is set at the root of the entity (regardless of the nesting level) */
|
|
4
5
|
export type EmbeddedPrefixMode = 'absolute' | 'relative';
|
|
5
|
-
export interface EmbeddedOptions {
|
|
6
|
-
entity?: string | (() =>
|
|
7
|
-
type?: string;
|
|
6
|
+
export interface EmbeddedOptions<Owner, Target> extends PropertyOptions<Owner> {
|
|
7
|
+
entity?: string | (() => EntityName<Target> | EntityName<Target>[]);
|
|
8
8
|
prefix?: string | boolean;
|
|
9
9
|
prefixMode?: EmbeddedPrefixMode;
|
|
10
|
-
nullable?: boolean;
|
|
11
10
|
object?: boolean;
|
|
12
11
|
array?: boolean;
|
|
13
|
-
hidden?: boolean;
|
|
14
|
-
serializer?: (value: any) => any;
|
|
15
|
-
serializedName?: string;
|
|
16
|
-
groups?: string[];
|
|
17
|
-
persist?: boolean;
|
|
18
12
|
}
|
|
@@ -27,4 +27,6 @@ export interface ManyToOneOptions<Owner, Target> extends ReferenceOptions<Owner,
|
|
|
27
27
|
updateRule?: 'cascade' | 'no action' | 'set null' | 'set default' | AnyString;
|
|
28
28
|
/** Set the constraint type. Immediate constraints are checked for each statement, while deferred ones are only checked at the end of the transaction. Only for postgres unique constraints. */
|
|
29
29
|
deferMode?: DeferMode | `${DeferMode}`;
|
|
30
|
+
/** Set a custom foreign key constraint name, overriding NamingStrategy.indexName(). */
|
|
31
|
+
foreignKeyName?: string;
|
|
30
32
|
}
|
package/decorators/OneToOne.d.ts
CHANGED
|
@@ -21,4 +21,6 @@ export interface OneToOneOptions<Owner, Target> extends Partial<Omit<OneToManyOp
|
|
|
21
21
|
updateRule?: 'cascade' | 'no action' | 'set null' | 'set default' | AnyString;
|
|
22
22
|
/** Set the constraint type. Immediate constraints are checked for each statement, while deferred ones are only checked at the end of the transaction. Only for postgres unique constraints. */
|
|
23
23
|
deferMode?: DeferMode | `${DeferMode}`;
|
|
24
|
+
/** Set a custom foreign key constraint name, overriding NamingStrategy.indexName(). */
|
|
25
|
+
foreignKeyName?: string;
|
|
24
26
|
}
|
package/entity/Collection.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { EntityDTO, EntityKey, FilterQuery, Loaded, LoadedCollection, Popul
|
|
|
2
2
|
import { ArrayCollection } from './ArrayCollection.js';
|
|
3
3
|
import { Reference } from './Reference.js';
|
|
4
4
|
import type { Transaction } from '../connections/Connection.js';
|
|
5
|
-
import type {
|
|
5
|
+
import type { CountOptions, FindOptions } from '../drivers/IDatabaseDriver.js';
|
|
6
6
|
import type { EntityLoaderOptions } from './EntityLoader.js';
|
|
7
7
|
export interface MatchingOptions<T extends object, P extends string = never> extends FindOptions<T, P> {
|
|
8
8
|
where?: FilterQuery<T>;
|
package/entity/Collection.js
CHANGED
|
@@ -226,8 +226,13 @@ export class Collection extends ArrayCollection {
|
|
|
226
226
|
this,
|
|
227
227
|
{ ...options, orderBy },
|
|
228
228
|
]);
|
|
229
|
-
if (
|
|
230
|
-
this.
|
|
229
|
+
if (this.property.kind === ReferenceKind.MANY_TO_MANY) {
|
|
230
|
+
this.initialized = true;
|
|
231
|
+
this.dirty = false;
|
|
232
|
+
if (!customOrder) {
|
|
233
|
+
this.reorderItems(items, order);
|
|
234
|
+
}
|
|
235
|
+
return this;
|
|
231
236
|
}
|
|
232
237
|
this.items.clear();
|
|
233
238
|
let i = 0;
|
package/entity/EntityLoader.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConnectionType, Dictionary, FilterQuery, PopulateOptions } from '../typings.js';
|
|
1
|
+
import type { AnyEntity, ConnectionType, Dictionary, EntityProperty, FilterQuery, PopulateOptions } from '../typings.js';
|
|
2
2
|
import type { EntityManager } from '../EntityManager.js';
|
|
3
3
|
import { LoadStrategy, type LockMode, type PopulateHint, PopulatePath, type QueryOrderMap } from '../enums.js';
|
|
4
4
|
import type { EntityField } from '../drivers/IDatabaseDriver.js';
|
|
@@ -49,7 +49,8 @@ export declare class EntityLoader {
|
|
|
49
49
|
private findChildren;
|
|
50
50
|
private mergePrimaryCondition;
|
|
51
51
|
private populateField;
|
|
52
|
-
|
|
52
|
+
/** @internal */
|
|
53
|
+
findChildrenFromPivotTable<Entity extends object>(filtered: Entity[], prop: EntityProperty<Entity>, options: Required<EntityLoaderOptions<Entity>>, orderBy?: QueryOrderMap<Entity>[], populate?: PopulateOptions<Entity>, pivotJoin?: boolean): Promise<AnyEntity[][]>;
|
|
53
54
|
private extractChildCondition;
|
|
54
55
|
private buildFields;
|
|
55
56
|
private getChildReferences;
|
package/entity/EntityLoader.js
CHANGED
|
@@ -141,7 +141,8 @@ export class EntityLoader {
|
|
|
141
141
|
.filter(orderBy => (Array.isArray(orderBy[prop.name]) && orderBy[prop.name].length > 0) || Utils.isObject(orderBy[prop.name]))
|
|
142
142
|
.flatMap(orderBy => orderBy[prop.name]);
|
|
143
143
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && this.driver.getPlatform().usesPivotTable()) {
|
|
144
|
-
|
|
144
|
+
const res = await this.findChildrenFromPivotTable(filtered, prop, options, innerOrderBy, populate, !!ref);
|
|
145
|
+
return Utils.flatten(res);
|
|
145
146
|
}
|
|
146
147
|
const where = await this.extractChildCondition(options, prop);
|
|
147
148
|
const data = await this.findChildren(entities, prop, populate, { ...options, where, orderBy: innerOrderBy }, !!(ref || prop.mapToPk));
|
|
@@ -343,6 +344,7 @@ export class EntityLoader {
|
|
|
343
344
|
visited: options.visited,
|
|
344
345
|
});
|
|
345
346
|
}
|
|
347
|
+
/** @internal */
|
|
346
348
|
async findChildrenFromPivotTable(filtered, prop, options, orderBy, populate, pivotJoin) {
|
|
347
349
|
const ids = filtered.map(e => e.__helper.__primaryKeys);
|
|
348
350
|
const refresh = options.refresh;
|
|
@@ -380,7 +382,7 @@ export class EntityLoader {
|
|
|
380
382
|
return this.em.getUnitOfWork().register(entity, item, { refresh, loaded: true });
|
|
381
383
|
});
|
|
382
384
|
entity[prop.name].hydrate(items, true);
|
|
383
|
-
children.push(
|
|
385
|
+
children.push(items);
|
|
384
386
|
}
|
|
385
387
|
return children;
|
|
386
388
|
}
|
package/enums.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ export declare enum QueryOrderNumeric {
|
|
|
66
66
|
ASC = 1,
|
|
67
67
|
DESC = -1
|
|
68
68
|
}
|
|
69
|
-
export type QueryOrderKeysFlat = QueryOrder | QueryOrderNumeric |
|
|
69
|
+
export type QueryOrderKeysFlat = QueryOrder | QueryOrderNumeric | `${QueryOrder}`;
|
|
70
70
|
export type QueryOrderKeys<T> = QueryOrderKeysFlat | QueryOrderMap<T>;
|
|
71
71
|
export type QueryOrderMap<T> = {
|
|
72
72
|
[K in EntityKey<T>]?: QueryOrderKeys<ExpandProperty<T[K]>>;
|
package/exports.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* @module core
|
|
4
|
+
*/
|
|
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, EntityDataValue, 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.js';
|
|
6
|
+
export * from './enums.js';
|
|
7
|
+
export * from './errors.js';
|
|
8
|
+
export * from './exceptions.js';
|
|
9
|
+
export * from './entity/index.js';
|
|
10
|
+
export * from './serialization/index.js';
|
|
11
|
+
export * from './events/index.js';
|
|
12
|
+
export { CreateOptions, MergeOptions, ForkOptions } from './EntityManager.js';
|
|
13
|
+
export * from './unit-of-work/index.js';
|
|
14
|
+
export * from './utils/index.js';
|
|
15
|
+
export * from './logging/index.js';
|
|
16
|
+
export * from './hydration/index.js';
|
|
17
|
+
export * from './drivers/index.js';
|
|
18
|
+
export * from './connections/index.js';
|
|
19
|
+
export * from './platforms/index.js';
|
|
20
|
+
export * from './types/index.js';
|
|
21
|
+
export * from './naming-strategy/index.js';
|
|
22
|
+
export * from './metadata/index.js';
|
|
23
|
+
export * from './cache/index.js';
|
|
24
|
+
export * from './decorators/index.js';
|
package/exports.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* @module core
|
|
4
|
+
*/
|
|
5
|
+
export { PrimaryKeyProp, EntityMetadata, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config, } from './typings.js';
|
|
6
|
+
export * from './enums.js';
|
|
7
|
+
export * from './errors.js';
|
|
8
|
+
export * from './exceptions.js';
|
|
9
|
+
export * from './entity/index.js';
|
|
10
|
+
export * from './serialization/index.js';
|
|
11
|
+
export * from './events/index.js';
|
|
12
|
+
export * from './unit-of-work/index.js';
|
|
13
|
+
export * from './utils/index.js';
|
|
14
|
+
export * from './logging/index.js';
|
|
15
|
+
export * from './hydration/index.js';
|
|
16
|
+
export * from './drivers/index.js';
|
|
17
|
+
export * from './connections/index.js';
|
|
18
|
+
export * from './platforms/index.js';
|
|
19
|
+
export * from './types/index.js';
|
|
20
|
+
export * from './naming-strategy/index.js';
|
|
21
|
+
export * from './metadata/index.js';
|
|
22
|
+
export * from './cache/index.js';
|
|
23
|
+
export * from './decorators/index.js';
|
|
@@ -31,7 +31,7 @@ export type EntitySchemaProperty<Target, Owner> = ({
|
|
|
31
31
|
kind: ReferenceKind.MANY_TO_MANY | 'm:n';
|
|
32
32
|
} & TypeDef<Target> & ManyToManyOptions<Owner, Target>) | ({
|
|
33
33
|
kind: ReferenceKind.EMBEDDED | 'embedded';
|
|
34
|
-
} & EmbeddedTypeDef<Target> & EmbeddedOptions & PropertyOptions<Owner>) | ({
|
|
34
|
+
} & EmbeddedTypeDef<Target> & EmbeddedOptions<Owner, Target> & PropertyOptions<Owner>) | ({
|
|
35
35
|
enum: true;
|
|
36
36
|
} & EnumOptions<Owner>) | (TypeDef<Target> & PropertyOptions<Owner>);
|
|
37
37
|
type OmitBaseProps<Entity, Base> = IsNever<Base> extends true ? Entity : Omit<Entity, keyof Base>;
|
|
@@ -63,7 +63,7 @@ export declare class EntitySchema<Entity = any, Base = never> {
|
|
|
63
63
|
addVersion(name: EntityKey<Entity>, type: TypeType, options?: PropertyOptions<Entity>): void;
|
|
64
64
|
addPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: PrimaryKeyOptions<Entity>): void;
|
|
65
65
|
addSerializedPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: SerializedPrimaryKeyOptions<Entity>): void;
|
|
66
|
-
addEmbedded<Target = AnyEntity>(name: EntityKey<Entity>, options: EmbeddedOptions): void;
|
|
66
|
+
addEmbedded<Target = AnyEntity>(name: EntityKey<Entity>, options: EmbeddedOptions<Entity, Target>): void;
|
|
67
67
|
addManyToOne<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: ManyToOneOptions<Entity, Target>): void;
|
|
68
68
|
addManyToMany<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: ManyToManyOptions<Entity, Target>): void;
|
|
69
69
|
addOneToMany<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: OneToManyOptions<Entity, Target>): void;
|
|
@@ -83,5 +83,7 @@ export declare class EntitySchema<Entity = any, Base = never> {
|
|
|
83
83
|
private initPrimaryKeys;
|
|
84
84
|
private normalizeType;
|
|
85
85
|
private createProperty;
|
|
86
|
+
private rename;
|
|
87
|
+
private renameCompositeOptions;
|
|
86
88
|
}
|
|
87
89
|
export {};
|
package/metadata/EntitySchema.js
CHANGED
|
@@ -34,23 +34,7 @@ export class EntitySchema {
|
|
|
34
34
|
return schema;
|
|
35
35
|
}
|
|
36
36
|
addProperty(name, type, options = {}) {
|
|
37
|
-
|
|
38
|
-
if (from in options && !(to in options)) {
|
|
39
|
-
// @ts-ignore
|
|
40
|
-
options[to] = [options[from]];
|
|
41
|
-
// @ts-ignore
|
|
42
|
-
delete options[from];
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
if (name !== options.name) {
|
|
46
|
-
Utils.renameKey(options, 'name', 'fieldName');
|
|
47
|
-
}
|
|
48
|
-
rename(options, 'fieldName', 'fieldNames');
|
|
49
|
-
rename(options, 'ref', 'ref');
|
|
50
|
-
rename(options, 'joinColumn', 'joinColumns');
|
|
51
|
-
rename(options, 'inverseJoinColumn', 'inverseJoinColumns');
|
|
52
|
-
rename(options, 'referenceColumnName', 'referencedColumnNames');
|
|
53
|
-
rename(options, 'columnType', 'columnTypes');
|
|
37
|
+
this.renameCompositeOptions(name, options);
|
|
54
38
|
const prop = { name, kind: ReferenceKind.SCALAR, ...options, type: this.normalizeType(options, type) };
|
|
55
39
|
if (type && Type.isMappedType(type.prototype)) {
|
|
56
40
|
prop.type = type;
|
|
@@ -94,6 +78,7 @@ export class EntitySchema {
|
|
|
94
78
|
this.addProperty(name, type, options);
|
|
95
79
|
}
|
|
96
80
|
addEmbedded(name, options) {
|
|
81
|
+
this.renameCompositeOptions(name, options);
|
|
97
82
|
Utils.defaultValue(options, 'prefix', true);
|
|
98
83
|
if (options.array) {
|
|
99
84
|
options.object = true; // force object mode for arrays
|
|
@@ -289,4 +274,25 @@ export class EntitySchema {
|
|
|
289
274
|
...options,
|
|
290
275
|
};
|
|
291
276
|
}
|
|
277
|
+
rename(data, from, to) {
|
|
278
|
+
if (from in data && !(to in data)) {
|
|
279
|
+
// @ts-ignore
|
|
280
|
+
data[to] = [data[from]];
|
|
281
|
+
// @ts-ignore
|
|
282
|
+
delete data[from];
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
renameCompositeOptions(name, options = {}) {
|
|
286
|
+
if (name !== options.name && !options.fieldNames) {
|
|
287
|
+
Utils.renameKey(options, 'name', 'fieldName');
|
|
288
|
+
}
|
|
289
|
+
else if (options.name && (options.fieldNames?.length ?? 0) > 1) {
|
|
290
|
+
delete options.name;
|
|
291
|
+
}
|
|
292
|
+
this.rename(options, 'fieldName', 'fieldNames');
|
|
293
|
+
this.rename(options, 'joinColumn', 'joinColumns');
|
|
294
|
+
this.rename(options, 'inverseJoinColumn', 'inverseJoinColumns');
|
|
295
|
+
this.rename(options, 'referenceColumnName', 'referencedColumnNames');
|
|
296
|
+
this.rename(options, 'columnType', 'columnTypes');
|
|
297
|
+
}
|
|
292
298
|
}
|
|
@@ -264,7 +264,8 @@ export class MetadataDiscovery {
|
|
|
264
264
|
// initialize global metadata for given entity
|
|
265
265
|
MetadataStorage.getMetadata(entity.meta.className, filepath);
|
|
266
266
|
}
|
|
267
|
-
|
|
267
|
+
const meta = Utils.copy(entity.meta, false);
|
|
268
|
+
return EntitySchema.fromMetadata(meta);
|
|
268
269
|
}
|
|
269
270
|
const path = entity[MetadataStorage.PATH_SYMBOL];
|
|
270
271
|
if (path) {
|
|
@@ -1148,6 +1149,9 @@ export class MetadataDiscovery {
|
|
|
1148
1149
|
prop.runtimeType ??= prop.customType.runtimeType;
|
|
1149
1150
|
}
|
|
1150
1151
|
}
|
|
1152
|
+
else if (prop.runtimeType === 'object') {
|
|
1153
|
+
prop.runtimeType = mappedType.runtimeType;
|
|
1154
|
+
}
|
|
1151
1155
|
else {
|
|
1152
1156
|
prop.runtimeType ??= mappedType.runtimeType;
|
|
1153
1157
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "7.0.0-dev.
|
|
4
|
+
"version": "7.0.0-dev.15",
|
|
5
5
|
"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.",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./package.json": "./package.json",
|
|
8
|
-
".": "./index.js"
|
|
8
|
+
".": "./index.js",
|
|
9
|
+
"./exports.js": "./exports.js"
|
|
9
10
|
},
|
|
10
11
|
"repository": {
|
|
11
12
|
"type": "git",
|
|
@@ -55,7 +56,7 @@
|
|
|
55
56
|
"dotenv": "16.5.0",
|
|
56
57
|
"esprima": "4.0.1",
|
|
57
58
|
"globby": "11.1.0",
|
|
58
|
-
"mikro-orm": "7.0.0-dev.
|
|
59
|
+
"mikro-orm": "7.0.0-dev.15",
|
|
59
60
|
"reflect-metadata": "0.2.2"
|
|
60
61
|
}
|
|
61
62
|
}
|
package/typings.d.ts
CHANGED
|
@@ -217,14 +217,17 @@ type ExpandRequiredEntityPropObject<T, I = never, C extends boolean = false> = {
|
|
|
217
217
|
} & {
|
|
218
218
|
[K in keyof T as OptionalKeys<T, K, I>]?: RequiredEntityDataProp<ExpandProperty<T[K]>, T, C> | EntityDataPropValue<ExpandProperty<T[K]>> | null | undefined;
|
|
219
219
|
};
|
|
220
|
+
type NonArrayObject = object & {
|
|
221
|
+
[Symbol.iterator]?: never;
|
|
222
|
+
};
|
|
220
223
|
export type EntityDataProp<T, C extends boolean> = T extends Date ? string | Date : T extends Scalar ? T : T extends {
|
|
221
224
|
__runtime?: infer Runtime;
|
|
222
225
|
__raw?: infer Raw;
|
|
223
|
-
} ? (C extends true ? Raw : Runtime) : T extends Reference<infer U> ? EntityDataNested<U, C> : T extends ScalarReference<infer U> ? EntityDataProp<U, C> : T extends Collection<infer U, any> ? U | U[] | EntityDataNested<U, C> | EntityDataNested<U, C>[] : T extends readonly (infer U)[] ? U | U[] | EntityDataNested<U, C> | EntityDataNested<U, C>[] : EntityDataNested<T, C>;
|
|
226
|
+
} ? (C extends true ? Raw : Runtime) : T extends Reference<infer U> ? EntityDataNested<U, C> : T extends ScalarReference<infer U> ? EntityDataProp<U, C> : T extends Collection<infer U, any> ? U | U[] | EntityDataNested<U, C> | EntityDataNested<U, C>[] : T extends readonly (infer U)[] ? U extends NonArrayObject ? U | U[] | EntityDataNested<U, C> | EntityDataNested<U, C>[] : U[] | EntityDataNested<U, C>[] : EntityDataNested<T, C>;
|
|
224
227
|
export type RequiredEntityDataProp<T, O, C extends boolean> = T extends Date ? string | Date : T extends Scalar ? T : T extends {
|
|
225
228
|
__runtime?: infer Runtime;
|
|
226
229
|
__raw?: infer Raw;
|
|
227
|
-
} ? (C extends true ? Raw : Runtime) : T extends Reference<infer U> ? RequiredEntityDataNested<U, O, C> : T extends ScalarReference<infer U> ? RequiredEntityDataProp<U, O, C> : T extends Collection<infer U, any> ? U | U[] | RequiredEntityDataNested<U, O, C> | RequiredEntityDataNested<U, O, C>[] : T extends readonly (infer U)[] ? U | U[] | RequiredEntityDataNested<U, O, C> | RequiredEntityDataNested<U, O, C>[] : RequiredEntityDataNested<T, O, C>;
|
|
230
|
+
} ? (C extends true ? Raw : Runtime) : T extends Reference<infer U> ? RequiredEntityDataNested<U, O, C> : T extends ScalarReference<infer U> ? RequiredEntityDataProp<U, O, C> : T extends Collection<infer U, any> ? U | U[] | RequiredEntityDataNested<U, O, C> | RequiredEntityDataNested<U, O, C>[] : T extends readonly (infer U)[] ? U extends NonArrayObject ? U | U[] | RequiredEntityDataNested<U, O, C> | RequiredEntityDataNested<U, O, C>[] : U[] | RequiredEntityDataNested<U, O, C>[] : RequiredEntityDataNested<T, O, C>;
|
|
228
231
|
export type EntityDataNested<T, C extends boolean = false> = T extends undefined ? never : T extends any[] ? Readonly<T> : EntityData<T, C> | ExpandEntityProp<T, C>;
|
|
229
232
|
type EntityDataItem<T, C extends boolean> = C extends false ? T | EntityDataProp<T, C> | null : EntityDataProp<T, C> | null;
|
|
230
233
|
export type RequiredEntityDataNested<T, O, C extends boolean> = T extends any[] ? Readonly<T> : RequiredEntityData<T, O> | ExpandRequiredEntityProp<T, O, C>;
|
|
@@ -391,6 +394,7 @@ export interface EntityProperty<Owner = any, Target = any> {
|
|
|
391
394
|
optional?: boolean;
|
|
392
395
|
ignoreSchemaChanges?: ('type' | 'extra' | 'default')[];
|
|
393
396
|
deferMode?: DeferMode;
|
|
397
|
+
foreignKeyName?: string;
|
|
394
398
|
}
|
|
395
399
|
export declare class EntityMetadata<T = any> {
|
|
396
400
|
private static counter;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type DataLoader from 'dataloader';
|
|
1
2
|
import type { Primary, Ref } from '../typings.js';
|
|
2
3
|
import { Collection, type InitCollectionOptions } from '../entity/Collection.js';
|
|
3
4
|
import { type EntityManager } from '../EntityManager.js';
|
|
4
|
-
import type DataLoader from 'dataloader';
|
|
5
5
|
import { type LoadReferenceOptions } from '../entity/Reference.js';
|
|
6
6
|
export declare class DataloaderUtils {
|
|
7
7
|
/**
|
package/utils/DataloaderUtils.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Collection } from '../entity/Collection.js';
|
|
|
2
2
|
import { helper } from '../entity/wrap.js';
|
|
3
3
|
import { ReferenceKind } from '../enums.js';
|
|
4
4
|
import { Reference } from '../entity/Reference.js';
|
|
5
|
+
import { Utils } from './Utils.js';
|
|
5
6
|
export class DataloaderUtils {
|
|
6
7
|
/**
|
|
7
8
|
* Groups identified references by entity and returns a Map with the
|
|
@@ -118,7 +119,6 @@ export class DataloaderUtils {
|
|
|
118
119
|
// We need to populate the inverse side of the relationship in order to be able to later retrieve the PK(s) from its item(s)
|
|
119
120
|
populate: [
|
|
120
121
|
...(opts.populate === false ? [] : opts.populate ?? []),
|
|
121
|
-
...(opts.ref ? [':ref'] : []),
|
|
122
122
|
...Array.from(filterMap.keys()).filter(
|
|
123
123
|
// We need to do so only if the inverse side is a collection, because we can already retrieve the PK from a reference without having to load it
|
|
124
124
|
prop => em.getMetadata(className).properties[prop]?.ref !== true),
|
|
@@ -149,10 +149,6 @@ export class DataloaderUtils {
|
|
|
149
149
|
else if (target) {
|
|
150
150
|
return target === collection.owner;
|
|
151
151
|
}
|
|
152
|
-
// FIXME https://github.com/mikro-orm/mikro-orm/issues/6031
|
|
153
|
-
if (!target && collection.property.kind === ReferenceKind.MANY_TO_MANY) {
|
|
154
|
-
throw new Error(`Inverse side is required for M:N relations with dataloader: ${collection.owner.constructor.name}.${collection.property.name}`);
|
|
155
|
-
}
|
|
156
152
|
return false;
|
|
157
153
|
};
|
|
158
154
|
}
|
|
@@ -162,6 +158,24 @@ export class DataloaderUtils {
|
|
|
162
158
|
*/
|
|
163
159
|
static getColBatchLoadFn(em) {
|
|
164
160
|
return async (collsWithOpts) => {
|
|
161
|
+
const prop = collsWithOpts[0][0].property;
|
|
162
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY && em.getPlatform().usesPivotTable()) {
|
|
163
|
+
const options = {};
|
|
164
|
+
const wrap = (cond) => ({ [prop.name]: cond });
|
|
165
|
+
const orderBy = Utils.asArray(collsWithOpts[0][1]?.orderBy).map(o => wrap(o));
|
|
166
|
+
const populate = wrap(collsWithOpts[0][1]?.populate);
|
|
167
|
+
const owners = collsWithOpts.map(c => c[0].owner);
|
|
168
|
+
const $or = [];
|
|
169
|
+
// a bit of a hack, but we need to prefix the key, since we have only a column name, not a property name
|
|
170
|
+
const alias = em.config.getNamingStrategy().aliasName(prop.pivotEntity, 0);
|
|
171
|
+
const fk = `${alias}.${Utils.getPrimaryKeyHash(prop.joinColumns)}`;
|
|
172
|
+
for (const c of collsWithOpts) {
|
|
173
|
+
$or.push({ $and: [c[1]?.where ?? {}, { [fk]: c[0].owner }] });
|
|
174
|
+
options.refresh ??= c[1]?.refresh;
|
|
175
|
+
}
|
|
176
|
+
options.where = wrap({ $or });
|
|
177
|
+
return em.getEntityLoader().findChildrenFromPivotTable(owners, prop, options, orderBy, populate, collsWithOpts[0][1]?.ref);
|
|
178
|
+
}
|
|
165
179
|
const entitiesAndOptsMap = DataloaderUtils.groupInversedOrMappedKeysByEntityAndOpts(collsWithOpts);
|
|
166
180
|
const promises = DataloaderUtils.entitiesAndOptsMapToQueries(entitiesAndOptsMap, em);
|
|
167
181
|
const resultsMap = new Map(await Promise.all(promises));
|
|
@@ -607,7 +607,7 @@ export class EntityComparator {
|
|
|
607
607
|
* perf: used to generate list of comparable properties during discovery, so we speed up the runtime comparison
|
|
608
608
|
*/
|
|
609
609
|
static isComparable(prop, root) {
|
|
610
|
-
const virtual = prop.persist === false || prop.generated;
|
|
610
|
+
const virtual = prop.persist === false || (prop.generated && !prop.primary);
|
|
611
611
|
const inverse = prop.kind === ReferenceKind.ONE_TO_ONE && !prop.owner;
|
|
612
612
|
const discriminator = prop.name === root.discriminatorColumn;
|
|
613
613
|
const collection = prop.kind === ReferenceKind.ONE_TO_MANY || prop.kind === ReferenceKind.MANY_TO_MANY;
|