Пример #1
0
module.exports = (plugins, custom) => {
    const allReducers = combineReducers(plugins, {
        locale: require('../../reducers/locale'),
        browser: require('../../reducers/browser'),
        theme: require('../../reducers/theme'),
        map: () => {return null; },
        mapInitialConfig: () => {return null; },
        layers: () => {return null; },
        pluginsConfig: require('./reducers/config'),
        custom
    });
    const standardEpics = {
        ...require('../../epics/controls')
    };
    const rootEpic = combineEpics(plugins, {...standardEpics });
    const epicMiddleware = createEpicMiddleware(rootEpic);

    const rootReducer = (state, action) => {
        if (action.type === 'LOADED_STATE') {
            return action.state;
        }
        let mapState = LayersUtils.splitMapAndLayers(mapConfig(state, action));
        let newState = {
            ...allReducers(state, action),
            map: mapState && mapState.map ? map(mapState.map, action) : null,
            mapInitialConfig: mapState ? mapState.mapInitialConfig : null,
            layers: mapState ? layers(mapState.layers, action) : null
        };
        return newState;
    };

    return createDebugStore(rootReducer, {}, [epicMiddleware]);
};
Пример #2
0
export default function initStore (initialState) {
  const epicMiddleware = createEpicMiddleware(rootEpic)
  const logger = createLogger({ collapsed: true })  // log every action to see what's happening behind the scenes.
  const reduxMiddleware = applyMiddleware(thunkMiddleware, epicMiddleware, logger)

  return createStore(starwarsReducer, initialState, reduxMiddleware)
};
Пример #3
0
describe('editorDuck Epics', () => {
  let store
  const bus = createBus()
  const epicMiddleware = createEpicMiddleware(populateEditorFromUrlEpic)
  const mockStore = configureMockStore([
    epicMiddleware,
    createReduxMiddleware(bus)
  ])
  beforeAll(() => {
    store = mockStore({
      settings: {
        cmdchar: ':'
      }
    })
  })
  afterEach(() => {
    bus.reset()
    store.clearActions()
  })
  test('Sends a SET_CONTENT event on initial url arguments', done => {
    const cmd = 'play'
    const arg = 'test-guide'
    const action = {
      type: APP_START,
      url: `http://url.com?cmd=${cmd}&arg=${arg}`
    }

    bus.take(SET_CONTENT, currentAction => {
      // Then
      expect(store.getActions()).toEqual([
        action,
        { type: SET_CONTENT, message: `:${cmd} ${arg}` }
      ])
      done()
    })

    // When
    store.dispatch(action)
  })
  test('Sends a SET_CONTENT event on url arguments change', done => {
    const cmd = 'play'
    const arg = 'test-guide'
    const action = {
      type: URL_ARGUMENTS_CHANGE,
      url: `?cmd=${cmd}&arg=${arg}`
    }

    bus.take(SET_CONTENT, currentAction => {
      // Then
      expect(store.getActions()).toEqual([
        action,
        { type: SET_CONTENT, message: `:${cmd} ${arg}` }
      ])
      done()
    })

    // When
    store.dispatch(action)
  })
})
Пример #4
0
export default initialState => [
  rootReducer,
  initialState,
  applyMiddleware(
    createEpicMiddleware(rootEpic)
  )
]
Пример #5
0
describe('injectDiscoveryEpic', () => {
  let store
  const bus = createBus()
  const epicMiddleware = createEpicMiddleware(discovery.injectDiscoveryEpic)
  const mockStore = configureMockStore([
    epicMiddleware,
    createReduxMiddleware(bus)
  ])
  beforeAll(() => {
    store = mockStore({
      connections: {}
    })
  })
  afterEach(() => {
    nock.cleanAll()
    bus.reset()
    store.clearActions()
  })
  test('injectDiscoveryEpic takes passed properties and updates discovery endpoint', () => {
    // Given
    const action = {
      type: discovery.INJECTED_DISCOVERY,
      username: '******',
      password: '******',
      host: 'bolt://localhost:7687',
      encrypted: true
    }

    const p = new Promise((resolve, reject) => {
      bus.take(discovery.DONE, currentAction => {
        // Then
        const actions = store.getActions()
        try {
          expect(actions).toEqual([
            action,
            discovery.updateDiscoveryConnection({
              host: action.host,
              username: action.username,
              password: action.password,
              encrypted: action.encrypted
            }),
            currentAction
          ])
          resolve()
        } catch (e) {
          reject(e)
        }
      })
    })

    // When
    store.dispatch(action)

    // Return
    return p
  })
})
Пример #6
0
exports.createStore = function () {
    return redux_2.createStore(redux_2.combineReducers({
        shell: exports.shell,
        format: exports.format,
        size: exports.size,
        connection: exports.connection,
        history: exports.history
    }), redux_1.applyMiddleware(redux_observable_1.createEpicMiddleware(redux_observable_1.combineEpics(updateSelectedActivityEpic, sendMessageEpic, trySendMessageEpic, retrySendMessageEpic, showTypingEpic, sendTypingEpic, speakSSMLEpic, speakOnMessageReceivedEpic, startListeningEpic, stopListeningEpic, stopSpeakingEpic, listeningSilenceTimeoutEpic))));
};
Пример #7
0
export default function configureStore() {
  const rootEpic = combineEpics(...epics);
  const middlewares = [createEpicMiddleware(rootEpic)];

  return createStore(
    rootReducer,
    defaultState,
    composeEnhancers(applyMiddleware(...middlewares))
  );
}
Пример #8
0
export default function configure(initialState) {
  const middleware = [
    createEpicMiddleware(rootEpic),
  ]

  const enhancer = compose(
    applyMiddleware(...middleware)
  )

  const store = createStore(rootReducer, initialState, enhancer)

  return store
}
Пример #9
0
export default function(givenInitialState: Object = {}) {
  const initialState = merge(getInitialState(), givenInitialState);
  const epicMiddleware = createEpicMiddleware(epics);
  const composeEnhancers =
    (typeof window !== "undefined" &&
      window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) ||
    compose;

  return createStore(
    reducer,
    initialState,
    composeEnhancers(
      applyMiddleware(epicMiddleware, coreMiddlewares.errorMiddleware)
    )
  );
}
Пример #10
0
const configureMiddleware = (initialState, platformDeps, platformMiddleware) => {
  const storageConfig = configureStorage(initialState, platformDeps.storageEngine);
  const deps = configureDeps(initialState, platformDeps, storageConfig);
  const rootEpic = configureEpics(deps);
  const epicMiddleware = createEpicMiddleware(rootEpic);
  const middleware = [
    injectMiddleware(deps),
    epicMiddleware,
    ...platformMiddleware,
  ];

  const enableLogger = process.env.NODE_ENV !== 'production' && (
    process.env.IS_BROWSER || initialState.device.isReactNative
  );

  // Logger must be the last middleware in chain.

  // if(false){
  if (enableLogger) {
    const ignoredActions = [REHYDRATE];
    const logger = createLoggerMiddleware({
      collapsed: true,
      predicate: (getState, action) => ignoredActions.indexOf(action.type) === -1,
      // Convert immutable to JSON.
      stateTransformer: state => JSON.parse(JSON.stringify(state)),
    });
    middleware.push(logger);
  }

  if (module.hot && typeof module.hot.accept === 'function') {
    if (initialState.device.isReactNative) {
      module.hot.accept(() => {
        const configureEpics = require('./configureEpics').default;

        epicMiddleware.replaceEpic(configureEpics(deps));
      });
    } else {
      module.hot.accept('./configureEpics', () => {
        const configureEpics = require('./configureEpics').default;

        epicMiddleware.replaceEpic(configureEpics(deps));
      });
    }
  }

  return { storageConfig, middleware, deps };
};
Пример #11
0
export function createFragmentMiddleware(rootModel, rootFragment) {

    let working = false;
    let reenter = false;

    const rootState = {};
    const arrayWrapper = new Array(2);
    const { _root } = rootModel;
    const { onChangesCompleted } = _root;
    const changes = new BehaviorSubject(arrayWrapper);

    arrayWrapper[0] = rootModel;
    arrayWrapper[1] = rootState;

    _root.onChangesCompleted = function() {
        if (working) { return reenter = true; }
        working = true;
        do {
            reenter = false;
            if (onChangesCompleted) {
                onChangesCompleted.call(this);
            }
            arrayWrapper[0] = this;
            arrayWrapper[1] = rootState;
            rootModel.derefCount++;
            changes.next(arrayWrapper);
        } while(false && reenter === true);
    }

    rootFragment = rootFragment(Models.from(changes));

    return createEpicMiddleware(function(action$, store) {
        return rootFragment(action$, store)
            .do(() => working = false)
            .map(([model, state]) => ({
                data: state, type: 'falcor'
            }));
    });
}
Пример #12
0
var expect = require('expect');

