ruddy
Version:
Modularized state-management tools for modern front-end applications. Manage dispatched messages in a clean and predictable way for either small or large scale projects
136 lines (106 loc) • 5.22 kB
JavaScript
;
exports.__esModule = true;
exports.createDuckSelector = exports.createSelector = exports.deriveSelectors = exports.needsExtraction = undefined;
var _init = require('ramda/src/init');
var _init2 = _interopRequireDefault(_init);
var _last = require('ramda/src/last');
var _last2 = _interopRequireDefault(_last);
var _converge = require('ramda/src/converge');
var _converge2 = _interopRequireDefault(_converge);
var _memoize = require('ramda/src/memoize');
var _memoize2 = _interopRequireDefault(_memoize);
var _pickBy = require('ramda/src/pickBy');
var _pickBy2 = _interopRequireDefault(_pickBy);
var _reduce = require('ramda/src/reduce');
var _reduce2 = _interopRequireDefault(_reduce);
var _toPairs = require('ramda/src/toPairs');
var _toPairs2 = _interopRequireDefault(_toPairs);
var _prop = require('ramda/src/prop');
var _prop2 = _interopRequireDefault(_prop);
var _equals = require('ramda/src/equals');
var _equals2 = _interopRequireDefault(_equals);
var _compose = require('ramda/src/compose');
var _compose2 = _interopRequireDefault(_compose);
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* A simple function that checks an Object for a prop called "needsExtraction"
* and determines if it is set to `true`
*
* @func
* @sig {k: v} -> Boolean
* @param {Object}
* @returns {Boolean}
*/
var needsExtraction = exports.needsExtraction = (0, _compose2.default)((0, _equals2.default)(true), (0, _prop2.default)('needsExtraction'));
/**
* Helper utility to assist in composing the selectors.
* Previously defined selectors can be used to derive future selectors.
* Any selector which is a pre-extracted state is expected to have a
* `needsExtraction: true` and an accompanying `justAddDuckSelectors` prop
* which performs the extraction. This function creates a sort of running total
* of all selectors and passes them into each `justAddDuckSelectors()`.
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} selectors An Object of selector functions, some of which may
* need to be extracted (those which require access to fellow selectors)
* @returns {Object} selectors, but now with access to fellow selectors
*/
var deriveSelectors = exports.deriveSelectors = function deriveSelectors() {
var selectors = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return (0, _compose2.default)((0, _reduce2.default)(function (composedSelectors, _ref) {
var _extends2;
var key = _ref[0],
selector = _ref[1];
return _extends({}, composedSelectors, (_extends2 = {}, _extends2[key] = selector.justAddDuckSelectors(composedSelectors), _extends2));
}, selectors), _toPairs2.default, (0, _pickBy2.default)(needsExtraction))(selectors);
};
/**
* A simple, Ramda implementation of Reselect's `createSelector()` function,
* taken from [this example](https://twitter.com/sharifsbeat/status/891001130632830976)
* The cost of all the Ramda functions which make up this library has already been
* paid, so may as well save on another dependency. You can still use Reselect
* if you prefer; they both work the same.
*
* @func
* @sig (*... -> a) -> (*... -> a)
* @ param {...Function} selectors One or more selector functions to be "merged" into one
* @returns {Function} A memoized "selector" function
*/
var createSelector = exports.createSelector = function createSelector() {
for (var _len = arguments.length, selectors = Array(_len), _key = 0; _key < _len; _key++) {
selectors[_key] = arguments[_key];
}
return (0, _memoize2.default)((0, _converge2.default)((0, _last2.default)(selectors), (0, _init2.default)(selectors)));
};
/**
* Selectors that require one or more of the existing selectors are built using this helper,
* and the extraction function is passed in as a param. The simplest type of
* extractor function that this helper was initially built to handle would be:
*
* selectors => state => selectors.getSomethingFrom(state)
*
* Additionally, the return Object is in a ready-to-be-extracted state (which is
* why it is flagged `needsExtraction: true`) and so invoking its
* `justAddDuckSelectors()` will perform the final step of running the extractor
* (ideally when the rest of the selectors are all being derived)
*
* @func
* @sig Function -> {k: v}
* @param {Function} extractFunction A helper that will extract all the existing selectors
* @returns {Object}
*/
var createDuckSelector = exports.createDuckSelector = function createDuckSelector(extractFunction) {
return {
needsExtraction: true,
justAddDuckSelectors: function justAddDuckSelectors() {
var allSelectorsObject = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var extracted = extractFunction(allSelectorsObject);
if (Array.isArray(extracted)) {
return createSelector.apply(undefined, extracted);
}
return extracted;
}
};
};