typedux
Version:
Slightly adjusted Redux (awesome by default) for TS
163 lines • 4.89 kB
JavaScript
import { Option } from "@3fv/prelude-ts";
import { isNotEmpty } from "../util";
import { getGlobalStore, createLeafActionType } from "./Actions";
import { getLogger } from "@3fv/logger-proxy";
import * as ID from "shortid";
import { isDefined, isFunction } from "@3fv/guard";
import * as Immutable from "immutable";
import { clone, uniqBy } from "lodash";
import { isDev } from "../dev";
const log = getLogger(__filename);
/**
* Base class for action implementations for a given state
*
*/
class BaseActionFactory {
/**
* Create a new action factory that consumes and produces a specific
* state type
*
* @param stateType
* @param withStore
*/
constructor(stateType, withStore = undefined) {
if (log.isDebugEnabled() && isDev) {
log.debug(`Created action factory with state type: ${stateType.name}`);
}
this.stateType = stateType;
this.store = withStore;
this.pushStoreActions();
}
pushStoreActions() {
var _a;
Option.ofNullable((_a = this.store) === null || _a === void 0 ? void 0 : _a.actionContainer)
.ifSome(actions => {
this.actions.forEach(actions.registerAction.bind(actions));
});
}
/**
* @inheritDoc
*/
get actions() {
return uniqBy([...this.actionMap.values()], ({ fullName }) => fullName);
}
getAction(leafOrFullName, type) {
return [leafOrFullName, createLeafActionType(leafOrFullName, type)]
.map(key => this.actionMap.get(key))
.filter(isDefined)[0];
}
/**
* @inheritDoc
*/
registerAction(reg) {
var _a;
const map = this.actionMap = (_a = this.actionMap) !== null && _a !== void 0 ? _a : new Map();
Array(reg.fullName, reg.type)
.forEach(key => map.set(key, reg));
this.pushStoreActions();
return reg;
}
getStore() {
var _a, _b;
return (_b = (_a = this.store) !== null && _a !== void 0 ? _a : BaseActionFactory.clazzStore) !== null && _b !== void 0 ? _b : getGlobalStore();
}
/**
* Get the current dispatcher
*
* Implemented for the purpose of thunks
* etc where the dispatcher can be augmented
*
* @returns {Function|(function(any): any)}
*/
get dispatcher() {
const store = this.getStore();
if (!store || !isFunction(store.dispatch)) {
throw new Error("Global dispatcher must be set before any actions occur");
}
return ((action) => store.dispatch(action));
}
/**
* Retrieve the current state using the global
* getState or the augmented one
*
* directly applicable to @see dispatcher
*
* @returns instance of the state supported by this factory
*/
get state() {
const store = this.getStore();
//const getStoreState = getGlobalStateProvider()
const state = store === null || store === void 0 ? void 0 : store.getState();
if (!state)
return null;
const leaf = this.leaf();
return !leaf
? state
: Immutable.Map.isMap(state)
? state.get(leaf)
: state[leaf];
}
/**
* withDispatcher creates a new instance of
* this action implementation with a
* new dispatcher and optionally a new
* getState
*
* @returns {any}
* @param newStore
*/
withStore(newStore) {
let instance = clone(this);
instance.setStore(newStore);
return instance;
}
/**
* Set the store for action factory
*
* @param newStore
* @return {this<S, M>}
*/
setStore(newStore) {
this.store = newStore;
this.pushStoreActions();
return this;
}
/**
* Create a new action message object that
* fits the shape defined by the generic M
*
* @param id
* @param type
* @param reducers
* @param data
* @param args
* @param leaf
*/
newMessage(id, leaf, type, reducers = [], args = [], data = {}) {
return Object.assign({
id: Option.ofNullable(id)
.filter(isNotEmpty)
.getOrCall(() => ID.generate()),
leaf,
type: createLeafActionType(this.leaf(), type),
reducers,
args,
stateType: this.stateType
}, data);
}
/**
* setError action applies to all states
*
* @param error
*/
//@ActionThunk()
setError(error) { }
}
(function (BaseActionFactory) {
function setStore(newClazzStore) {
BaseActionFactory.clazzStore = newClazzStore;
}
BaseActionFactory.setStore = setStore;
})(BaseActionFactory || (BaseActionFactory = {}));
export { BaseActionFactory };
//# sourceMappingURL=BaseActionFactory.js.map