Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

re-reselect

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

re-reselect - npm Package Compare versions

Comparing version 1.0.1 to 2.0.0

src/cache/__tests__/deprecated/FifoCacheObject.js

69

CHANGELOG.md
# Change log
## 2.0.0
### Breaking Changes
* `cacheKey` values no more restricted by default to `number` or `string`
* `cacheKey` validation delegated to `cacheObject`'s `isValidCacheKey` method
* `selectorCreator` argument removed in favour of `options` object
* `console.warn` when `resolverFunction` returns invalid `cacheKey`
* `cacheObject` export names renamed _(old ones are deprecated)_:
* `FlatCacheObject` -> `FlatObjectCache`
* `FifoCacheObject` -> `FifoObjectCache`
* `LruCacheObject` -> `LruObjectCache`
### New Features
* Added 3 new `cacheObject` implementations using `ES Map` objects accepting any value as `cacheKey`:
* `FlatMapCache`
* `FifoMapCache`
* `LruMapCache`
* Add a `sideEffects: false` flag for Webpack 4
## 1.0.1
- Remove wrong line at the beginning of the docs
* Remove wrong line at the beginning of the docs
## 1.0.0
### Breaking Changes
- `selectorCreator` argument is deprecated in favor of an option object
* `selectorCreator` argument is deprecated in favour of an option object
### New Features
- Accept an option object to provide `cacheObject` and `selectorCreator` options
- Extract caching logic into pluggable/customizable cache objects
- Introduce `Rollup.js` as bundler
- Make compilation cross-platform
* Accept an option object to provide `cacheObject` and `selectorCreator` options
* Extract caching logic into pluggable/customizable cache objects
* Introduce `Rollup.js` as bundler
* Make compilation cross-platform
## 0.6.3
- Add TS type definition for optional `selectorCreator`
* Add TS type definition for optional `selectorCreator`
## 0.6.2
- Fix wrong UMD reselect global import
* Fix wrong UMD reselect global import
## 0.6.1
- Fix TypeScript `OutputCachedSelector` and `OutputParametricCachedSelector` type definitions
* Fix TypeScript `OutputCachedSelector` and `OutputParametricCachedSelector` type definitions
## 0.6.0
- Add TypeScript type definitions
* Add TypeScript type definitions
## 0.5.0
- Expose `resultFunc` attribute
* Expose `resultFunc` attribute
## 0.4.0
- Expose `removeMatchingSelector` method
- Expose `clearCache` method
* Expose `removeMatchingSelector` method
* Expose `clearCache` method
## 0.3.0
- Add UMD dist
* Add UMD dist
## 0.2.0
- Expose `getMatchingSelector` method to retrieve the instance of cached selectors
* Expose `getMatchingSelector` method to retrieve the instance of cached selectors
## 0.1.0
- Allow resolver function to return keys of type number
* Allow resolver function to return keys of type number
## 0.0.0
- Initial release
* Initial release

