Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): refactor internals to reduce number of cycles #830

Merged
merged 2 commits into from
Sep 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions packages/cli/src/CLIConfigurator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import yargs, { Argv } from 'yargs';

import { ConfigurationLoader, Utils } from '@mikro-orm/core';
import { ClearCacheCommand } from './commands/ClearCacheCommand';
import { GenerateEntitiesCommand } from './commands/GenerateEntitiesCommand';
import { SchemaCommandFactory } from './commands/SchemaCommandFactory';
import { MigrationCommandFactory } from './commands/MigrationCommandFactory';
import { DebugCommand } from './commands/DebugCommand';
import { GenerateCacheCommand } from './commands/GenerateCacheCommand';
import { ImportCommand } from './commands/ImportCommand';

export class CLIConfigurator {

static async configure(): Promise<Argv> {
const settings = await ConfigurationLoader.getSettings();

if (settings.useTsNode) {
await ConfigurationLoader.registerTsNode(settings.tsConfigPath);
}

// noinspection HtmlDeprecatedTag
return yargs
.scriptName('mikro-orm')
.version(Utils.getORMVersion())
.usage('Usage: $0 <command> [options]')
.example('$0 schema:update --run', 'Runs schema synchronization')
.alias('v', 'version')
.alias('h', 'help')
.command(new ClearCacheCommand())
.command(new GenerateCacheCommand())
.command(new GenerateEntitiesCommand())
.command(new ImportCommand())
.command(SchemaCommandFactory.create('create'))
.command(SchemaCommandFactory.create('drop'))
.command(SchemaCommandFactory.create('update'))
.command(MigrationCommandFactory.create('create'))
.command(MigrationCommandFactory.create('up'))
.command(MigrationCommandFactory.create('down'))
.command(MigrationCommandFactory.create('list'))
.command(MigrationCommandFactory.create('pending'))
.command(new DebugCommand())
.recommendCommands()
.strict();
}

}
40 changes: 0 additions & 40 deletions packages/cli/src/CLIHelper.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import yargs, { Argv } from 'yargs';
import { pathExists } from 'fs-extra';
import CliTable3, { Table } from 'cli-table3';
import c from 'ansi-colors';

import { Configuration, ConfigurationLoader, IDatabaseDriver, MikroORM, Utils } from '@mikro-orm/core';
import { ClearCacheCommand } from './commands/ClearCacheCommand';
import { GenerateEntitiesCommand } from './commands/GenerateEntitiesCommand';
import { SchemaCommandFactory } from './commands/SchemaCommandFactory';
import { MigrationCommandFactory } from './commands/MigrationCommandFactory';
import { DebugCommand } from './commands/DebugCommand';
import { GenerateCacheCommand } from './commands/GenerateCacheCommand';
import { ImportCommand } from './commands/ImportCommand';

