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

220 lines (168 loc) 10.2 kB
'use strict'; exports.__esModule = true; exports.createEffectHandler = exports.makeResponseHandler = exports.makePredicate = exports.defaultErrorHandler = exports.defaultSuccessHandler = undefined; var _ifElse = require('ramda/src/ifElse'); var _ifElse2 = _interopRequireDefault(_ifElse); var _pipe = require('ramda/src/pipe'); var _pipe2 = _interopRequireDefault(_pipe); var _tryCatch = require('ramda/src/tryCatch'); var _tryCatch2 = _interopRequireDefault(_tryCatch); var _identity = require('ramda/src/identity'); var _identity2 = _interopRequireDefault(_identity); var _F = require('ramda/src/F'); var _F2 = _interopRequireDefault(_F); var _always = require('ramda/src/always'); var _always2 = _interopRequireDefault(_always); var _T = require('ramda/src/T'); var _T2 = _interopRequireDefault(_T); var _test = require('ramda/src/test'); var _test2 = _interopRequireDefault(_test); var _pathEq = require('ramda/src/pathEq'); var _pathEq2 = _interopRequireDefault(_pathEq); var _cond = require('ramda/src/cond'); var _cond2 = _interopRequireDefault(_cond); var _pick = require('ramda/src/pick'); var _pick2 = _interopRequireDefault(_pick); var _evolve = require('ramda/src/evolve'); var _evolve2 = _interopRequireDefault(_evolve); var _is = require('ramda/src/is'); var _is2 = _interopRequireDefault(_is); var _pathSatisfies = require('ramda/src/pathSatisfies'); var _pathSatisfies2 = _interopRequireDefault(_pathSatisfies); var _when = require('ramda/src/when'); var _when2 = _interopRequireDefault(_when); var _objOf = require('ramda/src/objOf'); var _objOf2 = _interopRequireDefault(_objOf); var _unless = require('ramda/src/unless'); var _unless2 = _interopRequireDefault(_unless); var _ = require('ramda/src/__'); var _2 = _interopRequireDefault(_); var _merge = require('ramda/src/merge'); var _merge2 = _interopRequireDefault(_merge); var _compose = require('ramda/src/compose'); var _compose2 = _interopRequireDefault(_compose); var _curry = require('ramda/src/curry'); var _curry2 = _interopRequireDefault(_curry); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _shapey = require('shapey'); var _is3 = require('../util/is'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } /** * A slightly opinionated way to handle successful effects and creating a new * Action to be dispatched. This default success handler assumes you're alright * with appending _SUCCESS to the original action type, and merging the return object * (from your effect function) into the new Action. However, if your effect does NOT * return an object, that return value will be merged onto the new Action onto a prop * called "payload". The other assumption it makes is that if you have suffixed your * original Action with _REQUEST or _EFFECT, that will be removed. A (somewhat) standard * pattern in the Redux community is to suffix _SUCCESS for effects that succeed * and either _ERROR or _FAIL for those that failed. You can always override * with your own success handler by providing it when you create an effect in * the ducks. * * @func * @sig String|{k: v} -> {k: v} -> {k: v} * @param {String|Object} result The result returned from your effect function * @param {Object} action The original Redux action that triggered the effect * @returns {Object} A new Action object that contains the "payload" that was * caught when the effect was created (unless your effect function returned an * object, in which case it will be merged onto this) */ var defaultSuccessHandler = exports.defaultSuccessHandler = (0, _curry2['default'])(function (result, action) { return (0, _compose2['default'])((0, _merge2['default'])(_2['default'], _extends({}, (0, _unless2['default'])(_is3.isPlainObj, (0, _objOf2['default'])('payload'))(result))), (0, _when2['default'])((0, _pathSatisfies2['default'])((0, _is2['default'])(String), ['type']), (0, _compose2['default'])((0, _evolve2['default'])({ type: function type(t) { return t.replace(/_REQUEST$/i, '').replace(/_EFFECT$/i, '') + '_SUCCESS'; } }), (0, _pick2['default'])(['type']))))(action); }); /** * A slightly opinionated way to handle catching an exception and creating a new * Action to be dispatched. This default error handler assumes you're alright * with appending _ERROR to the original action type, and pruning out all of the * other fields from the original action and setting only an "error" prop on the * new Action. The other assumption it makes is that if you have suffixed your * original Action with _REQUEST or _EFFECT, that will be removed. A (somewhat) standard * pattern in the Redux community is to suffix _SUCCESS for effects that succeed * and either _ERROR or _FAIL for those that failed. You can always override * with your own error handler by providing it when you create an effect in * the ducks. * * @func * @sig String|{k: v} -> {k: v} -> {k: v} * @param {String|Object} error An error that was caught when the effect was * triggered * @param {Object} action The original Redux action that triggered the effect * @returns {Object} A new Action object that contains the "error" that was * caught when the effect was created */ var defaultErrorHandler = exports.defaultErrorHandler = (0, _curry2['default'])(function (error, action) { return (0, _compose2['default'])((0, _merge2['default'])({ error: (0, _unless2['default'])(_is3.isPlainObj, String)(error) }), (0, _when2['default'])((0, _pathSatisfies2['default'])((0, _is2['default'])(String), ['type']), (0, _compose2['default'])((0, _evolve2['default'])({ type: function type(t) { return t.replace(/_REQUEST$/i, '').replace(/_EFFECT$/i, '') + '_ERROR'; } }), (0, _pick2['default'])(['type']))))(action); }); /** * Makes a predicate function out of either a String, RegExp, or a Function, * which can then be applied to an Object that contains a "type" property. * This is meant to be used to evaluate if a Redux action matches the predicate. * If neither a String, RegExp, nor Function is supplied here, then the result * will be to give back a function that always returns false. * * @func * @sig String|RegExp|({k: v} -> Boolean) -> ({k: v} -> Boolean) * @param {String|RegExp|Function} pattern A String to be exactly matched to an * Object's "type" property, OR a Regular expression to be matched against it, * OR a function to be used to match against any custom criteria on that Object * @returns {Function} A predicate function to be applied later to an Object * (ideally, one containing a "type" property) */ var makePredicate = exports.makePredicate = (0, _cond2['default'])([[(0, _is2['default'])(String), (0, _pathEq2['default'])(['type'])], [(0, _is2['default'])(RegExp), (0, _compose2['default'])((0, _pathSatisfies2['default'])(_2['default'], ['type']), _test2['default'])], [(0, _is2['default'])(Function), function (fn) { return (0, _compose2['default'])(Boolean, fn); }], [_T2['default'], (0, _always2['default'])(_F2['default'])]]); /** * Creates a function that handles the effect result (either success or failure) * * @func * @sig (a -> b) -> (a -> b) -> (a -> b) * @param {Function} defaultHandler The fall through handler function to be used * in case the handler passed into this function is null/undefined * @param {String|Object|Function} handler The handler function or the * String/Object to be turned into a handler function (if String/Object, it will * be turned into a Shapey spec-mapping function) * @returns {Function} A success OR error handler function to be applied after * the effect is finished */ var makeResponseHandler = exports.makeResponseHandler = (0, _curry2['default'])(function (defaultHandler, handler) { return (0, _cond2['default'])([[(0, _is2['default'])(String), (0, _compose2['default'])(_shapey.makeShaper, (0, _objOf2['default'])('type'))], [_is3.isPlainObj, _shapey.makeShaper], [(0, _is2['default'])(Function), _identity2['default']], [_T2['default'], (0, _always2['default'])(defaultHandler)]])(handler); }); /** * Creates a robust effect handler from a predicate, an effect creating * function, as well as a success and error handler. This curried function can * then be applied safely to any Action that matches the predicate (if the * Action does NOT match, this is simply an identity function - which returns * the Action as-is). * * @func * @param {String|RegExp|Function} pattern A String to be exactly matched to an * Object's "type" property, OR a Regular expression to be matched against it, * OR a function to be used to match against any custom criteria on that Object * @param {Function} effectHandler A custom function that creates some kind of * normal (but "impure") effect which may succeed or it may fail * @param {Function} successHandler A function that receives the input of the * effect creating function and creates a new Action containing its result * @param {Function} errorHandler A function that receives the caught exception * from the effect creating function and creates a new Action from it * @returns {Object} Either the original action (if it didn't match the * predicate) or a new Action that represents the succes of the effect or * alternatively it's failure */ var createEffectHandler = exports.createEffectHandler = (0, _curry2['default'])(function (pattern, effectHandler, successHandler, errorHandler, action) { return (0, _when2['default'])(makePredicate(pattern), (0, _tryCatch2['default'])((0, _pipe2['default'])(effectHandler, (0, _ifElse2['default'])(_is3.isPromise, function (promise) { return promise.then(function (res) { return successHandler(res, action); })['catch'](function (err) { return errorHandler(err, action); }); }, function (res) { return successHandler(res, action); })), function (ex) { return errorHandler(ex, action); }))(action); });