UNPKG

@grapi/server

Version:

Grapi Schema Generator For GraphQL Server

290 lines (289 loc) 13.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const __1 = require(".."); const constants_1 = require("../constants"); const type_1 = require("../dataModel/type"); const lodash_1 = require("../lodash"); const constants_2 = require("./constants"); const utils_1 = require("./utils"); const UNDERSCORE = '_'; class WhereInputPlugin { visitModel(model, context) { const { root } = context; const modelWhereInputName = this.getWhereInputName(model); const whereInput = `input ${modelWhereInputName} { OR: [${modelWhereInputName}!] AND: [${modelWhereInputName}!] ${this.createWhereFilter(root, model.getFields())} }`; root.addInput(whereInput); const modelWhereUniqueInputName = this.getWhereUniqueInputName(model); const whereUniqueInput = `input ${modelWhereUniqueInputName} { ${this.createWhereUniqueFilter(model.getName(), model.getFields())} }`; root.addInput(whereUniqueInput); } getWhereInputName(model) { return `${model.getNamings().capitalSingular}WhereInput`; } getWhereUniqueInputName(model) { return `${model.getNamings().capitalSingular}WhereUniqueInput`; } parseUniqueWhere(where) { if ((0, lodash_1.isEmpty)(where)) { throw new Error('You provided an invalid argument for the where selector on Entity. Please provide exactly one unique field and value.'); } return (0, lodash_1.mapValues)(where, value => { return { [__1.Operator.eq]: value }; }); } parseWhere(where, model) { return WhereInputPlugin.parseWhereIterate(where, model); } static parseWhereIterate(where, model) { return (0, lodash_1.reduce)(where, (result, value, key) => { if (key === __1.Operator.or || key === __1.Operator.and) { value = (0, lodash_1.map)(value, (where) => { return this.parseWhereIterate(where, model); }); return { [key]: value }; } let { operator } = WhereInputPlugin.getNameAndOperator(key); const { fieldName } = WhereInputPlugin.getNameAndOperator(key); const field = model.getField(fieldName); if (field && field.getType() === type_1.DataModelType.RELATION) { const relationTo = field.getRelationTo(); const metadataField = (0, utils_1.parseRelationConfig)(field.getRelationConfig()); let filter; if (field.isList()) { if ((0, lodash_1.size)(value) > 1) { throw new Error(`There can be only one input field named Filter${field.getTypename()}`); } const { some, none, every } = value; if (some) { filter = "some"; } else if (none) { filter = "none"; } else { filter = "every"; } value = some || none || every; } result[fieldName] = { filters: WhereInputPlugin.parseWhereIterate(value, relationTo), sourceKey: (0, lodash_1.get)(model.getMetadata(constants_1.MODEL_DIRECTIVE), constants_1.MODEL_DIRECTIVE_SOURCE_KEY), targetKey: (0, lodash_1.get)(relationTo.getMetadata(constants_1.MODEL_DIRECTIVE), constants_1.MODEL_DIRECTIVE_SOURCE_KEY), relation: { foreignKey: (0, lodash_1.get)(metadataField, `foreignKey`), source: model.getName(), target: relationTo.getName(), side: (0, lodash_1.get)(metadataField, `side`), list: field.isList(), filter, ship: field.getRelation(), type: field.getRelationType() } }; return result; } if (result[fieldName]) { throw new Error(`There can be only one input field named ${fieldName}_${operator}`); } if (field.isList()) { if ((0, lodash_1.size)(value) > 1) { throw new Error(`There can be only one input field named Filter${field.getTypename()}`); } const { has, hasNot } = value; if (has) { operator = __1.Operator.all; } else { operator = __1.Operator.notIn; } value = has || hasNot || []; } result[fieldName] = { [operator]: value }; return result; }, {}); } static getNameAndOperator(field) { const lastUnderscoreIndex = field.lastIndexOf(UNDERSCORE); if (lastUnderscoreIndex < 0) { return { fieldName: field, operator: __1.Operator.eq, }; } const operator = field.slice(lastUnderscoreIndex + 1); const validOperator = __1.Operator[operator]; if (!validOperator) { throw new Error(`Operator ${operator} no support`); } const fieldName = field.slice(0, lastUnderscoreIndex); return { fieldName, operator: validOperator }; } createWhereFilter(root, fields) { let inputFields = []; (0, lodash_1.forEach)(fields, (field, name) => { const typeName = field.getTypename(); if (field.isList()) { switch (field.getType()) { case type_1.DataModelType.STRING: case type_1.DataModelType.INT: case type_1.DataModelType.FLOAT: case type_1.DataModelType.ENUM: case type_1.DataModelType.ID: root.addInput(`input FilterScalar${typeName}List { ${"has"}: [ ${typeName} ! ] ${"hasNot"}: [ ${typeName} ! ] }`); inputFields.push({ fieldName: name, type: `FilterScalar${typeName}List`, }); break; case type_1.DataModelType.CUSTOM_SCALAR: root.addInput(`input FilterScalar${typeName}List { ${"has"}: [ ${typeName} ! ] ${"hasNot"}: [ ${typeName} ! ] }`); inputFields = WhereInputPlugin.createWhereFilterListCustomScalars(inputFields, typeName, name); break; case type_1.DataModelType.RELATION: root.addInput(`input Filter${typeName} { some: ${typeName}WhereInput every: ${typeName}WhereInput none: ${typeName}WhereInput }`); inputFields.push({ fieldName: name, type: `Filter${typeName}`, }); break; } } else { switch (field.getType()) { case type_1.DataModelType.STRING: inputFields.push(...WhereInputPlugin.parseEqFilter(name, typeName)); inputFields.push(...WhereInputPlugin.parseContainsFilter(name, typeName)); inputFields.push(...WhereInputPlugin.parseInFilter(name, typeName)); break; case type_1.DataModelType.INT: inputFields.push(...WhereInputPlugin.parseEqFilter(name, typeName)); inputFields.push(...WhereInputPlugin.parseGtLtInFilter(name, typeName)); inputFields.push({ fieldName: `${name}_between`, type: constants_2.inputIntBetweenName, }); break; case type_1.DataModelType.FLOAT: inputFields.push(...WhereInputPlugin.parseEqFilter(name, typeName)); inputFields.push(...WhereInputPlugin.parseGtLtInFilter(name, typeName)); inputFields.push({ fieldName: `${name}_between`, type: constants_2.inputFloatBetweenName, }); break; case type_1.DataModelType.ENUM: inputFields.push(...WhereInputPlugin.parseEqFilter(name, typeName)); inputFields.push(...WhereInputPlugin.parseContainsFilter(name, 'String')); break; case type_1.DataModelType.ID: inputFields.push(...WhereInputPlugin.parseEqFilter(name, typeName)); inputFields.push(...WhereInputPlugin.parseInFilter(name, typeName)); break; case type_1.DataModelType.BOOLEAN: inputFields.push(...WhereInputPlugin.parseEqFilter(name, typeName)); break; case type_1.DataModelType.CUSTOM_SCALAR: inputFields = WhereInputPlugin.createWhereFilterCustomScalars(inputFields, typeName, name); break; case type_1.DataModelType.RELATION: inputFields.push({ fieldName: name, type: `${typeName}WhereInput`, }); break; } } }); return inputFields.map(({ fieldName, type }) => `${fieldName}: ${type}`).join(' '); } static createWhereFilterListCustomScalars(inputFields, typeName, name) { switch (typeName) { case type_1.DataModelType.URL: case type_1.DataModelType.EMAIL: case type_1.DataModelType.JSON: inputFields.push({ fieldName: name, type: `FilterScalar${typeName}List`, }); break; case type_1.DataModelType.DATE_TIME: break; } return inputFields; } static createWhereFilterCustomScalars(inputFields, typeName, name) { switch (typeName) { case type_1.DataModelType.URL: case type_1.DataModelType.EMAIL: inputFields.push(...WhereInputPlugin.parseEqFilter(name, typeName)); inputFields.push(...WhereInputPlugin.parseContainsFilter(name, typeName)); break; case type_1.DataModelType.DATE_TIME: inputFields.push(...WhereInputPlugin.parseEqFilter(name, typeName)); inputFields.push(...WhereInputPlugin.parseGtLtInFilter(name, typeName)); inputFields.push({ fieldName: `${name}_between`, type: constants_2.inputDateTimeBetweenName, }); break; case type_1.DataModelType.JSON: inputFields.push(...WhereInputPlugin.parseObjectFilter(name, typeName)); break; } return inputFields; } createWhereUniqueFilter(modelName, fields) { const inputFields = []; (0, lodash_1.forEach)(fields, (field, name) => { if (field.isUnique()) { inputFields.push({ fieldName: name, type: field.getTypename(), }); } }); if ((0, lodash_1.isEmpty)(fields)) { throw new Error(`no unique field find in model ${modelName}`); } return inputFields.map(({ fieldName, type }) => `${fieldName}: ${type}`).join(' '); } static parseEqFilter(name, type) { return [{ fieldName: name, type }, { fieldName: `${name}_eq`, type }, { fieldName: `${name}_neq`, type }]; } static parseContainsFilter(name, type) { return [{ fieldName: `${name}_contains`, type }, { fieldName: `${name}_notcontains`, type }]; } static parseInFilter(name, type) { return [ { fieldName: `${name}_in`, type: `[ ${type} ]` } ]; } static parseGtLtInFilter(name, type) { return [ { fieldName: `${name}_gt`, type }, { fieldName: `${name}_gte`, type }, { fieldName: `${name}_lt`, type }, { fieldName: `${name}_lte`, type }, { fieldName: `${name}_in`, type: `[ ${type} ]` } ]; } static parseObjectFilter(name, type) { return [ { fieldName: `${name}_object`, type } ]; } } exports.default = WhereInputPlugin;