reselect-tools
Advanced tools
Comparing version 0.0.4 to 0.0.5
@@ -36,3 +36,2 @@ (function (global, factory) { | ||
var _registered = {}; | ||
var _getState = null; | ||
@@ -59,20 +58,12 @@ var _allSelectors = new Set(); | ||
function registerSelectors(selectors) { | ||
var actuallySelectors = {}; | ||
Object.keys(selectors).forEach(function (key) { | ||
var selector = selectors[key]; | ||
Object.keys(selectors).forEach(function (name) { | ||
var selector = selectors[name]; | ||
if (selector.resultFunc || _isFunction(selector)) { | ||
actuallySelectors[key] = selector; | ||
selector.selectorName = name; | ||
_allSelectors.add(selector); | ||
} | ||
}); | ||
return Object.assign(_registered, actuallySelectors); | ||
} | ||
function _unregisterSelectors() { | ||
Object.keys(_registered).forEach(function (key) { | ||
delete _registered[key]; | ||
}); | ||
} | ||
function reset() { | ||
_unregisterSelectors(); | ||
_getState = null; | ||
@@ -83,7 +74,30 @@ _allSelectors = new Set(); | ||
function checkSelector(selector) { | ||
if (typeof selector === 'string') { | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
var isRegistered = false; | ||
if (typeof selector === 'string' && _isFunction(_registered[selector])) { | ||
selector = _registered[selector]; | ||
isRegistered = true; | ||
try { | ||
for (var _iterator = _allSelectors[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var possibleSelector = _step.value; | ||
if (possibleSelector.selectorName === selector) { | ||
selector = possibleSelector; | ||
break; | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
} | ||
@@ -95,14 +109,12 @@ | ||
if (!isRegistered) { | ||
Object.keys(_registered).forEach(function (key) { | ||
if (_registered[key] === selector) { | ||
isRegistered = true; | ||
} | ||
}); | ||
} | ||
var _selector = selector, | ||
_selector$dependencie = _selector.dependencies, | ||
dependencies = _selector$dependencie === undefined ? [] : _selector$dependencie, | ||
_selector$selectorNam = _selector.selectorName, | ||
selectorName = _selector$selectorNam === undefined ? null : _selector$selectorNam; | ||
var dependencies = selector.dependencies || []; | ||
var isNamed = typeof selectorName === 'string'; | ||
var recomputations = selector.recomputations ? selector.recomputations() : null; | ||
var ret = { dependencies: dependencies, recomputations: recomputations, isRegistered: isRegistered }; | ||
var ret = { dependencies: dependencies, recomputations: recomputations, isNamed: isNamed, selectorName: selectorName }; | ||
if (_getState) { | ||
@@ -130,3 +142,7 @@ var state = _getState(); | ||
var defaultSelectorKey = function defaultSelectorKey(selector, registry) { | ||
var defaultSelectorKey = function defaultSelectorKey(selector) { | ||
if (selector.selectorName) { | ||
return selector.selectorName; | ||
} | ||
if (selector.name) { | ||
@@ -137,29 +153,2 @@ // if it's a vanilla function, it will have a name. | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
try { | ||
for (var _iterator = Object.keys(registry)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var key = _step.value; | ||
if (registry[key] === selector) { | ||
return key; | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
return (selector.dependencies || []).reduce(function (base, dep) { | ||
@@ -175,3 +164,3 @@ return base + _sumString(dep); | ||
var addToGraph = function addToGraph(selector) { | ||
var name = selectorKey(selector, _registered); | ||
var name = selectorKey(selector); | ||
if (graph.nodes[name]) return; | ||
@@ -181,7 +170,7 @@ | ||
recomputations = _checkSelector.recomputations, | ||
isRegistered = _checkSelector.isRegistered; | ||
isNamed = _checkSelector.isNamed; | ||
graph.nodes[name] = { | ||
recomputations: recomputations, | ||
isRegistered: isRegistered, | ||
isNamed: isNamed, | ||
name: name | ||
@@ -193,3 +182,3 @@ }; | ||
addToGraph(dependency); | ||
graph.edges.push({ from: name, to: selectorKey(dependency, _registered) }); | ||
graph.edges.push({ from: name, to: selectorKey(dependency) }); | ||
}); | ||
@@ -196,0 +185,0 @@ }; |
@@ -1,1 +0,1 @@ | ||
(function(e,r){if(typeof define==="function"&&define.amd){define("ReselectTools",["exports","reselect"],r)}else if(typeof exports!=="undefined"){r(exports,require("reselect"))}else{var t={exports:{}};r(t.exports,e.Reselect);e.ReselectTools=t.exports}})(this,function(e,r){"use strict";e.__esModule=true;e.createSelectorWithDependencies=u;e.registerSelectors=c;e.reset=s;e.checkSelector=l;e.getStateWith=d;e.selectorGraph=y;function t(e){if(Array.isArray(e)){for(var r=0,t=Array(e.length);r<e.length;r++){t[r]=e[r]}return t}else{return Array.from(e)}}var n={};var i=null;var o=new Set;var a=function e(r){return typeof r==="function"};function u(){for(var e=arguments.length,n=Array(e),i=0;i<e;i++){n[i]=arguments[i]}var a=n.pop();var u=Array.isArray(n[0])?n[0]:n;var c=r.createSelector.apply(undefined,t(u).concat([a]));c.dependencies=u;o.add(c);return c}function c(e){var r={};Object.keys(e).forEach(function(t){var n=e[t];if(n.resultFunc||a(n)){r[t]=n}});return Object.assign(n,r)}function f(){Object.keys(n).forEach(function(e){delete n[e]})}function s(){f();i=null;o=new Set}function l(e){var r=false;if(typeof e==="string"&&a(n[e])){e=n[e];r=true}if(!a(e)){throw new Error("Selector "+e+" is not a function...has it been registered?")}if(!r){Object.keys(n).forEach(function(t){if(n[t]===e){r=true}})}var t=e.dependencies||[];var o=e.recomputations?e.recomputations():null;var u={dependencies:t,recomputations:o,isRegistered:r};if(i){var c=i();var f=t.map(function(e){return e(c)});var s=e(c);Object.assign(u,{inputs:f,output:s})}return u}function d(e){i=e}function v(e){return Array.from(e.toString()).reduce(function(e,r){return r.charCodeAt(0)+e},0)}var p=function e(r,t){if(r.name){return r.name}var n=true;var i=false;var o=undefined;try{for(var a=Object.keys(t)[Symbol.iterator](),u;!(n=(u=a.next()).done);n=true){var c=u.value;if(t[c]===r){return c}}}catch(e){i=true;o=e}finally{try{if(!n&&a.return){a.return()}}finally{if(i){throw o}}}return(r.dependencies||[]).reduce(function(e,r){return e+v(r)},(r.resultFunc?r.resultFunc:r).toString())};function y(){var e=arguments.length>0&&arguments[0]!==undefined?arguments[0]:p;var r={nodes:{},edges:[]};var t=function t(i){var o=e(i,n);if(r.nodes[o])return;var a=l(i),u=a.recomputations,c=a.isRegistered;r.nodes[o]={recomputations:u,isRegistered:c,name:o};var f=i.dependencies||[];f.forEach(function(i){t(i);r.edges.push({from:o,to:e(i,n)})})};var i=true;var a=false;var u=undefined;try{for(var c=o[Symbol.iterator](),f;!(i=(f=c.next()).done);i=true){var s=f.value;t(s)}}catch(e){a=true;u=e}finally{try{if(!i&&c.return){c.return()}}finally{if(a){throw u}}}return r}if(typeof window!=="undefined"){window.__RESELECT_TOOLS__={selectorGraph:y,checkSelector:l}}}); | ||
(function(e,r){if(typeof define==="function"&&define.amd){define("ReselectTools",["exports","reselect"],r)}else if(typeof exports!=="undefined"){r(exports,require("reselect"))}else{var t={exports:{}};r(t.exports,e.Reselect);e.ReselectTools=t.exports}})(this,function(e,r){"use strict";e.__esModule=true;e.createSelectorWithDependencies=i;e.registerSelectors=u;e.reset=c;e.checkSelector=f;e.getStateWith=s;e.selectorGraph=v;function t(e){if(Array.isArray(e)){for(var r=0,t=Array(e.length);r<e.length;r++){t[r]=e[r]}return t}else{return Array.from(e)}}var n=null;var o=new Set;var a=function e(r){return typeof r==="function"};function i(){for(var e=arguments.length,n=Array(e),a=0;a<e;a++){n[a]=arguments[a]}var i=n.pop();var u=Array.isArray(n[0])?n[0]:n;var c=r.createSelector.apply(undefined,t(u).concat([i]));c.dependencies=u;o.add(c);return c}function u(e){Object.keys(e).forEach(function(r){var t=e[r];if(t.resultFunc||a(t)){t.selectorName=r;o.add(t)}})}function c(){n=null;o=new Set}function f(e){if(typeof e==="string"){var r=true;var t=false;var i=undefined;try{for(var u=o[Symbol.iterator](),c;!(r=(c=u.next()).done);r=true){var f=c.value;if(f.selectorName===e){e=f;break}}}catch(e){t=true;i=e}finally{try{if(!r&&u.return){u.return()}}finally{if(t){throw i}}}}if(!a(e)){throw new Error("Selector "+e+" is not a function...has it been registered?")}var s=e,l=s.dependencies,d=l===undefined?[]:l,v=s.selectorName,p=v===undefined?null:v;var y=typeof p==="string";var m=e.recomputations?e.recomputations():null;var h={dependencies:d,recomputations:m,isNamed:y,selectorName:p};if(n){var S=n();var g=d.map(function(e){return e(S)});var w=e(S);Object.assign(h,{inputs:g,output:w})}return h}function s(e){n=e}function l(e){return Array.from(e.toString()).reduce(function(e,r){return r.charCodeAt(0)+e},0)}var d=function e(r){if(r.selectorName){return r.selectorName}if(r.name){return r.name}return(r.dependencies||[]).reduce(function(e,r){return e+l(r)},(r.resultFunc?r.resultFunc:r).toString())};function v(){var e=arguments.length>0&&arguments[0]!==undefined?arguments[0]:d;var r={nodes:{},edges:[]};var t=function t(n){var o=e(n);if(r.nodes[o])return;var a=f(n),i=a.recomputations,u=a.isNamed;r.nodes[o]={recomputations:i,isNamed:u,name:o};var c=n.dependencies||[];c.forEach(function(n){t(n);r.edges.push({from:o,to:e(n)})})};var n=true;var a=false;var i=undefined;try{for(var u=o[Symbol.iterator](),c;!(n=(c=u.next()).done);n=true){var s=c.value;t(s)}}catch(e){a=true;i=e}finally{try{if(!n&&u.return){u.return()}}finally{if(a){throw i}}}return r}if(typeof window!=="undefined"){window.__RESELECT_TOOLS__={selectorGraph:v,checkSelector:f}}}); |
105
es/index.js
@@ -17,3 +17,2 @@ 'use strict'; | ||
var _registered = {}; | ||
var _getState = null; | ||
@@ -40,20 +39,12 @@ var _allSelectors = new Set(); | ||
function registerSelectors(selectors) { | ||
var actuallySelectors = {}; | ||
Object.keys(selectors).forEach(function (key) { | ||
var selector = selectors[key]; | ||
Object.keys(selectors).forEach(function (name) { | ||
var selector = selectors[name]; | ||
if (selector.resultFunc || _isFunction(selector)) { | ||
actuallySelectors[key] = selector; | ||
selector.selectorName = name; | ||
_allSelectors.add(selector); | ||
} | ||
}); | ||
return Object.assign(_registered, actuallySelectors); | ||
} | ||
function _unregisterSelectors() { | ||
Object.keys(_registered).forEach(function (key) { | ||
delete _registered[key]; | ||
}); | ||
} | ||
function reset() { | ||
_unregisterSelectors(); | ||
_getState = null; | ||
@@ -64,7 +55,30 @@ _allSelectors = new Set(); | ||
function checkSelector(selector) { | ||
if (typeof selector === 'string') { | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
var isRegistered = false; | ||
if (typeof selector === 'string' && _isFunction(_registered[selector])) { | ||
selector = _registered[selector]; | ||
isRegistered = true; | ||
try { | ||
for (var _iterator = _allSelectors[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var possibleSelector = _step.value; | ||
if (possibleSelector.selectorName === selector) { | ||
selector = possibleSelector; | ||
break; | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
} | ||
@@ -76,14 +90,12 @@ | ||
if (!isRegistered) { | ||
Object.keys(_registered).forEach(function (key) { | ||
if (_registered[key] === selector) { | ||
isRegistered = true; | ||
} | ||
}); | ||
} | ||
var _selector = selector, | ||
_selector$dependencie = _selector.dependencies, | ||
dependencies = _selector$dependencie === undefined ? [] : _selector$dependencie, | ||
_selector$selectorNam = _selector.selectorName, | ||
selectorName = _selector$selectorNam === undefined ? null : _selector$selectorNam; | ||
var dependencies = selector.dependencies || []; | ||
var isNamed = typeof selectorName === 'string'; | ||
var recomputations = selector.recomputations ? selector.recomputations() : null; | ||
var ret = { dependencies: dependencies, recomputations: recomputations, isRegistered: isRegistered }; | ||
var ret = { dependencies: dependencies, recomputations: recomputations, isNamed: isNamed, selectorName: selectorName }; | ||
if (_getState) { | ||
@@ -111,3 +123,7 @@ var state = _getState(); | ||
var defaultSelectorKey = function defaultSelectorKey(selector, registry) { | ||
var defaultSelectorKey = function defaultSelectorKey(selector) { | ||
if (selector.selectorName) { | ||
return selector.selectorName; | ||
} | ||
if (selector.name) { | ||
@@ -118,29 +134,2 @@ // if it's a vanilla function, it will have a name. | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
try { | ||
for (var _iterator = Object.keys(registry)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var key = _step.value; | ||
if (registry[key] === selector) { | ||
return key; | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
return (selector.dependencies || []).reduce(function (base, dep) { | ||
@@ -156,3 +145,3 @@ return base + _sumString(dep); | ||
var addToGraph = function addToGraph(selector) { | ||
var name = selectorKey(selector, _registered); | ||
var name = selectorKey(selector); | ||
if (graph.nodes[name]) return; | ||
@@ -162,7 +151,7 @@ | ||
recomputations = _checkSelector.recomputations, | ||
isRegistered = _checkSelector.isRegistered; | ||
isNamed = _checkSelector.isNamed; | ||
graph.nodes[name] = { | ||
recomputations: recomputations, | ||
isRegistered: isRegistered, | ||
isNamed: isNamed, | ||
name: name | ||
@@ -174,3 +163,3 @@ }; | ||
addToGraph(dependency); | ||
graph.edges.push({ from: name, to: selectorKey(dependency, _registered) }); | ||
graph.edges.push({ from: name, to: selectorKey(dependency) }); | ||
}); | ||
@@ -177,0 +166,0 @@ }; |
105
lib/index.js
@@ -15,3 +15,2 @@ 'use strict'; | ||
var _registered = {}; | ||
var _getState = null; | ||
@@ -38,20 +37,12 @@ var _allSelectors = new Set(); | ||
function registerSelectors(selectors) { | ||
var actuallySelectors = {}; | ||
Object.keys(selectors).forEach(function (key) { | ||
var selector = selectors[key]; | ||
Object.keys(selectors).forEach(function (name) { | ||
var selector = selectors[name]; | ||
if (selector.resultFunc || _isFunction(selector)) { | ||
actuallySelectors[key] = selector; | ||
selector.selectorName = name; | ||
_allSelectors.add(selector); | ||
} | ||
}); | ||
return Object.assign(_registered, actuallySelectors); | ||
} | ||
function _unregisterSelectors() { | ||
Object.keys(_registered).forEach(function (key) { | ||
delete _registered[key]; | ||
}); | ||
} | ||
function reset() { | ||
_unregisterSelectors(); | ||
_getState = null; | ||
@@ -62,7 +53,30 @@ _allSelectors = new Set(); | ||
function checkSelector(selector) { | ||
if (typeof selector === 'string') { | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
var isRegistered = false; | ||
if (typeof selector === 'string' && _isFunction(_registered[selector])) { | ||
selector = _registered[selector]; | ||
isRegistered = true; | ||
try { | ||
for (var _iterator = _allSelectors[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var possibleSelector = _step.value; | ||
if (possibleSelector.selectorName === selector) { | ||
selector = possibleSelector; | ||
break; | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
} | ||
@@ -74,14 +88,12 @@ | ||
if (!isRegistered) { | ||
Object.keys(_registered).forEach(function (key) { | ||
if (_registered[key] === selector) { | ||
isRegistered = true; | ||
} | ||
}); | ||
} | ||
var _selector = selector, | ||
_selector$dependencie = _selector.dependencies, | ||
dependencies = _selector$dependencie === undefined ? [] : _selector$dependencie, | ||
_selector$selectorNam = _selector.selectorName, | ||
selectorName = _selector$selectorNam === undefined ? null : _selector$selectorNam; | ||
var dependencies = selector.dependencies || []; | ||
var isNamed = typeof selectorName === 'string'; | ||
var recomputations = selector.recomputations ? selector.recomputations() : null; | ||
var ret = { dependencies: dependencies, recomputations: recomputations, isRegistered: isRegistered }; | ||
var ret = { dependencies: dependencies, recomputations: recomputations, isNamed: isNamed, selectorName: selectorName }; | ||
if (_getState) { | ||
@@ -109,3 +121,7 @@ var state = _getState(); | ||
var defaultSelectorKey = function defaultSelectorKey(selector, registry) { | ||
var defaultSelectorKey = function defaultSelectorKey(selector) { | ||
if (selector.selectorName) { | ||
return selector.selectorName; | ||
} | ||
if (selector.name) { | ||
@@ -116,29 +132,2 @@ // if it's a vanilla function, it will have a name. | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
try { | ||
for (var _iterator = Object.keys(registry)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var key = _step.value; | ||
if (registry[key] === selector) { | ||
return key; | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
return (selector.dependencies || []).reduce(function (base, dep) { | ||
@@ -154,3 +143,3 @@ return base + _sumString(dep); | ||
var addToGraph = function addToGraph(selector) { | ||
var name = selectorKey(selector, _registered); | ||
var name = selectorKey(selector); | ||
if (graph.nodes[name]) return; | ||
@@ -160,7 +149,7 @@ | ||
recomputations = _checkSelector.recomputations, | ||
isRegistered = _checkSelector.isRegistered; | ||
isNamed = _checkSelector.isNamed; | ||
graph.nodes[name] = { | ||
recomputations: recomputations, | ||
isRegistered: isRegistered, | ||
isNamed: isNamed, | ||
name: name | ||
@@ -172,3 +161,3 @@ }; | ||
addToGraph(dependency); | ||
graph.edges.push({ from: name, to: selectorKey(dependency, _registered) }); | ||
graph.edges.push({ from: name, to: selectorKey(dependency) }); | ||
}); | ||
@@ -175,0 +164,0 @@ }; |
{ | ||
"name": "reselect-tools", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "Selector Debugging Tools for Reselect.", | ||
@@ -14,3 +14,3 @@ "main": "lib/index.js", | ||
"bugs": { | ||
"url": "https://github.com/TODO" | ||
"url": "https://github.com/skortchmark9/reselect-tools" | ||
}, | ||
@@ -17,0 +17,0 @@ "scripts": { |
@@ -6,8 +6,9 @@ # Reselect Tools | ||
Some tools for working with the [reselect](https://github.com/reactjs/reselect) library: | ||
Tools for working with the [reselect](https://github.com/reactjs/reselect) library: | ||
*Check selector dependencies, inputs, outputs, and recomputations at any time without refreshing!* | ||
* Check selector dependencies, inputs, outputs, and recomputations at any time. | ||
* Output a JSON representation of your selector graph (soon to be a visual browser extension!) | ||
![Graph](examples/extension.png) | ||
```js | ||
@@ -38,3 +39,5 @@ // in selectors.js | ||
dependencies: [ui$, users$], | ||
recomputations: 1 | ||
recomputations: 1, | ||
isNamed: false, | ||
selectorName: 'currentUser$' | ||
} | ||
@@ -72,4 +75,4 @@ selectorGraph() | ||
- [Installation](#installation) | ||
- [Motivation](#motivation) | ||
- [Getting Started](#getting-started) | ||
- [Example](#example) | ||
@@ -81,8 +84,5 @@ - [API](#api) | ||
- [`selectorGraph`](#selectorgraphselectorkey--defaultselectorkey) | ||
- [`registerSelectors`](#registorselectorskeyselectorobj) | ||
- [License](#license) | ||
## Installation | ||
npm install reselect-tools | ||
## Motivation | ||
@@ -94,7 +94,55 @@ | ||
I am writing a chrome extension to take the output of selectorGraph() and create a graph inside the devtools, but you can use this library today for ```checkSelector``` and to create selector graphs statically (see the [example](#example)). | ||
This library was intended to be used with the [chrome extension](https://github.com/skortchmark9/reselect-devtools-extension). However, it can be still be [useful without the chrome extension installed](#without-the-extension). The chrome extension will be useless without this library. | ||
See the original reselect issue [here](https://github.com/reactjs/reselect/issues/279). | ||
## Getting Started | ||
Firstly, I apologize in advance that this section is required. It would be great to match the experience of installing redux devtools or react's. Hopefully the tools will be more tightly integrated with reselect at some point and these steps won't be necessary. | ||
1. Install the Package | ||
npm install -s reselect-tools | ||
2. Grab the [Chrome Extension](https://chrome.google.com/webstore/detail/reselect-devtools/cjmaipngmabglflfeepmdiffcijhjlbb) | ||
3. Tracking Dependencies: | ||
Replace ```createSelector``` from reselect with ```createSelectorWithDependencies```! | ||
``` | ||
import { | ||
createSelectorWithDependencies as createSelector | ||
} from 'reselect-tools' | ||
``` | ||
That's it! At this point you should be able to open the devtools and view the selector graph. While the graph will be correct, it might be hard to understand what's going on without... | ||
4. Naming Selectors: | ||
``` | ||
const foo$ = createSelectorWithDependencies(bar$, (foo) => foo + 1); | ||
foo$.selectorName = 'foo$' // selector while show up as 'foo' | ||
``` | ||
This can get tedious, so you might want to register your selectors all at once. | ||
``` | ||
import { registerSelectors } from 'reselect-tools' | ||
registerSelectors({ foo$, bar$ }); | ||
``` | ||
Or if you're keeping all your selectors in the same place: | ||
``` | ||
import { registerSelectors } from 'reselect-tools' | ||
import * as selectors from './selectors.js' | ||
ReselectTools.registerSelectors(selectors) | ||
``` | ||
Now the graph should have nice names for your selectors. | ||
5. Checking Selector Inputs and Outputs | ||
Imagine that your tests are passing, but you think some selector in your app might be receiving bad input from a depended-upon selector. Where in the chain is the problem? In order to allow ```checkSelector``` and by extension, the extension, to get this information, we need to give Reselect Tools some way of feeding state to a selector. | ||
``` | ||
import store from './configureStore' | ||
ReselectTools.getStateWith(() => store.getState()) | ||
``` | ||
## Example | ||
@@ -189,6 +237,25 @@ npm run example | ||
Nodes in the graph are keyed by string names. The name is determined by the ```selectorKey``` function. This function takes a selector and the registry populated from ```registerSelectors```. The ```defaultSelectorKey``` looks for a function name, then a match in the registry, and finally resorts to calling toString on the selector's ```resultFunc```. | ||
Nodes in the graph are keyed by string names. The name is determined by the ```selectorKey``` function. This function takes a selector outputs a string which must be unique and consistent for a given selector. The ```defaultSelectorKey``` looks for a function name, then a match in the registry, and finally resorts to calling toString on the selector's ```resultFunc```. | ||
See the [tests](test/test.js#L246) for an alternate selectorKey. | ||
### registorSelectors(keySelectorObj) | ||
Simple helper to set names on an object containing selector names as keys and selectors as values. Has the side effect of guaranteeing a selector is added to the graph (even if it was not created with ```createSelectorWithDependencies``` and no selector in the graph depends on it). | ||
### Without The Extension | ||
If you're using an unsupported browser, or aren't happy with the extension, you can still get at the data. | ||
The dev tools bind to your app via this global: | ||
``` | ||
window.__RESELECT_TOOLS__ = { | ||
selectorGraph, | ||
checkSelector | ||
} | ||
``` | ||
Even without the devtools, you can call ```__RESELECT_TOOLS__.checkSelector('mySelector$')``` from the developer console or ```__RESLECT_TOOLS__.selectorGraph()``` to see what's going on. If the JSON output of the graph is hard to parse, there's an example of how to create a visual selector graph [here](tests/your-app.js). | ||
## License | ||
@@ -195,0 +262,0 @@ |
import { createSelector } from 'reselect' | ||
const _registered = {} | ||
let _getState = null | ||
@@ -20,21 +19,13 @@ let _allSelectors = new Set() | ||
export function registerSelectors(selectors) { | ||
const actuallySelectors = {} | ||
Object.keys(selectors).forEach((key) => { | ||
const selector = selectors[key] | ||
Object.keys(selectors).forEach((name) => { | ||
const selector = selectors[name] | ||
if (selector.resultFunc || _isFunction(selector)) { | ||
actuallySelectors[key] = selector | ||
selector.selectorName = name | ||
_allSelectors.add(selector) | ||
} | ||
}) | ||
return Object.assign(_registered, actuallySelectors) | ||
} | ||
function _unregisterSelectors() { | ||
Object.keys(_registered).forEach((key) => { | ||
delete _registered[key] | ||
}) | ||
} | ||
export function reset() { | ||
_unregisterSelectors() | ||
_getState = null | ||
@@ -46,7 +37,9 @@ _allSelectors = new Set() | ||
export function checkSelector(selector) { | ||
let isRegistered = false | ||
if (typeof selector === 'string' && _isFunction(_registered[selector])) { | ||
selector = _registered[selector] | ||
isRegistered = true | ||
if (typeof selector === 'string') { | ||
for (const possibleSelector of _allSelectors) { | ||
if (possibleSelector.selectorName === selector) { | ||
selector = possibleSelector | ||
break | ||
} | ||
} | ||
} | ||
@@ -58,14 +51,8 @@ | ||
if (!isRegistered) { | ||
Object.keys(_registered).forEach((key) => { | ||
if (_registered[key] === selector) { | ||
isRegistered = true | ||
} | ||
}) | ||
} | ||
const dependencies = selector.dependencies || [] | ||
const { dependencies = [], selectorName = null } = selector | ||
const isNamed = typeof selectorName === 'string' | ||
const recomputations = selector.recomputations ? selector.recomputations() : null | ||
const ret = { dependencies, recomputations, isRegistered } | ||
const ret = { dependencies, recomputations, isNamed, selectorName } | ||
if (_getState) { | ||
@@ -91,3 +78,7 @@ const state = _getState() | ||
const defaultSelectorKey = (selector, registry) => { | ||
const defaultSelectorKey = (selector) => { | ||
if (selector.selectorName) { | ||
return selector.selectorName | ||
} | ||
if (selector.name) { // if it's a vanilla function, it will have a name. | ||
@@ -97,8 +88,2 @@ return selector.name | ||
for (let key of Object.keys(registry)) { | ||
if (registry[key] === selector) { | ||
return key | ||
} | ||
} | ||
return (selector.dependencies || []).reduce((base, dep) => { | ||
@@ -112,8 +97,8 @@ return base + _sumString(dep) | ||
const addToGraph = (selector) => { | ||
const name = selectorKey(selector, _registered) | ||
const name = selectorKey(selector) | ||
if (graph.nodes[name]) return | ||
const { recomputations, isRegistered } = checkSelector(selector) | ||
const { recomputations, isNamed } = checkSelector(selector) | ||
graph.nodes[name] = { | ||
recomputations, | ||
isRegistered, | ||
isNamed, | ||
name | ||
@@ -125,3 +110,3 @@ } | ||
addToGraph(dependency) | ||
graph.edges.push({ from: name, to: selectorKey(dependency, _registered) }) | ||
graph.edges.push({ from: name, to: selectorKey(dependency) }) | ||
}) | ||
@@ -128,0 +113,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
36063
267
598