@grapi/server
Version:
Grapi Schema Generator For GraphQL Server
290 lines (289 loc) • 13.1 kB
JavaScript
;
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;