Comparing version 1.4.1 to 1.4.2
@@ -63,3 +63,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function e(e,t){for(var i=0;i<t.length;i++){var n=t[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,i,n){return i&&e(t.prototype,i),n&&e(t,n),t}}();Object.defineProperty(exports,"__esModule",{value:!0});var _Queue=__webpack_require__(2),_Queue2=_interopRequireDefault(_Queue),noop=function(){},Domain=function(){function e(t,i){_classCallCheck(this,e),this.view=null,this.data=null,this._actionNames=null,this._claimView(t),this._claimActions(i)}return _createClass(e,[{key:"_claimView",value:function(e){if(!e.isReactor)throw new Error("view is not inheriting Reactor type");this.view=e,e.isData&&(this.data=e)}},{key:"_claimActions",value:function(e){var t=this;this._actionNames=e?Object.keys(e):[],this._actionNames.forEach(function(i){if(t[i])throw new Error('"'+i+'" is reserved for Domain interface');t[i]=_Queue2["default"].createAction(e[i],t)})}},{key:"read",value:function(){return this.view.read()}},{key:"map",value:function(e){return this.view.map(e)}},{key:"subscribe",value:function(e){return this.view.subscribe(e)}},{key:"appendReactor",value:function(e){return this.view.appendReactor(e)}},{key:"destroy",value:function(){var e=this;this.view.destroy(),this.view=null,this.data=null,_Queue2["default"].rejectContext(this),this._actionNames.forEach(function(t){e[t]=noop}),this._actionNames=null}},{key:"structure",get:function(){return this.view&&this.view.structure}},{key:"isDomain",get:function(){return!0}}]),e}();exports["default"]=Domain; | ||
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}();Object.defineProperty(exports,"__esModule",{value:!0});var _Queue=__webpack_require__(2),_Queue2=_interopRequireDefault(_Queue),noop=function(){return null},errorPrefix="Immview::Domain: ",Domain=function(){function e(t,r){_classCallCheck(this,e),this._claimStream(t),this._claimActions(r)}return _createClass(e,[{key:"_claimStream",value:function(e){if(e.isReactor)return void(this.stream=e);throw new Error(errorPrefix+" provided stream is not inheriting from Reactor class")}},{key:"_claimActions",value:function(e){var t=this;this._actionNames=e?Object.keys(e):[],this._actionNames.forEach(function(r){if(t[r])throw new Error(""+errorPrefix+r+" is reserved for Domain interface");if("function"!=typeof e[r])throw new Error(""+errorPrefix+r+" action is not a function");t[r]=_Queue2["default"].createAction(e[r],t)})}},{key:"read",value:function(){return this.stream.read()}},{key:"map",value:function(e){return this.stream.map(e)}},{key:"subscribe",value:function(e){return this.stream.subscribe(e)}},{key:"appendReactor",value:function(e){return this.stream.appendReactor(e)}},{key:"destroy",value:function(){var e=this;this.stream.destroy(),this.stream=null,_Queue2["default"].rejectContext(this),this._actionNames.forEach(function(t){e[t]=noop}),this._actionNames=null}},{key:"structure",get:function(){return this.read()}},{key:"isDomain",get:function(){return!0}}]),e}();exports["default"]=Domain; | ||
@@ -70,3 +70,3 @@ /***/ }, | ||
"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var u in e)Object.prototype.hasOwnProperty.call(e,u)&&(n[u]=e[u]);return n["default"]=e,n}function createAction(e,n){return function(){for(var u=arguments.length,r=Array(u),t=0;u>t;t++)r[t]=arguments[t];appendAndRunQueue(e,n,r)}}function appendToQueue(e,n,u){queue=queue.add({action:e,context:n,args:u})}function appendAndRunQueue(e,n,u){appendToQueue(e,n,u),run()}function shiftFromQueue(){var e=queue.first();return queue=queue.rest(),e}function rejectContext(e){queue=queue.filter(function(n){return n.context!==e})}function run(){if(!isRunning){for(isRunning=!0;queue.count()>0;)try{runFirst()}catch(e){console.error("Immview.Queue run - Error occured while running running a function"),console.error(e.message)}isRunning=!1}}function runFirst(){var e=shiftFromQueue(),n=e.context,u=e.action,r=e.args;u.apply(n,r)}Object.defineProperty(exports,"__esModule",{value:!0});var _immutable=__webpack_require__(3),I=_interopRequireWildcard(_immutable),isRunning=!1,queue=I.OrderedSet();exports["default"]={createAction:createAction,rejectContext:rejectContext,appendAndRunQueue:appendAndRunQueue}; | ||
"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var r={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(r[n]=e[n]);return r["default"]=e,r}function _typeof(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e}function createAction(e,r){return function(){for(var n=arguments.length,u=Array(n),t=0;n>t;t++)u[t]=arguments[t];runInQueue(e,r,u)}}function appendToQueue(e,r,n){queue=queue.add({action:e,context:r,args:n})}function runInQueue(e,r,n){appendToQueue(e,r,n),startQueue()}function shiftFromQueue(){var e=queue.first();return queue=queue.rest(),e}function rejectContext(e){queue=queue.filter(function(r){return r.context!==e})}function startQueue(){if(!isRunning){for(isRunning=!0;queue.count()>0;)try{tick(runFirst)}catch(e){logError(e)}isRunning=!1}}function tick(e){e()}function logError(e){console.error(errorPrefix+"Error occured while running a function"),"object"===("undefined"==typeof e?"undefined":_typeof(e))?e.stack?console.error(e.stack):console.error(e.name,e.message):console.error(e)}function runFirst(){var e=shiftFromQueue(),r=e.context,n=e.action,u=e.args;n.apply(r,u)}Object.defineProperty(exports,"__esModule",{value:!0});var _immutable=__webpack_require__(3),I=_interopRequireWildcard(_immutable),isRunning=!1,queue=I.OrderedSet(),errorPrefix="Immview::Queue: ";exports["default"]={createAction:createAction,rejectContext:rejectContext,runInQueue:runInQueue}; | ||
@@ -83,3 +83,3 @@ /***/ }, | ||
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t["default"]=e,t}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}();Object.defineProperty(exports,"__esModule",{value:!0});var _immutable=__webpack_require__(3),I=_interopRequireWildcard(_immutable),_Queue=__webpack_require__(2),_Queue2=_interopRequireDefault(_Queue),_View=__webpack_require__(5),_View2=_interopRequireDefault(_View),_Reactor2=__webpack_require__(6),_Reactor3=_interopRequireDefault(_Reactor2),Data=function(e){function t(e){_classCallCheck(this,t);var r=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this));return I.Iterable.isIterable(e)?r.digest(e):r.digest(I.fromJS(e)),r}return _inherits(t,e),_createClass(t,[{key:"write",value:function(e){"function"==typeof e?_Queue2["default"].appendAndRunQueue(function(){this.digest(e.apply(this,[this.read()]))},this,[e]):_Queue2["default"].appendAndRunQueue(this.digest,this,[e])}},{key:"map",value:function(e){return new _View2["default"](this,e)}},{key:"isData",get:function(){return!0}}]),t}(_Reactor3["default"]);exports["default"]=Data; | ||
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var u=t[r];u.enumerable=u.enumerable||!1,u.configurable=!0,"value"in u&&(u.writable=!0),Object.defineProperty(e,u.key,u)}}return function(t,r,u){return r&&e(t.prototype,r),u&&e(t,u),t}}();Object.defineProperty(exports,"__esModule",{value:!0});var _immutable=__webpack_require__(3),_Queue=__webpack_require__(2),_Queue2=_interopRequireDefault(_Queue),_View=__webpack_require__(5),_View2=_interopRequireDefault(_View),_Reactor2=__webpack_require__(6),_Reactor3=_interopRequireDefault(_Reactor2),Data=function(e){function t(e){_classCallCheck(this,t);var r=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this));return _immutable.Iterable.isIterable(e)?r.digest(e):r.digest((0,_immutable.fromJS)(e)),r}return _inherits(t,e),_createClass(t,[{key:"write",value:function(e){var t=this;"function"==typeof e?_Queue2["default"].runInQueue(function(){return t.digest(e(t.read()))},this):_Queue2["default"].runInQueue(this.digest,this,[e])}},{key:"map",value:function(e){return new _View2["default"](this,e)}},{key:"isData",get:function(){return!0}}]),t}(_Reactor3["default"]);exports["default"]=Data; | ||
@@ -90,3 +90,3 @@ /***/ }, | ||
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t["default"]=e,t}function _typeof(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var _createClass=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}();Object.defineProperty(exports,"__esModule",{value:!0});var _immutable=__webpack_require__(3),I=_interopRequireWildcard(_immutable),_Reactor2=__webpack_require__(6),_Reactor3=_interopRequireDefault(_Reactor2),pass=function(e){return e},View=function(e){function t(e){var n=arguments.length<=1||void 0===arguments[1]?pass:arguments[1];_classCallCheck(this,t);var r=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this));return e&&"object"===("undefined"==typeof e?"undefined":_typeof(e))&&(e.isReactor||e.isDomain?r.connectToView(e,n):r.connectToViews(e,n)),r}return _inherits(t,e),_createClass(t,[{key:"connectToView",value:function(e,t){var n=this;this.unsubs=[e.subscribe(function(e){return n.digest(t(e))})]}},{key:"connectToViews",value:function(e,t){var n=this,r=I.Map(),o=Object.keys(e);o.forEach(function(t){var n=e[t].read();n&&(r=r.set(t,n))});var u=function(){return n.digest(t(r))};this.unsubs=o.map(function(t){return e[t].appendReactor(function(e){r=r.set(t,e),u()})}),u()}},{key:"destroy",value:function(){_Reactor3["default"].prototype.destroy.call(this),this.unsubs&&this.unsubs.forEach(function(e){return e()}),this.unsubs=null}},{key:"map",value:function(e){return new t(this,e)}},{key:"isView",get:function(){return!0}}]),t}(_Reactor3["default"]);exports["default"]=View; | ||
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _typeof(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var _createClass=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}();Object.defineProperty(exports,"__esModule",{value:!0});var _immutable=__webpack_require__(3),_Reactor2=__webpack_require__(6),_Reactor3=_interopRequireDefault(_Reactor2),bypass=function(e){return e},View=function(e){function t(e){var n=arguments.length<=1||void 0===arguments[1]?bypass:arguments[1];_classCallCheck(this,t);var r=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this));return e&&"object"===("undefined"==typeof e?"undefined":_typeof(e))&&(e.isReactor||e.isDomain?r.connectToView(e,n):r.connectToViews(e,n)),r}return _inherits(t,e),_createClass(t,[{key:"connectToView",value:function(e,t){var n=this;this.unsubs=[e.subscribe(function(e){return n.digest(t(e))})]}},{key:"connectToViews",value:function(e,t){var n=this,r=(0,_immutable.Map)(),o=Object.keys(e);o.forEach(function(t){var n=e[t].read();n&&(r=r.set(t,n))});var u=function(){return n.digest(t(r))};this.unsubs=o.map(function(t){return e[t].appendReactor(function(e){r=r.set(t,e),u()})}),u()}},{key:"map",value:function(e){return new t(this,e)}},{key:"destroy",value:function(){_Reactor3["default"].prototype.destroy.call(this),this.unsubs&&this.unsubs.forEach(function(e){return e()}),this.unsubs=null}},{key:"isView",get:function(){return!0}}]),t}(_Reactor3["default"]);exports["default"]=View; | ||
@@ -97,3 +97,3 @@ /***/ }, | ||
"use strict";function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function hasValue(e){return void 0!==e&&null!==e}var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var u=t[r];u.enumerable=u.enumerable||!1,u.configurable=!0,"value"in u&&(u.writable=!0),Object.defineProperty(e,u.key,u)}}return function(t,r,u){return r&&e(t.prototype,r),u&&e(t,u),t}}();Object.defineProperty(exports,"__esModule",{value:!0});var _immutable=__webpack_require__(3),emptySet=(0,_immutable.Set)(),Reactor=function(){function e(){_classCallCheck(this,e),this.reactors=emptySet,this.structure=void 0}return _createClass(e,[{key:"appendReactor",value:function(e){var t=this;return this.reactors=this.reactors.add(e),function(){t.reactors=t.reactors["delete"](e)}}},{key:"subscribe",value:function(e){return e(this.structure),this.appendReactor(e)}},{key:"digest",value:function(e){!hasValue(e)||hasValue(this.structure)&&(0,_immutable.is)(e,this.structure)!==!1||(this.structure=e,this.flush())}},{key:"flush",value:function(){var e=this;this.reactors.forEach(function(t){return t(e.structure)})}},{key:"destroyReactor",value:function(){this.structure=null,this.reactors=emptySet}},{key:"destroy",value:function(){this.destroyReactor()}},{key:"read",value:function(){return this.structure}},{key:"isReactor",get:function(){return!0}}]),e}();exports["default"]=Reactor; | ||
"use strict";function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var u=t[r];u.enumerable=u.enumerable||!1,u.configurable=!0,"value"in u&&(u.writable=!0),Object.defineProperty(e,u.key,u)}}return function(t,r,u){return r&&e(t.prototype,r),u&&e(t,u),t}}();Object.defineProperty(exports,"__esModule",{value:!0});var _immutable=__webpack_require__(3),hasValue=function(e){return void 0!==e&&null!==e},shouldStructureBeReplaced=function(e,t){return hasValue(t)&&(!hasValue(e)||(0,_immutable.is)(t,e)===!1)},Reactor=function(){function e(){_classCallCheck(this,e),this.reactors=(0,_immutable.Set)()}return _createClass(e,[{key:"read",value:function(){return this.structure}},{key:"digest",value:function(e){shouldStructureBeReplaced(this.structure,e)&&(this.structure=e,this.flush())}},{key:"appendReactor",value:function(e){var t=this;return this.reactors=this.reactors.add(e),function(){t.reactors=t.reactors["delete"](e)}}},{key:"subscribe",value:function(e){return e(this.read()),this.appendReactor(e)}},{key:"flush",value:function(){var e=this;this.reactors.forEach(function(t){return t(e.read())})}},{key:"destroy",value:function(){this.structure=null,this.reactors=(0,_immutable.Set)()}},{key:"isReactor",get:function(){return!0}}]),e}();exports["default"]=Reactor; | ||
@@ -100,0 +100,0 @@ /***/ } |
{ | ||
"name": "immview", | ||
"version": "1.4.1", | ||
"version": "1.4.2", | ||
"description": "", | ||
"main": "dist/immview.js", | ||
"jsnext:main": "src/index.js", | ||
"scripts": { | ||
@@ -7,0 +8,0 @@ "test": "./node_modules/.bin/karma start", |
@@ -1,2 +0,5 @@ | ||
import * as I from 'immutable'; | ||
import { | ||
Iterable, | ||
fromJS, | ||
} from 'immutable'; | ||
@@ -12,6 +15,6 @@ import Queue from './Queue'; | ||
if (I.Iterable.isIterable(initialData)) { | ||
if (Iterable.isIterable(initialData)) { | ||
this.digest(initialData); | ||
} else { | ||
this.digest(I.fromJS(initialData)); | ||
this.digest(fromJS(initialData)); | ||
} | ||
@@ -24,12 +27,21 @@ } | ||
/** | ||
* Dispatch a change instruction to the Data | ||
* @param {Iterable|function(data: Iterable):Iterable} change | ||
*/ | ||
write(change) { | ||
if (typeof change === 'function') { | ||
Queue.appendAndRunQueue(function updateStructure() { | ||
this.digest(change.apply(this, [this.read()])); | ||
}, this, [change]); | ||
Queue.runInQueue( | ||
() => this.digest(change(this.read())), | ||
this | ||
); | ||
} else { | ||
Queue.appendAndRunQueue(this.digest, this, [change]); | ||
Queue.runInQueue(this.digest, this, [change]); | ||
} | ||
} | ||
/** | ||
* Creates a View by digesting the stream | ||
* @param {Function} nextProcessor | ||
*/ | ||
map(nextProcessor) { | ||
@@ -36,0 +48,0 @@ return new View(this, nextProcessor); |
import Queue from './Queue.js'; | ||
const noop = () => { | ||
}; | ||
const noop = () => null; | ||
const errorPrefix = 'Immview::Domain: '; | ||
export default class Domain { | ||
/** | ||
* Create a domain holding a view | ||
* @param {Reactor} view | ||
* @param {Reactor} stream | ||
* @optional | ||
* @param {Object.<function>} actions | ||
*/ | ||
constructor(view, actions) { | ||
/** | ||
* @private | ||
* @type {View} */ | ||
this.view = null; | ||
/** | ||
* @private | ||
* @type {Data} */ | ||
this.data = null; | ||
/** | ||
* @private | ||
* @type {String[]} */ | ||
this._actionNames = null; | ||
this._claimView(view); | ||
constructor(stream, actions) { | ||
this._claimStream(stream); | ||
this._claimActions(actions); | ||
} | ||
_claimView(view) { | ||
if (view.isReactor) { | ||
this.view = view; | ||
/** | ||
* @private | ||
*/ | ||
_claimStream(stream) { | ||
if (stream.isReactor) { | ||
this.stream = stream; | ||
return; | ||
} | ||
if (view.isData) { | ||
this.data = view; | ||
} | ||
} else { | ||
throw new Error('view is not inheriting Reactor type'); | ||
} | ||
throw new Error(`${errorPrefix} provided stream is not inheriting from Reactor class`); | ||
} | ||
/** | ||
* @private | ||
*/ | ||
_claimActions(actions) { | ||
/** | ||
* @private | ||
*/ | ||
this._actionNames = actions ? Object.keys(actions) : []; | ||
@@ -46,5 +42,9 @@ | ||
if (this[actionName]) { | ||
throw new Error('"' + actionName + '" is reserved for Domain interface'); | ||
throw new Error(`${errorPrefix}${actionName} is reserved for Domain interface`); | ||
} | ||
if (typeof actions[actionName] !== 'function') { | ||
throw new Error(`${errorPrefix}${actionName} action is not a function`); | ||
} | ||
this[actionName] = Queue.createAction(actions[actionName], this); | ||
@@ -55,13 +55,23 @@ }); | ||
get structure() { | ||
return this.view && this.view.structure; | ||
return this.read(); | ||
} | ||
/** | ||
* Retrieve last value on stream attached to the Domain | ||
* @returns {Iterable} | ||
*/ | ||
read() { | ||
return this.view.read(); | ||
return this.stream.read(); | ||
} | ||
/** | ||
* Create a new stream from a stream attached to the Domain | ||
* @param {function(Iterable)} nextProcessor | ||
* @returns {View} | ||
*/ | ||
map(nextProcessor) { | ||
return this.view.map(nextProcessor); | ||
return this.stream.map(nextProcessor); | ||
} | ||
// WRITE ? | ||
// no write method now and in the future | ||
@@ -76,15 +86,30 @@ // as it would encourage developers | ||
/** | ||
* Register a listener to changes on data stream. | ||
* Calls provided method upon registration. | ||
* @param reaction | ||
* @returns {function()} unsubscribe | ||
*/ | ||
subscribe(reaction) { | ||
return this.view.subscribe(reaction); | ||
return this.stream.subscribe(reaction); | ||
} | ||
/** | ||
* Register a listener to changes on data stream. | ||
* @param reaction | ||
* @returns {function()} unsubscribe | ||
*/ | ||
appendReactor(reaction) { | ||
return this.view.appendReactor(reaction); | ||
return this.stream.appendReactor(reaction); | ||
} | ||
/** | ||
* Remove all subscriptions caused by the domain. | ||
* Destroy stream attached to it. | ||
* Cancel all currently dispatched actions. | ||
*/ | ||
destroy() { | ||
// destroy and unmount a structure | ||
this.view.destroy(); | ||
this.view = null; | ||
this.data = null; | ||
this.stream.destroy(); | ||
this.stream = null; | ||
@@ -91,0 +116,0 @@ // remove all queued actions |
@@ -5,3 +5,10 @@ import * as I from 'immutable'; | ||
let queue = I.OrderedSet(); | ||
const errorPrefix = 'Immview::Queue: '; | ||
export default { | ||
createAction, | ||
rejectContext, | ||
runInQueue, | ||
}; | ||
/** | ||
@@ -15,3 +22,3 @@ * Returns a function that is queueable version of provided one. | ||
return (...args) => { | ||
appendAndRunQueue(action, context, args); | ||
runInQueue(action, context, args); | ||
}; | ||
@@ -34,5 +41,5 @@ } | ||
function appendAndRunQueue(action, context, args) { | ||
function runInQueue(action, context, args) { | ||
appendToQueue(action, context, args); | ||
run(); | ||
startQueue(); | ||
} | ||
@@ -61,3 +68,3 @@ | ||
*/ | ||
function run() { | ||
function startQueue() { | ||
if (isRunning) { | ||
@@ -71,6 +78,5 @@ return; | ||
try { | ||
runFirst(); | ||
tick(runFirst); | ||
} catch (e) { | ||
console.error('Immview.Queue run - Error occured while running running a function'); | ||
console.error(e.message); | ||
logError(e); | ||
} | ||
@@ -82,2 +88,20 @@ } | ||
// TODO make it replacable | ||
function tick(func) { | ||
func(); | ||
} | ||
function logError(e) { | ||
console.error(`${errorPrefix}Error occured while running a function`); | ||
if (typeof e === 'object') { | ||
if (e.stack) { | ||
console.error(e.stack); | ||
} else { | ||
console.error(e.name, e.message); | ||
} | ||
} else { | ||
console.error(e); | ||
} | ||
} | ||
/** | ||
@@ -87,4 +111,4 @@ * Execute first action of current queue | ||
function runFirst() { | ||
let toRun = shiftFromQueue(); | ||
let { | ||
const toRun = shiftFromQueue(); | ||
const { | ||
context, | ||
@@ -96,7 +120,1 @@ action, | ||
} | ||
export default { | ||
createAction, | ||
rejectContext, | ||
appendAndRunQueue, | ||
}; |
@@ -6,11 +6,16 @@ import { | ||
function hasValue(v) { | ||
const hasValue = v => ( | ||
v !== undefined && | ||
v !== null | ||
); | ||
const shouldStructureBeReplaced = (structure, candidate) => { | ||
return ( | ||
v !== undefined && | ||
v !== null | ||
hasValue(candidate) && ( | ||
!hasValue(structure) || | ||
is(candidate, structure) === false | ||
) | ||
); | ||
} | ||
}; | ||
const emptySet = Set(); | ||
export default class Reactor { | ||
@@ -21,8 +26,3 @@ constructor() { | ||
*/ | ||
this.reactors = emptySet; | ||
/** | ||
* @private | ||
* @type {Iterable} | ||
*/ | ||
this.structure = undefined; //yet declared | ||
this.reactors = Set(); | ||
} | ||
@@ -34,2 +34,13 @@ | ||
read() { | ||
return this.structure; | ||
} | ||
digest(data) { | ||
if (shouldStructureBeReplaced(this.structure, data)) { | ||
this.structure = data; | ||
this.flush(); | ||
} | ||
} | ||
/** | ||
@@ -51,34 +62,14 @@ * @param {function} reaction | ||
subscribe(reaction) { | ||
reaction(this.structure); | ||
reaction(this.read()); | ||
return this.appendReactor(reaction); | ||
} | ||
digest(data) { | ||
if ( | ||
hasValue(data) && ( | ||
!hasValue(this.structure) || | ||
is(data, this.structure) === false | ||
) | ||
) { | ||
this.structure = data; | ||
this.flush(); | ||
} | ||
} | ||
flush() { | ||
this.reactors.forEach(reactor => reactor(this.structure)); | ||
this.reactors.forEach(reaction => reaction(this.read())); | ||
} | ||
destroyReactor() { | ||
destroy() { | ||
this.structure = null; | ||
this.reactors = emptySet; | ||
this.reactors = Set(); | ||
} | ||
destroy() { | ||
this.destroyReactor(); | ||
} | ||
read() { | ||
return this.structure; | ||
} | ||
} |
@@ -1,9 +0,11 @@ | ||
import * as I from 'immutable'; | ||
import { | ||
Map, | ||
} from 'immutable'; | ||
import Reactor from './Reactor.js'; | ||
const pass = data => data; | ||
const bypass = data => data; | ||
export default class View extends Reactor { | ||
constructor(source, process = pass) { | ||
constructor(source, process = bypass) { | ||
super(); | ||
@@ -20,2 +22,6 @@ | ||
get isView() { | ||
return true; | ||
} | ||
/** | ||
@@ -37,7 +43,7 @@ * @private | ||
// initialize as a map{string:Iterable} | ||
let mergedStructure = I.Map(); | ||
let mergedStructure = Map(); | ||
const viewsNames = Object.keys(views); | ||
//prefill mergedStructure before launching subscriptions | ||
// prefill mergedStructure before launching subscriptions | ||
viewsNames.forEach(viewName => { | ||
@@ -52,3 +58,3 @@ const viewData = views[viewName].read(); | ||
//subscribe to all data changes in parent views | ||
// subscribe to all data changes in parent views | ||
this.unsubs = viewsNames.map( | ||
@@ -66,4 +72,8 @@ viewName => views[viewName].appendReactor( | ||
get isView() { | ||
return true; | ||
/** | ||
* Creates a View by digesting the stream | ||
* @param {Function} nextProcessor | ||
*/ | ||
map(nextProcessor) { | ||
return new View(this, nextProcessor); | ||
} | ||
@@ -81,10 +91,2 @@ | ||
/** | ||
* Creates a View by digesting current View data | ||
* @param {Function} nextProcessor | ||
*/ | ||
map(nextProcessor) { | ||
return new View(this, nextProcessor); | ||
} | ||
} |
@@ -1,8 +0,7 @@ | ||
import Queue from '../src/Queue.js'; | ||
import Data from '../src/Data'; | ||
import * as I from 'immutable'; | ||
describe('Data', function () { | ||
describe('Data', () => { | ||
var d; | ||
let d; | ||
@@ -13,7 +12,7 @@ beforeEach(()=> { | ||
it('can be created', function () { | ||
it('can be created', () => { | ||
expect(d.isData).toBe(true); | ||
}); | ||
it('can be read from', function () { | ||
it('can be read from', () => { | ||
expect(d.read().get('a')).toBe(1); | ||
@@ -24,3 +23,3 @@ expect(d.read().getIn(['b', 'c'])).toBe(2); | ||
it('can be written to with a new data', function () { | ||
it('can be written to with a new data', () => { | ||
d.write(d.read().setIn(['b', 'c'], 3)); | ||
@@ -32,17 +31,3 @@ d.write(d.read().set('d', 3)); | ||
it('can be written to with a new data', function () { | ||
Queue.appendAndRunQueue(function () { | ||
//this time both writes will be executed after current command execution | ||
d.write(d.read().setIn(['b', 'c'], 3)); | ||
d.write(d.read().set('d', 3)); | ||
}); | ||
// with a value only last write | ||
// requested during one queue command or outside of queue | ||
// will last | ||
expect(d.read().getIn(['b', 'c'])).toBe(2); | ||
expect(d.read().get('d')).toBe(3); | ||
}); | ||
it('can be written to with a function returning data', function () { | ||
it('can be written to with a function returning data', () => { | ||
d.write(v => v.setIn(['b', 'c'], 3)); | ||
@@ -54,3 +39,3 @@ d.write(v => v.set('d', 3)); | ||
it('can be subscribed to', function (done) { | ||
it('can be subscribed to', done => { | ||
let forthVal; | ||
@@ -70,9 +55,9 @@ | ||
it('triggers reaction only for actual change', function () { | ||
it('triggers reaction only for actual change', () => { | ||
var reactions = 0; | ||
let reactions = 0; | ||
var getDataMap = () => I.fromJS({ a: 1, b: { c: 2 } }); | ||
const getDataMap = () => I.fromJS({ a: 1, b: { c: 2 } }); | ||
var d = new Data(getDataMap()); | ||
const d = new Data(getDataMap()); | ||
@@ -92,5 +77,5 @@ d.subscribe(() => { | ||
it('can be unsubscribed from', function () { | ||
var reactions = 0; | ||
var unsub = d.subscribe(() => { | ||
it('can be unsubscribed from', () => { | ||
let reactions = 0; | ||
const unsub = d.subscribe(() => { | ||
reactions++; | ||
@@ -97,0 +82,0 @@ }); |
@@ -5,9 +5,9 @@ import Domain from '../src/Domain'; | ||
describe('Domain', function () { | ||
it('exists', function () { | ||
describe('Domain', () => { | ||
it('exists', () => { | ||
expect(typeof Domain).toBeTruthy(); | ||
}); | ||
it('cannot be created from non-Reactor type', function () { | ||
expect(function () { | ||
it('cannot be created from non-Reactor type', () => { | ||
expect(() => { | ||
new Domain({}); | ||
@@ -17,4 +17,4 @@ }).toThrow(); | ||
it('can be created from Data type', function () { | ||
let d = new Data({ a: 1 }); | ||
it('can be created from Data type', () => { | ||
const d = new Data({ a: 1 }); | ||
@@ -25,20 +25,20 @@ // this should be really tested here | ||
let dmn = new Domain(d); | ||
const dmn = new Domain(d); | ||
expect(dmn.read().get('a')).toBe(1); | ||
}); | ||
it('can be created from a View type', function () { | ||
let d = new Data({ a: 1 }); | ||
it('can be created from a View type', () => { | ||
const d = new Data({ a: 1 }); | ||
let v = new View(d, data => data); | ||
const v = new View(d, data => data); | ||
expect(d.read().get('a')).toBe(1); | ||
let dmn2 = new Domain(v); | ||
const dmn2 = new Domain(v); | ||
expect(dmn2.read().get('a')).toBe(1); | ||
}); | ||
it('acquire queueable methods', function () { | ||
it('acquire queueable methods', () => { | ||
let testVar = ''; | ||
let d = new Data({ a: 1 }); | ||
let dmn = new Domain(d, { | ||
const d = new Data({ a: 1 }); | ||
const dmn = new Domain(d, { | ||
testMethod1: () => { | ||
@@ -61,6 +61,6 @@ testVar += '1'; | ||
it('allow subscriptions', function () { | ||
it('allow subscriptions', () => { | ||
let testVar = 0; | ||
let d = new Data({ a: 1 }); | ||
let dmn = new Domain(d); | ||
const d = new Data({ a: 1 }); | ||
const dmn = new Domain(d); | ||
@@ -80,6 +80,6 @@ expect(testVar).toBe(0); | ||
it('can be destroyed mid-digest', function () { | ||
it('can be destroyed mid-digest', () => { | ||
let testVar = ''; | ||
let d = new Data({ a: 1 }); | ||
let dmn = new Domain(d, { | ||
const d = new Data({ a: 1 }); | ||
const dmn = new Domain(d, { | ||
testMethod1: () => { | ||
@@ -86,0 +86,0 @@ testVar += '1'; |
@@ -7,8 +7,29 @@ import { | ||
describe('Immview', function () { | ||
it('exports', function () { | ||
expect(Data).toBeDefined(); | ||
expect(View).toBeDefined(); | ||
expect(Domain).toBeDefined(); | ||
function fulfillsReactorInterface(instance) { | ||
expect(typeof instance.read).toBe('function'); | ||
expect(typeof instance.subscribe).toBe('function'); | ||
expect(typeof instance.appendReactor).toBe('function'); | ||
expect(typeof instance.map).toBe('function'); | ||
} | ||
describe('Immview', () => { | ||
describe('has public interface', () => { | ||
it('Data', () => { | ||
expect(Data).toBeDefined(); | ||
const d = new Data(); | ||
fulfillsReactorInterface(d); | ||
expect(typeof d.write).toBe('function'); | ||
}); | ||
it('View', () => { | ||
expect(View).toBeDefined(); | ||
const v = new View(); | ||
fulfillsReactorInterface(v); | ||
}); | ||
it('Domain', () => { | ||
expect(Domain).toBeDefined(); | ||
const testData = new Data(); | ||
const testDomain = new Domain(testData); | ||
fulfillsReactorInterface(testDomain); | ||
}); | ||
}); | ||
}); |
import Queue from '../src/Queue'; | ||
describe('Queue', function () { | ||
it('exists', function () { | ||
describe('Queue', () => { | ||
it('exists', () => { | ||
expect(typeof Queue).toBeTruthy(); | ||
}); | ||
it('creates a runnable command', function () { | ||
it('creates a runnable command', () => { | ||
let test = false; | ||
let d = { | ||
const d = { | ||
testCmd: () => { | ||
@@ -15,3 +15,3 @@ test = true; | ||
}; | ||
let command = Queue.createAction(d.testCmd); | ||
const command = Queue.createAction(d.testCmd); | ||
command(); | ||
@@ -21,7 +21,6 @@ expect(test).toBeTruthy(); | ||
it('creates a runnable context command', function () { | ||
it('creates a runnable context command', () => { | ||
let test = false; | ||
let d = { | ||
testCmd: () => { | ||
console.log('testCmd'); | ||
const d = { | ||
testCmd: function () { | ||
test = true; | ||
@@ -31,7 +30,6 @@ }, | ||
secondTestCmd: function () { | ||
console.log('secondTestCmd'); | ||
this.testCmd(); | ||
}, | ||
}; | ||
let command = Queue.createAction(d.secondTestCmd, d); | ||
const command = Queue.createAction(d.secondTestCmd, d); | ||
command(); | ||
@@ -41,5 +39,5 @@ expect(test).toBeTruthy(); | ||
it('runs commands separately in call order', function () { | ||
it('runs commands separately in call order', () => { | ||
let testString = ''; | ||
let commands = { | ||
const commands = { | ||
cmd1: () => { | ||
@@ -59,3 +57,3 @@ testString += '1'; | ||
}; | ||
let queueableCommands = { | ||
const queueableCommands = { | ||
cmd1: Queue.createAction(commands.cmd1, commands), | ||
@@ -73,6 +71,6 @@ cmd2: Queue.createAction(commands.cmd2, commands), | ||
it('passes arguments', function () { | ||
it('passes arguments', () => { | ||
let test = 'c'; | ||
let action = appendix => test += appendix; | ||
let command = Queue.createAction(action); | ||
const action = appendix => test += appendix; | ||
const command = Queue.createAction(action); | ||
command('asd'); | ||
@@ -82,3 +80,3 @@ expect(test).toBe('casd'); | ||
it('removes unused context', function () { | ||
it('removes unused context', () => { | ||
let test; | ||
@@ -111,2 +109,15 @@ | ||
}); | ||
it('catches action error', done => { | ||
const action = () => { | ||
throw new Error('dope!'); | ||
}; | ||
Queue.runInQueue( | ||
action, | ||
null, | ||
null | ||
); | ||
done(); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
82198
984