UNPKG

attadux

Version:

Implementation of the redux-modular-ducks, forked from the extensible-duck implementation and extended to include spected validators, state machines, helpers, web workers, effect handling, action multipliers, action enhancers, action throttling/debouncing

251 lines (177 loc) 11.1 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]; var 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); }; };