export class CLIHelper {

Expand All @@ -34,38 +26,6 @@ export class CLIHelper {
return MikroORM.init(options);
}

static async configure(): Promise<Argv> {
const settings = await ConfigurationLoader.getSettings();

if (settings.useTsNode) {
await ConfigurationLoader.registerTsNode(settings.tsConfigPath);
}

// noinspection HtmlDeprecatedTag
return yargs
.scriptName('mikro-orm')
.version(Utils.getORMVersion())
.usage('Usage: $0 <command> [options]')
.example('$0 schema:update --run', 'Runs schema synchronization')
.alias('v', 'version')
.alias('h', 'help')
.command(new ClearCacheCommand())
.command(new GenerateCacheCommand())
.command(new GenerateEntitiesCommand())
.command(new ImportCommand())
.command(SchemaCommandFactory.create('create'))
.command(SchemaCommandFactory.create('drop'))
.command(SchemaCommandFactory.create('update'))
.command(MigrationCommandFactory.create('create'))
.command(MigrationCommandFactory.create('up'))
.command(MigrationCommandFactory.create('down'))
.command(MigrationCommandFactory.create('list'))
.command(MigrationCommandFactory.create('pending'))
.command(new DebugCommand())
.recommendCommands()
.strict();
}

static getNodeVersion(): string {
return process.versions.node;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ require('yargonaut')
.errorsStyle('red');

import yargs from 'yargs';
import { CLIHelper } from './CLIHelper';
import { CLIConfigurator } from './CLIConfigurator';

(async () => {
const args = (await CLIHelper.configure()).parse(process.argv.slice(2)) as { _: string[] };
const args = (await CLIConfigurator.configure()).parse(process.argv.slice(2)) as { _: string[] };

if (args._.length === 0) {
yargs.showHelp();
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './CLIHelper';
export * from './CLIConfigurator';
17 changes: 12 additions & 5 deletions packages/core/src/EntityManager.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { v4 as uuid } from 'uuid';
import { inspect } from 'util';

import { Configuration, OptimisticLockError, QueryHelper, RequestContext, Utils, ValidationError } from './utils';
import { AssignOptions, EntityAssigner, EntityFactory, EntityLoader, EntityRepository, EntityValidator, IdentifiedReference, LoadStrategy, Reference, ReferenceType, SCALAR_TYPES } from './entity';
import { LockMode, UnitOfWork } from './unit-of-work';
import { Configuration, QueryHelper, RequestContext, Utils } from './utils';
import { AssignOptions, EntityAssigner, EntityFactory, EntityLoader, EntityRepository, EntityValidator, IdentifiedReference, Reference } from './entity';
import { UnitOfWork } from './unit-of-work';
import { CountOptions, DeleteOptions, EntityManagerType, FindOneOptions, FindOneOrFailOptions, FindOptions, IDatabaseDriver, UpdateOptions } from './drivers';
import { AnyEntity, Dictionary, EntityData, EntityMetadata, EntityName, FilterDef, FilterQuery, Loaded, Primary, Populate, PopulateMap, PopulateOptions, New, GetRepository } from './typings';
import { QueryOrderMap } from './enums';
import { LoadStrategy, LockMode, QueryOrderMap, ReferenceType, SCALAR_TYPES } from './enums';
import { MetadataStorage } from './metadata';
import { Transaction } from './connections';
import { EventManager } from './events';
import { EntityComparator } from './utils/EntityComparator';
import { OptimisticLockError, ValidationError } from './errors';

/**
* The EntityManager is the central access point to ORM functionality. It is a facade to all different ORM subsystems
Expand All @@ -23,6 +25,7 @@ export class EntityManager<D extends IDatabaseDriver = IDatabaseDriver> {
private readonly entityLoader: EntityLoader = new EntityLoader(this);
private readonly unitOfWork = new UnitOfWork(this);
private readonly entityFactory = new EntityFactory(this.unitOfWork, this);
private readonly comparator = new EntityComparator(this.metadata, this.driver.getPlatform());
private filters: Dictionary<FilterDef<any>> = {};
private filterParams: Dictionary<Dictionary> = {};
private transactionContext?: Transaction;
Expand Down Expand Up @@ -331,7 +334,7 @@ export class EntityManager<D extends IDatabaseDriver = IDatabaseDriver> {

if (data === undefined) {
entityName = entityNameOrEntity.constructor.name;
data = Utils.prepareEntity(entityNameOrEntity as T, this.metadata, this.driver.getPlatform());
data = this.comparator.prepareEntity(entityNameOrEntity as T);
} else {
entityName = Utils.className(entityNameOrEntity as EntityName<T>);
}
Expand Down Expand Up @@ -679,6 +682,10 @@ export class EntityManager<D extends IDatabaseDriver = IDatabaseDriver> {
return this.metadata;
}

getComparator(): EntityComparator {
return this.comparator;
}

private checkLockRequirements(mode: LockMode | undefined, meta: EntityMetadata): void {
if (!mode) {
return;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/cache/FileCacheAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import globby from 'globby';
import { ensureDir, pathExists, readFile, readJSON, unlink, writeJSON } from 'fs-extra';

import { CacheAdapter } from './CacheAdapter';
import { Utils } from '../utils';
import { Utils } from '../utils/Utils';

export class FileCacheAdapter implements CacheAdapter {

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/decorators/Embedded.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AnyEntity, EntityProperty } from '../typings';
import { MetadataStorage, MetadataValidator } from '../metadata';
import { ReferenceType } from '../entity/enums';
import { Utils } from '../utils';
import { ReferenceType } from '../enums';

export function Embedded(options: EmbeddedOptions | (() => AnyEntity) = {}) {
return function (target: AnyEntity, propertyName: string) {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/decorators/Enum.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MetadataStorage } from '../metadata';
import { ReferenceType } from '../entity';
import { PropertyOptions } from '.';
import { ReferenceType } from '../enums';
import { PropertyOptions } from './Property';
import { EntityProperty, AnyEntity, Dictionary } from '../typings';

export function Enum(options: EnumOptions<AnyEntity> | (() => Dictionary) = {}) {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/decorators/Formula.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MetadataStorage } from '../metadata';
import { ReferenceType } from '../entity';
import { ReferenceType } from '../enums';
import { EntityProperty, AnyEntity } from '../typings';

export function Formula(formula: string | ((alias: string) => string)) {
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/decorators/ManyToMany.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { ReferenceOptions } from './Property';
import { MetadataStorage, MetadataValidator } from '../metadata';
import { Utils } from '../utils';
import { ReferenceType } from '../entity';
import { EntityName, EntityProperty, AnyEntity } from '../typings';
import { QueryOrder } from '../enums';
import { ReferenceType, QueryOrder } from '../enums';

export function ManyToMany<T, O>(
entity?: ManyToManyOptions<T, O> | string | (() => EntityName<T>),
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/decorators/ManyToOne.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ReferenceOptions } from './Property';
import { MetadataStorage, MetadataValidator } from '../metadata';
import { Utils } from '../utils';
import { ReferenceType } from '../entity';
import { ReferenceType } from '../enums';
import { AnyEntity, EntityName, EntityProperty } from '../typings';

export function ManyToOne<T, O>(
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/decorators/OneToMany.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { ReferenceOptions } from './Property';
import { MetadataStorage, MetadataValidator } from '../metadata';
import { Utils } from '../utils';
import { ReferenceType } from '../entity';
import { QueryOrder } from '../enums';
import { ReferenceType, QueryOrder } from '../enums';
import { EntityName, EntityProperty, AnyEntity } from '../typings';

export function createOneToDecorator<T, O>(
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/decorators/OneToOne.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ReferenceType } from '../entity';
import { ReferenceType } from '../enums';
import { createOneToDecorator, OneToManyOptions } from './OneToMany';
import { EntityName } from '../typings';

Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/decorators/PrimaryKey.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MetadataStorage, MetadataValidator } from '../metadata';
import { ReferenceType } from '../entity';
import { PropertyOptions } from '.';
import { ReferenceType } from '../enums';
import { PropertyOptions } from './Property';
import { AnyEntity, EntityProperty } from '../typings';

function createDecorator<T>(options: PrimaryKeyOptions<T> | SerializedPrimaryKeyOptions<T>, serialized: boolean) {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/decorators/Property.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MetadataStorage, MetadataValidator } from '../metadata';
import { Utils } from '../utils';
import { Cascade, ReferenceType, LoadStrategy } from '../entity';
import { Cascade, ReferenceType, LoadStrategy } from '../enums';
import { EntityName, EntityProperty, AnyEntity, Constructor } from '../typings';
import { Type } from '../types';

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/decorators/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MetadataStorage } from '../metadata';
import { EventType } from '../events';
import { EventType } from '../enums';

function hook(type: EventType) {
return function (target: any, method: string) {
Expand Down
10 changes: 6 additions & 4 deletions packages/core/src/drivers/DatabaseDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { EntityManagerType, FindOneOptions, FindOptions, IDatabaseDriver } from
import { EntityData, EntityMetadata, EntityProperty, FilterQuery, AnyEntity, Dictionary, Primary, PopulateOptions } from '../typings';
import { MetadataStorage } from '../metadata';
import { Connection, QueryResult, Transaction } from '../connections';
import { Configuration, ConnectionOptions, Utils, ValidationError } from '../utils';
import { QueryOrder, QueryOrderMap } from '../enums';
import { Configuration, ConnectionOptions, Utils } from '../utils';
import { LockMode, QueryOrder, QueryOrderMap, ReferenceType } from '../enums';
import { Platform } from '../platforms';
import { Collection, ReferenceType } from '../entity';
import { DriverException, EntityManager, LockMode } from '../index';
import { Collection } from '../entity';
import { EntityManager } from '../EntityManager';
import { ValidationError } from '../errors';
import { DriverException } from '../exceptions';

export abstract class DatabaseDriver<C extends Connection> implements IDatabaseDriver<C> {

Expand Down
7 changes: 3 additions & 4 deletions packages/core/src/drivers/IDatabaseDriver.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { EntityData, EntityMetadata, EntityProperty, AnyEntity, FilterQuery, Primary, Dictionary, QBFilterQuery, IPrimaryKey, Populate, PopulateOptions } from '../typings';
import { Connection, QueryResult, Transaction } from '../connections';
import { QueryOrderMap, QueryFlag } from '../enums';
import { LockMode, QueryOrderMap, QueryFlag, LoadStrategy } from '../enums';
import { Platform } from '../platforms';
import { MetadataStorage } from '../metadata';
import { LockMode } from '../unit-of-work';
import { Collection, LoadStrategy } from '../entity';
import { EntityManager } from '../index';
import { Collection } from '../entity';
import { EntityManager } from '../EntityManager';
import { DriverException } from '../exceptions';

export const EntityManagerType = Symbol('EntityManagerType');
Expand Down
19 changes: 14 additions & 5 deletions packages/core/src/entity/ArrayCollection.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { AnyEntity, Dictionary, EntityProperty, IPrimaryKey, Primary } from '../typings';
import { ReferenceType } from './enums';
import { Collection } from './Collection';
import { Reference } from './Reference';
import { wrap } from './wrap';
import { ReferenceType } from '../enums';

export class ArrayCollection<T extends AnyEntity<T>, O extends AnyEntity<O>> {

[k: number]: T;

protected readonly items: T[] = [];
protected initialized = true;
private _property?: EntityProperty;

constructor(readonly owner: O, items?: T[]) {
Expand All @@ -20,6 +20,7 @@ export class ArrayCollection<T extends AnyEntity<T>, O extends AnyEntity<O>> {
Object.defineProperty(this, 'items', { enumerable: false });
Object.defineProperty(this, 'owner', { enumerable: false, writable: true });
Object.defineProperty(this, '_property', { enumerable: false, writable: true });
Object.defineProperty(this, '__collection', { value: true });
}

getItems(): T[] {
Expand Down Expand Up @@ -111,6 +112,14 @@ export class ArrayCollection<T extends AnyEntity<T>, O extends AnyEntity<O>> {
return this.items.length;
}

isInitialized(fully = false): boolean {
if (fully) {
return this.initialized && this.items.every(item => item.__helper!.isInitialized());
}

return this.initialized;
}

get length(): number {
return this.count();
}
Expand Down Expand Up @@ -143,15 +152,15 @@ export class ArrayCollection<T extends AnyEntity<T>, O extends AnyEntity<O>> {
}

protected propagateToInverseSide(item: T, method: 'add' | 'remove'): void {
const collection = item[this.property.inversedBy as keyof T] as unknown as Collection<O, T>;
const collection = item[this.property.inversedBy as keyof T] as unknown as ArrayCollection<O, T>;

if (this.shouldPropagateToCollection(collection, method)) {
collection[method](this.owner);
}
}

protected propagateToOwningSide(item: T, method: 'add' | 'remove'): void {
const collection = item[this.property.mappedBy as keyof T] as unknown as Collection<O, T>;
const collection = item[this.property.mappedBy as keyof T] as unknown as ArrayCollection<O, T>;

if (this.property.reference === ReferenceType.MANY_TO_MANY && this.shouldPropagateToCollection(collection, method)) {
collection[method](this.owner);
Expand All @@ -160,7 +169,7 @@ export class ArrayCollection<T extends AnyEntity<T>, O extends AnyEntity<O>> {
}
}

protected shouldPropagateToCollection(collection: Collection<O, T>, method: 'add' | 'remove'): boolean {
protected shouldPropagateToCollection(collection: ArrayCollection<O, T>, method: 'add' | 'remove'): boolean {
if (!collection || !collection.isInitialized()) {
return false;
}
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/entity/BaseEntity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { AssignOptions, EntityAssigner } from './EntityAssigner';

export abstract class BaseEntity<T extends AnyEntity<T>, PK extends keyof T> implements IWrappedEntity<T, PK> {

constructor() {
Object.defineProperty(this, '__baseEntity', { value: true });
}

isInitialized(): boolean {
return (this as unknown as T).__helper!.isInitialized();
}
Expand Down
Loading