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

433 lines (309 loc) 22.7 kB
'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')))]);