@shopgate/pwa-common
Version:
Common library for the Shopgate Connect PWA.
58 lines • 4.83 kB
JavaScript
import noop from'lodash/noop';import{isObject}from"../validation";/**
* @typedef {Object} MutableFunction
* @property {Function} replace Replaces the original functionality with a custom function.
* @property {Function} restore Restores the original function.
* @property {Function} reset Restores the original function and removes all pre-processes steps.
* @property {Function} useBefore Adds a pre-processing step func.
* @property {Function} original Original function
*/var BEFORE_ACTION_NEXT='next';var BEFORE_ACTION_SKIP_REST='skipRest';var BEFORE_ACTION_STOP='stop';/**
* Defines parameters to be used by the next step or mutable function.
* @param {*} args Transforms an argument list to be consumed by the next step or
* @returns {Object}
*/export function next(){for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}return{action:BEFORE_ACTION_NEXT,args:args};}/**
* Causes the stack to skip forward to processing the mutable using the given arguments.
* @param {*} [args] A number of arguments to be passed to the mutable. This is optional.
* @returns {Object}
*/export function skipRest(){for(var _len2=arguments.length,args=new Array(_len2),_key2=0;_key2<_len2;_key2++){args[_key2]=arguments[_key2];}return{action:BEFORE_ACTION_SKIP_REST,args:args};}/**
* Causes the stack to stop processing any further actions. On stop only one return value possible.
* @param {*} [arg] Optional final result value.
* @returns {Object}
*/export function stop(arg){return{action:BEFORE_ACTION_STOP,args:arg};}/**
* Public api export
* @type {{next: Function, stop: Function, skipRest: Function}}
*/export var mutableActions={next:next,skipRest:skipRest,stop:stop};/**
* Takes a function and makes it mutable.
* @template {Function} T
* @param {T} func Original function to convert to a mutable
* @returns {T}
*/export var mutable=function mutable(func){var original=func;var current=func;var steps=[];/**
* Takes the pre-processing steps and calls all step functions, as well as the mutable function
* afterwards. Each step can transform the arguments, that are passed in to the next step in the
* stack and ultimately to the mutable function.
* @param {*} args Arguments passed down to the mutable and its pre-processor actions.
* @returns {Function} A function to be consumed by redux
*/function mutableFunc(){for(var _len3=arguments.length,args=new Array(_len3),_key3=0;_key3<_len3;_key3++){args[_key3]=arguments[_key3];}var mutatedArgs=args;var runAction=true;// Execute pre-processing steps, if any available.
if(steps.length>0){mutatedArgs=steps.reduce(function(acc,step,i,arr){// Call next step func in the pipeline with mutated args
var res=step.apply(void 0,acc);// Keep params unchanged if the step did not perform any change action at all
if(!isObject(res)){return acc;}// Unpack arguments from the "useBefore" pre-processor with "next" action.
if(res.action===BEFORE_ACTION_NEXT){if(res.args&&res.args.length>0){res=res.args;}else{res=args;}}// Unpack arguments from the "useBefore" pre-processor with "skipRest" action.
if(res.action===BEFORE_ACTION_SKIP_REST){arr.splice(-(arr.length-i));if(res.args&&res.args.length>0){res=res.args;}else{res=args;}}// Check if the step requested to stop any further processing including the action itself
if(res.action===BEFORE_ACTION_STOP){// Cut off all following step functions including the mutable func
arr.splice(-(arr.length-i));runAction=false;res=res.args;}// Replace arguments for the next step to get.
return res;},args);}if(!runAction){// the return value here gets passed to the dispatch() so it must be a function or action obj
return noop;}// Call the actual mutable
return current.apply(void 0,mutatedArgs);}/**
* Replaces the original functionality with a custom function.
* @param {Function} customFunc The function to execute instead of the original one.
*/mutableFunc.replace=function(customFunc){current=customFunc;// Allow access to the current mutation.
mutableFunc.current=current;};/**
* Restores the original func, while keeping additional functions to be called beforehand.
*/mutableFunc.restore=function(){current=original;};/**
* Resets the whole mutable to its initial state, restoring the original functionality and
* dropping all injected functions.
*/mutableFunc.reset=function(){current=original;steps.length=0;};/**
* Adds a pre-processing step func to a list to be called before the actual functionality
* executes. Each step can modify the arguments, passed down to the next step or the mutable.
* @param {Function} stepFunc The function to be executed before
*/mutableFunc.useBefore=function(stepFunc){steps.push(stepFunc);};// Allow access to the original function.
mutableFunc.original=original;return mutableFunc;};