diff --git a/src/common/EntityTarget.ts b/src/common/EntityTarget.ts new file mode 100644 index 0000000000..6ee00dd1be --- /dev/null +++ b/src/common/EntityTarget.ts @@ -0,0 +1,11 @@ +import {ObjectType} from "./ObjectType"; +import {EntitySchema} from ".."; + +/** + * Entity target. + */ +export type EntityTarget = + | ObjectType + | EntitySchema + | string + | { type: Entity, name: string }; diff --git a/src/connection/Connection.ts b/src/connection/Connection.ts index 1ddb8ff7b5..3f7ba32706 100644 --- a/src/connection/Connection.ts +++ b/src/connection/Connection.ts @@ -1,6 +1,7 @@ import {Driver} from "../driver/Driver"; import {Repository} from "../repository/Repository"; import {EntitySubscriberInterface} from "../subscriber/EntitySubscriberInterface"; +import {EntityTarget} from "../common/EntityTarget"; import {ObjectType} from "../common/ObjectType"; import {EntityManager} from "../entity-manager/EntityManager"; import {DefaultNamingStrategy} from "../naming-strategy/DefaultNamingStrategy"; @@ -320,14 +321,14 @@ export class Connection { /** * Checks if entity metadata exist for the given entity class, target name or table name. */ - hasMetadata(target: Function|EntitySchema|string): boolean { + hasMetadata(target: EntityTarget): boolean { return !!this.findMetadata(target); } /** * Gets entity metadata for the given entity class or schema name. */ - getMetadata(target: Function|EntitySchema|string): EntityMetadata { + getMetadata(target: EntityTarget): EntityMetadata { const metadata = this.findMetadata(target); if (!metadata) throw new EntityMetadataNotFoundError(target); @@ -338,7 +339,7 @@ export class Connection { /** * Gets repository for the given entity. */ - getRepository(target: ObjectType|EntitySchema|string): Repository { + getRepository(target: EntityTarget): Repository { return this.manager.getRepository(target); } @@ -346,7 +347,7 @@ export class Connection { * Gets tree repository for the given entity class or name. * Only tree-type entities can have a TreeRepository, like ones decorated with @Tree decorator. */ - getTreeRepository(target: ObjectType|EntitySchema|string): TreeRepository { + getTreeRepository(target: EntityTarget): TreeRepository { return this.manager.getTreeRepository(target); } @@ -354,7 +355,7 @@ export class Connection { * Gets mongodb-specific repository for the given entity class or name. * Works only if connection is mongodb-specific. */ - getMongoRepository(target: ObjectType|EntitySchema|string): MongoRepository { + getMongoRepository(target: EntityTarget): MongoRepository { if (!(this.driver instanceof MongoDriver)) throw new Error(`You can use getMongoRepository only for MongoDB connections.`); @@ -408,7 +409,7 @@ export class Connection { /** * Creates a new query builder that can be used to build a sql query. */ - createQueryBuilder(entityClass: ObjectType|EntitySchema|Function|string, alias: string, queryRunner?: QueryRunner): SelectQueryBuilder; + createQueryBuilder(entityClass: EntityTarget, alias: string, queryRunner?: QueryRunner): SelectQueryBuilder; /** * Creates a new query builder that can be used to build a sql query. @@ -418,12 +419,12 @@ export class Connection { /** * Creates a new query builder that can be used to build a sql query. */ - createQueryBuilder(entityOrRunner?: ObjectType|EntitySchema|Function|string|QueryRunner, alias?: string, queryRunner?: QueryRunner): SelectQueryBuilder { + createQueryBuilder(entityOrRunner?: EntityTarget|QueryRunner, alias?: string, queryRunner?: QueryRunner): SelectQueryBuilder { if (this instanceof MongoEntityManager) throw new Error(`Query Builder is not supported by MongoDB.`); if (alias) { - const metadata = this.getMetadata(entityOrRunner as Function|EntitySchema|string); + const metadata = this.getMetadata(entityOrRunner as EntityTarget); return new SelectQueryBuilder(this, queryRunner) .select(alias) .from(metadata.target, alias); @@ -453,7 +454,7 @@ export class Connection { /** * Gets entity metadata of the junction table (many-to-many table). */ - getManyToManyMetadata(entityTarget: Function|string, relationPropertyPath: string) { + getManyToManyMetadata(entityTarget: EntityTarget, relationPropertyPath: string) { const relationMetadata = this.getMetadata(entityTarget).findRelationWithPropertyPath(relationPropertyPath); if (!relationMetadata) throw new Error(`Relation "${relationPropertyPath}" was not found in ${entityTarget} entity.`); @@ -478,7 +479,7 @@ export class Connection { /** * Finds exist entity metadata by the given entity class, target name or table name. */ - protected findMetadata(target: Function|EntitySchema|string): EntityMetadata|undefined { + protected findMetadata(target: EntityTarget): EntityMetadata|undefined { return this.entityMetadatas.find(metadata => { if (metadata.target === target) return true; diff --git a/src/entity-manager/EntityManager.ts b/src/entity-manager/EntityManager.ts index 5ed47b3690..1d214757ec 100644 --- a/src/entity-manager/EntityManager.ts +++ b/src/entity-manager/EntityManager.ts @@ -1,5 +1,6 @@ import {Connection} from "../connection/Connection"; import {FindManyOptions} from "../find-options/FindManyOptions"; +import {EntityTarget} from "../common/EntityTarget"; import {ObjectType} from "../common/ObjectType"; import {EntityNotFoundError} from "../error/EntityNotFoundError"; import {QueryRunnerProviderAlreadyReleasedError} from "../error/QueryRunnerProviderAlreadyReleasedError"; @@ -161,17 +162,7 @@ export class EntityManager { /** * Creates a new query builder that can be used to build a sql query. */ - createQueryBuilder(entityClass: ObjectType, alias: string, queryRunner?: QueryRunner): SelectQueryBuilder; - - /** - * Creates a new query builder that can be used to build a sql query. - */ - createQueryBuilder(entityClass: EntitySchema, alias: string, queryRunner?: QueryRunner): SelectQueryBuilder; - - /** - * Creates a new query builder that can be used to build a sql query. - */ - createQueryBuilder(entityName: string, alias: string, queryRunner?: QueryRunner): SelectQueryBuilder; + createQueryBuilder(entityClass: EntityTarget, alias: string, queryRunner?: QueryRunner): SelectQueryBuilder; /** * Creates a new query builder that can be used to build a sql query. @@ -181,9 +172,9 @@ export class EntityManager { /** * Creates a new query builder that can be used to build a sql query. */ - createQueryBuilder(entityClass?: ObjectType|EntitySchema|string|QueryRunner, alias?: string, queryRunner?: QueryRunner): SelectQueryBuilder { + createQueryBuilder(entityClass?: EntityTarget|QueryRunner, alias?: string, queryRunner?: QueryRunner): SelectQueryBuilder { if (alias) { - return this.connection.createQueryBuilder(entityClass as EntitySchema|string, alias, queryRunner || this.queryRunner); + return this.connection.createQueryBuilder(entityClass as EntityTarget, alias, queryRunner || this.queryRunner); } else { return this.connection.createQueryBuilder(entityClass as QueryRunner|undefined || queryRunner || this.queryRunner); @@ -218,12 +209,12 @@ export class EntityManager { /** * Gets entity mixed id. */ - getId(target: Function|string, entity: any): any; + getId(target: EntityTarget, entity: any): any; /** * Gets entity mixed id. */ - getId(targetOrEntity: any|Function|string, maybeEntity?: any): any { + getId(targetOrEntity: any|EntityTarget, maybeEntity?: any): any { const target = arguments.length === 2 ? targetOrEntity : targetOrEntity.constructor; const entity = arguments.length === 2 ? maybeEntity : targetOrEntity; const metadata = this.connection.getMetadata(target); @@ -234,43 +225,19 @@ export class EntityManager { * Creates a new entity instance and copies all entity properties from this object into a new entity. * Note that it copies only properties that present in entity schema. */ - create(entityClass: ObjectType, plainObject?: DeepPartial): Entity; + create(entityClass: EntityTarget, plainObject?: DeepPartial): Entity; /** * Creates a new entities and copies all entity properties from given objects into their new entities. * Note that it copies only properties that present in entity schema. */ - create(entityClass: ObjectType, plainObjects?: DeepPartial[]): Entity[]; - - /** - * Creates a new entity instance and copies all entity properties from this object into a new entity. - * Note that it copies only properties that present in entity schema. - */ - create(entitySchema: EntitySchema, plainObject?: DeepPartial): Entity; - - /** - * Creates a new entities and copies all entity properties from given objects into their new entities. - * Note that it copies only properties that present in entity schema. - */ - create(entitySchema: EntitySchema, plainObjects?: DeepPartial[]): Entity[]; - - /** - * Creates a new entity instance and copies all entity properties from this object into a new entity. - * Note that it copies only properties that present in entity schema. - */ - create(entityName: string, plainObject?: DeepPartial): Entity; - - /** - * Creates a new entities and copies all entity properties from given objects into their new entities. - * Note that it copies only properties that present in entity schema. - */ - create(entityName: string, plainObjects?: DeepPartial[]): Entity[]; + create(entityClass: EntityTarget, plainObjects?: DeepPartial[]): Entity[]; /** * Creates a new entity instance or instances. * Can copy properties from the given object into new entities. */ - create(entityClass: ObjectType|EntitySchema|string, plainObjectOrObjects?: DeepPartial|DeepPartial[]): Entity|Entity[] { + create(entityClass: EntityTarget, plainObjectOrObjects?: DeepPartial|DeepPartial[]): Entity|Entity[] { const metadata = this.connection.getMetadata(entityClass); if (!plainObjectOrObjects) @@ -287,22 +254,7 @@ export class EntityManager { /** * Merges two entities into one new entity. */ - merge(entityClass: ObjectType, mergeIntoEntity: Entity, ...entityLikes: DeepPartial[]): Entity; - - /** - * Merges two entities into one new entity. - */ - merge(entitySchema: EntitySchema, mergeIntoEntity: Entity, ...entityLikes: DeepPartial[]): Entity; - - /** - * Merges two entities into one new entity. - */ - merge(entityName: string, mergeIntoEntity: Entity, ...entityLikes: DeepPartial[]): Entity; - - /** - * Merges two entities into one new entity. - */ - merge(entityClass: ObjectType|EntitySchema|string, mergeIntoEntity: Entity, ...entityLikes: DeepPartial[]): Entity { // todo: throw exception if entity manager is released + merge(entityClass: EntityTarget, mergeIntoEntity: Entity, ...entityLikes: DeepPartial[]): Entity { // todo: throw exception if entity manager is released const metadata = this.connection.getMetadata(entityClass); entityLikes.forEach(object => this.plainObjectToEntityTransformer.transform(mergeIntoEntity, object, metadata)); return mergeIntoEntity; @@ -314,31 +266,7 @@ export class EntityManager { * and returns this new entity. This new entity is actually a loaded from the db entity with all properties * replaced from the new object. */ - preload(entityClass: ObjectType, entityLike: DeepPartial): Promise; - - /** - * Creates a new entity from the given plain javascript object. If entity already exist in the database, then - * it loads it (and everything related to it), replaces all values with the new ones from the given object - * and returns this new entity. This new entity is actually a loaded from the db entity with all properties - * replaced from the new object. - */ - preload(entitySchema: EntitySchema, entityLike: DeepPartial): Promise; - - /** - * Creates a new entity from the given plain javascript object. If entity already exist in the database, then - * it loads it (and everything related to it), replaces all values with the new ones from the given object - * and returns this new entity. This new entity is actually a loaded from the db entity with all properties - * replaced from the new object. - */ - preload(entityName: string, entityLike: DeepPartial): Promise; - - /** - * Creates a new entity from the given plain javascript object. If entity already exist in the database, then - * it loads it (and everything related to it), replaces all values with the new ones from the given object - * and returns this new entity. This new entity is actually a loaded from the db entity with all properties - * replaced from the new object. - */ - async preload(entityClass: ObjectType|EntitySchema|string, entityLike: DeepPartial): Promise { + async preload(entityClass: EntityTarget, entityLike: DeepPartial): Promise { const metadata = this.connection.getMetadata(entityClass); const plainObjectToDatabaseEntityTransformer = new PlainObjectToDatabaseEntityTransformer(this.connection.manager); const transformedEntity = await plainObjectToDatabaseEntityTransformer.transform(entityLike, metadata); @@ -364,30 +292,18 @@ export class EntityManager { * Saves all given entities in the database. * If entities do not exist in the database then inserts, otherwise updates. */ - save>(targetOrEntity: ObjectType|EntitySchema, entities: T[], options?: SaveOptions): Promise; - - /** - * Saves all given entities in the database. - * If entities do not exist in the database then inserts, otherwise updates. - */ - save>(targetOrEntity: ObjectType|EntitySchema, entity: T, options?: SaveOptions): Promise; + save>(targetOrEntity: EntityTarget, entities: T[], options?: SaveOptions): Promise; /** * Saves all given entities in the database. * If entities do not exist in the database then inserts, otherwise updates. */ - save(targetOrEntity: string, entities: T[], options?: SaveOptions): Promise; - - /** - * Saves all given entities in the database. - * If entities do not exist in the database then inserts, otherwise updates. - */ - save(targetOrEntity: string, entity: T, options?: SaveOptions): Promise; + save>(targetOrEntity: EntityTarget, entity: T, options?: SaveOptions): Promise; /** * Saves a given entity in the database. */ - save>(targetOrEntity: (T|T[])|ObjectType|EntitySchema|string, maybeEntityOrOptions?: T|T[], maybeOptions?: SaveOptions): Promise { + save>(targetOrEntity: (T|T[])|EntityTarget, maybeEntityOrOptions?: T|T[], maybeOptions?: SaveOptions): Promise { // normalize mixed parameters let target = (arguments.length > 1 && (targetOrEntity instanceof Function || targetOrEntity instanceof EntitySchema || typeof targetOrEntity === "string")) ? targetOrEntity as Function|string : undefined; @@ -415,17 +331,7 @@ export class EntityManager { /** * Removes a given entity from the database. */ - remove(targetOrEntity: ObjectType, entity: Entity, options?: RemoveOptions): Promise; - - /** - * Removes a given entity from the database. - */ - remove(targetOrEntity: EntitySchema, entity: Entity, options?: RemoveOptions): Promise; - - /** - * Removes a given entity from the database. - */ - remove(targetOrEntity: string, entity: Entity, options?: RemoveOptions): Promise; + remove(targetOrEntity: EntityTarget, entity: Entity, options?: RemoveOptions): Promise; /** * Removes a given entity from the database. @@ -435,22 +341,12 @@ export class EntityManager { /** * Removes a given entity from the database. */ - remove(targetOrEntity: ObjectType, entity: Entity[], options?: RemoveOptions): Promise; - - /** - * Removes a given entity from the database. - */ - remove(targetOrEntity: EntitySchema, entity: Entity[], options?: RemoveOptions): Promise; - - /** - * Removes a given entity from the database. - */ - remove(targetOrEntity: string, entity: Entity[], options?: RemoveOptions): Promise; + remove(targetOrEntity: EntityTarget, entity: Entity[], options?: RemoveOptions): Promise; /** * Removes a given entity from the database. */ - remove(targetOrEntity: (Entity|Entity[])|Function|string, maybeEntityOrOptions?: Entity|Entity[], maybeOptions?: RemoveOptions): Promise { + remove(targetOrEntity: (Entity|Entity[])|EntityTarget, maybeEntityOrOptions?: Entity|Entity[], maybeOptions?: RemoveOptions): Promise { // normalize mixed parameters const target = (arguments.length > 1 && (targetOrEntity instanceof Function || typeof targetOrEntity === "string")) ? targetOrEntity as Function|string : undefined; @@ -480,27 +376,17 @@ export class EntityManager { /** * Records the delete date of all given entities. */ - softRemove>(targetOrEntity: ObjectType|EntitySchema, entities: T[], options?: SaveOptions): Promise; + softRemove>(targetOrEntity: EntityTarget, entities: T[], options?: SaveOptions): Promise; /** * Records the delete date of a given entity. */ - softRemove>(targetOrEntity: ObjectType|EntitySchema, entity: T, options?: SaveOptions): Promise; - - /** - * Records the delete date of all given entities. - */ - softRemove(targetOrEntity: string, entities: T[], options?: SaveOptions): Promise; - - /** - * Records the delete date of a given entity. - */ - softRemove(targetOrEntity: string, entity: T, options?: SaveOptions): Promise; + softRemove>(targetOrEntity: EntityTarget, entity: T, options?: SaveOptions): Promise; /** * Records the delete date of one or many given entities. */ - softRemove>(targetOrEntity: (T|T[])|ObjectType|EntitySchema|string, maybeEntityOrOptions?: T|T[], maybeOptions?: SaveOptions): Promise { + softRemove>(targetOrEntity: (T|T[])|EntityTarget, maybeEntityOrOptions?: T|T[], maybeOptions?: SaveOptions): Promise { // normalize mixed parameters let target = (arguments.length > 1 && (targetOrEntity instanceof Function || targetOrEntity instanceof EntitySchema || typeof targetOrEntity === "string")) ? targetOrEntity as Function|string : undefined; @@ -533,27 +419,17 @@ export class EntityManager { /** * Recovers all given entities. */ - recover>(targetOrEntity: ObjectType|EntitySchema, entities: T[], options?: SaveOptions): Promise; + recover>(targetOrEntity: EntityTarget, entities: T[], options?: SaveOptions): Promise; /** * Recovers a given entity. */ - recover>(targetOrEntity: ObjectType|EntitySchema, entity: T, options?: SaveOptions): Promise; - - /** - * Recovers all given entities. - */ - recover(targetOrEntity: string, entities: T[], options?: SaveOptions): Promise; - - /** - * Recovers a given entity. - */ - recover(targetOrEntity: string, entity: T, options?: SaveOptions): Promise; + recover>(targetOrEntity: EntityTarget, entity: T, options?: SaveOptions): Promise; /** * Recovers one or many given entities. */ - recover>(targetOrEntity: (T|T[])|ObjectType|EntitySchema|string, maybeEntityOrOptions?: T|T[], maybeOptions?: SaveOptions): Promise { + recover>(targetOrEntity: (T|T[])|EntityTarget, maybeEntityOrOptions?: T|T[], maybeOptions?: SaveOptions): Promise { // normalize mixed parameters let target = (arguments.length > 1 && (targetOrEntity instanceof Function || targetOrEntity instanceof EntitySchema || typeof targetOrEntity === "string")) ? targetOrEntity as Function|string : undefined; @@ -580,7 +456,7 @@ export class EntityManager { * Does not check if entity exist in the database, so query will fail if duplicate entity is being inserted. * You can execute bulk inserts using this method. */ - async insert(target: ObjectType|EntitySchema|string, entity: QueryDeepPartialEntity|(QueryDeepPartialEntity[])): Promise { + async insert(target: EntityTarget, entity: QueryDeepPartialEntity|(QueryDeepPartialEntity[])): Promise { // TODO: Oracle does not support multiple values. Need to create another nice solution. if (this.connection.driver instanceof OracleDriver && Array.isArray(entity)) { const results = await Promise.all(entity.map(entity => this.insert(target, entity))); @@ -600,7 +476,7 @@ export class EntityManager { * Does not check if entity exist in the database. * Condition(s) cannot be empty. */ - update(target: ObjectType|EntitySchema|string, criteria: string|string[]|number|number[]|Date|Date[]|ObjectID|ObjectID[]|any, partialEntity: QueryDeepPartialEntity): Promise { + update(target: EntityTarget, criteria: string|string[]|number|number[]|Date|Date[]|ObjectID|ObjectID[]|any, partialEntity: QueryDeepPartialEntity): Promise { // if user passed empty criteria or empty list of criterias, then throw an error if (criteria === undefined || @@ -638,7 +514,7 @@ export class EntityManager { * Does not check if entity exist in the database. * Condition(s) cannot be empty. */ - delete(targetOrEntity: ObjectType|EntitySchema|string, criteria: string|string[]|number|number[]|Date|Date[]|ObjectID|ObjectID[]|any): Promise { + delete(targetOrEntity: EntityTarget, criteria: string|string[]|number|number[]|Date|Date[]|ObjectID|ObjectID[]|any): Promise { // if user passed empty criteria or empty list of criterias, then throw an error if (criteria === undefined || @@ -676,7 +552,7 @@ export class EntityManager { * Does not check if entity exist in the database. * Condition(s) cannot be empty. */ - softDelete(targetOrEntity: ObjectType|EntitySchema|string, criteria: string|string[]|number|number[]|Date|Date[]|ObjectID|ObjectID[]|any): Promise { + softDelete(targetOrEntity: EntityTarget, criteria: string|string[]|number|number[]|Date|Date[]|ObjectID|ObjectID[]|any): Promise { // if user passed empty criteria or empty list of criterias, then throw an error if (criteria === undefined || @@ -714,7 +590,7 @@ export class EntityManager { * Does not check if entity exist in the database. * Condition(s) cannot be empty. */ - restore(targetOrEntity: ObjectType|EntitySchema|string, criteria: string|string[]|number|number[]|Date|Date[]|ObjectID|ObjectID[]|any): Promise { + restore(targetOrEntity: EntityTarget, criteria: string|string[]|number|number[]|Date|Date[]|ObjectID|ObjectID[]|any): Promise { // if user passed empty criteria or empty list of criterias, then throw an error if (criteria === undefined || @@ -746,85 +622,47 @@ export class EntityManager { } /** - * Counts entities that match given options. + * Counts entities that match given conditions. * Useful for pagination. */ - count(entityClass: ObjectType, options?: FindOneOptions): Promise; + count(entityClass: EntityTarget, conditions?: FindConditions): Promise; /** * Counts entities that match given options. * Useful for pagination. */ - count(entityClass: EntitySchema, options?: FindOneOptions): Promise; + count(entityClass: EntityTarget, options?: FindOneOptions): Promise; /** * Counts entities that match given options. * Useful for pagination. */ - count(entityClass: string, options?: FindOneOptions): Promise; - - /** - * Counts entities that match given conditions. - * Useful for pagination. - */ - count(entityClass: ObjectType, conditions?: FindConditions): Promise; - - /** - * Counts entities that match given conditions. - * Useful for pagination. - */ - count(entityClass: EntitySchema, conditions?: FindConditions): Promise; - - /** - * Counts entities that match given conditions. - * Useful for pagination. - */ - count(entityClass: string, conditions?: FindConditions): Promise; + count(entityClass: EntityTarget, options?: FindManyOptions): Promise; /** * Counts entities that match given find options or conditions. * Useful for pagination. */ - async count(entityClass: ObjectType|EntitySchema|string, optionsOrConditions?: FindManyOptions|any): Promise { + async count(entityClass: EntityTarget, optionsOrConditions?: FindConditions|FindOneOptions|FindManyOptions): Promise { const metadata = this.connection.getMetadata(entityClass); - const qb = this.createQueryBuilder(entityClass as any, FindOptionsUtils.extractFindManyOptionsAlias(optionsOrConditions) || metadata.name); + const qb = this.createQueryBuilder(entityClass, FindOptionsUtils.extractFindManyOptionsAlias(optionsOrConditions) || metadata.name); return FindOptionsUtils.applyFindManyOptionsOrConditionsToQueryBuilder(qb, optionsOrConditions).getCount(); } - /** - * Finds entities that match given options. - */ - find(entityClass: ObjectType, options?: FindManyOptions): Promise; - /** * Finds entities that match given conditions. */ - find(entityClass: ObjectType, conditions?: FindConditions): Promise; + find(entityClass: EntityTarget, conditions?: FindConditions): Promise; /** * Finds entities that match given options. */ - find(entitySchema: EntitySchema, options?: FindManyOptions): Promise; - - /** - * Finds entities that match given conditions. - */ - find(entitySchema: EntitySchema, conditions?: FindConditions): Promise; - - /** - * Finds entities that match given conditions. - */ - find(entityClass: string, options?: FindManyOptions): Promise; - - /** - * Finds entities that match given conditions. - */ - find(entityClass: string, conditions?: FindConditions): Promise; + find(entityClass: EntityTarget, options?: FindManyOptions): Promise; /** * Finds entities that match given find options or conditions. */ - async find(entityClass: ObjectType|EntitySchema|string, optionsOrConditions?: FindManyOptions|any): Promise { + async find(entityClass: EntityTarget, optionsOrConditions?: FindManyOptions|FindConditions): Promise { const metadata = this.connection.getMetadata(entityClass); const qb = this.createQueryBuilder(entityClass as any, FindOptionsUtils.extractFindManyOptionsAlias(optionsOrConditions) || metadata.name); @@ -834,54 +672,26 @@ export class EntityManager { return FindOptionsUtils.applyFindManyOptionsOrConditionsToQueryBuilder(qb, optionsOrConditions).getMany(); } - /** - * Finds entities that match given find options. - * Also counts all entities that match given conditions, - * but ignores pagination settings (from and take options). - */ - findAndCount(entityClass: ObjectType, options?: FindManyOptions): Promise<[Entity[], number]>; - - /** - * Finds entities that match given find options. - * Also counts all entities that match given conditions, - * but ignores pagination settings (from and take options). - */ - findAndCount(entityClass: EntitySchema, options?: FindManyOptions): Promise<[Entity[], number]>; - - /** - * Finds entities that match given find options. - * Also counts all entities that match given conditions, - * but ignores pagination settings (from and take options). - */ - findAndCount(entityClass: string, options?: FindManyOptions): Promise<[Entity[], number]>; - - /** - * Finds entities that match given conditions. - * Also counts all entities that match given conditions, - * but ignores pagination settings (from and take options). - */ - findAndCount(entityClass: ObjectType, conditions?: FindConditions): Promise<[Entity[], number]>; - /** * Finds entities that match given conditions. * Also counts all entities that match given conditions, * but ignores pagination settings (from and take options). */ - findAndCount(entityClass: EntitySchema, conditions?: FindConditions): Promise<[Entity[], number]>; + findAndCount(entityClass: EntityTarget, conditions?: FindConditions): Promise<[Entity[], number]>; /** - * Finds entities that match given conditions. + * Finds entities that match given find options. * Also counts all entities that match given conditions, * but ignores pagination settings (from and take options). */ - findAndCount(entityClass: string, conditions?: FindConditions): Promise<[Entity[], number]>; + findAndCount(entityClass: EntityTarget, options?: FindManyOptions): Promise<[Entity[], number]>; /** * Finds entities that match given find options and conditions. * Also counts all entities that match given conditions, * but ignores pagination settings (from and take options). */ - async findAndCount(entityClass: ObjectType|EntitySchema|string, optionsOrConditions?: FindManyOptions|any): Promise<[Entity[], number]> { + async findAndCount(entityClass: EntityTarget, optionsOrConditions?: FindConditions|FindManyOptions): Promise<[Entity[], number]> { const metadata = this.connection.getMetadata(entityClass); const qb = this.createQueryBuilder(entityClass as any, FindOptionsUtils.extractFindManyOptionsAlias(optionsOrConditions) || metadata.name); @@ -891,47 +701,23 @@ export class EntityManager { return FindOptionsUtils.applyFindManyOptionsOrConditionsToQueryBuilder(qb, optionsOrConditions).getManyAndCount(); } - /** - * Finds entities with ids. - * Optionally find options can be applied. - */ - findByIds(entityClass: ObjectType, ids: any[], options?: FindManyOptions): Promise; - - /** - * Finds entities with ids. - * Optionally find options can be applied. - */ - findByIds(entityClass: EntitySchema, ids: any[], options?: FindManyOptions): Promise; - - /** - * Finds entities with ids. - * Optionally find options can be applied. - */ - findByIds(entityClass: string, ids: any[], options?: FindManyOptions): Promise; - - /** - * Finds entities with ids. - * Optionally conditions can be applied. - */ - findByIds(entityClass: ObjectType, ids: any[], conditions?: FindConditions): Promise; - /** * Finds entities with ids. * Optionally conditions can be applied. */ - findByIds(entityClass: EntitySchema, ids: any[], conditions?: FindConditions): Promise; + findByIds(entityClass: EntityTarget, ids: any[], conditions?: FindConditions): Promise; /** * Finds entities with ids. - * Optionally conditions can be applied. + * Optionally find options can be applied. */ - findByIds(entityClass: string, ids: any[], conditions?: FindConditions): Promise; + findByIds(entityClass: EntityTarget, ids: any[], options?: FindManyOptions): Promise; /** * Finds entities with ids. * Optionally find options or conditions can be applied. */ - async findByIds(entityClass: ObjectType|EntitySchema|string, ids: any[], optionsOrConditions?: FindManyOptions|any): Promise { + async findByIds(entityClass: EntityTarget, ids: any[], optionsOrConditions?: FindConditions|FindManyOptions): Promise { // if no ids passed, no need to execute a query - just return an empty array of values if (!ids.length) @@ -949,52 +735,22 @@ export class EntityManager { /** * Finds first entity that matches given find options. */ - findOne(entityClass: ObjectType, id?: string|number|Date|ObjectID, options?: FindOneOptions): Promise; + findOne(entityClass: EntityTarget, id?: string|number|Date|ObjectID, options?: FindOneOptions): Promise; /** * Finds first entity that matches given find options. */ - findOne(entityClass: EntitySchema, id?: string|number|Date|ObjectID, options?: FindOneOptions): Promise; - - /** - * Finds first entity that matches given find options. - */ - findOne(entityClass: string, id?: string|number|Date|ObjectID, options?: FindOneOptions): Promise; - - /** - * Finds first entity that matches given find options. - */ - findOne(entityClass: ObjectType, options?: FindOneOptions): Promise; - - /** - * Finds first entity that matches given find options. - */ - findOne(entityClass: EntitySchema, options?: FindOneOptions): Promise; - - /** - * Finds first entity that matches given find options. - */ - findOne(entityClass: string, options?: FindOneOptions): Promise; - - /** - * Finds first entity that matches given conditions. - */ - findOne(entityClass: ObjectType, conditions?: FindConditions, options?: FindOneOptions): Promise; - - /** - * Finds first entity that matches given conditions. - */ - findOne(entityClass: EntitySchema, conditions?: FindConditions, options?: FindOneOptions): Promise; + findOne(entityClass: EntityTarget, options?: FindOneOptions): Promise; /** * Finds first entity that matches given conditions. */ - findOne(entityClass: string, conditions?: FindConditions, options?: FindOneOptions): Promise; + findOne(entityClass: EntityTarget, conditions?: FindConditions, options?: FindOneOptions): Promise; /** * Finds first entity that matches given conditions. */ - async findOne(entityClass: ObjectType|EntitySchema|string, idOrOptionsOrConditions?: string|string[]|number|number[]|Date|Date[]|ObjectID|ObjectID[]|FindOneOptions|any, maybeOptions?: FindOneOptions): Promise { + async findOne(entityClass: EntityTarget, idOrOptionsOrConditions?: string|string[]|number|number[]|Date|Date[]|ObjectID|ObjectID[]|FindOneOptions|FindConditions, maybeOptions?: FindOneOptions): Promise { let findOptions: FindManyOptions|FindOneOptions|undefined = undefined; if (FindOptionsUtils.isFindOneOptions(idOrOptionsOrConditions)) { @@ -1044,52 +800,22 @@ export class EntityManager { /** * Finds first entity that matches given find options or rejects the returned promise on error. */ - findOneOrFail(entityClass: ObjectType, id?: string|number|Date|ObjectID, options?: FindOneOptions): Promise; + findOneOrFail(entityClass: EntityTarget, id?: string|number|Date|ObjectID, options?: FindOneOptions): Promise; /** * Finds first entity that matches given find options or rejects the returned promise on error. */ - findOneOrFail(entityClass: EntitySchema, id?: string|number|Date|ObjectID, options?: FindOneOptions): Promise; - - /** - * Finds first entity that matches given find options or rejects the returned promise on error. - */ - findOneOrFail(entityClass: string, id?: string|number|Date|ObjectID, options?: FindOneOptions): Promise; - - /** - * Finds first entity that matches given find options or rejects the returned promise on error. - */ - findOneOrFail(entityClass: ObjectType, options?: FindOneOptions): Promise; - - /** - * Finds first entity that matches given find options or rejects the returned promise on error. - */ - findOneOrFail(entityClass: EntitySchema, options?: FindOneOptions): Promise; - - /** - * Finds first entity that matches given find options or rejects the returned promise on error. - */ - findOneOrFail(entityClass: string, options?: FindOneOptions): Promise; - - /** - * Finds first entity that matches given conditions or rejects the returned promise on error. - */ - findOneOrFail(entityClass: ObjectType, conditions?: FindConditions, options?: FindOneOptions): Promise; - - /** - * Finds first entity that matches given conditions or rejects the returned promise on error. - */ - findOneOrFail(entityClass: EntitySchema, conditions?: FindConditions, options?: FindOneOptions): Promise; + findOneOrFail(entityClass: EntityTarget, options?: FindOneOptions): Promise; /** * Finds first entity that matches given conditions or rejects the returned promise on error. */ - findOneOrFail(entityClass: string, conditions?: FindConditions, options?: FindOneOptions): Promise; + findOneOrFail(entityClass: EntityTarget, conditions?: FindConditions, options?: FindOneOptions): Promise; /** * Finds first entity that matches given conditions or rejects the returned promise on error. */ - async findOneOrFail(entityClass: ObjectType|EntitySchema|string, idOrOptionsOrConditions?: string|string[]|number|number[]|Date|Date[]|ObjectID|ObjectID[]|FindOneOptions|any, maybeOptions?: FindOneOptions): Promise { + async findOneOrFail(entityClass: EntityTarget, idOrOptionsOrConditions?: string|string[]|number|number[]|Date|Date[]|ObjectID|ObjectID[]|FindOneOptions|FindConditions, maybeOptions?: FindOneOptions): Promise { return this.findOne(entityClass as any, idOrOptionsOrConditions as any, maybeOptions).then((value) => { if (value === undefined) { return Promise.reject(new EntityNotFoundError(entityClass, idOrOptionsOrConditions)); @@ -1104,7 +830,7 @@ export class EntityManager { * Note: this method uses TRUNCATE and may not work as you expect in transactions on some platforms. * @see https://stackoverflow.com/a/5972738/925151 */ - async clear(entityClass: ObjectType|EntitySchema|string): Promise { + async clear(entityClass: EntityTarget): Promise { const metadata = this.connection.getMetadata(entityClass); const queryRunner = this.queryRunner || this.connection.createQueryRunner("master"); try { @@ -1119,7 +845,7 @@ export class EntityManager { /** * Increments some column by provided value of the entities matched given conditions. */ - async increment(entityClass: ObjectType|EntitySchema|string, + async increment(entityClass: EntityTarget, conditions: any, propertyPath: string, value: number | string): Promise { @@ -1151,7 +877,7 @@ export class EntityManager { /** * Decrements some column by provided value of the entities matched given conditions. */ - async decrement(entityClass: ObjectType|EntitySchema|string, + async decrement(entityClass: EntityTarget, conditions: any, propertyPath: string, value: number | string): Promise { @@ -1186,7 +912,7 @@ export class EntityManager { * repository aggregator, where each repository is individually created for this entity manager. * When single database connection is not used, repository is being obtained from the connection. */ - getRepository(target: ObjectType|EntitySchema|string): Repository { + getRepository(target: EntityTarget): Repository { // throw exception if there is no repository with this target registered if (!this.connection.hasMetadata(target)) @@ -1210,7 +936,7 @@ export class EntityManager { * repository aggregator, where each repository is individually created for this entity manager. * When single database connection is not used, repository is being obtained from the connection. */ - getTreeRepository(target: ObjectType|EntitySchema|string): TreeRepository { + getTreeRepository(target: EntityTarget): TreeRepository { // tree tables aren't supported by some drivers (mongodb) if (this.connection.driver.treeSupport === false) @@ -1227,7 +953,7 @@ export class EntityManager { /** * Gets mongodb repository for the given entity class. */ - getMongoRepository(target: ObjectType|EntitySchema|string): MongoRepository { + getMongoRepository(target: EntityTarget): MongoRepository { return this.connection.getMongoRepository(target); } diff --git a/src/entity-manager/MongoEntityManager.ts b/src/entity-manager/MongoEntityManager.ts index 346cf1eee4..1a5ce45199 100644 --- a/src/entity-manager/MongoEntityManager.ts +++ b/src/entity-manager/MongoEntityManager.ts @@ -1,6 +1,6 @@ import { Connection } from "../connection/Connection"; import { EntityManager } from "./EntityManager"; -import { ObjectType } from "../common/ObjectType"; +import { EntityTarget } from "../common/EntityTarget"; import { AggregationCursor, BulkWriteOpResultObject, @@ -51,7 +51,7 @@ import { InsertResult } from "../query-builder/result/InsertResult"; import { UpdateResult } from "../query-builder/result/UpdateResult"; import { DeleteResult } from "../query-builder/result/DeleteResult"; import { EntityMetadata } from "../metadata/EntityMetadata"; -import { EntitySchema, FindConditions } from "../index"; +import { FindConditions } from "../index"; import { BroadcasterResult } from "../subscriber/BroadcasterResult"; /** @@ -88,7 +88,7 @@ export class MongoEntityManager extends EntityManager { /** * Finds entities that match given find options or conditions. */ - async find(entityClassOrName: ObjectType | EntitySchema | string, optionsOrConditions?: FindManyOptions | Partial): Promise { + async find(entityClassOrName: EntityTarget, optionsOrConditions?: FindManyOptions | Partial): Promise { const query = this.convertFindManyOptionsOrConditionsToMongodbQuery(optionsOrConditions); const cursor = await this.createEntityCursor(entityClassOrName, query); if (FindOptionsUtils.isFindManyOptions(optionsOrConditions)) { @@ -109,7 +109,7 @@ export class MongoEntityManager extends EntityManager { * Also counts all entities that match given conditions, * but ignores pagination settings (from and take options). */ - async findAndCount(entityClassOrName: ObjectType | EntitySchema | string, optionsOrConditions?: FindManyOptions | Partial): Promise<[Entity[], number]> { + async findAndCount(entityClassOrName: EntityTarget, optionsOrConditions?: FindManyOptions | Partial): Promise<[Entity[], number]> { const query = this.convertFindManyOptionsOrConditionsToMongodbQuery(optionsOrConditions); const cursor = await this.createEntityCursor(entityClassOrName, query); if (FindOptionsUtils.isFindManyOptions(optionsOrConditions)) { @@ -134,7 +134,7 @@ export class MongoEntityManager extends EntityManager { * Finds entities by ids. * Optionally find options can be applied. */ - async findByIds(entityClassOrName: ObjectType | EntitySchema | string, ids: any[], optionsOrConditions?: FindManyOptions | Partial): Promise { + async findByIds(entityClassOrName: EntityTarget, ids: any[], optionsOrConditions?: FindManyOptions | Partial): Promise { const metadata = this.connection.getMetadata(entityClassOrName); const query = this.convertFindManyOptionsOrConditionsToMongodbQuery(optionsOrConditions) || {}; const objectIdInstance = PlatformTools.load("mongodb").ObjectID; @@ -164,7 +164,7 @@ export class MongoEntityManager extends EntityManager { /** * Finds first entity that matches given conditions and/or find options. */ - async findOne(entityClassOrName: ObjectType | EntitySchema | string, + async findOne(entityClassOrName: EntityTarget, optionsOrConditions?: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindOneOptions | DeepPartial, maybeOptions?: FindOneOptions): Promise { const objectIdInstance = PlatformTools.load("mongodb").ObjectID; @@ -194,7 +194,7 @@ export class MongoEntityManager extends EntityManager { * Does not check if entity exist in the database, so query will fail if duplicate entity is being inserted. * You can execute bulk inserts using this method. */ - async insert(target: ObjectType | EntitySchema | string, entity: QueryDeepPartialEntity | QueryDeepPartialEntity[]): Promise { + async insert(target: EntityTarget, entity: QueryDeepPartialEntity | QueryDeepPartialEntity[]): Promise { // todo: convert entity to its database name const result = new InsertResult(); if (Array.isArray(entity)) { @@ -220,7 +220,7 @@ export class MongoEntityManager extends EntityManager { * Executes fast and efficient UPDATE query. * Does not check if entity exist in the database. */ - async update(target: ObjectType | EntitySchema | string, criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindConditions, partialEntity: QueryDeepPartialEntity): Promise { + async update(target: EntityTarget, criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindConditions, partialEntity: QueryDeepPartialEntity): Promise { if (Array.isArray(criteria)) { await Promise.all((criteria as any[]).map(criteriaItem => { return this.update(target, criteriaItem, partialEntity); @@ -240,7 +240,7 @@ export class MongoEntityManager extends EntityManager { * Executes fast and efficient DELETE query. * Does not check if entity exist in the database. */ - async delete(target: ObjectType | EntitySchema | string, criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindConditions): Promise { + async delete(target: EntityTarget, criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindConditions): Promise { if (Array.isArray(criteria)) { await Promise.all((criteria as any[]).map(criteriaItem => { return this.delete(target, criteriaItem); @@ -260,7 +260,7 @@ export class MongoEntityManager extends EntityManager { /** * Creates a cursor for a query that can be used to iterate over results from MongoDB. */ - createCursor(entityClassOrName: ObjectType | EntitySchema | string, query?: ObjectLiteral): Cursor { + createCursor(entityClassOrName: EntityTarget, query?: ObjectLiteral): Cursor { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.cursor(metadata.tableName, query); } @@ -269,7 +269,7 @@ export class MongoEntityManager extends EntityManager { * Creates a cursor for a query that can be used to iterate over results from MongoDB. * This returns modified version of cursor that transforms each result into Entity model. */ - createEntityCursor(entityClassOrName: ObjectType | EntitySchema | string, query?: ObjectLiteral): Cursor { + createEntityCursor(entityClassOrName: EntityTarget, query?: ObjectLiteral): Cursor { const metadata = this.connection.getMetadata(entityClassOrName); const cursor = this.createCursor(entityClassOrName, query); this.applyEntityTransformationToCursor(metadata, cursor); @@ -279,7 +279,7 @@ export class MongoEntityManager extends EntityManager { /** * Execute an aggregation framework pipeline against the collection. */ - aggregate(entityClassOrName: ObjectType | EntitySchema | string, pipeline: ObjectLiteral[], options?: CollectionAggregationOptions): AggregationCursor { + aggregate(entityClassOrName: EntityTarget, pipeline: ObjectLiteral[], options?: CollectionAggregationOptions): AggregationCursor { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.aggregate(metadata.tableName, pipeline, options); } @@ -288,7 +288,7 @@ export class MongoEntityManager extends EntityManager { * Execute an aggregation framework pipeline against the collection. * This returns modified version of cursor that transforms each result into Entity model. */ - aggregateEntity(entityClassOrName: ObjectType | EntitySchema | string, pipeline: ObjectLiteral[], options?: CollectionAggregationOptions): AggregationCursor { + aggregateEntity(entityClassOrName: EntityTarget, pipeline: ObjectLiteral[], options?: CollectionAggregationOptions): AggregationCursor { const metadata = this.connection.getMetadata(entityClassOrName); const cursor = this.queryRunner.aggregate(metadata.tableName, pipeline, options); this.applyEntityTransformationToCursor(metadata, cursor); @@ -298,7 +298,7 @@ export class MongoEntityManager extends EntityManager { /** * Perform a bulkWrite operation without a fluent API. */ - bulkWrite(entityClassOrName: ObjectType | EntitySchema | string, operations: ObjectLiteral[], options?: CollectionBulkWriteOptions): Promise { + bulkWrite(entityClassOrName: EntityTarget, operations: ObjectLiteral[], options?: CollectionBulkWriteOptions): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.bulkWrite(metadata.tableName, operations, options); } @@ -306,7 +306,7 @@ export class MongoEntityManager extends EntityManager { /** * Count number of matching documents in the db to a query. */ - count(entityClassOrName: ObjectType | EntitySchema | string, query?: ObjectLiteral, options?: MongoCountPreferences): Promise { + count(entityClassOrName: EntityTarget, query?: ObjectLiteral, options?: MongoCountPreferences): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.count(metadata.tableName, query, options); } @@ -314,7 +314,7 @@ export class MongoEntityManager extends EntityManager { /** * Creates an index on the db and collection. */ - createCollectionIndex(entityClassOrName: ObjectType | EntitySchema | string, fieldOrSpec: string | any, options?: MongodbIndexOptions): Promise { + createCollectionIndex(entityClassOrName: EntityTarget, fieldOrSpec: string | any, options?: MongodbIndexOptions): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.createCollectionIndex(metadata.tableName, fieldOrSpec, options); } @@ -324,7 +324,7 @@ export class MongoEntityManager extends EntityManager { * Earlier version of MongoDB will throw a command not supported error. * Index specifications are defined at http://docs.mongodb.org/manual/reference/command/createIndexes/. */ - createCollectionIndexes(entityClassOrName: ObjectType | EntitySchema | string, indexSpecs: ObjectLiteral[]): Promise { + createCollectionIndexes(entityClassOrName: EntityTarget, indexSpecs: ObjectLiteral[]): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.createCollectionIndexes(metadata.tableName, indexSpecs); } @@ -332,7 +332,7 @@ export class MongoEntityManager extends EntityManager { /** * Delete multiple documents on MongoDB. */ - deleteMany(entityClassOrName: ObjectType | EntitySchema | string, query: ObjectLiteral, options?: CollectionOptions): Promise { + deleteMany(entityClassOrName: EntityTarget, query: ObjectLiteral, options?: CollectionOptions): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.deleteMany(metadata.tableName, query, options); } @@ -340,7 +340,7 @@ export class MongoEntityManager extends EntityManager { /** * Delete a document on MongoDB. */ - deleteOne(entityClassOrName: ObjectType | EntitySchema | string, query: ObjectLiteral, options?: CollectionOptions): Promise { + deleteOne(entityClassOrName: EntityTarget, query: ObjectLiteral, options?: CollectionOptions): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.deleteOne(metadata.tableName, query, options); } @@ -348,7 +348,7 @@ export class MongoEntityManager extends EntityManager { /** * The distinct command returns returns a list of distinct values for the given key across a collection. */ - distinct(entityClassOrName: ObjectType | EntitySchema | string, key: string, query: ObjectLiteral, options?: { readPreference?: ReadPreference | string }): Promise { + distinct(entityClassOrName: EntityTarget, key: string, query: ObjectLiteral, options?: { readPreference?: ReadPreference | string }): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.distinct(metadata.tableName, key, query, options); } @@ -356,7 +356,7 @@ export class MongoEntityManager extends EntityManager { /** * Drops an index from this collection. */ - dropCollectionIndex(entityClassOrName: ObjectType | EntitySchema | string, indexName: string, options?: CollectionOptions): Promise { + dropCollectionIndex(entityClassOrName: EntityTarget, indexName: string, options?: CollectionOptions): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.dropCollectionIndex(metadata.tableName, indexName, options); } @@ -364,7 +364,7 @@ export class MongoEntityManager extends EntityManager { /** * Drops all indexes from the collection. */ - dropCollectionIndexes(entityClassOrName: ObjectType | EntitySchema | string): Promise { + dropCollectionIndexes(entityClassOrName: EntityTarget): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.dropCollectionIndexes(metadata.tableName); } @@ -372,7 +372,7 @@ export class MongoEntityManager extends EntityManager { /** * Find a document and delete it in one atomic operation, requires a write lock for the duration of the operation. */ - findOneAndDelete(entityClassOrName: ObjectType | EntitySchema | string, query: ObjectLiteral, options?: { projection?: Object, sort?: Object, maxTimeMS?: number }): Promise { + findOneAndDelete(entityClassOrName: EntityTarget, query: ObjectLiteral, options?: { projection?: Object, sort?: Object, maxTimeMS?: number }): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.findOneAndDelete(metadata.tableName, query, options); } @@ -380,7 +380,7 @@ export class MongoEntityManager extends EntityManager { /** * Find a document and replace it in one atomic operation, requires a write lock for the duration of the operation. */ - findOneAndReplace(entityClassOrName: ObjectType | EntitySchema | string, query: ObjectLiteral, replacement: Object, options?: FindOneAndReplaceOption): Promise { + findOneAndReplace(entityClassOrName: EntityTarget, query: ObjectLiteral, replacement: Object, options?: FindOneAndReplaceOption): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.findOneAndReplace(metadata.tableName, query, replacement, options); } @@ -388,7 +388,7 @@ export class MongoEntityManager extends EntityManager { /** * Find a document and update it in one atomic operation, requires a write lock for the duration of the operation. */ - findOneAndUpdate(entityClassOrName: ObjectType | EntitySchema | string, query: ObjectLiteral, update: Object, options?: FindOneAndReplaceOption): Promise { + findOneAndUpdate(entityClassOrName: EntityTarget, query: ObjectLiteral, update: Object, options?: FindOneAndReplaceOption): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.findOneAndUpdate(metadata.tableName, query, update, options); } @@ -396,7 +396,7 @@ export class MongoEntityManager extends EntityManager { /** * Execute a geo search using a geo haystack index on a collection. */ - geoHaystackSearch(entityClassOrName: ObjectType | EntitySchema | string, x: number, y: number, options?: GeoHaystackSearchOptions): Promise { + geoHaystackSearch(entityClassOrName: EntityTarget, x: number, y: number, options?: GeoHaystackSearchOptions): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.geoHaystackSearch(metadata.tableName, x, y, options); } @@ -404,7 +404,7 @@ export class MongoEntityManager extends EntityManager { /** * Execute the geoNear command to search for items in the collection. */ - geoNear(entityClassOrName: ObjectType | EntitySchema | string, x: number, y: number, options?: GeoNearOptions): Promise { + geoNear(entityClassOrName: EntityTarget, x: number, y: number, options?: GeoNearOptions): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.geoNear(metadata.tableName, x, y, options); } @@ -412,7 +412,7 @@ export class MongoEntityManager extends EntityManager { /** * Run a group command across a collection. */ - group(entityClassOrName: ObjectType | EntitySchema | string, keys: Object | Array | Function | Code, condition: Object, initial: Object, reduce: Function | Code, finalize: Function | Code, command: boolean, options?: { readPreference?: ReadPreference | string }): Promise { + group(entityClassOrName: EntityTarget, keys: Object | Array | Function | Code, condition: Object, initial: Object, reduce: Function | Code, finalize: Function | Code, command: boolean, options?: { readPreference?: ReadPreference | string }): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.group(metadata.tableName, keys, condition, initial, reduce, finalize, command, options); } @@ -420,7 +420,7 @@ export class MongoEntityManager extends EntityManager { /** * Retrieve all the indexes on the collection. */ - collectionIndexes(entityClassOrName: ObjectType | EntitySchema | string): Promise { + collectionIndexes(entityClassOrName: EntityTarget): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.collectionIndexes(metadata.tableName); } @@ -428,7 +428,7 @@ export class MongoEntityManager extends EntityManager { /** * Retrieve all the indexes on the collection. */ - collectionIndexExists(entityClassOrName: ObjectType | EntitySchema | string, indexes: string | string[]): Promise { + collectionIndexExists(entityClassOrName: EntityTarget, indexes: string | string[]): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.collectionIndexExists(metadata.tableName, indexes); } @@ -436,7 +436,7 @@ export class MongoEntityManager extends EntityManager { /** * Retrieves this collections index info. */ - collectionIndexInformation(entityClassOrName: ObjectType | EntitySchema | string, options?: { full: boolean }): Promise { + collectionIndexInformation(entityClassOrName: EntityTarget, options?: { full: boolean }): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.collectionIndexInformation(metadata.tableName, options); } @@ -444,7 +444,7 @@ export class MongoEntityManager extends EntityManager { /** * Initiate an In order bulk write operation, operations will be serially executed in the order they are added, creating a new operation for each switch in types. */ - initializeOrderedBulkOp(entityClassOrName: ObjectType | EntitySchema | string, options?: CollectionOptions): OrderedBulkOperation { + initializeOrderedBulkOp(entityClassOrName: EntityTarget, options?: CollectionOptions): OrderedBulkOperation { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.initializeOrderedBulkOp(metadata.tableName, options); } @@ -452,7 +452,7 @@ export class MongoEntityManager extends EntityManager { /** * Initiate a Out of order batch write operation. All operations will be buffered into insert/update/remove commands executed out of order. */ - initializeUnorderedBulkOp(entityClassOrName: ObjectType | EntitySchema | string, options?: CollectionOptions): UnorderedBulkOperation { + initializeUnorderedBulkOp(entityClassOrName: EntityTarget, options?: CollectionOptions): UnorderedBulkOperation { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.initializeUnorderedBulkOp(metadata.tableName, options); } @@ -460,7 +460,7 @@ export class MongoEntityManager extends EntityManager { /** * Inserts an array of documents into MongoDB. */ - insertMany(entityClassOrName: ObjectType | EntitySchema | string, docs: ObjectLiteral[], options?: CollectionInsertManyOptions): Promise { + insertMany(entityClassOrName: EntityTarget, docs: ObjectLiteral[], options?: CollectionInsertManyOptions): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.insertMany(metadata.tableName, docs, options); } @@ -468,7 +468,7 @@ export class MongoEntityManager extends EntityManager { /** * Inserts a single document into MongoDB. */ - insertOne(entityClassOrName: ObjectType | EntitySchema | string, doc: ObjectLiteral, options?: CollectionInsertOneOptions): Promise { + insertOne(entityClassOrName: EntityTarget, doc: ObjectLiteral, options?: CollectionInsertOneOptions): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.insertOne(metadata.tableName, doc, options); } @@ -476,7 +476,7 @@ export class MongoEntityManager extends EntityManager { /** * Returns if the collection is a capped collection. */ - isCapped(entityClassOrName: ObjectType | EntitySchema | string): Promise { + isCapped(entityClassOrName: EntityTarget): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.isCapped(metadata.tableName); } @@ -484,7 +484,7 @@ export class MongoEntityManager extends EntityManager { /** * Get the list of all indexes information for the collection. */ - listCollectionIndexes(entityClassOrName: ObjectType | EntitySchema | string, options?: { batchSize?: number, readPreference?: ReadPreference | string }): CommandCursor { + listCollectionIndexes(entityClassOrName: EntityTarget, options?: { batchSize?: number, readPreference?: ReadPreference | string }): CommandCursor { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.listCollectionIndexes(metadata.tableName, options); } @@ -492,7 +492,7 @@ export class MongoEntityManager extends EntityManager { /** * Run Map Reduce across a collection. Be aware that the inline option for out will return an array of results not a collection. */ - mapReduce(entityClassOrName: ObjectType | EntitySchema | string, map: Function | string, reduce: Function | string, options?: MapReduceOptions): Promise { + mapReduce(entityClassOrName: EntityTarget, map: Function | string, reduce: Function | string, options?: MapReduceOptions): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.mapReduce(metadata.tableName, map, reduce, options); } @@ -501,7 +501,7 @@ export class MongoEntityManager extends EntityManager { * Return N number of parallel cursors for a collection allowing parallel reading of entire collection. * There are no ordering guarantees for returned results. */ - parallelCollectionScan(entityClassOrName: ObjectType | EntitySchema | string, options?: ParallelCollectionScanOptions): Promise[]> { + parallelCollectionScan(entityClassOrName: EntityTarget, options?: ParallelCollectionScanOptions): Promise[]> { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.parallelCollectionScan(metadata.tableName, options); } @@ -509,7 +509,7 @@ export class MongoEntityManager extends EntityManager { /** * Reindex all indexes on the collection Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections. */ - reIndex(entityClassOrName: ObjectType | EntitySchema | string): Promise { + reIndex(entityClassOrName: EntityTarget): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.reIndex(metadata.tableName); } @@ -517,7 +517,7 @@ export class MongoEntityManager extends EntityManager { /** * Reindex all indexes on the collection Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections. */ - rename(entityClassOrName: ObjectType | EntitySchema | string, newName: string, options?: { dropTarget?: boolean }): Promise> { + rename(entityClassOrName: EntityTarget, newName: string, options?: { dropTarget?: boolean }): Promise> { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.rename(metadata.tableName, newName, options); } @@ -525,7 +525,7 @@ export class MongoEntityManager extends EntityManager { /** * Replace a document on MongoDB. */ - replaceOne(entityClassOrName: ObjectType | EntitySchema | string, query: ObjectLiteral, doc: ObjectLiteral, options?: ReplaceOneOptions): Promise { + replaceOne(entityClassOrName: EntityTarget, query: ObjectLiteral, doc: ObjectLiteral, options?: ReplaceOneOptions): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.replaceOne(metadata.tableName, query, doc, options); } @@ -533,12 +533,12 @@ export class MongoEntityManager extends EntityManager { /** * Get all the collection statistics. */ - stats(entityClassOrName: ObjectType | EntitySchema | string, options?: { scale: number }): Promise { + stats(entityClassOrName: EntityTarget, options?: { scale: number }): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.stats(metadata.tableName, options); } - watch(entityClassOrName: ObjectType | EntitySchema | string, pipeline?: Object[], options?: ChangeStreamOptions): ChangeStream { + watch(entityClassOrName: EntityTarget, pipeline?: Object[], options?: ChangeStreamOptions): ChangeStream { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.watch(metadata.tableName, pipeline, options); } @@ -546,7 +546,7 @@ export class MongoEntityManager extends EntityManager { /** * Update multiple documents on MongoDB. */ - updateMany(entityClassOrName: ObjectType | EntitySchema | string, query: ObjectLiteral, update: ObjectLiteral, options?: { upsert?: boolean, w?: any, wtimeout?: number, j?: boolean }): Promise { + updateMany(entityClassOrName: EntityTarget, query: ObjectLiteral, update: ObjectLiteral, options?: { upsert?: boolean, w?: any, wtimeout?: number, j?: boolean }): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.updateMany(metadata.tableName, query, update, options); } @@ -554,7 +554,7 @@ export class MongoEntityManager extends EntityManager { /** * Update a single document on MongoDB. */ - updateOne(entityClassOrName: ObjectType | EntitySchema | string, query: ObjectLiteral, update: ObjectLiteral, options?: ReplaceOneOptions): Promise { + updateOne(entityClassOrName: EntityTarget, query: ObjectLiteral, update: ObjectLiteral, options?: ReplaceOneOptions): Promise { const metadata = this.connection.getMetadata(entityClassOrName); return this.queryRunner.updateOne(metadata.tableName, query, update, options); } diff --git a/src/error/EntityMetadataNotFoundError.ts b/src/error/EntityMetadataNotFoundError.ts index 3365617f86..ecb43fd7cf 100644 --- a/src/error/EntityMetadataNotFoundError.ts +++ b/src/error/EntityMetadataNotFoundError.ts @@ -1,3 +1,4 @@ +import {EntityTarget} from "../common/EntityTarget"; import {EntitySchema} from "../index"; /** @@ -5,7 +6,7 @@ import {EntitySchema} from "../index"; export class EntityMetadataNotFoundError extends Error { name = "EntityMetadataNotFound"; - constructor(target: Function|EntitySchema|string) { + constructor(target: EntityTarget) { super(); Object.setPrototypeOf(this, EntityMetadataNotFoundError.prototype); let targetName: string; @@ -13,10 +14,12 @@ export class EntityMetadataNotFoundError extends Error { targetName = target.options.name; } else if (typeof target === "function") { targetName = target.name; + } else if (typeof target === "object" && "name" in target) { + targetName = target.name; } else { targetName = target; } this.message = `No metadata for "${targetName}" was found.`; } -} \ No newline at end of file +} diff --git a/src/error/EntityNotFoundError.ts b/src/error/EntityNotFoundError.ts index df6d21404f..446b79aaab 100644 --- a/src/error/EntityNotFoundError.ts +++ b/src/error/EntityNotFoundError.ts @@ -1,4 +1,4 @@ -import {ObjectType} from "../common/ObjectType"; +import {EntityTarget} from "../common/EntityTarget"; import {EntitySchema} from "../index"; /** @@ -7,7 +7,7 @@ import {EntitySchema} from "../index"; export class EntityNotFoundError extends Error { name = "EntityNotFound"; - constructor(entityClass: ObjectType|EntitySchema|string, criteria: any) { + constructor(entityClass: EntityTarget, criteria: any) { super(); Object.setPrototypeOf(this, EntityNotFoundError.prototype); let targetName: string; @@ -15,6 +15,8 @@ export class EntityNotFoundError extends Error { targetName = entityClass.options.name; } else if (typeof entityClass === "function") { targetName = entityClass.name; + } else if (typeof entityClass === "object" && "name" in entityClass) { + targetName = entityClass.name; } else { targetName = entityClass; } diff --git a/src/error/RepositoryNotFoundError.ts b/src/error/RepositoryNotFoundError.ts index 620078e751..1a53bc0620 100644 --- a/src/error/RepositoryNotFoundError.ts +++ b/src/error/RepositoryNotFoundError.ts @@ -1,3 +1,4 @@ +import {EntityTarget} from "../common/EntityTarget"; import {EntitySchema} from "../index"; /** @@ -6,7 +7,7 @@ import {EntitySchema} from "../index"; export class RepositoryNotFoundError extends Error { name = "RepositoryNotFoundError"; - constructor(connectionName: string, entityClass: Function|EntitySchema|string) { + constructor(connectionName: string, entityClass: EntityTarget) { super(); Object.setPrototypeOf(this, RepositoryNotFoundError.prototype); let targetName: string; @@ -14,6 +15,8 @@ export class RepositoryNotFoundError extends Error { targetName = entityClass.options.name; } else if (typeof entityClass === "function") { targetName = entityClass.name; + } else if (typeof entityClass === "object" && "name" in entityClass) { + targetName = entityClass.name; } else { targetName = entityClass; } @@ -21,4 +24,4 @@ export class RepositoryNotFoundError extends Error { `current "${connectionName}" connection?`; } -} \ No newline at end of file +} diff --git a/src/error/RepositoryNotTreeError.ts b/src/error/RepositoryNotTreeError.ts index c1533ece2e..082f01c7f3 100644 --- a/src/error/RepositoryNotTreeError.ts +++ b/src/error/RepositoryNotTreeError.ts @@ -1,3 +1,4 @@ +import {EntityTarget} from "../common/EntityTarget"; import {EntitySchema} from "../index"; /** @@ -6,18 +7,20 @@ import {EntitySchema} from "../index"; export class RepositoryNotTreeError extends Error { name = "RepositoryNotTreeError"; - constructor(target: Function|EntitySchema|string) { + constructor(entityClass: EntityTarget) { super(); Object.setPrototypeOf(this, RepositoryNotTreeError.prototype); let targetName: string; - if (target instanceof EntitySchema) { - targetName = target.options.name; - } else if (typeof target === "function") { - targetName = target.name; + if (entityClass instanceof EntitySchema) { + targetName = entityClass.options.name; + } else if (typeof entityClass === "function") { + targetName = entityClass.name; + } else if (typeof entityClass === "object" && "name" in entityClass) { + targetName = entityClass.name; } else { - targetName = target; + targetName = entityClass; } this.message = `Repository of the "${targetName}" class is not a TreeRepository. Try to apply @Tree decorator on your entity.`; } -} \ No newline at end of file +} diff --git a/src/index.ts b/src/index.ts index 749d53390c..5407300bb2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,13 +17,14 @@ import {PromiseUtils} from "./util/PromiseUtils"; import {MongoEntityManager} from "./entity-manager/MongoEntityManager"; import {SqljsEntityManager} from "./entity-manager/SqljsEntityManager"; import {SelectQueryBuilder} from "./query-builder/SelectQueryBuilder"; -import {EntitySchema} from "./entity-schema/EntitySchema"; +import {EntityTarget} from "./common/EntityTarget"; // ------------------------------------------------------------------------- // Commonly Used exports // ------------------------------------------------------------------------- export * from "./container"; +export * from "./common/EntityTarget"; export * from "./common/ObjectType"; export * from "./common/ObjectLiteral"; export * from "./common/DeepPartial"; @@ -283,14 +284,14 @@ export function getSqljsManager(connectionName: string = "default"): SqljsEntity /** * Gets repository for the given entity class. */ -export function getRepository(entityClass: ObjectType|EntitySchema|string, connectionName: string = "default"): Repository { +export function getRepository(entityClass: EntityTarget, connectionName: string = "default"): Repository { return getConnectionManager().get(connectionName).getRepository(entityClass); } /** * Gets tree repository for the given entity class. */ -export function getTreeRepository(entityClass: ObjectType|string, connectionName: string = "default"): TreeRepository { +export function getTreeRepository(entityClass: EntityTarget, connectionName: string = "default"): TreeRepository { return getConnectionManager().get(connectionName).getTreeRepository(entityClass); } @@ -304,14 +305,14 @@ export function getCustomRepository(customRepository: ObjectType, connecti /** * Gets mongodb repository for the given entity class or name. */ -export function getMongoRepository(entityClass: ObjectType|string, connectionName: string = "default"): MongoRepository { +export function getMongoRepository(entityClass: EntityTarget, connectionName: string = "default"): MongoRepository { return getConnectionManager().get(connectionName).getMongoRepository(entityClass); } /** * Creates a new query builder. */ -export function createQueryBuilder(entityClass?: ObjectType|string, alias?: string, connectionName: string = "default"): SelectQueryBuilder { +export function createQueryBuilder(entityClass?: EntityTarget, alias?: string, connectionName: string = "default"): SelectQueryBuilder { if (entityClass) { return getRepository(entityClass, connectionName).createQueryBuilder(alias); } diff --git a/src/metadata-args/EntityRepositoryMetadataArgs.ts b/src/metadata-args/EntityRepositoryMetadataArgs.ts index 1b7e3e0dbb..fd55676630 100644 --- a/src/metadata-args/EntityRepositoryMetadataArgs.ts +++ b/src/metadata-args/EntityRepositoryMetadataArgs.ts @@ -1,4 +1,4 @@ -import { EntitySchema } from "../entity-schema/EntitySchema"; +import { EntityTarget } from "../common/EntityTarget"; /** * Arguments for EntityRepositoryMetadata class, helps to construct an EntityRepositoryMetadata object. @@ -13,6 +13,6 @@ export interface EntityRepositoryMetadataArgs { /** * Entity managed by this custom repository. */ - readonly entity?: Function|string|EntitySchema; + readonly entity?: EntityTarget; } diff --git a/src/query-builder/DeleteQueryBuilder.ts b/src/query-builder/DeleteQueryBuilder.ts index e6efd9d697..c4c1358d16 100644 --- a/src/query-builder/DeleteQueryBuilder.ts +++ b/src/query-builder/DeleteQueryBuilder.ts @@ -2,7 +2,7 @@ import {CockroachDriver} from "../driver/cockroachdb/CockroachDriver"; import {OracleDriver} from "../driver/oracle/OracleDriver"; import {QueryBuilder} from "./QueryBuilder"; import {ObjectLiteral} from "../common/ObjectLiteral"; -import {ObjectType} from "../common/ObjectType"; +import {EntityTarget} from "../common/EntityTarget"; import {Connection} from "../connection/Connection"; import {QueryRunner} from "../query-runner/QueryRunner"; import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver"; @@ -133,7 +133,7 @@ export class DeleteQueryBuilder extends QueryBuilder implements * Specifies FROM which entity's table select/update/delete will be executed. * Also sets a main string alias of the selection data. */ - from(entityTarget: ObjectType|EntitySchema|string, aliasName?: string): DeleteQueryBuilder { + from(entityTarget: EntityTarget, aliasName?: string): DeleteQueryBuilder { entityTarget = entityTarget instanceof EntitySchema ? entityTarget.options.name : entityTarget; const mainAlias = this.createFromAlias(entityTarget, aliasName); this.expressionMap.setMainAlias(mainAlias); diff --git a/src/query-builder/InsertQueryBuilder.ts b/src/query-builder/InsertQueryBuilder.ts index 106cd41494..8192293f62 100644 --- a/src/query-builder/InsertQueryBuilder.ts +++ b/src/query-builder/InsertQueryBuilder.ts @@ -2,7 +2,7 @@ import {CockroachDriver} from "../driver/cockroachdb/CockroachDriver"; import {SapDriver} from "../driver/sap/SapDriver"; import {QueryBuilder} from "./QueryBuilder"; import {ObjectLiteral} from "../common/ObjectLiteral"; -import {ObjectType} from "../common/ObjectType"; +import {EntityTarget} from "../common/EntityTarget"; import {QueryDeepPartialEntity} from "./QueryPartialEntity"; import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver"; import {PostgresDriver} from "../driver/postgres/PostgresDriver"; @@ -164,7 +164,7 @@ export class InsertQueryBuilder extends QueryBuilder { /** * Specifies INTO which entity's table insertion will be executed. */ - into(entityTarget: ObjectType|EntitySchema|string, columns?: string[]): InsertQueryBuilder { + into(entityTarget: EntityTarget, columns?: string[]): InsertQueryBuilder { entityTarget = entityTarget instanceof EntitySchema ? entityTarget.options.name : entityTarget; const mainAlias = this.createFromAlias(entityTarget); this.expressionMap.setMainAlias(mainAlias); diff --git a/src/query-builder/QueryBuilder.ts b/src/query-builder/QueryBuilder.ts index 21ae390277..c883b5ad07 100644 --- a/src/query-builder/QueryBuilder.ts +++ b/src/query-builder/QueryBuilder.ts @@ -8,7 +8,7 @@ import {DeleteQueryBuilder} from "./DeleteQueryBuilder"; import {SoftDeleteQueryBuilder} from "./SoftDeleteQueryBuilder"; import {InsertQueryBuilder} from "./InsertQueryBuilder"; import {RelationQueryBuilder} from "./RelationQueryBuilder"; -import {ObjectType} from "../common/ObjectType"; +import {EntityTarget} from "../common/EntityTarget"; import {Alias} from "./Alias"; import {Brackets} from "./Brackets"; import {QueryDeepPartialEntity} from "./QueryPartialEntity"; @@ -187,17 +187,7 @@ export abstract class QueryBuilder { /** * Creates UPDATE query for the given entity and applies given update values. */ - update(entity: ObjectType, updateSet?: QueryDeepPartialEntity): UpdateQueryBuilder; - - /** - * Creates UPDATE query for the given entity and applies given update values. - */ - update(entity: EntitySchema, updateSet?: QueryDeepPartialEntity): UpdateQueryBuilder; - - /** - * Creates UPDATE query for the given entity and applies given update values. - */ - update(entity: Function|EntitySchema|string, updateSet?: QueryDeepPartialEntity): UpdateQueryBuilder; + update(entity: EntityTarget, updateSet?: QueryDeepPartialEntity): UpdateQueryBuilder; /** * Creates UPDATE query for the given table name and applies given update values. @@ -207,7 +197,7 @@ export abstract class QueryBuilder { /** * Creates UPDATE query and applies given update values. */ - update(entityOrTableNameUpdateSet?: string|Function|EntitySchema|ObjectLiteral, maybeUpdateSet?: ObjectLiteral): UpdateQueryBuilder { + update(entityOrTableNameUpdateSet?: EntityTarget|ObjectLiteral, maybeUpdateSet?: ObjectLiteral): UpdateQueryBuilder { const updateSet = maybeUpdateSet ? maybeUpdateSet : entityOrTableNameUpdateSet as ObjectLiteral|undefined; entityOrTableNameUpdateSet = entityOrTableNameUpdateSet instanceof EntitySchema ? entityOrTableNameUpdateSet.options.name : entityOrTableNameUpdateSet; @@ -271,7 +261,7 @@ export abstract class QueryBuilder { /** * Sets entity's relation with which this query builder gonna work. */ - relation(entityTarget: ObjectType|string, propertyPath: string): RelationQueryBuilder; + relation(entityTarget: EntityTarget, propertyPath: string): RelationQueryBuilder; /** * Sets entity's relation with which this query builder gonna work. @@ -303,7 +293,7 @@ export abstract class QueryBuilder { * * todo: move this method to manager? or create a shortcut? */ - hasRelation(target: ObjectType|string, relation: string): boolean; + hasRelation(target: EntityTarget, relation: string): boolean; /** * Checks if given relations exist in the entity. @@ -311,7 +301,7 @@ export abstract class QueryBuilder { * * todo: move this method to manager? or create a shortcut? */ - hasRelation(target: ObjectType|string, relation: string[]): boolean; + hasRelation(target: EntityTarget, relation: string[]): boolean; /** * Checks if given relation or relations exist in the entity. @@ -319,7 +309,7 @@ export abstract class QueryBuilder { * * todo: move this method to manager? or create a shortcut? */ - hasRelation(target: ObjectType|string, relation: string|string[]): boolean { + hasRelation(target: EntityTarget, relation: string|string[]): boolean { const entityMetadata = this.connection.getMetadata(target); const relations = Array.isArray(relation) ? relation : [relation]; return relations.every(relation => { @@ -532,7 +522,7 @@ export abstract class QueryBuilder { * Specifies FROM which entity's table select/update/delete will be executed. * Also sets a main string alias of the selection data. */ - protected createFromAlias(entityTarget: Function|string|((qb: SelectQueryBuilder) => SelectQueryBuilder), aliasName?: string): Alias { + protected createFromAlias(entityTarget: EntityTarget|((qb: SelectQueryBuilder) => SelectQueryBuilder), aliasName?: string): Alias { // if table has a metadata then find it to properly escape its properties // const metadata = this.connection.entityMetadatas.find(metadata => metadata.tableName === tableName); @@ -547,21 +537,25 @@ export abstract class QueryBuilder { }); } else { - let subQuery: string = ""; - if (entityTarget instanceof Function) { - const subQueryBuilder: SelectQueryBuilder = (entityTarget as any)(((this as any) as SelectQueryBuilder).subQuery()); - this.setParameters(subQueryBuilder.getParameters()); - subQuery = subQueryBuilder.getQuery(); - - } else { - subQuery = entityTarget; + if (typeof entityTarget === "string") { + const isSubquery = entityTarget.substr(0, 1) === "(" && entityTarget.substr(-1) === ")"; + + return this.expressionMap.createAlias({ + type: "from", + name: aliasName, + tablePath: !isSubquery ? entityTarget as string : undefined, + subQuery: isSubquery ? entityTarget : undefined, + }); } - const isSubQuery = entityTarget instanceof Function || entityTarget.substr(0, 1) === "(" && entityTarget.substr(-1) === ")"; + + const subQueryBuilder: SelectQueryBuilder = (entityTarget as any)(((this as any) as SelectQueryBuilder).subQuery()); + this.setParameters(subQueryBuilder.getParameters()); + const subquery = subQueryBuilder.getQuery(); + return this.expressionMap.createAlias({ type: "from", name: aliasName, - tablePath: isSubQuery === false ? entityTarget as string : undefined, - subQuery: isSubQuery === true ? subQuery : undefined, + subQuery: subquery }); } } diff --git a/src/query-builder/SelectQueryBuilder.ts b/src/query-builder/SelectQueryBuilder.ts index 9a87ac832a..821be3186c 100644 --- a/src/query-builder/SelectQueryBuilder.ts +++ b/src/query-builder/SelectQueryBuilder.ts @@ -24,7 +24,7 @@ import {EntityMetadata} from "../metadata/EntityMetadata"; import {ColumnMetadata} from "../metadata/ColumnMetadata"; import {OrderByCondition} from "../find-options/OrderByCondition"; import {QueryExpressionMap} from "./QueryExpressionMap"; -import {ObjectType} from "../common/ObjectType"; +import {EntityTarget} from "../common/EntityTarget"; import {QueryRunner} from "../query-runner/QueryRunner"; import {WhereExpression} from "./WhereExpression"; import {Brackets} from "./Brackets"; @@ -188,14 +188,14 @@ export class SelectQueryBuilder extends QueryBuilder implements * Also sets a main string alias of the selection data. * Removes all previously set from-s. */ - from(entityTarget: ObjectType|string, aliasName: string): SelectQueryBuilder; + from(entityTarget: EntityTarget, aliasName: string): SelectQueryBuilder; /** * Specifies FROM which entity's table select/update/delete will be executed. * Also sets a main string alias of the selection data. * Removes all previously set from-s. */ - from(entityTarget: ObjectType|string|((qb: SelectQueryBuilder) => SelectQueryBuilder), aliasName: string): SelectQueryBuilder { + from(entityTarget: EntityTarget|((qb: SelectQueryBuilder) => SelectQueryBuilder), aliasName: string): SelectQueryBuilder { const mainAlias = this.createFromAlias(entityTarget, aliasName); this.expressionMap.setMainAlias(mainAlias); return (this as any) as SelectQueryBuilder; @@ -211,13 +211,13 @@ export class SelectQueryBuilder extends QueryBuilder implements * Specifies FROM which entity's table select/update/delete will be executed. * Also sets a main string alias of the selection data. */ - addFrom(entityTarget: ObjectType|string, aliasName: string): SelectQueryBuilder; + addFrom(entityTarget: EntityTarget, aliasName: string): SelectQueryBuilder; /** * Specifies FROM which entity's table select/update/delete will be executed. * Also sets a main string alias of the selection data. */ - addFrom(entityTarget: ObjectType|string|((qb: SelectQueryBuilder) => SelectQueryBuilder), aliasName: string): SelectQueryBuilder { + addFrom(entityTarget: EntityTarget|((qb: SelectQueryBuilder) => SelectQueryBuilder), aliasName: string): SelectQueryBuilder { const alias = this.createFromAlias(entityTarget, aliasName); if (!this.expressionMap.mainAlias) this.expressionMap.setMainAlias(alias); diff --git a/src/query-builder/SoftDeleteQueryBuilder.ts b/src/query-builder/SoftDeleteQueryBuilder.ts index 3f5b903f48..f4e54395cf 100644 --- a/src/query-builder/SoftDeleteQueryBuilder.ts +++ b/src/query-builder/SoftDeleteQueryBuilder.ts @@ -1,7 +1,7 @@ import {CockroachDriver} from "../driver/cockroachdb/CockroachDriver"; import {QueryBuilder} from "./QueryBuilder"; import {ObjectLiteral} from "../common/ObjectLiteral"; -import {ObjectType} from "../common/ObjectType"; +import {EntityTarget} from "../common/EntityTarget"; import {Connection} from "../connection/Connection"; import {QueryRunner} from "../query-runner/QueryRunner"; import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver"; @@ -142,7 +142,7 @@ export class SoftDeleteQueryBuilder extends QueryBuilder impleme * Specifies FROM which entity's table select/update/delete/soft-delete will be executed. * Also sets a main string alias of the selection data. */ - from(entityTarget: ObjectType|EntitySchema|string, aliasName?: string): SoftDeleteQueryBuilder { + from(entityTarget: EntityTarget, aliasName?: string): SoftDeleteQueryBuilder { entityTarget = entityTarget instanceof EntitySchema ? entityTarget.options.name : entityTarget; const mainAlias = this.createFromAlias(entityTarget, aliasName); this.expressionMap.setMainAlias(mainAlias); diff --git a/src/repository/AbstractRepository.ts b/src/repository/AbstractRepository.ts index 87005cb0a9..789368f2b9 100644 --- a/src/repository/AbstractRepository.ts +++ b/src/repository/AbstractRepository.ts @@ -2,12 +2,12 @@ import {ObjectLiteral} from "../common/ObjectLiteral"; import {EntityManager} from "../entity-manager/EntityManager"; import {Repository} from "./Repository"; import {TreeRepository} from "./TreeRepository"; +import {EntityTarget} from "../common/EntityTarget"; import {ObjectType} from "../common/ObjectType"; import {CustomRepositoryDoesNotHaveEntityError} from "../error/CustomRepositoryDoesNotHaveEntityError"; import {getMetadataArgsStorage} from "../index"; import {CustomRepositoryNotFoundError} from "../error/CustomRepositoryNotFoundError"; import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder"; -import { EntitySchema } from "../entity-schema/EntitySchema"; /** * Provides abstract class for custom repositories that do not inherit from original orm Repository. @@ -100,7 +100,7 @@ export class AbstractRepository { * Gets custom repository's managed entity. * If given custom repository does not manage any entity then undefined will be returned. */ - private getCustomRepositoryTarget(customRepository: any): Function|string|EntitySchema|undefined { + private getCustomRepositoryTarget(customRepository: any): EntityTarget|undefined { const entityRepositoryMetadataArgs = getMetadataArgsStorage().entityRepositories.find(repository => { return repository.target === (customRepository instanceof Function ? customRepository : (customRepository as any).constructor); }); @@ -110,4 +110,4 @@ export class AbstractRepository { return entityRepositoryMetadataArgs.entity; } -} \ No newline at end of file +} diff --git a/src/repository/Repository.ts b/src/repository/Repository.ts index b8ad4390b2..96c9223fa7 100644 --- a/src/repository/Repository.ts +++ b/src/repository/Repository.ts @@ -147,7 +147,7 @@ export class Repository { * Saves one or many given entities. */ save>(entityOrEntities: T|T[], options?: SaveOptions): Promise { - return this.manager.save(this.metadata.target as any, entityOrEntities as any, options); + return this.manager.save(this.metadata.target as any, entityOrEntities as any, options); } /** @@ -191,7 +191,7 @@ export class Repository { * Records the delete date of one or many given entities. */ softRemove>(entityOrEntities: T|T[], options?: SaveOptions): Promise { - return this.manager.softRemove(this.metadata.target as any, entityOrEntities as any, options); + return this.manager.softRemove(this.metadata.target as any, entityOrEntities as any, options); } /** @@ -218,7 +218,7 @@ export class Repository { * Recovers one or many given entities. */ recover>(entityOrEntities: T|T[], options?: SaveOptions): Promise { - return this.manager.recover(this.metadata.target as any, entityOrEntities as any, options); + return this.manager.recover(this.metadata.target as any, entityOrEntities as any, options); } /**