_injectContextVars()

in src/plugins/vis_type_vega/public/data_model/opensearch_query_parser.ts [253:355]


  _injectContextVars(obj: Query | SearchParams['body']['aggs'], isQuery: boolean) {
    if (obj && typeof obj === 'object') {
      if (Array.isArray(obj)) {
        // For arrays, replace MUST_CLAUSE and MUST_NOT_CLAUSE string elements
        for (let pos = 0; pos < obj.length; ) {
          const item = obj[pos];
          if (
            isQuery &&
            (item === FILTER_CLAUSE || item === MUST_CLAUSE || item === MUST_NOT_CLAUSE)
          ) {
            let ctxTag = '';
            switch (item) {
              case FILTER_CLAUSE:
                ctxTag = 'filter';
                break;
              case MUST_CLAUSE:
                ctxTag = 'must';
                break;
              case MUST_NOT_CLAUSE:
                ctxTag = 'must_not';
                break;
            }
            const ctx = cloneDeep(this._filters);
            if (ctx && ctx.bool && ctx.bool[ctxTag]) {
              if (Array.isArray(ctx.bool[ctxTag])) {
                // replace one value with an array of values
                obj.splice(pos, 1, ...ctx.bool[ctxTag]);
                pos += ctx.bool[ctxTag].length;
              } else {
                obj[pos++] = ctx.bool[ctxTag];
              }
            } else {
              obj.splice(pos, 1); // remove item, keep pos at the same position
            }
          } else {
            this._injectContextVars(item, isQuery);
            pos++;
          }
        }
      } else {
        for (const prop of Object.keys(obj)) {
          const subObj = (obj as ContextVarsObject)[prop];
          if (!subObj || typeof obj !== 'object') continue;

          // replace "interval": { "%autointerval%": true|integer } with
          // auto-generated range based on the timepicker
          if (prop === 'interval' && subObj[AUTOINTERVAL]) {
            let size = subObj[AUTOINTERVAL];
            if (size === true) {
              size = 50; // by default, try to get ~80 values
            } else if (typeof size !== 'number') {
              throw new Error(
                i18n.translate(
                  'visTypeVega.opensearchQueryParser.autointervalValueTypeErrorMessage',
                  {
                    defaultMessage: '{autointerval} must be either {trueValue} or a number',
                    values: {
                      autointerval: `"${AUTOINTERVAL}"`,
                      trueValue: 'true',
                    },
                  }
                )
              );
            }
            const bounds = this._timeCache.getTimeBounds();
            (obj as ContextVarsObject).interval = OpenSearchQueryParser._roundInterval(
              (bounds.max - bounds.min) / size
            );
            continue;
          }

          // handle %timefilter%
          switch (subObj[TIMEFILTER]) {
            case 'min':
            case 'max':
              // Replace {"%timefilter%": "min|max", ...} object with a timestamp
              (obj as ContextVarsObject)[prop] = this._getTimeBound(subObj, subObj[TIMEFILTER]);
              continue;
            case true:
              // Replace {"%timefilter%": true, ...} object with the "range" object
              this._createRangeFilter(subObj);
              continue;
            case undefined:
              this._injectContextVars(subObj, isQuery);
              continue;
            default:
              throw new Error(
                i18n.translate('visTypeVega.opensearchQueryParser.timefilterValueErrorMessage', {
                  defaultMessage:
                    '{timefilter} property must be set to {trueValue}, {minValue}, or {maxValue}',
                  values: {
                    timefilter: `"${TIMEFILTER}"`,
                    trueValue: 'true',
                    minValue: '"min"',
                    maxValue: '"max"',
                  },
                })
              );
          }
        }
      }
    }
  }