Skip to content

Commit

Permalink
Action chaining will pass calling values if function arguments are re…
Browse files Browse the repository at this point in the history
…quired
  • Loading branch information
codemeasandwich committed Jun 17, 2017
1 parent b4acda0 commit 3a5e2e9
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 107 deletions.
42 changes: 14 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,20 @@
[![Known Vulnerabilities](https://snyk.io/test/npm/redux-auto/badge.svg)](https://snyk.io/test/npm/redux-auto)
[![bitHound Dependencies](https://www.bithound.io/github/codemeasandwich/redux-auto/badges/dependencies.svg)](https://www.bithound.io/github/codemeasandwich/redux-auto/master/dependencies/npm)

* [why](#why)
+ [plug & Play](#plug---play)
* [Why](#why)
+ [plug & Play](#plug--play)
+ [asynchronous](#asynchronous)
- [Live Demo](http://redux-auto.s3-website-eu-west-1.amazonaws.com/)
* [Source](https://github.com/codemeasandwich/redux-auto/tree/master/example)
- [Overview](#overview-)
- [setup](#setup)
* [Using along side an existing Redux setup.](#using-along-side-an-existing-redux-setup)
* [Using along side other Redux middleware.](#using-along-side-other-redux-middleware)
* [actions are available in the UI](#actions-are-available-in-the-ui)
- [action files](#action-files)
- [lifecycle diagrame](#lifecycle-diagrame)
- [index files](#index-files)
* [Using along side an existing Redux setup](#using-along-side-an-existing-redux-setup)
* [Using along side other Redux middleware](#using-along-side-other-redux-middleware)
* [Actions are available in the UI](#actions-are-available-in-the-ui)
- [Action files](#action-files)
* [Chaining action together](#chaining-action-together)
- [Lifecycle diagrame](#lifecycle-diagrame)
- [Index files](#index-files)

## why

Expand Down Expand Up @@ -198,16 +199,14 @@ export function action (payload,apps){

You chain actions back-to-back by setting a chain function on the exported function.

There are 2 ways to chain actions together.

**1:** Attach a function to the "chain" property
Attach a function as the "chain" property of the function

**Example:**
/store/user/getInfo
```JS
export function fulfilled (user, payload, userFromServer){
return userFromServer;
} fulfilled.chain = () => actions.nav.move({page:"home"})
} fulfilled.chain = (user, payload, userFromServer) => actions.nav.move({page:"home"})

export function rejected (user, payload, userFromServer){
return userFromServer;
Expand All @@ -218,25 +217,12 @@ export function action (payload){
return fetch('/api/foo/bar/user/'+payload.userId)
}
```
Calling "**actions.user.login({userId:1})**" will automatically call **actions.nav.move** OR **actions.user.reset** *with out arguments

If you pass you our function. It will be passed all the arguments, the same a the host function. Else you can pass thought a function to be called without any arguments

So calling "**actions.user.login({userId:1})**" will automatically call **actions.nav.move** with the host arguments OR **actions.user.reset** *with out arguments.

**2:** Call the action from the index action - *(anti-pattern)*

**Example:**
/store/nav/index
```JS

import actions from 'redux-auto'

export default function nav(nav = defaultNavSetting, action) {
if(action.type == actions.user.login.fulfilled){
actions.nav.move({page:"home"})
}
return nav;
}
```
**!! WARNING !!** Starting another dispatch before your reducer is finished an anti-pattern, because the state you received at the beginning of your reducer will not be the current application state anymore when your reducer finishes.

## lifecycle diagrame

Expand Down
56 changes: 30 additions & 26 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,26 @@ let autoWasCalled = false, reducers = {
throw new Error(reducersBeforeAutoErrorMessage);
}
}

function chaining(actionType){
// console.log(actionType, typeof chaining[actionType])
//if(undefined === chaining[actionType])
// return;
chaining[actionType] && chaining[actionType]();
// else throw new Error(`Chaining function used with ${actionType} was not a function. ${typeof chaining[actionType]}`)
}
chaining.set = function(fn,actionType, argsArray){
if (undefined === fn) {
return
}
chaining[actionType] = (0 < fn.length) ? fn.apply(null,argsArray) : fn;
}

const settings = {}, testing = {};
const settingsOptions = {}, testingOptions = {};

function reset(){

Object.keys(settings).forEach(p => delete settings[p]);
Object.keys(testing).forEach(p => delete testing[p]);
Object.keys(settingsOptions).forEach(p => delete settingsOptions[p]);
Object.keys(testingOptions).forEach(p => delete testingOptions[p]);
Object.keys(actionsBuilder).forEach(p => delete actionsBuilder[p]);
Object.keys(reducers).forEach(p => delete reducers[p]);
Object.keys(lookup).forEach(p => delete lookup[p]);
Expand Down Expand Up @@ -81,7 +86,6 @@ function mergeReducers(otherReducers){
if("_" === actionName[0] || null === reducerName || "index" === actionName)
return;


actionsBuilder[reducerName] = actionsBuilder[reducerName] || {};
actionsBuilder[reducerName][actionName] = (...args) => actionsBuilder[reducerName][actionName](...args);
})
Expand All @@ -90,8 +94,12 @@ function mergeReducers(otherReducers){
function auto (modules, fileNameArray){

autoWasCalled = true;
reset();
buildActionLayout(fileNameArray); if(testing.preOnly) return;
//reset();
delete reducers.auto_function_not_call_before_combineReducers;
buildActionLayout(fileNameArray);

if(testingOptions.preOnly) return;

fileNameArray.forEach(function(key){

// get action name
Expand Down Expand Up @@ -169,29 +177,25 @@ function mergeReducers(otherReducers){
}

// if( stage === "pending" || stage === "fulfilled" || stage === "rejected" ){
if (isFunction(lookup[reducerName][avabileAction][stage])){//("function" === typeof lookup[reducerName][avabileAction][stage]) {
newState = lookup[reducerName][avabileAction][stage](data, action.reqPayload, payload);
if(isFunction(lookup[reducerName][avabileAction][stage].chain)){
chaining[action.type] = lookup[reducerName][avabileAction][stage].chain
}
if (isFunction(lookup[reducerName][avabileAction][stage])){
const argsArray = [data, action.reqPayload, payload];
newState = lookup[reducerName][avabileAction][stage](...argsArray);
chaining.set(lookup[reducerName][avabileAction][stage].chain,action.type,argsArray);
} else {
newState = lookup[reducerName][avabileAction](data, action.reqPayload, actionFragments[1], payload);
if(isFunction(lookup[reducerName][avabileAction].chain)){
chaining[action.type] = lookup[reducerName][avabileAction].chain
}
}
const argsArray = [data, action.reqPayload, actionFragments[1], payload];
newState = lookup[reducerName][avabileAction](...argsArray);
chaining.set(lookup[reducerName][avabileAction].chain,action.type,argsArray)
} // END else

async[avabileAction] = (stage === "pending") ? true : (stage === "fulfilled") ? false : payload;

if(clearFn)//(async[avabileAction] instanceof Error){
async[avabileAction].clear = clearFn
}
} // END else "clear" !== stage
} else {
newState = lookup[reducerName][avabileAction](data, payload);

if(isFunction(lookup[reducerName][avabileAction].chain)){
chaining[action.type] = lookup[reducerName][avabileAction].chain
}
const argsArray = [data, payload]
newState = lookup[reducerName][avabileAction](...argsArray);
chaining.set(lookup[reducerName][avabileAction].chain,action.type,argsArray);
}
} else {// if("index" in lookup[reducerName]){

Expand Down Expand Up @@ -304,13 +308,13 @@ function mergeReducers(otherReducers){
return next => action => next(action)
}
}

auto.reset = reset;
auto.settings = function settings(options){
Object.assign(settings,options)
Object.assign(settingsOptions,options)
}

auto.testing = function testing(options){
Object.assign(testing,options)
Object.assign(testingOptions,options)
}

export default actionsBuilder;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "redux-auto",
"version": "1.5.1",
"version": "1.5.2",
"description": "automatically generate stories and actions from your folder and file structure",
"main": "index.js",
"scripts": {
Expand Down
114 changes: 62 additions & 52 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,11 @@ let middleware,store;

function RefrashStore(){
// build 'auto' based on target files via Webpack
middleware = applyMiddleware( auto(webpackModules, webpackModules.keys(),true));
auto.reset();
middleware = applyMiddleware( auto(webpackModules, webpackModules.keys()));
store = createStore(combineReducers(reducers), middleware );
}

//=====================================================
//=============================================== Setup
//=====================================================
/*
describe('Setup', () => {
beforeEach(function() {
webpackModules.clear();
});
it('should throw an Error when no index is found', () => expect( RefrashStore ).toThrow() )
}) */
//=====================================================
//====================================== initialization
//=====================================================
Expand Down Expand Up @@ -71,14 +60,17 @@ describe('initialization', () => {

it('should have a testing function', () => {

auto.testing({foo:"bar"})
webpackModules.set(propName,"index","default",(posts=[]) => posts );
webpackModules.set(propName,actionName,"default",data => data );
auto.reset();
auto.testing({preOnly:true});
auto(webpackModules, webpackModules.keys())
})

//+++++++++++ should have place holder action function
//++++++++++++++++++ for reducers to ref at build time

it('should have a settings function', () => {

auto.settings({foo:"bar"})
})

Expand Down Expand Up @@ -688,7 +680,6 @@ describe('action middlware', () => {
break;
}
return posts;

})

webpackModules.set(propName,actionName,"action",(payload)=> Promise.reject(new Error(errorMessage)) )
Expand Down Expand Up @@ -732,12 +723,12 @@ describe('action middlware', () => {
actions[propName][actionName]();
})

describe('chaining action together', () => {
//++++++++++ should chain actions for default function
//++++++++++++++++++++++++++++++++++++++++++++++++++++

it('should chain actions for default function', (done) => {


webpackModules.set(propName,"index","default",(data={})=> data )

const actionFunction = data => data;
Expand All @@ -746,8 +737,60 @@ describe('action middlware', () => {
webpackModules.set(propName,actionName,"default",actionFunction)
RefrashStore();
actions[propName][actionName]();

})

// expect(action).toHaveProperty('type', actions[propName][actionName].toString());

//+++++ should pass calling values to chain with async
//++++++++++++++++++++++++++++++++++++++++++++++++++++

it('should pass calling values to chain with async', (done) => {

const defaultData = {}

webpackModules.set(propName,"index","default",(data=defaultData)=> data )
webpackModules.set(propName,actionName,"default",(data)=>data)

const actionFunction = function (data, payload, error){ return data }
actionFunction.chain = (data, payload, error)=>{
expect(data).toEqual(defaultData);
expect(Object.keys(payload).length).toEqual(0);
expect(error).toBeInstanceOf(Error);
done()
};

webpackModules.set(propName,actionName,"rejected",actionFunction)

webpackModules.set(propName,actionName,"action",()=> Promise.reject(new Error("testing: calling values to chain with async")) )

RefrashStore();
actions[propName][actionName]();

})

//++ should allow calling values to be paseed to chain
//++++++++++++++++++++++++++++++++++++++++++++++++++++

it('should allow calling values to be paseed to chain', (done) => {

const defaultData = {};

webpackModules.set(propName,"index","default",(data=defaultData)=> data )

const actionFunction = data => data;
actionFunction.chain = (data,payload)=>{
expect(Object.keys(payload).length).toEqual(0);
expect(data).toEqual(defaultData);
done()
};

webpackModules.set(propName,actionName,"default",actionFunction)
RefrashStore();
actions[propName][actionName]();
})


//++++++++++ should chain actions for PENDING function
//++++++++++++++++++++++++++++++++++++++++++++++++++++

Expand Down Expand Up @@ -841,7 +884,8 @@ describe('action middlware', () => {
})
*/
})
}) // END describe('chaining action together'
}) // END describe('action middlware'


//=====================================================
Expand Down Expand Up @@ -946,37 +990,3 @@ describe('Using the stores', () => {

})
})




// redux-middlware
// - pass default
// store
// - .test.js
// ./ _ ...js
// index
// - no default export
// action-middle
// - null
// - string
// - undefined
// - object
// - promuse
// - pending
// - filfed
// - catch
// init
// before
// - undefined
// - payload
// after
// - undefined
// - state
// actions(file)
// - no default export
// + same name across actions

// actions(function)
// - strings
// - sub-types via promuses

0 comments on commit 3a5e2e9

Please sign in to comment.