{"version":3,"sources":["../../src/find-options/FindOptionsUtils.ts"],"names":[],"mappings":"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","file":"FindOptionsUtils.js","sourcesContent":["import { FindManyOptions } from \"./FindManyOptions\"\nimport { FindOneOptions } from \"./FindOneOptions\"\nimport { SelectQueryBuilder } from \"../query-builder/SelectQueryBuilder\"\nimport { FindRelationsNotFoundError } from \"../error\"\nimport { EntityMetadata } from \"../metadata/EntityMetadata\"\nimport { DriverUtils } from \"../driver/DriverUtils\"\nimport { FindTreeOptions } from \"./FindTreeOptions\"\nimport { ObjectLiteral } from \"../common/ObjectLiteral\"\nimport { RelationMetadata } from \"../metadata/RelationMetadata\"\nimport { EntityPropertyNotFoundError } from \"../error\"\n\n/**\n * Utilities to work with FindOptions.\n */\nexport class FindOptionsUtils {\n // -------------------------------------------------------------------------\n // Public Static Methods\n // -------------------------------------------------------------------------\n\n /**\n * Checks if given object is really instance of FindOneOptions interface.\n */\n static isFindOneOptions(\n obj: any,\n ): obj is FindOneOptions {\n const possibleOptions: FindOneOptions = obj\n return (\n possibleOptions &&\n (Array.isArray(possibleOptions.select) ||\n Array.isArray(possibleOptions.relations) ||\n typeof possibleOptions.select === \"object\" ||\n typeof possibleOptions.relations === \"object\" ||\n typeof possibleOptions.where === \"object\" ||\n // typeof possibleOptions.where === \"string\" ||\n typeof possibleOptions.join === \"object\" ||\n typeof possibleOptions.order === \"object\" ||\n typeof possibleOptions.cache === \"object\" ||\n typeof possibleOptions.cache === \"boolean\" ||\n typeof possibleOptions.cache === \"number\" ||\n typeof possibleOptions.comment === \"string\" ||\n typeof possibleOptions.lock === \"object\" ||\n typeof possibleOptions.loadRelationIds === \"object\" ||\n typeof possibleOptions.loadRelationIds === \"boolean\" ||\n typeof possibleOptions.loadEagerRelations === \"boolean\" ||\n typeof possibleOptions.withDeleted === \"boolean\" ||\n typeof possibleOptions.relationLoadStrategy === \"string\" ||\n typeof possibleOptions.transaction === \"boolean\")\n )\n }\n\n /**\n * Checks if given object is really instance of FindManyOptions interface.\n */\n static isFindManyOptions(\n obj: any,\n ): obj is FindManyOptions {\n const possibleOptions: FindManyOptions = obj\n return (\n possibleOptions &&\n (this.isFindOneOptions(possibleOptions) ||\n typeof (possibleOptions as FindManyOptions).skip ===\n \"number\" ||\n typeof (possibleOptions as FindManyOptions).take ===\n \"number\" ||\n typeof (possibleOptions as FindManyOptions).skip ===\n \"string\" ||\n typeof (possibleOptions as FindManyOptions).take ===\n \"string\")\n )\n }\n\n /**\n * Checks if given object is really instance of FindOptions interface.\n */\n static extractFindManyOptionsAlias(object: any): string | undefined {\n if (this.isFindManyOptions(object) && object.join)\n return object.join.alias\n\n return undefined\n }\n\n /**\n * Applies give find many options to the given query builder.\n\n static applyFindManyOptionsOrConditionsToQueryBuilder(qb: SelectQueryBuilder, options: FindManyOptions|Partial|undefined): SelectQueryBuilder {\n if (this.isFindManyOptions(options))\n return this.applyOptionsToQueryBuilder(qb, options);\n\n if (options)\n return qb.where(options);\n\n return qb;\n }*/\n\n /**\n * Applies give find options to the given query builder.\n\n static applyOptionsToQueryBuilder(qb: SelectQueryBuilder, options: FindOneOptions|FindManyOptions|undefined): SelectQueryBuilder {\n\n // if options are not set then simply return query builder. This is made for simplicity of usage.\n if (!options || (!this.isFindOneOptions(options) && !this.isFindManyOptions(options)))\n return qb;\n\n if (options.transaction === true) {\n qb.expressionMap.useTransaction = true;\n }\n\n if (!qb.expressionMap.mainAlias || !qb.expressionMap.mainAlias.hasMetadata)\n return qb;\n\n const metadata = qb.expressionMap.mainAlias!.metadata;\n\n // apply all options from FindOptions\n if (options.comment) {\n qb.comment(options.comment);\n }\n\n if (options.withDeleted) {\n qb.withDeleted();\n }\n\n if (options.select) {\n qb.select([]);\n options.select.forEach(select => {\n if (!metadata.hasColumnWithPropertyPath(`${select}`))\n throw new TypeORMError(`${select} column was not found in the ${metadata.name} entity.`);\n\n const columns = metadata.findColumnsWithPropertyPath(`${select}`);\n\n for (const column of columns) {\n qb.addSelect(qb.alias + \".\" + column.propertyPath);\n }\n });\n }\n\n if (options.relations) {\n // Copy because `applyRelationsRecursively` modifies it\n const allRelations = [...options.relations];\n this.applyRelationsRecursively(qb, allRelations, qb.expressionMap.mainAlias!.name, qb.expressionMap.mainAlias!.metadata, \"\");\n // recursive removes found relations from allRelations array\n // if there are relations left in this array it means those relations were not found in the entity structure\n // so, we give an exception about not found relations\n if (allRelations.length > 0)\n throw new FindRelationsNotFoundError(allRelations);\n }\n\n if (options.join) {\n if (options.join.leftJoin)\n Object.keys(options.join.leftJoin).forEach(key => {\n qb.leftJoin(options.join!.leftJoin![key], key);\n });\n\n if (options.join.innerJoin)\n Object.keys(options.join.innerJoin).forEach(key => {\n qb.innerJoin(options.join!.innerJoin![key], key);\n });\n\n if (options.join.leftJoinAndSelect)\n Object.keys(options.join.leftJoinAndSelect).forEach(key => {\n qb.leftJoinAndSelect(options.join!.leftJoinAndSelect![key], key);\n });\n\n if (options.join.innerJoinAndSelect)\n Object.keys(options.join.innerJoinAndSelect).forEach(key => {\n qb.innerJoinAndSelect(options.join!.innerJoinAndSelect![key], key);\n });\n }\n\n if (options.cache) {\n if (options.cache instanceof Object) {\n const cache = options.cache as { id: any, milliseconds: number };\n qb.cache(cache.id, cache.milliseconds);\n } else {\n qb.cache(options.cache);\n }\n }\n\n if (options.lock) {\n if (options.lock.mode === \"optimistic\") {\n qb.setLock(options.lock.mode, options.lock.version);\n } else if (\n options.lock.mode === \"pessimistic_read\" ||\n options.lock.mode === \"pessimistic_write\" ||\n options.lock.mode === \"dirty_read\" ||\n options.lock.mode === \"pessimistic_partial_write\" ||\n options.lock.mode === \"pessimistic_write_or_fail\" ||\n options.lock.mode === \"for_no_key_update\" ||\n options.lock.mode === \"for_key_share\"\n ) {\n const tableNames = options.lock.tables ? options.lock.tables.map((table) => {\n const tableAlias = qb.expressionMap.aliases.find((alias) => {\n return alias.metadata.tableNameWithoutPrefix === table;\n });\n if (!tableAlias) {\n throw new TypeORMError(`\"${table}\" is not part of this query`);\n }\n return qb.escape(tableAlias.name);\n }) : undefined;\n qb.setLock(options.lock.mode, undefined, tableNames);\n }\n }\n\n if (options.loadRelationIds === true) {\n qb.loadAllRelationIds();\n\n } else if (options.loadRelationIds instanceof Object) {\n qb.loadAllRelationIds(options.loadRelationIds as any);\n }\n\n if (options.where)\n qb.where(options.where);\n\n if ((options as FindManyOptions).skip)\n qb.skip((options as FindManyOptions).skip!);\n\n if ((options as FindManyOptions).take)\n qb.take((options as FindManyOptions).take!);\n\n if (options.order)\n Object.keys(options.order).forEach(key => {\n const order = ((options as FindOneOptions).order as any)[key as any];\n\n if (!metadata.findColumnWithPropertyPath(key))\n throw new Error(`${key} column was not found in the ${metadata.name} entity.`);\n\n switch (order) {\n case 1:\n qb.addOrderBy(qb.alias + \".\" + key, \"ASC\");\n break;\n case -1:\n qb.addOrderBy(qb.alias + \".\" + key, \"DESC\");\n break;\n case \"ASC\":\n qb.addOrderBy(qb.alias + \".\" + key, \"ASC\");\n break;\n case \"DESC\":\n qb.addOrderBy(qb.alias + \".\" + key, \"DESC\");\n break;\n }\n });\n\n return qb;\n }*/\n\n static applyOptionsToTreeQueryBuilder(\n qb: SelectQueryBuilder,\n options?: FindTreeOptions,\n ): SelectQueryBuilder {\n if (options?.relations) {\n // Copy because `applyRelationsRecursively` modifies it\n const allRelations = [...options.relations]\n\n FindOptionsUtils.applyRelationsRecursively(\n qb,\n allRelations,\n qb.expressionMap.mainAlias!.name,\n qb.expressionMap.mainAlias!.metadata,\n \"\",\n )\n\n // recursive removes found relations from allRelations array\n // if there are relations left in this array it means those relations were not found in the entity structure\n // so, we give an exception about not found relations\n if (allRelations.length > 0)\n throw new FindRelationsNotFoundError(allRelations)\n }\n\n return qb\n }\n\n // -------------------------------------------------------------------------\n // Protected Static Methods\n // -------------------------------------------------------------------------\n\n /**\n * Adds joins for all relations and sub-relations of the given relations provided in the find options.\n */\n public static applyRelationsRecursively(\n qb: SelectQueryBuilder,\n allRelations: string[],\n alias: string,\n metadata: EntityMetadata,\n prefix: string,\n ): void {\n // find all relations that match given prefix\n let matchedBaseRelations: RelationMetadata[] = []\n if (prefix) {\n const regexp = new RegExp(\"^\" + prefix.replace(\".\", \"\\\\.\") + \"\\\\.\")\n matchedBaseRelations = allRelations\n .filter((relation) => relation.match(regexp))\n .map((relation) =>\n metadata.findRelationWithPropertyPath(\n relation.replace(regexp, \"\"),\n ),\n )\n .filter((entity) => entity) as RelationMetadata[]\n } else {\n matchedBaseRelations = allRelations\n .map((relation) =>\n metadata.findRelationWithPropertyPath(relation),\n )\n .filter((entity) => entity) as RelationMetadata[]\n }\n\n // go through all matched relations and add join for them\n matchedBaseRelations.forEach((relation) => {\n // generate a relation alias\n let relationAlias: string = DriverUtils.buildAlias(\n qb.connection.driver,\n { joiner: \"__\" },\n alias,\n relation.propertyPath,\n )\n\n // add a join for the found relation\n const selection = alias + \".\" + relation.propertyPath\n if (qb.expressionMap.relationLoadStrategy === \"query\") {\n qb.concatRelationMetadata(relation)\n } else {\n qb.leftJoinAndSelect(selection, relationAlias)\n }\n\n // remove added relations from the allRelations array, this is needed to find all not found relations at the end\n allRelations.splice(\n allRelations.indexOf(\n prefix\n ? prefix + \".\" + relation.propertyPath\n : relation.propertyPath,\n ),\n 1,\n )\n\n // try to find sub-relations\n let relationMetadata: EntityMetadata | undefined\n let relationName: string | undefined\n\n if (qb.expressionMap.relationLoadStrategy === \"query\") {\n relationMetadata = relation.inverseEntityMetadata\n relationName = relationAlias\n } else {\n const join = qb.expressionMap.joinAttributes.find(\n (join) => join.entityOrProperty === selection,\n )\n relationMetadata = join!.metadata!\n relationName = join!.alias.name\n }\n\n if (!relationName || !relationMetadata) {\n throw new EntityPropertyNotFoundError(\n relation.propertyPath,\n metadata,\n )\n }\n\n this.applyRelationsRecursively(\n qb,\n allRelations,\n relationName,\n relationMetadata,\n prefix\n ? prefix + \".\" + relation.propertyPath\n : relation.propertyPath,\n )\n\n // join the eager relations of the found relation\n // Only supported for \"join\" relationLoadStrategy\n if (qb.expressionMap.relationLoadStrategy === \"join\") {\n const relMetadata = metadata.relations.find(\n (metadata) =>\n metadata.propertyName === relation.propertyPath,\n )\n if (relMetadata) {\n this.joinEagerRelations(\n qb,\n relationAlias,\n relMetadata.inverseEntityMetadata,\n )\n }\n }\n })\n }\n\n public static joinEagerRelations(\n qb: SelectQueryBuilder,\n alias: string,\n metadata: EntityMetadata,\n ) {\n metadata.eagerRelations.forEach((relation) => {\n // generate a relation alias\n let relationAlias: string = DriverUtils.buildAlias(\n qb.connection.driver,\n { joiner: \"__\" },\n alias,\n relation.propertyName,\n )\n\n // add a join for the relation\n // Checking whether the relation wasn't joined yet.\n let addJoin = true\n // TODO: Review this validation\n for (const join of qb.expressionMap.joinAttributes) {\n if (\n join.condition !== undefined ||\n join.mapToProperty !== undefined ||\n join.isMappingMany !== undefined ||\n join.direction !== \"LEFT\" ||\n join.entityOrProperty !==\n `${alias}.${relation.propertyPath}`\n ) {\n continue\n }\n addJoin = false\n relationAlias = join.alias.name\n break\n }\n\n const joinAlreadyAdded = Boolean(\n qb.expressionMap.joinAttributes.find(\n (joinAttribute) =>\n joinAttribute.alias.name === relationAlias,\n ),\n )\n\n if (addJoin && !joinAlreadyAdded) {\n qb.leftJoin(alias + \".\" + relation.propertyPath, relationAlias)\n }\n\n // Checking whether the relation wasn't selected yet.\n // This check shall be after the join check to detect relationAlias.\n let addSelect = true\n for (const select of qb.expressionMap.selects) {\n if (\n select.aliasName !== undefined ||\n select.virtual !== undefined ||\n select.selection !== relationAlias\n ) {\n continue\n }\n addSelect = false\n break\n }\n\n if (addSelect) {\n qb.addSelect(relationAlias)\n }\n\n // (recursive) join the eager relations\n this.joinEagerRelations(\n qb,\n relationAlias,\n relation.inverseEntityMetadata,\n )\n })\n }\n}\n"],"sourceRoot":".."}