UNPKG

redux-loop

Version:

Sequence your effects naturally and purely by returning them from your reducers.

447 lines (357 loc) 17.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isCmd = isCmd; exports.executeCmd = executeCmd; exports["default"] = void 0; var _utils = require("./utils"); var _Object$freeze4; function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var isCmdSymbol = Symbol('isCmd'); var dispatchSymbol = Symbol('dispatch'); var getStateSymbol = Symbol('getState'); var cmdTypes = { RUN: 'RUN', ACTION: 'ACTION', SET_TIMEOUT: 'SET_TIMEOUT', SET_INTERVAL: 'SET_INTERVAL', LIST: 'LIST', MAP: 'MAP', NONE: 'NONE' }; function isCmd(object) { return object ? !!object[isCmdSymbol] : false; } function getMappedCmdArgs() { var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var dispatch = arguments.length > 1 ? arguments[1] : undefined; var getState = arguments.length > 2 ? arguments[2] : undefined; return args.map(function (arg) { if (arg === dispatchSymbol) { return dispatch; } else if (arg === getStateSymbol) { return getState; } else { return arg; } }); } function handleRunCmd(cmd, context) { var dispatch = context.dispatch, getState = context.getState, loopConfig = context.loopConfig; var onSuccess = cmd.successActionCreator || function () {}; var onFail; if (cmd.failActionCreator) { onFail = function onFail(error) { if (!loopConfig.DONT_LOG_ERRORS_ON_HANDLED_FAILURES) { console.error(error); } return cmd.failActionCreator(error); }; } else { onFail = console.error; } try { var result = cmd.func.apply( // Pass undefined so that 'this' will not point to our 'cmd' object. undefined, getMappedCmdArgs(cmd.args, dispatch, getState)); if ((0, _utils.isPromiseLike)(result) && !cmd.forceSync) { return result.then(onSuccess, onFail).then(function (action) { return action ? [action] : []; }); } var resultAction = onSuccess(result); return resultAction ? Promise.resolve([resultAction]) : null; } catch (err) { if (!cmd.failActionCreator) { console.error(err); throw err; //don't swallow errors if they are not handling them } var _resultAction = onFail(err); return _resultAction ? Promise.resolve([_resultAction]) : null; } } function handleParallelList(_ref, context) { var cmds = _ref.cmds, _ref$batch = _ref.batch, batch = _ref$batch === void 0 ? false : _ref$batch; var promises = cmds.map(function (nestedCmd) { var possiblePromise = executeCmdInternal(nestedCmd, context); if (!possiblePromise || batch) { return possiblePromise; } return possiblePromise.then(function (result) { return Promise.all(result.map(function (a) { return context.wrappedDispatch(a); })); }); }).filter(function (x) { return x; }); if (promises.length === 0) { return null; } return Promise.all(promises).then(_utils.flatten).then(function (actions) { return batch ? actions : []; }); } function handleSequenceList(_ref2, context) { var cmds = _ref2.cmds, _ref2$batch = _ref2.batch, batch = _ref2$batch === void 0 ? false : _ref2$batch; var firstCmd = cmds.length ? cmds[0] : null; if (!firstCmd) { return null; } var result = new Promise(function (resolve) { var firstPromise = executeCmdInternal(firstCmd, context); firstPromise = firstPromise || Promise.resolve([]); firstPromise.then(function (result) { var executePromise; if (!batch) { executePromise = Promise.all(result.map(function (a) { return context.wrappedDispatch(a); })); } else { executePromise = Promise.resolve(); } executePromise.then(function () { var remainingSequence = list(cmds.slice(1), { batch: batch, sequence: true }); var remainingPromise = executeCmdInternal(remainingSequence, context); if (remainingPromise) { remainingPromise.then(function (innerResult) { resolve(result.concat(innerResult)); }); } else { resolve(result); } }); }); }).then(_utils.flatten); return batch ? result : result.then(function () { return []; }); } function handleDelayCmd(cmd, context) { var executeNestedCmd = function executeNestedCmd() { var cmdPromise = executeCmdInternal(cmd.nestedCmd, context); if (cmdPromise) { cmdPromise.then(function (actions) { actions.forEach(function (action) { return context.wrappedDispatch(action); }); }); } }; var timerId; if (cmd.type === cmdTypes.SET_INTERVAL) { timerId = setInterval(executeNestedCmd, cmd.delayMs); } else { timerId = setTimeout(executeNestedCmd, cmd.delayMs); } if (cmd.scheduledActionCreator) { return Promise.resolve([cmd.scheduledActionCreator(timerId)]); } else { return null; } } function executeCmd(cmd, dispatch, getState) { var loopConfig = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; return executeCmdInternal(cmd, { dispatch: dispatch, wrappedDispatch: dispatch, getState: getState, loopConfig: loopConfig }); } function executeCmdInternal(cmd, context) { switch (cmd.type) { case cmdTypes.RUN: return handleRunCmd(cmd, context); case cmdTypes.ACTION: return Promise.resolve([cmd.actionToDispatch]); case cmdTypes.SET_TIMEOUT: case cmdTypes.SET_INTERVAL: return handleDelayCmd(cmd, context); case cmdTypes.LIST: return cmd.sequence ? handleSequenceList(cmd, context) : handleParallelList(cmd, context); case cmdTypes.MAP: { var possiblePromise = executeCmdInternal(cmd.nestedCmd, _objectSpread(_objectSpread({}, context), {}, { wrappedDispatch: function wrappedDispatch(action) { return context.wrappedDispatch(cmd.tagger.apply(cmd, _toConsumableArray(cmd.args).concat([action]))); } })); if (!possiblePromise) { return null; } return possiblePromise.then(function (actions) { return actions.map(function (action) { return cmd.tagger.apply(cmd, _toConsumableArray(cmd.args).concat([action])); }); }); } case cmdTypes.NONE: return null; default: throw new Error("Invalid Cmd type ".concat(cmd.type)); } } function simulateRun(_ref3) { var result = _ref3.result, success = _ref3.success; if (success && this.successActionCreator) { return this.successActionCreator(result); } else if (!success && this.failActionCreator) { return this.failActionCreator(result); } return null; } function run(func) { var _objectSpread2; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (process.env.NODE_ENV !== 'production') { if (!options.testInvariants) { (0, _utils.throwInvariant)(typeof func === 'function', 'Cmd.run: first argument to Cmd.run must be a function'); (0, _utils.throwInvariant)(_typeof(options) === 'object', 'Cmd.run: second argument to Cmd.run must be an options object'); (0, _utils.throwInvariant)(!options.successActionCreator || typeof options.successActionCreator === 'function', 'Cmd.run: successActionCreator option must be a function if specified'); (0, _utils.throwInvariant)(!options.failActionCreator || typeof options.failActionCreator === 'function', 'Cmd.run: failActionCreator option must be a function if specified'); (0, _utils.throwInvariant)(!options.args || options.args.constructor === Array, 'Cmd.run: args option must be an array if specified'); } } else if (options.testInvariants) { throw Error("Redux Loop: Detected usage of Cmd.run's testInvariants option in production code. This should only be used in tests."); } var testInvariants = options.testInvariants, rest = _objectWithoutProperties(options, ["testInvariants"]); return Object.freeze(_objectSpread((_objectSpread2 = {}, _defineProperty(_objectSpread2, isCmdSymbol, true), _defineProperty(_objectSpread2, "type", cmdTypes.RUN), _defineProperty(_objectSpread2, "func", func), _defineProperty(_objectSpread2, "simulate", simulateRun), _objectSpread2), rest)); } function simulateAction() { return this.actionToDispatch; } function action(actionToDispatch) { var _Object$freeze; if (process.env.NODE_ENV !== 'production') { (0, _utils.throwInvariant)(_typeof(actionToDispatch) === 'object' && actionToDispatch !== null && typeof actionToDispatch.type !== 'undefined', 'Cmd.action: first argument and only argument to Cmd.action must be an action'); } return Object.freeze((_Object$freeze = {}, _defineProperty(_Object$freeze, isCmdSymbol, true), _defineProperty(_Object$freeze, "type", cmdTypes.ACTION), _defineProperty(_Object$freeze, "actionToDispatch", actionToDispatch), _defineProperty(_Object$freeze, "simulate", simulateAction), _Object$freeze)); } function clearTimeoutCmd(timerId) { return run(clearTimeout, { args: [timerId] }); } function clearIntervalCmd(timerId) { return run(clearInterval, { args: [timerId] }); } function setTimeoutCmd(nestedCmd, delayMs) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return delay(nestedCmd, delayMs, options, cmdTypes.SET_TIMEOUT, 'Cmd.setTimeout'); } function setIntervalCmd(nestedCmd, delayMs) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return delay(nestedCmd, delayMs, options, cmdTypes.SET_INTERVAL, 'Cmd.setInterval'); } function delay(nestedCmd, delayMs, options, cmdType, funcName) { var _Object$freeze2; if (process.env.NODE_ENV !== 'production') { (0, _utils.throwInvariant)(isCmd(nestedCmd), "".concat(funcName, ": first argument must be another Cmd")); (0, _utils.throwInvariant)(typeof delayMs === 'number', "".concat(funcName, ": second argument must be a number")); (0, _utils.throwInvariant)(_typeof(options) === 'object', "".concat(funcName, ": third argument must be an options object")); (0, _utils.throwInvariant)(options.scheduledActionCreator === undefined || typeof options.scheduledActionCreator === 'function', "".concat(funcName, ": scheduledActionCreator option must be a function if specified")); } return Object.freeze((_Object$freeze2 = {}, _defineProperty(_Object$freeze2, isCmdSymbol, true), _defineProperty(_Object$freeze2, "type", cmdType), _defineProperty(_Object$freeze2, "nestedCmd", nestedCmd), _defineProperty(_Object$freeze2, "delayMs", delayMs), _defineProperty(_Object$freeze2, "scheduledActionCreator", options.scheduledActionCreator), _defineProperty(_Object$freeze2, "simulate", simulateDelay), _Object$freeze2)); } function simulateDelay(timerId, nestedSimulation) { var result = this.nestedCmd.simulate(nestedSimulation); var nestedActions = null; if (Array.isArray(result)) { nestedActions = result; } else if (result) { nestedActions = [result]; } if (this.scheduledActionCreator) { return [this.scheduledActionCreator(timerId)].concat(nestedActions); } else { return nestedActions; } } function simulateList(simulations) { return (0, _utils.flatten)(this.cmds.map(function (cmd, i) { return cmd.simulate(simulations[i]); }).filter(function (a) { return a; })); } function list(cmds) { var _objectSpread3; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (process.env.NODE_ENV !== 'production') { if (!options.testInvariants) { (0, _utils.throwInvariant)(Array.isArray(cmds) && cmds.every(isCmd), 'Cmd.list: first argument to Cmd.list must be an array of other Cmds'); (0, _utils.throwInvariant)(_typeof(options) === 'object', 'Cmd.list: second argument to Cmd.list must be an options object'); } } else if (options.testInvariants) { throw Error("Redux Loop: Detected usage of Cmd.list's testInvariants option in production code. This should only be used in tests."); } var testInvariants = options.testInvariants, rest = _objectWithoutProperties(options, ["testInvariants"]); return Object.freeze(_objectSpread((_objectSpread3 = {}, _defineProperty(_objectSpread3, isCmdSymbol, true), _defineProperty(_objectSpread3, "type", cmdTypes.LIST), _defineProperty(_objectSpread3, "cmds", cmds), _defineProperty(_objectSpread3, "simulate", simulateList), _objectSpread3), rest)); } function simulateMap(simulation) { var _this = this; var result = this.nestedCmd.simulate(simulation); if (Array.isArray(result)) { return result.map(function (action) { return _this.tagger.apply(_this, _toConsumableArray(_this.args).concat([action])); }); } else if (result) { return this.tagger.apply(this, _toConsumableArray(this.args).concat([result])); } else { return null; } } function map(nestedCmd, tagger) { var _Object$freeze3; if (process.env.NODE_ENV !== 'production') { (0, _utils.throwInvariant)(isCmd(nestedCmd), 'Cmd.map: first argument to Cmd.map must be another Cmd'); (0, _utils.throwInvariant)(typeof tagger === 'function', 'Cmd.map: second argument to Cmd.map must be a function that returns an action'); } for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; } return Object.freeze((_Object$freeze3 = {}, _defineProperty(_Object$freeze3, isCmdSymbol, true), _defineProperty(_Object$freeze3, "type", cmdTypes.MAP), _defineProperty(_Object$freeze3, "tagger", tagger), _defineProperty(_Object$freeze3, "nestedCmd", nestedCmd), _defineProperty(_Object$freeze3, "args", args), _defineProperty(_Object$freeze3, "simulate", simulateMap), _Object$freeze3)); } var none = Object.freeze((_Object$freeze4 = {}, _defineProperty(_Object$freeze4, isCmdSymbol, true), _defineProperty(_Object$freeze4, "type", cmdTypes.NONE), _defineProperty(_Object$freeze4, "simulate", function simulate() { return null; }), _Object$freeze4)); var _default = { run: run, action: action, setTimeout: setTimeoutCmd, setInterval: setIntervalCmd, clearTimeout: clearTimeoutCmd, clearInterval: clearIntervalCmd, list: list, map: map, none: none, dispatch: dispatchSymbol, getState: getStateSymbol }; exports["default"] = _default;