graphql-compose-mongoose
Version:
Plugin for `graphql-compose` which derive a graphql types from a mongoose model.
158 lines (127 loc) • 5.71 kB
JavaScript
;
exports.__esModule = true;
exports.addFilterOperators = addFilterOperators;
exports.processFilterOperators = processFilterOperators;
exports._prepareAndOrFilter = _prepareAndOrFilter;
exports._createOperatorsField = _createOperatorsField;
exports.OPERATORS_FIELDNAME = void 0;
var _graphql = require("graphql-compose/lib/graphql");
var _utils = require("../../utils");
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const availableOperators = ['gt', 'gte', 'lt', 'lte', 'ne', 'in[]', 'nin[]'];
const OPERATORS_FIELDNAME = '_operators';
exports.OPERATORS_FIELDNAME = OPERATORS_FIELDNAME;
function addFilterOperators(itc, model, opts) {
if (!{}.hasOwnProperty.call(opts, 'operators') || opts.operators !== false) {
_createOperatorsField(itc, `Operators${opts.filterTypeName || ''}`, model, opts.operators || {});
}
itc.addFields({
OR: [itc.getTypeNonNull()],
AND: [itc.getTypeNonNull()]
});
}
function processFilterOperators(filter) {
if (!filter) return filter;
_prepareAndOrFilter(filter);
if (filter[OPERATORS_FIELDNAME]) {
const operatorFields = filter[OPERATORS_FIELDNAME];
Object.keys(operatorFields).forEach(fieldName => {
const fieldOperators = _objectSpread({}, operatorFields[fieldName]);
const criteria = {};
Object.keys(fieldOperators).forEach(operatorName => {
if (Array.isArray(fieldOperators[operatorName])) {
criteria[`$${operatorName}`] = fieldOperators[operatorName].map(v => processFilterOperators(v));
} else {
criteria[`$${operatorName}`] = processFilterOperators(fieldOperators[operatorName]);
}
});
if (Object.keys(criteria).length > 0) {
// eslint-disable-next-line
filter[fieldName] = criteria;
}
}); // eslint-disable-next-line no-param-reassign
delete filter[OPERATORS_FIELDNAME];
}
return filter;
}
function _prepareAndOrFilter(filter) {
/* eslint-disable no-param-reassign */
if (!filter.OR && !filter.AND) return;
const {
OR,
AND
} = filter;
if (OR) {
const $or = OR.map(d => {
processFilterOperators(d);
return d;
});
filter.$or = $or;
delete filter.OR;
}
if (AND) {
const $and = AND.map(d => {
processFilterOperators(d);
return d;
});
filter.$and = $and;
delete filter.AND;
}
/* eslint-enable no-param-reassign */
}
function _createOperatorsField(itc, typeName, model, operatorsOpts) {
const operatorsITC = itc.schemaComposer.getOrCreateITC(typeName, tc => {
tc.setDescription('For performance reason this type contains only *indexed* fields.');
}); // if `opts.resolvers.[resolverName].filter.operators` is empty and not disabled via `false`
// then fill it up with indexed fields
const indexedFields = (0, _utils.getIndexedFieldNamesForGraphQL)(model);
if (Object.keys(operatorsOpts).length === 0) {
indexedFields.forEach(fieldName => {
operatorsOpts[fieldName] = availableOperators; // eslint-disable-line
});
}
itc.getFieldNames().forEach(fieldName => {
if (operatorsOpts[fieldName] && operatorsOpts[fieldName] !== false) {
const fields = {};
let operators;
if (operatorsOpts[fieldName] && Array.isArray(operatorsOpts[fieldName])) {
operators = operatorsOpts[fieldName];
} else {
operators = availableOperators;
}
operators.forEach(operatorName => {
const fc = itc.getFieldConfig(fieldName); // unwrap from GraphQLNonNull and GraphQLList, if present
const namedType = (0, _graphql.getNamedType)(fc.type);
if (namedType) {
if (operatorName.slice(-2) === '[]') {
// wrap with GraphQLList, if operator required this with `[]`
const newName = operatorName.slice(0, -2);
fields[newName] = _objectSpread({}, fc, {
type: [namedType]
});
} else {
fields[operatorName] = _objectSpread({}, fc, {
type: namedType
});
}
}
});
if (Object.keys(fields).length > 0) {
const operatorTypeName = `${(0, _utils.upperFirst)(fieldName)}${typeName}`;
const operatorITC = itc.schemaComposer.getOrCreateITC(operatorTypeName, tc => {
tc.setFields(fields);
});
operatorsITC.setField(fieldName, operatorITC);
}
}
}); // add to main filterITC if was added some fields
if (operatorsITC.getFieldNames().length > 0) {
itc.setField(OPERATORS_FIELDNAME, {
type: operatorsITC,
description: 'List of *indexed* fields that can be filtered via operators.'
});
}
return operatorsITC;
}