selectorator
Version:
Simplified generator of reselect selectors
198 lines (191 loc) • 7.32 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var identitate = require('identitate');
var fastEquals = require('fast-equals');
var reselect = require('reselect');
var unchanged = require('unchanged');
var INVALID_ARRAY_PATHS_MESSAGE = 'You have not provided any values for paths, so no values can be retrieved from state.';
var INVALID_PATHS_MESSAGE = [
'First parameter passed must be either an array or a plain object.',
'If you are creating a standard selector, pass an array of either',
'properties on the state to retrieve, or custom selector functions.',
'If creating a structured selector, pass a plain object with source',
'and destination properties, where source is an array of properties',
'or custom selector functions, and destination is an array of property',
'names to assign the values from source to.',
].join(' ');
var INVALID_OBJECT_PATH_MESSAGE = "\nWhen providing an object path, you must provide the following properties:\n * path: the path to retrieve, e.g. \"foo.bar\"\n * argIndx: the index of the argument to retrieve the path from\n".trim();
var INVALID_PATH_MESSAGE = "\nPath provided is of invalid type. It can be any one of the following values:\n * Dot-bracket notation, e.g. \"foo.bar\" or \"bar[0].baz\"\n * Number index, e.g. 0\n * Object {path, argIndex}, e.g. {path: \"foo.bar\", argIndex: 1}\n * Selector function\n".trim();
// external dependencies
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* @private
*
* @function isFunctionPath
*
* @description
* is the path a function
*
* @param path the path to test
* @param type the typeof value for the path
* @returns is the path a function
*/
var isFunctionPath = function (path, type) { return type === 'function'; };
/**
* @private
*
* @function isObjectPath
*
* @description
* is the path an object
*
* @param path the path to test
* @param type the typeof value for the path
* @returns is the path an object
*/
var isObjectPath = function (path, type) { return !!path && type === 'object'; };
/**
* @private
*
* @function isUnchangedPath
*
* @description
* is the path an unchanged path value
*
* @param path the path to test
* @param type the typeof value for the path
* @returns is the path an unchanged path value
*/
var isUnchangedPath = function (path, type) {
return type === 'string' || type === 'number' || Array.isArray(path);
};
/**
* @private
*
* @function createIdentitySelector
*
* @description
* based on the path passed, create the identity function for it or return the function itself
*
* @param path nested path to retrieve from the state object
* @returns identity function to retrieve value from state for given property
*/
var createIdentitySelector = function (path) {
var type = typeof path;
if (isFunctionPath(path, type)) {
return path;
}
if (isUnchangedPath(path, type)) {
return function (state) { return unchanged.get(path, state); };
}
if (isObjectPath(path, type)) {
if (hasOwnProperty.call(path, 'path') &&
hasOwnProperty.call(path, 'argIndex')) {
var selectorIdentity_1 = identitate.createIdentity(path.argIndex);
return function () {
return unchanged.get(path.path, selectorIdentity_1.apply(null, arguments));
};
}
throw new ReferenceError(INVALID_OBJECT_PATH_MESSAGE);
}
throw new TypeError(INVALID_PATH_MESSAGE);
};
/**
* @private
*
* @function getSelectorCreator
*
* @description
* get the creator function to use when generating the selector
*
* @param deepEqual should the memoizer be based on strict equality
* @param isEqual the custom equality method to use when comparing values
* @param memoizer custom selector memoizer
* @param memoizerParams custom parameters to pass to the memoizer function
* @returns function to create selector with
*/
var getSelectorCreator = function (_a) {
var _b = _a.deepEqual, deepEqual = _b === void 0 ? false : _b, _c = _a.isEqual, isEqual = _c === void 0 ? fastEquals.sameValueZeroEqual : _c, memoizer = _a.memoizer, _d = _a.memoizerParams, memoizerParams = _d === void 0 ? [] : _d;
var _e;
var memoizerFn = memoizer || reselect.defaultMemoize;
var equals = deepEqual ? fastEquals.deepEqual : isEqual;
return (_e = reselect.createSelectorCreator).call.apply(_e, [// fix strict mode error
null,
memoizerFn,
equals].concat(memoizerParams));
};
/**
* @private
*
* @function getStandardSelector
*
* @description
* get a standard selector based on the paths and getComputedValue provided
*
* @param paths paths to retrieve values from state from
* @param selectorCreator function to create selector with
* @param getComputedValue function to compute values with, receiving properties in state based
* on paths and returning computed values from them (defaults to pass-through identity function)
* @returns selector to return computed value from state
*/
var getStandardSelector = function (paths, selectorCreator, getComputedValue) {
return selectorCreator(paths.map(createIdentitySelector), getComputedValue);
};
/**
* @private
*
* @function getStructuredObject
*
* @description
* get the structured object based on the computed selector values
*
* @param properties properties to assign values from state to
* @returns object of property => selected value pairs
*/
var getStructuredObject = function (properties) { return function () {
var values = [];
for (var _i = 0; _i < arguments.length; _i++) {
values[_i] = arguments[_i];
}
return properties.reduce(function (structuredObject, property, index) {
structuredObject[property] = values[index];
return structuredObject;
}, {});
}; };
/**
* @private
*
* @function getStructuredSelector
*
* @description
* get an object of property => selected value pairs bsaed on paths
*
* @param paths property => path pairs, where path is state value to retrieve and assign to property
* @param selectorCreator function to create selector with
* @returns selector to return structured values from state
*/
var getStructuredSelector = function (paths, selectorCreator) {
var destinationKeys = Object.keys(paths);
var selectors = destinationKeys.map(function (key) { return createIdentitySelector(paths[key]); });
return selectorCreator(selectors, getStructuredObject(destinationKeys));
};
// external dependencies
function createSelector(// actual implementation - no changes
paths, getComputedValue, options) {
if (getComputedValue === void 0) { getComputedValue = identitate.identity; }
if (options === void 0) { options = {}; }
var selectorCreator = getSelectorCreator(options);
if (Array.isArray(paths)) {
if (!paths.length) {
throw new ReferenceError(INVALID_ARRAY_PATHS_MESSAGE);
}
return getStandardSelector(paths, selectorCreator, getComputedValue);
}
// added null check
if (paths && paths !== null && typeof paths === 'object') {
return getStructuredSelector(paths, selectorCreator);
}
throw new TypeError(INVALID_PATHS_MESSAGE);
}
exports.default = createSelector;
//# sourceMappingURL=selectorator.cjs.js.map