@elastic/eui
Version:
Elastic UI Component Library
605 lines (601 loc) • 21.5 kB
JavaScript
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
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) { _defineProperty(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; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
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 _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
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 _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { isArray, isNil } from '../../../services/predicate';
import { dateValuesEqual, isDateValue } from './date_value';
export var Match = Object.freeze({
MUST: 'must',
MUST_NOT: 'must_not',
isMust: function isMust(match) {
return match === Match.MUST;
},
isMustClause: function isMustClause(clause) {
return Match.isMust(clause.match);
}
});
export var Operator = Object.freeze({
EQ: 'eq',
EXACT: 'exact',
GT: 'gt',
GTE: 'gte',
LT: 'lt',
LTE: 'lte',
isEQ: function isEQ(match) {
return match === Operator.EQ;
},
isEQClause: function isEQClause(clause) {
return Field.isInstance(clause) && Operator.isEQ(clause.operator);
},
isEXACT: function isEXACT(match) {
return match === Operator.EXACT;
},
isEXACTClause: function isEXACTClause(clause) {
return Field.isInstance(clause) && Operator.isEXACT(clause.operator);
},
isRange: function isRange(match) {
return Operator.isGT(match) || Operator.isGTE(match) || Operator.isLT(match) || Operator.isLTE(match);
},
isRangeClause: function isRangeClause(clause) {
return Field.isInstance(clause) && Operator.isRange(clause.operator);
},
isGT: function isGT(match) {
return match === Operator.GT;
},
isGTClause: function isGTClause(clause) {
return Field.isInstance(clause) && Operator.isGT(clause.operator);
},
isGTE: function isGTE(match) {
return match === Operator.GTE;
},
isGTEClause: function isGTEClause(clause) {
return Field.isInstance(clause) && Operator.isGTE(clause.operator);
},
isLT: function isLT(match) {
return match === Operator.LT;
},
isLTClause: function isLTClause(clause) {
return Field.isInstance(clause) && Operator.isLT(clause.operator);
},
isLTE: function isLTE(match) {
return match === Operator.LTE;
},
isLTEClause: function isLTEClause(clause) {
return Field.isInstance(clause) && Operator.isLTE(clause.operator);
}
});
var Term = Object.freeze({
TYPE: 'term',
isInstance: function isInstance(clause) {
return clause.type === Term.TYPE;
},
must: function must(value) {
return {
type: Term.TYPE,
value: value,
match: Match.MUST
};
},
mustNot: function mustNot(value) {
return {
type: Term.TYPE,
value: value,
match: Match.MUST_NOT
};
}
});
var Group = Object.freeze({
TYPE: 'group',
isInstance: function isInstance(clause) {
return clause.type === Group.TYPE;
},
must: function must(value) {
return {
type: Group.TYPE,
value: value,
match: Match.MUST
};
},
mustNot: function mustNot(value) {
return {
type: Group.TYPE,
value: value,
match: Match.MUST_NOT
};
}
});
var Field = Object.freeze({
TYPE: 'field',
isInstance: function isInstance(clause) {
return clause.type === Field.TYPE;
},
must: {
eq: function eq(field, value) {
return {
type: Field.TYPE,
field: field,
value: value,
match: Match.MUST,
operator: Operator.EQ
};
},
exact: function exact(field, value) {
return {
type: Field.TYPE,
field: field,
value: value,
match: Match.MUST,
operator: Operator.EXACT
};
},
gt: function gt(field, value) {
return {
type: Field.TYPE,
field: field,
value: value,
match: Match.MUST,
operator: Operator.GT
};
},
gte: function gte(field, value) {
return {
type: Field.TYPE,
field: field,
value: value,
match: Match.MUST,
operator: Operator.GTE
};
},
lt: function lt(field, value) {
return {
type: Field.TYPE,
field: field,
value: value,
match: Match.MUST,
operator: Operator.LT
};
},
lte: function lte(field, value) {
return {
type: Field.TYPE,
field: field,
value: value,
match: Match.MUST,
operator: Operator.LTE
};
}
},
mustNot: {
eq: function eq(field, value) {
return {
type: Field.TYPE,
field: field,
value: value,
match: Match.MUST_NOT,
operator: Operator.EQ
};
},
exact: function exact(field, value) {
return {
type: Field.TYPE,
field: field,
value: value,
match: Match.MUST_NOT,
operator: Operator.EXACT
};
},
gt: function gt(field, value) {
return {
type: Field.TYPE,
field: field,
value: value,
match: Match.MUST_NOT,
operator: Operator.GT
};
},
gte: function gte(field, value) {
return {
type: Field.TYPE,
field: field,
value: value,
match: Match.MUST_NOT,
operator: Operator.GTE
};
},
lt: function lt(field, value) {
return {
type: Field.TYPE,
field: field,
value: value,
match: Match.MUST_NOT,
operator: Operator.LT
};
},
lte: function lte(field, value) {
return {
type: Field.TYPE,
field: field,
value: value,
match: Match.MUST_NOT,
operator: Operator.LTE
};
}
}
});
var Is = Object.freeze({
TYPE: 'is',
isInstance: function isInstance(clause) {
return clause.type === Is.TYPE;
},
must: function must(flag) {
return {
type: Is.TYPE,
flag: flag,
match: Match.MUST
};
},
mustNot: function mustNot(flag) {
return {
type: Is.TYPE,
flag: flag,
match: Match.MUST_NOT
};
}
});
var valuesEqual = function valuesEqual(v1, v2) {
if (isDateValue(v1)) {
return dateValuesEqual(v1, v2);
}
return v1 === v2;
};
var arrayIncludesValue = function arrayIncludesValue(array, value) {
return array.some(function (item) {
return valuesEqual(item, value);
});
};
var mustToMatch = function mustToMatch(must) {
return must === true ? Match.MUST : Match.MUST_NOT;
};
/**
* The AST structure is an array of clauses. There are 3 types of clauses that are supported:
*
* :term:
* Holds a VALUE and an OCCUR. The OCCUR indicates whether the value must match or must not match. Default
* clauses are not associated with any specific field - when executing the search, one can specify what are
* the default fields that the default clauses will be matched against.
*
* :field:
* Like the `term` clause, holds a VALUE and an MATCH, but this clause also specifies the field that the
* value will be matched against.
*
* :is:
* Holds a FLAG and indicates whether this flag must be applied or must not be applied. Typically this clause
* matches against boolean values of a record (e.g. "is:online", "is:internal", "is:on", etc..)
*
* This AST is immutable - every "mutating" operation returns a newly mutated AST.
*/
export var _AST = /*#__PURE__*/function () {
function _AST() {
var _this = this;
var clauses = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
_classCallCheck(this, _AST);
_defineProperty(this, "_clauses", void 0);
_defineProperty(this, "_indexedClauses", void 0);
this._clauses = clauses;
this._indexedClauses = {
field: {},
is: {},
term: [],
group: []
};
clauses.forEach(function (clause) {
switch (clause.type) {
case Field.TYPE:
if (!_this._indexedClauses.field[clause.field]) {
_this._indexedClauses.field[clause.field] = [];
}
_this._indexedClauses.field[clause.field].push(clause);
break;
case Is.TYPE:
_this._indexedClauses.is[clause.flag] = clause;
break;
case Term.TYPE:
_this._indexedClauses.term.push(clause);
break;
case Group.TYPE:
_this._indexedClauses.group.push(clause);
break;
default:
// @ts-ignore TS knows we have exhausted the match
throw new Error("Unknown query clause type [".concat(clause.type, "]"));
}
});
}
_createClass(_AST, [{
key: "clauses",
get: function get() {
return this._clauses;
}
}, {
key: "getTermClauses",
value: function getTermClauses() {
return this._indexedClauses.term;
}
}, {
key: "getTermClause",
value: function getTermClause(value) {
var clauses = this.getTermClauses();
return clauses.find(function (clause) {
return valuesEqual(clause.value, value);
});
}
}, {
key: "getFieldNames",
value: function getFieldNames() {
return Object.keys(this._indexedClauses.field);
}
}, {
key: "getFieldClauses",
value: function getFieldClauses(field) {
return field ? this._indexedClauses.field[field] : this._clauses.filter(Field.isInstance);
}
}, {
key: "getFieldClause",
value: function getFieldClause(field, predicate) {
var clauses = this.getFieldClauses(field);
if (clauses) {
return clauses.find(predicate);
}
}
}, {
key: "hasOrFieldClause",
value: function hasOrFieldClause(field, value) {
var clause = this.getFieldClause(field, function (clause) {
return isArray(clause.value);
});
if (!clause) {
return false;
}
// We can apply this type cast due to the `isArray` filter above
return isNil(value) || arrayIncludesValue(clause.value, value);
}
}, {
key: "getOrFieldClause",
value: function getOrFieldClause(field, value, must, operator) {
return this.getFieldClause(field, function (clause) {
if (!isArray(clause.value)) {
return false;
}
var matchValue = isNil(value) || arrayIncludesValue(clause.value, value);
var matchMust = isNil(must) || mustToMatch(must) === clause.match;
var matchOperator = isNil(operator) || operator === clause.operator;
return matchValue && matchMust && matchOperator;
});
}
}, {
key: "addOrFieldValue",
value: function addOrFieldValue(field, value) {
var must = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
var operator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : Operator.EQ;
var existingClause = this.getOrFieldClause(field, undefined, must, operator);
if (!existingClause) {
var newClause = must ? Field.must[operator](field, [value]) : Field.mustNot[operator](field, [value]);
return new _AST([].concat(_toConsumableArray(this._clauses), [newClause]));
}
var clauses = this._clauses.map(function (clause) {
if (clause === existingClause) {
clause.value.push(value);
}
return clause;
});
return new _AST(clauses);
}
}, {
key: "removeOrFieldValue",
value: function removeOrFieldValue(field, value) {
var existingClause = this.getOrFieldClause(field, value);
if (!existingClause) {
return new _AST(_toConsumableArray(this._clauses));
}
var clauses = this._clauses.reduce(function (clauses, clause) {
if (clause !== existingClause) {
clauses.push(clause);
return clauses;
}
var filteredValue = clause.value.filter(function (val) {
return !valuesEqual(val, value);
});
if (filteredValue.length === 0) {
return clauses;
}
clauses.push(_objectSpread(_objectSpread({}, clause), {}, {
value: filteredValue
}));
return clauses;
}, []);
return new _AST(clauses);
}
}, {
key: "removeOrFieldClauses",
value: function removeOrFieldClauses(field) {
var clauses = this._clauses.filter(function (clause) {
return !Field.isInstance(clause) || clause.field !== field || !isArray(clause.value);
});
return new _AST(clauses);
}
}, {
key: "hasSimpleFieldClause",
value: function hasSimpleFieldClause(field, value) {
var clause = this.getFieldClause(field, function (clause) {
return !isArray(clause.value);
});
if (!clause) {
return false;
}
return isNil(value) || valuesEqual(clause.value, value);
}
}, {
key: "getSimpleFieldClause",
value: function getSimpleFieldClause(field, value) {
return this.getFieldClause(field, function (clause) {
return !isArray(clause.value) && (isNil(value) || valuesEqual(clause.value, value));
});
}
}, {
key: "addSimpleFieldValue",
value: function addSimpleFieldValue(field, value) {
var must = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
var operator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : Operator.EQ;
var clause = must ? Field.must[operator](field, value) : Field.mustNot[operator](field, value);
return this.addClause(clause);
}
}, {
key: "removeSimpleFieldValue",
value: function removeSimpleFieldValue(field, value) {
var existingClause = this.getSimpleFieldClause(field, value);
if (!existingClause) {
return new _AST(_toConsumableArray(this._clauses));
}
var clauses = this._clauses.filter(function (clause) {
return clause !== existingClause;
});
return new _AST(clauses);
}
}, {
key: "removeSimpleFieldClauses",
value: function removeSimpleFieldClauses(field) {
var clauses = this._clauses.filter(function (clause) {
return !Field.isInstance(clause) || clause.field !== field || isArray(clause.value);
});
return new _AST(clauses);
}
}, {
key: "getIsClauses",
value: function getIsClauses() {
return Object.values(this._indexedClauses.is);
}
}, {
key: "getIsClause",
value: function getIsClause(flag) {
return this._indexedClauses.is[flag];
}
}, {
key: "removeIsClause",
value: function removeIsClause(flag) {
return new _AST(this._clauses.filter(function (clause) {
return !Is.isInstance(clause) || clause.flag !== flag;
}));
}
}, {
key: "removeIsClauses",
value: function removeIsClauses() {
return new _AST(this._clauses.filter(function (clause) {
return !Is.isInstance(clause);
}));
}
}, {
key: "removeAllClauses",
value: function removeAllClauses() {
return new _AST();
}
}, {
key: "getGroupClauses",
value: function getGroupClauses() {
return Object.values(this._indexedClauses.group);
}
/**
* Creates and returns a new AST with the given clause added to the current clauses. If
* the current clauses already include a similar clause, it will be (in-place) replaced by
* the given clause. Whether a clause is similar to the given one depends on the type of the clause.
* Two clauses are similar if:
*
* - they are both of the same type
* - if they are `default` clauses, they must have the same value
* - if they are `term` clauses, they must have the same fields and values
* - if they are `is` clauses, they must have the same flags
*
* The reasoning behind not including the `match` attributes of the clauses in the rules above, stems
* in the fact that the AST clauses are ANDed, and having two similar clauses with two different
* match attributes creates a logically contradicted AST (e.g. what does it mean to
* "(must have x) AND (must not have x)"?)
*
* note: in-place replacement means the given clause will be placed in the same position as the one it
* replaced
*/
}, {
key: "addClause",
value: function addClause(newClause) {
var added = false;
var newClauses = this._clauses.reduce(function (clauses, clause) {
if (newClause.type !== clause.type) {
clauses.push(clause);
return clauses;
}
switch (newClause.type) {
case Term.TYPE:
if (newClause.value !== clause.value) {
clauses.push(clause);
return clauses;
}
break;
case Field.TYPE:
if (newClause.field !== clause.field || newClause.value !== clause.value) {
clauses.push(clause);
return clauses;
}
break;
case Is.TYPE:
if (newClause.flag !== clause.flag) {
clauses.push(clause);
return clauses;
}
break;
default:
throw new Error("unknown clause type [".concat(newClause.type, "]"));
}
added = true;
clauses.push(newClause);
return clauses;
}, []);
if (!added) {
newClauses.push(newClause);
}
return new _AST(newClauses);
}
}], [{
key: "create",
value: function create(clauses) {
return new _AST(clauses);
}
}]);
return _AST;
}();
export var AST = Object.freeze({
Match: Match,
Operator: Operator,
Term: Term,
Group: Group,
Field: Field,
Is: Is,
create: function create(clauses) {
return new _AST(clauses);
}
});