From 5bc158396817bed29808af2f1d4d2bee7cb9174d Mon Sep 17 00:00:00 2001 From: antjanus Date: Fri, 5 Jan 2018 00:11:00 -0700 Subject: [PATCH 1/4] feat(lib): provide store functionality --- src/components/ngRedux.js | 75 +++++++++++++++++++++------------- src/components/storeWrapper.js | 16 ++++++++ 2 files changed, 62 insertions(+), 29 deletions(-) create mode 100644 src/components/storeWrapper.js diff --git a/src/components/ngRedux.js b/src/components/ngRedux.js index 4b86840..53683b1 100644 --- a/src/components/ngRedux.js +++ b/src/components/ngRedux.js @@ -2,6 +2,7 @@ import Connector from './connector'; import invariant from 'invariant'; import {createStore, applyMiddleware, compose, combineReducers} from 'redux'; import digestMiddleware from './digestMiddleware'; +import wrapStore from './storeWrapper'; import curry from 'lodash.curry'; import isFunction from 'lodash.isfunction'; @@ -20,6 +21,11 @@ export default function ngReduxProvider() { let _storeEnhancers = undefined; let _initialState = undefined; let _reducerIsObject = undefined; + let _providedStore = undefined; + + this.provideStore = (store) => { + _providedStore = store; + } this.createStoreWith = (reducer, middlewares, storeEnhancers, initialState) => { invariant( @@ -42,45 +48,56 @@ export default function ngReduxProvider() { }; this.$get = ($injector) => { - const resolveMiddleware = middleware => isString(middleware) - ? $injector.get(middleware) - : middleware; + if (_providedStore) { + const emptyStore = createNgReduxStore($injector, [], [], state => state, undefined); - const resolvedMiddleware = map(_middlewares, resolveMiddleware); + return wrapStore(_providedStore, emptyStore); + } - const resolveStoreEnhancer = storeEnhancer => isString(storeEnhancer) - ? $injector.get(storeEnhancer) - : storeEnhancer; + return createNgReduxStore($injector, _middlewares, _storeEnhancers, _reducer, _initialState); - const resolvedStoreEnhancer = map(_storeEnhancers, resolveStoreEnhancer); + }; - if(_reducerIsObject) { - const getReducerKey = key => isString(_reducer[key]) - ? $injector.get(_reducer[key]) - : _reducer[key]; + this.$get.$inject = ['$injector']; +} - const resolveReducerKey = (result, key) => assign({}, result, - { [key]: getReducerKey(key) } - ); +function createNgReduxStore($injector, _middlewares, _storeEnhancers, _reducer, _initialState) { + const resolveMiddleware = middleware => isString(middleware) + ? $injector.get(middleware) + : middleware; - const reducersObj = Object - .keys(_reducer) - .reduce(resolveReducerKey, {}); + const resolvedMiddleware = map(_middlewares, resolveMiddleware); - _reducer = combineReducers(reducersObj); - } + const resolveStoreEnhancer = storeEnhancer => isString(storeEnhancer) + ? $injector.get(storeEnhancer) + : storeEnhancer; - const finalCreateStore = resolvedStoreEnhancer ? compose(...resolvedStoreEnhancer)(createStore) : createStore; + const resolvedStoreEnhancer = map(_storeEnhancers, resolveStoreEnhancer); - //digestMiddleware needs to be the last one. - resolvedMiddleware.push(digestMiddleware($injector.get('$rootScope'))); + if(_reducerIsObject) { + const getReducerKey = key => isString(_reducer[key]) + ? $injector.get(_reducer[key]) + : _reducer[key]; - const store = _initialState - ? applyMiddleware(...resolvedMiddleware)(finalCreateStore)(_reducer, _initialState) - : applyMiddleware(...resolvedMiddleware)(finalCreateStore)(_reducer); + const resolveReducerKey = (result, key) => assign({}, result, + { [key]: getReducerKey(key) } + ); - return assign({}, store, { connect: Connector(store) }); - }; + const reducersObj = Object + .keys(_reducer) + .reduce(resolveReducerKey, {}); - this.$get.$inject = ['$injector']; + _reducer = combineReducers(reducersObj); + } + + const finalCreateStore = resolvedStoreEnhancer ? compose(...resolvedStoreEnhancer)(createStore) : createStore; + + //digestMiddleware needs to be the last one. + resolvedMiddleware.push(digestMiddleware($injector.get('$rootScope'))); + + const store = _initialState + ? applyMiddleware(...resolvedMiddleware)(finalCreateStore)(_reducer, _initialState) + : applyMiddleware(...resolvedMiddleware)(finalCreateStore)(_reducer); + + return assign({}, store, { connect: Connector(store) }); } diff --git a/src/components/storeWrapper.js b/src/components/storeWrapper.js new file mode 100644 index 0000000..ae6db57 --- /dev/null +++ b/src/components/storeWrapper.js @@ -0,0 +1,16 @@ +export default function wrapStore(providedStore, ngReduxStore) { + const unsubscribe = providedStore + .subscribe(() => { + let newState = providedStore.getState(); + + ngReduxStore.dispatch(newState); + }) + ; + + return Object.assign({}, + providedStore, + { + subscribe: ngReduxStore.subscribe + }) + ; +} From 745f3c7ff34000712d94ea0e757a0ed9104d8471 Mon Sep 17 00:00:00 2001 From: Derrick Pelletier Date: Wed, 17 Jan 2018 23:17:49 -0800 Subject: [PATCH 2/4] feat(lib): fixes bugs with proposed provided-store logic --- src/components/ngRedux.js | 73 ++++++++++------------- src/components/providedStoreMiddleware.js | 11 ++++ src/components/storeWrapper.js | 13 ++-- 3 files changed, 48 insertions(+), 49 deletions(-) create mode 100644 src/components/providedStoreMiddleware.js diff --git a/src/components/ngRedux.js b/src/components/ngRedux.js index 53683b1..ddba822 100644 --- a/src/components/ngRedux.js +++ b/src/components/ngRedux.js @@ -2,6 +2,7 @@ import Connector from './connector'; import invariant from 'invariant'; import {createStore, applyMiddleware, compose, combineReducers} from 'redux'; import digestMiddleware from './digestMiddleware'; +import providedStoreMiddleware from './providedStoreMiddleware'; import wrapStore from './storeWrapper'; import curry from 'lodash.curry'; @@ -25,6 +26,8 @@ export default function ngReduxProvider() { this.provideStore = (store) => { _providedStore = store; + _reducer = (state, action) => action.payload; + _middlewares = [providedStoreMiddleware(_providedStore)]; } this.createStoreWith = (reducer, middlewares, storeEnhancers, initialState) => { @@ -48,56 +51,46 @@ export default function ngReduxProvider() { }; this.$get = ($injector) => { - if (_providedStore) { - const emptyStore = createNgReduxStore($injector, [], [], state => state, undefined); + const resolveMiddleware = middleware => isString(middleware) + ? $injector.get(middleware) + : middleware; - return wrapStore(_providedStore, emptyStore); - } - - return createNgReduxStore($injector, _middlewares, _storeEnhancers, _reducer, _initialState); - - }; - - this.$get.$inject = ['$injector']; -} + const resolvedMiddleware = map(_middlewares, resolveMiddleware); -function createNgReduxStore($injector, _middlewares, _storeEnhancers, _reducer, _initialState) { - const resolveMiddleware = middleware => isString(middleware) - ? $injector.get(middleware) - : middleware; + const resolveStoreEnhancer = storeEnhancer => isString(storeEnhancer) + ? $injector.get(storeEnhancer) + : storeEnhancer; - const resolvedMiddleware = map(_middlewares, resolveMiddleware); + const resolvedStoreEnhancer = map(_storeEnhancers, resolveStoreEnhancer); - const resolveStoreEnhancer = storeEnhancer => isString(storeEnhancer) - ? $injector.get(storeEnhancer) - : storeEnhancer; + if(_reducerIsObject) { + const getReducerKey = key => isString(_reducer[key]) + ? $injector.get(_reducer[key]) + : _reducer[key]; - const resolvedStoreEnhancer = map(_storeEnhancers, resolveStoreEnhancer); + const resolveReducerKey = (result, key) => assign({}, result, + { [key]: getReducerKey(key) } + ); - if(_reducerIsObject) { - const getReducerKey = key => isString(_reducer[key]) - ? $injector.get(_reducer[key]) - : _reducer[key]; + const reducersObj = Object + .keys(_reducer) + .reduce(resolveReducerKey, {}); - const resolveReducerKey = (result, key) => assign({}, result, - { [key]: getReducerKey(key) } - ); - - const reducersObj = Object - .keys(_reducer) - .reduce(resolveReducerKey, {}); + _reducer = combineReducers(reducersObj); + } - _reducer = combineReducers(reducersObj); - } + const finalCreateStore = resolvedStoreEnhancer ? compose(...resolvedStoreEnhancer)(createStore) : createStore; - const finalCreateStore = resolvedStoreEnhancer ? compose(...resolvedStoreEnhancer)(createStore) : createStore; + //digestMiddleware needs to be the last one. + resolvedMiddleware.push(digestMiddleware($injector.get('$rootScope'))); - //digestMiddleware needs to be the last one. - resolvedMiddleware.push(digestMiddleware($injector.get('$rootScope'))); + const store = applyMiddleware(...resolvedMiddleware)(finalCreateStore)(_reducer, _initialState || undefined) + const mergedStore = assign({}, store, { connect: Connector(store) }); + + if (_providedStore) wrapStore(_providedStore, mergedStore) - const store = _initialState - ? applyMiddleware(...resolvedMiddleware)(finalCreateStore)(_reducer, _initialState) - : applyMiddleware(...resolvedMiddleware)(finalCreateStore)(_reducer); + return mergedStore; + }; - return assign({}, store, { connect: Connector(store) }); + this.$get.$inject = ['$injector']; } diff --git a/src/components/providedStoreMiddleware.js b/src/components/providedStoreMiddleware.js new file mode 100644 index 0000000..3238513 --- /dev/null +++ b/src/components/providedStoreMiddleware.js @@ -0,0 +1,11 @@ +/** + * middleware for the empty store that ng-redux uses when a external store is provided + * Provides two cases: + * 1. NGREDUX_PASSTHROUGH, where data is coming IN to the "fake" store + * 2. all other, where actions are dispatched out, and proxied to the true store + */ +export default _providedStore => store => next => action => { + return action.type === '@@NGREDUX_PASSTHROUGH' + ? next(action) + : _providedStore.dispatch(action) +} diff --git a/src/components/storeWrapper.js b/src/components/storeWrapper.js index ae6db57..838ec31 100644 --- a/src/components/storeWrapper.js +++ b/src/components/storeWrapper.js @@ -2,15 +2,10 @@ export default function wrapStore(providedStore, ngReduxStore) { const unsubscribe = providedStore .subscribe(() => { let newState = providedStore.getState(); - - ngReduxStore.dispatch(newState); - }) - ; - - return Object.assign({}, - providedStore, - { - subscribe: ngReduxStore.subscribe + ngReduxStore.dispatch({ + type: '@@NGREDUX_PASSTHROUGH', + payload: newState + }); }) ; } From 8128828d19c395f2e39949ad4e46152b22320769 Mon Sep 17 00:00:00 2001 From: Derrick Pelletier Date: Thu, 18 Jan 2018 00:57:59 -0800 Subject: [PATCH 3/4] feat(lib): reverted a change to the store initialization --- src/components/ngRedux.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/ngRedux.js b/src/components/ngRedux.js index ddba822..e30f56a 100644 --- a/src/components/ngRedux.js +++ b/src/components/ngRedux.js @@ -84,7 +84,10 @@ export default function ngReduxProvider() { //digestMiddleware needs to be the last one. resolvedMiddleware.push(digestMiddleware($injector.get('$rootScope'))); - const store = applyMiddleware(...resolvedMiddleware)(finalCreateStore)(_reducer, _initialState || undefined) + const store = _initialState + ? applyMiddleware(...resolvedMiddleware)(finalCreateStore)(_reducer, _initialState) + : applyMiddleware(...resolvedMiddleware)(finalCreateStore)(_reducer); + const mergedStore = assign({}, store, { connect: Connector(store) }); if (_providedStore) wrapStore(_providedStore, mergedStore) From b94282bc4b4fa964f3062178f951631a078a7aed Mon Sep 17 00:00:00 2001 From: Derrick Pelletier Date: Sat, 27 Jan 2018 12:17:27 -0800 Subject: [PATCH 4/4] feat(lib): added initial populate dispatch and middleware/enhancer support to provided mode --- src/components/ngRedux.js | 9 +++++---- src/components/storeWrapper.js | 17 ++++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/ngRedux.js b/src/components/ngRedux.js index e30f56a..18028b3 100644 --- a/src/components/ngRedux.js +++ b/src/components/ngRedux.js @@ -24,10 +24,11 @@ export default function ngReduxProvider() { let _reducerIsObject = undefined; let _providedStore = undefined; - this.provideStore = (store) => { + this.provideStore = (store, middlewares = [], storeEnhancers) => { _providedStore = store; _reducer = (state, action) => action.payload; - _middlewares = [providedStoreMiddleware(_providedStore)]; + _storeEnhancers = storeEnhancers; + _middlewares = [...middlewares, providedStoreMiddleware(store)]; } this.createStoreWith = (reducer, middlewares, storeEnhancers, initialState) => { @@ -45,7 +46,7 @@ export default function ngReduxProvider() { _reducer = reducer; _reducerIsObject = isObject(reducer); - _storeEnhancers = storeEnhancers + _storeEnhancers = storeEnhancers; _middlewares = middlewares || []; _initialState = initialState; }; @@ -90,7 +91,7 @@ export default function ngReduxProvider() { const mergedStore = assign({}, store, { connect: Connector(store) }); - if (_providedStore) wrapStore(_providedStore, mergedStore) + if (_providedStore) wrapStore(_providedStore, mergedStore); return mergedStore; }; diff --git a/src/components/storeWrapper.js b/src/components/storeWrapper.js index 838ec31..ae03797 100644 --- a/src/components/storeWrapper.js +++ b/src/components/storeWrapper.js @@ -1,11 +1,10 @@ export default function wrapStore(providedStore, ngReduxStore) { - const unsubscribe = providedStore - .subscribe(() => { - let newState = providedStore.getState(); - ngReduxStore.dispatch({ - type: '@@NGREDUX_PASSTHROUGH', - payload: newState - }); - }) - ; + providedStore.subscribe(() => { + let newState = providedStore.getState(); + ngReduxStore.dispatch({ + type: '@@NGREDUX_PASSTHROUGH', + payload: newState + }); + }); + providedStore.dispatch({ type: '@@NGREDUX_PASSTHROUGH_INIT' }) }