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
433 lines (309 loc) • 22.7 kB
JavaScript
'use strict';
exports.__esModule = true;
exports.createValidationMiddlewareHelpers = exports.createDuckReducer = exports.createDuckActionCreators = exports.createDuckActionMultipliers = exports.makeMultipliers = exports.createDuckActionEnhancers = exports.makeEnhancers = exports.createDuckSelectors = exports.createDuckInitialState = exports.createDuckMachines = exports.createDuckWorkers = exports.createDuckQueries = exports.createDuckDebouncers = exports.createDuckThrottlers = exports.createDuckEffects = exports.createDuckValidators = exports.createDuckMetadata = exports.createDuckLookup = exports.createRow = undefined;
var _applySpec = require('ramda/src/applySpec');
var _applySpec2 = _interopRequireDefault(_applySpec);
var _juxt = require('ramda/src/juxt');
var _juxt2 = _interopRequireDefault(_juxt);
var _all = require('ramda/src/all');
var _all2 = _interopRequireDefault(_all);
var _both = require('ramda/src/both');
var _both2 = _interopRequireDefault(_both);
var _adjust = require('ramda/src/adjust');
var _adjust2 = _interopRequireDefault(_adjust);
var _assocPath = require('ramda/src/assocPath');
var _assocPath2 = _interopRequireDefault(_assocPath);
var _applyTo = require('ramda/src/applyTo');
var _applyTo2 = _interopRequireDefault(_applyTo);
var _isEmpty = require('ramda/src/isEmpty');
var _isEmpty2 = _interopRequireDefault(_isEmpty);
var _propSatisfies = require('ramda/src/propSatisfies');
var _propSatisfies2 = _interopRequireDefault(_propSatisfies);
var _not = require('ramda/src/not');
var _not2 = _interopRequireDefault(_not);
var _anyPass = require('ramda/src/anyPass');
var _anyPass2 = _interopRequireDefault(_anyPass);
var _allPass = require('ramda/src/allPass');
var _allPass2 = _interopRequireDefault(_allPass);
var _call = require('ramda/src/call');
var _call2 = _interopRequireDefault(_call);
var _isNil = require('ramda/src/isNil');
var _isNil2 = _interopRequireDefault(_isNil);
var _pathSatisfies = require('ramda/src/pathSatisfies');
var _pathSatisfies2 = _interopRequireDefault(_pathSatisfies);
var _ifElse = require('ramda/src/ifElse');
var _ifElse2 = _interopRequireDefault(_ifElse);
var _map = require('ramda/src/map');
var _map2 = _interopRequireDefault(_map);
var _propEq = require('ramda/src/propEq');
var _propEq2 = _interopRequireDefault(_propEq);
var _keys = require('ramda/src/keys');
var _keys2 = _interopRequireDefault(_keys);
var _pick = require('ramda/src/pick');
var _pick2 = _interopRequireDefault(_pick);
var _evolve = require('ramda/src/evolve');
var _evolve2 = _interopRequireDefault(_evolve);
var _mergeDeepRight = require('ramda/src/mergeDeepRight');
var _mergeDeepRight2 = _interopRequireDefault(_mergeDeepRight);
var _converge = require('ramda/src/converge');
var _converge2 = _interopRequireDefault(_converge);
var _objOf = require('ramda/src/objOf');
var _objOf2 = _interopRequireDefault(_objOf);
var _ap = require('ramda/src/ap');
var _ap2 = _interopRequireDefault(_ap);
var _of = require('ramda/src/of');
var _of2 = _interopRequireDefault(_of);
var _mergeAll = require('ramda/src/mergeAll');
var _mergeAll2 = _interopRequireDefault(_mergeAll);
var _path = require('ramda/src/path');
var _path2 = _interopRequireDefault(_path);
var _split = require('ramda/src/split');
var _split2 = _interopRequireDefault(_split);
var _nth = require('ramda/src/nth');
var _nth2 = _interopRequireDefault(_nth);
var _head = require('ramda/src/head');
var _head2 = _interopRequireDefault(_head);
var _either = require('ramda/src/either');
var _either2 = _interopRequireDefault(_either);
var _is = require('ramda/src/is');
var _is2 = _interopRequireDefault(_is);
var _ = require('ramda/src/__');
var _2 = _interopRequireDefault(_);
var _prop = require('ramda/src/prop');
var _prop2 = _interopRequireDefault(_prop);
var _when = require('ramda/src/when');
var _when2 = _interopRequireDefault(_when);
var _always = require('ramda/src/always');
var _always2 = _interopRequireDefault(_always);
var _unless = require('ramda/src/unless');
var _unless2 = _interopRequireDefault(_unless);
var _curry = require('ramda/src/curry');
var _curry2 = _interopRequireDefault(_curry);
var _identity = require('ramda/src/identity');
var _identity2 = _interopRequireDefault(_identity);
var _unapply = require('ramda/src/unapply');
var _unapply2 = _interopRequireDefault(_unapply);
var _filter = require('ramda/src/filter');
var _filter2 = _interopRequireDefault(_filter);
var _assoc = require('ramda/src/assoc');
var _assoc2 = _interopRequireDefault(_assoc);
var _reduce = require('ramda/src/reduce');
var _reduce2 = _interopRequireDefault(_reduce);
var _compose = require('ramda/src/compose');
var _compose2 = _interopRequireDefault(_compose);
var _spected = require('spected');
var _spected2 = _interopRequireDefault(_spected);
var _shapey = require('shapey');
var _machines = require('../machines');
var _reducers = require('../reducers');
var _selectors = require('../selectors');
var _workers = require('../workers');
var _queries = require('../queries');
var _schema = require('./schema');
var _types = require('../types');
var _util = require('../util');
var _validate = require('./validate');
var _effects = require('../effects');
var _validators = require('../validators');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Merges multiple ducks into one flattened Object (row).
*
* @func
* @sig ({k: v}...) -> {k: v}
* @param {...Object} ducks One or more ducks to merge into one row
* @returns {Object} A single object composed of many ducks
*/
var createRow = exports.createRow = (0, _compose2.default)((0, _reduce2.default)(function (row, duck) {
return (0, _assoc2.default)(duck.store, duck, row);
}, {}), (0, _filter2.default)(_schema.isDux), (0, _unapply2.default)(_identity2.default));
/**
* A function which takes an Object of one or more ducks and finds the duck
* which matches a (potentially) namespaced Redux action
*
* @func
* @sig {k: v} -> {k: v} -> {k: v}
* @param {Object} row An Object containing one or more ducks
* @param {Object} action An dispatch Redux action (if belonging to this lib,
* should have a namespaced action type)
* @returns {Object} A single duck that corresponds to the dispatched action
* (defaults to an empty object if none found)
*/
var createDuckLookup = exports.createDuckLookup = (0, _curry2.default)(function (row, action) {
return (0, _compose2.default)((0, _unless2.default)(_util.isPlainObj, (0, _always2.default)({})), (0, _when2.default)(_util.isStringieThingie, (0, _prop2.default)(_2.default, (0, _filter2.default)(_schema.isDux, row))), (0, _when2.default)((0, _is2.default)(String), (0, _compose2.default)((0, _either2.default)((0, _nth2.default)(1), _head2.default), (0, _split2.default)('/'))), (0, _path2.default)(['type']))(action);
});
/**
* Validates and applies the configuration options for a new Duck, also
* performing final formatting for many of the duck's simpler props
* (consts, types, validationLevel, namespace, store, etc.).
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} options All the configuration options to be passed into the duck constructor
* @returns {Object} An object containing all the validated configuration options for the new Duck
*/
var createDuckMetadata = exports.createDuckMetadata = (0, _compose2.default)(_mergeAll2.default, (0, _ap2.default)([(0, _compose2.default)((0, _objOf2.default)('stateMachinesPropName'), (0, _always2.default)(['states'])), (0, _compose2.default)((0, _converge2.default)(_mergeDeepRight2.default, [(0, _compose2.default)((0, _evolve2.default)(_schema.metadataEvolvers), (0, _pick2.default)((0, _keys2.default)(_schema.metadataEvolvers)), _queries.copyRawQueriesToConsts), (0, _compose2.default)((0, _objOf2.default)('types'), (0, _converge2.default)(_types.createTypes, [_identity2.default, (0, _prop2.default)('types')]))]), (0, _prop2.default)('validatedOptions')), (0, _compose2.default)((0, _when2.default)(_util.isNotEmpty, (0, _objOf2.default)('invalidOptions')), _validators.pruneValidatedFields, (0, _prop2.default)('validationsResult')), (0, _compose2.default)((0, _objOf2.default)('options'), (0, _prop2.default)('validatedOptions'))]), _of2.default, _validate.createDuckSchemaValidator);
/**
* Creates the Duck's validators (if they are present inside of its 'options' prop).
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain validators (inside of its 'options')
* @returns {Object} A clone of the duck, but now with validators (if they were found inside of 'options').
*/
var createDuckValidators = exports.createDuckValidators = (0, _compose2.default)((0, _unless2.default)((0, _propEq2.default)('validationLevel', 'PRUNE'), (0, _evolve2.default)({
validators: (0, _map2.default)(function (validator) {
return (0, _compose2.default)(_validators.pruneValidatedFields, validator);
})
})), (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _ifElse2.default)((0, _pathSatisfies2.default)(_isNil2.default, ['options', 'validators']), (0, _always2.default)({}), (0, _compose2.default)((0, _objOf2.default)('validators'), (0, _map2.default)(_spected2.default), (0, _converge2.default)(_call2.default, [(0, _compose2.default)(_util.coerceToFn, (0, _path2.default)(['options', 'validators'])), _identity2.default])))]));
/**
* Creates the Duck's effect handlers (if they are present inside of its 'options' prop).
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain effect handlers (inside of its 'options')
* @returns {Object} A clone of the duck, but now with effect handlers (if they were found inside of 'options').
*/
var createDuckEffects = exports.createDuckEffects = (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _ifElse2.default)((0, _pathSatisfies2.default)(_isNil2.default, ['options', 'effects']), (0, _always2.default)([]), (0, _compose2.default)((0, _objOf2.default)('effects'), (0, _map2.default)(_effects.makeEffectHandler), (0, _filter2.default)(_util.isEffect), (0, _converge2.default)(_call2.default, [(0, _compose2.default)(_util.coerceToFn, (0, _path2.default)(['options', 'effects'])), _identity2.default])))]);
/**
* Creates the Duck's throttlers (if they are present inside of its 'options' prop).
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain throttlers (inside of its 'options')
* @returns {Object} A clone of the duck, but now with throttlers (if they were found inside of 'options').
*/
var createDuckThrottlers = exports.createDuckThrottlers = (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _ifElse2.default)((0, _pathSatisfies2.default)(_isNil2.default, ['options', 'throttling']), (0, _always2.default)([]), (0, _compose2.default)((0, _objOf2.default)('throttling'), (0, _map2.default)(function (_ref) {
var pattern = _ref[0],
milliseconds = _ref[1];
return [pattern, Number(milliseconds)];
}), (0, _filter2.default)((0, _allPass2.default)([(0, _is2.default)(Array), (0, _pathSatisfies2.default)((0, _anyPass2.default)([(0, _is2.default)(String), (0, _is2.default)(RegExp), (0, _is2.default)(Function)]), [0]), (0, _pathSatisfies2.default)((0, _compose2.default)(_not2.default, isNaN, Number), [1])])), (0, _converge2.default)(_call2.default, [(0, _compose2.default)(_util.coerceToFn, (0, _path2.default)(['options', 'throttling'])), _identity2.default])))]);
/**
* Creates the Duck's debouncers (if they are present inside of its 'options' prop).
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain debouncers (inside of its 'options')
* @returns {Object} A clone of the duck, but now with debouncers (if they were found inside of 'options').
*/
var createDuckDebouncers = exports.createDuckDebouncers = (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _ifElse2.default)((0, _pathSatisfies2.default)(_isNil2.default, ['options', 'debouncing']), (0, _always2.default)([]), (0, _compose2.default)((0, _objOf2.default)('debouncing'), (0, _map2.default)(function (_ref2) {
var pattern = _ref2[0],
milliseconds = _ref2[1];
return [pattern, Number(milliseconds)];
}), (0, _filter2.default)((0, _allPass2.default)([(0, _is2.default)(Array), (0, _pathSatisfies2.default)((0, _anyPass2.default)([(0, _is2.default)(String), (0, _is2.default)(RegExp), (0, _is2.default)(Function)]), [0]), (0, _pathSatisfies2.default)((0, _compose2.default)(_not2.default, isNaN, Number), [1])])), (0, _converge2.default)(_call2.default, [(0, _compose2.default)(_util.coerceToFn, (0, _path2.default)(['options', 'debouncing'])), _identity2.default])))]);
/**
* Creates the Duck's queries (if they are present inside of its 'options' prop).
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain queries (inside of its 'options')
* @returns {Object} A clone of the duck, but now with queries (if they were found inside of 'options').
*/
var createDuckQueries = exports.createDuckQueries = (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _ifElse2.default)((0, _pathSatisfies2.default)(_isNil2.default, ['options', 'queries']), (0, _always2.default)({}), (0, _compose2.default)((0, _objOf2.default)('queries'), _queries.makeQueries))]);
/**
* Creates the Duck's workers (if they are present inside of its 'options' prop).
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain workers (inside of its 'options')
* @returns {Object} A clone of the duck, but now with workers (if they were found inside of 'options').
*/
var createDuckWorkers = exports.createDuckWorkers = (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _ifElse2.default)((0, _pathSatisfies2.default)(_isNil2.default, ['options', 'workers']), (0, _always2.default)({}), (0, _compose2.default)((0, _objOf2.default)('workers'), _workers.makeWorkers))]);
/**
* Creates the Duck's state machines (if they are present inside of its 'options' prop).
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain state machines (inside of its 'options')
* @returns {Object} A clone of the duck, but now with state machines (if they were found inside of 'options').
*/
var createDuckMachines = exports.createDuckMachines = (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _ifElse2.default)((0, _pathSatisfies2.default)(_isNil2.default, ['options', 'machines']), (0, _always2.default)({}), (0, _compose2.default)((0, _objOf2.default)('machines'), (0, _converge2.default)(_machines.createMachines, [(0, _converge2.default)(_call2.default, [(0, _compose2.default)(_util.coerceToFn, (0, _path2.default)(['options', 'machines'])), _identity2.default]), _identity2.default])))]);
/**
* Creates the Duck's initial state for the section of the store that affects this duck.
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain initialState (inside of its 'options')
* @returns {Object} A clone of the duck, but now with initialState (if it was found inside of 'options').
*/
var createDuckInitialState = exports.createDuckInitialState = (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _compose2.default)((0, _objOf2.default)('initialState'), (0, _converge2.default)(_mergeDeepRight2.default, [(0, _converge2.default)(_call2.default, [(0, _compose2.default)(_util.coerceToFn, (0, _path2.default)(['options', 'initialState'])), _identity2.default]), (0, _ifElse2.default)((0, _propSatisfies2.default)(_isEmpty2.default, 'machines'), (0, _always2.default)({}), (0, _compose2.default)((0, _applyTo2.default)({}), (0, _converge2.default)(_assocPath2.default, [(0, _prop2.default)('stateMachinesPropName'), (0, _compose2.default)(_machines.getDefaultStateForMachines, (0, _prop2.default)('machines'))])))]))]);
/**
* Creates the Duck's selectors (if they are present inside of its 'options' prop).
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain selectors (inside of its 'options')
* @returns {Object} A clone of the duck, but now with selectors (if they were found inside of 'options').
*/
var createDuckSelectors = exports.createDuckSelectors = (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _ifElse2.default)((0, _pathSatisfies2.default)(_isNil2.default, ['options', 'selectors']), (0, _always2.default)({}), (0, _compose2.default)((0, _objOf2.default)('selectors'), _selectors.deriveSelectors, (0, _converge2.default)(_call2.default, [(0, _compose2.default)(_util.coerceToFn, (0, _path2.default)(['options', 'selectors'])), _identity2.default])))]);
/**
* Creates an Object of enhancement functions out of an Object of spec objects
* (or arrays of spec objects).
*
* @func
* @sig {k: [({k: v} -> {k: v}), ({k: v} -> {k: v}), ...]|({k: v} -> {k: v}) } -> {k: ({k: v} -> {k: v}) }
* @param {Object[]|Object} enhancements A single enhancement spec or an Array of enhancement specs
* @returns {Object} An object of enhancer functions, each ready to receive an
* input object and apply their single or chain of enhancer functions to it.
*/
var makeEnhancers = exports.makeEnhancers = (0, _ifElse2.default)((0, _is2.default)(Array), _shapey.shapeline, _shapey.makeShaper);
/**
* Creates the Duck's action enhancers (if they are present inside of its 'options' prop).
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain action enhancers (inside of its 'options')
* @returns {Object} A clone of the duck, but now with action enhancers (if they were found inside of 'options').
*/
var createDuckActionEnhancers = exports.createDuckActionEnhancers = (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _ifElse2.default)((0, _pathSatisfies2.default)(_isNil2.default, ['options', 'enhancers']), (0, _always2.default)({}), (0, _compose2.default)((0, _objOf2.default)('enhancers'), (0, _ifElse2.default)((0, _is2.default)(Array), (0, _map2.default)((0, _adjust2.default)(makeEnhancers, 1)), (0, _map2.default)(makeEnhancers)), (0, _ifElse2.default)(_util.isPlainObj, (0, _filter2.default)(_util.isSpecOrFunction), (0, _filter2.default)((0, _both2.default)((0, _is2.default)(Array), (0, _all2.default)(_util.isEnhancer)))), (0, _converge2.default)(_call2.default, [(0, _compose2.default)(_util.coerceToFn, (0, _path2.default)(['options', 'enhancers'])), _identity2.default])))]);
/**
* Creates an Object of multiplier functions out of an Object of spec objects
* (or arrays of spec objects).
*
* @func
* @sig {k: [({k: v} -> {k: v}), ({k: v} -> {k: v}), ...]|({k: v} -> {k: v}) } -> {k: ({k: v} -> {k: v}) }
* @param {Object[]|Object} multipliers A single multiplier spec or an Array of multipler specs
* @returns {Object} An object of multipler functions, each ready to receive an
* input object and apply their single or many multipler functions to it.
*/
var makeMultipliers = exports.makeMultipliers = (0, _compose2.default)(_juxt2.default, (0, _map2.default)(_shapey.makeShaper), (0, _unless2.default)((0, _is2.default)(Array), _of2.default));
/**
* Creates the Duck's action multipliers (if they are present inside of its 'options' prop).
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain action multipliers (inside of its 'options')
* @returns {Object} A clone of the duck, but now with action multipliers (if they were found inside of 'options').
*/
var createDuckActionMultipliers = exports.createDuckActionMultipliers = (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _ifElse2.default)((0, _pathSatisfies2.default)(_isNil2.default, ['options', 'multipliers']), (0, _always2.default)({}), (0, _compose2.default)((0, _objOf2.default)('multipliers'), (0, _map2.default)(makeMultipliers), (0, _converge2.default)(_call2.default, [(0, _compose2.default)(_util.coerceToFn, (0, _path2.default)(['options', 'multipliers'])), _identity2.default])))]);
/**
* Creates the Duck's action creators (if they are present inside of its 'options' prop).
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain action creators (inside of its 'options')
* @returns {Object} A clone of the duck, but now with action creators (if they were found inside of 'options').
*/
var createDuckActionCreators = exports.createDuckActionCreators = (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _ifElse2.default)((0, _pathSatisfies2.default)(_isNil2.default, ['options', 'creators']), (0, _always2.default)({}), (0, _compose2.default)((0, _objOf2.default)('creators'), (0, _converge2.default)(_call2.default, [(0, _compose2.default)(_util.coerceToFn, (0, _path2.default)(['options', 'creators'])), _identity2.default])))]);
/**
* Creates the Duck's reducer (if it was present inside of its 'options' prop).
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain a reducer (inside of its 'options')
* @returns {Object} A clone of the duck, but now with a reducer (if it was found inside of 'options').
*/
var createDuckReducer = exports.createDuckReducer = (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _ifElse2.default)((0, _either2.default)((0, _pathSatisfies2.default)(_isNil2.default, ['options', 'reducer']), (0, _propSatisfies2.default)(_isEmpty2.default, 'machines')), (0, _compose2.default)((0, _objOf2.default)('reducer'), _reducers.createReducer), (0, _compose2.default)((0, _objOf2.default)('reducer'), _reducers.createTransitionsPostReducer))]);
/**
* Creates validation helpers for a given Duck, to be used in the middleware chain.
*
* @func
* @sig {k: v} -> {k: v}
* @param {Object} duck A duck which (may) contain validators (inside of its 'options')
* @returns {Object} A clone of the duck, but now with validator helpers (if validators were found inside of 'options').
*/
var createValidationMiddlewareHelpers = exports.createValidationMiddlewareHelpers = (0, _converge2.default)(_mergeDeepRight2.default, [_identity2.default, (0, _ifElse2.default)((0, _propSatisfies2.default)(_isNil2.default, 'validators'), (0, _always2.default)({}), (0, _compose2.default)((0, _applySpec2.default)({
isPayloadValid: _validators.createPayloadValidator,
getValidationErrors: _validators.createPayloadValidationsLogger,
pruneInvalidFields: _validators.createPayloadPruner
}), (0, _prop2.default)('validators')))]);