UNPKG

graphql-composer-typeorm

Version:
207 lines 9.28 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Parser = void 0; const graphql_composer_1 = require("graphql-composer"); const graphql_composer_decorators_1 = require("graphql-composer-decorators"); const typeorm_1 = require("typeorm"); class Parser { constructor(classType, args) { this._classType = classType; this._args = args; } get classType() { return this._classType; } get computedArgs() { if (!this._computedArgs) { this._computedArgs = this._args(); } return this._computedArgs; } getRelationPath(item) { const name = `${this._classType.name}.${item}`; const nameArgs = name.split(/\./g); const prop = nameArgs[nameArgs.length - 1]; nameArgs.splice(nameArgs.length - 1, 1); return `${nameArgs.join("_")}.${prop}`; } async buildQuery(ctx) { const args = ctx.rawArgs; const where = args.where; const relations = await this.getRelations(ctx); const query = typeorm_1.createQueryBuilder(this._classType, this._classType.name); if (args.orders !== undefined) { args.orders.map((item) => { query.addOrderBy(this.getRelationPath(item.field), item.order); }); } if (args.limit !== undefined && args.skip !== undefined) { query.limit(args.limit); query.offset(args.skip); } relations.map((item) => { const relationName = this.getRelationPath(item); query.leftJoinAndSelect(relationName, relationName.replace(/\./g, "_")); }); if (args.where !== undefined) { const parseWhere = (object, inputType, parent) => { Object.keys(object).map((key) => { const value = object[key]; if (inputType instanceof graphql_composer_1.InputType) { const field = inputType.fields.find((f) => f.name === key); const type = Parser.unwrapModifiedType(field.type); const propName = `${parent}.${key}`; if (type instanceof graphql_composer_1.InputType) { switch (type.name) { case "StringArgument": const strArg = value; if (strArg.eq !== undefined) { query.andWhere(`${propName} = :${key}`, { [key]: strArg.eq, }); } else if (strArg.like !== undefined) { query.andWhere(`${propName} LIKE :${key}`, { [key]: strArg.like, }); } return; case "NumberArgument": const nbArg = value; if (nbArg.eq !== undefined) { query.andWhere(`${propName} = :${key}`, { [key]: nbArg.eq, }); } else if (nbArg.gt !== undefined) { query.andWhere(`${propName} > :${key}`, { [key]: nbArg.gt, }); } else if (nbArg.gte !== undefined) { query.andWhere(`${propName} >= :${key}`, { [key]: nbArg.gte, }); } else if (nbArg.lt !== undefined) { query.andWhere(`${propName} < :${key}`, { [key]: nbArg.lt, }); } else if (nbArg.lte !== undefined) { query.andWhere(`${propName} <= :${key}`, { [key]: nbArg.lte, }); } return; } } else { query.andWhere(`${propName} = :${key}`, { [key]: value, }); } parseWhere(value, type, `${parent}_${key}`); } }); }; parseWhere(where, this._computedArgs.fields.find((f) => f.name === "where") .type.type, this._classType.name); } return query; } async getRelations(ctx) { const selections = ctx.infos.fieldNodes[0].selectionSet.selections; const relationsWhere = await this.parseWhereToRelations(ctx.rawArgs.where); const relationsSelection = await this.parseSelectionsToRelations(this._classType, selections); let relations = [...relationsWhere, ...relationsSelection]; relations = relations.filter((item, index) => relations.indexOf(item) === index); return relations; } async parseWhereToRelations(where) { const relations = []; const ormMetadatas = typeorm_1.getMetadataArgsStorage(); const args = this.computedArgs.fields.find((f) => f.name === "where") .type.type; if (where === undefined) { return relations; } const parse = async (obj, args, parent) => { if (!obj) { return; } Object.keys(obj).map((key) => { if (typeof obj[key] === "object" && obj[key]) { const relation = ormMetadatas.relations.find((relation) => { return relation.propertyName === key; }); if (relation) { const table = ormMetadatas.tables.find((t) => { return t.target === relation.type(); }); if (table) { const prefix = parent ? `${parent}.` : ""; const relationName = prefix + relation.propertyName; relations.push(relationName); const field = args.fields.find((f) => f.name === key); if (field) { const t = Parser.unwrapModifiedType(field.type); parse(obj[key], t, relationName); } } } } }); }; await parse(where, args); return relations; } async parseSelectionsToRelations(classType, selections) { const relations = []; const ormMetadatas = typeorm_1.getMetadataArgsStorage(); const objectType = graphql_composer_decorators_1.MetadataStorage.instance.classTypeMap.get(classType) .object; if (!objectType) { throw new Error(`You should decorate the class ${classType.name} with @ObjectType`); } const parse = async (selections, parent) => { selections.map((selection) => { if (!selection.selectionSet) { return; } const relationInfos = ormMetadatas.relations.find((item) => { return item.propertyName === selection.name.value; }); if (relationInfos) { const relationType = relationInfos.type(); const relation = ormMetadatas.tables.find((item) => { return item.target === relationType; }); if (relation) { const prefix = parent ? `${parent}.` : ""; const relationName = prefix + relationInfos.propertyName; relations.push(relationName); parse(selection.selectionSet.selections, relationName); } } }); }; await parse(selections); return relations; } static unwrapModifiedType(fieldType) { let type = fieldType; if (type instanceof graphql_composer_1.NullableType) { type = type.type; } if (type instanceof graphql_composer_1.RequiredType) { type = type.type; } if (Array.isArray(type)) { type = type[0]; } return type; } } exports.Parser = Parser; //# sourceMappingURL=Parser.js.map