webamp/js/store.ts
2019-05-21 17:19:00 -07:00

72 lines
1.9 KiB
TypeScript

import { createStore, applyMiddleware, DeepPartial } from "redux";
import thunk from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension";
import reducer from "./reducers";
import mediaMiddleware from "./mediaMiddleware";
import { merge } from "./utils";
import { UPDATE_TIME_ELAPSED, STEP_MARQUEE } from "./actionTypes";
import Media from "./media";
import Emitter from "./emitter";
import { Extras, Dispatch, Action, AppState, Middleware } from "./types";
import {
createEpicMiddleware,
combineEpics,
EpicMiddleware,
} from "redux-observable";
import * as Epics from "./epics";
// TODO: Move to demo
const compose = composeWithDevTools({
actionsBlacklist: [UPDATE_TIME_ELAPSED, STEP_MARQUEE],
});
export default function(
media: Media,
actionEmitter: Emitter,
customMiddlewares: Middleware[] = [],
stateOverrides: DeepPartial<AppState> | undefined,
extras: Extras
) {
let initialState;
if (stateOverrides) {
initialState = merge(
reducer(undefined, { type: "@@init" }),
stateOverrides
);
}
const emitterMiddleware = () => (next: Dispatch) => (action: Action) => {
actionEmitter.trigger(action.type, action);
return next(action);
};
const epicMiddleware: EpicMiddleware<
Action,
Action,
AppState,
Extras
> = createEpicMiddleware({
dependencies: extras,
});
const enhancer = compose(
applyMiddleware(
...[
thunk.withExtraArgument(extras),
epicMiddleware,
mediaMiddleware(media),
emitterMiddleware,
...customMiddlewares,
].filter(Boolean)
)
);
// The Redux types are a bit confused, and don't realize that passing an
// undefined initialState is allowed.
const store = initialState
? createStore(reducer, initialState, enhancer)
: createStore(reducer, enhancer);
epicMiddleware.run(combineEpics(...Object.values(Epics)));
return store;
}