UNPKG

@elastic/eui

Version:

Elastic UI Component Library

604 lines (600 loc) 20.8 kB
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 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; } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _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(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 _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } 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 _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /* * 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, "]")); } }); } return _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); } }]); }(); 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); } });