@xailabs/altx
Version:
Flux flavor based on alt.js
116 lines (95 loc) • 4.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = bindCalls;
var _decorators = require('alt-utils/lib/decorators');
var _flatten = require('../utils/flatten');
var _flatten2 = _interopRequireDefault(_flatten);
var _logging = require('../utils/logging');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Decorates a store with any number of call definitions.
*/
function bindCalls() {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return function decorate(storeClass) {
var calls = (0, _flatten2.default)(args);
calls.forEach(function (call) {
return decorateStoreWithCall(storeClass, call);
});
return storeClass;
};
}
/**
* Decorates a store with a single call definition.
* Attaches the dataSource specified in the call definition using alt's datasource decorator.
* Creates and binds a handler function for all reducers and actions specified in the call definition.
*/
function decorateStoreWithCall(storeClass, callDefinition) {
var actionNames = Object.keys(callDefinition.actions).reduce(function (result, key) {
// remove ACTION_CONSTANT variants generated by alt
if (result.indexOf(key.toLowerCase()) === -1) {
result.push(key);
}
return result;
}, []);
actionNames.forEach(function (reducerName) {
bindReducerHandler(reducerName, storeClass, callDefinition);
});
}
/**
* Attaches a single reducer handling to the store.
* A new handler method will be created on the store for each action associated
* with a reducer (defaults to the action names: loading, error, success). Each handler will pass
* the current state and the action payload to the reducer with the same name
* and mutate the store with the new state returned by the reducer.
* Any sideEffects defined in the call will be executed with a ({state, prevState, payload}) signature.
*/
function bindReducerHandler(reducerName, storeClass, callDefinition) {
var handlerName = '_' + callDefinition.name + '_' + reducerName;
if (storeClass.prototype[handlerName]) throw new Error('Duplicate handler "' + handlerName + '"');
storeClass.prototype[handlerName] = function handleCallAction(payload) {
var reducer = callDefinition.hasOwnProperty('reducers') && callDefinition.reducers[reducerName];
var sideEffect = callDefinition.hasOwnProperty('sideEffects') && callDefinition.sideEffects[reducerName];
var logging = callDefinition.hasOwnProperty('logging') && callDefinition.logging;
var logger = callDefinition.hasOwnProperty('logger') && callDefinition.logger;
var isError = payload instanceof Error;
if (isError) {
if (payload.response && payload.response.body && payload.response.body.message) {
logger.error(reducerName, payload.response.body.message);
}
// logger.debug(payload);
} else if (logging || (0, _logging.getLevel)() === _logging.logLevel.FORCE) {
logger[isError ? 'error' : 'log'](reducerName, payload && payload.toJS ? payload.toJS() : payload);
}
var currentState = this.state;
var nextState = currentState;
if (reducer) {
//console.log(`[${handlerName}]`, payload, callDefinition);
try {
nextState = reducer(currentState, payload);
} catch (error) {
console.error('Error in reducer (' + callDefinition.name + ', ' + reducerName + ')', error);
}
}
if (reducer && !nextState) console.warn('reducer "' + reducerName + '" in call "' + callDefinition.name + '" did not return a new state. Either you forgot to return it, or you should consider using a sideEffect instead of a reducer if no return value is needed.');
if (nextState) {
this.setState(nextState);
}
if (sideEffect) {
setTimeout(function () {
try {
sideEffect({ state: nextState, prevState: currentState, payload: payload });
} catch (error) {
console.error('Error in sideEffect (' + callDefinition.name + ', ' + reducerName + ')', error);
}
});
}
};
var action = callDefinition.actions[reducerName];
var bindActionHandler = (0, _decorators.bind)(action);
bindActionHandler(storeClass, handlerName, Object.getOwnPropertyDescriptor(storeClass.prototype, handlerName));
};