@coocoon/react-awesome-query-builder
Version:
User-friendly query builder for React. Demo: https://ukrbublik.github.io/react-awesome-query-builder
477 lines (381 loc) • 18.2 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.mongodbFormat = exports._mongodbFormat = void 0;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _stuff = require("../utils/stuff");
var _configUtils = require("../utils/configUtils");
var _ruleUtils = require("../utils/ruleUtils");
var _defaultUtils = require("../utils/defaultUtils");
var _funcUtils = require("../utils/funcUtils");
var _omit = _interopRequireDefault(require("lodash/omit"));
var _pick = _interopRequireDefault(require("lodash/pick"));
var _immutable = require("immutable");
var _default = require("../config/default");
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); 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 = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
// helpers
var isObject = function isObject(v) {
return (0, _typeof2["default"])(v) == "object" && v !== null && !Array.isArray(v);
};
var mongodbFormat = function mongodbFormat(tree, config) {
return _mongodbFormat(tree, config, false);
};
exports.mongodbFormat = mongodbFormat;
var _mongodbFormat = function _mongodbFormat(tree, config) {
var returnErrors = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
//meta is mutable
var meta = {
errors: []
};
var res = formatItem([], tree, config, meta);
if (returnErrors) {
return [res, meta.errors];
} else {
if (meta.errors.length) console.warn("Errors while exporting to MongoDb:", meta.errors);
return res;
}
};
exports._mongodbFormat = _mongodbFormat;
var formatItem = function formatItem(parents, item, config, meta) {
var _not = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
var _canWrapExpr = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;
var _fieldName = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : undefined;
var _value = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : undefined;
if (!item) return undefined;
var type = item.get("type");
if (type === "group" || type === "rule_group") {
return formatGroup(parents, item, config, meta, _not, _canWrapExpr, _fieldName, _value);
} else if (type === "rule") {
return formatRule(parents, item, config, meta, _not, _canWrapExpr, _fieldName, _value);
}
return undefined;
};
var formatGroup = function formatGroup(parents, item, config, meta) {
var _not = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
var _canWrapExpr = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;
var _fieldName = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : undefined;
var _value = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : undefined;
var type = item.get("type");
var properties = item.get("properties") || new _immutable.Map();
var children = item.get("children1");
var canShortMongoQuery = config.settings.canShortMongoQuery;
if (!children) return undefined;
var hasParentRuleGroup = parents.filter(function (it) {
return it.get("type") == "rule_group";
}).length > 0;
var parentPath = parents.filter(function (it) {
return it.get("type") == "rule_group";
}).map(function (it) {
return it.get("properties").get("field");
}).slice(-1).pop();
var realParentPath = hasParentRuleGroup && parentPath;
var groupField = type === "rule_group" ? properties.get("field") : null;
var groupFieldName = formatFieldName(groupField, config, meta, realParentPath);
var groupFieldDef = (0, _configUtils.getFieldConfig)(config, groupField) || {};
var mode = groupFieldDef.mode; //properties.get("mode");
var canHaveEmptyChildren = groupField && mode == "array";
var not = _not ? !properties.get("not") : properties.get("not");
var list = children.map(function (currentChild) {
return formatItem([].concat((0, _toConsumableArray2["default"])(parents), [item]), currentChild, config, meta, not, true, mode == "array" ? function (f) {
return "$$el.".concat(f);
} : undefined);
}).filter(function (currentChild) {
return typeof currentChild !== "undefined";
});
if (!canHaveEmptyChildren && !list.size) return undefined;
var conjunction = properties.get("conjunction");
if (!conjunction) conjunction = (0, _defaultUtils.defaultConjunction)(config);
var conjunctionDefinition = config.conjunctions[conjunction];
var reversedConj = conjunctionDefinition.reversedConj;
if (not && reversedConj) {
conjunction = reversedConj;
conjunctionDefinition = config.conjunctions[conjunction];
}
var mongoConj = conjunctionDefinition.mongoConj;
var resultQuery;
if (list.size == 1) {
resultQuery = list.first();
} else if (list.size > 1) {
var rules = list.toList().toJS();
var canShort = canShortMongoQuery && mongoConj == "$and";
if (canShort) {
resultQuery = rules.reduce(function (acc, rule) {
if (!acc) return undefined;
for (var k in rule) {
if (k[0] == "$") {
acc = undefined;
break;
}
if (acc[k] == undefined) {
acc[k] = rule[k];
} else {
// https://github.com/ukrbublik/react-awesome-query-builder/issues/182
var prev = acc[k],
next = rule[k];
if (!isObject(prev)) {
prev = {
"$eq": prev
};
}
if (!isObject(next)) {
next = {
"$eq": next
};
}
var prevOp = Object.keys(prev)[0],
nextOp = Object.keys(next)[0];
if (prevOp == nextOp) {
acc = undefined;
break;
}
acc[k] = Object.assign({}, prev, next);
}
}
return acc;
}, {});
}
if (!resultQuery) // can't be shorten
resultQuery = (0, _defineProperty2["default"])({}, mongoConj, rules);
}
if (groupField) {
if (mode == "array") {
var totalQuery = {
"$size": groupFieldName
};
var filterQuery = resultQuery ? {
"$size": {
"$filter": {
input: "$" + groupFieldName,
as: "el",
cond: resultQuery
}
}
} : totalQuery;
resultQuery = formatItem(parents, item.set("type", "rule"), config, meta, false, false, function (_f) {
return filterQuery;
}, totalQuery);
resultQuery = {
"$expr": resultQuery
};
} else {
resultQuery = (0, _defineProperty2["default"])({}, groupFieldName, {
"$elemMatch": resultQuery
});
}
}
return resultQuery;
};
var formatRule = function formatRule(parents, item, config, meta) {
var _not = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
var _canWrapExpr = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;
var _fieldName = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : undefined;
var _value = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : undefined;
var properties = item.get("properties") || new _immutable.Map();
var hasParentRuleGroup = parents.filter(function (it) {
return it.get("type") == "rule_group";
}).length > 0;
var parentPath = parents.filter(function (it) {
return it.get("type") == "rule_group";
}).map(function (it) {
return it.get("properties").get("field");
}).slice(-1).pop();
var realParentPath = hasParentRuleGroup && parentPath;
var operator = properties.get("operator");
var operatorOptions = properties.get("operatorOptions");
var field = properties.get("field");
var iValue = properties.get("value");
var iValueSrc = properties.get("valueSrc");
var iValueType = properties.get("valueType");
var asyncListValues = properties.get("asyncListValues");
if (field == null || operator == null || iValue === undefined) return undefined;
var fieldDef = (0, _configUtils.getFieldConfig)(config, field) || {};
var operatorDefinition = (0, _configUtils.getOperatorConfig)(config, operator, field) || {};
var reversedOp = operatorDefinition.reversedOp;
var revOperatorDefinition = (0, _configUtils.getOperatorConfig)(config, reversedOp, field) || {};
var cardinality = (0, _stuff.defaultValue)(operatorDefinition.cardinality, 1);
var not = _not;
if (not && reversedOp) {
var _ref = [reversedOp, operator];
operator = _ref[0];
reversedOp = _ref[1];
var _ref2 = [revOperatorDefinition, operatorDefinition];
operatorDefinition = _ref2[0];
revOperatorDefinition = _ref2[1];
not = false;
}
var fieldName = formatFieldName(field, config, meta, realParentPath); //format value
var valueSrcs = [];
var valueTypes = [];
var useExpr = false;
var fvalue = iValue.map(function (currentValue, ind) {
var valueSrc = iValueSrc ? iValueSrc.get(ind) : null;
var valueType = iValueType ? iValueType.get(ind) : null;
var cValue = (0, _funcUtils.completeValue)(currentValue, valueSrc, config);
var widget = (0, _ruleUtils.getWidgetForFieldOp)(config, field, operator, valueSrc);
var fieldWidgetDef = (0, _omit["default"])((0, _configUtils.getFieldWidgetConfig)(config, field, operator, widget, valueSrc), ["factory"]);
var _formatValue = formatValue(meta, config, cValue, valueSrc, valueType, fieldWidgetDef, fieldDef, realParentPath, operator, operatorDefinition, asyncListValues),
_formatValue2 = (0, _slicedToArray2["default"])(_formatValue, 2),
fv = _formatValue2[0],
fvUseExpr = _formatValue2[1];
if (fv !== undefined) {
useExpr = useExpr || fvUseExpr;
valueSrcs.push(valueSrc);
valueTypes.push(valueType);
}
return fv;
});
if (_fieldName) useExpr = true;
var wrapExpr = useExpr && _canWrapExpr;
var hasUndefinedValues = fvalue.filter(function (v) {
return v === undefined;
}).size > 0;
if (fvalue.size < cardinality || hasUndefinedValues) return undefined;
var formattedValue = cardinality > 1 ? fvalue.toArray() : cardinality == 1 ? fvalue.first() : null; //build rule
var fn = operatorDefinition.mongoFormatOp;
if (!fn) {
meta.errors.push("Operator ".concat(operator, " is not supported"));
return undefined;
}
var args = [_fieldName ? _fieldName(fieldName) : fieldName, operator, _value !== undefined && formattedValue == null ? _value : formattedValue, useExpr, valueSrcs.length > 1 ? valueSrcs : valueSrcs[0], valueTypes.length > 1 ? valueTypes : valueTypes[0], (0, _omit["default"])(operatorDefinition, ["formatOp", "mongoFormatOp", "sqlFormatOp", "jsonLogic", "spelFormatOp"]), operatorOptions, fieldDef];
var ruleQuery = fn.apply(void 0, args);
if (wrapExpr) {
ruleQuery = {
"$expr": ruleQuery
};
}
if (not) {
ruleQuery = {
"$not": ruleQuery
};
}
return ruleQuery;
};
var formatValue = function formatValue(meta, config, currentValue, valueSrc, valueType, fieldWidgetDef, fieldDef, parentPath, operator, operatorDef, asyncListValues) {
if (currentValue === undefined) return [undefined, false];
var ret;
var useExpr = false;
if (valueSrc == "field") {
var _formatRightField = formatRightField(meta, config, currentValue, parentPath);
var _formatRightField2 = (0, _slicedToArray2["default"])(_formatRightField, 2);
ret = _formatRightField2[0];
useExpr = _formatRightField2[1];
} else if (valueSrc == "func") {
var _formatFunc = formatFunc(meta, config, currentValue, parentPath);
var _formatFunc2 = (0, _slicedToArray2["default"])(_formatFunc, 2);
ret = _formatFunc2[0];
useExpr = _formatFunc2[1];
} else {
if (typeof fieldWidgetDef.mongoFormatValue === "function") {
var fn = fieldWidgetDef.mongoFormatValue;
var args = [currentValue, _objectSpread(_objectSpread({}, (0, _pick["default"])(fieldDef, ["fieldSettings", "listValues"])), {}, {
asyncListValues: asyncListValues
}), //useful options: valueFormat for date/time
(0, _omit["default"])(fieldWidgetDef, ["formatValue", "mongoFormatValue", "sqlFormatValue", "jsonLogic", "elasticSearchFormatValue", "spelFormatValue"])];
if (operator) {
args.push(operator);
args.push(operatorDef);
}
ret = fn.apply(void 0, args);
} else {
ret = currentValue;
}
}
return [ret, useExpr];
};
var formatFieldName = function formatFieldName(field, config, meta, parentPath) {
if (!field) return;
var fieldDef = (0, _configUtils.getFieldConfig)(config, field) || {};
var fieldSeparator = config.settings.fieldSeparator;
var fieldParts = Array.isArray(field) ? field : field.split(fieldSeparator);
var fieldName = Array.isArray(field) ? field.join(fieldSeparator) : field; // if (fieldDef.tableName) { // legacy
// const fieldPartsCopy = [...fieldParts];
// fieldPartsCopy[0] = fieldDef.tableName;
// fieldName = fieldPartsCopy.join(fieldSeparator);
// }
if (fieldDef.fieldName) {
fieldName = fieldDef.fieldName;
}
if (parentPath) {
var parentFieldDef = (0, _configUtils.getFieldConfig)(config, parentPath) || {};
var parentFieldName = parentPath;
if (parentFieldDef.fieldName) {
parentFieldName = parentFieldDef.fieldName;
}
if (fieldName.indexOf(parentFieldName + ".") == 0) {
fieldName = fieldName.slice((parentFieldName + ".").length);
} else {
meta.errors.push("Can't cut group ".concat(parentFieldName, " from field ").concat(fieldName));
}
}
return fieldName;
};
var formatRightField = function formatRightField(meta, config, rightField, parentPath) {
var fieldSeparator = config.settings.fieldSeparator;
var ret;
var useExpr = true;
if (rightField) {
var rightFieldDefinition = (0, _configUtils.getFieldConfig)(config, rightField) || {};
var fieldParts = Array.isArray(rightField) ? rightField : rightField.split(fieldSeparator);
var _fieldKeys = (0, _ruleUtils.getFieldPath)(rightField, config);
var fieldPartsLabels = (0, _ruleUtils.getFieldPathLabels)(rightField, config);
var fieldFullLabel = fieldPartsLabels ? fieldPartsLabels.join(fieldSeparator) : null;
var formatFieldFn = config.settings.formatField || _default.settings.formatField;
var rightFieldName = formatFieldName(rightField, config, meta, parentPath);
var formattedField = formatFieldFn(rightFieldName, fieldParts, fieldFullLabel, rightFieldDefinition, config, false);
ret = "$" + formattedField;
}
return [ret, useExpr];
};
var formatFunc = function formatFunc(meta, config, currentValue, parentPath) {
var useExpr = true;
var ret;
var funcKey = currentValue.get("func");
var args = currentValue.get("args");
var funcConfig = (0, _configUtils.getFuncConfig)(config, funcKey);
var funcName = funcConfig.mongoFunc || funcKey;
var mongoArgsAsObject = funcConfig.mongoArgsAsObject;
var formattedArgs = {};
var argsCnt = 0;
var lastArg = undefined;
for (var argKey in funcConfig.args) {
var argConfig = funcConfig.args[argKey];
var fieldDef = (0, _configUtils.getFieldConfig)(config, argConfig);
var argVal = args ? args.get(argKey) : undefined;
var argValue = argVal ? argVal.get("value") : undefined;
var argValueSrc = argVal ? argVal.get("valueSrc") : undefined;
var argAsyncListValues = argVal ? argVal.get("asyncListValues") : undefined;
var widget = (0, _ruleUtils.getWidgetForFieldOp)(config, fieldDef, null, argValueSrc);
var fieldWidgetDef = (0, _omit["default"])((0, _configUtils.getFieldWidgetConfig)(config, fieldDef, null, widget, argValueSrc), ["factory"]);
var _formatValue3 = formatValue(meta, config, argValue, argValueSrc, argConfig.type, fieldWidgetDef, fieldDef, parentPath, null, null, argAsyncListValues),
_formatValue4 = (0, _slicedToArray2["default"])(_formatValue3, 2),
formattedArgVal = _formatValue4[0],
_argUseExpr = _formatValue4[1];
if (argValue != undefined && formattedArgVal === undefined) {
meta.errors.push("Can't format value of arg ".concat(argKey, " for func ").concat(funcKey));
return [undefined, false];
}
argsCnt++;
if (formattedArgVal !== undefined) {
// skip optional in the end
formattedArgs[argKey] = formattedArgVal;
lastArg = formattedArgVal;
}
}
if (typeof funcConfig.mongoFormatFunc === "function") {
var fn = funcConfig.mongoFormatFunc;
var _args = [formattedArgs];
ret = fn.apply(void 0, _args);
} else if (funcConfig.mongoFormatFunc === null) {
meta.errors.push("Functon ".concat(funcName, " is not supported"));
return [undefined, false];
} else {
if (mongoArgsAsObject) ret = (0, _defineProperty2["default"])({}, funcName, formattedArgs);else if (argsCnt == 1 && lastArg !== undefined) ret = (0, _defineProperty2["default"])({}, funcName, lastArg);else ret = (0, _defineProperty2["default"])({}, funcName, Object.values(formattedArgs));
}
return [ret, useExpr];
};