freeCodeCamp/common/app/create-app.jsx

97 lines
2.6 KiB
JavaScript

import { Observable } from 'rx';
import { match } from 'react-router';
import { compose, createStore, applyMiddleware } from 'redux';
import { createEpic } from 'redux-epic';
import createReducer from './create-reducer';
import createRoutes from './create-routes.js';
import createPanesMap from './create-panes-map.js';
import createPanesAspects from './Panes/redux';
import epics from './epics';
import servicesCreator from '../utils/services-creator';
const createRouteProps = Observable.fromNodeCallback(match);
//
// createApp(settings: {
// location?: Location|String,
// history?: History,
// syncHistoryWithStore?: ((history, store) => history) = (x) => x,
// initialState?: Object|Void,
// serviceOptions?: Object,
// middlewares?: Function[],
// sideReducers?: Object
// enhancers?: Function[],
// epics?: Function[],
// }) => Observable
//
// Either location or history must be defined
export default function createApp({
location,
history,
syncHistoryWithStore = (x) => x,
syncOptions = {},
initialState,
serviceOptions = {},
middlewares: sideMiddlewares = [],
enhancers: sideEnhancers = [],
reducers: sideReducers = {},
epics: sideEpics = [],
epicOptions: sideEpicOptions = {}
}) {
const epicOptions = {
...sideEpicOptions,
services: servicesCreator(serviceOptions)
};
const epicMiddleware = createEpic(
epicOptions,
...epics,
...sideEpics
);
const {
reducer: panesReducer,
middleware: panesMiddleware
} = createPanesAspects(createPanesMap());
const enhancer = compose(
applyMiddleware(
panesMiddleware,
epicMiddleware,
...sideMiddlewares
),
// enhancers must come after middlewares
// on client side these are things like Redux DevTools
...sideEnhancers
);
const reducer = createReducer(
{
[panesReducer]: panesReducer,
...sideReducers
},
);
// create composed store enhancer
// use store enhancer function to enhance `createStore` function
// call enhanced createStore function with reducer and initialState
// to create store
const store = createStore(reducer, initialState, enhancer);
// sync history client side with store.
// server side this is an identity function and history is undefined
history = syncHistoryWithStore(history, store, syncOptions);
const routes = createRoutes(store);
// createRouteProps({
// redirect: LocationDescriptor,
// history: History,
// routes: Object
// }) => Observable
return createRouteProps({ routes, location, history })
.map(([ redirect, props ]) => ({
redirect,
props,
reducer,
store,
epic: epicMiddleware
}));
}