const configureMockStore = require('redux-mock-store').default;
const { createEpicMiddleware, combineEpics } = require('redux-observable');
const {
    refreshLayers, LAYERS_REFRESHED, LAYERS_REFRESH_ERROR, UPDATE_NODE,
    updateLayerDimension, CHANGE_LAYER_PARAMS
} = require('../../actions/layers');
const {
    testEpic
} = require('./epicTestUtils');

const { refresh, updateDimension } = require('../layers');
const rootEpic = combineEpics(refresh);
const epicMiddleware = createEpicMiddleware(rootEpic);
const mockStore = configureMockStore([epicMiddleware]);

describe('layers Epics', () => {
    let store;
    beforeEach(() => {
        store = mockStore();
    });

    afterEach(() => {
        epicMiddleware.replaceEpic(rootEpic);
    });

    it('refreshes layers', (done) => {
        let action = refreshLayers([{
            url: 'base/web/client/test-resources/wms/GetCapabilities-1.1.1.xml',
Пример #13
0
"use strict";
var redux_1 = require("redux");
var createLogger = require("redux-logger");
var redux_observable_1 = require("redux-observable");
var reducers_1 = require("./reducers");
var index_1 = require("./epics/index");
var epicMiddleware = redux_observable_1.createEpicMiddleware(index_1.default);
function configureStore() {
    var store = redux_1.createStore(reducers_1.default, redux_1.compose(redux_1.applyMiddleware(epicMiddleware, createLogger())));
    return store;
}
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = configureStore;
Пример #14
0
import { createStore, applyMiddleware } from 'redux';
import { createEpicMiddleware } from 'redux-observable';

import { pingEpic } from '../epics';
import pingReducer from '../reducers';

const epicMiddleware = createEpicMiddleware(pingEpic);

export default createStore(
  pingReducer,
  applyMiddleware(epicMiddleware)
);
Пример #15
0
  createStore,
  applyMiddleware,
  compose,
} from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import { createEpicMiddleware } from 'redux-observable';
import { routerMiddleware } from 'react-router-redux';
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import createHistory from 'history/createBrowserHistory';
import reducers from 'src/reducers';
import epics from './epics';

const isProd: boolean = String(process.env.NODE_ENV) === 'production';
const composeEnhancers: Function = isProd ? compose : composeWithDevTools;
const epicMiddleware: Object = createEpicMiddleware();

export const history: Object = createHistory();

const persistConfig: Object = {
  key: 'root',
  storage,
  whitelist: ['auth'],
};

const middlewares: Array<any> = [
  epicMiddleware,
  routerMiddleware(history),
];

const persistedReducer: Object = persistReducer(persistConfig, reducers);
Пример #16
0
const { compose, createStore, applyMiddleware } = require('redux');
const { createEpicMiddleware } = require('redux-observable');
const epics = require('./epics');
const reducers = require('./reducers');

const epicsMiddleware = createEpicMiddleware(epics);

module.exports = createStore(
  reducers,
  applyMiddleware(epicsMiddleware)
);
Пример #17
0
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import { createEpicMiddleware } from 'redux-observable';
import { createLogger } from 'redux-logger';

import rootReducer from './redux/reducers';
import rootEpic from './redux/epics'; // remember this defaults to the index file in the folder

const loggerMiddleware = createLogger()

const store = createStore(
  rootReducer,
  // you should try adding the redux-logger middleware!
  applyMiddleware(createEpicMiddleware(rootEpic), loggerMiddleware),
);

// I make a new component here that wraps the App component in a provider, THIS provider
// is what allows redux to communicate with the application on the whole
const ReduxApp = () => (
  <Provider store={store}>
    <App />
  </Provider>
);

ReactDOM.render(<ReduxApp />, document.getElementById('root'));
registerServiceWorker();
Пример #18
0
/* @flow */
import React, { Component } from 'react';
import { AppRegistry } from 'react-native';

import { createStore, applyMiddleware, combineReducers } from 'redux';
import { Provider, connect } from 'react-redux';
import { createEpicMiddleware } from 'redux-observable';
import createLogger from 'redux-logger';

import reducers from './reducers';
import epic from './epic';
import Main from './containers/Main';

const store = createStore(
  combineReducers(reducers),
  applyMiddleware(
    createEpicMiddleware(epic),
    createLogger()
  )
);
store.dispatch({ type: 'APP_INIT' });

function Compare() {
  return <Provider store={store}>
    <Main />
  </Provider>;
}

AppRegistry.registerComponent('Compare', () => Compare);
Пример #19
0
module.exports = (initialState = {defaultState: {}, mobile: {}}, appReducers = {}, appEpics = {}, plugins = {}, storeOpts = {}) => {
    const allReducers = combineReducers(plugins, {
        ...appReducers,
        localConfig: require('../reducers/localConfig'),
        locale: require('../reducers/locale'),
        browser: require('../reducers/browser'),
        controls: require('../reducers/controls'),
        theme: require('../reducers/theme'),
        help: require('../reducers/help'),
        map: () => {return null; },
        mapInitialConfig: () => {return null; },
        layers: () => {return null; },
        routing: routerReducer
    });
    const rootEpic = combineEpics(plugins, {...appEpics, ...standardEpics});
    const optsState = storeOpts.initialState || {defaultState: {}, mobile: {}};
    const defaultState = assign({}, initialState.defaultState, optsState.defaultState);
    const mobileOverride = assign({}, initialState.mobile, optsState.mobile);
    const epicMiddleware = createEpicMiddleware(rootEpic);
    const rootReducer = (state, action) => {
        let mapState = createHistory(LayersUtils.splitMapAndLayers(mapConfig(state, action)));
        let newState = {
            ...allReducers(state, action),
            map: mapState && mapState.map ? map(mapState.map, action) : null,
            mapInitialConfig: mapState && mapState.mapInitialConfig || mapState && mapState.loadingError && {
                loadingError: mapState.loadingError,
                mapId: mapState.loadingError.mapId
            } || null,
            layers: mapState ? layers(mapState.layers, action) : null
        };
        if (action && action.type === CHANGE_BROWSER_PROPERTIES && newState.browser.mobile) {
            newState = assign(newState, mobileOverride);
        }

        return newState;
    };
    let store;
    let enhancer;
    if (storeOpts && storeOpts.notify) {
        enhancer = ListenerEnhancer;
    }
    if (storeOpts && storeOpts.persist) {
        storeOpts.persist.whitelist.forEach((fragment) => {
            const fragmentState = localStorage.getItem('mapstore2.persist.' + fragment);
            if (fragmentState) {
                defaultState[fragment] = JSON.parse(fragmentState);
            }
        });
        if (storeOpts.onPersist) {
            setTimeout(() => {storeOpts.onPersist(); }, 0);
        }
    }
    store = DebugUtils.createDebugStore(rootReducer, defaultState, [epicMiddleware, reduxRouterMiddleware], enhancer);
    if (storeOpts && storeOpts.persist) {
        const persisted = {};
        store.subscribe(() => {
            storeOpts.persist.whitelist.forEach((fragment) => {
                const fragmentState = store.getState()[fragment];
                if (fragmentState && persisted[fragment] !== fragmentState) {
                    persisted[fragment] = fragmentState;
                    localStorage.setItem('mapstore2.persist.' + fragment, JSON.stringify(fragmentState));
                }
            });
        });
    }
    SecurityUtils.setStore(store);
    return store;
};
Пример #20
0
const epicMiddleware = () => {
  return createEpicMiddleware(rootEpic)
}
Пример #21
0
const win = typeof window !== 'undefined' ? window : {};
const doc = win.document ? win.document : {};
const devTools = win.devToolsExtension ? win.devToolsExtension() : f => f;

const epicDependencies = {
  window: win,
  document: doc,
  ga: win.ga
};

export const store = createStore(
  createReducer(),
  compose(
    applyMiddleware(createEpicMiddleware(
      (actions, store) => combineEpics(
        appEpic,
        headerEpic
      )(actions, store, epicDependencies)
    )),
    devTools
  )
);

if (doc.getElementById) {
  render(
    createElement(
      Provider,
      { store },
      createElement(App)
    ),
    doc.getElementById('app')
  );
Пример #22
0
import { createStore, applyMiddleware, combineReducers, compose } from 'redux';
import { createEpicMiddleware, combineEpics } from 'redux-observable';
import gameReducer from './game/game.reducer';
import gameEpics from './game/game.epics';

const reducer = combineReducers({
  game: gameReducer,
});

const epics = combineEpics(...gameEpics);

const middleware = applyMiddleware(createEpicMiddleware(epics));

export const createAppStore = (initialValue = {}) => {
  let store;
  if (process.env.NODE_ENV === 'development') {
    // Development mode with Redux DevTools support enabled.
    const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
      // Prevents Redux DevTools from re-dispatching all previous actions.
      shouldHotReload: false,
    }) : compose
    // Create the redux store.
    store = createStore(reducer, initialValue, composeEnhancers(middleware));
  } else {
    // Production mode.
    store = createStore(reducer, initialValue, middleware);
  }
  return store;
};

export default createAppStore;
Пример #23
0
import { createStore, applyMiddleware } from 'redux';
import ReduxThunk from 'redux-thunk';
import { createEpicMiddleware } from 'redux-observable';
import { rootReducer, rootEpic } from './modules/root';
import { routerMiddleware } from 'react-router-redux';
import createHistory from 'history/createBrowserHistory';

const history = createHistory();

const middlewares = [
  ReduxThunk,
  routerMiddleware(history),
  createEpicMiddleware(rootEpic)
];

export default function configureStore(preloadedState = {}) {
  // only inlcude logger in development
  if (process.env.NODE_ENV === 'development') {
    const { createLogger } = require('redux-logger');
    const logger = createLogger();
    middlewares.push(logger);
  }

  const store = createStore(
    rootReducer,
    preloadedState,
    applyMiddleware(...middlewares)
  );

  return { store, history };
}
Пример #24
0
import { createEpicMiddleware } from 'redux-observable';
import rootEpic from '../modules/rootEpic';

export default createEpicMiddleware(rootEpic);
Пример #25
0
describe('discoveryOnStartupEpic', () => {
  let store
  const bus = createBus()
  const epicMiddleware = createEpicMiddleware(discovery.discoveryOnStartupEpic)
  const mockStore = configureMockStore([
    epicMiddleware,
    createReduxMiddleware(bus)
  ])
  beforeAll(() => {
    store = mockStore({
      connections: {}
    })
  })
  afterEach(() => {
    nock.cleanAll()
    bus.reset()
    store.clearActions()
  })

  test('listens on APP_START and tries to find a bolt host and sets it to default when bolt discovery not found', done => {
    // Given
    const action = { type: APP_START }
    nock(getDiscoveryEndpoint())
      .get('/')
      .reply(200, { http: 'http://localhost:7474' })

    bus.take(discovery.DONE, currentAction => {
      // Then
      expect(store.getActions()).toEqual([action, { type: discovery.DONE }])
      done()
    })

    // When
    store.dispatch(action)
  })

  test('listens on APP_START and tries to find a bolt host and sets it to default when fail on server error', done => {
    // Given
    const action = { type: APP_START }
    nock(getDiscoveryEndpoint())
      .get('/')
      .reply(500)

    bus.take(discovery.DONE, currentAction => {
      // Then
      expect(store.getActions()).toEqual([action, { type: discovery.DONE }])
      done()
    })

    // When
    store.dispatch(action)
  })

  test('listens on APP_START and finds a bolt host and dispatches an action with the found host', done => {
    // Given
    const action = { type: APP_START, env: WEB }
    const expectedHost = 'bolt://myhost:7777'
    nock(getDiscoveryEndpoint())
      .get('/')
      .reply(200, { bolt: expectedHost })
    bus.take(discovery.DONE, currentAction => {
      // Then
      expect(store.getActions()).toEqual([
        action,
        discovery.updateDiscoveryConnection({ host: expectedHost }),
        { type: discovery.DONE }
      ])
      done()
    })

    // When
    store.dispatch(action)
  })
  test('listens on APP_START and reads bolt URL from location URL and dispatches an action with the found host', done => {
    // Given
    const action = {
      type: APP_START,
      url: 'http://localhost/?connectURL=myhost:8888'
    }
    const expectedURL = 'myhost:8888'
    bus.take(discovery.DONE, currentAction => {
      // Then
      expect(store.getActions()).toEqual([
        action,
        discovery.updateDiscoveryConnection({ host: expectedURL }),
        currentAction
      ])
      done()
    })

    // When
    store.dispatch(action)
  })
  test('listens on APP_START and reads bolt URL from location URL and dispatches an action with the found host, incl protocol', done => {
    // Given
    const action = {
      type: APP_START,
      url: 'http://localhost/?connectURL=bolt%2Brouting%3A%2F%2Fmyhost%3A8889'
    }
    const expectedURL = 'bolt+routing://myhost:8889'
    bus.take(discovery.DONE, currentAction => {
      // Then
      expect(store.getActions()).toEqual([
        action,
        discovery.updateDiscoveryConnection({ host: expectedURL }),
        currentAction
      ])
      done()
    })

    // When
    store.dispatch(action)
  })
  test('listens on APP_START and reads bolt URL with auth info from location URL and dispatches an action with the found host, incl protocol', done => {
    // Given
    const action = {
      type: APP_START,
      url:
        'http://localhost/?connectURL=bolt%2Brouting%3A%2F%2Fneo4j%3Aneo4j%40myhost%3A8889'
    }
    const expectedURL = 'bolt+routing://myhost:8889'
    bus.take(discovery.DONE, currentAction => {
      // Then
      expect(store.getActions()).toEqual([
        action,
        discovery.updateDiscoveryConnection({
          host: expectedURL,
          username: '******',
          password: '******'
        }),
        currentAction
      ])
      done()
    })

    // When
    store.dispatch(action)
  })
})
Пример #26
0
import mostAdapter from 'redux-observable-adapter-most'

import Root from './containers/Root'
import configureStore from './store/configureStore'
import { rootClientSaga } from './sagas'
import { clientEpic } from './epics'
import QuivadeTheme from './styles/theme'

// Needed for onTouchTap
// Can go away when react 1.0 release
// Check this repo:
// https://github.com/zilverline/react-tap-event-plugin
injectTapEventPlugin()

const epicMiddleware = createEpicMiddleware(
  clientEpic,
  { adapter: mostAdapter }
)
// It is different store enhancer
// than rendering server side
const store = reduxReactRouter({
  createHistory
})(configureStore)(epicMiddleware, window.__INITIAL_STATE__)
store.runSaga(rootClientSaga)

let routes = require('./routes').default
const rootElement = document.getElementById('root')
const rootNode = Base => (
  <AppContainer>
    <Base store={store} routes={routes(QuivadeTheme)} />
  </AppContainer>
)
Пример #27
0
import { createStore, compose, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension/logOnlyInProduction';
import { createEpicMiddleware } from 'redux-observable';
import { ajax } from 'rxjs/observable/dom/ajax';
import { isDev } from '@environment';

import rootReducer, { epics as rootEpic } from '@redux';

const epicMiddleware = createEpicMiddleware(rootEpic, {
    dependencies: { ajax },
});

const enableHMR = (store) => {
    if (isDev() && module.hot) {
        module.hot.accept('@redux', () => {
            store.replaceReducer(rootReducer);
            epicMiddleware.replaceEpic(rootEpic);
        });
    }
};

export default () => {
    const composeEnhancers = isDev() ? composeWithDevTools({}) : compose;

    const store = createStore(
        rootReducer,
        composeEnhancers(applyMiddleware(
            epicMiddleware,
        )),
    );
Пример #28
0

const history = createHistory()

// support for redux dev tools
const compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || reduxCompose

const store = createStore(
  combineReducers({
    router,
    form,
    resource,
    ...reducers,
  }),
  initialState,
  compose(
    applyMiddleware(
      createEpicMiddleware(combineEpics(...epics, resourceEpic), { dependencies: { API } }),
      routerMiddleware(history),
      cacheMiddleware,
    )
  )
)

// FIXME API should not need store
configureAPI(store)

export {
  store, history,
}