methods/fetch.js

import { search } from '@ecomplus/client'
import * as cloneDeep from 'lodash.clonedeep'
import dslMiddlewares from './../lib/dsl-middlewares'

export default (self, isSimpleSearch, axiosConfig) => {
  // mount axios req options for complex or simpĺe search
  const { storeId } = self
  const reqOptions = {
    url: '/items.json',
    storeId,
    axiosConfig
  }

  // prepare search DSL
  let dsl = cloneDeep(self.dsl)
  dslMiddlewares.forEach(fn => {
    if (typeof fn === 'function') {
      const _dsl = fn(dsl)
      if (_dsl) {
        dsl = _dsl
      }
    }
  })

  if (isSimpleSearch === true) {
    // https://www.elastic.co/guide/en/elasticsearch/reference/6.3/search-uri-request.html
    const { query } = dsl
    reqOptions.url += '?q='
    if (query && query.bool && Array.isArray(query.bool.filter)) {
      // parse query filters to string
      let queryString = ''
      query.bool.filter.forEach(({ term, terms }, i) => {
        if (i > 0) {
          queryString += ' AND '
        }
        const condition = term || terms
        if (condition) {
          const field = Object.keys(condition)[0]
          const value = condition[field]
          queryString += `${field}:${(Array.isArray(value) ? `("${value.join('" "')}")` : value)}`
        }
      })
      reqOptions.url += encodeURIComponent(queryString)
    }
    // handle pagination
    ;['from', 'size'].forEach(field => {
      if (dsl[field]) {
        reqOptions.url += `&${field}=${dsl[field]}`
      }
    })
  } else {
    reqOptions.method = 'post'
    reqOptions.data = dsl
    if (isSimpleSearch && !axiosConfig) {
      // fallback for old reference with `fetch(axiosConfig)`
      reqOptions.axiosConfig = isSimpleSearch
    }
  }

  // request Search API and return promise
  return search(reqOptions).then(({ data }) => {
    // save last result on instance
    self.result = data
    const { dsl, history, localStorage, storageKey } = self
    if (data.hits.total && dsl && dsl.suggest) {
      const { text } = dsl.suggest
      if (text) {
        // add search term to history
        const index = history.indexOf(text)
        if (index > -1) {
          // prevent duplicated term
          history.splice(index, 1)
        }
        history.unshift(text)
        if (localStorage && storageKey) {
          localStorage.setItem(storageKey, history.slice(0, 20).join('||'))
        }
      }
    }
    // resolving with response data
    return data
  })
}

/**
 * @typedef {object} result
 * @property {object} hits - Elasticsearch hits object
 * @property {number} hits.total - Total number of products found
 * @property {array<object>} hits.hits - List of resultant items
 * @property {object} aggregations - Elasticsearch aggregations results
 * @property {object} suggest - Search term suggestions object
 * @property {number} took - Request time in milliseconds
 */

/**
 * @method
 * @name EcomSearch#fetch
 * @description Send POST request to
 * [E-Com Plus Search API]{@link https://developers.e-com.plus/docs/api/#/search/items/items}
 * and returns promise resolved with search result.
 *
 * @param {boolean} [isSimpleSearch=false] - Handle simple (and faster) search without sort and aggregations
 * @param {object} [axiosConfig] - Additional
 * [axios config]{@link https://github.com/axios/axios#request-config} object
 *
 * @returns {Promise<result|error>}
 *
 * @example

// Run search request
search.fetch()
  .then(result => {
    console.log(result.took)
    console.log(`${result.hits.total} items found:`)
    console.log(result.hits.hits)
  })
  .catch(error => {
    console.error(error)
    if (error.response) {
      console.log(error.response)
    }
  })

 */