UNPKG

flexy

Version:

A Flux library based on Channels and reducer functions

382 lines (323 loc) 13 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); exports.defineStore = defineStore; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function _defineProperty(obj, key, value) { return Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _immutable = require('immutable'); var _immutable2 = _interopRequireDefault(_immutable); var _jsCsp = require('js-csp'); var _transducersJs = require('transducers.js'); function defineStore(_ref) { var _ref$primaryKey = _ref.primaryKey; var primaryKey = _ref$primaryKey === undefined ? 'id' : _ref$primaryKey; var consumers = _ref.consumers; var transformers = _ref.transformers; var ctx = _objectWithoutProperties(_ref, ['primaryKey', 'consumers', 'transformers']); return (function () { var _class = function (initialData, ctx2) { _classCallCheck(this, _class); this.data = !initialData ? _immutable2['default'].Map() : Array.isArray(initialData) && primaryKey ? _immutable2['default'].fromJS(initialData.reduce(function (collection, obj) { return Object.assign(collection, _defineProperty({}, obj[primaryKey], obj)); }, {})) : typeof initialData === 'object' ? _immutable2['default'].fromJS(initialData) : _immutable2['default'].Map(); this.context = _transducersJs.merge({}, ctx, ctx2); this.reducers = _immutable2['default'].OrderedMap(); this.inCh = _jsCsp.chan(); this.outCh = _jsCsp.chan(_jsCsp.buffers.fixed(100), _transducersJs.compose(_transducersJs.dedupe())); this.outMult = _jsCsp.operations.mult(this.outCh); this.sources = _immutable2['default'].Set(); this.throughCh = _jsCsp.chan(_jsCsp.buffers.fixed(100)); this.throughMult = _jsCsp.operations.mult(this.throughCh); }; _createClass(_class, [{ key: 'toJSON', value: function toJSON() { return JSON.stringify(this.data); } }, { key: 'subscribeTo', value: function subscribeTo(dispatcher) { dispatcher.subscribe(this.handleAction, this); return this; } }, { key: 'unsubscribeFrom', value: function unsubscribeFrom(dispatcher) { dispatcher.unsubscribe(this.handleAction, this); return this; } }, { key: 'listen', value: function listen(source) { if (source.outMult && source.throughMult) { source = source.throughMult; } else if (source.outMult) { source = source.outMult; } var ch = _jsCsp.chan(); var that = this; _jsCsp.operations.mult.tap(source, ch); _jsCsp.go(regeneratorRuntime.mark(function callee$3$0() { var value; return regeneratorRuntime.wrap(function callee$3$0$(context$4$0) { while (1) switch (context$4$0.prev = context$4$0.next) { case 0: context$4$0.next = 2; return _jsCsp.take(ch); case 2: value = context$4$0.sent; case 3: if (!(value !== _jsCsp.CLOSED)) { context$4$0.next = 10; break; } that.handleAction(value); context$4$0.next = 7; return _jsCsp.take(ch); case 7: value = context$4$0.sent; context$4$0.next = 3; break; case 10: case 'end': return context$4$0.stop(); } }, callee$3$0, this); })); return this; } }, { key: 'trigger', value: function trigger() { // const oldData = this.data var fnsToApply = this.reducers.takeWhile(function (v) { return v > 0; }); this.reducers = this.reducers.skipWhile(function (v) { return v > 0; }).filter(function (v) { return v >= 0; }); this.data = fnsToApply.reduce(function (value, val, fn) { return fn(value); }, this.data); var dataToSend = this.reducers.reduce(function (value, val, fn) { return fn(value); }, this.data); _jsCsp.putAsync(this.outCh, dataToSend); } }, { key: 'getObservable', value: function getObservable(transformer, onUndefined) { transformer = transformer || function (a) { return a; }; var that = this; return { subscribe: function subscribe(onNext, onError, onCompleted) { var initialData = transformer(that.reducers.filter(function (v) { return v >= 0; }).reduce(function (value, val, fn) { return fn(value); }, that.data)); if (initialData === undefined) { typeof onUndefined === 'function' && onUndefined(); onNext(undefined); } else { onNext(initialData); } var tempCh = _jsCsp.chan(); _jsCsp.operations.mult.tap(that.outMult, tempCh); var completed = false; _jsCsp.go(regeneratorRuntime.mark(function callee$4$0() { var value; return regeneratorRuntime.wrap(function callee$4$0$(context$5$0) { while (1) switch (context$5$0.prev = context$5$0.next) { case 0: context$5$0.prev = 0; context$5$0.next = 3; return _jsCsp.take(tempCh); case 3: value = context$5$0.sent; case 4: if (!(value !== _jsCsp.CLOSED)) { context$5$0.next = 11; break; } onNext(transformer(value)); context$5$0.next = 8; return _jsCsp.take(tempCh); case 8: value = context$5$0.sent; context$5$0.next = 4; break; case 11: if (completed) { onCompleted(); } context$5$0.next = 17; break; case 14: context$5$0.prev = 14; context$5$0.t0 = context$5$0['catch'](0); onError(context$5$0.t0); case 17: case 'end': return context$5$0.stop(); } }, callee$4$0, this, [[0, 14]]); })); return { dispose: function dispose() { _jsCsp.operations.mult.untap(that.outMult, tempCh); tempCh.close(); } }; } }; } }, { key: 'subscribe', value: function subscribe(onNext, onError, onCompleted) { var tempCh = _jsCsp.chan(); _jsCsp.operations.mult.tap(this.outMult, tempCh); var completed = false; _jsCsp.go(regeneratorRuntime.mark(function callee$3$0() { var value; return regeneratorRuntime.wrap(function callee$3$0$(context$4$0) { while (1) switch (context$4$0.prev = context$4$0.next) { case 0: context$4$0.prev = 0; context$4$0.next = 3; return _jsCsp.take(tempCh); case 3: value = context$4$0.sent; case 4: if (!(value !== _jsCsp.CLOSED)) { context$4$0.next = 11; break; } onNext(value); context$4$0.next = 8; return _jsCsp.take(tempCh); case 8: value = context$4$0.sent; context$4$0.next = 4; break; case 11: if (completed) { onCompleted(); } context$4$0.next = 17; break; case 14: context$4$0.prev = 14; context$4$0.t1 = context$4$0['catch'](0); onError(context$4$0.t1); case 17: case 'end': return context$4$0.stop(); } }, callee$3$0, this, [[0, 14]]); })); return { dispose: function dispose() { _jsCsp.operations.mult.untap(this.outMult, tempCh); tempCh.close(); } }; } }, { key: 'tap', value: function tap(channel) { _jsCsp.operations.mult.tap(this.outMult, channel); return this; } }, { key: 'untap', value: function untap(channel) { _jsCsp.operations.mult.untap(this.outMult, channel); return this; } }, { key: 'handleAction', value: function handleAction(action) { var _this = this; var that = this; var name = action.name; var payload = action.payload; var promise = action.promise; // in case of full consumer. We provide, (controls, action) // controls is an object of three functions — apply, commit, and reject // in case of sync operations, the consumer is expected to call apply with a reducer function and then immediately call commit // in case of async ops, the consumer should call apply with a reducer function. Then if the async op is successful call commit, // if the async operation fails, reject should be called. This will roll back the change. if (consumers[name]) { (function () { var cached = null; consumers[name].call(_this.context, { apply: function apply(fn) { if (cached) { that.reducers = that.reducers.set(cached, -1); } cached = fn; that.reducers = that.reducers.set(fn, 0); that.trigger(); }, commit: function commit() { if (!cached) { return false; } that.reducers = that.reducers.set(cached, 1); that.trigger(); cached = null; _jsCsp.putAsync(that.throughCh, action); return true; }, reject: function reject() { if (!cached) { return false; } that.reducers = that.reducers.set(cached, -1); that.trigger(); cached = null; _jsCsp.putAsync(that.throughCh, action); return true; } }, { payload: payload, promise: promise }); })(); } else if (transformers[name]) { (function () { var cached = function cached(data) { return transformers[name].call(_this.context, data, payload); }; that.reducers = that.reducers.set(cached, 0); if (promise) { that.trigger(); promise.then(function () { that.reducers = that.reducers.set(cached, 1); that.trigger(); _jsCsp.putAsync(that.throughCh, action); })['catch'](function (err) { that.reducers = that.reducers.set(cached, -1); that.trigger(); console.error(err); _jsCsp.putAsync(that.throughCh, action); }); } else { that.reducers = that.reducers.set(cached, 1); that.trigger(); _jsCsp.putAsync(that.throughCh, action); } })(); } else { _jsCsp.putAsync(that.throughCh, action); } } }]); return _class; })(); }