data-provider/core

Allow define custom method for Selector queries

Closed this issue · 0 comments

The problem

When a selector is queried recursively, the resultant query is the extension of all objects used as "query".

const queriedSelector = mySelectorInstance
  .query({foo: "var"})
  .query({foo2:"var2"});

console.log(queriedSelector.queryValue) // -> {foo:"var", foo2: "var2"}

In providers created with the Axios addon, this behavior changes, as the addon defines its own "queryMethod", and the result of applying recurrent queries is the extension of the queryParams and urlParams properties of the query objects, not the extension of the objects itself (it applies almost "deep" extend, instead of "extend"):

const queriedAxiosProvider = mySelectorInstance
  .query({urlParams: { foo:"var"}})
  .query({urlParams: {foo2:"var2"}});

console.log(queriedAxiosProvider.queryValue) // -> {urlParams: {foo:"var", foo2: "var2"}};

This difference in selector and providers query method is a pain point when you want to use a Selector as a proxy of an Axios provider, as you don't have the possibility to use recursive queries:

const proxySelector = new Selector(
  (query) => axiosProvider.query(query),
  (response) => response.results
)

// THIS WORKS ----- Examples using an unique query
axiosProvider
  .query({ queryString: { author: 1, sort: "asc" }})
  .read();
// Request to "/foo-url?author=1&sort=asc", then return response;

proxySelector
  .query({ queryString: { author: 1, sort: "asc" }})
  .read();
// Request to "/foo-url?author=1&sort=asc" (from cache), then return "results" property of the response;


// THIS DOESN'T WORK ----- Examples using recurrent queries
axiosProvider
  .query({ queryString: { author: 1 }})
  .query({ queryString: { sort: "asc" }})
  .read();
// Same request than the first one. Shared cache.

proxySelector
  .query({ queryString: { author: 1 }})
  .query({ queryString: { sort: "asc" }})
  .read();
/* Request to "/foo-url?sort=asc", then return "results" property of the response.
   The first `queryString` property is being overwritten
   because the selectors applies a simple extend for recurrent queries. */

Proposed solution

A getChildQueryMethod option can be added to Selectors configuration (same property name than the exposed in Provider Class for allowing addons to define its own behavior):

const proxySelector = new Selector(
  (query) => axiosProvider.query(query),
  (response) => response.results,
  {
    getChildQueryMethod: (newQuery, currentQuery) => {
      return {
        queryString: {
          ...currentQuery.queryString,
          ...newQuery.queryString,
        },
        urlParams: {
          ...currentQuery.urlParams,
          ...newQuery.urlParams,
        },
      };
    }
  }
);

// Now, all previous examples would work