UNPKG

react-redux-provide

Version:

Build your UI with React. Manage application state with Redux providers. Persist and share application state with replication. Use pure functions everywhere.

1,351 lines (1,117 loc) 39.3 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; exports.default = instantiateProvider; exports.getTempFauxInstance = getTempFauxInstance; exports.getFromContextOrProps = getFromContextOrProps; exports.getProviders = getProviders; exports.getProviderInstances = getProviderInstances; exports.getActiveQueries = getActiveQueries; exports.getQueryResults = getQueryResults; exports.getPartialStates = getPartialStates; exports.getFunctionOrObject = getFunctionOrObject; exports.getQueries = getQueries; exports.getQuery = getQuery; exports.getQueryOptions = getQueryOptions; exports.getQueriesOptions = getQueriesOptions; exports.getQueryHandlers = getQueryHandlers; exports.getMergedResult = getMergedResult; exports.resultsEqual = resultsEqual; exports.handleQueries = handleQueries; var _shallowEqual = require('./shallowEqual'); var _shallowEqual2 = _interopRequireDefault(_shallowEqual); var _getRelevantKeys = require('./getRelevantKeys'); var _getRelevantKeys2 = _interopRequireDefault(_getRelevantKeys); var _createProviderStore = require('./createProviderStore'); var _createProviderStore2 = _interopRequireDefault(_createProviderStore); var _keyConcats = require('./keyConcats'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var isServerSide = typeof window === 'undefined'; var isTesting = typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'test'; var globalProviderInstances = {}; // TODO: we'll use this at some point to select only component propTypes /* function hasReducerKeys(providerInstance, getReducerKeys) { if (!getReducerKeys) { return true; } const { hasReducerKeys = {} } = providerInstance; for (let reducerKey in getReducerKeys) { if (!hasReducerKeys[reducerKey]) { providerInstance.hasReducerKeys = { ...hasReducerKeys, ...getReducerKeys }; return false; } } return true; }*/ /** * Instantiates a provider with its own store. * * @param {Object} fauxInstance resembles { props, context } * @param {Object} provider * @param {String|Function} providerKey Optional * @param {Function} readyCallback Optional * @param {Object} createState Optional * @param {Object} getReducerKeys Optional * @param {Boolean} useCreator Optional * @return {Object} * @api public */ function instantiateProvider(fauxInstance, provider, providerKey, readyCallback, createState, getReducerKeys, useCreator // TODO: clean this up ) { if (arguments.length === 1) { fauxInstance = arguments[0].fauxInstance; provider = arguments[0].provider; providerKey = arguments[0].providerKey; readyCallback = arguments[0].readyCallback; createState = arguments[0].createState; getReducerKeys = arguments[0].getReducerKeys; useCreator = arguments[0].useCreator; if (!fauxInstance) { provider = arguments[0]; fauxInstance = {}; } } if (!fauxInstance.props) { fauxInstance.props = {}; } if (typeof providerKey === 'undefined') { providerKey = provider.key; } if (!provider.actions) { provider.actions = {}; } if (!provider.reducers) { provider.reducers = {}; } if (getReducerKeys === true) { getReducerKeys = provider.reducers; } var providers = getProviders(fauxInstance); var providerInstances = getProviderInstances(fauxInstance); var providerInstance = void 0; var isStatic = typeof providerKey !== 'function'; var storeKey = void 0; var creator = void 0; if (typeof provider.key === 'string') { if (!providers[provider.key]) { providers[provider.key] = provider; } } else if (provider.defaultKey) { if (!providers[provider.defaultKey]) { providers[provider.defaultKey] = provider; } } else if (!provider.key || !provider.key.toString) { console.warn('Missing or invalid provider key!'); } else if (!providers[provider.key.toString()]) { providers[provider.key.toString()] = provider; } if (!isStatic) { // get actual `providerKey` providerKey = providerKey(fauxInstance); // if actual `providerKey` matches `key`, treat as static provider isStatic = providerKey === provider.key; } if (providerKey === null) { storeKey = null; providerKey = provider.defaultKey; isStatic = true; } providerInstance = provider.isGlobal ? globalProviderInstances[providerKey] : providerInstances && providerInstances[providerKey]; if (fauxInstance.relevantProviders) { fauxInstance.relevantProviders[providerKey] = true; } if (createState && (typeof createState === 'undefined' ? 'undefined' : _typeof(createState)) === 'object' && provider.state && _typeof(provider.state) === 'object') { createState = _extends({}, provider.state, createState); } // TODO: we'll use this at some point //if (providerInstance && hasReducerKeys(providerInstance, getReducerKeys)) { if (providerInstance) { if (createState) { if (useCreator) { // TODO: clean this up creator = providerInstance; } else { providerInstances[providerKey] = providerInstance; providerInstance.store.setState(createState, false, true); if (readyCallback) { if (providerInstance.ready) { readyCallback(providerInstance); } else { (0, _keyConcats.pushOnReady)({ providerInstance: providerInstance }, readyCallback); } } return providerInstance; } } else { providerInstances[providerKey] = providerInstance; if (readyCallback) { if (providerInstance.ready) { readyCallback(providerInstance); } else { (0, _keyConcats.pushOnReady)({ providerInstance: providerInstance }, readyCallback); } } return providerInstance; } } if (!provider.hasThunk) { var findProvider = function findProvider(props) { if ((0, _getRelevantKeys2.default)(provider.reducers, props).length) { return provider; } for (var key in providers) { if ((0, _getRelevantKeys2.default)(providers[key].reducers, props).length) { return providers[key]; } } return provider; }; var getResultInstances = function getResultInstances(result, callback) { var resultInstances = []; var semaphore = result && result.length; function clear() { if (--semaphore === 0) { callback(resultInstances); } } if (!semaphore) { semaphore = 1; clear(); return; } result.forEach(function (resultProps, index) { resultInstances[index] = null; instantiateProvider({ fauxInstance: getTempFauxInstance(fauxInstance, resultProps), provider: findProvider(resultProps), readyCallback: function readyCallback(resultInstance) { resultInstances[index] = resultInstance; clear(); } }); }); }; var getInstance = function getInstance(props, callback, create, useCreator) { var provider = void 0; var providerKey = void 0; if (typeof props === 'string') { // key is already known if (providerInstances[props]) { providerKey = props; } provider = providers[props] || providerInstances[props]; props = {}; } else { provider = findProvider(props); } return instantiateProvider({ fauxInstance: getTempFauxInstance(fauxInstance, props), provider: provider, providerKey: providerKey, readyCallback: callback, createState: create ? props : null, useCreator: useCreator }); }; var getInstances = function getInstances(propsArray, callback, create, useCreator) { var instances = []; var getCount = propsArray.length; var clear = function clear() { if (--getCount === 0) { if (callback) { callback(instances); } } }; propsArray.forEach(function (props, index) { getInstance(props, function (instance) { instances[index] = instance; clear(); }, create); }); return instances; }; var createInstance = function createInstance(props, callback, useCreator) { return getInstance(props, callback, true, useCreator); }; var createInstances = function createInstances(propsArray, callback, useCreator) { return getInstances(propsArray, callback, true, useCreator); }; var setStates = function setStates(states) { var gettingInstances = []; var settingStates = []; var clientStates = null; if (!isServerSide) { if (!window.clientStates) { window.clientStates = {}; } clientStates = window.clientStates; } var _loop = function _loop(_providerKey) { var state = states[_providerKey]; var providerInstance = providerInstances[_providerKey]; if (providerInstance) { if (providerInstance.store.setState) { settingStates.push(function () { return providerInstance.store.setState(state); }); } } else { if (clientStates) { clientStates[_providerKey] = state; } gettingInstances.push(state); } }; for (var _providerKey in states) { _loop(_providerKey); } // now that `clientStates` are cached... while (gettingInstances.length) { getInstance(gettingInstances.shift()); } while (settingStates.length) { settingStates.shift()(); } }; var find = function find(props, doInstantiate, callback) { if (arguments.length === 2) { callback = doInstantiate; doInstantiate = false; } handleQueries(getTempFauxInstance(fauxInstance, props), function () { if (!doInstantiate) { callback(props.query ? props.result : props.results); return; } if (props.query) { getResultInstances(props.result, callback); return; } var results = props.results; var resultsInstances = {}; var resultsKeys = results && Object.keys(results); var semaphore = resultsKeys && resultsKeys.length; function clear() { if (--semaphore === 0) { callback(resultsInstances); } } if (!semaphore) { semaphore = 1; clear(); } resultsKeys.forEach(function (resultKey) { resultsInstances[resultKey] = []; getResultInstances(results[resultKey], function (resultInstances) { resultsInstances[resultKey] = resultInstances; clear(); }); }); }); }; provider.hasThunk = true; if (provider.wait && !Array.isArray(provider.wait)) { provider.wait = [provider.wait]; } if (provider.clear && !Array.isArray(provider.clear)) { provider.clear = [provider.clear]; } var providerApi = { getInstance: getInstance, getInstances: getInstances, createInstance: createInstance, createInstances: createInstances, setStates: setStates, find: find }; (0, _keyConcats.unshiftMiddleware)({ provider: provider }, function (_ref) { var dispatch = _ref.dispatch, getState = _ref.getState; return function (next) { return function (action) { if (typeof action !== 'function') { return next(action); } if (provider.wait) { provider.wait.forEach(function (fn) { return fn(); }); } return action(function (action) { var state = store.getState(); var storeChanged = false; dispatch(action); if (provider.clear) { storeChanged = state !== store.getState(); provider.clear.forEach(function (fn) { return fn(storeChanged); }); } }, getState, providerApi); }; }; }); } if (provider.wait) { provider.wait.forEach(function (fn) { return fn(); }); } providerInstance = Object.create(provider); providerInstance.providerKey = providerKey; providerInstance.isStatic = isStatic; var store = (0, _createProviderStore2.default)(providerInstance, storeKey, createState, createState ? function (state) { var _providerInstance = providerInstance, onReady = _providerInstance.onReady; providerInstance = instantiateProvider({ fauxInstance: getTempFauxInstance(fauxInstance, state), provider: provider, readyCallback: function readyCallback(createdInstance) { if (Array.isArray(onReady)) { onReady.forEach(function (fn) { return fn(createdInstance); }); } else if (onReady) { onReady(createdInstance); } } }); } : null, // TODO: we need a better way to create + replicate creator && creator.store); var initialState = store.getState(); var _providerInstance2 = providerInstance, actions = _providerInstance2.actions; var actionCreators = {}; var setKey = store.setKey; if (setKey) { store.setKey = function (newKey, readyCallback) { if (provider.wait) { provider.wait.forEach(function (fn) { return fn(); }); } setKey(newKey, function () { if (Array.isArray(providerInstance.onReady)) { providerInstance.onReady.forEach(function (fn) { return fn(providerInstance); }); } else if (providerInstance.onReady) { providerInstance.onReady(providerInstance); } if (readyCallback) { readyCallback(); } if (provider.clear) { provider.clear.forEach(function (fn) { return fn(true); }); } }); }; } var _loop2 = function _loop2(actionKey) { actionCreators[actionKey] = function () { return store.dispatch(actions[actionKey].apply(this, arguments)); }; }; for (var actionKey in actions) { _loop2(actionKey); } providerInstance.store = store; providerInstance.actionCreators = actionCreators; if (!createState) { if (provider.isGlobal) { globalProviderInstances[providerKey] = providerInstance; } if (providerInstances) { providerInstances[providerKey] = providerInstance; } if (!provider.instances) { provider.instances = []; } provider.instances.push(providerInstance); } if (provider.subscribers) { Object.keys(provider.subscribers).forEach(function (key) { var handler = provider.subscribers[key]; var subProvider = providers[key]; var subKey = provider.defaultKey || (typeof provider.key === 'function' ? provider.key({}) : String(provider.key)); var callHandler = function callHandler() { var subProviderInstances = subProvider && subProvider.instances; if (subProviderInstances) { subProviderInstances.forEach(function (subProviderInstance) { handler(providerInstance, subProviderInstance); }); } }; if (subProvider) { if (!subProvider.subscribeTo) { subProvider.subscribeTo = {}; } if (!subProvider.subscribeTo[subKey]) { subProvider.subscribeTo[subKey] = handler; } } providerInstance.store.subscribe(callHandler); callHandler(); }); } if (provider.subscribeTo) { Object.keys(provider.subscribeTo).forEach(function (key) { var handler = provider.subscribeTo[key]; var supProvider = providers[key]; var supKey = provider.defaultKey || (typeof provider.key === 'function' ? provider.key({}) : String(provider.key)); if (!supProvider) { return; } if (!supProvider.subscribers) { supProvider.subscribers = {}; } if (!supProvider.subscribers[supKey]) { supProvider.subscribers[supKey] = handler; if (supProvider.instances) { supProvider.instances.forEach(function (supProviderInstance) { supProviderInstance.store.subscribe(function () { provider.instances.forEach(function (providerInstance) { handler(supProviderInstance, providerInstance); }); }); }); } } if (supProvider.instances) { supProvider.instances.forEach(function (supProviderInstance) { handler(supProviderInstance, providerInstance); }); } }); } if (!createState) { if (Array.isArray(providerInstance.onInstantiated)) { providerInstance.onInstantiated.forEach(function (fn) { return fn(providerInstance); }); } else if (providerInstance.onInstantiated) { providerInstance.onInstantiated(providerInstance); } } (0, _keyConcats.unshiftOnReady)({ providerInstance: providerInstance }, function () { providerInstance.ready = true; }); if (readyCallback) { (0, _keyConcats.pushOnReady)({ providerInstance: providerInstance }, readyCallback); } function done() { if (Array.isArray(providerInstance.onReady)) { providerInstance.onReady.forEach(function (fn) { return fn(providerInstance); }); } else if (providerInstance.onReady) { providerInstance.onReady(providerInstance); } if (provider.clear) { var storeChanged = initialState !== providerInstance.store.getState(); provider.clear.forEach(function (fn) { return fn(storeChanged); }); } } if (provider.replication && store.onReady && !store.initializedReplication) { store.onReady(done); } else { done(); } return providerInstance; } function getContext(fauxInstance) { if (!fauxInstance.context) { fauxInstance.context = {}; } return fauxInstance.context; } function getTempFauxInstance(fauxInstance, props) { return { props: props, context: getContext(fauxInstance), providers: getProviders(fauxInstance), providerInstances: getProviderInstances(fauxInstance), activeQueries: getActiveQueries(fauxInstance), queryResults: getQueryResults(fauxInstance), partialStates: getPartialStates(fauxInstance) }; } function getFromContextOrProps(fauxInstance, key, defaultValue) { if (typeof fauxInstance[key] === 'undefined') { var props = fauxInstance.props; var context = getContext(fauxInstance); if (typeof props[key] !== 'undefined') { fauxInstance[key] = props[key]; } else if (typeof context[key] !== 'undefined') { fauxInstance[key] = context[key]; } else { fauxInstance[key] = defaultValue; } } return fauxInstance[key]; } function getProviders(fauxInstance) { return getFromContextOrProps(fauxInstance, 'providers', {}); } function getProviderInstances(fauxInstance) { return getFromContextOrProps(fauxInstance, 'providerInstances', {}); } function getActiveQueries(fauxInstance) { return getFromContextOrProps(fauxInstance, 'activeQueries', {}); } function getQueryResults(fauxInstance) { return getFromContextOrProps(fauxInstance, 'queryResults', {}); } function getPartialStates(fauxInstance) { return getFromContextOrProps(fauxInstance, 'partialStates', {}); } function getFunctionOrObject(fauxInstance, key) { var defaultValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; if (typeof fauxInstance[key] !== 'undefined') { return fauxInstance[key]; } var value = fauxInstance.props[key]; if (typeof value === 'function') { value = value(fauxInstance); } fauxInstance[key] = value || defaultValue; return fauxInstance[key]; } function getQueries(fauxInstance) { if (getQueries.disabled) { return false; } if (typeof fauxInstance.queries !== 'undefined') { return fauxInstance.queries; } var props = fauxInstance.props, relevantProviders = fauxInstance.relevantProviders; var providers = getProviders(fauxInstance); var query = getQuery(fauxInstance); var queries = getFunctionOrObject(fauxInstance, 'queries'); var hasQueries = false; if (query) { // we need to map the query to relevant provider(s) if (!queries) { queries = {}; } else if (typeof props.queries !== 'function') { queries = _extends({}, queries); } for (var key in providers) { var provider = providers[key]; var queryKeys = (0, _getRelevantKeys2.default)(provider.reducers, query); if (queryKeys.length) { // provider is relevant, so we map it within the queries object if (!queries[key]) { queries[key] = {}; } var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = queryKeys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var queryKey = _step.value; queries[key][queryKey] = query[queryKey]; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } } } for (var _key in queries) { var _query = queries[_key]; if (typeof _query === 'function') { queries[_key] = _query(fauxInstance); } // make sure each provider is instantiated instantiateProvider(fauxInstance, providers[_key]); hasQueries = true; } if (!hasQueries) { queries = null; if (props.query) { props.result = null; } if (props.queries) { props.results = {}; } } fauxInstance.queries = queries; return queries; } function getQuery(fauxInstance) { return getFunctionOrObject(fauxInstance, 'query'); } function getQueryOptions(fauxInstance) { return getFunctionOrObject(fauxInstance, 'queryOptions'); } function getQueriesOptions(fauxInstance) { return getFunctionOrObject(fauxInstance, 'queriesOptions', {}); } // gets all `handleQuery` functions within replicators function getQueryHandlers(provider) { var queryHandlers = []; var replication = provider.replication; if (replication) { if (!Array.isArray(replication)) { replication = [replication]; } var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = replication[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var _ref3 = _step2.value; var replicator = _ref3.replicator, reducerKeys = _ref3.reducerKeys, baseQuery = _ref3.baseQuery, baseQueryOptions = _ref3.baseQueryOptions; if (replicator) { if (!Array.isArray(replicator)) { replicator = [replicator]; } var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = replicator[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var _ref5 = _step3.value; var handleQuery = _ref5.handleQuery; if (handleQuery) { queryHandlers.push({ handleQuery: handleQuery, reducerKeys: reducerKeys || Object.keys(provider.reducers), baseQuery: baseQuery, baseQueryOptions: baseQueryOptions }); } } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } return queryHandlers; } function getMergedResult(mergedResult, result) { if (Array.isArray(result)) { return [].concat(_toConsumableArray(mergedResult || []), _toConsumableArray(result)); } else if (result && (typeof result === 'undefined' ? 'undefined' : _typeof(result)) === 'object' && result.constructor === Object) { return _extends({}, mergedResult || {}, result); } else if (typeof result !== 'undefined') { return result; } else { return mergedResult; } } function resultsEqual(result, previousResult) { if (result === previousResult) { return true; } if ((typeof result === 'undefined' ? 'undefined' : _typeof(result)) !== (typeof previousResult === 'undefined' ? 'undefined' : _typeof(previousResult))) { return false; } if (Array.isArray(result)) { if (Array.isArray(previousResult)) { var i = 0; var length = result.length; if (length !== previousResult.length) { return false; } while (i < length) { if (!(0, _shallowEqual2.default)(result[i], previousResult[i])) { return false; } i++; } } else { return false; } } else if (Array.isArray(previousResult)) { return false; } return (0, _shallowEqual2.default)(result, previousResult); } // this is admittedly a mess... :( // we're accounting for both synchronous and asynchronous query handling // where asynchronous results will override the synchronous results function handleQueries(fauxInstance, callback, previousResults) { var doUpdate = false; var queries = getQueries(fauxInstance); if (!queries) { if (callback) { callback(doUpdate); } return false; } var props = fauxInstance.props; var context = getContext(fauxInstance); var originalResult = props.result, originalResults = props.results; var validQuery = false; // for determining whether or not we should update if (!previousResults) { previousResults = _extends({}, props.results); } // get what we need to handle the queries var query = getQuery(fauxInstance); var queryOptions = getQueryOptions(fauxInstance); var queriesOptions = getQueriesOptions(fauxInstance); var activeQueries = getActiveQueries(fauxInstance); var queryResults = getQueryResults(fauxInstance); var partialStates = getPartialStates(fauxInstance); var providers = getProviders(fauxInstance); var providerInstances = getProviderInstances(fauxInstance); // TODO: we should probably do something better at some point var setPartialStates = function setPartialStates(provider, result) { if (!result || typeof result.map !== 'function' || !isServerSide) { return; } var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = result[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var partialState = _step4.value; var providerKey = provider.key; if (typeof providerKey === 'function') { providerKey = providerKey({ props: partialState, context: context }); } if (providerKey !== null && !providerInstances[providerKey]) { partialStates[providerKey] = partialState; } } } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4.return) { _iterator4.return(); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } }; // most queries should be async var queryCount = Object.keys(queries).length; var queryClear = function queryClear() { if (--queryCount === 0) { // at this point we have all our results if (callback) { callback(doUpdate); } } }; // merge each result into `props.result` if using `props.query` var setMergedResult = function setMergedResult(result) { if (props.query) { props.result = getMergedResult(props.result, result); } }; // go ahead and set null value if using `props.query` if (props.query) { props.result = null; } // results start out as an empty object props.results = {}; // check each query Object.keys(queries).forEach(function (key) { var provider = providers[key]; var queryHandlers = getQueryHandlers(provider); var handlerCount = queryHandlers.length; // no handlers? Y U DO DIS? if (!handlerCount) { queryClear(); return; } validQuery = true; // let the provider know we're waiting for all of the handlers to finish if (Array.isArray(provider.wait)) { provider.wait.forEach(function (fn) { return fn(); }); } else if (provider.wait) { provider.wait(); } // here we determine the `resultKey` used for caching the results // in the current context var query = queries[key]; var options = queryOptions || queriesOptions[key] || {}; var resultKey = JSON.stringify({ query: query, options: options }); var queryResult = queryResults[resultKey]; var queryResultExists = typeof queryResult !== 'undefined'; // subscribe to all of this provider's instances' stores for requeries subscribeToAll(key, provider, fauxInstance, resultKey, query, callback); // result handler for both sync and async queries var setResult = function setResult(result) { if (!activeQueries[resultKey]) { console.warn('setResult was called but the following query is no longer active:', { query: query, options: options }); return; } var first = activeQueries[resultKey].values().next().value; var leader = setResult === first; var previousResult = queryResultExists ? queryResult : previousResults[key]; var asyncReset = setResult.asyncReset; // if new result, set `doUpdate` flag if (!doUpdate && !resultsEqual(result, previousResult)) { doUpdate = true; } // a special `asyncReset` flag is set if async handler is detected; // we want async results to override sync if (asyncReset) { // this should only occur once, at the start of setting async results setResult.asyncReset = false; props.results = {}; if (props.query) { props.result = null; } } props.results[key] = result; previousResults[key] = result; queryResults[resultKey] = result; setMergedResult(result); // if this handler is the leader, we pass the result onto the others if (leader && activeQueries[resultKey]) { activeQueries[resultKey].forEach(function (otherSetResult) { if (otherSetResult !== setResult) { otherSetResult(result); } }); } if (--handlerCount === 0) { // handler is done, so remove self activeQueries[resultKey].delete(setResult); // if there are no handlers remaining, this query is no longer active if (!activeQueries[resultKey].size) { delete activeQueries[resultKey]; setPartialStates(provider, result); } // no more query handlers, so let the provider know we're done if (Array.isArray(provider.clear)) { provider.clear.forEach(function (fn) { return fn(doUpdate); }); } else if (provider.clear) { provider.clear(doUpdate); } // and this query is clear queryClear(); // we want to remove the cached query results on the client/tests // so that it will always update if (!isServerSide || isTesting) { delete queryResults[resultKey]; } } }; var setError = function setError(error) { console.error(error); }; // this query is currently taking place, make the handler follow the leader if (activeQueries[resultKey]) { activeQueries[resultKey].add(setResult); return; } // this is a new query, so this handler is a leader; // other handlers matching this `resultKey` will check // if the query is active and become a follower activeQueries[resultKey] = new Set(); activeQueries[resultKey].add(setResult); // already have our query result cached? // no point in calling any handlers; go ahead and set the result if (queryResultExists) { handlerCount = 1; setResult(queryResult); return; } // now we need to run the query through each `handleQuery` function, // which may or may not be synchronous queryHandlers.forEach(function (_ref6) { var handleQuery = _ref6.handleQuery, reducerKeys = _ref6.reducerKeys, baseQuery = _ref6.baseQuery, baseQueryOptions = _ref6.baseQueryOptions; // we can determine whether or not its synchronous by checking the // `handlerCount` immediately after `handleQuery` is called var handlerCountBefore = handlerCount; // normalize the query + options so that people can be lazy var normalizedQuery = _extends({}, baseQuery, query); var normalizedOptions = _extends({}, baseQueryOptions, options); if (typeof normalizedOptions.select === 'undefined') { normalizedOptions.select = reducerKeys === true ? Object.keys(provider.reducers) : reducerKeys; } else if (!Array.isArray(normalizedOptions.select)) { normalizedOptions.select = [normalizedOptions.select]; } if (Array.isArray(normalizedOptions.select)) { for (var reducerKey in normalizedQuery) { if (normalizedOptions.select.indexOf(reducerKey) < 0) { normalizedOptions.select.push(reducerKey); } } } handleQuery({ query: normalizedQuery, options: normalizedOptions, setResult: setResult, setError: setError }); if (handlerCount === handlerCountBefore) { // asynchronous query, so we set the `asyncReset` flags to true // only if they haven't been set to false yet activeQueries[resultKey].forEach(function (setResult) { setResult.asyncReset = setResult.asyncReset !== false; }); } }); }); if (!validQuery) { props.result = originalResult; props.results = originalResults; } return validQuery; } function subscribeToAll(key, provider, fauxInstance, resultKey, query, callback) { if (isServerSide || !fauxInstance.props.__wrapper) { return; } fauxInstance.requeryCallback = callback; if (!provider.subscribedFauxInstances) { provider.subscribedFauxInstances = {}; } if (provider.subscribedFauxInstances[resultKey]) { provider.subscribedFauxInstances[resultKey].add(fauxInstance); return; } var subscribedFauxInstances = new Set(); provider.subscribedFauxInstances[resultKey] = subscribedFauxInstances; subscribedFauxInstances.add(fauxInstance); var timeout = void 0; var requery = function requery(providerInstance) { clearTimeout(timeout); timeout = setTimeout(function () { var _iteratorNormalCompletion5 = true; var _didIteratorError5 = false; var _iteratorError5 = undefined; try { for (var _iterator5 = subscribedFauxInstances[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { var _fauxInstance = _step5.value; if (_fauxInstance.props.__wrapper.unmounted) { subscribedFauxInstances.delete(_fauxInstance); } else { handleQueries(_fauxInstance, _fauxInstance.requeryCallback); } } } catch (err) { _didIteratorError5 = true; _iteratorError5 = err; } finally { try { if (!_iteratorNormalCompletion5 && _iterator5.return) { _iterator5.return(); } } finally { if (_didIteratorError5) { throw _iteratorError5; } } } }); }; (0, _keyConcats.pushOnReady)({ provider: provider }, requery); if (!provider.subscriber) { provider.subscriber = {}; } var subscriber = provider.subscriber[key]; provider.subscriber[key] = function (providerInstance, providerInstance2) { if (subscriber) { subscriber(providerInstance, providerInstance2); } if (shouldRequery(providerInstance, query)) { requery(providerInstance); } }; if (provider.instances) { provider.instances.forEach(function (providerInstance) { providerInstance.store.subscribe(function () { if (shouldRequery(providerInstance, query)) { requery(providerInstance); } }); }); } } function shouldRequery(providerInstance, query) { var currentState = providerInstance.store.getState(); var lastQueriedState = providerInstance.lastQueriedState; providerInstance.lastQueriedState = currentState; if (!lastQueriedState) { return true; } if (currentState !== lastQueriedState) { if ((typeof query === 'undefined' ? 'undefined' : _typeof(query)) === 'object') { for (var key in query) { if (currentState[key] !== lastQueriedState[key]) { return true; } } } else { return true; } } return false; }