UNPKG

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

251 lines (177 loc) 10.9 kB
'use strict'; exports.__esModule = true; exports.createDuckExtender = exports.createExtendedOptions = exports.extendOptionsForDuck = exports.extendReducer = exports.createOptionsExtender = undefined; var _uniq = require('ramda/src/uniq'); var _uniq2 = _interopRequireDefault(_uniq); var _path = require('ramda/src/path'); var _path2 = _interopRequireDefault(_path); var _ = require('ramda/src/__'); var _2 = _interopRequireDefault(_); var _when = require('ramda/src/when'); var _when2 = _interopRequireDefault(_when); var _mapAccum = require('ramda/src/mapAccum'); var _mapAccum2 = _interopRequireDefault(_mapAccum); var _mergeAll = require('ramda/src/mergeAll'); var _mergeAll2 = _interopRequireDefault(_mergeAll); var _applyTo = require('ramda/src/applyTo'); var _applyTo2 = _interopRequireDefault(_applyTo); var _concat = require('ramda/src/concat'); var _concat2 = _interopRequireDefault(_concat); var _reduce = require('ramda/src/reduce'); var _reduce2 = _interopRequireDefault(_reduce); var _objOf = require('ramda/src/objOf'); var _objOf2 = _interopRequireDefault(_objOf); var _mergeDeepRight = require('ramda/src/mergeDeepRight'); var _mergeDeepRight2 = _interopRequireDefault(_mergeDeepRight); var _of = require('ramda/src/of'); var _of2 = _interopRequireDefault(_of); var _find = require('ramda/src/find'); var _find2 = _interopRequireDefault(_find); var _last = require('ramda/src/last'); var _last2 = _interopRequireDefault(_last); var _has = require('ramda/src/has'); var _has2 = _interopRequireDefault(_has); var _all = require('ramda/src/all'); var _all2 = _interopRequireDefault(_all); var _ifElse = require('ramda/src/ifElse'); var _ifElse2 = _interopRequireDefault(_ifElse); var _T = require('ramda/src/T'); var _T2 = _interopRequireDefault(_T); var _isNil = require('ramda/src/isNil'); var _isNil2 = _interopRequireDefault(_isNil); var _identity = require('ramda/src/identity'); var _identity2 = _interopRequireDefault(_identity); var _mergeDeepWith = require('ramda/src/mergeDeepWith'); var _mergeDeepWith2 = _interopRequireDefault(_mergeDeepWith); var _converge = require('ramda/src/converge'); var _converge2 = _interopRequireDefault(_converge); var _always = require('ramda/src/always'); var _always2 = _interopRequireDefault(_always); var _pair = require('ramda/src/pair'); var _pair2 = _interopRequireDefault(_pair); var _prop = require('ramda/src/prop'); var _prop2 = _interopRequireDefault(_prop); var _map = require('ramda/src/map'); var _map2 = _interopRequireDefault(_map); var _is = require('ramda/src/is'); var _is2 = _interopRequireDefault(_is); var _any = require('ramda/src/any'); var _any2 = _interopRequireDefault(_any); var _compose = require('ramda/src/compose'); var _compose2 = _interopRequireDefault(_compose); var _cond = require('ramda/src/cond'); var _cond2 = _interopRequireDefault(_cond); var _curry = require('ramda/src/curry'); var _curry2 = _interopRequireDefault(_curry); var _reducers = require('../reducers'); var _schema = require('./schema'); var _types = require('../types'); var _util = require('../util'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * A function that creates an "extender" function which will merges * a portion of two duck together at a specified prop * * @func * @sig {k: v} -> {k: v} -> String -> * * @param {Object} childDuckOptions A set of options from which a duck can be built * @param {Object} parentDuck A duck that has already been built and whose original constructor options will be re-invoked * @param {String} key A key name from which to match child options to parent (same prop for both) * @returns {Function} A function that takes the name of a prop on a duck, and * will merge the parent and child together for that prop */ var createOptionsExtender = exports.createOptionsExtender = (0, _curry2.default)(function (childDuckOptions, _ref, key) { var parentOptions = _ref.options; return (0, _cond2.default)([ /* If the key at the child or parent is a function */ [(0, _compose2.default)((0, _any2.default)((0, _is2.default)(Function)), (0, _map2.default)((0, _prop2.default)(key)), (0, _pair2.default)(parentOptions)), /** * then they both need to be invoked * (coerced to fn, if not already) * and then their results are merged */ (0, _always2.default)((0, _converge2.default)((0, _mergeDeepWith2.default)(_util.simpleMergeStrategy), [(0, _util.coerceToFn)(parentOptions[key]), (0, _converge2.default)((0, _util.coerceToFn)(childDuckOptions[key]), [_identity2.default, (0, _util.coerceToFn)(parentOptions[key])])]))], /* If the child doesn't have anything at that key, just return from the parent */ [(0, _compose2.default)(_isNil2.default, (0, _prop2.default)(key)), (0, _always2.default)(parentOptions[key])], /* Otherwise, simply merge the parent and child together at that key */ [_T2.default, (0, _compose2.default)((0, _mergeDeepWith2.default)(_util.simpleMergeStrategy, parentOptions[key]), (0, _prop2.default)(key))]])(childDuckOptions); }); /** * Merges the reducer from an existing duck with a reducer inside of a set of configuration options (for a new duck). * If a reducer doesn't exist in both sources, no merging is needed, otherwise the merged reducer * will always invoke the parent's reducer and feed that result into the child's reducer as its 'state' argument. * This way a chain of reducers will always be executed. * * @func * @sig {k: v} -> {k: v} -> {k: v} * @param {Object} duck An existing duck, which contains its original * configuration options at its 'options' prop. * @param {Object} options A set of configuration options for a new duck * @returns {Object} A reducer function which is either a chain of reducers (parent first, then child) * or one of the reducers (if a reducer wasn't present in both sets of config options) */ var extendReducer = exports.extendReducer = function extendReducer(_ref2) { var parentOptions = _ref2.options; return (0, _compose2.default)((0, _ifElse2.default)((0, _all2.default)((0, _has2.default)('reducer')), (0, _compose2.default)((0, _reducers.makeExtendedReducer)(parentOptions), _last2.default), (0, _compose2.default)((0, _find2.default)((0, _has2.default)('reducer')), (0, _pair2.default)(parentOptions))), (0, _pair2.default)(parentOptions)); }; /** * Merges a set of configuration options (for a new duck) with those of an * existing duck (along with defaults for any unsupplied, but required values). * * @func * @sig {k: v} -> {k: v} -> {k: v} * @param {Object} duck An existing duck, which contains its original * configuration options at its 'options' prop. * @param {Object} options A set of configuration options for a new duck * @returns {Object} A set of configuration options where schema defaults are * merged with the existing duck's configuration options and the new * (to-be-built) duck's configuration options */ var extendOptionsForDuck = exports.extendOptionsForDuck = function extendOptionsForDuck(duck) { return (0, _compose2.default)((0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _compose2.default)((0, _objOf2.default)('reducer'), extendReducer(duck))]), (0, _reduce2.default)(_mergeDeepRight2.default, {}), (0, _concat2.default)([_schema.duxDefaults, duck.options]), _of2.default, (0, _applyTo2.default)(duck), _util.coerceToFn); }; /** * Applies a set of evolvers, which are just transformations that are run against a given prop inside of an object. * In this case the config options for a new duck are transformed and then * those are merged with the same prop(s) inside of the config 'options' of the existing duck. * * @func * @sig [[k: (a -> b)] -> {k: v} -> {k: v} -> {k: v} * @param {Array} evolvers An array of arrays (which are key/value pairs whose * key is a prop name on an options object and whose value is a function to * execute against the corresponding value on the options object) * @param {Object} duck An existing duck, which contains its original * configuration options at its 'options' prop. * @param {Object} options A set of configuration options for a new duck * @returns {Object} The options from the original duck extended with the * configuration options for a new (to-be-built) duck, according to the * transformations defined in the evolvers. */ var createExtendedOptions = exports.createExtendedOptions = (0, _curry2.default)(function (evolvers, duck, options) { return (0, _compose2.default)((0, _mergeDeepRight2.default)(options), _mergeAll2.default, _last2.default, (0, _mapAccum2.default)(function (mergedDuck, _ref3) { var key = _ref3[0], builder = _ref3[1]; var option = (0, _compose2.default)((0, _objOf2.default)(key), (0, _when2.default)((0, _is2.default)(Function), (0, _applyTo2.default)(key)), builder)(mergedDuck); return [(0, _mergeDeepRight2.default)(mergedDuck, option), option]; }, duck))(evolvers); }); /** * Takes an already built duck and the options for building a new one and * extends the new options onto the options and simple props of the already built duck. * The combined object can be passed as options when creating a new duck. * * @func * @sig {k: v} -> {k: v} -> {k: v} * @param {Object} duck An existing duck from which a new duck will be based * @param {Object} options A set of options to be merged with those of an * existing duck (to be used together whenn creating a new duck) * @returns {Object} a merged set of options to be fed into a new duck */ var createDuckExtender = exports.createDuckExtender = function createDuckExtender(duck) { var extendOptions = extendOptionsForDuck(duck); return function (options) { var childOptions = extendOptions(options); var optionBuilders = [['consts', (0, _compose2.default)((0, _mergeDeepWith2.default)(_types.concatOrReplace, _2.default, childOptions.consts), (0, _path2.default)(['options', 'consts']))], ['types', (0, _compose2.default)(_uniq2.default, (0, _concat2.default)(childOptions.types), (0, _path2.default)(['options', 'types']))], ['initialState', createOptionsExtender(childOptions)], ['machines', createOptionsExtender(childOptions)], ['creators', createOptionsExtender(childOptions)], ['selectors', createOptionsExtender(childOptions)], ['queries', createOptionsExtender(childOptions)], ['enhancers', createOptionsExtender(childOptions)], ['multipliers', createOptionsExtender(childOptions)], ['throttling', createOptionsExtender(childOptions)], ['debouncing', createOptionsExtender(childOptions)], ['effects', createOptionsExtender(childOptions)], ['validators', createOptionsExtender(childOptions)], ['workers', createOptionsExtender(childOptions)]]; return createExtendedOptions(optionBuilders, duck, childOptions); }; };