UNPKG

@react-query-builder-express/core

Version:
1,304 lines (1,285 loc) 58 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.loadFromSpel = exports._loadFromSpel = 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 _spel2js = require("spel2js"); var _uuid = _interopRequireDefault(require("../utils/uuid")); var _configUtils = require("../utils/configUtils"); var _ruleUtils = require("../utils/ruleUtils"); var _tree = require("./tree"); var _defaultUtils = require("../utils/defaultUtils"); var _stuff = require("../utils/stuff"); var _moment = _interopRequireDefault(require("moment")); var _spel = require("../export/spel"); function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/expressions.html#expressions // spel type => raqb type var SpelPrimitiveTypes = { number: "number", string: "text", "boolean": "boolean", "null": "null" // should not be }; // spel class => raqb type var SpelPrimitiveClasses = { String: "text" }; var ListValueType = "multiselect"; var isFuncableProperty = function isFuncableProperty(p) { return ["length"].includes(p); }; var isObject = function isObject(v) { return (0, _typeof2["default"])(v) == "object" && v !== null && !Array.isArray(v); }; var loadFromSpel = exports.loadFromSpel = function loadFromSpel(logicTree, config) { return _loadFromSpel(logicTree, config, true); }; var _loadFromSpel = exports._loadFromSpel = function _loadFromSpel(spelStr, config) { var returnErrors = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; //meta is mutable var meta = { errors: [] }; var extendedConfig = (0, _configUtils.extendConfig)(config, undefined, false); var conv = buildConv(extendedConfig); var compiledExpression; var convertedObj; var jsTree = undefined; try { var compileRes = _spel2js.SpelExpressionEvaluator.compile(spelStr); compiledExpression = compileRes._compiledExpression; } catch (e) { meta.errors.push(e); } if (compiledExpression) { //logger.debug("compiledExpression:", compiledExpression); convertedObj = postprocessCompiled(compiledExpression, meta); _stuff.logger.debug("convertedObj:", convertedObj, meta); jsTree = convertToTree(convertedObj, conv, extendedConfig, meta); if (jsTree && jsTree.type != "group" && jsTree.type != "switch_group") { jsTree = wrapInDefaultConj(jsTree, extendedConfig, convertedObj["not"]); } _stuff.logger.debug("jsTree:", jsTree); } var immTree = jsTree ? (0, _tree.loadTree)(jsTree) : undefined; if (returnErrors) { return [immTree, meta.errors]; } else { if (meta.errors.length) console.warn("Errors while importing from SpEL:", meta.errors); return immTree; } }; var postprocessCompiled = function postprocessCompiled(expr, meta) { var parentExpr = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var type = expr.getType(); var children = expr.getChildren().map(function (child) { return postprocessCompiled(child, meta, expr); }); // flatize OR/AND if (type == "op-or" || type == "op-and") { children = children.reduce(function (acc, child) { var canFlatize = child.type == type && !child.not; var flat = canFlatize ? child.children : [child]; return [].concat((0, _toConsumableArray2["default"])(acc), (0, _toConsumableArray2["default"])(flat)); }, []); } // unwrap NOT if (type == "op-not") { if (children.length != 1) { meta.errors.push("Operator NOT should have 1 child, but got ".concat(children.length, "}")); } return _objectSpread(_objectSpread({}, children[0]), {}, { not: !(children[0].not || false) }); } if (type == "compound") { // remove `.?[true]` children = children.filter(function (child) { var isListFix = child.type == "selection" && child.children.length == 1 && child.children[0].type == "boolean" && child.children[0].val == true; return !isListFix; }); // aggregation // eg. `results.?[product == 'abc'].length` var selection = children.find(function (child) { return child.type == "selection"; }); if (selection && selection.children.length != 1) { meta.errors.push("Selection should have 1 child, but got ".concat(selection.children.length)); } var filter = selection ? selection.children[0] : null; var lastChild = children[children.length - 1]; var isSize = lastChild.type == "method" && lastChild.val.methodName == "size" || lastChild.type == "!func" && lastChild.methodName == "size"; var isLength = lastChild.type == "property" && lastChild.val == "length"; var sourceParts = children.filter(function (child) { return child !== selection && child !== lastChild; }); var source = { type: "compound", children: sourceParts }; var isAggr = (isSize || isLength) && convertPath(sourceParts) != null; if (isAggr) { return { type: "!aggr", filter: filter, source: source }; } // remove `#this`, `#root` children = children.filter(function (child) { var isThis = child.type == "variable" && child.val == "this"; var isRoot = child.type == "variable" && child.val == "root"; return !(isThis || isRoot); }); // indexer children = children.map(function (child) { if (child.type == "indexer" && child.children.length == 1) { return { type: "indexer", val: child.children[0].val, itype: child.children[0].type }; } else { return child; } }); // method // if (lastChild.type == "method") { // // seems like obsolete code! // debugger // const obj = children.filter(child => // child !== lastChild // ); // return { // type: "!func", // obj, // methodName: lastChild.val.methodName, // args: lastChild.val.args // }; // } // !func if (lastChild.type == "!func") { var ret = {}; var curr = ret; do { var _lastChild, _lastChild2; Object.assign(curr, lastChild); children = children.filter(function (child) { return child !== lastChild; }); lastChild = children[children.length - 1]; if (((_lastChild2 = lastChild) === null || _lastChild2 === void 0 ? void 0 : _lastChild2.type) == "!func") { curr.obj = {}; curr = curr.obj; } else { if (children.length > 1) { curr.obj = { type: "compound", children: children }; } else { curr.obj = lastChild; } } } while (((_lastChild = lastChild) === null || _lastChild === void 0 ? void 0 : _lastChild.type) == "!func"); return ret; } } // getRaw || getValue var val; try { if (expr.getRaw) { // use my fork val = expr.getRaw(); } else if (expr.getValue.length == 0) { // getValue not requires context arg -> can use val = expr.getValue(); } } catch (e) { _stuff.logger.error("[spel2js] Error in getValue()", e); } // ternary if (type == "ternary") { val = flatizeTernary(children); } // convert method/function args if ((0, _typeof2["default"])(val) === "object" && val !== null) { if (val.methodName || val.functionName) { val.args = val.args.map(function (child) { return postprocessCompiled(child, meta, expr); }); } } // convert list if (type == "list") { val = val.map(function (item) { return postprocessCompiled(item, meta, expr); }); // fix whole expression wrapped in `{}` if (!parentExpr && val.length == 1) { return val[0]; } } // convert constructor if (type == "constructorref") { var qid = children.find(function (child) { return child.type == "qualifiedidentifier"; }); var cls = qid === null || qid === void 0 ? void 0 : qid.val; if (!cls) { meta.errors.push("Can't find qualifiedidentifier in constructorref children: ".concat(JSON.stringify(children))); return undefined; } var args = children.filter(function (child) { return child.type != "qualifiedidentifier"; }); return { type: "!new", cls: cls, args: args }; } // convert type if (type == "typeref") { var _qid = children.find(function (child) { return child.type == "qualifiedidentifier"; }); var _cls = _qid === null || _qid === void 0 ? void 0 : _qid.val; if (!_cls) { meta.errors.push("Can't find qualifiedidentifier in typeref children: ".concat(JSON.stringify(children))); return undefined; } var _args = children.filter(function (child) { return child.type != "qualifiedidentifier"; }); return { type: "!type", cls: _cls }; } // convert function/method if (type == "function" || type == "method") { // `foo()` is method, `#foo()` is function // let's use common property `methodName` and just add `isVar` for function var _val = val, functionName = _val.functionName, methodName = _val.methodName, _args2 = _val.args; return { type: "!func", methodName: functionName || methodName, isVar: type == "function", args: _args2 }; } return { type: type, children: children, val: val }; }; var flatizeTernary = function flatizeTernary(children) { var flat = []; function _processTernaryChildren(tern) { var _tern = (0, _slicedToArray2["default"])(tern, 3), cond = _tern[0], if_val = _tern[1], else_val = _tern[2]; flat.push([cond, if_val]); if ((else_val === null || else_val === void 0 ? void 0 : else_val.type) == "ternary") { _processTernaryChildren(else_val.children); } else { flat.push([undefined, else_val]); } } _processTernaryChildren(children); return flat; }; var buildConv = function buildConv(config) { var operators = {}; var _loop = function _loop(opKey) { var opConfig = config.operators[opKey]; if (opConfig.spelOps) { // examples: "==", "eq", ".contains", "matches" (can be used for starts_with, ends_with) opConfig.spelOps.forEach(function (spelOp) { var opk = spelOp; // + "/" + getOpCardinality(opConfig); if (!operators[opk]) operators[opk] = []; operators[opk].push(opKey); }); } else if (opConfig.spelOp) { var opk = opConfig.spelOp; // + "/" + getOpCardinality(opConfig); if (!operators[opk]) operators[opk] = []; operators[opk].push(opKey); } else { _stuff.logger.log("[spel] No spelOp for operator ".concat(opKey)); } }; for (var opKey in config.operators) { _loop(opKey); } var conjunctions = {}; for (var conjKey in config.conjunctions) { var conjunctionDefinition = config.conjunctions[conjKey]; var ck = conjunctionDefinition.spelConj || conjKey.toLowerCase(); conjunctions[ck] = conjKey; } var funcs = {}; var _iterator = _createForOfIteratorHelper((0, _configUtils.iterateFuncs)(config)), _step; try { var _loop2 = function _loop2() { var _step$value = (0, _slicedToArray2["default"])(_step.value, 2), funcPath = _step$value[0], funcConfig = _step$value[1]; var fks = []; var spelFunc = funcConfig.spelFunc; if (typeof spelFunc === "string") { var optionalArgs = Object.keys(funcConfig.args || {}).reverse().filter(function (argKey) { return !!funcConfig.args[argKey].isOptional || funcConfig.args[argKey].defaultValue != undefined; }); var funcSignMain = spelFunc.replace(/\${(\w+)}/g, function (_, _k) { return "?"; }); var funcSignsOptional = optionalArgs.reduce(function (acc, argKey) { return [].concat((0, _toConsumableArray2["default"])(acc), [[argKey].concat((0, _toConsumableArray2["default"])(acc[acc.length - 1] || []))]); }, []).map(function (optionalArgKeys) { return spelFunc.replace(/(?:, )?\${(\w+)}/g, function (found, a) { return optionalArgKeys.includes(a) ? "" : found; }).replace(/\${(\w+)}/g, function (_, _k) { return "?"; }); }); fks = [funcSignMain].concat((0, _toConsumableArray2["default"])(funcSignsOptional)); } var _iterator3 = _createForOfIteratorHelper(fks), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var _fk = _step3.value; if (!funcs[_fk]) funcs[_fk] = []; funcs[_fk].push(funcPath); } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } }; for (_iterator.s(); !(_step = _iterator.n()).done;) { _loop2(); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } var valueFuncs = {}; for (var w in config.widgets) { var widgetDef = config.widgets[w]; var spelImportFuncs = widgetDef.spelImportFuncs, type = widgetDef.type; if (spelImportFuncs) { var _iterator2 = _createForOfIteratorHelper(spelImportFuncs), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var fk = _step2.value; if (typeof fk === "string") { var fs = fk.replace(/\${(\w+)}/g, function (_, k) { return "?"; }); var argsOrder = (0, _toConsumableArray2["default"])(fk.matchAll(/\${(\w+)}/g)).map(function (_ref) { var _ref2 = (0, _slicedToArray2["default"])(_ref, 2), _ = _ref2[0], k = _ref2[1]; return k; }); if (!valueFuncs[fs]) valueFuncs[fs] = []; valueFuncs[fs].push({ w: w, argsOrder: argsOrder }); } } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } } } var opFuncs = {}; for (var op in config.operators) { var opDef = config.operators[op]; var spelOp = opDef.spelOp; if (spelOp !== null && spelOp !== void 0 && spelOp.includes("${0}")) { var _fs = spelOp.replace(/\${(\w+)}/g, function (_, k) { return "?"; }); var _argsOrder = (0, _toConsumableArray2["default"])(spelOp.matchAll(/\${(\w+)}/g)).map(function (_ref3) { var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2), _ = _ref4[0], k = _ref4[1]; return k; }); if (!opFuncs[_fs]) opFuncs[_fs] = []; opFuncs[_fs].push({ op: op, argsOrder: _argsOrder }); } } // Special .compareTo() var compareToSS = _spel.compareToSign.replace(/\${(\w+)}/g, function (_, k) { return "?"; }); opFuncs[compareToSS] = [{ op: "!compare", argsOrder: ["0", "1"] }]; return { operators: operators, conjunctions: conjunctions, funcs: funcs, valueFuncs: valueFuncs, opFuncs: opFuncs }; }; var convertToTree = function convertToTree(spel, conv, config, meta) { var _spel$_groupField; var parentSpel = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; if (!spel) return undefined; spel._groupField = (_spel$_groupField = spel._groupField) !== null && _spel$_groupField !== void 0 ? _spel$_groupField : parentSpel === null || parentSpel === void 0 ? void 0 : parentSpel._groupField; var res, canParseAsArg = true; if (spel.type.indexOf("op-") === 0 || spel.type === "matches") { res = convertOp(spel, conv, config, meta, parentSpel); } else if (spel.type == "!aggr") { var _groupFilter; var groupFieldValue = convertToTree(spel.source, conv, config, meta, spel); spel._groupField = groupFieldValue === null || groupFieldValue === void 0 ? void 0 : groupFieldValue.value; var groupFilter = convertToTree(spel.filter, conv, config, meta, spel); if (((_groupFilter = groupFilter) === null || _groupFilter === void 0 ? void 0 : _groupFilter.type) == "rule") { groupFilter = wrapInDefaultConj(groupFilter, config, spel.filter.not); } res = { groupFilter: groupFilter, groupFieldValue: groupFieldValue }; if (!parentSpel) { // !aggr can't be in root, it should be compared with something res = undefined; meta.errors.push("Unexpected !aggr in root"); canParseAsArg = false; } } else if (spel.type == "ternary") { var children1 = {}; spel.val.forEach(function (v) { var _v = (0, _slicedToArray2["default"])(v, 2), cond = _v[0], val = _v[1]; var caseI = buildCase(cond, val, conv, config, meta, spel); if (caseI) { children1[caseI.id] = caseI; } }); res = { type: "switch_group", id: (0, _uuid["default"])(), children1: children1, properties: {} }; } if (!res && canParseAsArg) { res = convertArg(spel, conv, config, meta, parentSpel); } if (res && !res.type && !parentSpel) { // res is not a rule, it's value at root // try to parse whole `"1"` as ternary var sw = buildSimpleSwitch(spel, conv, config, meta); if (sw) { res = sw; } else { res = undefined; meta.errors.push("Can't convert rule of type ".concat(spel.type, ", it looks like var/literal")); } } return res; }; var convertOp = function convertOp(spel, conv, config, meta) { var parentSpel = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; var res; var op = spel.type.startsWith("op-") ? spel.type.slice("op-".length) : spel.type; // unary var isUnary = (op == "minus" || op == "plus") && spel.children.length == 1; if (isUnary) { var negative = spel.negative; if (op == "minus") { negative = !negative; } spel.children[0].negative = negative; return convertToTree(spel.children[0], conv, config, meta, parentSpel); } // between var isBetweenNormal = op == "and" && spel.children.length == 2 && spel.children[0].type == "op-ge" && spel.children[1].type == "op-le"; var isBetweenRev = op == "or" && spel.children.length == 2 && spel.children[0].type == "op-lt" && spel.children[1].type == "op-gt"; var isBetween = isBetweenNormal || isBetweenRev; if (isBetween) { var _spel$children$0$chil = (0, _slicedToArray2["default"])(spel.children[0].children, 2), left = _spel$children$0$chil[0], from = _spel$children$0$chil[1]; var _spel$children$1$chil = (0, _slicedToArray2["default"])(spel.children[1].children, 2), right = _spel$children$1$chil[0], to = _spel$children$1$chil[1]; var isSameSource = compareArgs(left, right, spel, conv, config, meta, parentSpel); if (isSameSource) { var _fromValue = from.val; var _toValue = to.val; var oneSpel = { type: "op-between", children: [left, from, to], not: isBetweenRev }; oneSpel._groupField = parentSpel === null || parentSpel === void 0 ? void 0 : parentSpel._groupField; return convertOp(oneSpel, conv, config, meta, parentSpel); } } // find op var opKeys = conv.operators[op]; if (op == "eq" && spel.children[1].type == "null") { opKeys = ["is_null"]; } else if (op == "ne" && spel.children[1].type == "null") { opKeys = ["is_not_null"]; } else if (op == "le" && spel.children[1].type == "string" && spel.children[1].val == "") { opKeys = ["is_empty"]; } else if (op == "gt" && spel.children[1].type == "string" && spel.children[1].val == "") { opKeys = ["is_not_empty"]; } else if (op == "between") { opKeys = ["between"]; } // convert children var convertChildren = function convertChildren() { var _newChildren; var newChildren = spel.children.map(function (child) { return convertToTree(child, conv, config, meta, spel); }); if (newChildren.length >= 2 && ((_newChildren = newChildren) === null || _newChildren === void 0 || (_newChildren = _newChildren[0]) === null || _newChildren === void 0 ? void 0 : _newChildren.type) == "!compare") { newChildren = newChildren[0].children; } return newChildren; }; if (op == "and" || op == "or") { var children1 = {}; var vals = convertChildren(); vals.forEach(function (v) { if (v) { var id = (0, _uuid["default"])(); v.id = id; if (v.type != undefined) { children1[id] = v; } else { meta.errors.push("Bad item in AND/OR: ".concat(JSON.stringify(v))); } } }); res = { type: "group", id: (0, _uuid["default"])(), children1: children1, properties: { conjunction: conv.conjunctions[op], not: spel.not } }; } else if (opKeys) { var _fieldObj$groupFieldV, _convertedArgs, _opConfig; var _vals = convertChildren(); var fieldObj = _vals[0]; var convertedArgs = _vals.slice(1); var groupField = fieldObj === null || fieldObj === void 0 || (_fieldObj$groupFieldV = fieldObj.groupFieldValue) === null || _fieldObj$groupFieldV === void 0 ? void 0 : _fieldObj$groupFieldV.value; var opArg = (_convertedArgs = convertedArgs) === null || _convertedArgs === void 0 ? void 0 : _convertedArgs[0]; var opKey = opKeys[0]; if (opKeys.length > 1) { var _vals$, _vals$2; var valueType = ((_vals$ = _vals[0]) === null || _vals$ === void 0 ? void 0 : _vals$.valueType) || ((_vals$2 = _vals[1]) === null || _vals$2 === void 0 ? void 0 : _vals$2.valueType); //todo: it's naive, use valueType var field = fieldObj === null || fieldObj === void 0 ? void 0 : fieldObj.value; var widgets = opKeys.map(function (op) { return { op: op, widget: (0, _ruleUtils.getWidgetForFieldOp)(config, field, op) }; }); _stuff.logger.warn("[spel] Spel operator ".concat(op, " can be mapped to ").concat(opKeys, "."), "widgets:", widgets, "vals:", _vals, "valueType=", valueType); if (op == "eq" || op == "ne") { var ws = widgets.find(function (_ref5) { var op = _ref5.op, widget = _ref5.widget; return widget && widget != "field"; }); if (ws) { opKey = ws.op; } } } // some/all/none if (fieldObj !== null && fieldObj !== void 0 && fieldObj.groupFieldValue) { if (opArg && opArg.groupFieldValue && opArg.groupFieldValue.valueSrc == "field" && opArg.groupFieldValue.value == groupField) { // group.?[...].size() == group.size() opKey = "all"; convertedArgs = []; } else if (opKey == "equal" && opArg.valueSrc == "value" && opArg.valueType == "number" && opArg.value == 0) { opKey = "none"; convertedArgs = []; } else if (opKey == "greater" && opArg.valueSrc == "value" && opArg.valueType == "number" && opArg.value == 0) { opKey = "some"; convertedArgs = []; } } var opConfig = config.operators[opKey]; var reversedOpConfig = config.operators[(_opConfig = opConfig) === null || _opConfig === void 0 ? void 0 : _opConfig.reversedOp]; var opNeedsReverse = spel.not && ["between"].includes(opKey); var opCanReverse = !!reversedOpConfig; var canRev = opCanReverse && (!!config.settings.reverseOperatorsForNot || opNeedsReverse); var needRev = spel.not && canRev || opNeedsReverse; if (needRev) { opKey = opConfig.reversedOp; opConfig = config.operators[opKey]; spel.not = !spel.not; } var needWrapWithNot = !!spel.not; spel.not = false; // handled with needWrapWithNot if (!fieldObj) { // LHS can't be parsed } else if (fieldObj.groupFieldValue) { // 1. group if (fieldObj.groupFieldValue.valueSrc != "field") { meta.errors.push("Expected group field ".concat(JSON.stringify(fieldObj))); } res = buildRuleGroup(fieldObj, opKey, convertedArgs, config, meta); } else { // 2. not group if (fieldObj.valueSrc != "field" && fieldObj.valueSrc != "func") { meta.errors.push("Expected field/func at LHS, but got ".concat(JSON.stringify(fieldObj))); } var _field = fieldObj.value; res = buildRule(config, meta, _field, opKey, convertedArgs, spel); } if (needWrapWithNot) { if (res.type !== "group") { res = wrapInDefaultConj(res, config, true); } else { res.properties.not = !res.properties.not; } } } else { if (!parentSpel) { // try to parse whole `"str" + prop + #var` as ternary res = buildSimpleSwitch(spel, conv, config, meta); } // if (!res) { // meta.errors.push(`Can't convert op ${op}`); // } } return res; }; var convertPath = function convertPath(parts) { var meta = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var expectingField = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var isError = false; var res = parts.map(function (c) { if (c.type == "variable" || c.type == "property" || c.type == "indexer" && c.itype == "string") { return c.val; } else { var _meta$errors, _meta$errors$push; isError = true; expectingField && (meta === null || meta === void 0 || (_meta$errors = meta.errors) === null || _meta$errors === void 0 || (_meta$errors$push = _meta$errors.push) === null || _meta$errors$push === void 0 ? void 0 : _meta$errors$push.call(_meta$errors, "Unexpected item in field path compound: ".concat(JSON.stringify(c)))); } }); return !isError ? res : undefined; }; var convertArg = function convertArg(spel, conv, config, meta) { var _spel$_groupField2, _config$settings$case; var parentSpel = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; if (spel == undefined) return undefined; var fieldSeparator = config.settings.fieldSeparator; spel._groupField = (_spel$_groupField2 = spel._groupField) !== null && _spel$_groupField2 !== void 0 ? _spel$_groupField2 : parentSpel === null || parentSpel === void 0 ? void 0 : parentSpel._groupField; if (spel.type == "variable" || spel.type == "property") { // normal field var field = (0, _configUtils.normalizeField)(config, spel.val, spel._groupField); var fieldConfig = (0, _configUtils.getFieldConfig)(config, field); var isVariable = spel.type == "variable"; return { valueSrc: "field", valueType: fieldConfig === null || fieldConfig === void 0 ? void 0 : fieldConfig.type, isVariable: isVariable, value: field }; } else if (spel.type == "compound") { // complex field var parts = convertPath(spel.children, meta); if (parts) { var _spel$children; var _field2 = (0, _configUtils.normalizeField)(config, parts.join(fieldSeparator), spel._groupField); var _fieldConfig = (0, _configUtils.getFieldConfig)(config, _field2); var _isVariable = ((_spel$children = spel.children) === null || _spel$children === void 0 || (_spel$children = _spel$children[0]) === null || _spel$children === void 0 ? void 0 : _spel$children.type) == "variable"; return { valueSrc: "field", valueType: _fieldConfig === null || _fieldConfig === void 0 ? void 0 : _fieldConfig.type, isVariable: _isVariable, value: _field2 }; } else { // it's not complex field } } else if (SpelPrimitiveTypes[spel.type]) { var value = spel.val; var valueType = SpelPrimitiveTypes[spel.type]; if (spel.negative) { value = -value; } return { valueSrc: "value", valueType: valueType, value: value }; } else if (spel.type == "!new" && SpelPrimitiveClasses[spel.cls.at(-1)]) { var args = spel.args.map(function (v) { return convertArg(v, conv, config, meta, spel); }); var _value = args === null || args === void 0 ? void 0 : args[0]; var _valueType = SpelPrimitiveClasses[spel.cls.at(-1)]; return _objectSpread(_objectSpread({}, _value), {}, { valueType: _valueType }); } else if (spel.type == "list") { var _values$; var values = spel.val.map(function (v) { return convertArg(v, conv, config, meta, spel); }); var _itemType = values.length ? (_values$ = values[0]) === null || _values$ === void 0 ? void 0 : _values$.valueType : null; var _value2 = values.map(function (v) { return v === null || v === void 0 ? void 0 : v.value; }); var _valueType2 = ListValueType; return { valueSrc: "value", valueType: _valueType2, value: _value2 }; } else if (spel.type === "op-plus" && (parentSpel === null || parentSpel === void 0 ? void 0 : parentSpel.type) === "ternary" && ((_config$settings$case = config.settings.caseValueField) === null || _config$settings$case === void 0 ? void 0 : _config$settings$case.type) === "case_value") { /** * @deprecated */ return buildCaseValueConcat(spel, conv, config, meta); } var maybe = convertFunc(spel, conv, config, meta, parentSpel); if (maybe !== undefined) { return maybe; } meta.errors.push("Can't convert arg of type ".concat(spel.type)); return undefined; }; var buildFuncSignatures = function buildFuncSignatures(spel) { // branches var brns = [{ s: "", params: [], objs: [] }]; _buildFuncSignatures(spel, brns); return brns.map(function (_ref6) { var s = _ref6.s, params = _ref6.params; return { s: s, params: params }; }).reverse().filter(function (_ref7) { var s = _ref7.s; return s !== "" && s !== "?"; }); }; // a.toLower().toUpper() // -> // ?.toLower().toUpper() // ?.toUpper() var _buildFuncSignatures = function _buildFuncSignatures(spel, brns) { var params = [], s = ""; var type = spel.type, methodName = spel.methodName, val = spel.val, obj = spel.obj, args = spel.args, isVar = spel.isVar, cls = spel.cls, children = spel.children; var lastChild = children === null || children === void 0 ? void 0 : children[children.length - 1]; var currBrn = brns[brns.length - 1]; if (type === "!func") { // T(DateTimeFormat).forPattern(?).parseDateTime(?) -- ok // T(LocalDateTime).parse(?, T(DateTimeFormatter).ofPattern(?)) -- will not work var o = obj; while (o) { var _currBrn$params; var _buildFuncSignatures2 = _buildFuncSignatures(_objectSpread(_objectSpread({}, o), {}, { obj: null }), [{}]), _buildFuncSignatures3 = (0, _slicedToArray2["default"])(_buildFuncSignatures2, 2), s1 = _buildFuncSignatures3[0], params1 = _buildFuncSignatures3[1]; if (s1 !== "?") { // start new branch var newBrn = { s: currBrn.s, params: (0, _toConsumableArray2["default"])(currBrn.params), objs: (0, _toConsumableArray2["default"])(currBrn.objs) }; // finish old branch currBrn.objs.unshift("?"); currBrn.params.unshift(o); // switch brns.push(newBrn); currBrn = brns[brns.length - 1]; } // step currBrn.objs.unshift(s1); (_currBrn$params = currBrn.params).unshift.apply(_currBrn$params, (0, _toConsumableArray2["default"])(params1)); o = o.type === "!func" ? o.obj : null; } var _iterator4 = _createForOfIteratorHelper(brns), _step4; try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { var _brn$objs; var brn = _step4.value; params = [].concat((0, _toConsumableArray2["default"])((brn === null || brn === void 0 ? void 0 : brn.params) || []), (0, _toConsumableArray2["default"])(args || [])); s = ""; if (brn !== null && brn !== void 0 && (_brn$objs = brn.objs) !== null && _brn$objs !== void 0 && _brn$objs.length) s += brn.objs.join(".") + "."; s += (isVar ? "#" : "") + methodName; s += "(" + (args || []).map(function (_) { return "?"; }).join(", ") + ")"; brn.s = s; brn.params = params; } } catch (err) { _iterator4.e(err); } finally { _iterator4.f(); } } else if (type === "!new") { // new java.text.SimpleDateFormat('HH:mm:ss').parse('...') params = args || []; s = "new ".concat(cls.join("."), "(").concat(params.map(function (_) { return "?"; }).join(", "), ")"); } else if (type === "!type") { // T(java.time.LocalTime).parse('...') s = "T(".concat(cls.join("."), ")"); } else if (type === "compound" && lastChild.type === "property" && isFuncableProperty(lastChild.val)) { // {1,2}.length -- ok // 'Hello World'.bytes.length -- will not work s = children.map(function (c) { var _params; if (c === lastChild) return c.val; var _buildFuncSignatures4 = _buildFuncSignatures(_objectSpread(_objectSpread({}, c), {}, { obj: null }), [{}]), _buildFuncSignatures5 = (0, _slicedToArray2["default"])(_buildFuncSignatures4, 2), s1 = _buildFuncSignatures5[0], params1 = _buildFuncSignatures5[1]; (_params = params).push.apply(_params, (0, _toConsumableArray2["default"])(params1)); return s1; }).join("."); } else { params = [spel]; s = "?"; } if (currBrn) { currBrn.s = s; currBrn.params = params; } return [s, params]; }; var convertFunc = function convertFunc(spel, conv, config, meta) { var _fsigns$; var parentSpel = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; // Build signatures var convertFuncArg = function convertFuncArg(v) { return convertToTree(v, conv, config, meta, spel); }; var fsigns = buildFuncSignatures(spel); var firstSign = fsigns === null || fsigns === void 0 || (_fsigns$ = fsigns[0]) === null || _fsigns$ === void 0 ? void 0 : _fsigns$.s; if (fsigns.length) _stuff.logger.debug("Signatures for ", spel, ":", firstSign, fsigns); // 1. Try to parse as value var maybeValue = convertFuncToValue(spel, conv, config, meta, parentSpel, fsigns, convertFuncArg); if (maybeValue !== undefined) return maybeValue; // 2. Try to parse as op var maybeOp = convertFuncToOp(spel, conv, config, meta, parentSpel, fsigns, convertFuncArg); if (maybeOp !== undefined) return maybeOp; // 3. Try to parse as func var funcKey, funcConfig, argsObj; // try func signature matching var _iterator5 = _createForOfIteratorHelper(fsigns), _step5; try { var _loop3 = function _loop3() { var _step5$value = _step5.value, s = _step5$value.s, params = _step5$value.params; var funcKeys = conv.funcs[s]; if (funcKeys) { // todo: here we can check arg types, if we have function overloading funcKey = funcKeys[0]; funcConfig = (0, _configUtils.getFuncConfig)(config, funcKey); var _funcConfig = funcConfig, spelFunc = _funcConfig.spelFunc; var argsArr = params.map(convertFuncArg); var argsOrder = (0, _toConsumableArray2["default"])(spelFunc.matchAll(/\${(\w+)}/g)).map(function (_ref8) { var _ref9 = (0, _slicedToArray2["default"])(_ref8, 2), _ = _ref9[0], k = _ref9[1]; return k; }); argsObj = Object.fromEntries(argsOrder.map(function (argKey, i) { return [argKey, argsArr[i]]; })); return 1; // break } }; for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) { if (_loop3()) break; } // try `spelImport` } catch (err) { _iterator5.e(err); } finally { _iterator5.f(); } if (!funcKey) { var _iterator6 = _createForOfIteratorHelper((0, _configUtils.iterateFuncs)(config)), _step6; try { for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) { var _step6$value = (0, _slicedToArray2["default"])(_step6.value, 2), f = _step6$value[0], fc = _step6$value[1]; if (fc.spelImport) { var parsed = void 0; try { parsed = fc.spelImport(spel); } catch (_e) { // can't be parsed } if (parsed) { funcKey = f; funcConfig = (0, _configUtils.getFuncConfig)(config, funcKey); argsObj = {}; for (var argKey in parsed) { argsObj[argKey] = convertFuncArg(parsed[argKey]); } } } } } catch (err) { _iterator6.e(err); } finally { _iterator6.f(); } } // convert if (funcKey) { var funcArgs = {}; for (var _argKey in funcConfig.args) { var argConfig = funcConfig.args[_argKey]; var argVal = argsObj[_argKey]; if (argVal === undefined) { argVal = argConfig === null || argConfig === void 0 ? void 0 : argConfig.defaultValue; if (argVal === undefined) { if (argConfig !== null && argConfig !== void 0 && argConfig.isOptional) { //ignore } else { meta.errors.push("No value for arg ".concat(_argKey, " of func ").concat(funcKey)); return undefined; } } else { var _argVal; argVal = { value: argVal, valueSrc: (_argVal = argVal) !== null && _argVal !== void 0 && _argVal.func ? "func" : "value", valueType: argConfig.type }; } } if (argVal) funcArgs[_argKey] = argVal; } return { valueSrc: "func", value: { func: funcKey, args: funcArgs }, valueType: funcConfig.returnType }; } var methodName = spel.methodName; if (methodName) meta.errors.push("Signature ".concat(firstSign, " - failed to convert")); return undefined; }; var convertFuncToValue = function convertFuncToValue(spel, conv, config, meta, parentSpel, fsigns, convertFuncArg) { var errs, foundSign, foundWidget; var candidates = []; for (var w in config.widgets) { var widgetDef = config.widgets[w]; var spelImportFuncs = widgetDef.spelImportFuncs; if (spelImportFuncs) { for (var i = 0; i < spelImportFuncs.length; i++) { var fj = spelImportFuncs[i]; if (isObject(fj)) { var bag = {}; if ((0, _stuff.isJsonCompatible)(fj, spel, bag)) { for (var k in bag) { bag[k] = convertFuncArg(bag[k]); } candidates.push({ s: "widgets.".concat(w, ".spelImportFuncs[").concat(i, "]"), w: w, argsObj: bag }); } } } } } var _iterator7 = _createForOfIteratorHelper(fsigns), _step7; try { for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) { var _step7$value = _step7.value, _s = _step7$value.s, params = _step7$value.params; var found = conv.valueFuncs[_s] || []; var _iterator8 = _createForOfIteratorHelper(found), _step8; try { var _loop4 = function _loop4() { var _step8$value = _step8.value, w = _step8$value.w, argsOrder = _step8$value.argsOrder; var argsArr = params.map(convertFuncArg); var argsObj = Object.fromEntries(argsOrder.map(function (argKey, i) { return [argKey, argsArr[i]]; })); candidates.push({ s: _s, w: w, argsObj: argsObj }); }; for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) { _loop4(); } } catch (err) { _iterator8.e(err); } finally { _iterator8.f(); } } } catch (err) { _iterator7.e(err); } finally { _iterator7.f(); } for (var _i = 0, _candidates = candidates; _i < _candidates.length; _i++) { var _candidates$_i = _candidates[_i], s = _candidates$_i.s, _w = _candidates$_i.w, argsObj = _candidates$_i.argsObj; var _widgetDef = config.widgets[_w]; var spelImportValue = _widgetDef.spelImportValue, type = _widgetDef.type; foundWidget = _w; foundSign = s; errs = []; for (var _k2 in argsObj) { if (!["value"].includes(argsObj[_k2].valueSrc)) { errs.push("".concat(_k2, " has unsupported value src ").concat(argsObj[_k2].valueSrc)); } } var value = argsObj.v.value; if (spelImportValue && !errs.length) { var _spelImportValue$call = spelImportValue.call(config.ctx, argsObj.v, _widgetDef, argsObj); var _spelImportValue$call2 = (0, _slicedToArray2["default"])(_spelImportValue$call, 2); value = _spelImportValue$call2[0]; errs = _spelImportValue$call2[1]; if (errs && !Array.isArray(errs)) errs = [errs]; } if (!errs.length) { return { valueSrc: "value", valueType: type, value: value }; } } if (foundWidget && errs.length) { meta.errors.push("Signature ".concat(foundSign, " - looks like convertable to ").concat(foundWidget, ", but: ").concat(errs.join("; "))); } return undefined; }; var convertFuncToOp = function convertFuncToOp(spel, conv, config, meta, parentSpel, fsigns, convertFuncArg) { var errs, opKey, foundSign; var _iterator9 = _createForOfIteratorHelper(fsigns), _step9; try { for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) { var _step9$value = _step9.value, s = _step9$value.s, params = _step9$value.params; var found = conv.opFuncs[s] || []; var _iterator10 = _createForOfIteratorHelper(found), _step10; try { var _loop5 = function _loop5() { var _argsArr$filter$find; var _step10$value = _step10.value, op = _step10$value.op, argsOrder = _step10$value.argsOrder; var argsArr = params.map(convertFuncArg); opKey = op; if (op === "!compare") { if (parentSpel.type.startsWith("op-") && parentSpel.children.length == 2 && parentSpel.children[1].type == "number" && parentSpel.children[1].val === 0) { return { v: { type: "!compare", children: argsArr } }; } else { errs.push("Result of compareTo() should be compared to 0"); } } foundSign = s; errs = []; var opDef = config.operators[opKey]; var spelOp = opDef.spelOp, valueTypes = opDef.valueTypes; var argsObj = Object.fromEntries(argsOrder.map(function (argKey, i) { return [argKey, argsArr[i]]; })); var field = argsObj["0"]; var convertedArgs = Object.keys(argsObj).filter(function (k) { return parseInt(k) > 0; }).map(function (k) { return argsObj[k]; }); var valueType = (_argsArr$filter$find = argsArr.filter(function (a) { return !!a; }).find(function (_ref10) { var valueSrc = _ref10.valueSrc; return valueSrc === "value"; })) === null || _argsArr$filter$find === void 0 ? void 0 : _argsArr$filter$find.valueType; if (valueTypes && valueType && !valueTypes.includes(valueType)) { errs.push("Op supports types ".concat(valueTypes, ", but got ").concat(valueType)); } if (!errs.length) { return { v: buildRule(config, meta, field, opKey, convertedArgs, spel) }; } }, _ret; for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) { _ret = _loop5(); if (_ret) return _ret.v; } } catch (err) { _iterator10.e(err); } finally { _iterator10.f(); } } } catch (err) { _iterator9.e(err); } finally { _iterator9.f(); } if (opKey && errs.length) { meta.errors.push("Signature ".concat(foundSign, " - looks like convertable to ").concat(opKey, ", but: ").concat(errs.join("; "))); } return undefined; }; var buildRule = function buildRule(config, meta, field, opKey, convertedArgs, spel) { var _field3, _opConfig2; if (convertedArgs.filter(function (v) { return v === undefined; }).length) { return undefined; } var fieldSrc = (_field3 = field) !== null && _field3 !== void 0 && _field3.func ? "func" : "field"; if (isObject(field) && field.valueSrc) { // if comed from convertFuncToOp() fieldSrc = field.valueSrc; field = field.value; } var fieldConfig = (0, _configUtils.getFieldConfig)(config, field); if (!fieldConfig) { meta.errors.push("No config for field ".concat(field)); return undefined; } var parentFieldConfig = (0, _configUtils.getFieldConfig)(config, spel === null || spel === void 0 ? void 0 : spel._groupField); var isRuleGroup = fieldConfig.type == "!group"; var isGroupArray = isRuleGroup && fieldConfig.mode == "array"; var isInRuleGroup = (parentFieldConfig === null || parentFieldConfig === void 0 ? void 0 : parentFieldConfig.type) == "!group"; var opConfig = config.operators[opKey]; var reversedOpConfig = config.operators[(_opConfig2 = opConfig) === null || _opConfig2 === void 0 ? void 0 : _opConfig2.reversedOp]; var opNeedsReverse = (spel === null || spel === void 0 ? void 0 : spel.not) && ["between"].includes(opKey); var opCanReverse = !!reversedOpConfig; var canRev = opCanReverse && (!!config.settings.reverseOperatorsForNot || opNeedsReverse || !isRuleGroup && isInRuleGroup // 2+ rules in rule-group should be flat. see inits.with_not_and_in_some in test ); var needRev = (spel === null || spel === void 0 ? void 0 : spel.not) && canRev || opNeedsReverse; if (needRev) { // todo: should be already handled at convertOp ? or there are special cases to handle here, like rule-group ? opKey = opConfig.reversedOp; opConfig = config.operators[opKey]; spel.not = !spel.not; } var needWrapWithNot = !!(spel !== null && spel !== void 0 && spel.not); var widget = (0, _ruleUtils.getWidgetForFieldOp)(config, field, opKey); var widgetConfig = config.widgets[widget || fieldConfig.mainWidget]; var asyncListValuesArr = convertedArgs.map(function (v) { return v.asyncListValues; }).filter(function (v) { return v != undefined; }); var asyncListValues = asyncListValuesArr.length ? asyncListValuesArr[0] : undefined; var res = { type: "rule", id: (0, _uuid["default"])(), properties: _objectSpread({ field: field, fieldSrc: fieldSrc, operator: opKey, value: convertedArgs.map(function (v) { return v.value; }), valueSrc: convertedArgs.map(function (v) { return v.valueSrc; }), valueType: convertedArgs.map(function (v) { if (v.valueSrc == "value") { return (widgetConfig === null || widgetConfig === void 0 ? void 0 : widgetConfig.type) || (fieldConfig === null || fieldConfig === void 0 ? void 0 : fieldConfig.type) || v.valueType; } return v