Skip to content

Commit

Permalink
Added waitOfInitStore and filterSubStore
Browse files Browse the repository at this point in the history
  • Loading branch information
codemeasandwich committed Jun 16, 2022
1 parent 7096cc8 commit 1f2034b
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 10 deletions.
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ Example layout:

```JS
...
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { auto, reducers } from 'redux-auto';
...
// load the folder that hold you store
Expand All @@ -123,6 +124,37 @@ const store = createStore(combineReducers(reducers), middleware );
...
```

### Inside your API file **Server-side Rendering*
```JS
...
import React from 'react'
import ReactDOMServer from 'react-dom/server'
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { auto, reducers, waitOfInitStore, filterSubStore, fsModules } from 'redux-auto';
import Main from './Main';
...
const webpackModules = fsModules("./store")
...
// Just calling genStore() without args, will load the complete store
function genStore(subStoreToLoad, waitTime){
const limitStoreToLoad = arguments.length ? filterSubStore(webpackModules.keys(),subStoreToLoad) : webpackModules.keys()
const middleware = applyMiddleware( auto(webpackModules, limitStoreToLoad))
const store = createStore(combineReducers(reducers), middleware );
return waitOfInitStore(store,waitTime)
}
...
app.get('/', function (req, res) {
genStore(["user"],5000) // wait 5 sec
.then( store => {
res.send(ReactDOMServer.renderToString(<Main store={store} />)))
}).catch( err => {
// check your init promise are completing
res.status(500).send("Problem in getting your page");
})
})
...
```

### Inside your setup file **React-Native*

