UNPKG

@tixel/vuex-correlated-effects

Version:

Correlated effects is a side effect model for Vuex. Correlated effects use subscribers to provide new sources of actions such as network requests, web socket messages and time-based events. Effects can be correlated back to the component that initially di

229 lines (186 loc) 9.66 kB
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); } import _every from 'lodash-es/every.js'; import _some from 'lodash-es/some.js'; var VuexEffects = function VuexEffects(store) { var effectsList = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; return { install: function install(VueGlobal) { function matchComponentProps(path, action) { var _this = this; var effectMatchers = path[action.type].matchComponentProps; if (effectMatchers && effectMatchers.length > 0 && !_every(effectMatchers, function (propertyToMatch) { var _action$payload; if (!(action !== null && action !== void 0 && (_action$payload = action.payload) !== null && _action$payload !== void 0 && _action$payload.match)) { console.error('[vuex-effects] matchComponentProps is set and expects the action sends a payload with match'); return false; } if (_typeof(_this === null || _this === void 0 ? void 0 : _this[propertyToMatch]) === undefined) { console.error("[vuex-effects] matchComponentProps is set and expects the component to have props \"".concat(effectMatchers, "\". \"").concat(propertyToMatch, "\", doesn't exist, you need to set this in the component props")); return false; } return _some(action.payload.match, function (match) { if (!(match !== null && match !== void 0 && match[propertyToMatch])) { console.error("[vuex-effects] matchComponentProps is set and expects the action to send, \"".concat(propertyToMatch, "\" as a property in the match array, this action is sending \"").concat(Object.keys(match), "\"")); return false; } return match[propertyToMatch] === _this[propertyToMatch]; }); })) { // do not execute the action as it needs to match all properties return true; } } function callActionEffect(effectsPath, stage, action, state) { var prepend = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; var actionsPath = effectsPath.actions; // matchComponentProps will match the component properties from the component // and the action if (matchComponentProps.apply(this, [actionsPath, action])) { return; } // exit if effect's prepend not the same as subscriber if (_typeof(actionsPath[action.type]) === 'object') { if (!!actionsPath[action.type].prepend !== prepend) { return; } } else if (typeof actionsPath[action.type] === 'function' && prepend) { return; } if (stage === 'before') { // if effect is function if (typeof actionsPath[action.type] === 'function') { actionsPath[action.type].apply(this, [action, state]); return; } // if effect is object and it has handler function if (_typeof(actionsPath[action.type]) === 'object' && typeof actionsPath[action.type].handler === 'function') { actionsPath[action.type].handler.apply(this, [action, state]); return; } // if effect is object with before function if (_typeof(actionsPath[action.type]) === 'object' && typeof actionsPath[action.type][stage] === 'function') { actionsPath[action.type][stage].apply(this, [action, state]); } } else if (stage === 'after') { // if effect is object with after function if (_typeof(actionsPath[action.type]) === 'object' && typeof actionsPath[action.type][stage] === 'function') { actionsPath[action.type][stage].apply(this, [action, state]); } } } function callMutationEffect(effectsPath, mutation, state) { var prepend = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; var mutationsPath = effectsPath.mutations; // exit if effect's prepend not the same as subscriber if (_typeof(mutationsPath[mutation.type]) === 'object') { if (!!mutationsPath[mutation.type].prepend !== prepend) { return; } } else if (typeof mutationsPath[mutation.type] === 'function' && prepend) { return; } // if effect is function if (typeof mutationsPath[mutation.type] === 'function') { mutationsPath[mutation.type].apply(this, [mutation, state]); return; } // if effect is object and it has handler function if (_typeof(mutationsPath[mutation.type]) === 'object' && typeof mutationsPath[mutation.type].handler === 'function') { mutationsPath[mutation.type].handler.apply(this, [mutation, state]); } } // action wrapper fn function actionFn(effectsPath, effectActionsList) { var _this2 = this; var prepend = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; return { before: function before(action, state) { if (effectActionsList.includes(action.type)) { callActionEffect.apply(_this2, [effectsPath, 'before', action, state, prepend]); } }, after: function after(action, state) { if (effectActionsList.includes(action.type)) { callActionEffect.apply(_this2, [effectsPath, 'after', action, state, prepend]); } } }; } // mutation wrapper fn function mutationFn(effectsPath, effectActionsList) { var _this3 = this; var prepend = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; return function (mutation, state) { if (effectActionsList.includes(mutation.type)) { callMutationEffect.apply(_this3, [effectsPath, mutation, state, prepend]); } }; } // register effects for component VueGlobal.mixin({ beforeUnmount: function beforeUnmount() { if (Array.isArray(this.subscribers)) { this.subscribers.forEach(function (subscriber) { return subscriber(); }); } }, beforeCreate: function beforeCreate() { var _this4 = this; var effects = this.$options.effects; if (effects) { this.subscribers = []; var effectTypes = Object.keys(effects); effectTypes.forEach(function (effectType) { var effectActionsList = Object.keys(effects[effectType]); // subscribe to two identical events, with 'prepend' option and without it // so we have only two subscriber for all events // for actions and mutations switch (effectType) { case 'actions': { _this4.subscribers.push(store.subscribeAction(actionFn.apply(_this4, [_this4.$options.effects, effectActionsList])), store.subscribeAction(actionFn.apply(_this4, [_this4.$options.effects, effectActionsList, true]), { prepend: true })); break; } case 'mutations': { _this4.subscribers.push(store.subscribe(mutationFn.apply(_this4, [_this4.$options.effects, effectActionsList])), store.subscribe(mutationFn.apply(_this4, [_this4.$options.effects, effectActionsList, true]), { prepend: true })); break; } default: { throw new Error("[vuex-effects] Unrecognized effect section ".concat(effectType, " \n Maybe you mean 'actions' or 'mutations'?")); } } }); } } }); // register global effects effectsList.forEach(function (effectsItem) { var effects = effectsItem.effects; var effectTypes = Object.keys(effects); effectTypes.forEach(function (effectType) { var effectActionsList = Object.keys(effects[effectType]); // subscribe to two identical events, with 'prepend' option and without it // so we have only two subscriber for all events // for actions and mutations switch (effectType) { case 'actions': { store.subscribeAction(actionFn.apply(effectsItem, [effectsItem.effects, effectActionsList])); store.subscribeAction(actionFn.apply(effectsItem, [effectsItem.effects, effectActionsList, true]), { prepend: true }); break; } case 'mutations': { store.subscribe(mutationFn.apply(effectsItem, [effectsItem.effects, effectActionsList])); store.subscribe(mutationFn.apply(effectsItem, [effectsItem.effects, effectActionsList, true]), { prepend: true }); break; } default: { throw new Error("[vuex-effects] Unrecognized effect section ".concat(effectType)); } } }); }); } }; }; export default VuexEffects;