Skip to content

Commit

Permalink
Merge 1114263 into cedbae7
Browse files Browse the repository at this point in the history
  • Loading branch information
B4nan committed Aug 9, 2019
2 parents cedbae7 + 1114263 commit 92205d6
Show file tree
Hide file tree
Showing 36 changed files with 284 additions and 229 deletions.
33 changes: 19 additions & 14 deletions lib/EntityManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ export class EntityManager {
private readonly validator = new EntityValidator(this.config.get('strict'));
private readonly repositoryMap: Record<string, EntityRepository<IEntity>> = {};
private readonly entityLoader = new EntityLoader(this);
private readonly metadata = MetadataStorage.getMetadata();
private readonly unitOfWork = new UnitOfWork(this);
private readonly entityFactory = new EntityFactory(this.unitOfWork, this.driver, this.config);
private readonly entityFactory = new EntityFactory(this.unitOfWork, this.driver, this.config, this.metadata);
private transactionContext: Transaction;

constructor(readonly config: Configuration,
private readonly driver: IDatabaseDriver) { }
private readonly driver: IDatabaseDriver,
private readonly metadata: MetadataStorage) { }

getDriver<D extends IDatabaseDriver = IDatabaseDriver>(): D {
return this.driver as D;
Expand All @@ -32,7 +32,7 @@ export class EntityManager {
entityName = Utils.className(entityName);

if (!this.repositoryMap[entityName]) {
const meta = this.metadata[entityName];
const meta = this.metadata.get(entityName);
const RepositoryClass = this.config.getRepositoryClass(meta.customRepository);
this.repositoryMap[entityName] = new RepositoryClass(this, entityName);
}
Expand All @@ -53,7 +53,7 @@ export class EntityManager {
async find<T extends IEntityType<T>>(entityName: EntityName<T>, where?: FilterQuery<T>, populate?: string[], orderBy?: QueryOrderMap, limit?: number, offset?: number): Promise<T[]>;
async find<T extends IEntityType<T>>(entityName: EntityName<T>, where = {} as FilterQuery<T>, populate?: string[] | FindOptions, orderBy?: QueryOrderMap, limit?: number, offset?: number): Promise<T[]> {
entityName = Utils.className(entityName);
where = SmartQueryHelper.processWhere(where, entityName);
where = SmartQueryHelper.processWhere(where, entityName, this.metadata.get(entityName));
this.validator.validateParams(where);
const options = Utils.isObject<FindOptions>(populate) ? populate : { populate, orderBy, limit, offset };
const results = await this.driver.find(entityName, where, options.populate || [], options.orderBy || {}, options.limit, options.offset, this.transactionContext);
Expand All @@ -79,9 +79,10 @@ export class EntityManager {
async findOne<T extends IEntityType<T>>(entityName: EntityName<T>, where: FilterQuery<T> | IPrimaryKey, populate?: string[] | FindOneOptions, orderBy?: QueryOrderMap): Promise<T | null> {
entityName = Utils.className(entityName);
const options = Utils.isObject<FindOneOptions>(populate) ? populate : { populate, orderBy };
const meta = this.metadata.get(entityName);
this.validator.validateEmptyWhere(where);
where = SmartQueryHelper.processWhere(where as FilterQuery<T>, entityName);
this.checkLockRequirements(options.lockMode, this.metadata[entityName]);
where = SmartQueryHelper.processWhere(where as FilterQuery<T>, entityName, meta);
this.checkLockRequirements(options.lockMode, meta);
let entity = this.getUnitOfWork().tryGetById<T>(entityName, where);
const isOptimisticLocking = !Utils.isDefined(options.lockMode) || options.lockMode === LockMode.OPTIMISTIC;

Expand Down Expand Up @@ -129,7 +130,7 @@ export class EntityManager {
async nativeUpdate<T extends IEntityType<T>>(entityName: EntityName<T>, where: FilterQuery<T>, data: EntityData<T>): Promise<number> {
entityName = Utils.className(entityName);
data = SmartQueryHelper.processParams(data);
where = SmartQueryHelper.processWhere(where as FilterQuery<T>, entityName);
where = SmartQueryHelper.processWhere(where as FilterQuery<T>, entityName, this.metadata.get(entityName));
this.validator.validateParams(data, 'update data');
this.validator.validateParams(where, 'update condition');
const res = await this.driver.nativeUpdate(entityName, where, data, this.transactionContext);
Expand All @@ -139,7 +140,7 @@ export class EntityManager {

async nativeDelete<T extends IEntityType<T>>(entityName: EntityName<T>, where: FilterQuery<T> | string | any): Promise<number> {
entityName = Utils.className(entityName);
where = SmartQueryHelper.processWhere(where as FilterQuery<T>, entityName);
where = SmartQueryHelper.processWhere(where as FilterQuery<T>, entityName, this.metadata.get(entityName));
this.validator.validateParams(where, 'delete condition');
const res = await this.driver.nativeDelete(entityName, where, this.transactionContext);

Expand All @@ -148,7 +149,7 @@ export class EntityManager {

map<T extends IEntityType<T>>(entityName: EntityName<T>, result: EntityData<T>): T {
entityName = Utils.className(entityName);
const meta = this.metadata[entityName];
const meta = this.metadata.get(entityName);
const data = this.driver.mapResult(result, meta)!;

return this.merge<T>(entityName, data, true);
Expand All @@ -170,7 +171,7 @@ export class EntityManager {
}

entityName = Utils.className(entityName);
this.validator.validatePrimaryKey(data as EntityData<T>, this.metadata[entityName]);
this.validator.validatePrimaryKey(data as EntityData<T>, this.metadata.get(entityName));
let entity = this.getUnitOfWork().tryGetById<T>(entityName, data as EntityData<T>);

if (entity && entity.isInitialized() && !refresh) {
Expand Down Expand Up @@ -206,7 +207,7 @@ export class EntityManager {

async count<T extends IEntityType<T>>(entityName: EntityName<T>, where: FilterQuery<T>): Promise<number> {
entityName = Utils.className(entityName);
where = SmartQueryHelper.processWhere(where as FilterQuery<T>, entityName);
where = SmartQueryHelper.processWhere(where as FilterQuery<T>, entityName, this.metadata.get(entityName));
this.validator.validateParams(where);

return this.driver.count(entityName, where, this.transactionContext);
Expand Down Expand Up @@ -283,7 +284,7 @@ export class EntityManager {
canPopulate(entityName: string | Function, property: string): boolean {
entityName = Utils.className(entityName);
const [p, ...parts] = property.split('.');
const props = this.metadata[entityName].properties;
const props = this.metadata.get(entityName).properties;
const ret = p in props && props[p].reference !== ReferenceType.SCALAR;

if (!ret) {
Expand All @@ -298,7 +299,7 @@ export class EntityManager {
}

fork(clear = true): EntityManager {
const em = new EntityManager(this.config, this.driver);
const em = new EntityManager(this.config, this.driver, this.metadata);

if (!clear) {
Object.values(this.getUnitOfWork().getIdentityMap()).forEach(entity => em.merge(entity));
Expand All @@ -325,6 +326,10 @@ export class EntityManager {
return this.transactionContext as T;
}

getMetadata(): MetadataStorage {
return this.metadata;
}

private checkLockRequirements(mode: LockMode | undefined, meta: EntityMetadata): void {
if (!mode) {
return;
Expand Down
15 changes: 8 additions & 7 deletions lib/MikroORM.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import { EntityManager } from './EntityManager';
import { IDatabaseDriver } from './drivers';
import { MetadataDiscovery } from './metadata';
import { MetadataDiscovery, MetadataStorage } from './metadata';
import { Configuration, Logger, Options } from './utils';
import { EntityMetadata } from './decorators';

export class MikroORM {

em: EntityManager;
readonly config: Configuration;
private metadata: Record<string, EntityMetadata>;
private metadata: MetadataStorage;
private readonly driver: IDatabaseDriver;
private readonly logger: Logger;

static async init(options: Options): Promise<MikroORM> {
const orm = new MikroORM(options);
const driver = await orm.connect();
orm.em = new EntityManager(orm.config, driver);

try {
const storage = new MetadataDiscovery(orm.em, orm.config, orm.logger);
orm.metadata = await storage.discover();
const discovery = new MetadataDiscovery(MetadataStorage.init(), orm.driver.getPlatform(), orm.config, orm.logger);
orm.metadata = await discovery.discover();
orm.em = new EntityManager(orm.config, driver, orm.metadata);
orm.metadata.decorate(orm.em);
driver.setMetadata(orm.metadata);

return orm;
} catch (e) {
Expand Down Expand Up @@ -57,7 +58,7 @@ export class MikroORM {
return this.driver.getConnection().close(force);
}

getMetadata(): Record<string, EntityMetadata> {
getMetadata(): MetadataStorage {
return this.metadata;
}

Expand Down
6 changes: 5 additions & 1 deletion lib/connections/Connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { MetadataStorage } from '../metadata';
export abstract class Connection {

protected readonly logger = this.config.getLogger();
protected readonly metadata = MetadataStorage.getMetadata();
protected metadata: MetadataStorage;
protected abstract client: any;

constructor(protected readonly config: Configuration) { }
Expand Down Expand Up @@ -56,6 +56,10 @@ export abstract class Connection {
return `${url.protocol}//${options.user}${options.password ? ':*****' : ''}@${options.host}:${options.port}`;
}

setMetadata(metadata: MetadataStorage): void {
this.metadata = metadata;
}

protected async executeQuery<T>(query: string, params: any[], cb: () => Promise<T>): Promise<T> {
const now = Date.now();
const res = await cb();
Expand Down
4 changes: 3 additions & 1 deletion lib/connections/MongoConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ export class MongoConnection extends Connection {

private getCollectionName(name: EntityName<IEntity>): string {
name = Utils.className(name);
return this.metadata[name] ? this.metadata[name].collection : name;
const meta = this.metadata.get(name);

return meta ? meta.collection : name;
}

}
14 changes: 7 additions & 7 deletions lib/drivers/AbstractSqlDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export abstract class AbstractSqlDriver<C extends AbstractSqlConnection = Abstra
}

async findOne<T extends IEntityType<T>>(entityName: string, where: FilterQuery<T> | string, populate: string[] = [], orderBy: QueryOrderMap = {}, fields?: string[], lockMode?: LockMode, ctx?: Transaction): Promise<T | null> {
const pk = this.metadata[entityName].primaryKey;
const pk = this.metadata.get(entityName).primaryKey;

if (Utils.isPrimaryKey(where)) {
where = { [pk]: where };
Expand All @@ -45,7 +45,7 @@ export abstract class AbstractSqlDriver<C extends AbstractSqlConnection = Abstra

async count(entityName: string, where: any, ctx?: Transaction): Promise<number> {
const qb = this.createQueryBuilder(entityName, ctx);
const pk = this.metadata[entityName].primaryKey;
const pk = this.metadata.get(entityName).primaryKey;
const res = await qb.count(pk, true).where(where).execute('get', false);

return +res.count;
Expand Down Expand Up @@ -78,7 +78,7 @@ export abstract class AbstractSqlDriver<C extends AbstractSqlConnection = Abstra
res = await qb.update(data).where(where).execute('run', false);
}

await this.processManyToMany(entityName, Utils.extractPK(data[pk] || where, this.metadata[entityName])!, collections, ctx);
await this.processManyToMany(entityName, Utils.extractPK(data[pk] || where, this.metadata.get(entityName))!, collections, ctx);

return res;
}
Expand All @@ -97,11 +97,11 @@ export abstract class AbstractSqlDriver<C extends AbstractSqlConnection = Abstra
}

protected extractManyToMany<T extends IEntityType<T>>(entityName: string, data: EntityData<T>): EntityData<T> {
if (!this.metadata[entityName]) {
if (!this.metadata.get(entityName)) {
return {};
}

const props = this.metadata[entityName].properties;
const props = this.metadata.get(entityName).properties;
const ret: EntityData<T> = {};

for (const k of Object.keys(data)) {
Expand All @@ -117,11 +117,11 @@ export abstract class AbstractSqlDriver<C extends AbstractSqlConnection = Abstra
}

protected async processManyToMany<T extends IEntityType<T>>(entityName: string, pk: IPrimaryKey, collections: EntityData<T>, ctx?: Transaction) {
if (!this.metadata[entityName]) {
if (!this.metadata.get(entityName)) {
return;
}

const props = this.metadata[entityName].properties;
const props = this.metadata.get(entityName).properties;
const owners = Object.keys(collections).filter(k => props[k].owner);

for (const k of owners) {
Expand Down
14 changes: 10 additions & 4 deletions lib/drivers/DatabaseDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export abstract class DatabaseDriver<C extends Connection> implements IDatabaseD

protected readonly connection: C;
protected readonly platform: Platform;
protected readonly metadata = MetadataStorage.getMetadata();
protected readonly logger = this.config.getLogger();
protected metadata: MetadataStorage;

constructor(protected readonly config: Configuration) { }

Expand All @@ -39,8 +39,8 @@ export abstract class DatabaseDriver<C extends Connection> implements IDatabaseD

const fk1 = prop.joinColumn;
const fk2 = prop.inverseJoinColumn;
const pivotTable = prop.owner ? prop.pivotTable : this.metadata[prop.type].properties[prop.mappedBy].pivotTable;
const orderBy = { [`${pivotTable}.${this.metadata[pivotTable].primaryKey}`]: QueryOrder.ASC };
const pivotTable = prop.owner ? prop.pivotTable : this.metadata.get(prop.type).properties[prop.mappedBy].pivotTable;
const orderBy = { [`${pivotTable}.${this.metadata.get(pivotTable).primaryKey}`]: QueryOrder.ASC };
const items = owners.length ? await this.find(prop.type, { [fk1]: { $in: owners } }, [pivotTable], orderBy, undefined, undefined, ctx) : [];

const map: Record<string, T[]> = {};
Expand Down Expand Up @@ -82,8 +82,14 @@ export abstract class DatabaseDriver<C extends Connection> implements IDatabaseD
return this.platform;
}

setMetadata(metadata: MetadataStorage): void {
this.metadata = metadata;
this.connection.setMetadata(metadata);
}

protected getPrimaryKeyField(entityName: string): string {
return this.metadata[entityName] ? this.metadata[entityName].primaryKey : this.config.getNamingStrategy().referenceColumnName();
const meta = this.metadata.get(entityName);
return meta ? meta.primaryKey : this.config.getNamingStrategy().referenceColumnName();
}

}
3 changes: 3 additions & 0 deletions lib/drivers/IDatabaseDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Connection, QueryResult, Transaction } from '../connections';
import { QueryOrderMap } from '../query';
import { Platform } from '../platforms';
import { LockMode } from '../unit-of-work';
import { MetadataStorage } from '../metadata';

export interface IDatabaseDriver<C extends Connection = Connection> {

Expand Down Expand Up @@ -37,6 +38,8 @@ export interface IDatabaseDriver<C extends Connection = Connection> {

getPlatform(): Platform;

setMetadata(metadata: MetadataStorage): void;

}

export type FilterQuery<T> = Partial<T> | Record<string, any>;
6 changes: 3 additions & 3 deletions lib/drivers/MongoDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class MongoDriver extends DatabaseDriver<MongoConnection> {
where = this.renameFields(entityName, where);
const res = await this.connection.find<T>(entityName, where, orderBy, limit, offset);

return res.map((r: T) => this.mapResult<T>(r, this.metadata[entityName])!);
return res.map((r: T) => this.mapResult<T>(r, this.metadata.get(entityName))!);
}

async findOne<T extends IEntityType<T>>(entityName: string, where: FilterQuery<T> | IPrimaryKey, populate: string[] = [], orderBy: QueryOrderMap = {}, fields?: string[], lockMode?: LockMode): Promise<T | null> {
Expand All @@ -28,7 +28,7 @@ export class MongoDriver extends DatabaseDriver<MongoConnection> {
where = this.renameFields(entityName, where) as FilterQuery<T>;
const res = await this.connection.find<T>(entityName, where, orderBy, 1, undefined, fields);

return this.mapResult<T>(res[0], this.metadata[entityName]);
return this.mapResult<T>(res[0], this.metadata.get(entityName));
}

async count<T extends IEntityType<T>>(entityName: string, where: FilterQuery<T>): Promise<number> {
Expand Down Expand Up @@ -69,7 +69,7 @@ export class MongoDriver extends DatabaseDriver<MongoConnection> {
private renameFields(entityName: string, data: any): any {
data = Object.assign({}, data); // copy first
Utils.renameKey(data, 'id', '_id');
const meta = this.metadata[entityName];
const meta = this.metadata.get(entityName);

Object.keys(data).forEach(k => {
if (meta && meta.properties[k]) {
Expand Down
4 changes: 2 additions & 2 deletions lib/entity/ArrayCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class ArrayCollection<T extends IEntityType<T>> {

toArray(): Record<string, any>[] {
return this.getItems().map(item => {
const meta = MetadataStorage.getMetadata(item.constructor.name);
const meta = this.owner.__em.getMetadata().get(item.constructor.name);
const args = [...meta.toJsonParams.map(() => undefined), [this.property.name]];

return item.toJSON(...args);
Expand Down Expand Up @@ -141,7 +141,7 @@ export class ArrayCollection<T extends IEntityType<T>> {

protected get property() {
if (!this._property) {
const meta = MetadataStorage.getMetadata(this.owner.constructor.name);
const meta = this.owner.__em.getMetadata().get(this.owner.constructor.name);
const field = Object.keys(meta.properties).find(k => this.owner[k] === this);
this._property = meta.properties[field!];
}
Expand Down
2 changes: 1 addition & 1 deletion lib/entity/EntityAssigner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class EntityAssigner {
static assign<T extends IEntityType<T>>(entity: T, data: EntityData<T>, options?: AssignOptions): void;
static assign<T extends IEntityType<T>>(entity: T, data: EntityData<T>, onlyProperties?: boolean): void;
static assign<T extends IEntityType<T>>(entity: T, data: EntityData<T>, onlyProperties: AssignOptions | boolean = false): void {
const meta = MetadataStorage.getMetadata(entity.constructor.name);
const meta = entity.__em.getMetadata().get(entity.constructor.name);
const props = meta.properties;
const options = (typeof onlyProperties === 'boolean' ? { onlyProperties } : onlyProperties);

Expand Down
8 changes: 4 additions & 4 deletions lib/entity/EntityFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ export const SCALAR_TYPES = ['string', 'number', 'boolean', 'Date'];

export class EntityFactory {

private readonly metadata = MetadataStorage.getMetadata();
private readonly hydrator = this.config.getHydrator(this);

constructor(private readonly unitOfWork: UnitOfWork,
private readonly driver: IDatabaseDriver,
private readonly config: Configuration) { }
private readonly config: Configuration,
private readonly metadata: MetadataStorage) { }

create<T extends IEntityType<T>>(entityName: EntityName<T>, data: EntityData<T>, initialized = true): T {
entityName = Utils.className(entityName);
data = Object.assign({}, data);
const meta = this.metadata[entityName];
const meta = this.metadata.get(entityName);
const platform = this.driver.getPlatform();
const pk = platform.getSerializedPrimaryKeyField(meta.primaryKey);

Expand Down Expand Up @@ -64,7 +64,7 @@ export class EntityFactory {

createReference<T extends IEntityType<T>>(entityName: EntityName<T>, id: IPrimaryKey): T {
entityName = Utils.className(entityName);
const meta = this.metadata[entityName];
const meta = this.metadata.get(entityName);

if (this.unitOfWork.getById(entityName, id)) {
return this.unitOfWork.getById<T>(entityName, id);
Expand Down

0 comments on commit 92205d6

Please sign in to comment.