import { RelationMetadata } from "../../metadata/RelationMetadata" import { QueryBuilderUtils } from "../QueryBuilderUtils" import { EntityMetadata } from "../../metadata/EntityMetadata" import { QueryExpressionMap } from "../QueryExpressionMap" import { SelectQueryBuilder } from "../SelectQueryBuilder" import { ObjectUtils } from "../../util/ObjectUtils" import { TypeORMError } from "../../error/TypeORMError" /** * Stores all join relation id attributes which will be used to build a JOIN query. */ export class RelationIdAttribute { // ------------------------------------------------------------------------- // Public Properties // ------------------------------------------------------------------------- /** * Alias of the joined (destination) table. */ alias?: string /** * Name of relation. */ relationName: string /** * Property + alias of the object where to joined data should be mapped. */ mapToProperty: string /** * Extra condition applied to "ON" section of join. */ queryBuilderFactory?: ( qb: SelectQueryBuilder, ) => SelectQueryBuilder /** * Indicates if relation id should NOT be loaded as id map. */ disableMixedMap = false // ------------------------------------------------------------------------- // Constructor // ------------------------------------------------------------------------- constructor( private queryExpressionMap: QueryExpressionMap, relationIdAttribute?: Partial, ) { ObjectUtils.assign(this, relationIdAttribute || {}) } // ------------------------------------------------------------------------- // Public Methods // ------------------------------------------------------------------------- get joinInverseSideMetadata(): EntityMetadata { return this.relation.inverseEntityMetadata } /** * Alias of the parent of this join. * For example, if we join ("post.category", "categoryAlias") then "post" is a parent alias. * This value is extracted from entityOrProperty value. * This is available when join was made using "post.category" syntax. */ get parentAlias(): string { if (!QueryBuilderUtils.isAliasProperty(this.relationName)) throw new TypeORMError( `Given value must be a string representation of alias property`, ) return this.relationName.substr(0, this.relationName.indexOf(".")) } /** * Relation property name of the parent. * This is used to understand what is joined. * For example, if we join ("post.category", "categoryAlias") then "category" is a relation property. * This value is extracted from entityOrProperty value. * This is available when join was made using "post.category" syntax. */ get relationPropertyPath(): string { if (!QueryBuilderUtils.isAliasProperty(this.relationName)) throw new TypeORMError( `Given value must be a string representation of alias property`, ) return this.relationName.substr(this.relationName.indexOf(".") + 1) } /** * Relation of the parent. * This is used to understand what is joined. * This is available when join was made using "post.category" syntax. */ get relation(): RelationMetadata { if (!QueryBuilderUtils.isAliasProperty(this.relationName)) throw new TypeORMError( `Given value must be a string representation of alias property`, ) const relationOwnerSelection = this.queryExpressionMap.findAliasByName( this.parentAlias!, ) const relation = relationOwnerSelection.metadata.findRelationWithPropertyPath( this.relationPropertyPath!, ) if (!relation) throw new TypeORMError( `Relation with property path ${this.relationPropertyPath} in entity was not found.`, ) return relation } /** * Generates alias of junction table, whose ids we get. */ get junctionAlias(): string { const [parentAlias, relationProperty] = this.relationName.split(".") return parentAlias + "_" + relationProperty + "_rid" } /** * Metadata of the joined entity. * If extra condition without entity was joined, then it will return undefined. */ get junctionMetadata(): EntityMetadata { return this.relation.junctionEntityMetadata! } get mapToPropertyParentAlias(): string { return this.mapToProperty.substr(0, this.mapToProperty.indexOf(".")) } get mapToPropertyPropertyPath(): string { return this.mapToProperty.substr(this.mapToProperty.indexOf(".") + 1) } }