fluorine-lib
Version:
Reactive state and side effect management for React using a single stream of actions
215 lines (139 loc) • 5.53 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Dispatcher = Dispatcher;
exports.default = createDispatcher;
var _Subject = require('rxjs/Subject');
var Subject = _Subject.Subject;
var _Observable = require('rxjs/Observable');
var Observable = _Observable.Observable;
var _BehaviorSubject = require('rxjs/BehaviorSubject');
var BehaviorSubject = _BehaviorSubject.BehaviorSubject;
var _of = require('rxjs/observable/of');
var of = _of.of;
var _concat = require('rxjs/operator/concat');
var concat = _concat.concat;
var _map = require('rxjs/operator/map');
var map = _map.map;
var _mergeMap = require('rxjs/operator/mergeMap');
var mergeMap = _mergeMap.mergeMap;
var _distinctUntilChanged = require('rxjs/operator/distinctUntilChanged');
var distinctUntilChanged = _distinctUntilChanged.distinctUntilChanged;
var _publishReplay = require('rxjs/operator/publishReplay');
var publishReplay = _publishReplay.publishReplay;
var _subscribeOn = require('rxjs/operator/subscribeOn');
var subscribeOn = _subscribeOn.subscribeOn;
var _share = require('rxjs/operator/share');
var share = _share.share;
var _filter = require('rxjs/operator/filter');
var filter = _filter.filter;
var _catch2 = require('rxjs/operator/catch');
var _catch = _catch2._catch;
var _state = require('./util/state');
var createState = _state.createState;
var filterActions = _state.filterActions;
var _logger = require('./util/logger');
var parseOpts = _logger.parseOpts;
var logAgendas = _logger.logAgendas;
var logStore = _logger.logStore;
var _assert = require('./util/assert');
var assert = _interopRequireDefault(_assert).default;
var _wrapActions = require('./util/wrapActions');
var wrapActions = _interopRequireDefault(_wrapActions).default;
var _toObservable = require('./util/toObservable');
var toObservable = _interopRequireDefault(_toObservable).default;
var _isObservable = require('./util/isObservable');
var isObservable = _interopRequireDefault(_isObservable).default;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var KICKSTART_ACTION = { type: '_INIT_' };
function Dispatcher() {
var _this = this;
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var middlewares = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
Subject.call(this);
this.keyCache = [];
this.valCache = [];
this.middlewares = [].concat(middlewares).map(function (x) {
return x(_this);
});
// Options: Logging
this.logging = parseOpts(opts.logging);
if (this.logging.agendas) {
logAgendas(this);
}
this.reduce = this.reduce.bind(this);
this.rawNext = this.rawNext.bind(this);
this.next = this.next.bind(this);
}
// Inherit from Rx.Subject
Dispatcher.prototype = Object.create(Subject.prototype);
Dispatcher.prototype.constructor = Dispatcher;
Dispatcher.prototype.reduce = function reduce(fn, init) {
var _context;
var keyCache = this.keyCache,
valCache = this.valCache,
logging = this.logging;
var index = keyCache.indexOf(fn);
if (index > -1) {
return valCache[index].store;
}
// Create cursor pointing to the state history
var cursor = createState(fn, fn(init, KICKSTART_ACTION));
// Describe states using the series of agendas
var store = (_context = (_context = (_context = of(cursor.state), concat).call(_context, mergeMap.call(this, function (agenda) {
var _context2;
// Reference agenda's root state
var anchor = cursor;
// Collect agenda's actions
var actions = [];
// Prepare agenda logger if necessary
var logger = logging.stores ? logStore(fn.name || index, agenda) : null;
// Map Agenda to consecutive states and catch errors
return (_context2 = (_context2 = map.call(agenda, function (action) {
cursor = cursor.doNext(action);
actions.push(action);
if (logger) {
logger.change(action, cursor.state); // Logging new state by action
}
return cursor.state;
}), _catch).call(_context2, function (err) {
if (!logger) {
console.error(err);
}
// Filter past actions by all of the failed agenda
var previousState = cursor.state;
filterActions(anchor, function (x) {
return actions.indexOf(x) === -1;
});
if (logger) {
logger.revert([previousState, cursor.state], err, actions); // Logging reversion
}
return of(cursor.state);
}), distinctUntilChanged).call(_context2);
})), distinctUntilChanged).call(_context), publishReplay).call(_context, 1);
var subscription = store.connect();
// Cache the store
var key = keyCache.length;
keyCache.push(fn);
valCache[key] = { store: store, subscription: subscription };
return store;
};
// Save subject's normal next method
Dispatcher.prototype.rawNext = Dispatcher.prototype.next;
Dispatcher.prototype.next = function next(arg) {
var _context3;
var middlewares = this.middlewares;
var agenda = (_context3 = toObservable(arg), share).call(_context3);
for (var i = 0; i < middlewares.length; i++) {
var middleware = middlewares[i];
agenda = middleware(agenda);
if (!isObservable(agenda)) {
return undefined;
}
}
return this.rawNext((_context3 = (_context3 = agenda, filter).call(_context3, Boolean), publishReplay).call(_context3).refCount());
};
function createDispatcher(opts, middlewares) {
return new Dispatcher(opts, middlewares);
}