kaa
Version:
Actions wrapper for React JS, Mowgli and The Jungle
72 lines (53 loc) • 2.52 kB
JavaScript
;
import {getCursorFns, mapObj, navigatePath, callIfFunction, throwError} from 'junglejs-common';
export default class Actions {
constructor(tree, baseUrl, definition, defaults, allActions = this) {
if (!tree) throwError(`Must provide a tree object to Actions that encapsulates all application state`);
const {path, url, actions} = definition ? definition : throwError(`Must provide a definition object to Actions that details all actions over the tree`);
// give access to the root actions node
this.getAllActions = () => allActions;
// give actions access to the whole tree
this.getTree = () => tree;
// set cursor prop to a function returning the cursor
path && (this.getCursor = getCursorFn(tree, path));
// set url prop to a function returning the full url
url && (this.getUrl = getUrlFn(tree, path, baseUrl, url));
// set a prop for each action
actions && this._setActions__(actions, defaults);
// set all remaining props on the definition to a prop on this
this._setChildren__(tree, baseUrl, definition, defaults, allActions);
}
_setActions__(actions, defaults) {
if (typeof actions !== 'object') throwError(`Defined actions must to be an object`);
// set a prop on this for each action
mapObj(getActions(actions, defaults), (v, k) =>
this[k] = typeof v === 'function' ? v.bind(this) : throwError(`Action '${k}' must be a function`)
);
}
_setChildren__(tree, baseUrl, definition, defaults, allActions) {
const keyProps = ['path', 'url', 'actions'];
// create a new actions object and set a prop on this for each remaining prop in the definition
mapObj(definition, (v, k) =>
keyProps.indexOf(k) < 0 ? this[k] = new Actions(tree, baseUrl, v, defaults, allActions) : null
);
}
}
const getCursorFn = (tree, path) => {
const getFn = getCursorFns(tree).get;
// resolve the cursor and return the value
return (...args) => navigatePath(callIfFunction(path, ...args), tree, getFn);
};
const getUrlFn = (tree, path, baseUrl, url) => {
// resolve the url and return the full url
return (...args) => baseUrl + callIfFunction(url, ...args);
};
const getActions = (actions, defaults) => {
// return the map of actions after setting any defaults
return mapObj(actions, (v, k) =>
v === true ? getDefaultAction(k, defaults) : v
);
};
const getDefaultAction = (name, defaults) => {
const defaultAction = defaults && defaults[name];
return defaultAction ? defaultAction : throwError(`Default action '${name}' used but not defined`);
};