UNPKG

@react-awesome-query-builder/core

Version:
545 lines (532 loc) 26.1 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, 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 o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } 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) { _defineProperty(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; } import { getFieldConfig, getOperatorConfig, getFieldWidgetConfig, getFuncConfig, getFieldParts, getWidgetForFieldOp, getFieldPartsConfigs } from "../utils/configUtils"; import { extendConfig } from "../utils/configExtend"; import { formatFieldName, completeValue } from "../utils/ruleUtils"; import pick from "lodash/pick"; import { getOpCardinality, widgetDefKeysToOmit, opDefKeysToOmit, omit } from "../utils/stuff"; import { defaultConjunction } from "../utils/defaultUtils"; import { List, Map } from "immutable"; import { spelEscape } from "../utils/spelUtils"; // https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/expressions.html#expressions export var compareToSign = "${0}.compareTo(${1})"; var TypesWithCompareTo = { datetime: true, time: true, date: true }; export var spelFormat = function spelFormat(tree, config) { return _spelFormat(tree, config, false); }; export var _spelFormat = function _spelFormat(tree, config) { var returnErrors = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; //meta is mutable var meta = { errors: [] }; var extendedConfig = extendConfig(config, undefined, false); var res = formatItem(tree, extendedConfig, meta, null); if (returnErrors) { return [res, meta.errors]; } else { if (meta.errors.length) console.warn("Errors while exporting to SpEL:", meta.errors); return res; } }; var formatItem = function formatItem(item, config, meta) { var parentField = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; if (!item) return undefined; var type = item.get("type"); if (type === "group" || type === "rule_group") { return formatGroup(item, config, meta, parentField); } else if (type === "rule") { return formatRule(item, config, meta, parentField); } else if (type == "switch_group") { return formatSwitch(item, config, meta, parentField); } else if (type == "case_group") { return formatCase(item, config, meta, parentField); } return undefined; }; var formatCase = function formatCase(item, config, meta) { var parentField = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; var type = item.get("type"); if (type != "case_group") { meta.errors.push("Unexpected child of type ".concat(type, " inside switch")); return undefined; } var properties = item.get("properties") || new Map(); var _formatItemValue = formatItemValue(config, properties, meta, null, parentField, "!case_value"), formattedValue = _formatItemValue.value, valueSrc = _formatItemValue.valueSrc, valueType = _formatItemValue.valueType; var cond = formatGroup(item, config, meta, parentField); return [cond, formattedValue]; }; var formatSwitch = function formatSwitch(item, config, meta) { var parentField = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; var properties = item.get("properties") || new Map(); var children = item.get("children1"); if (!children) return undefined; var cases = children.map(function (currentChild) { return formatCase(currentChild, config, meta, null); }).filter(function (currentChild) { return typeof currentChild !== "undefined"; }).valueSeq().toArray(); if (!cases.length) return undefined; if (cases.length == 1 && !cases[0][0]) { // only 1 case without condition return cases[0][1]; } var filteredCases = []; for (var i = 0; i < cases.length; i++) { if (i != cases.length - 1 && !cases[i][0]) { meta.errors.push("No condition for case ".concat(i)); } else { filteredCases.push(cases[i]); if (i == cases.length - 1 && cases[i][0]) { // no default - add null as default filteredCases.push([undefined, null]); } } } var left = "", right = ""; for (var _i = 0; _i < filteredCases.length; _i++) { var _filteredCases$_i = _slicedToArray(filteredCases[_i], 2), cond = _filteredCases$_i[0], value = _filteredCases$_i[1]; if (value == undefined) value = "null"; if (cond == undefined) cond = "true"; if (_i != filteredCases.length - 1) { left += "(".concat(cond, " ? ").concat(value, " : "); right += ")"; } else { left += "".concat(value); } } return left + right; }; var formatGroup = function formatGroup(item, config, meta) { var parentField = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; var type = item.get("type"); var properties = item.get("properties") || new Map(); var mode = properties.get("mode"); var children = item.get("children1") || new List(); var field = properties.get("field"); var conjunction = properties.get("conjunction"); if (!conjunction) conjunction = defaultConjunction(config); var conjunctionDefinition = config.conjunctions[conjunction]; var not = properties.get("not"); var isRuleGroup = type === "rule_group" && field; var isRuleGroupArray = isRuleGroup && mode != "struct"; var groupField = isRuleGroupArray ? field : parentField; var groupFieldDef = getFieldConfig(config, groupField) || {}; var isSpelArray = groupFieldDef.isSpelArray; var fieldSeparator = config.settings.fieldSeparator; // check op for reverse var groupOperator = properties.get("operator"); if (!groupOperator && (!mode || mode == "some")) { groupOperator = "some"; } var realGroupOperator = checkOp(config, groupOperator, field); var isGroupOpRev = realGroupOperator != groupOperator; var realGroupOperatorDefinition = groupOperator && getOperatorConfig(config, realGroupOperator, field) || null; var isGroup0 = isRuleGroup && (!realGroupOperator || realGroupOperatorDefinition.cardinality == 0); // build value for aggregation op var _formatItemValue2 = formatItemValue(config, properties, meta, realGroupOperator, parentField, null), formattedValue = _formatItemValue2.value, valueSrc = _formatItemValue2.valueSrc, valueType = _formatItemValue2.valueType; // build filter in aggregation var list = children.map(function (currentChild) { return formatItem(currentChild, config, meta, groupField); }).filter(function (currentChild) { return typeof currentChild !== "undefined"; }); if (isRuleGroupArray && !isGroup0) { // "count" rule can have no "having" children, but should have number value if (formattedValue == undefined) return undefined; } else { if (!list.size) return undefined; } var omitBrackets = isRuleGroup; var filter = list.size ? conjunctionDefinition.spelFormatConj.call(config.ctx, list, conjunction, not, omitBrackets) : null; // build result var ret; if (isRuleGroupArray) { var _formatField = formatField(meta, config, field, parentField), formattedField = _formatField.value; var sep = fieldSeparator || "."; var getSize = sep + (isSpelArray ? "length" : "size()"); var fullSize = "".concat(formattedField).concat(getSize); // https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/expressions.html#expressions-collection-selection var filteredSize = filter ? "".concat(formattedField, ".?[").concat(filter, "]").concat(getSize) : fullSize; var groupValue = isGroup0 ? fullSize : formattedValue; // format expression ret = formatExpression(meta, config, properties, filteredSize, groupValue, realGroupOperator, valueSrc, valueType, isGroupOpRev); } else { ret = filter; } return ret; }; var buildFnToFormatOp = function buildFnToFormatOp(operator, operatorDefinition, valueType) { var spelOp = operatorDefinition.spelOp; if (!spelOp) return undefined; var isSign = spelOp.includes("${0}"); var isCompareTo = TypesWithCompareTo[valueType]; var sop = spelOp; var fn; var cardinality = getOpCardinality(operatorDefinition); if (isCompareTo) { // date1.compareTo(date2) >= 0 // instead of // date1 >= date2 fn = function fn(field, op, values, valueSrc, valueType, opDef, operatorOptions, fieldDef) { var compareRes = compareToSign.replace(/\${(\w+)}/g, function (_, k) { return k == 0 ? field : cardinality > 1 ? values[k - 1] : values; }); return "".concat(compareRes, " ").concat(sop, " 0"); }; } else if (isSign) { fn = function fn(field, op, values, valueSrc, valueType, opDef, operatorOptions, fieldDef) { return spelOp.replace(/\${(\w+)}/g, function (_, k) { return k == 0 ? field : cardinality > 1 ? values[k - 1] : values; }); }; } else if (cardinality == 0) { // should not be fn = function fn(field, op, values, valueSrc, valueType, opDef, operatorOptions, fieldDef) { return "".concat(field, " ").concat(sop); }; } else if (cardinality == 1) { fn = function fn(field, op, values, valueSrc, valueType, opDef, operatorOptions, fieldDef) { return "".concat(field, " ").concat(sop, " ").concat(values); }; } return fn; }; var formatExpression = function formatExpression(meta, config, properties, formattedField, formattedValue, operator, valueSrc, valueType) { var isRev = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : false; var field = properties.get("field"); var opDef = getOperatorConfig(config, operator, field) || {}; var fieldDef = getFieldConfig(config, field) || {}; var operatorOptions = properties.get("operatorOptions"); //find fn to format expr var fn = opDef.spelFormatOp || buildFnToFormatOp(operator, opDef, valueType !== null && valueType !== void 0 ? valueType : fieldDef.type); if (!fn) { meta.errors.push("Operator ".concat(operator, " is not supported")); return undefined; } //format expr var args = [formattedField, operator, formattedValue, valueSrc, valueType, omit(opDef, opDefKeysToOmit), operatorOptions, fieldDef]; var ret; ret = fn.call.apply(fn, [config.ctx].concat(args)); //rev if (isRev) { ret = config.settings.spelFormatReverse.call(config.ctx, ret); } if (ret === undefined) { meta.errors.push("Operator ".concat(operator, " is not supported for value source ").concat(valueSrc)); } return ret; }; var checkOp = function checkOp(config, operator, field) { if (!operator) return undefined; var opDef = getOperatorConfig(config, operator, field) || {}; var reversedOp = opDef.reversedOp; var revOpDef = getOperatorConfig(config, reversedOp, field) || {}; var isRev = false; var canFormatOp = opDef.spelOp || opDef.spelFormatOp; var canFormatRevOp = revOpDef.spelOp || revOpDef.spelFormatOp; if (!canFormatOp && !canFormatRevOp) { return undefined; } if (!canFormatOp && canFormatRevOp) { isRev = true; var _ref = [reversedOp, operator]; operator = _ref[0]; reversedOp = _ref[1]; var _ref2 = [revOpDef, opDef]; opDef = _ref2[0]; revOpDef = _ref2[1]; } return operator; }; var formatRule = function formatRule(item, config, meta) { var _formatLhs; var parentField = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; var properties = item.get("properties") || new Map(); var field = properties.get("field"); var fieldSrc = properties.get("fieldSrc"); var operator = properties.get("operator"); if (field == null || operator == null) return undefined; // check op for reverse var realOp = checkOp(config, operator, field); if (!realOp) { meta.errors.push("Operator ".concat(operator, " is not supported")); return undefined; } var isRev = realOp != operator; //format value var _formatItemValue3 = formatItemValue(config, properties, meta, realOp, parentField, null), formattedValue = _formatItemValue3.value, valueSrc = _formatItemValue3.valueSrc, valueType = _formatItemValue3.valueType; if (formattedValue === undefined) return undefined; //format field var _ref3 = (_formatLhs = formatLhs(meta, config, field, fieldSrc, parentField)) !== null && _formatLhs !== void 0 ? _formatLhs : {}, formattedField = _ref3.value, _fieldSrc = _ref3.valueSrc, fieldType = _ref3.valueType; if (formattedField === undefined) return undefined; // format expression var res = formatExpression(meta, config, properties, formattedField, formattedValue, realOp, valueSrc, valueType !== null && valueType !== void 0 ? valueType : fieldType, isRev); return res; }; var formatLhs = function formatLhs(meta, config, field, fieldSrc) { var parentField = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; if (fieldSrc === "func") return formatFunc(meta, config, field, parentField);else return formatField(meta, config, field, parentField); }; var formatItemValue = function formatItemValue(config, properties, meta, operator, parentField) { var expectedValueType = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null; var field = properties.get("field"); var iValueSrc = properties.get("valueSrc"); var iValueType = properties.get("valueType"); if (expectedValueType == "!case_value" || iValueType && iValueType.get(0) == "case_value") { field = "!case_value"; } var fieldDef = getFieldConfig(config, field) || {}; var operatorDefinition = getOperatorConfig(config, operator, field) || {}; var cardinality = getOpCardinality(operatorDefinition); var iValue = properties.get("value"); var asyncListValues = properties.get("asyncListValues"); var valueSrcs = []; var valueTypes = []; var formattedValue; if (iValue != undefined) { var fvalue = iValue.map(function (currentValue, ind) { var valueSrc = iValueSrc ? iValueSrc.get(ind) : null; var valueType = iValueType ? iValueType.get(ind) : null; var cValue = completeValue(currentValue, valueSrc, config); var widget = getWidgetForFieldOp(config, field, operator, valueSrc); var fieldWidgetDef = getFieldWidgetConfig(config, field, operator, widget, valueSrc, { forExport: true }); var fv = formatValue(meta, config, cValue, valueSrc, valueType, fieldWidgetDef, fieldDef, operator, operatorDefinition, parentField, asyncListValues); if (fv !== undefined) { valueSrcs.push(valueSrc); valueTypes.push(valueType); } return fv; }); var hasUndefinedValues = fvalue.filter(function (v) { return v === undefined; }).size > 0; if (!(fvalue.size < cardinality || hasUndefinedValues)) { formattedValue = cardinality > 1 ? fvalue.toArray() : cardinality == 1 ? fvalue.first() : null; } } return { value: formattedValue, valueSrc: valueSrcs.length > 1 ? valueSrcs : valueSrcs[0], valueType: valueTypes.length > 1 ? valueTypes : valueTypes[0] }; }; var formatValue = function formatValue(meta, config, currentValue, valueSrc, valueType, fieldWidgetDef, fieldDef, operator, operatorDef) { var parentField = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : null; var asyncListValues = arguments.length > 10 ? arguments[10] : undefined; if (currentValue === undefined) return undefined; var ret; if (valueSrc === "field") { var _formatField2; // formatField() returns type {value, valueSrc, valueType} ret = (_formatField2 = formatField(meta, config, currentValue, parentField)) === null || _formatField2 === void 0 ? void 0 : _formatField2.value; } else if (valueSrc === "func") { var _formatFunc; // formatFunc() returns type {value, valueSrc, valueType} ret = (_formatFunc = formatFunc(meta, config, currentValue, parentField, valueType)) === null || _formatFunc === void 0 ? void 0 : _formatFunc.value; } else { if (typeof (fieldWidgetDef === null || fieldWidgetDef === void 0 ? void 0 : fieldWidgetDef.spelFormatValue) === "function") { var fn = fieldWidgetDef.spelFormatValue; var args = [currentValue, _objectSpread(_objectSpread({}, pick(fieldDef, ["fieldSettings", "listValues"])), {}, { asyncListValues: asyncListValues }), //useful options: valueFormat for date/time omit(fieldWidgetDef, widgetDefKeysToOmit)]; if (operator) { args.push(operator); args.push(operatorDef); } if (valueSrc == "field") { var valFieldDefinition = getFieldConfig(config, currentValue) || {}; args.push(valFieldDefinition); } ret = fn.call.apply(fn, [config.ctx].concat(args)); } else { ret = spelEscape(currentValue); } } return ret; }; var formatField = function formatField(meta, config, field) { var parentField = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; if (!field) return; var fieldSeparator = config.settings.fieldSeparator; var fieldDefinition = getFieldConfig(config, field) || {}; var fieldParts = getFieldParts(field, config); var fieldPartsConfigs = getFieldPartsConfigs(field, config, parentField); var formatFieldFn = config.settings.formatSpelField; var fieldName = formatFieldName(field, config, meta, parentField); var fieldPartsMeta = fieldPartsConfigs.map(function (_ref4) { var _ref5 = _slicedToArray(_ref4, 3), key = _ref5[0], cnf = _ref5[1], parentCnf = _ref5[2]; var parent; if (parentCnf) { if (parentCnf.type == "!struct" || parentCnf.type == "!group" && parentCnf.mode == "struct") parent = cnf !== null && cnf !== void 0 && cnf.isSpelMap ? "map" : "class";else if (parentCnf.type == "!group") parent = cnf !== null && cnf !== void 0 && cnf.isSpelItemMap ? "[map]" : "[class]";else parent = "class"; } var isSpelVariable = cnf === null || cnf === void 0 ? void 0 : cnf.isSpelVariable; return { key: key, parent: parent, isSpelVariable: isSpelVariable, fieldSeparator: fieldSeparator }; }); var formattedField = formatFieldFn.call(config.ctx, fieldName, parentField, fieldParts, fieldPartsMeta, fieldDefinition, config); return { value: formattedField, valueSrc: "field", valueType: fieldDefinition === null || fieldDefinition === void 0 ? void 0 : fieldDefinition.type }; }; var formatFunc = function formatFunc(meta, config, currentValue) { var _currentValue$get, _currentValue$get2; var parentField = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; var valueType = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; var funcKey = (_currentValue$get = currentValue.get) === null || _currentValue$get === void 0 ? void 0 : _currentValue$get.call(currentValue, "func"); var args = (_currentValue$get2 = currentValue.get) === null || _currentValue$get2 === void 0 ? void 0 : _currentValue$get2.call(currentValue, "args"); var funcConfig = getFuncConfig(config, funcKey); if (!funcConfig) { meta.errors.push("Func ".concat(funcKey, " is not defined in config")); return undefined; } var formattedArgs = {}; var gaps = []; var missingArgKeys = []; for (var argKey in funcConfig.args) { var _argValue, _argConfig$escapeForF; var argConfig = funcConfig.args[argKey]; var fieldDef = getFieldConfig(config, argConfig); var defaultValue = argConfig.defaultValue, isOptional = argConfig.isOptional; var defaultValueSrc = defaultValue !== null && defaultValue !== void 0 && defaultValue.func ? "func" : "value"; var argVal = args ? args.get(argKey) : undefined; var argValue = argVal ? argVal.get("value") : undefined; var argValueSrc = argVal ? argVal.get("valueSrc") : undefined; if (argValueSrc !== "func" && (_argValue = argValue) !== null && _argValue !== void 0 && _argValue.toJS) { // value should not be Immutable argValue = argValue.toJS(); } var argAsyncListValues = argVal ? argVal.get("asyncListValues") : undefined; var doEscape = (_argConfig$escapeForF = argConfig.escapeForFormat) !== null && _argConfig$escapeForF !== void 0 ? _argConfig$escapeForF : true; var operator = null; var widget = getWidgetForFieldOp(config, argConfig, operator, argValueSrc); var fieldWidgetDef = getFieldWidgetConfig(config, argConfig, operator, widget, argValueSrc, { forExport: true }); var formattedArgVal = formatValue(meta, config, argValue, argValueSrc, argConfig.type, fieldWidgetDef, fieldDef, null, null, parentField, argAsyncListValues); if (argValue != undefined && formattedArgVal === undefined) { if (argValueSrc != "func") // don't triger error if args value is another incomplete function meta.errors.push("Can't format value of arg ".concat(argKey, " for func ").concat(funcKey)); return undefined; } var formattedDefaultVal = void 0; if (formattedArgVal === undefined && !isOptional && defaultValue != undefined) { var defaultWidget = getWidgetForFieldOp(config, argConfig, operator, defaultValueSrc); var defaultFieldWidgetDef = getFieldWidgetConfig(config, argConfig, operator, defaultWidget, defaultValueSrc, { forExport: true }); formattedDefaultVal = formatValue(meta, config, defaultValue, defaultValueSrc, argConfig.type, defaultFieldWidgetDef, fieldDef, null, null, parentField, argAsyncListValues); if (formattedDefaultVal === undefined) { if (defaultValueSrc != "func") // don't triger error if args value is another incomplete function meta.errors.push("Can't format default value of arg ".concat(argKey, " for func ").concat(funcKey)); return undefined; } } var finalFormattedVal = formattedArgVal !== null && formattedArgVal !== void 0 ? formattedArgVal : formattedDefaultVal; if (finalFormattedVal !== undefined) { if (gaps.length) { var _iterator = _createForOfIteratorHelper(gaps), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var missedArgKey = _step.value; formattedArgs[missedArgKey] = undefined; } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } gaps = []; } formattedArgs[argKey] = doEscape ? finalFormattedVal : argValue !== null && argValue !== void 0 ? argValue : defaultValue; } else { if (!isOptional) missingArgKeys.push(argKey); gaps.push(argKey); } } if (missingArgKeys.length) { //meta.errors.push(`Missing vals for args ${missingArgKeys.join(", ")} for func ${funcKey}`); return undefined; // incomplete } var ret; if (typeof funcConfig.spelFormatFunc === "function") { var fn = funcConfig.spelFormatFunc; var _args = [formattedArgs]; ret = fn.call.apply(fn, [config.ctx].concat(_args)); } else if (funcConfig.spelFunc) { // fill arg values ret = funcConfig.spelFunc.replace(/\${(\w+)}/g, function (found, argKey) { var _formattedArgs$argKey; return (_formattedArgs$argKey = formattedArgs[argKey]) !== null && _formattedArgs$argKey !== void 0 ? _formattedArgs$argKey : found; }); // remove optional args (from end only) var optionalArgs = Object.keys(funcConfig.args || {}).reverse().filter(function (argKey) { return !!funcConfig.args[argKey].isOptional; }); var _iterator2 = _createForOfIteratorHelper(optionalArgs), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var _argKey = _step2.value; if (formattedArgs[_argKey] != undefined) break; ret = ret.replace(new RegExp("(, )?" + "\\${" + _argKey + "}", "g"), ""); } // missing required arg vals } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } ret = ret.replace(/\${(\w+)}/g, "null"); } else { meta.errors.push("Func ".concat(funcKey, " is not supported")); } // tip: returnType should equal valueType return { value: ret, valueSrc: "func", valueType: funcConfig.returnType }; };