@@ -7,2 +7,6 @@ (function (global, factory) {

function isStringOrNumber(value) {
return typeof value === 'string' || typeof value === 'number';
}
var classCallCheck = function (instance, Constructor) {

@@ -14,5 +18,5 @@ if (!(instance instanceof Constructor)) {

var FlatCacheObject = function () {
function FlatCacheObject() {
classCallCheck(this, FlatCacheObject);
var FlatObjectCache = function () {
function FlatObjectCache() {
classCallCheck(this, FlatObjectCache);

@@ -22,34 +26,42 @@ this._cache = {};

FlatCacheObject.prototype.set = function set$$1(key, selectorFn) {
FlatObjectCache.prototype.set = function set$$1(key, selectorFn) {
this._cache[key] = selectorFn;
};
FlatCacheObject.prototype.get = function get$$1(key) {
FlatObjectCache.prototype.get = function get$$1(key) {
return this._cache[key];
};
FlatCacheObject.prototype.remove = function remove(key) {
FlatObjectCache.prototype.remove = function remove(key) {
delete this._cache[key];
};
FlatCacheObject.prototype.clear = function clear() {
FlatObjectCache.prototype.clear = function clear() {
this._cache = {};
};
return FlatCacheObject;
FlatObjectCache.prototype.isValidCacheKey = function isValidCacheKey(cacheKey) {
return isStringOrNumber(cacheKey);
};
return FlatObjectCache;
}();
var FifoCacheObject = function () {
function FifoCacheObject() {
function validateCacheSize(cacheSize) {
if (cacheSize === undefined) {
throw new Error('Missing the required property "cacheSize".');
}
if (!Number.isInteger(cacheSize) || cacheSize <= 0) {
throw new Error('The "cacheSize" property must be a positive integer value.');
}
}
var FifoObjectCache = function () {
function FifoObjectCache() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
cacheSize = _ref.cacheSize;
classCallCheck(this, FifoCacheObject);
classCallCheck(this, FifoObjectCache);
if (cacheSize === undefined) {
throw new Error('Missing the required property `cacheSize`.');
}
if (!Number.isInteger(cacheSize) || cacheSize <= 0) {
throw new Error('The `cacheSize` property must be a positive integer value.');
}
validateCacheSize(cacheSize);
this._cache = {};

@@ -60,3 +72,3 @@ this._cacheOrdering = [];

FifoCacheObject.prototype.set = function set$$1(key, selectorFn) {
FifoObjectCache.prototype.set = function set$$1(key, selectorFn) {
this._cache[key] = selectorFn;

@@ -71,7 +83,7 @@ this._cacheOrdering.push(key);

FifoCacheObject.prototype.get = function get$$1(key) {
FifoObjectCache.prototype.get = function get$$1(key) {
return this._cache[key];
};
FifoCacheObject.prototype.remove = function remove(key) {
FifoObjectCache.prototype.remove = function remove(key) {
var index = this._cacheOrdering.indexOf(key);

@@ -85,3 +97,3 @@

FifoCacheObject.prototype.clear = function clear() {
FifoObjectCache.prototype.clear = function clear() {
this._cache = {};

@@ -91,18 +103,17 @@ this._cacheOrdering = [];

return FifoCacheObject;
FifoObjectCache.prototype.isValidCacheKey = function isValidCacheKey(cacheKey) {
return isStringOrNumber(cacheKey);
};
return FifoObjectCache;
}();
var LruCacheObject = function () {
function LruCacheObject() {
var LruObjectCache = function () {
function LruObjectCache() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
cacheSize = _ref.cacheSize;
classCallCheck(this, LruCacheObject);
classCallCheck(this, LruObjectCache);
if (cacheSize === undefined) {
throw new Error('Missing the required property `cacheSize`.');
}
if (!Number.isInteger(cacheSize) || cacheSize <= 0) {
throw new Error('The `cacheSize` property must be a positive integer value.');
}
validateCacheSize(cacheSize);
this._cache = {};

@@ -113,3 +124,3 @@ this._cacheOrdering = [];

LruCacheObject.prototype.set = function set$$1(key, selectorFn) {
LruObjectCache.prototype.set = function set$$1(key, selectorFn) {
this._cache[key] = selectorFn;

@@ -124,3 +135,3 @@ this._registerCacheHit(key);

LruCacheObject.prototype.get = function get$$1(key) {
LruObjectCache.prototype.get = function get$$1(key) {
this._registerCacheHit(key);

@@ -130,3 +141,3 @@ return this._cache[key];

LruCacheObject.prototype.remove = function remove(key) {
LruObjectCache.prototype.remove = function remove(key) {
this._deleteCacheHit(key);

@@ -136,3 +147,3 @@ delete this._cache[key];

LruCacheObject.prototype.clear = function clear() {
LruObjectCache.prototype.clear = function clear() {
this._cache = {};

@@ -142,3 +153,3 @@ this._cacheOrdering = [];

LruCacheObject.prototype._registerCacheHit = function _registerCacheHit(key) {
LruObjectCache.prototype._registerCacheHit = function _registerCacheHit(key) {
this._deleteCacheHit(key);

@@ -148,3 +159,3 @@ this._cacheOrdering.push(key);

LruCacheObject.prototype._deleteCacheHit = function _deleteCacheHit(key) {
LruObjectCache.prototype._deleteCacheHit = function _deleteCacheHit(key) {
var index = this._cacheOrdering.indexOf(key);

@@ -156,5 +167,119 @@ if (index > -1) {

return LruCacheObject;
LruObjectCache.prototype.isValidCacheKey = function isValidCacheKey(cacheKey) {
return isStringOrNumber(cacheKey);
};
return LruObjectCache;
}();
var FlatMapCache = function () {
function FlatMapCache() {
classCallCheck(this, FlatMapCache);
this._cache = new Map();
}
FlatMapCache.prototype.set = function set$$1(key, selectorFn) {
this._cache.set(key, selectorFn);
};
FlatMapCache.prototype.get = function get$$1(key) {
return this._cache.get(key);
};
FlatMapCache.prototype.remove = function remove(key) {
this._cache.delete(key);
};
FlatMapCache.prototype.clear = function clear() {
this._cache.clear();
};
return FlatMapCache;
}();
var FifoMapCache = function () {
function FifoMapCache() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
cacheSize = _ref.cacheSize;
classCallCheck(this, FifoMapCache);
validateCacheSize(cacheSize);
this._cache = new Map();
this._cacheSize = cacheSize;
}
FifoMapCache.prototype.set = function set$$1(key, selectorFn) {
this._cache.set(key, selectorFn);
if (this._cache.size > this._cacheSize) {
var earliest = this._cache.keys().next().value;
this.remove(earliest);
}
};
FifoMapCache.prototype.get = function get$$1(key) {
return this._cache.get(key);
};
FifoMapCache.prototype.remove = function remove(key) {
this._cache.delete(key);
};
FifoMapCache.prototype.clear = function clear() {
this._cache.clear();
};
return FifoMapCache;
}();
var LruMapCache = function () {
function LruMapCache() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
cacheSize = _ref.cacheSize;
classCallCheck(this, LruMapCache);
validateCacheSize(cacheSize);
this._cache = new Map();
this._cacheSize = cacheSize;
}
LruMapCache.prototype.set = function set$$1(key, selectorFn) {
this._cache.set(key, selectorFn);
if (this._cache.size > this._cacheSize) {
var earliest = this._cache.keys().next().value;
this.remove(earliest);
}
};
LruMapCache.prototype.get = function get$$1(key) {
var value = this._cache.get(key);
// Register cache hit
if (this._cache.has(key)) {
this.remove(key);
this._cache.set(key, value);
}
return value;
};
LruMapCache.prototype.remove = function remove(key) {
this._cache.delete(key);
};
LruMapCache.prototype.clear = function clear() {
this._cache.clear();
};
return LruMapCache;
}();
var defaultCacheCreator = FlatObjectCache;
var defaultCacheKeyValidator = function defaultCacheKeyValidator() {
return true;
};
function createCachedSelector() {

@@ -165,26 +290,19 @@ for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) {

var defaultCacheCreator = FlatCacheObject;
return function (resolver) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var cache = void 0;
var selectorCreator = void 0;
// Allow "options" to be provided as a "selectorCreator" for backward compatibility
// @TODO Remove "options" as a function in next breaking release
// @NOTE Versions 0.x/1.x accepted "options" as a function
if (typeof options === 'function') {
console.warn('[re-reselect] Deprecation warning: "selectorCreator" argument is discouraged and will be removed in the upcoming major release. Please use "options.selectorCreator" instead.');
cache = new defaultCacheCreator();
selectorCreator = options;
} else {
cache = options.cacheObject || new defaultCacheCreator();
selectorCreator = options.selectorCreator || reselect.createSelector;
throw new Error('[re-reselect] Second argument "options" must be an object. Please use "options.selectorCreator" to provide a custom selectorCreator.');
}
var cache = options.cacheObject || new defaultCacheCreator();
var selectorCreator = options.selectorCreator || reselect.createSelector;
var isValidCacheKey = cache.isValidCacheKey || defaultCacheKeyValidator;
// Application receives this function
var selector = function selector() {
// Application receives this function
var cacheKey = resolver.apply(undefined, arguments);
if (typeof cacheKey === 'string' || typeof cacheKey === 'number') {
if (isValidCacheKey(cacheKey)) {
var cacheResponse = cache.get(cacheKey);

@@ -199,2 +317,3 @@

}
console.warn('[re-reselect] Invalid cache key "' + cacheKey + '" has been returned by resolver function.');
return undefined;

@@ -225,6 +344,12 @@ };

exports['default'] = createCachedSelector;
exports.FlatCacheObject = FlatCacheObject;
exports.FifoCacheObject = FifoCacheObject;
exports.LruCacheObject = LruCacheObject;
exports.default = createCachedSelector;
exports.FlatObjectCache = FlatObjectCache;
exports.FlatCacheObject = FlatObjectCache;
exports.FifoObjectCache = FifoObjectCache;
exports.LruObjectCache = LruObjectCache;
exports.FlatMapCache = FlatMapCache;
exports.FifoMapCache = FifoMapCache;
exports.LruMapCache = LruMapCache;
exports.FifoCacheObject = FifoObjectCache;
exports.LruCacheObject = LruMapCache;

@@ -231,0 +356,0 @@ Object.defineProperty(exports, '__esModule', { value: true });

import { createSelector } from 'reselect';
function isStringOrNumber(value) {
return typeof value === 'string' || typeof value === 'number';
}
var classCallCheck = function (instance, Constructor) {

@@ -9,5 +13,5 @@ if (!(instance instanceof Constructor)) {

var FlatCacheObject = function () {
function FlatCacheObject() {
classCallCheck(this, FlatCacheObject);
var FlatObjectCache = function () {
function FlatObjectCache() {
classCallCheck(this, FlatObjectCache);

@@ -17,34 +21,42 @@ this._cache = {};

FlatCacheObject.prototype.set = function set$$1(key, selectorFn) {
FlatObjectCache.prototype.set = function set$$1(key, selectorFn) {
this._cache[key] = selectorFn;
};
FlatCacheObject.prototype.get = function get$$1(key) {
FlatObjectCache.prototype.get = function get$$1(key) {
return this._cache[key];
};
FlatCacheObject.prototype.remove = function remove(key) {
FlatObjectCache.prototype.remove = function remove(key) {
delete this._cache[key];
};
FlatCacheObject.prototype.clear = function clear() {
FlatObjectCache.prototype.clear = function clear() {
this._cache = {};
};
return FlatCacheObject;
FlatObjectCache.prototype.isValidCacheKey = function isValidCacheKey(cacheKey) {
return isStringOrNumber(cacheKey);
};
return FlatObjectCache;
}();
var FifoCacheObject = function () {
function FifoCacheObject() {
function validateCacheSize(cacheSize) {
if (cacheSize === undefined) {
throw new Error('Missing the required property "cacheSize".');
}
if (!Number.isInteger(cacheSize) || cacheSize <= 0) {
throw new Error('The "cacheSize" property must be a positive integer value.');
}
}
var FifoObjectCache = function () {
function FifoObjectCache() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
cacheSize = _ref.cacheSize;
classCallCheck(this, FifoCacheObject);
classCallCheck(this, FifoObjectCache);
if (cacheSize === undefined) {
throw new Error('Missing the required property `cacheSize`.');
}
if (!Number.isInteger(cacheSize) || cacheSize <= 0) {
throw new Error('The `cacheSize` property must be a positive integer value.');
}
validateCacheSize(cacheSize);
this._cache = {};

@@ -55,3 +67,3 @@ this._cacheOrdering = [];

FifoCacheObject.prototype.set = function set$$1(key, selectorFn) {
FifoObjectCache.prototype.set = function set$$1(key, selectorFn) {
this._cache[key] = selectorFn;

@@ -66,7 +78,7 @@ this._cacheOrdering.push(key);

FifoCacheObject.prototype.get = function get$$1(key) {
FifoObjectCache.prototype.get = function get$$1(key) {
return this._cache[key];
};
FifoCacheObject.prototype.remove = function remove(key) {
FifoObjectCache.prototype.remove = function remove(key) {
var index = this._cacheOrdering.indexOf(key);

@@ -80,3 +92,3 @@

FifoCacheObject.prototype.clear = function clear() {
FifoObjectCache.prototype.clear = function clear() {
this._cache = {};

@@ -86,18 +98,17 @@ this._cacheOrdering = [];

return FifoCacheObject;
FifoObjectCache.prototype.isValidCacheKey = function isValidCacheKey(cacheKey) {
return isStringOrNumber(cacheKey);
};
return FifoObjectCache;
}();
var LruCacheObject = function () {
function LruCacheObject() {
var LruObjectCache = function () {
function LruObjectCache() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
cacheSize = _ref.cacheSize;
classCallCheck(this, LruCacheObject);
classCallCheck(this, LruObjectCache);
if (cacheSize === undefined) {
throw new Error('Missing the required property `cacheSize`.');
}
if (!Number.isInteger(cacheSize) || cacheSize <= 0) {
throw new Error('The `cacheSize` property must be a positive integer value.');
}
validateCacheSize(cacheSize);
this._cache = {};

@@ -108,3 +119,3 @@ this._cacheOrdering = [];

LruCacheObject.prototype.set = function set$$1(key, selectorFn) {
LruObjectCache.prototype.set = function set$$1(key, selectorFn) {
this._cache[key] = selectorFn;

@@ -119,3 +130,3 @@ this._registerCacheHit(key);

LruCacheObject.prototype.get = function get$$1(key) {
LruObjectCache.prototype.get = function get$$1(key) {
this._registerCacheHit(key);

@@ -125,3 +136,3 @@ return this._cache[key];

LruCacheObject.prototype.remove = function remove(key) {
LruObjectCache.prototype.remove = function remove(key) {
this._deleteCacheHit(key);

@@ -131,3 +142,3 @@ delete this._cache[key];

LruCacheObject.prototype.clear = function clear() {
LruObjectCache.prototype.clear = function clear() {
this._cache = {};

@@ -137,3 +148,3 @@ this._cacheOrdering = [];

LruCacheObject.prototype._registerCacheHit = function _registerCacheHit(key) {
LruObjectCache.prototype._registerCacheHit = function _registerCacheHit(key) {
this._deleteCacheHit(key);

@@ -143,3 +154,3 @@ this._cacheOrdering.push(key);

LruCacheObject.prototype._deleteCacheHit = function _deleteCacheHit(key) {
LruObjectCache.prototype._deleteCacheHit = function _deleteCacheHit(key) {
var index = this._cacheOrdering.indexOf(key);

@@ -151,5 +162,119 @@ if (index > -1) {

return LruCacheObject;
LruObjectCache.prototype.isValidCacheKey = function isValidCacheKey(cacheKey) {
return isStringOrNumber(cacheKey);
};
return LruObjectCache;
}();
var FlatMapCache = function () {
function FlatMapCache() {
classCallCheck(this, FlatMapCache);
this._cache = new Map();
}
FlatMapCache.prototype.set = function set$$1(key, selectorFn) {
this._cache.set(key, selectorFn);
};
FlatMapCache.prototype.get = function get$$1(key) {
return this._cache.get(key);
};
FlatMapCache.prototype.remove = function remove(key) {
this._cache.delete(key);
};
FlatMapCache.prototype.clear = function clear() {
this._cache.clear();
};
return FlatMapCache;
}();
var FifoMapCache = function () {
function FifoMapCache() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
cacheSize = _ref.cacheSize;
classCallCheck(this, FifoMapCache);
validateCacheSize(cacheSize);
this._cache = new Map();
this._cacheSize = cacheSize;
}
FifoMapCache.prototype.set = function set$$1(key, selectorFn) {
this._cache.set(key, selectorFn);
if (this._cache.size > this._cacheSize) {
var earliest = this._cache.keys().next().value;
this.remove(earliest);
}
};
FifoMapCache.prototype.get = function get$$1(key) {
return this._cache.get(key);
};
FifoMapCache.prototype.remove = function remove(key) {
this._cache.delete(key);
};
FifoMapCache.prototype.clear = function clear() {
this._cache.clear();
};
return FifoMapCache;
}();
var LruMapCache = function () {
function LruMapCache() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
cacheSize = _ref.cacheSize;
classCallCheck(this, LruMapCache);
validateCacheSize(cacheSize);
this._cache = new Map();
this._cacheSize = cacheSize;
}
LruMapCache.prototype.set = function set$$1(key, selectorFn) {
this._cache.set(key, selectorFn);
if (this._cache.size > this._cacheSize) {
var earliest = this._cache.keys().next().value;
this.remove(earliest);
}
};
LruMapCache.prototype.get = function get$$1(key) {
var value = this._cache.get(key);
// Register cache hit
if (this._cache.has(key)) {
this.remove(key);
this._cache.set(key, value);
}
return value;
};
LruMapCache.prototype.remove = function remove(key) {
this._cache.delete(key);
};
LruMapCache.prototype.clear = function clear() {
this._cache.clear();
};
return LruMapCache;
}();
var defaultCacheCreator = FlatObjectCache;
var defaultCacheKeyValidator = function defaultCacheKeyValidator() {
return true;
};
function createCachedSelector() {

@@ -160,26 +285,19 @@ for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) {

var defaultCacheCreator = FlatCacheObject;
return function (resolver) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var cache = void 0;
var selectorCreator = void 0;
// Allow "options" to be provided as a "selectorCreator" for backward compatibility
// @TODO Remove "options" as a function in next breaking release
// @NOTE Versions 0.x/1.x accepted "options" as a function
if (typeof options === 'function') {
console.warn('[re-reselect] Deprecation warning: "selectorCreator" argument is discouraged and will be removed in the upcoming major release. Please use "options.selectorCreator" instead.');
cache = new defaultCacheCreator();
selectorCreator = options;
} else {
cache = options.cacheObject || new defaultCacheCreator();
selectorCreator = options.selectorCreator || createSelector;
throw new Error('[re-reselect] Second argument "options" must be an object. Please use "options.selectorCreator" to provide a custom selectorCreator.');
}
var cache = options.cacheObject || new defaultCacheCreator();
var selectorCreator = options.selectorCreator || createSelector;
var isValidCacheKey = cache.isValidCacheKey || defaultCacheKeyValidator;
// Application receives this function
var selector = function selector() {
// Application receives this function
var cacheKey = resolver.apply(undefined, arguments);
if (typeof cacheKey === 'string' || typeof cacheKey === 'number') {
if (isValidCacheKey(cacheKey)) {
var cacheResponse = cache.get(cacheKey);

@@ -194,2 +312,3 @@

}
console.warn('[re-reselect] Invalid cache key "' + cacheKey + '" has been returned by resolver function.');
return undefined;

@@ -220,4 +339,4 @@ };

export { FlatCacheObject, FifoCacheObject, LruCacheObject };
export default createCachedSelector;
export { FlatObjectCache, FlatObjectCache as FlatCacheObject, FifoObjectCache, LruObjectCache, FlatMapCache, FifoMapCache, LruMapCache, FifoObjectCache as FifoCacheObject, LruMapCache as LruCacheObject };
//# sourceMappingURL=index.js.map

@@ -7,2 +7,6 @@ 'use strict';

function isStringOrNumber(value) {
return typeof value === 'string' || typeof value === 'number';
}
var classCallCheck = function (instance, Constructor) {

@@ -14,5 +18,5 @@ if (!(instance instanceof Constructor)) {

var FlatCacheObject = function () {
function FlatCacheObject() {
classCallCheck(this, FlatCacheObject);
var FlatObjectCache = function () {
function FlatObjectCache() {
classCallCheck(this, FlatObjectCache);

@@ -22,34 +26,42 @@ this._cache = {};

FlatCacheObject.prototype.set = function set$$1(key, selectorFn) {
FlatObjectCache.prototype.set = function set$$1(key, selectorFn) {
this._cache[key] = selectorFn;
};
FlatCacheObject.prototype.get = function get$$1(key) {
FlatObjectCache.prototype.get = function get$$1(key) {
return this._cache[key];
};
FlatCacheObject.prototype.remove = function remove(key) {
FlatObjectCache.prototype.remove = function remove(key) {
delete this._cache[key];
};
FlatCacheObject.prototype.clear = function clear() {
FlatObjectCache.prototype.clear = function clear() {
this._cache = {};
};
return FlatCacheObject;
FlatObjectCache.prototype.isValidCacheKey = function isValidCacheKey(cacheKey) {
return isStringOrNumber(cacheKey);
};
return FlatObjectCache;
}();
var FifoCacheObject = function () {
function FifoCacheObject() {
function validateCacheSize(cacheSize) {
if (cacheSize === undefined) {
throw new Error('Missing the required property "cacheSize".');
}
if (!Number.isInteger(cacheSize) || cacheSize <= 0) {
throw new Error('The "cacheSize" property must be a positive integer value.');
}
}
var FifoObjectCache = function () {
function FifoObjectCache() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
cacheSize = _ref.cacheSize;
classCallCheck(this, FifoCacheObject);
classCallCheck(this, FifoObjectCache);
if (cacheSize === undefined) {
throw new Error('Missing the required property `cacheSize`.');
}
if (!Number.isInteger(cacheSize) || cacheSize <= 0) {
throw new Error('The `cacheSize` property must be a positive integer value.');
}
validateCacheSize(cacheSize);
this._cache = {};

@@ -60,3 +72,3 @@ this._cacheOrdering = [];

FifoCacheObject.prototype.set = function set$$1(key, selectorFn) {
FifoObjectCache.prototype.set = function set$$1(key, selectorFn) {
this._cache[key] = selectorFn;

@@ -71,7 +83,7 @@ this._cacheOrdering.push(key);

FifoCacheObject.prototype.get = function get$$1(key) {
FifoObjectCache.prototype.get = function get$$1(key) {
return this._cache[key];
};
FifoCacheObject.prototype.remove = function remove(key) {
FifoObjectCache.prototype.remove = function remove(key) {
var index = this._cacheOrdering.indexOf(key);

@@ -85,3 +97,3 @@

FifoCacheObject.prototype.clear = function clear() {
FifoObjectCache.prototype.clear = function clear() {
this._cache = {};

@@ -91,18 +103,17 @@ this._cacheOrdering = [];

return FifoCacheObject;
FifoObjectCache.prototype.isValidCacheKey = function isValidCacheKey(cacheKey) {
return isStringOrNumber(cacheKey);
};
return FifoObjectCache;
}();
var LruCacheObject = function () {
function LruCacheObject() {
var LruObjectCache = function () {
function LruObjectCache() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
cacheSize = _ref.cacheSize;
classCallCheck(this, LruCacheObject);
classCallCheck(this, LruObjectCache);
if (cacheSize === undefined) {
throw new Error('Missing the required property `cacheSize`.');
}
if (!Number.isInteger(cacheSize) || cacheSize <= 0) {
throw new Error('The `cacheSize` property must be a positive integer value.');
}
validateCacheSize(cacheSize);
this._cache = {};

@@ -113,3 +124,3 @@ this._cacheOrdering = [];

LruCacheObject.prototype.set = function set$$1(key, selectorFn) {
LruObjectCache.prototype.set = function set$$1(key, selectorFn) {
this._cache[key] = selectorFn;

@@ -124,3 +135,3 @@ this._registerCacheHit(key);

LruCacheObject.prototype.get = function get$$1(key) {
LruObjectCache.prototype.get = function get$$1(key) {
this._registerCacheHit(key);

@@ -130,3 +141,3 @@ return this._cache[key];

LruCacheObject.prototype.remove = function remove(key) {
LruObjectCache.prototype.remove = function remove(key) {
this._deleteCacheHit(key);

@@ -136,3 +147,3 @@ delete this._cache[key];

LruCacheObject.prototype.clear = function clear() {
LruObjectCache.prototype.clear = function clear() {
this._cache = {};

@@ -142,3 +153,3 @@ this._cacheOrdering = [];

LruCacheObject.prototype._registerCacheHit = function _registerCacheHit(key) {
LruObjectCache.prototype._registerCacheHit = function _registerCacheHit(key) {
this._deleteCacheHit(key);

@@ -148,3 +159,3 @@ this._cacheOrdering.push(key);

LruCacheObject.prototype._deleteCacheHit = function _deleteCacheHit(key) {
LruObjectCache.prototype._deleteCacheHit = function _deleteCacheHit(key) {
var index = this._cacheOrdering.indexOf(key);

@@ -156,5 +167,119 @@ if (index > -1) {

return LruCacheObject;
LruObjectCache.prototype.isValidCacheKey = function isValidCacheKey(cacheKey) {
return isStringOrNumber(cacheKey);
};
return LruObjectCache;
}();
var FlatMapCache = function () {
function FlatMapCache() {
classCallCheck(this, FlatMapCache);
this._cache = new Map();
}
FlatMapCache.prototype.set = function set$$1(key, selectorFn) {
this._cache.set(key, selectorFn);
};
FlatMapCache.prototype.get = function get$$1(key) {
return this._cache.get(key);
};
FlatMapCache.prototype.remove = function remove(key) {
this._cache.delete(key);
};
FlatMapCache.prototype.clear = function clear() {
this._cache.clear();
};
return FlatMapCache;
}();
var FifoMapCache = function () {
function FifoMapCache() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
cacheSize = _ref.cacheSize;
classCallCheck(this, FifoMapCache);
validateCacheSize(cacheSize);
this._cache = new Map();
this._cacheSize = cacheSize;
}
FifoMapCache.prototype.set = function set$$1(key, selectorFn) {
this._cache.set(key, selectorFn);
if (this._cache.size > this._cacheSize) {
var earliest = this._cache.keys().next().value;
this.remove(earliest);
}
};
FifoMapCache.prototype.get = function get$$1(key) {
return this._cache.get(key);
};
FifoMapCache.prototype.remove = function remove(key) {
this._cache.delete(key);
};
FifoMapCache.prototype.clear = function clear() {
this._cache.clear();
};
return FifoMapCache;
}();
var LruMapCache = function () {
function LruMapCache() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
cacheSize = _ref.cacheSize;
classCallCheck(this, LruMapCache);
validateCacheSize(cacheSize);
this._cache = new Map();
this._cacheSize = cacheSize;
}
LruMapCache.prototype.set = function set$$1(key, selectorFn) {
this._cache.set(key, selectorFn);
if (this._cache.size > this._cacheSize) {
var earliest = this._cache.keys().next().value;
this.remove(earliest);
}
};
LruMapCache.prototype.get = function get$$1(key) {
var value = this._cache.get(key);
// Register cache hit
if (this._cache.has(key)) {
this.remove(key);
this._cache.set(key, value);
}
return value;
};
LruMapCache.prototype.remove = function remove(key) {
this._cache.delete(key);
};
LruMapCache.prototype.clear = function clear() {
this._cache.clear();
};
return LruMapCache;
}();
var defaultCacheCreator = FlatObjectCache;
var defaultCacheKeyValidator = function defaultCacheKeyValidator() {
return true;
};
function createCachedSelector() {

@@ -165,26 +290,19 @@ for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) {

var defaultCacheCreator = FlatCacheObject;
return function (resolver) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var cache = void 0;
var selectorCreator = void 0;
// Allow "options" to be provided as a "selectorCreator" for backward compatibility
// @TODO Remove "options" as a function in next breaking release
// @NOTE Versions 0.x/1.x accepted "options" as a function
if (typeof options === 'function') {
console.warn('[re-reselect] Deprecation warning: "selectorCreator" argument is discouraged and will be removed in the upcoming major release. Please use "options.selectorCreator" instead.');
cache = new defaultCacheCreator();
selectorCreator = options;
} else {
cache = options.cacheObject || new defaultCacheCreator();
selectorCreator = options.selectorCreator || reselect.createSelector;
throw new Error('[re-reselect] Second argument "options" must be an object. Please use "options.selectorCreator" to provide a custom selectorCreator.');
}
var cache = options.cacheObject || new defaultCacheCreator();
var selectorCreator = options.selectorCreator || reselect.createSelector;
var isValidCacheKey = cache.isValidCacheKey || defaultCacheKeyValidator;
// Application receives this function
var selector = function selector() {
// Application receives this function
var cacheKey = resolver.apply(undefined, arguments);
if (typeof cacheKey === 'string' || typeof cacheKey === 'number') {
if (isValidCacheKey(cacheKey)) {
var cacheResponse = cache.get(cacheKey);

@@ -199,2 +317,3 @@

}
console.warn('[re-reselect] Invalid cache key "' + cacheKey + '" has been returned by resolver function.');
return undefined;

@@ -225,6 +344,12 @@ };

exports['default'] = createCachedSelector;
exports.FlatCacheObject = FlatCacheObject;
exports.FifoCacheObject = FifoCacheObject;
exports.LruCacheObject = LruCacheObject;
exports.default = createCachedSelector;
exports.FlatObjectCache = FlatObjectCache;
exports.FlatCacheObject = FlatObjectCache;
exports.FifoObjectCache = FifoObjectCache;
exports.LruObjectCache = LruObjectCache;
exports.FlatMapCache = FlatMapCache;
exports.FifoMapCache = FifoMapCache;
exports.LruMapCache = LruMapCache;
exports.FifoCacheObject = FifoObjectCache;
exports.LruCacheObject = LruMapCache;
//# sourceMappingURL=index.js.map
{
"name": "re-reselect",
"version": "1.0.1",
"description": "Memoize selectors and avoid recalculation between calls with different inputs",
"version": "2.0.0",
"description": "Enhance Reselect selectors with deeper memoization and cache management",
"main": "lib/index.js",
"module": "es/index.js",
"jsnext:main": "es/index.js",
"browser": "dist/index.js",
"typings": "src/index.d.ts",

@@ -16,3 +17,3 @@ "files": [

"scripts": {
"test": "npm run test:js && npm run test:typescript",
"test": "npm run test:typescript && npm run test:js -- --coverage",
"test:js": "jest",

@@ -29,4 +30,4 @@ "test:typescript": "typings-tester --dir typescript_test",

"precommit": "lint-staged",
"prettier": "prettier --single-quote --trailing-comma es5 --no-bracket-spacing --write",
"prettier:src": "npm run prettier \"src/**/*.js\""
"prettier": "prettier --write",
"format": "npm run prettier \"{,{examples,src,typescript_test}/**/}*.{js,ts,md}\""
},

@@ -55,2 +56,3 @@ "keywords": [

"babel-register": "^6.23.0",
"coveralls": "^3.0.0",
"cross-env": "^5.0.5",

@@ -60,10 +62,20 @@ "husky": "^0.14.3",

"lint-staged": "^4.0.3",
"prettier": "^1.5.3",
"prettier": "^1.11.1",
"reselect": ">1.0.0",
"rimraf": "^2.6.1",
"rollup": "^0.47.4",
"rollup-plugin-babel": "^3.0.1",
"typescript": "^2.4.1",
"rollup": "^0.56.5",
"rollup-plugin-babel": "^3.0.3",
"typescript": "^2.7.2",
"typings-tester": "^0.2.2"
}
},
"jest": {
"coverageReporters": [
"text",
"lcov"
],
"coveragePathIgnorePatterns": [
"__util__"
]
},
"sideEffects": false
}

@@ -1,93 +0,81 @@

# Re-reselect [![Build Status][ci-img]][ci]
# Re-reselect
Improve **[Reselect][reselect] selectors performance/usage** on a few edge cases, by initializing selectors on runtime, using a **memoized factory**.
[![Build status][ci-badge]][ci]
[![Coveralls][coveralls-badge]][coveralls]
[![Npm][npm-badge]][npm]
**Re-reselect returns a reselect-like selector**, which is able to determine internally when **querying a new selector instance or a cached one** on the fly, depending on the supplied arguments.
`re-reselect` is a lightweight wrapper around **[Reselect][reselect]** meant to enhance selectors with **deeper memoization** and **cache management**.
Useful to **reduce selectors recalculation** when:
- a selector is sequentially **called with one/few different arguments**
- a selector is **imported by different modules** at the same time
**Switching between different arguments** using standard `reselect` selectors causes **cache invalidation** since default `reselect` cache has a **limit of one**.
...or to:
- **join similar selectors** into one
- **share selectors** with props across multiple components (see [reselect example](https://github.com/reactjs/reselect#sharing-selectors-with-props-across-multiple-components) and [re-reselect solution](https://github.com/toomuchdesign/re-reselect#how-to-share-a-selector-across-multiple-components-while-passing-in-props-and-retaining-memoization))
- **instantiate** selectors **on runtime**
`re-reselect` **forwards different calls to different** `reselect` **selectors** stored in cache, so that computed/memoized values are retained.
[reselect]: https://github.com/reactjs/reselect
[ci-img]: https://travis-ci.org/toomuchdesign/re-reselect.svg
[ci]: https://travis-ci.org/toomuchdesign/re-reselect
`re-reselect` **selectors work as normal** `reselect` **selectors** but they are able to determine when **creating a new selector or querying a cached one** on the fly, depending on the supplied arguments.
![Reselect and re-reselect][reselect-and-re-reselect-sketch]
Useful to:
* **retain selector's cache** when sequentially **called with one/few different arguments** ([example][example-1])
* **join similar selectors** into one
* **share selectors** with props across multiple components (see [reselect example][reselect-sharing-selectors] and [re-reselect solution][example-2])
* **instantiate** selectors **on runtime**
<!-- prettier-ignore -->
```js
import createCachedSelector from 're-reselect';
// Normal reselect routine: declare "inputSelectors" and "resultFunc"
const selectorA = state => state.a;
const selectorB = state => state.b;
const selectorB = (state, itemName) => state.items[itemName];
const cachedSelector = createCachedSelector(
// Set up your Reselect selector as normal:
// inputSelectors
selectorA,
selectorB,
// reselect inputSelectors:
selectorA,
selectorB,
(state, someArg) => someArg,
// reselect resultFunc:
(A, B, someArg) => expensiveComputation(A, B, someArg),
// resultFunc
(A, B) => expensiveComputation(A, B)
)(
/*
* Now it comes the re-reselect caching part:
* declare a resolver function, used as mapping cache key.
* It takes the same arguments as the generated selector
* and must return a string or number (the cache key).
*
* A new selector will be cached for each different returned key
*
* In this example the second argument of the selector is used as cache key
*/
(state, someArg) => someArg,
// resolverFunction
// Instruct re-reselect to use "itemName" as cacheKey
(state, itemName) => itemName
);
// Now you are ready to call/expose the cached selector like a normal selector:
/*
* Call selector with "foo" and with "bar":
* 2 different selectors are created, called and cached behind the scenes.
* The selectors return their computed result.
*/
// Use the cached selector like a normal selector:
const fooResult = cachedSelector(state, 'foo');
const barResult = cachedSelector(state, 'bar');
/*
* Call selector with "foo" again:
* "foo" hits the cache, now: the selector cached under "foo" key
* is retrieved, called again and the result is returned.
*/
// 2 reselect selectors were created, called and cached behind the scenes
const fooResultAgain = cachedSelector(state, 'foo');
/*
* Note that fooResult === fooResultAgain.
* The cache was not invalidated by "cachedSelector(state, 'bar')" call
*/
// fooResult === fooResultAgain
// Cache was not invalidated by calling "cachedSelector(state, 'bar')"
// "expensiveComputation" totally called twice
```
## Table of contents
- [Installation](#installation)
- [Why? + example](#why--example)
- [Re-reselect solution](#re-reselect-solution)
- [Other viable solutions](#other-viable-solutions)
- [FAQ](#faq)
- [How do I wrap my existing selector with re-reselect?](#how-do-i-wrap-my-existing-selector-with-re-reselect)
- [How do I use multiple inputs to set the cache key?](#how-do-i-use-multiple-inputs-to-set-the-cache-key)
- [How do I limit the cache size?](#how-do-i-limit-the-cache-size)
- [How to share a selector across multiple components while passing in props and retaining memoization?](#how-to-share-a-selector-across-multiple-components-while-passing-in-props-and-retaining-memoization)
- [How do I test a re-reselect selector?](#how-do-i-test-a-re-reselect-selector)
- [API](#api)
- [`reReselect`](#rereselectreselects-createselector-argumentsresolverfunction-selectorcreator--selectorcreator)
- [reReselectInstance`()`](#rereselectinstanceselectorarguments)
- [reReselectInstance`.getMatchingSelector`](#rereselectinstancegetmatchingselectorselectorarguments)
- [reReselectInstance`.removeMatchingSelector`](#rereselectinstanceremovematchingselectorselectorarguments)
- [reReselectInstance`.clearCache`](#rereselectinstanceclearcache)
- [reReselectInstance`.resultFunc`](#rereselectinstanceresultfunc)
* [Installation](#installation)
* [Why? + example](#why--example)
* [Re-reselect solution](#re-reselect-solution)
* [Other viable solutions](#other-viable-solutions)
* [FAQ](#faq)
* [How do I wrap my existing selector with re-reselect?](#how-do-i-wrap-my-existing-selector-with-re-reselect)
* [How do I use multiple inputs to set the cacheKey?](#how-do-i-use-multiple-inputs-to-set-the-cache-key)
* [How do I limit the cache size?](#how-do-i-limit-the-cache-size)
* [How to share a selector across multiple components while passing in props and retaining memoization?](#how-to-share-a-selector-across-multiple-components-while-passing-in-props-and-retaining-memoization)
* [How do I test a re-reselect selector?](#how-do-i-test-a-re-reselect-selector)
* [Examples](#examples)
* [API](#api)
* [`reReselect`](#rereselectreselects-createselector-argumentsresolverfunction-selectorcreator--selectorcreator)
* [reReselectInstance`()`](#rereselectinstanceselectorarguments)
* [reReselectInstance`.getMatchingSelector`](#rereselectinstancegetmatchingselectorselectorarguments)
* [reReselectInstance`.removeMatchingSelector`](#rereselectinstanceremovematchingselectorselectorarguments)
* [reReselectInstance`.clearCache`](#rereselectinstanceclearcache)
* [reReselectInstance`.resultFunc`](#rereselectinstanceresultfunc)
## Installation
```console

@@ -99,44 +87,56 @@ npm install reselect

## Why? + example
I found my self wrapping a library of data elaboration (quite heavy stuff) with reselect selectors (`getPieceOfData` in the example).
I found myself wrapping a library of data elaboration (quite heavy stuff) with reselect selectors (`getPieceOfData` in the example).
On each store update, I had to repeatedly call the selector in order to retrieve all the pieces of data needed by my UI. Like this:
```js
getPieceOfData(state, itemId, 'dataA', otherArg);
getPieceOfData(state, itemId, 'dataB', otherArg);
getPieceOfData(state, itemId, 'dataC', otherArg);
getPieceOfData(state, itemId, 'dataA');
getPieceOfData(state, itemId, 'dataB');
getPieceOfData(state, itemId, 'dataC');
```
What happens, here? `getPieceOfData` **selector cache is invalidated** on each call because of the changing 3rd `dataX` argument.
What happens, here? `getPieceOfData` **selector cache is invalidated** on each call because of the different 3rd `'dataX'` argument.
### Re-reselect solution
`createCachedSelector` keeps a private collection of selectors and store them by `key`.
`key` is the output of the `resolver` function, declared at selector initialization.
`re-reselect` selectors keep a **cache of `reselect` selectors** and store/retrieve them by `cacheKey`.
`resolver` is a custom function which receives the same arguments as the final selector (in the example: `state`, `itemId`, `'dataX'`, `otherArgs`) and returns a `string` or `number`.
<!-- Please note that part of this lines are repeated in #api chapter -->
That said, I was able to configure `re-reselect` to retrieve my data by querying a set of cached selectors using the 3rd argument as cache key:
`cacheKey` is by default a `string` or `number` but can be anything depending on the chosen cache strategy (see [`cacheObject` option](#optionscacheobject)).
`cacheKey` is the output of `resolverFunction`, declared at selector initialization.
`resolverFunction` is a **custom function** which:
* takes the same arguments as the final selector (in the example: `state`, `itemId`, `'dataX'`)
* returns a `cacheKey`.
Note that the **same `reselect` selector instance** stored in cache will be used for computing data for the **same `cacheKey`** (1:1).
Back to the example, `re-reselect` retrieves data by **querying one of the cached selectors** using the 3rd argument as `cacheKey`, allowing cache invalidation only when `state` or `itemId` change (but not `dataType`):
<!-- prettier-ignore -->
```js
const getPieceOfData = createCachedSelector(
state => state,
(state, itemId) => itemId
(state, itemId, dataType) => dataType
(state, itemId, dataType, otherArg) => otherArg
(state, itemId, dataType, otherArg) => expensiveComputation(state, itemId, dataType, otherArg),
(state, itemId) => itemId,
(state, itemId, dataType) => dataType,
(state, itemId, dataType) => expensiveComputation(state, itemId, dataType)
)(
(state, itemId, dataType) => dataType, // Memoize by dataType
(state, itemId, dataType) => dataType // Use dataType as cacheKey
);
```
The final result is a normal selector taking the same arguments as before.
`createCachedSelector` returns a selector with the **same signature as a normal `reselect` selector**.
But now, **each time the selector is called**, the following happens behind the scenes:
- Run `resolver` function and get its result (the cache key)
- Look for a matching key from the cache
- Return a cached selector or create a new one if no matching key is found in cache
- Call selector with provided arguments
**Re-reselect** stays completely optional and uses **your installed reselect** library under the hoods (reselect is declared as a **peer dependency**).
1. **Evaluate the `cacheKey`** for current call by executing `resolverFunction`
2. **Retrieve** from cache the **`reselect` selector** stored under the given `cacheKey`
3. **Return found selector or create a new one** if no selector was found
4. **Call returned selector** with provided arguments
Furthermore you can use any custom selector (see [API](#api)).
**Re-reselect** stays completely optional and consumes **your installed reselect** module (`reselect` is declared as **peer dependency**).

@@ -146,30 +146,44 @@ ### Other viable solutions

#### 1- Declare a different selector for each different call
Easy but doesn't scale.
#### 2- Declare a `makeGetPieceOfData` selector factory as explained in [Reselect docs](https://github.com/reactjs/reselect/tree/v2.5.4#sharing-selectors-with-props-across-multiple-components)
Easy, but doesn't scale. See ["join similar selectors" example][example-1].
Fine, but has 2 downsides:
- Bloat your selectors module by exposing both `get` selectors and `makeGet` selector factories
- Two different selector instances given the same arguments will individually recompute and store the same result (read [this](https://github.com/reactjs/reselect/pull/213))
#### 2- Declare a `makeGetPieceOfData` selector factory as explained in [Reselect docs][reselect-sharing-selectors]
Fine, but has a few downsides:
* Bloats your code by exposing both `get` selectors and `makeGet` selector factories
* Needs to import/call selector factory instead of directly using selector
* Two different instances given the same arguments, will individually store and recompute the same result (read [this](https://github.com/reactjs/reselect/pull/213))
#### 3- Wrap your `makeGetPieceOfData` selector factory into a memoizer function and call the returning memoized selector
This is what **re-reselect** actually does. It's quite verbose (since should be repeated for each selector), that's why re-reselect is here.
This is what `re-reselect` actually does! :-) It's quite verbose (since has to be repeated for each selector), **that's why re-reselect is here**.
## Examples
* [Join similar selectors][example-1]
* [Avoid selector factories][example-2]
* [Cache API calls][example-3]
## FAQ
### How do I wrap my existing selector with re-reselect?
Given your `reselect` selectors:
<!-- prettier-ignore -->
```js
import { createSelector } from 'reselect';
import {createSelector} from 'reselect';
export const getMyData = createSelector(
selectorA, // eg: selectors receive: (state, arg1, arg2)
selectorA,
selectorB,
selectorC,
(A, B, C) => doSomethingWith(A, B, C),
(A, B, C) => doSomethingWith(A, B, C)
);
```
...it becomes:
...add `resolverFunction` in the second function call:
<!-- prettier-ignore -->
```js

@@ -179,114 +193,74 @@ import createCachedSelector from 're-reselect';

export const getMyData = createCachedSelector(
selectorA, // eg: selectors receive: (state, arg1, arg2)
selectorA,
selectorB,
selectorC,
(A, B, C) => doSomethingWith(A, B, C),
(A, B, C) => doSomethingWith(A, B, C)
)(
(state, arg1, arg2) => arg2, // Use arg2 as cache key
(state, arg1, arg2) => arg2 // Use arg2 as cacheKey
);
```
Voilà, `getMyData` is ready for use!
```js
let myData = getMyData(state, 'foo', 'bar');
const myData = getMyData(state, 'foo', 'bar');
```
### How do I use multiple inputs to set the cache key?
The **cache key** is defined by the output of the `resolverFunction`.
### How do I use multiple inputs to set the cacheKey?
`resolverFunction` is a function which receives the same arguments of your `inputSelectors` and *must return a **string** or **number***.
`cacheKey` is the return value of `resolverFunction`.
`resolverFunction` receives the same arguments of your `inputSelectors` and (by default) **must return a `string` or `number`.**
A few good examples and [a bonus](https://github.com/toomuchdesign/re-reselect/issues/3):
<!-- prettier-ignore -->
```js
// Basic usage: use a single argument as cache key
// Basic usage: use a single argument as cacheKey
createCachedSelector(
...
)((state, arg1, arg2, arg3) => arg3)
// ...
)(
(state, arg1, arg2, arg3) => arg3
)
// Use multiple arguments and chain them into a string
createCachedSelector(
...
)((state, arg1, arg2, arg3) => `${arg1}:${arg3}`)
// ...
)(
(state, arg1, arg2, arg3) => `${arg1}:${arg3}`
)
// Extract properties from an object
createCachedSelector(
...
)((state, props) => `${props.a}:${props.b}`)
// ...
)(
(state, props) => `${props.a}:${props.b}`
)
```
### How do I limit the cache size?
Use the [`cacheObject` option](#optionscacheobject).
### How to share a selector across multiple components while passing in props and retaining memoization?
This example is how `re-reselect` would solve the scenario described in [Reselect docs](https://github.com/reactjs/reselect#sharing-selectors-with-props-across-multiple-components).
Use a `cacheObject` which provides that feature by supplying a [`cacheObject` option](#optionscacheobject).
We can directly declare `getVisibleTodos` selector. Since `re-reselect` handles selectors instantiation transparently, there is no need to declare a `makeGetVisibleTodos` factory.
You can also write **your own cache strategy**!
#### `selectors/todoSelectors.js`
### How to share a selector across multiple components while passing in props and retaining memoization?
```js
import createCachedSelector from 're-reselect';
[This example][example-2] shows how `re-reselect` would solve the scenario described in [reselect docs][reselect-sharing-selectors].
const getVisibilityFilter = (state, props) =>
state.todoLists[props.listId].visibilityFilter
### How do I test a re-reselect selector?
const getTodos = (state, props) =>
state.todoLists[props.listId].todos
Just like a normal reselect selector! Read more [here][reselect-test-selectors].
const getVisibleTodos = createCachedSelector(
[ getVisibilityFilter, getTodos ],
(visibilityFilter, todos) => {
switch (visibilityFilter) {
case 'SHOW_COMPLETED':
return todos.filter(todo => todo.completed)
case 'SHOW_ACTIVE':
return todos.filter(todo => !todo.completed)
default:
return todos
}
}
)(
/*
* Re-reselect resolver function.
* Cache/call a new selector for each different "listId"
*/
(state, props) => props.listId,
);
Each **re-reselect** selector exposes a `getMatchingSelector` method which returns the **underlying matching selector** instance for the given arguments, **instead of the result**.
export default getVisibleTodos;
```
#### `containers/VisibleTodoList.js`
```js
import { connect } from 'react-redux'
import { toggleTodo } from '../actions'
import TodoList from '../components/TodoList'
import { getVisibleTodos } from '../selectors'
// No need of makeMapStateToProps function:
// use getVisibleTodos as a normal selector
const mapStateToProps = (state, props) => {
return {
todos: getVisibleTodos(state, props)
}
}
// ...
```
### How do I test a re-reselect selector?
Just like a normal reselect selector! Read more [here](https://github.com/reactjs/reselect#q-how-do-i-test-a-selector).
Each **re-reselect** cached selector exposes a `getMatchingSelector` method which returns the **underlying matching selector** instance for the given arguments, **instead of the result**.
`getMatchingSelector` expects the same arguments as a normal selector call **BUT returns the instance of the cached selector itself**.
Once you get a selector instance you can call [its public methods](https://github.com/reactjs/reselect/blob/v3.0.0/src/index.js#L81) like:
Once you get a selector instance you can call [its public methods][reselect-selectors-methods] like:
- `resultFunc`
- `recomputations`
- `resetRecomputations`
* `resultFunc`
* `recomputations`
* `resetRecomputations`
<!-- prettier-ignore -->
```js

@@ -298,13 +272,12 @@ import createCachedSelector from 're-reselect';

selectorB,
(A, B) => doSomethingWith(A, B),
(A, B) => doSomethingWith(A, B)
)(
(state, arg1) => arg1, // Use arg1 as cache key
(state, arg1) => arg1 // cacheKey
);
// ...
// Call the selector to retrieve data
// Call your selector
const myFooData = getMyData(state, 'foo');
const myBarData = getMyData(state, 'bar');
// Call getMatchingSelector to retrieve the selectors
// Call getMatchingSelector method to retrieve underlying reselect selectors
// which generated "myFooData" and "myBarData" results

@@ -320,2 +293,3 @@ const myFooDataSelector = getMyData.getMatchingSelector(state, 'foo');

## API
`Re-reselect` exposes its **cached selector creator** as **default export**.

@@ -325,2 +299,4 @@

import reReselect from 're-reselect';
// or:
import createCachedSelector from 're-reselect';
```

@@ -330,34 +306,35 @@

**Re-reselect** accepts your original [selector creator arguments](https://github.com/reactjs/reselect/tree/v2.5.4#createselectorinputselectors--inputselectors-resultfunc) and returns a new function which accepts **2 arguments**:
**Re-reselect** accepts reselect's original [`createSelector` arguments][reselect-create-selector] and returns a new function which accepts **2 arguments**:
- `resolverFunction`
- `options { cacheObject, selectorCreator }` *(optional)*
* `resolverFunction`
* `options { cacheObject, selectorCreator }` _(optional)_
#### resolverFunction
`resolverFunction` is a function which receives the same arguments of your selectors (and `inputSelectors`) and *must return a **string** or **number***. The result is used as cache key to store/retrieve selector instances.
Cache keys of type `number` are treated like strings, since they are assigned to a JS object as arguments.
`resolverFunction` is a custom function receiving the same arguments as your selectors (and `inputSelectors`) and **returning a `cacheKey`**.
The resolver idea is inspired by [Lodash's .memoize](https://lodash.com/docs/4.17.4#memoize) util.
`cacheKey` is **by default a `string` or `number`** but can be anything depending on the chosen cache strategy (see [`cacheObject` option](#optionscacheobject)).
The `resolverFunction` idea comes from [Lodash's .memoize][lodash-memoize].
#### options.cacheObject
An optional custom [strategy object](https://sourcemaking.com/design_patterns/strategy) to handle the caching behaviour. It must adhere to the following interface:
```js
interface ICacheObject {
set (key: string|number, selectorFn: Function): void;
get (key: string|number): Function;
remove (key: string|number): void;
clear (): void;
}
```
An optional custom [strategy object][docs-strategy-object] to handle the caching behaviour.
`re-reselect` provides **3 ready to use cache object creators**:
Default cache: `FlatObjectCache`.
- [`FlatCacheObject`](src/cache/FlatCacheObject.js) (default)
- [`FifoCacheObject`](src/cache/FifoCacheObject.js) ([first in first out cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#First_In_First_Out_.28FIFO.29))
- [`LruCacheObject`](src/cache/LruCacheObject.js) ([least recently used cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29))
`re-reselect` provides **6 ready to use cache object constructors**:
| name | accepted cacheKey | type | storage |
| :-----------------------------------------------: | :---------------: | :-----------------------------------: | :----------------------------: |
| [`FlatObjectCache`](src/cache/FlatObjectCache.js) | `number` `string` | flat unlimited | JS object |
| [`FifoObjectCache`](src/cache/FifoObjectCache.js) | `number` `string` | [first in first out][docs-fifo-cache] | JS object |
| [`LruObjectCache`](src/cache/LruObjectCache.js) | `number` `string` | [least recently used][docs-lru-cache] | JS object |
| [`FlatMapCache`](src/cache/FlatMapCache.js) | any | flat unlimited | [Map object][docs-mozilla-map] |
| [`FifoMapCache`](src/cache/FifoMapCache.js) | any | [first in first out][docs-fifo-cache] | [Map object][docs-mozilla-map] |
| [`LruMapCache`](src/cache/LruMapCache.js) | any | [least recently used][docs-lru-cache] | [Map object][docs-mozilla-map] |
<!-- prettier-ignore -->
```js
import createCachedSelector, { LruCacheObject, FifoCacheObject } from re-reselect;
import createCachedSelector, {LruObjectCache, LruMapCache} from 're-reselect';

@@ -369,47 +346,97 @@ createCachedSelector(

{
cacheObject: new LruCacheObject({ cacheSize: 5 });
cacheObject: new LruObjectCache({cacheSize: 5}),
// or:
// cacheObject: new FifoCacheObject({ cacheSize: 5 });
// cacheObject: new LruMapCache({cacheSize: 5}),
}
)
);
```
The default cache strategy, `FlatCache` doesn't limit cache.
**[*]ObjectCache** strategy objects treat `cacheKey` of type `number` like strings, since they are used as arguments of JS objects.
You can provide **any kind of caching strategy**. Just write your own. You can use the [existing ones](src/cache/) as starting point.
**[*]MapCache** strategy objects needs a **Map objects polyfill** in order to use them on non-supporting browsers.
##### Custom cache strategy object
You can provide **any kind of cache strategy**. Declare a JS object adhering to the following interface:
```ts
interface ICacheObject {
set(key: any, selectorFn: any): void;
get(key: any): any;
remove(key: any): void;
clear(): void;
isValidCacheKey?(key: any): boolean; // optional
}
```
#### options.selectorCreator
`selectorCreator` is an optional function describing a [custom selectors](https://github.com/reactjs/reselect/tree/v3.0.0#createselectorcreatormemoize-memoizeoptions). By default it uses Reselect's `createSelector`.
An optional function describing a [custom selectors][reselect-create-selector-creator]. By default it uses `reselect`'s `createSelector`.
#### Returns
(Function): a `reReselectInstance` selector ready to be used **like a normal reselect selector**.
### reReselectInstance(selectorArguments)
Retrieve data for given arguments.
>The followings are advanced methods and you won't need them for basic usage!
> The followings are advanced methods and you won't need them for basic usage!
### reReselectInstance`.getMatchingSelector(selectorArguments)`
Retrieve the selector responding to the given arguments.
### reReselectInstance`.removeMatchingSelector(selectorArguments)`
Remove the selector responding to the given arguments from the cache.
Remove from the cache the selector responding to the given arguments.
### reReselectInstance`.clearCache()`
Clear the whole `reReselectInstance` cache.
Clear whole `reReselectInstance` cache.
### reReselectInstance`.resultFunc`
Get `resultFunc` for easily [test composed selectors](https://github.com/reactjs/reselect#q-how-do-i-test-a-selector).
Get `resultFunc` for easily [test composed selectors][reselect-test-selectors].
## Todo's
- Flow type definitions?
- Improve TS tests readability
* Flow type definitions?
* Improve TS tests readability
* More examples
## Contributors
Thanks to you all ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):
Thanks to you all ([emoji key][docs-all-contributors]):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
| [<img src="https://avatars3.githubusercontent.com/u/4573549?v=4" width="100px;"/><br /><sub>Andrea Carraro</sub>](http://www.andreacarraro.it)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=toomuchdesign "Code") [📖](https://github.com/toomuchdesign/re-reselect/commits?author=toomuchdesign "Documentation") [🚇](#infra-toomuchdesign "Infrastructure (Hosting, Build-Tools, etc)") [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=toomuchdesign "Tests") [👀](#review-toomuchdesign "Reviewed Pull Requests") | [<img src="https://avatars2.githubusercontent.com/u/830824?v=4" width="100px;"/><br /><sub>Stepan Burguchev</sub>](https://github.com/xsburg)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=xsburg "Code") [👀](#review-xsburg "Reviewed Pull Requests") [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=xsburg "Tests") | [<img src="https://avatars3.githubusercontent.com/u/693493?v=4" width="100px;"/><br /><sub>Mitch Robb</sub>](https://olslash.github.io/)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=olslash "Code") [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=olslash "Tests") | [<img src="https://avatars3.githubusercontent.com/u/1128559?v=4" width="100px;"/><br /><sub>Stephane Rufer</sub>](https://github.com/rufman)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=rufman "Code") [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=rufman "Tests") | [<img src="https://avatars0.githubusercontent.com/u/2788860?v=4" width="100px;"/><br /><sub>Tracy Mullen</sub>](https://github.com/spiffysparrow)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=spiffysparrow "Code") [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=spiffysparrow "Tests") | [<img src="https://avatars1.githubusercontent.com/u/4211838?v=4" width="100px;"/><br /><sub>Sushain Cherivirala</sub>](https://www.skc.name)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=sushain97 "Code") | [<img src="https://avatars0.githubusercontent.com/u/6316590?v=4" width="100px;"/><br /><sub>Steve Mao</sub>](https://twitter.com/MaoStevemao)<br />[📖](https://github.com/toomuchdesign/re-reselect/commits?author=stevemao "Documentation") |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| [<img src="https://avatars2.githubusercontent.com/u/1428826?v=4" width="100px;"/><br /><sub>Gaurav Lahoti</sub>](https://github.com/Dante-101)<br />[🐛](https://github.com/toomuchdesign/re-reselect/issues?q=author%3ADante-101 "Bug reports") | [<img src="https://avatars3.githubusercontent.com/u/13602053?v=4" width="100px;"/><br /><sub>Lon</sub>](http://lon.im)<br />[🐛](https://github.com/toomuchdesign/re-reselect/issues?q=author%3Acnlon "Bug reports") | [<img src="https://avatars2.githubusercontent.com/u/5492495?v=4" width="100px;"/><br /><sub>bratushka</sub>](https://github.com/bratushka)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=bratushka "Code") |
| [<img src="https://avatars3.githubusercontent.com/u/4573549?v=4" width="100px;"/><br /><sub>Andrea Carraro</sub>](http://www.andreacarraro.it)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=toomuchdesign 'Code') [📖](https://github.com/toomuchdesign/re-reselect/commits?author=toomuchdesign 'Documentation') [🚇](#infra-toomuchdesign 'Infrastructure (Hosting, Build-Tools, etc)') [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=toomuchdesign 'Tests') [👀](#review-toomuchdesign 'Reviewed Pull Requests') | [<img src="https://avatars2.githubusercontent.com/u/830824?v=4" width="100px;"/><br /><sub>Stepan Burguchev</sub>](https://github.com/xsburg)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=xsburg 'Code') [👀](#review-xsburg 'Reviewed Pull Requests') [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=xsburg 'Tests') | [<img src="https://avatars3.githubusercontent.com/u/693493?v=4" width="100px;"/><br /><sub>Mitch Robb</sub>](https://olslash.github.io/)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=olslash 'Code') [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=olslash 'Tests') | [<img src="https://avatars3.githubusercontent.com/u/1128559?v=4" width="100px;"/><br /><sub>Stephane Rufer</sub>](https://github.com/rufman)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=rufman 'Code') [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=rufman 'Tests') | [<img src="https://avatars0.githubusercontent.com/u/2788860?v=4" width="100px;"/><br /><sub>Tracy Mullen</sub>](https://github.com/spiffysparrow)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=spiffysparrow 'Code') [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=spiffysparrow 'Tests') | [<img src="https://avatars1.githubusercontent.com/u/4211838?v=4" width="100px;"/><br /><sub>Sushain Cherivirala</sub>](https://www.skc.name)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=sushain97 'Code') | [<img src="https://avatars0.githubusercontent.com/u/6316590?v=4" width="100px;"/><br /><sub>Steve Mao</sub>](https://twitter.com/MaoStevemao)<br />[📖](https://github.com/toomuchdesign/re-reselect/commits?author=stevemao 'Documentation') |
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| [<img src="https://avatars2.githubusercontent.com/u/1428826?v=4" width="100px;"/><br /><sub>Gaurav Lahoti</sub>](https://github.com/Dante-101)<br />[🐛](https://github.com/toomuchdesign/re-reselect/issues?q=author%3ADante-101 'Bug reports') | [<img src="https://avatars3.githubusercontent.com/u/13602053?v=4" width="100px;"/><br /><sub>Lon</sub>](http://lon.im)<br />[🐛](https://github.com/toomuchdesign/re-reselect/issues?q=author%3Acnlon 'Bug reports') | [<img src="https://avatars2.githubusercontent.com/u/5492495?v=4" width="100px;"/><br /><sub>bratushka</sub>](https://github.com/bratushka)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=bratushka 'Code') | [<img src="https://avatars3.githubusercontent.com/u/615381?v=4" width="100px;"/><br /><sub>Anders D. Johnson</sub>](https://andrz.me)<br />[📖](https://github.com/toomuchdesign/re-reselect/commits?author=AndersDJohnson 'Documentation') | [<img src="https://avatars3.githubusercontent.com/u/8556724?v=4" width="100px;"/><br /><sub>Július Retzer</sub>](https://github.com/wormyy)<br />[📖](https://github.com/toomuchdesign/re-reselect/commits?author=wormyy 'Documentation') | [<img src="https://avatars3.githubusercontent.com/u/10407025?v=4" width="100px;"/><br /><sub>Maarten Schumacher</sub>](https://github.com/maartenschumacher)<br />[🤔](#ideas-maartenschumacher 'Ideas, Planning, & Feedback') | [<img src="https://avatars2.githubusercontent.com/u/664238?v=4" width="100px;"/><br /><sub>Alexander Jarvis</sub>](https://github.com/alexanderjarvis)<br />[🤔](#ideas-alexanderjarvis 'Ideas, Planning, & Feedback') |
| [<img src="https://avatars1.githubusercontent.com/u/514026?v=4" width="100px;"/><br /><sub>Gregg B</sub>](https://github.com/greggb)<br />[💡](#example-greggb 'Examples') | [<img src="https://avatars0.githubusercontent.com/u/897931?v=4" width="100px;"/><br /><sub>Ian Obermiller</sub>](http://ianobermiller.com)<br />[👀](#review-ianobermiller 'Reviewed Pull Requests') |
<!-- ALL-CONTRIBUTORS-LIST:END -->
[reselect]: https://github.com/reactjs/reselect
[reselect-sharing-selectors]: https://github.com/reactjs/reselect/tree/v3.0.1#sharing-selectors-with-props-across-multiple-components
[reselect-test-selectors]: https://github.com/reactjs/reselect/tree/v3.0.1#q-how-do-i-test-a-selector
[reselect-selectors-methods]: https://github.com/reactjs/reselect/blob/v3.0.1/src/index.js#L81
[reselect-create-selector]: https://github.com/reactjs/reselect/tree/v3.0.1#createselectorinputselectors--inputselectors-resultfunc
[reselect-create-selector-creator]: https://github.com/reactjs/reselect/tree/v3.0.1#createselectorcreatormemoize-memoizeoptions
[lodash-memoize]: https://lodash.com/docs/4.17.4#memoize
[ci-badge]: https://travis-ci.org/toomuchdesign/re-reselect.svg?branch=master
[ci]: https://travis-ci.org/toomuchdesign/re-reselect
[coveralls-badge]: https://coveralls.io/repos/github/toomuchdesign/re-reselect/badge.svg?branch=master
[coveralls]: https://coveralls.io/github/toomuchdesign/re-reselect?branch=master
[npm-badge]: https://img.shields.io/npm/dm/re-reselect.svg
[npm]: https://www.npmjs.com/package/re-reselect
[reselect-and-re-reselect-sketch]: examples/reselect-and-re-reselect.png?raw=true
[example-1]: examples/1-join-selectors.md
[example-2]: examples/2-avoid-selector-factories.md
[example-3]: examples/3-cache-api-calls.md
[docs-fifo-cache]: https://en.wikipedia.org/wiki/Cache_replacement_policies#First_In_First_Out_.28FIFO.29
[docs-lru-cache]: https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29
[docs-mozilla-map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
[docs-strategy-object]: https://sourcemaking.com/design_patterns/strategy
[docs-all-contributors]: https://github.com/kentcdodds/all-contributors#emoji-key
/* eslint comma-dangle: 0 */
import {createSelector} from 'reselect';
import createCachedSelector, {FlatCacheObject} from '../index';
import createCachedSelector, {FlatObjectCache} from '../index';
let resultFunc;
let consoleWarnSpy;
beforeAll(() => {
consoleWarnSpy = jest
.spyOn(global.console, 'warn')
.mockImplementation(() => {});
});
beforeEach(() => {
resultFunc = jest.fn();
consoleWarnSpy.mockReset();
});

@@ -18,3 +26,3 @@

describe('createCachedSelector', () => {
it('Should use the same cached selector when resolver function returns the same string', () => {
it('Should use the same cached selector when resolver function returns the same value', () => {
const cachedSelector = selectorWithMockedResultFunc();

@@ -24,6 +32,6 @@ const firstCall = cachedSelector('foo', 'bar');

expect(resultFunc.mock.calls.length).toBe(1);
expect(resultFunc).toHaveBeenCalledTimes(1);
});
it('Should create 2 different selectors when resolver function returns different strings', () => {
it('Should create 2 selectors when resolver function returns different values', () => {
const cachedSelector = selectorWithMockedResultFunc();

@@ -33,122 +41,149 @@ const firstCallResult = cachedSelector('foo', 'bar');

expect(resultFunc.mock.calls.length).toBe(2);
expect(resultFunc).toHaveBeenCalledTimes(2);
});
it('Should return "undefined" if provided resolver does not return a string', () => {
const cachedSelector = createCachedSelector(resultFunc)(
() => {} // Resolver
);
const firstCallResult = cachedSelector('foo', 'bar');
describe('cacheKey validity check', () => {
describe('cacheObject.isValidCacheKey not available', () => {
it('Should accept any value', () => {
const cacheObjectMock = {
get: jest.fn(() => () => 'foo'),
};
const values = [{}, [], null, undefined, 12, 'bar'];
expect(resultFunc.mock.calls.length).toBe(0);
expect(firstCallResult).toBe(undefined);
});
const cachedSelector = createCachedSelector(resultFunc)(
arg1 => arg1, // cacheKey
{
cacheObject: cacheObjectMock,
}
);
it('Should allow resolver function to return keys of type number', () => {
const cachedSelector = selectorWithMockedResultFunc();
const firstCall = cachedSelector('foo', 1);
const secondCallWithSameResolver = cachedSelector('foo', 1);
values.forEach((value, index) => {
cachedSelector(value);
expect(cacheObjectMock.get).toHaveBeenCalledTimes(index + 1);
expect(cacheObjectMock.get).toHaveBeenLastCalledWith(value);
});
});
});
expect(resultFunc.mock.calls.length).toBe(1);
});
describe('cacheObject.isValidCacheKey returns "true"', () => {
it('Should call cache.get method', () => {
const cacheObjectMock = new FlatObjectCache();
cacheObjectMock.isValidCacheKey = jest.fn(() => true);
cacheObjectMock.get = jest.fn();
it('Should expose underlying reselect selector for a cache key with "getMatchingSelector"', () => {
const cachedSelector = createCachedSelector(() => {})((arg1, arg2) => arg2);
const cachedSelector = createCachedSelector(resultFunc)(arg1 => arg1, {
cacheObject: cacheObjectMock,
});
// Retrieve result from re-reselect cached selector
const actualResult = cachedSelector('foo', 1);
cachedSelector('foo');
// Retrieve result directly calling underlying reselect selector
const reselectSelector = cachedSelector.getMatchingSelector('foo', 1);
const expectedResultFromSelector = reselectSelector('foo', 1);
expect(cacheObjectMock.get).toHaveBeenCalledTimes(1);
// Receive cacheKey and reselect selector as arguments
expect(cacheObjectMock.get).toHaveBeenCalledWith('foo');
});
});
expect(actualResult).toBe(expectedResultFromSelector);
});
describe('cacheObject.isValidCacheKey returns "false"', () => {
it('Should return "undefined" and call "console.warn"', () => {
const cacheObjectMock = new FlatObjectCache();
cacheObjectMock.isValidCacheKey = jest.fn(() => false);
cacheObjectMock.get = jest.fn();
it('Should return "undefined" when "getMatchingSelector" doesn\'t hit any cache entry', () => {
const cachedSelector = selectorWithMockedResultFunc();
const cachedSelector = createCachedSelector(resultFunc)(arg1 => arg1, {
cacheObject: cacheObjectMock,
});
const actual = cachedSelector.getMatchingSelector('foo', 1);
const expected = undefined;
const actual = cachedSelector('foo');
expect(actual).toEqual(expected);
expect(actual).toBe(undefined);
expect(cacheObjectMock.get).not.toHaveBeenCalled();
expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
});
});
});
it('Should reset the cache when calling "clearCache"', () => {
const cachedSelector = selectorWithMockedResultFunc();
it('Should throw an error when a function is provided as 2° argument', () => {
expect(() => {
const cachedSelector = createCachedSelector(resultFunc)(() => {},
createSelector);
}).toThrow(/Second argument "options" must be an object/);
});
cachedSelector('foo', 1); // add to cache
cachedSelector.clearCache(); // clear cache
const actual = cachedSelector.getMatchingSelector('foo', 1);
it('Should accept an options object', () => {
const cachedSelector = createCachedSelector(resultFunc)(
(arg1, arg2) => arg2,
{
cacheObject: new FlatObjectCache(),
selectorCreator: createSelector,
}
);
expect(actual).toBe(undefined);
expect(resultFunc).toHaveBeenCalledTimes(0);
cachedSelector('foo', 'bar');
cachedSelector('foo', 'bar');
expect(resultFunc).toHaveBeenCalledTimes(1);
});
it('Should set the selected key to "undefined" when calling "removeMatchingSelector"', () => {
const cachedSelector = selectorWithMockedResultFunc();
describe('getMatchingSelector()', () => {
it('Should return underlying reselect selector for a given cache key', () => {
const cachedSelector = createCachedSelector(() => {})(
(arg1, arg2) => arg2
);
cachedSelector('foo', 1); // add to cache
cachedSelector('foo', 2); // add to cache
cachedSelector.removeMatchingSelector('foo', 1); // remove key from chache
// Retrieve result from re-reselect cached selector
const actualResult = cachedSelector('foo', 1);
const firstSelectorActual = cachedSelector.getMatchingSelector('foo', 1);
const secondSelectorActual = cachedSelector.getMatchingSelector('foo', 2);
// Retrieve result directly calling underlying reselect selector
const reselectSelector = cachedSelector.getMatchingSelector('foo', 1);
const expectedResultFromSelector = reselectSelector('foo', 1);
expect(firstSelectorActual).toBe(undefined);
expect(secondSelectorActual).not.toBe(undefined);
});
expect(actualResult).toBe(expectedResultFromSelector);
});
it('resultFunc attribute should point to provided result function', () => {
const cachedSelector = createCachedSelector(() => {}, resultFunc)(
(arg1, arg2) => arg2
);
expect(cachedSelector.resultFunc).toBe(resultFunc);
it('Should return "undefined" when given cache key doesn\'t match any cache entry', () => {
const cachedSelector = selectorWithMockedResultFunc();
const actual = cachedSelector.getMatchingSelector('foo', 1);
const expected = undefined;
expect(actual).toEqual(expected);
});
});
it('Should accept a "selectorCreator" function as 2° argument', () => {
const consoleWarnSpy = jest
.spyOn(global.console, 'warn')
.mockImplementation(() => {});
const cachedSelector = createCachedSelector(resultFunc)(
(arg1, arg2) => arg2,
createSelector
);
describe('removeMatchingSelector()', () => {
it('Should set the matching cache entry to "undefined"', () => {
const cachedSelector = selectorWithMockedResultFunc();
expect(resultFunc.mock.calls.length).toBe(0);
cachedSelector('foo', 'bar');
cachedSelector('foo', 'bar');
expect(resultFunc.mock.calls.length).toBe(1);
cachedSelector('foo', 1); // add to cache
cachedSelector('foo', 2); // add to cache
cachedSelector.removeMatchingSelector('foo', 1); // remove key from chache
consoleWarnSpy.mockReset();
consoleWarnSpy.mockRestore();
const firstSelectorActual = cachedSelector.getMatchingSelector('foo', 1);
const secondSelectorActual = cachedSelector.getMatchingSelector('foo', 2);
expect(firstSelectorActual).toBe(undefined);
expect(secondSelectorActual).not.toBe(undefined);
});
});
it('Should cast a deprecation warning when "selectorCreator" is provided as 2° argument', () => {
const consoleWarnSpy = jest
.spyOn(global.console, 'warn')
.mockImplementation(() => {});
const cachedSelector = createCachedSelector(
resultFunc
)(() => {}, createSelector);
describe('clearCache()', () => {
it('Should reset cache', () => {
const cachedSelector = selectorWithMockedResultFunc();
expect(consoleWarnSpy).toHaveBeenCalled();
cachedSelector('foo', 1); // add to cache
cachedSelector.clearCache(); // clear cache
const actual = cachedSelector.getMatchingSelector('foo', 1);
consoleWarnSpy.mockReset();
consoleWarnSpy.mockRestore();
expect(actual).toBe(undefined);
});
});
it('Should accept an options object', () => {
const cachedSelector = createCachedSelector(resultFunc)(
(arg1, arg2) => arg2,
{
cacheObject: new FlatCacheObject(),
selectorCreator: createSelector,
}
);
expect(resultFunc.mock.calls.length).toBe(0);
cachedSelector('foo', 'bar');
cachedSelector('foo', 'bar');
expect(resultFunc.mock.calls.length).toBe(1);
describe('resultFunc', () => {
it('Should point to provided result function', () => {
const cachedSelector = createCachedSelector(() => {}, resultFunc)(
(arg1, arg2) => arg2
);
expect(cachedSelector.resultFunc).toBe(resultFunc);
});
});
});

@@ -1,16 +0,19 @@

import { createSelector } from 'reselect';
import {createSelector} from 'reselect';
export type Selector<S, R> = (state: S) => R;
export type Resolver<S> = (state: S, ...args: any[]) => number | string;
export type Resolver<S> = (state: S, ...args: any[]) => any;
export type CreateSelectorInstance = typeof createSelector;
type Options = {
selectorCreator?: CreateSelectorInstance;
cacheObject: ICacheObject;
}|{
selectorCreator: CreateSelectorInstance;
cacheObject?: ICacheObject;
}|CreateSelectorInstance;
type Options =
| {
selectorCreator?: CreateSelectorInstance;
cacheObject: ICacheObject;
}
| {
selectorCreator: CreateSelectorInstance;
cacheObject?: ICacheObject;
}
| CreateSelectorInstance;

@@ -23,3 +26,6 @@ export type OutputSelector<S, R, C> = Selector<S, R> & {

export type OutputCachedSelector<S, R, C> = (resolver: Resolver<S>, optionsOrSelectorCreator?: Options) => OutputSelector<S, R, C> & {
export type OutputCachedSelector<S, R, C> = (
resolver: Resolver<S>,
optionsOrSelectorCreator?: Options
) => OutputSelector<S, R, C> & {
getMatchingSelector: (state: S, ...args: any[]) => OutputSelector<S, R, C>;

@@ -31,7 +37,19 @@ removeMatchingSelector: (state: S, ...args: any[]) => void;

export type ParametricSelector<S, P, R> = (state: S, props: P, ...args: any[]) => R;
export type ParametricSelector<S, P, R> = (
state: S,
props: P,
...args: any[]
) => R;
export type ParametricResolver<S, P> = (state: S, props: P, ...args: any[]) => number | string;
export type ParametricResolver<S, P> = (
state: S,
props: P,
...args: any[]
) => any;
export type OutputParametricSelector<S, P, R, C> = ParametricSelector<S, P, R> & {
export type OutputParametricSelector<S, P, R, C> = ParametricSelector<
S,
P,
R
> & {
resultFunc: C;

@@ -42,4 +60,11 @@ recomputations: () => number;

export type OutputParametricCachedSelector<S, P, R, C> = (resolver: ParametricResolver<S, P>, optionsOrSelectorCreator?: Options) => OutputParametricSelector<S, P, R, C> & {
getMatchingSelector: (state: S, props: P, ...args: any[]) => OutputParametricSelector<S, P, R, C>;
export type OutputParametricCachedSelector<S, P, R, C> = (
resolver: ParametricResolver<S, P>,
optionsOrSelectorCreator?: Options
) => OutputParametricSelector<S, P, R, C> & {
getMatchingSelector: (
state: S,
props: P,
...args: any[]
) => OutputParametricSelector<S, P, R, C>;
removeMatchingSelector: (state: S, props: P, ...args: any[]) => void;

@@ -51,7 +76,7 @@ clearCache: () => void;

/* one selector */
export default function createCachedSelector<S, R1, T> (
export default function createCachedSelector<S, R1, T>(
selector: Selector<S, R1>,
combiner: (res: R1) => T
): OutputCachedSelector<S, T, (res: R1) => T>;
export default function createCachedSelector<S, P, R1, T> (
export default function createCachedSelector<S, P, R1, T>(
selector: ParametricSelector<S, P, R1>,

@@ -62,3 +87,3 @@ combiner: (res: R1) => T

/* two selectors */
export default function createCachedSelector<S, R1, R2, T> (
export default function createCachedSelector<S, R1, R2, T>(
selector1: Selector<S, R1>,

@@ -68,3 +93,3 @@ selector2: Selector<S, R2>,

): OutputCachedSelector<S, T, (res1: R1, res2: R2) => T>;
export default function createCachedSelector<S, P, R1, R2, T> (
export default function createCachedSelector<S, P, R1, R2, T>(
selector1: ParametricSelector<S, P, R1>,

@@ -76,3 +101,3 @@ selector2: ParametricSelector<S, P, R2>,

/* three selectors */
export default function createCachedSelector<S, R1, R2, R3, T> (
export default function createCachedSelector<S, R1, R2, R3, T>(
selector1: Selector<S, R1>,

@@ -83,3 +108,3 @@ selector2: Selector<S, R2>,

): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, T> (
export default function createCachedSelector<S, P, R1, R2, R3, T>(
selector1: ParametricSelector<S, P, R1>,

@@ -92,3 +117,3 @@ selector2: ParametricSelector<S, P, R2>,

/* four selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, T> (
export default function createCachedSelector<S, R1, R2, R3, R4, T>(
selector1: Selector<S, R1>,

@@ -100,3 +125,3 @@ selector2: Selector<S, R2>,

): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, T> (
export default function createCachedSelector<S, P, R1, R2, R3, R4, T>(
selector1: ParametricSelector<S, P, R1>,

@@ -107,6 +132,11 @@ selector2: ParametricSelector<S, P, R2>,

combiner: (res1: R1, res2: R2, res3: R3, res4: R4) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4) => T>;
): OutputParametricCachedSelector<
S,
P,
T,
(res1: R1, res2: R2, res3: R3, res4: R4) => T
>;
/* five selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, T> (
export default function createCachedSelector<S, R1, R2, R3, R4, R5, T>(
selector1: Selector<S, R1>,

@@ -118,4 +148,8 @@ selector2: Selector<S, R2>,

combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, T> (
): OutputCachedSelector<
S,
T,
(res1: R1, res2: R2, res3: R3, res4: R4, res5: R5) => T
>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, T>(
selector1: ParametricSelector<S, P, R1>,

@@ -127,6 +161,11 @@ selector2: ParametricSelector<S, P, R2>,

combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5) => T>;
): OutputParametricCachedSelector<
S,
P,
T,
(res1: R1, res2: R2, res3: R3, res4: R4, res5: R5) => T
>;
/* six selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, T> (
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, T>(
selector1: Selector<S, R1>,

@@ -139,4 +178,8 @@ selector2: Selector<S, R2>,

combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, T> (
): OutputCachedSelector<
S,
T,
(res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6) => T
>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, T>(
selector1: ParametricSelector<S, P, R1>,

@@ -149,6 +192,11 @@ selector2: ParametricSelector<S, P, R2>,

combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6) => T>;
): OutputParametricCachedSelector<
S,
P,
T,
(res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6) => T
>;
/* seven selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, T> (
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, T>(
selector1: Selector<S, R1>,

@@ -161,7 +209,28 @@ selector2: Selector<S, R2>,

selector7: Selector<S, R7>,
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, R7, T> (
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7
) => T
): OutputCachedSelector<
S,
T,
(res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6, res7: R7) => T
>;
export default function createCachedSelector<
S,
P,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
T
>(
selector1: ParametricSelector<S, P, R1>,

@@ -174,9 +243,31 @@ selector2: ParametricSelector<S, P, R2>,

selector7: ParametricSelector<S, P, R7>,
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7) => T>;
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7
) => T
): OutputParametricCachedSelector<
S,
P,
T,
(res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6, res7: R7) => T
>;
/* eight selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, R8, T> (
export default function createCachedSelector<
S,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
T
>(
selector1: Selector<S, R1>,

@@ -190,7 +281,39 @@ selector2: Selector<S, R2>,

selector8: Selector<S, R8>,
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, R7, R8, T> (
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8
) => T
): OutputCachedSelector<
S,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8
) => T
>;
export default function createCachedSelector<
S,
P,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
T
>(
selector1: ParametricSelector<S, P, R1>,

@@ -204,9 +327,42 @@ selector2: ParametricSelector<S, P, R2>,

selector8: ParametricSelector<S, P, R8>,
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8) => T>;
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8
) => T
): OutputParametricCachedSelector<
S,
P,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8
) => T
>;
/* nine selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, R8, R9, T> (
export default function createCachedSelector<
S,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
T
>(
selector1: Selector<S, R1>,

@@ -221,7 +377,42 @@ selector2: Selector<S, R2>,

selector9: Selector<S, R9>,
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, R7, R8, R9, T> (
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9
) => T
): OutputCachedSelector<
S,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9
) => T
>;
export default function createCachedSelector<
S,
P,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
T
>(
selector1: ParametricSelector<S, P, R1>,

@@ -236,9 +427,45 @@ selector2: ParametricSelector<S, P, R2>,

selector9: ParametricSelector<S, P, R9>,
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9) => T>;
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9
) => T
): OutputParametricCachedSelector<
S,
P,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9
) => T
>;
/* ten selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, T> (
export default function createCachedSelector<
S,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
T
>(
selector1: Selector<S, R1>,

@@ -254,7 +481,45 @@ selector2: Selector<S, R2>,

selector10: Selector<S, R10>,
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, T> (
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10
) => T
): OutputCachedSelector<
S,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10
) => T
>;
export default function createCachedSelector<
S,
P,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
T
>(
selector1: ParametricSelector<S, P, R1>,

@@ -270,9 +535,48 @@ selector2: ParametricSelector<S, P, R2>,

selector10: ParametricSelector<S, P, R10>,
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10) => T>;
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10
) => T
): OutputParametricCachedSelector<
S,
P,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10
) => T
>;
/* eleven selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, T> (
export default function createCachedSelector<
S,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
T
>(
selector1: Selector<S, R1>,

@@ -289,7 +593,48 @@ selector2: Selector<S, R2>,

selector11: Selector<S, R11>,
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, T> (
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11
) => T
): OutputCachedSelector<
S,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11
) => T
>;
export default function createCachedSelector<
S,
P,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
T
>(
selector1: ParametricSelector<S, P, R1>,

@@ -306,9 +651,51 @@ selector2: ParametricSelector<S, P, R2>,

selector11: ParametricSelector<S, P, R11>,
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11) => T>;
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11
) => T
): OutputParametricCachedSelector<
S,
P,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11
) => T
>;
/* twelve selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, T> (
export default function createCachedSelector<
S,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
R12,
T
>(
selector1: Selector<S, R1>,

@@ -326,7 +713,51 @@ selector2: Selector<S, R2>,

selector12: Selector<S, R12>,
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11, res12: R12) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11, res12: R12) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, T> (
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11,
res12: R12
) => T
): OutputCachedSelector<
S,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11,
res12: R12
) => T
>;
export default function createCachedSelector<
S,
P,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
R12,
T
>(
selector1: ParametricSelector<S, P, R1>,

@@ -344,6 +775,35 @@ selector2: ParametricSelector<S, P, R2>,

selector12: ParametricSelector<S, P, R12>,
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11, res12: R12) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11, res12: R12) => T>;
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11,
res12: R12
) => T
): OutputParametricCachedSelector<
S,
P,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11,
res12: R12
) => T
>;

@@ -353,7 +813,7 @@ /* array argument */

/* one selector */
export default function createCachedSelector<S, R1, T> (
export default function createCachedSelector<S, R1, T>(
selectors: [Selector<S, R1>],
combiner: (res: R1) => T
): OutputCachedSelector<S, T, (res: R1) => T>;
export default function createCachedSelector<S, P, R1, T> (
export default function createCachedSelector<S, P, R1, T>(
selectors: [ParametricSelector<S, P, R1>],

@@ -364,10 +824,8 @@ combiner: (res: R1) => T

/* two selectors */
export default function createCachedSelector<S, R1, R2, T> (
selectors: [Selector<S, R1>,
Selector<S, R2>],
export default function createCachedSelector<S, R1, R2, T>(
selectors: [Selector<S, R1>, Selector<S, R2>],
combiner: (res1: R1, res2: R2) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2) => T>;
export default function createCachedSelector<S, P, R1, R2, T> (
selectors: [ParametricSelector<S, P, R1>,
ParametricSelector<S, P, R2>],
export default function createCachedSelector<S, P, R1, R2, T>(
selectors: [ParametricSelector<S, P, R1>, ParametricSelector<S, P, R2>],
combiner: (res1: R1, res2: R2) => T

@@ -377,12 +835,12 @@ ): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2) => T>;

/* three selectors */
export default function createCachedSelector<S, R1, R2, R3, T> (
selectors: [Selector<S, R1>,
Selector<S, R2>,
Selector<S, R3>],
export default function createCachedSelector<S, R1, R2, R3, T>(
selectors: [Selector<S, R1>, Selector<S, R2>, Selector<S, R3>],
combiner: (res1: R1, res2: R2, res3: R3) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, T> (
selectors: [ParametricSelector<S, P, R1>,
export default function createCachedSelector<S, P, R1, R2, R3, T>(
selectors: [
ParametricSelector<S, P, R1>,
ParametricSelector<S, P, R2>,
ParametricSelector<S, P, R3>],
ParametricSelector<S, P, R3>
],
combiner: (res1: R1, res2: R2, res3: R3) => T

@@ -392,38 +850,61 @@ ): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3) => T>;

/* four selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, T> (
selectors: [Selector<S, R1>,
export default function createCachedSelector<S, R1, R2, R3, R4, T>(
selectors: [
Selector<S, R1>,
Selector<S, R2>,
Selector<S, R3>,
Selector<S, R4>],
Selector<S, R4>
],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, T> (
selectors: [ParametricSelector<S, P, R1>,
export default function createCachedSelector<S, P, R1, R2, R3, R4, T>(
selectors: [
ParametricSelector<S, P, R1>,
ParametricSelector<S, P, R2>,
ParametricSelector<S, P, R3>,
ParametricSelector<S, P, R4>],
ParametricSelector<S, P, R4>
],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4) => T>;
): OutputParametricCachedSelector<
S,
P,
T,
(res1: R1, res2: R2, res3: R3, res4: R4) => T
>;
/* five selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, T> (
selectors: [Selector<S, R1>,
export default function createCachedSelector<S, R1, R2, R3, R4, R5, T>(
selectors: [
Selector<S, R1>,
Selector<S, R2>,
Selector<S, R3>,
Selector<S, R4>,
Selector<S, R5>],
Selector<S, R5>
],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, T> (
selectors: [ParametricSelector<S, P, R1>,
): OutputCachedSelector<
S,
T,
(res1: R1, res2: R2, res3: R3, res4: R4, res5: R5) => T
>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, T>(
selectors: [
ParametricSelector<S, P, R1>,
ParametricSelector<S, P, R2>,
ParametricSelector<S, P, R3>,
ParametricSelector<S, P, R4>,
ParametricSelector<S, P, R5>],
ParametricSelector<S, P, R5>
],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5) => T>;
): OutputParametricCachedSelector<
S,
P,
T,
(res1: R1, res2: R2, res3: R3, res4: R4, res5: R5) => T
>;
/* six selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, T> (
selectors: [Selector<S, R1>,
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, T>(
selectors: [
Selector<S, R1>,
Selector<S, R2>,

@@ -433,7 +914,13 @@ Selector<S, R3>,

Selector<S, R5>,
Selector<S, R6>],
Selector<S, R6>
],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, T> (
selectors: [ParametricSelector<S, P, R1>,
): OutputCachedSelector<
S,
T,
(res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6) => T
>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, T>(
selectors: [
ParametricSelector<S, P, R1>,
ParametricSelector<S, P, R2>,

@@ -443,9 +930,16 @@ ParametricSelector<S, P, R3>,

ParametricSelector<S, P, R5>,
ParametricSelector<S, P, R6>],
ParametricSelector<S, P, R6>
],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6) => T>;
): OutputParametricCachedSelector<
S,
P,
T,
(res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6) => T
>;
/* seven selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, T> (
selectors: [Selector<S, R1>,
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, T>(
selectors: [
Selector<S, R1>,
Selector<S, R2>,

@@ -456,9 +950,32 @@ Selector<S, R3>,

Selector<S, R6>,
Selector<S, R7>],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, R7, T> (
selectors: [ParametricSelector<S, P, R1>,
Selector<S, R7>
],
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7
) => T
): OutputCachedSelector<
S,
T,
(res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6, res7: R7) => T
>;
export default function createCachedSelector<
S,
P,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
T
>(
selectors: [
ParametricSelector<S, P, R1>,
ParametricSelector<S, P, R2>,

@@ -469,11 +986,35 @@ ParametricSelector<S, P, R3>,

ParametricSelector<S, P, R6>,
ParametricSelector<S, P, R7>],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7) => T>;
ParametricSelector<S, P, R7>
],
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7
) => T
): OutputParametricCachedSelector<
S,
P,
T,
(res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6, res7: R7) => T
>;
/* eight selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, R8, T> (
selectors: [Selector<S, R1>,
export default function createCachedSelector<
S,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
T
>(
selectors: [
Selector<S, R1>,
Selector<S, R2>,

@@ -485,9 +1026,43 @@ Selector<S, R3>,

Selector<S, R7>,
Selector<S, R8>],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, R7, R8, T> (
selectors: [ParametricSelector<S, P, R1>,
Selector<S, R8>
],
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8
) => T
): OutputCachedSelector<
S,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8
) => T
>;
export default function createCachedSelector<
S,
P,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
T
>(
selectors: [
ParametricSelector<S, P, R1>,
ParametricSelector<S, P, R2>,

@@ -499,11 +1074,46 @@ ParametricSelector<S, P, R3>,

ParametricSelector<S, P, R7>,
ParametricSelector<S, P, R8>],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8) => T>;
ParametricSelector<S, P, R8>
],
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8
) => T
): OutputParametricCachedSelector<
S,
P,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8
) => T
>;
/* nine selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, R8, R9, T> (
selectors: [Selector<S, R1>,
export default function createCachedSelector<
S,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
T
>(
selectors: [
Selector<S, R1>,
Selector<S, R2>,

@@ -516,9 +1126,46 @@ Selector<S, R3>,

Selector<S, R8>,
Selector<S, R9>],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, R7, R8, R9, T> (
selectors: [ParametricSelector<S, P, R1>,
Selector<S, R9>
],
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9
) => T
): OutputCachedSelector<
S,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9
) => T
>;
export default function createCachedSelector<
S,
P,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
T
>(
selectors: [
ParametricSelector<S, P, R1>,
ParametricSelector<S, P, R2>,

@@ -531,11 +1178,49 @@ ParametricSelector<S, P, R3>,

ParametricSelector<S, P, R8>,
ParametricSelector<S, P, R9>],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9) => T>;
ParametricSelector<S, P, R9>
],
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9
) => T
): OutputParametricCachedSelector<
S,
P,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9
) => T
>;
/* ten selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, T> (
selectors: [Selector<S, R1>,
export default function createCachedSelector<
S,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
T
>(
selectors: [
Selector<S, R1>,
Selector<S, R2>,

@@ -549,9 +1234,49 @@ Selector<S, R3>,

Selector<S, R9>,
Selector<S, R10>],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, T> (
selectors: [ParametricSelector<S, P, R1>,
Selector<S, R10>
],
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10
) => T
): OutputCachedSelector<
S,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10
) => T
>;
export default function createCachedSelector<
S,
P,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
T
>(
selectors: [
ParametricSelector<S, P, R1>,
ParametricSelector<S, P, R2>,

@@ -565,11 +1290,52 @@ ParametricSelector<S, P, R3>,

ParametricSelector<S, P, R9>,
ParametricSelector<S, P, R10>],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10) => T>;
ParametricSelector<S, P, R10>
],
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10
) => T
): OutputParametricCachedSelector<
S,
P,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10
) => T
>;
/* eleven selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, T> (
selectors: [Selector<S, R1>,
export default function createCachedSelector<
S,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
T
>(
selectors: [
Selector<S, R1>,
Selector<S, R2>,

@@ -584,9 +1350,52 @@ Selector<S, R3>,

Selector<S, R10>,
Selector<S, R11>],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, T> (
selectors: [ParametricSelector<S, P, R1>,
Selector<S, R11>
],
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11
) => T
): OutputCachedSelector<
S,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11
) => T
>;
export default function createCachedSelector<
S,
P,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
T
>(
selectors: [
ParametricSelector<S, P, R1>,
ParametricSelector<S, P, R2>,

@@ -601,11 +1410,55 @@ ParametricSelector<S, P, R3>,

ParametricSelector<S, P, R10>,
ParametricSelector<S, P, R11>],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11) => T>;
ParametricSelector<S, P, R11>
],
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11
) => T
): OutputParametricCachedSelector<
S,
P,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11
) => T
>;
/* twelve selectors */
export default function createCachedSelector<S, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, T> (
selectors: [Selector<S, R1>,
export default function createCachedSelector<
S,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
R12,
T
>(
selectors: [
Selector<S, R1>,
Selector<S, R2>,

@@ -621,9 +1474,55 @@ Selector<S, R3>,

Selector<S, R11>,
Selector<S, R12>],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11, res12: R12) => T
): OutputCachedSelector<S, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11, res12: R12) => T>;
export default function createCachedSelector<S, P, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, T> (
selectors: [ParametricSelector<S, P, R1>,
Selector<S, R12>
],
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11,
res12: R12
) => T
): OutputCachedSelector<
S,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11,
res12: R12
) => T
>;
export default function createCachedSelector<
S,
P,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
R12,
T
>(
selectors: [
ParametricSelector<S, P, R1>,
ParametricSelector<S, P, R2>,

@@ -639,36 +1538,93 @@ ParametricSelector<S, P, R3>,

ParametricSelector<S, P, R11>,
ParametricSelector<S, P, R12>],
combiner: (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11, res12: R12) => T
): OutputParametricCachedSelector<S, P, T, (res1: R1, res2: R2, res3: R3, res4: R4, res5: R5, res6: R6,
res7: R7, res8: R8, res9: R9, res10: R10, res11: R11, res12: R12) => T>;
ParametricSelector<S, P, R12>
],
combiner: (
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11,
res12: R12
) => T
): OutputParametricCachedSelector<
S,
P,
T,
(
res1: R1,
res2: R2,
res3: R3,
res4: R4,
res5: R5,
res6: R6,
res7: R7,
res8: R8,
res9: R9,
res10: R10,
res11: R11,
res12: R12
) => T
>;
export interface ICacheObject {
set (key: string|number, selectorFn: any): void;
get (key: string|number): any;
remove (key: string|number): void;
clear (): void;
set(key: any, selectorFn: any): void;
get(key: any): any;
remove(key: any): void;
clear(): void;
isValidCacheKey?(): boolean;
}
export class FlatCacheObject implements ICacheObject {
set (key: string|number, selectorFn: any): void;
get (key: string|number): any;
remove (key: string|number): void;
clear (): void;
export class FlatObjectCache implements ICacheObject {
set(key: string | number, selectorFn: any): void;
get(key: string | number): any;
remove(key: string | number): void;
clear(): void;
isValidCacheKey(): boolean;
}
export class FifoCacheObject implements ICacheObject {
constructor (options: { cacheSize: number });
set (key: string|number, selectorFn: any): void;
get (key: string|number): any;
remove (key: string|number): void;
clear (): void;
export class FifoObjectCache implements ICacheObject {
constructor(options: {cacheSize: number});
set(key: string | number, selectorFn: any): void;
get(key: string | number): any;
remove(key: string | number): void;
clear(): void;
isValidCacheKey(): boolean;
}
export class LruCacheObject implements ICacheObject {
constructor (options: { cacheSize: number });
set (key: string|number, selectorFn: any): void;
get (key: string|number): any;
remove (key: string|number): void;
clear (): void;
export class LruObjectCache implements ICacheObject {
constructor(options: {cacheSize: number});
set(key: string | number, selectorFn: any): void;
get(key: string | number): any;
remove(key: string | number): void;
clear(): void;
isValidCacheKey(): boolean;
}
export class FlatMapCache implements ICacheObject {
set(key: any, selectorFn: any): void;
get(key: any): any;
remove(key: any): void;
clear(): void;
}
export class FifoMapCache implements ICacheObject {
constructor(options: {cacheSize: number});
set(key: any, selectorFn: any): void;
get(key: any): any;
remove(key: any): void;
clear(): void;
}
export class LruMapCache implements ICacheObject {
constructor(options: {cacheSize: number});
set(key: any, selectorFn: any): void;
get(key: any): any;
remove(key: any): void;
clear(): void;
}
import {createSelector} from 'reselect';
import FlatCacheObject from './cache/FlatCacheObject';
import FlatObjectCache from './cache/FlatObjectCache';
export default function createCachedSelector(...funcs) {
const defaultCacheCreator = FlatCacheObject;
const defaultCacheCreator = FlatObjectCache;
const defaultCacheKeyValidator = () => true;
function createCachedSelector(...funcs) {
return (resolver, options = {}) => {
let cache;
let selectorCreator;
// Allow "options" to be provided as a "selectorCreator" for backward compatibility
// @TODO Remove "options" as a function in next breaking release
// @NOTE Versions 0.x/1.x accepted "options" as a function
if (typeof options === 'function') {
console.warn(
'[re-reselect] Deprecation warning: "selectorCreator" argument is discouraged and will be removed in the upcoming major release. Please use "options.selectorCreator" instead.'
throw new Error(
'[re-reselect] Second argument "options" must be an object. Please use "options.selectorCreator" to provide a custom selectorCreator.'
);
cache = new defaultCacheCreator();
selectorCreator = options;
} else {
cache = options.cacheObject || new defaultCacheCreator();
selectorCreator = options.selectorCreator || createSelector;
}
const cache = options.cacheObject || new defaultCacheCreator();
const selectorCreator = options.selectorCreator || createSelector;
const isValidCacheKey = cache.isValidCacheKey || defaultCacheKeyValidator;
// Application receives this function
const selector = function(...args) {
// Application receives this function
const cacheKey = resolver(...args);
if (typeof cacheKey === 'string' || typeof cacheKey === 'number') {
if (isValidCacheKey(cacheKey)) {
let cacheResponse = cache.get(cacheKey);

@@ -38,2 +34,5 @@

}
console.warn(
`[re-reselect] Invalid cache key "${cacheKey}" has been returned by resolver function.`
);
return undefined;

@@ -64,4 +63,16 @@ };

export {FlatCacheObject};
export {default as FifoCacheObject} from './cache/FifoCacheObject';
export {default as LruCacheObject} from './cache/LruCacheObject';
export default createCachedSelector;
// Cache objects
export {FlatObjectCache};
export {default as FifoObjectCache} from './cache/FifoObjectCache';
export {default as LruObjectCache} from './cache/LruObjectCache';
export {default as FlatMapCache} from './cache/FlatMapCache';
export {default as FifoMapCache} from './cache/FifoMapCache';
export {default as LruMapCache} from './cache/LruMapCache';
// Deprecated cache objects exports
// @TODO remove in next major release
export {FlatObjectCache as FlatCacheObject};
export {default as FifoCacheObject} from './cache/FifoObjectCache';
export {default as LruCacheObject} from './cache/LruMapCache';

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc