action-store
Version:
Action store a la redux
174 lines (143 loc) • 3.5 kB
JavaScript
;
/**
* Module dependencies.
*/
Object.defineProperty(exports, "__esModule", {
value: true
});
var _constants = require('./constants');
var _lodash = require('lodash');
var _vo = require('vo');
var _vo2 = _interopRequireDefault(_vo);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
/**
* Module constants.
*/
var clone = function clone(obj) {
return JSON.parse(JSON.stringify(obj));
};
/**
* Context creator initializer.
*
* @param {Object} options
* @return {Function}
* @api public
*/
exports.default = function (options) {
var store = options.store;
var engine = options.engine;
var emit = options.emit;
var contexts = {};
/**
* Create a new context.
*
* @param {String} id
* @return {Object}
* @api public
*/
function context(id) {
var status = _constants.EMPTY;
var queue = [];
var history = [];
var counter = 0;
/**
* Load history of actions of this context id.
*
* @param {Function} fn
* @return {Promise}
* @api public
*/
function load(fn) {
status = _constants.LOADING;
return (0, _vo2.default)(engine.load)(id).then(function (actions) {
status = _constants.REPLAYING;
history = [].concat(_toConsumableArray(history), _toConsumableArray(actions));
var action = (0, _lodash.last)(history);
counter = action && action.version || counter;
clone(actions).map(store.dispatch);
status = _constants.LOADED;
drain(fn());
});
}
/**
* Persist an action.
*
* @param {Object} action
* @param {Function} [fn]
* @return {Promise}
* @api public
*/
function save(action, fn) {
return (0, _vo2.default)(engine.save)(normalize(action)).then(fn);
}
/**
* Publish state and action as an event.
*
* @param {Object} action
* @return {Object} action
* @api public
*/
function publish(action) {
emit(action.type, state(), action);
emit('event', state(), action);
return action;
}
/**
* Return current state.
*
* @return {Mixed}
* @api public
*/
function state() {
return store.getState()[id];
}
/**
* Add an action function to queue.
*
* @param {Function} fn
* @return {Array}
* @api public
*/
function enqueue(fn) {
return queue.push(fn);
}
/**
* Drain queue.
*
* @return {Void}
* @api private
*/
function drain() {
while (queue.length) {
queue.shift()();
}
}
/**
* Normalize action.
*
* @param {Object} action
* @return {Object}
* @api private
*/
function normalize(action) {
action.version = counter++;
action.timestamp = Date.now();
return action;
}
// return context public methods.
return {
load: load, save: save, enqueue: enqueue, publish: publish,
get status() {
return status;
},
get state() {
return state();
}
};
}
// return context or create a new one and return it
return function (id) {
return contexts[id] = contexts[id] || context(id);
};
};