➡ If you want to use Redux-auto in a **React-Native project**. You will just need to install the [babel-plugin-redux-auto](https://www.npmjs.com/package/babel-plugin-redux-auto) to allow to dynamic importing of your store.
Expand All @@ -133,6 +165,7 @@ Now back to the setup...

```JS
...
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { auto, reducers } from 'redux-auto';
...
// load the folder that hold you store
Expand Down
59 changes: 51 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import smartAction from './middleware/smartActions.js';
import webpackModules from './test/webpackModules';
import fsModules from './test/fsModules';

function isFunction(value){
//return ({}).toString.call(value) === '[object Function]';
Expand Down Expand Up @@ -105,10 +106,8 @@ function buildActionLayout(fileNameArray){
actionsBuilder[reducerName][actionName].clear = (...args) => actionsBuilder[reducerName][actionName].clear(...args);
})
} // END buildActionLayout



function auto (modules, fileNameArray){

function auto (modules, fileNameArray, settings){

if("object" === typeof modules && arguments.length === 1){
Object.keys(modules).forEach(reducers =>{
Expand Down Expand Up @@ -348,8 +347,8 @@ Object.assign(actionsBuilder,actionsImplementation);

actionOutput.payload
.then(result => {

if(true === settingsOptions.smartActions){
if((settings && true === settings .smartActions) ||
( true === settingsOptions.smartActions)){
const smartActionOutPut = smartAction(result)
if(smartActionOutPut){
smartActionOutPut
Expand Down Expand Up @@ -403,9 +402,53 @@ Object.assign(actionsBuilder,actionsImplementation);
}
}) // END setTimeout
return next => action => next(action)
}
} // END setDispatch

} // END of auto

function waitOfInitStore(store,timeToWait) {

return new Promise((resolve, reject) => {

const timeout = setTimeout(()=>{
console.log(x,new Date(),timeToWait)
reject(new Error("Store setup is taking to long!"))
},timeToWait)

const unsubscribe = store.subscribe(()=>{

const state = store.getState()

const initsCompleted =
Object.keys(state).reduce((check,name)=>{
if( ! check){
return false
}

if ( undefined === state[name].loading ) {
return check
}

return check && (undefined !== state[name].loading.init && // not fired yet
true !== state[name].loading.init) // in progress
},true) // END blockThisInitsComplete.reduce

if(initsCompleted){
clearTimeout(timeout)
unsubscribe()
resolve(store)
} // END if initsCompleted

}) // END store.subscribe

}); // END new Promise
}

function filterSubStore(fileNameArray, loadSubStore){
return fileNameArray.filter(fileName => loadSubStore.some(name => fileName.includes(`${name}/`) ||
fileName.includes(`${name}\\`)))
} // END filterSubStore

auto.reset = reset;
auto.settings = function settings(options){
Object.assign(settingsOptions,options)
Expand All @@ -416,4 +459,4 @@ auto.testing = function testing(options){
}

export default actionsBuilder;
export { auto, mergeReducers, reducers }
export { auto, mergeReducers, reducers, filterSubStore, waitOfInitStore, fsModules }
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": "2.1.0",
"version": "2.2.0",
"description": "automatically generate stories and actions from your folder and file structure",
"main": "bundle.js",
"scripts": {
Expand Down
109 changes: 108 additions & 1 deletion test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import faker from 'faker'
import { createStore, applyMiddleware, combineReducers } from 'redux'

import webpackModules from './webpackModules';
import actions, { auto, reducers, mergeReducers, reset, after } from '../index';
import actions, { auto, reducers, mergeReducers, after, filterSubStore, waitOfInitStore } from '../index';

let middleware,store;

Expand Down Expand Up @@ -264,6 +264,113 @@ describe('initialization', () => {
RefrashStore();
// should be automatically called
})

//++++ should load parts of the store based on 2nd arg
//++++++++++++++++++++++++++++++++++++++++++++++++++++

it('should only load the parts of the store based on 2nd arg', (done) => {

const Apn = "A "+propName,
Bpn = "B "+propName;
let initComplete = false;

webpackModules.set(Apn, "index", "default",(data={})=> data )
webpackModules.set(Apn, "init", "default",data => data )
webpackModules.set(Apn, "init", "action", () => Promise.resolve(true))

const badFn = () => {
expect(false).toBe(true)
throw new Error("Should not be loaded OR run!")
}

webpackModules.set(Bpn, "index", "default",badFn)
webpackModules.set(Bpn, "init", "default",badFn)
webpackModules.set(Bpn, "init", "action", badFn)

auto.reset();
middleware = applyMiddleware( auto(webpackModules, filterSubStore(webpackModules.keys(),[Apn])));
store = createStore(combineReducers(reducers), middleware );
const state = store.getState()
expect(state).toHaveProperty(Apn)
expect(state).not.toHaveProperty(Bpn)
done()
})

//+++++ should provide a promise for when init is done
//+++++++++++++++++++++++++++++++++++++++++++++ Single

it('should provide a promise for when initialisation is complete', (done) => {

let initComplete = false;

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

webpackModules.set(propName, "init", "default",(posts, payload, stage)=> {
expect(['PENDING','FULFILLED'].includes(stage)).toBe(true) // should call PENDING and FULFILLED
if ('FULFILLED' === stage) {
initComplete = true;
}
return posts;
})
webpackModules.set(propName, "init", "action", () => Promise.resolve(true))
RefrashStore();
waitOfInitStore(store,100) // wait... but the Promise.resolve should complete immediately
.then(storex => {
expect(storex).toBe(store)
expect(initComplete).toBe(true)
done();
})
})

//+++++ should provide a promise for when init is done
//+++++++++++++++++++++++++++++++++++++++++++++ Muilti

it('should provide a promise for when Muil-initialisation is complete', (done) => {

let initCompleted = [];

const Apn = "A "+propName, // with init
Bpn = "B "+propName, // with init
Cpn = "C "+propName; // with OUT init

webpackModules.set(Apn, "index", "default",(data={})=> data )
webpackModules.set(Apn, "init", "default",(posts, payload, stage)=> {
expect(['PENDING','FULFILLED'].includes(stage)).toBe(true) // should call PENDING and FULFILLED
expect(initCompleted.includes("A")).not.toBe(true)
if ('FULFILLED' === stage) {
initCompleted.push("A");
}
return posts;
})
webpackModules.set(Apn, "init", "action", () => {
return new Promise(resolve => {
setTimeout(()=>resolve(true), Math.random()*50); // add a bit of spice
});
})

webpackModules.set(Bpn, "index", "default",(data={})=> data )
webpackModules.set(Bpn, "init", "default",(posts, payload, stage)=> {
expect(['PENDING','FULFILLED'].includes(stage)).toBe(true) // should call PENDING and FULFILLED
expect(initCompleted.includes("B")).not.toBe(true)
if ('FULFILLED' === stage) {
initCompleted.push("B");
}
return posts;
})
webpackModules.set(Bpn, "init", "action", () => Promise.resolve(true))
webpackModules.set(Bpn, actionName, "default",(data={})=> data )

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

RefrashStore();
waitOfInitStore(store,1000) // wait... but the Promise.resolve should complete immediately
.then(storex => {
expect(storex).toBe(store)
expect(initCompleted).toHaveLength(2)
done();
})
})
})

//=====================================================
Expand Down

0 comments on commit 1f2034b

Please sign in to comment.