New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

immview

Package Overview
Dependencies
Maintainers
1
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

immview - npm Package Compare versions

Comparing version 1.6.2 to 1.7.0

.flowconfig

37

changelog.md

@@ -1,12 +0,21 @@

##Changelog
#Changelog
### 1.6.2
## 1.7
- feat: New node `Merge`. Merging multiple source can and should be done with `Merge` and this functionality in `View` is now deprecated.
- feat: New node `Reduce`. Provide it with observable source and function that takes current state and source stream state.
- feat: Immview no longer depends on `Immutable.js` and doesn't have `Immutable.js` oriented optimizations.
- feat: All objects that are provided within `View` processor and all subscriptions are now frozen. Functionality requires `Proxy`, but library doesn't rely on that as in many environments it is not present. It is cheaper than cloning, yet secures immutability of data provided to processing functions too.
- feat: `Observable` class got `shouldObservableUpdate` method responsible for decision if candidate value should replace old one and thus trigger subscriptions. Method can be overriden in subclass.
- feat: Any `Observable` can pass a `Promise` and it will result in asynchronous subscriptions triggering with `Promise` result. `Promise` rejection is not being handled. This, ofcourse, will work with `async`/`await` or `Promise`-returning processing functions in `View`.
## 1.6.2
- fix: Simpler and faster solution for eliminating unnecessary rerenders of merging views
### 1.6.1
## 1.6.1
- fix: `Data` ignores write instructions raised after the node being destroyed
### 1.6
## 1.6

@@ -19,11 +28,11 @@ - feat: `Scan` and `*.scan` added

### 1.5.2
## 1.5.2
- fix: writing during single tick, to the same Data twice or more, causing to reject all but last change
### 1.5.1
## 1.5.1
- fix: support for deferring ticker replacements
### 1.5
## 1.5

@@ -38,11 +47,11 @@ - feat: `Data` writes are prioritized over Domain actions

### 1.4.2
## 1.4.2
- fix: `Queue` (dispatcher) returns stack trace instead of just error message
### 1.4.1
## 1.4.1
- fix: broken contract - `View` could not be created from a domain as a source
### 1.4.0
## 1.4.0

@@ -53,15 +62,15 @@ - fix: merged views processors will receive already fully merged source at first run

### 1.3.0
## 1.3.0
- read & write methods
### 1.2.2
## 1.2.2
- `Data` exposes Immutable.Set functions too
### 1.2.1
## 1.2.1
- uglify dist version
### 1.2.0
## 1.2.0

@@ -68,0 +77,0 @@ - `Domain` and `Queue` have been added

@@ -1,2 +0,2 @@

!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("immutable")):"function"==typeof define&&define.amd?define(["immutable"],e):"object"==typeof exports?exports.immview=e(require("immutable")):t.immview=e(t.immutable)}(this,function(t){return function(t){function e(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return t[r].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0}),e.dispatch=e.Dispatcher=e.Scan=e.Throttle=e.Debounce=e.Domain=e.View=e.Data=void 0;var i=n(1),u=r(i),o=n(11),s=r(o),c=n(6),a=r(c),f=n(8),l=r(f),d=n(9),h=r(d),p=n(10),m=r(p),b=n(2);e.Data=s.default,e.View=a.default,e.Domain=u.default,e.Debounce=l.default,e.Throttle=h.default,e.Scan=m.default,e.Dispatcher=b.Dispatcher,e.dispatch=b.dispatch},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!t.subscribe)throw Error(a+" stream source required");this.stream=t,u(this,e)}function u(t,e){if(!e)return void(t.actions=function(){return[]});var n=Object.keys(e);n.forEach(function(n){var r=e[n];if(void 0!==t[n])throw Error(""+a+n+" is reserved for Domain interface");if("function"!=typeof r)throw Error(""+a+n+" action is not a function");t[n]=function(){for(var e=arguments.length,n=Array(e),i=0;e>i;i++)n[i]=arguments[i];(0,o.dispatchDomainAction)(r,t,n)},t[n].originalLength=r.length||r.originalLength}),t._actionNames=n,t.actions=function(){return n}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i;var o=n(2),s=n(3),c=(r(s),function(){return null}),a="Immview::Domain: ";i.prototype={read:function(){return this.stream.read()},map:function(t){return this.stream.map(t)},debounce:function(t){return this.stream.debounce(t)},throttle:function(t){return this.stream.throttle(t)},scan:function(t,e){return this.stream.scan(t,e)},subscribe:function(t){return this.stream.subscribe(t)},addSubscription:function(t){return this.stream.addSubscription(t)},destroy:function(){var t=this;this.stream.destroy(),this.stream=null,(0,o.rejectContext)(this),this._actionNames.forEach(function(e){t[e]=c}),this._actionNames=null}}},function(t,e){"use strict";function n(t){return t&&"undefined"!=typeof Symbol&&t.constructor===Symbol?"symbol":typeof t}function r(){var t=i();if(t){var e=t.context,n=t.action,r=t.args;n&&n.apply(e,r)}}function i(){var t=u();return b.splice(b.indexOf(t),1),t}function u(){for(var t=-1,e=null,n=0;b.length>n;n++){var r=b[n].priority;r>t&&(e=b[n],t=r)}return e}function o(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:y;b.push({priority:r,action:t,context:e,args:n})}function s(t,e,n){l(t,e,n,g)}function c(t,e,n){l(t,e,n,_)}function a(t,e,n){l(t,e,n,D)}function f(t,e,n){l(t,e,n,y)}function l(t,e,n,r){o(t,e,n,r),d()}function d(){m||b.length>0&&(m=!0,j.tick(function(){try{r()}catch(t){h(t)}m=!1,d()}))}function h(t){j.logger.error(v+"Error occured while running a function"),"object"===(void 0===t?"undefined":n(t))?t.stack?j.logger.error(t.stack):j.logger.error(t.name,t.message):j.logger.error(t)}function p(t){b=b.filter(function(e){return e.context!==t})}Object.defineProperty(e,"__esModule",{value:!0});var m=!1,b=[],v="Immview::Dispatcher: ",y=0,g=1,_=2,D=3,j={dispatch:f,tick:function(t){t()},rejectContext:p,logger:console};e.default=j,e.Dispatcher=j,e.dispatch=l,e.dispatchDomainAction=s,e.dispatchDataWrite=c,e.dispatchDataConsume=a,e.dispatchExternal=f,e.rejectContext=p},function(t,e,n){"use strict";function r(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}function i(){this._id=i.lastInstanceId++,this._subscriptions=[],this.closed=!1}function u(t,e){return o(e)&&(!o(t)||!(0,c.is)(e,t))}function o(t){return void 0!==t&&null!==t}function s(t){return t}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i;var c=n(4),a=n(5),f=r(a),l=n(2),d=r(l);i.lastInstanceId=0,i.prototype={read:function(){return this.structure},_consume:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:s;f.queue(this,t,e)},_digest:function(t){u(this.structure,t)&&(this.structure=t,this._flush(t))},_flush:function(t){this._subscriptions.forEach(function(e){return e(t)})},addSubscription:function(t){var e=this;return this._subscriptions.indexOf(t)<0&&this._subscriptions.push(t),function(){e._subscriptions=e._subscriptions.filter(function(e){return e!==t})}},subscribe:function(t){return t(this.read()),this.addSubscription(t)},destroy:function(){d.rejectContext(this),this.structure=null,this._subscriptions=[],Object.defineProperty?Object.defineProperty(this,"closed",{value:!0,writable:!1}):this.closed=!0},map:function(t){var e=n(6).default;return new e(this,t)},debounce:function(t){var e=n(8).default;return new e(this,t)},throttle:function(t){var e=n(9).default;return new e(this,t)},scan:function(t,e){var r=n(10).default;return new r(this,t,e)}}},function(e,n){e.exports=t},function(t,e,n){"use strict";function r(t,e,n){(0,c.dispatchDataConsume)(function(){i(t,e,n),u()})}function i(t,e,n){for(var r=0;a.length>r;r++){if(a[r].observable._id===t._id)return void(a[r].data=e);if(a[r].observable._id>t._id)return void a.splice(r,0,{observable:t,data:e,process:n})}a.splice(a.length,0,{observable:t,data:e,process:n})}function u(){(0,c.dispatchDataWrite)(o)}function o(){if(a.length){var t=a.splice(0,1),e=s(t,1),n=e[0],r=n.observable,i=n.data,o=n.process;r._digest(o(i)),u()}}var s=function(){function t(t,e){var n=[],r=!0,i=!1,u=void 0;try{for(var o,s=t[Symbol.iterator]();!(r=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);r=!0);}catch(c){i=!0,u=c}finally{try{!r&&s.return&&s.return()}finally{if(i)throw u}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();Object.defineProperty(e,"__esModule",{value:!0}),e.queue=r;var c=n(2),a=[]},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t){return t&&"undefined"!=typeof Symbol&&t.constructor===Symbol?"symbol":typeof t}function u(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:o;if(d.default.call(this),t&&"object"===(void 0===t?"undefined":i(t)))return void(this.unsubs=t.subscribe?s(this,t,e):c(this,t,e));throw Error(h+"No sources to plug in")}function o(t){return t}function s(t,e,n){return t._digest(n(e.read())),[e.addSubscription(function(e){return t._consume(e,n)})]}function c(t,e,n){var r=new f.default,i=Object.keys(e);i.forEach(function(t){var n=e[t],i=n.read();r=r.set(t,i)});var u=i.map(function(i){return e[i].addSubscription(function(e){r=r.set(i,e),t._consume(r.clone(),n)})});return t._digest(n(r.clone())),u}Object.defineProperty(e,"__esModule",{value:!0}),e.default=u;var a=n(7),f=r(a),l=n(3),d=r(l),h="Immview::View: ";u.prototype=Object.create(d.default.prototype),u.prototype.destroy=function(){d.default.prototype.destroy.call(this),this.unsubs&&this.unsubs.forEach(function(t){return t()}),this.unsubs=null}},function(t,e){"use strict";function n(t){return Array.isArray(t)?t:Array.from(t)}function r(t){return t&&"undefined"!=typeof Symbol&&t.constructor===Symbol?"symbol":typeof t}function i(t){for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&(this[e]=t[e])}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i,i.prototype={clone:function(){return new i(this)},set:function(t,e){var n=new i(this);return n[t]=e,n},get:function(t){return this[t]},map:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this,n=new i;for(var r in this)Object.prototype.hasOwnProperty.call(this,r)&&(n[r]=t.call(e,this[r]));return n},toJS:function(){return this.map(function(t){return"object"===(void 0===t?"undefined":r(t))&&"function"==typeof t.toJS?t.toJS():t})},toObject:function(){return this},getIn:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=n(t),r=e[0],i=e.slice(1),u=arguments[1];return i.length?this.get(r).getIn(i,u):void 0===this.get(r)?u:this.get(r)},setIn:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=n(t),r=e[0],u=e.slice(1),o=arguments[1];return u.length?this.set(r,(this.get(r)||new i).setIn(u,o)):this.set(r,o)}}},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(o.default.call(this),!t||!t.subscribe)throw Error(s+"incorrect source");this.timeoutID=null,this._digest(t.read()),this.subscription=t.addSubscription(function(t){e.timeoutID&&clearTimeout(e.timeoutID),e.timeoutID=setTimeout(function(){e.timeoutID=null,e._consume(t)},n)})}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i;var u=n(3),o=r(u),s="Immview::Debounce: ";i.prototype=Object.create(o.default.prototype),i.prototype.destroy=function(){this.timeoutID&&(clearTimeout(this.timeoutID),this.timeoutID=null),this.subscription&&this.subscription(),o.default.prototype.destroy.call(this)}},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(o.default.call(this),!t||!t.subscribe)throw Error(s+"incorrect source");this.timeoutID=null,this.timeoutedData=null,this._digest(t.read()),this.subscription=t.addSubscription(function(t){e.timeoutedData=t,e.timeoutID||(e.timeoutID=setTimeout(function(){e.timeoutID=null,e._consume(e.timeoutedData)},n))})}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i;var u=n(3),o=r(u),s="Immview::Throttle: ";i.prototype=Object.create(o.default.prototype),i.prototype.destroy=function(){this.timeoutID&&(clearTimeout(this.timeoutID),this.timeoutID=null),this.subscription&&this.subscription(),o.default.prototype.destroy.call(this)}},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;c.default.apply(this);var i=o(u(r,n),n,t.read());this._digest(i),this.unsubscribe=t.addSubscription(function(t){i=o(i,n,t),e._consume(i)})}function u(t,e){if(null===t)return[];for(var n=[],r=0;e>r;r++)n.push(t);return n}function o(t,e,n){var r=t.slice(-1*e+1);return r.push(n),r}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i;var s=n(3),c=r(s);i.prototype=Object.create(c.default.prototype),i.prototype.read=function(){return[].concat(c.default.prototype.read.apply(this))},i.prototype.destroy=function(){c.default.prototype.destroy.apply(this),this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null)}},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t){s.default.call(this),this._digest(t)}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i;var u=n(2),o=n(3),s=r(o);i.prototype=Object.create(s.default.prototype),i.prototype.write=function(t){var e=this;(0,u.dispatchDataWrite)(function(){e.closed||e._digest("function"==typeof t?t(e.read()):t)},this)}}])});
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.immview=e():t.immview=e()}(this,function(){return function(t){function e(n){if(r[n])return r[n].exports;var i=r[n]={exports:{},id:n,loaded:!1};return t[n].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var r={};return e.m=t,e.c=r,e.p="",e(0)}([function(t,e,r){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0}),e.dispatch=e.Dispatcher=e.Reduce=e.Merge=e.Scan=e.Throttle=e.Debounce=e.Domain=e.View=e.Data=e.Observable=void 0;var i=r(1),o=n(i),u=r(12),s=n(u),a=r(13),c=n(a),f=r(6),l=n(f),d=r(8),h=n(d),p=r(9),m=n(p),y=r(10),b=n(y),g=r(14),v=n(g),_=r(11),j=n(_),w=r(3);e.Observable=o.default,e.Data=c.default,e.View=l.default,e.Domain=s.default,e.Debounce=h.default,e.Throttle=m.default,e.Scan=b.default,e.Merge=v.default,e.Reduce=j.default,e.Dispatcher=w.Dispatcher,e.dispatch=w.dispatch},function(t,e,r){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function i(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}function o(){var t=this;this.structure=null,this.priority=o.nextPriority++,this.subscriptions=[function(e){t.structure=e}],this.closed=!1}function u(t){return void 0!==t&&null!==t}function s(t){return t}Object.defineProperty(e,"__esModule",{value:!0}),e.default=o;var a=r(2),c=i(a),f=r(3),l=i(f),d=r(4),h=n(d),p=r(5),m=n(p),y="production"===m.default?s:h.default;o.nextPriority=0,o.prototype={structure:null,priority:0,subscriptions:[],closed:!1,read:function(){return this.structure},shouldObservableUpdate:function(t){return u(t)&&this.read()!=t},consume:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:s;c.queue(this,t,e)},digest:function(t){var e=this;this.digestCandidate||t instanceof Promise?this.digestCandidate=(this.digestCandidate||Promise.resolve()).then(function(){return t}).then(function(t){return e.flush(t)}):this.flush(t)},flush:function(t){if(this.shouldObservableUpdate(t))for(var e=0;this.subscriptions&&this.subscriptions.length>e;e++)this.subscriptions[e](y(t))},addSubscription:function(t){var e=this;return this.subscriptions.indexOf(t)<0&&this.subscriptions.push(t),function(){e.subscriptions=e.subscriptions.filter(function(e){return e!==t})}},subscribe:function(t){return t(this.read()),this.addSubscription(t)},destroy:function(){l.rejectContext(this),this.structure=null,this.subscriptions=[],Object.defineProperty?Object.defineProperty(this,"closed",{value:!0,writable:!1}):this.closed=!0},map:function(t){var e=r(6).default;return new e(this,t)},debounce:function(t){var e=r(8).default;return new e(this,t)},throttle:function(t){var e=r(9).default;return new e(this,t)},scan:function(t,e){var n=r(10).default;return new n(this,t,e)},reduce:function(t){var e=r(11).default;return new e(this,t)},info:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";try{var e=JSON.stringify(this.read()).substr(0,32);l.Dispatcher.logger.log("#"+this.priority+" "+t+" "+e)}catch(r){l.Dispatcher.logger.log("#"+this.priority+" "+t,this.read())}}}},function(t,e,r){"use strict";function n(t,e,r){(0,a.dispatchDataConsume)(function(){i(t,e,r),o()})}function i(t,e,r){for(var n=0;c.length>n;n++){if(c[n].observable.priority===t.priority)return void(c[n].data=e);if(c[n].observable.priority>t.priority)return void c.splice(n,0,{observable:t,data:e,process:r})}c.splice(c.length,0,{observable:t,data:e,process:r})}function o(){(0,a.dispatchDataWrite)(u)}function u(){if(c.length){var t=c.splice(0,1),e=s(t,1),r=e[0],n=r.observable,i=r.data,u=r.process;n.digest(u(i)),o()}}var s=function(){function t(t,e){var r=[],n=!0,i=!1,o=void 0;try{for(var u,s=t[Symbol.iterator]();!(n=(u=s.next()).done)&&(r.push(u.value),!e||r.length!==e);n=!0);}catch(a){i=!0,o=a}finally{try{!n&&s.return&&s.return()}finally{if(i)throw o}}return r}return function(e,r){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,r);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();Object.defineProperty(e,"__esModule",{value:!0}),e.queue=n;var a=r(3),c=[]},function(t,e){"use strict";function r(t){return t&&"undefined"!=typeof Symbol&&t.constructor===Symbol?"symbol":typeof t}function n(){var t=i();if(t){var e=t.context,r=t.action,n=t.args;r&&r.apply(e,n)}}function i(){var t=o();return t&&y.splice(y.indexOf(t),1),t}function o(){for(var t=-1,e=null,r=0;y.length>r;r++){var n=y[r].priority;n>t&&(e=y[r],t=n)}return e}function u(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:g;y.push({priority:n,action:t,context:e,args:r})}function s(t,e,r){l(t,e,r,v)}function a(t,e,r){l(t,e,r,_)}function c(t,e,r){l(t,e,r,j)}function f(t,e,r){l(t,e,r,g)}function l(t,e,r,n){u(t,e,r,n),d()}function d(){m||y.length>0&&(m=!0,w.tick(function(){try{n()}catch(t){h(t)}m=!1,d()}))}function h(t){w.logger.error(b+"Error occured while running a function"),"object"===(void 0===t?"undefined":r(t))?t.stack?w.logger.error(t.stack):w.logger.error(t.name,t.message):w.logger.error(t)}function p(t){y=y.filter(function(e){return e.context!==t})}Object.defineProperty(e,"__esModule",{value:!0});var m=!1,y=[],b="Immview::Dispatcher: ",g=0,v=1,_=2,j=3,w={dispatch:f,tick:function(t){t()},rejectContext:p,logger:console};e.default=w,e.Dispatcher=w,e.dispatch=l,e.dispatchDomainAction=s,e.dispatchDataWrite=a,e.dispatchDataConsume=c,e.dispatchExternal=f,e.rejectContext=p},function(t,e,r){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function i(t){return t&&"undefined"!=typeof Symbol&&t.constructor===Symbol?"symbol":typeof t}function o(t){try{return[!0,JSON.stringify(t)]}catch(e){return[!1,""]}}function u(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:32;return t.length>e?t.substr(0,29).replace(/\r/g,"").replace(/\n/g,"")+"...":t}var s=function(){function t(t,e){var r=[],n=!0,i=!1,o=void 0;try{for(var u,s=t[Symbol.iterator]();!(n=(u=s.next()).done)&&(r.push(u.value),!e||r.length!==e);n=!0);}catch(a){i=!0,o=a}finally{try{!n&&s.return&&s.return()}finally{if(i)throw o}}return r}return function(e,r){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,r);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();Object.defineProperty(e,"__esModule",{value:!0});var a=r(5),c=n(a),f="function"!=typeof Proxy?function(t){return t}:function(t){return"object"!==(void 0===t?"undefined":i(t))||null===t||void 0===t?t:new Proxy(t,{get:function(t,e){return f(t[e])},set:function(t,e,r,n){if("production"===c.default)return!1;var i=o(n),a=s(i,2),f=a[0],l=a[1];if(f)throw Error(["Immview::immutabilizer: Object",u(l),"has been frozen in order to contain side-effects. You should not modify this object."].join(" "));throw Error("Immview::immutabilizer: Unrepresentable object has been frozen in order to contain side-effects. You should not modify this object.")}})};e.default=f},function(t,e,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=void 0;try{n=function(){return"production"}()}catch(i){n="production"}e.default=n},function(t,e,r){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function i(t){return t&&"undefined"!=typeof Symbol&&t.constructor===Symbol?"symbol":typeof t}function o(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:u;if(d.default.call(this),t&&"object"===(void 0===t?"undefined":i(t)))return void(this.unsubs=t.subscribe?s(this,t,e):a(this,t,e));throw Error(m+"No sources to plug in")}function u(t){return t}function s(t,e,r){return t.digest(r(e.read())),[e.addSubscription(function(e){return t.consume(e,r)})]}function a(t,e,r){"production"!==p.default&&console.warn([m,"View usage for merging streams is deprecated since 1.7. Consider changing to Merge type of node."].join(" "));var n=new f.default,i=Object.keys(e);i.forEach(function(t){var r=e[t],i=r.read();n=n.set(t,i)});var o=i.map(function(i){return e[i].addSubscription(function(e){n=n.set(i,e),t.consume(n.clone(),r)})});return t.digest(r(n.clone())),o}Object.defineProperty(e,"__esModule",{value:!0}),e.default=o;var c=r(7),f=n(c),l=r(1),d=n(l),h=r(5),p=n(h),m="Immview::View: ";o.prototype=Object.create(d.default.prototype),o.prototype.destroy=function(){d.default.prototype.destroy.call(this),this.unsubs&&this.unsubs.forEach(function(t){return t()}),this.unsubs=null}},function(t,e){"use strict";function r(t){return Array.isArray(t)?t:Array.from(t)}function n(t){return t&&"undefined"!=typeof Symbol&&t.constructor===Symbol?"symbol":typeof t}function i(t){for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&(this[e]=t[e])}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i,i.prototype={clone:function(){return new i(this)},set:function(t,e){var r=new i(this);return r[t]=e,r},get:function(t){return this[t]},map:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this,r=new i;for(var n in this)Object.prototype.hasOwnProperty.call(this,n)&&(r[n]=t.call(e,this[n]));return r},toJS:function(){return this.map(function(t){return"object"===(void 0===t?"undefined":n(t))&&"function"==typeof t.toJS?t.toJS():t})},toObject:function(){return this},getIn:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=r(t),n=e[0],i=e.slice(1),o=arguments[1];return i.length?this.get(n).getIn(i,o):void 0===this.get(n)?o:this.get(n)},setIn:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=r(t),n=e[0],o=e.slice(1),u=arguments[1];return o.length?this.set(n,(this.get(n)||new i).setIn(o,u)):this.set(n,u)}}},function(t,e,r){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function i(t){var e=this,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(u.default.call(this),!t||!t.subscribe)throw Error(s+"incorrect source");this.timeoutID=null,this.digest(t.read()),this.subscription=t.addSubscription(function(t){e.timeoutID&&clearTimeout(e.timeoutID),e.timeoutID=setTimeout(function(){e.timeoutID=null,e.consume(t)},r)})}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i;var o=r(1),u=n(o),s="Immview::Debounce: ";i.prototype=Object.create(u.default.prototype),i.prototype.destroy=function(){this.timeoutID&&(clearTimeout(this.timeoutID),this.timeoutID=null),this.subscription&&this.subscription(),u.default.prototype.destroy.call(this)}},function(t,e,r){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function i(t){var e=this,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(u.default.call(this),!t||!t.subscribe)throw Error(s+"incorrect source");this.timeoutID=null,this.timeoutedData=null,this.digest(t.read()),this.subscription=t.addSubscription(function(t){e.timeoutedData=t,e.timeoutID||(e.timeoutID=setTimeout(function(){e.timeoutID=null,e.consume(e.timeoutedData)},r))})}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i;var o=r(1),u=n(o),s="Immview::Throttle: ";i.prototype=Object.create(u.default.prototype),i.prototype.destroy=function(){this.timeoutID&&(clearTimeout(this.timeoutID),this.timeoutID=null),this.subscription&&this.subscription(),u.default.prototype.destroy.call(this)}},function(t,e,r){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function i(t){var e=this,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;a.default.apply(this);var i=u(o(n,r),r,t.read());this.digest(i),this.unsubscribe=t.addSubscription(function(t){i=u(i,r,t),e.consume(i)})}function o(t,e){if(null===t)return[];for(var r=[],n=0;e>n;n++)r.push(t);return r}function u(t,e,r){var n=t.slice(-1*e+1);return n.push(r),n}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i;var s=r(1),a=n(s);i.prototype=Object.create(a.default.prototype),i.prototype.read=function(){return[].concat(a.default.prototype.read.apply(this))},i.prototype.destroy=function(){a.default.prototype.destroy.apply(this),this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null)}},function(t,e,r){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){var r=this;if("production"!==a.default){if(!t)throw Error(c+" #"+this.priority+": No source");if(!t.subscribe)throw Error(c+" #"+this.priority+": Source is not an observable");if(!e)throw Error(c+" #"+this.priority+": No reducer provided")}u.default.call(this),this.unsubscribeFromSource=t.subscribe(function(t){r.consume(e(r.read(),t))})}Object.defineProperty(e,"__esModule",{value:!0});var o=r(1),u=n(o),s=r(5),a=n(s),c="Immview::Reduce";i.prototype=Object.create(u.default.prototype),i.prototype.destroy=function(){this.closed||(this.unsubscribeFromSource(),u.default.prototype.destroy.call(this))},e.default=i},function(t,e,r){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!t.subscribe)throw Error(c+" stream source required");this.stream=t,o(this,e)}function o(t,e){if(!e)return void(t.actions=function(){return[]});var r=Object.keys(e);r.forEach(function(r){var n=e[r];if(void 0!==t[r])throw Error(""+c+r+" is reserved for Domain interface");if("function"!=typeof n)throw Error(""+c+r+" action is not a function");t[r]=function(){for(var e=arguments.length,r=Array(e),i=0;e>i;i++)r[i]=arguments[i];(0,u.dispatchDomainAction)(n,t,r)},t[r].originalLength=n.length||n.originalLength}),t._actionNames=r,t.actions=function(){return r}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i;var u=r(3),s=r(1),a=(n(s),function(){return null}),c="Immview::Domain: ";i.prototype={read:function(){return this.stream.read()},map:function(){for(var t=arguments.length,e=Array(t),r=0;t>r;r++)e[r]=arguments[r];return this.stream.map.apply(this.stream,e)},debounce:function(){for(var t=arguments.length,e=Array(t),r=0;t>r;r++)e[r]=arguments[r];return this.stream.debounce.apply(this.stream,e)},throttle:function(){for(var t=arguments.length,e=Array(t),r=0;t>r;r++)e[r]=arguments[r];return this.stream.throttle.apply(this.stream,e)},scan:function(){for(var t=arguments.length,e=Array(t),r=0;t>r;r++)e[r]=arguments[r];return this.stream.scan.apply(this.stream,e)},reduce:function(){for(var t=arguments.length,e=Array(t),r=0;t>r;r++)e[r]=arguments[r];return this.stream.reduce.apply(this.stream,e)},subscribe:function(){for(var t=arguments.length,e=Array(t),r=0;t>r;r++)e[r]=arguments[r];return this.stream.subscribe.apply(this.stream,e)},addSubscription:function(){for(var t=arguments.length,e=Array(t),r=0;t>r;r++)e[r]=arguments[r];return this.stream.addSubscription.apply(this.stream,e)},destroy:function(){var t=this;this.stream.destroy(),this.stream=null,(0,u.rejectContext)(this),this._actionNames.forEach(function(e){t[e]=a}),this._actionNames=null}}},function(t,e,r){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function i(t){s.default.call(this),this.digest(t),this.pendingChanges=[]}function o(t){var e=t.pendingChanges.reduce(function(t,e){return e(t)},t.read());return t.pendingChanges=[],e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i;var u=r(1),s=n(u);i.prototype=Object.create(s.default.prototype),i.prototype.write=function(t){this.closed||("function"==typeof t?(this.pendingChanges.push(t),this.consume(this,o)):this.consume(t))},i.prototype.destroy=function(){s.default.prototype.destroy.call(this),this.pendingChanges=null}},function(t,e,r){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function i(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function o(t){return t&&"undefined"!=typeof Symbol&&t.constructor===Symbol?"symbol":typeof t}function u(t){var e=this;if(a.default.call(this),!t||"object"!==(void 0===t?"undefined":o(t)))throw Error(c+" No sources to plug in");var r=Object.keys(t),n=r.reduce(function(e,r){return Object.assign(i({},r,t[r].read()),e)},{});this.unsubs=r.map(function(r){return t[r].addSubscription(function(t){n=Object.assign({},n,i({},r,t)),e.consume(n)})}),this.digest(Object.assign({},n))}Object.defineProperty(e,"__esModule",{value:!0}),e.default=u;var s=r(1),a=n(s),c="Immview::Merge:";u.prototype=Object.create(a.default.prototype),u.prototype.destroy=function(){a.default.prototype.destroy.call(this),this.unsubs&&this.unsubs.forEach(function(t){return t()}),this.unsubs=null}}])});
//# sourceMappingURL=immview.js.map
#Docs
## Domain
### class
#### ( source: Stream )
#### ( source: Stream , { [string]: () => void } )
> Any types are provided in descriptions follow **flowtype** style.
First argument of constructor is a data source. It can be any observable class listed below. That will be a *state* stream of the newly created **Domain**. Only single data source can be tied to it, and because of that **Domain** can be used as data source.
- [abstract class Observable](#abstract-class-observable)
- [class Domain](#class-domain)
- [class Data](#class-data)
- [class View](#class-view)
- [class Merge](#class-merge)
- [class Debounce](#class-debounce)
- [class Throttle](#class-throttle)
- [class Scan](#class-scan)
- [module Dispatcher](#module-dispatcher)
## abstract class `Observable`
### Observable::read
#### () => mixed
Method used to retrieve current structure holden by the Observable.
```javascript
// Example
const source = new Data({a: 1})
source.read().a // = 1
```
### Observable::subscribe
#### ( reaction: (data: mixed) => void ) => () => void
Registers a function called every time when the Observable changes value that it holds.
Returns a function to unregister the subscription.
### Observable::map
#### ( processor: (data: mixed) => mixed ) => View (since 1.4)
Creates new **View** with the current instance as a data source and **processor** as function applying onto it's source stream state. **Processor** function will receive a data structure and should return data structure that will become that **View** instance state. Read more in **View** section.
### Observable::debounce
#### ( timeout: number ) => Debounce (since 1.5)
Creates a new stream of values being pushed with a provided delay since last update.
### Observable::throttle
#### ( timeout: number ) => Throttle (since 1.5)
Creates a new stream of values being push with a provided delay since first update.
### Observable::scan
#### ( valuesToRemember: number, initialValue: any ) => Scan (since 1.6)
Creates a new stream of `List` of values that were pushed from a source stream recently. List has a max length of `valuesToRemember` argument. Additionally for first `valuesToRemember - 1` runs if `initialValue` is provided, `List` of values is always `valuesToRemember` long and filled with `initialValue` for not yet existing steps.
## class `Domain`
#### extends `Observable`
#### ( source: Observable )
#### ( source: Observable , { [name: string]: () => void } )
First argument of constructor is a data source. It can be any observable element listed below. That will be a *state* stream of the newly created **Domain**. Only single data source can be tied to a **Domain**, and because of that any **Domain** can be used as data source.
Second argument is an object aggregating functions used to create commands that will be exposed as part of the **Domain** interface. These functions will be wrapped with an internal Dispatcher calls. **Domain** *actions* won't be returning anything and will be executed in call order, **one after another** even if *actions* calls are done from another *action* call.

@@ -14,5 +60,6 @@

// example usage
import {Data, View, Domain} from 'immview';
import {Data, Merge, Domain} from 'immview'
const EyesDomain = new Domain(
new View({
new Merge({
HorizonDomain,

@@ -23,8 +70,8 @@ MusclesDomain,

roll() {
MusclesDomain.doStuff();
MusclesDomain.doStuff()
}
}
);
)
EyesDomain.roll();
EyesDomain.roll()
```

@@ -34,3 +81,3 @@

bypassed to state stream given in constructor (see `Data` or `View`)
bypassed to state stream given in constructor (see `Data.read`)

@@ -40,25 +87,41 @@ > Although **Domain** can be created using **Data**, Domain won't be having **write** method available to discourage writing directly from dependent instances.

### Domain::subscribe (since 1.2)
bypassed to state stream given in constructor (see `Data`)
bypassed to state stream given in constructor (see `Data.subscribe`)
### Domain::map (since 1.4)
bypassed to state stream given in constructor (see `Data`)
bypassed to state stream given in constructor (see `Data.map`)
### Domain::debounce (since 1.5)
bypassed to state stream given in constructor (see `Data`)
bypassed to state stream given in constructor (see `Data.debounce`)
### Domain::throttle (since 1.5)
bypassed to state stream given in constructor (see `Data`)
bypassed to state stream given in constructor (see `Data.throttle`)
### Domain::scan (since 1.6)
bypassed to state stream given in constructor (see `Data`)
bypassed to state stream given in constructor (see `Data.scan`)
### Domain::[ACTION_NAME]
function that existed on a set of functions provided as actions in constructor. It is not exactly the same function as it is wrapped, so it is run in **Dispatcher** queue.
```javascript
const domain = new Domain(
new Data(0),
{ foo: () => console.log('bar') }
)
domain.foo()
// prints: 'bar'
```
### Domain::[ACTION_NAME].originalLength (since 1.6)
Amount of arguments indicated by original action function
## Data
### class
#### ( initialData: Immutable )
```javascript
import {Data} from 'immview';
domain.foo.originalLength // 0
```
## class `Data`
#### extends `Observable`
#### ( initialData: mixed )
```javascript
import {Data} from 'immview'
new Data( 2 )

@@ -69,85 +132,48 @@ ```

### Data::read
#### () => Immutable
Method used to retrieve current structure holden by the Data.
```javascript
// Example
const source = new Data(fromJS({a: 1}));
source.read().get('a'); // = 1
```
### Data::write
#### (change: Immutable ) => void
#### (change: (currentStructure) => Immutable) => void
#### (change: mixed ) => void
#### (change: (currentStructure) => mixed) => void
Method used to store new Immutable data structure.
Method used to store new data structure.
**change** parameter:
**change** parameter is:
- is any Immutable data structure that should replace current one. If passed value is either undefined or null, replacement will not occur...
- ...or a function that should return Immutable data structure that should replace current one. If function returns undefined or null, replacement will not occur.
- any data structure that should replace current one. If passed value is either undefined or null, replacement will not occur;
- a function that should return a data structure that should replace current one. If function returns undefined or null, replacement will not occur.
This function will not return changed structure so chaining will not be possible. It is because if this the change is requested during inside queued function (another *write* call or a **Domain** command), it will be postponed and executed after all currently queued commands. You should never presume timing of write execution.
```javascript
const source = new Data({a: 1})
source.write({a: 2})
```javascript
const source = new Data(fromJS({a: 1}));
source.write(fromJS({a: 2}));
source.write(data => data.set('b', 3));
/*
be also warned, that you should not change any data structures you are given inside these functions
*/
source.write(data => ({ ...data, b: 3}))
```
### Data::subscribe
#### ( reaction: (data: Immutable) => void ) => () => void
Registers a function called every time when the Data changes value that it holds. Returns a function to unregister the subscription.
If already inside **Dispatcher** queue, replacement will be postponed and executed after all currently queued commands. This may be even more varied with non-standard **Dispatcher.tick** function. **You should never presume timing of write execution.**
### Data::map
#### ( processor: (data: Immutable) => Immutable ) => View (since 1.4)
Creates new **View** with the current instance as a data source and **processor** as transformer function. **Processor** function will receive Immutable data structure and should be returned Immutable data structure too.
## class `View`
#### extends `Observable`
#### ( source: Observable, processor: (sourceData: mixed) => mixed )
### Data::debounce
#### ( timeout: number ) => Debounce (since 1.5)
Creates a new stream of values being pushed with a provided delay since last update.
### Data::throttle
#### ( timeout: number ) => Throttle (since 1.5)
Creates a new stream of values being push with a provided delay since first update.
### Data::scan
#### ( valuesToRemember: number, initialValue: any ) => Scan (since 1.6)
Creates a new stream of `List` of values that were pushed from a source stream recently. List has a max length of `valuesToRemember` argument. Additionally for first `valuesToRemember - 1` runs if `initialValue` is provided, `List` of values is always `valuesToRemember` long and filled with `initialValue` for not yet existing steps.
## View
### class
#### ( sourceDataProvider: Stream )
#### ( sourceDataProvider: { [string]: Stream } )
#### ( sourceDataProvider: Stream, processor: (sourceData: Immutable) => Immutable )
#### ( sourceDataProvider: { [string]: Stream } , processor: (sourceData: { [string]: Immutable }) => Immutable )
```javascript
import {View} from 'immview';
import { Data, View } from 'immview'
// duplicate source
new View ( sourceDataProvider: Stream )
// join sources into a Map
new View ( sourceDataProvider: { [string]: Stream } )
// transform source with processor function
new View (
sourceDataProvider: Stream,
processor: (sourceData: Immutable) => Immutable
)
const place = new Data(0)
const transformation = new View (place, v => v + 1)
transformation.read() === 1 // true
// join sources into a Map and transform it with processor function
new View (
sourceDataProvider: { [string]: Stream } ,
processor:
(sourceData: { [string]: Immutable}) => Immutable
)
place.write(1)
transformation.read() === 2 // true
```
Constructor of **View** object takes any source (a stream or a **Domain**) as first argument and optionally function transforming this data as a second argument.
A processor function will receive an Immutable data structure and its result must be any Immutable.js data structure. Returning Null or undefined will result in no subscription being fired.
A processor function will receive a value and has to return next one that will be state of current node.
Returning a `Promise` will result in subscriptions being fired upon that `Promise` resolution.
Returning **null** or **undefined** will result in no subscription being fired.
### View::read

@@ -171,9 +197,25 @@ Same as `Data` function of the same name.

## Debounce (since 1.5)
### class
#### ( sourceStream, delay: number )
## class `Merge`
(since 1.7)
#### extends `Observable`
#### ( { [name: string]: Observable } )
Responsible for being reactive to more than one source and placing source streams contents in their respective (according to informations provided upon initialization) place.
```javascript
const join = new Merge({
a: new Data('a'),
b: new Data('b')
})
join.read() // { a: 'a', b: 'b' }
```
## class `Debounce`
(since 1.5)
#### extends `Observable`
#### ( source: Observable, delay: number )
```javascript
new Debouce(sourceStream, 10)
// or
sourceStream.debounce(delay)
sourceStream.debounce(10)
```

@@ -184,9 +226,11 @@

## Throttle (since 1.5)
### class
#### ( sourceStream, delay: number )
## class `Throttle`
(since 1.5)
#### extends `Observable`
#### ( source: Observable, delay: number )
```javascript
new Throttle(sourceStream, 10)
// or
sourceStream.throttle(delay)
sourceStream.throttle(10)
```

@@ -197,9 +241,33 @@

## Scan (since 1.6)
### class
#### ( sourceStream, valuesToRemember: number = 2, initialValue: any = null )
## class `Scan`
(since 1.6)
#### extends `Observable`
#### ( source: Observable, valuesToRemember: number = 2, initialValue: any = null )
```javascript
new Scan(sourceStream, 2)
// or
sourceStream.scan(valuesToRemember = 2, initialValue = null)
sourceStream.scan(2)
new Scan(sourceStream, 2, {})
// or
sourceStream.scan(2, {})
const source = new Data(0)
const trans =
source
.scan(2)
.map(
numbers => numbers.reduce((sum, num) => sum + num)
)
trans.read() === 0
source.write(1)
trans.read() === 1
source.write(2)
trans.read() === 3
source.write(3)
trans.read() === 5
```

@@ -211,5 +279,26 @@

## Dispatcher
### module
## class `Reduce`
(since 1.7)
### extends `Observable`
#### &lt;T, U&gt;(source: Observable&lt;T&gt;, (resultState: &lt;U&gt;, sourceState: T) =&gt; U)
```javascript
const source = new Data(0)
const result = new Reduce(
source,
(resultState, sourceState) => resultState + sourceState
)
source.write(1)
result.read() === 1
source.write(2)
result.read() === 3
source.write(3)
result.read() === 6
```
## module `Dispatcher`
### Dispatcher.logger (since 1.5)

@@ -231,3 +320,3 @@

### Dispatcher.dispatch( action: function, context: any, args: Array<any> ) (since 1.5)
### Dispatcher.dispatch( action: function, context: any, args: any[] ) (since 1.5)

@@ -234,0 +323,0 @@ Call to place action on a queue. Can be imported directly from package too.

@@ -64,3 +64,3 @@ var webpackConfig = require('./webpack.config.js');

browsers: process.env.TRAVIS ? ['PhantomJS'] : ['Chrome'],
browsers: process.env.TRAVIS ? ['PhantomJS'] : ['Chrome', 'Firefox', 'Safari'],

@@ -67,0 +67,0 @@ // Continuous Integration mode

{
"name": "immview",
"version": "1.6.2",
"version": "1.7.0",
"description": "",

@@ -17,3 +17,4 @@ "main": "dist/immview.js",

"fix:tests": "$(npm bin)/jscs --fix tests/*.js",
"fix": "npm run fix:src; npm run fix:tests;"
"fix": "npm run fix:src; npm run fix:tests;",
"flow": "flow; test $? -eq 0 -o $? -eq 2"
},

@@ -25,5 +26,8 @@ "author": "Artur Kulig",

"babel-loader": "^6.2.0",
"babel-plugin-transform-flow-strip-types": "^6.14.0",
"babel-plugin-transform-object-rest-spread": "^6.8.0",
"babel-polyfill": "^6.2.0",
"babel-preset-es2015": "^6.1.18",
"flow-bin": "^0.32.0",
"immutable": "^3.8.1",
"jasmine": "^2.4.1",

@@ -37,4 +41,6 @@ "jasmine-core": "^2.3.4",

"karma-coverage": "^0.5.3",
"karma-firefox-launcher": "^1.0.0",
"karma-jasmine": "^0.3.6",
"karma-phantomjs-launcher": "^0.2.1",
"karma-safari-launcher": "^1.0.0",
"karma-sourcemap-loader": "^0.3.6",

@@ -47,5 +53,5 @@ "karma-webpack": "^1.7.0",

},
"dependencies": {
"immutable": "^3.7.5"
"engines": {
"node": ">=6"
}
}

@@ -1,13 +0,10 @@

# immview 1.6
# <img src="https://raw.githubusercontent.com/arturkulig/immview/master/immview.png" />
Immview is a library to create **Domains** - *non-visual components* - similar to flux stores, exposing their **state** through *observables* pushing immutable data structures and having their own, specific to them **actions**. It can be used in place of any flux implementation, redux.
Immview is a library to create **Domains** - *non-visual components* - similar to flux stores, exposing their **state** through *observables* pushing data and having specific to them **actions**. It can be used instead of any flux implementation or redux.
State of a **Domain** can be either *original* data source (**Data**) or *derivative* data source (**View**). **Views** can be **only** a derivative of other stream (or combination of sources) and optionally use a processing function. By connecting these, derivative data source subscribes to all changes of it's source (or sources) and recomputes it's content upon these changes.
State of a **Domain** can be either an *original* data source (**Data**) or a *derivative* data source (**View/Merge/Debounce/Throttle/Scan**). **Views** etc. can be **only** a derivative of other stream (or combination of sources) and eventually use pure transforming function. By connecting these nodes, derivative data source subscribes to all changes of it's source (or sources) and recomputes it's content upon these changes.
If you familiar with stream libraries like Rx\* **Data** can be seen as an observable and **View** be merging and/or mapping of original stream.
If you familiar with stream libraries like Rx\* **Data** can be seen as an original observable and others are transformation functions like `map` effectively producing new observable.
All **Domains** must be provided with a state stream (so either **Data** or a **View**), but not all storages must be assigned to a **Domain**.
State storages (thanks to use of Immutable.js) will only push changes only if actual change is detected.
**Domains** are exposing same interface as Data and View and bypassing method calls to assigned streams.
## Installation

@@ -27,5 +24,4 @@

* [Reactive logic with immview](https://medium.com/@arturkulig/reactive-logic-with-immview-cf60ff06b7dc) - an introduction to reasoning behind immview
* [Introduction to Immutable.js (Auth0 Blog)](https://auth0.com/blog/2016/03/23/intro-to-immutable-js/)
* [Documentation](./docs.md)
* [Simple usage](./usage_simple.md)
* [Changelog](./changelog.md)

@@ -1,27 +0,34 @@

import { dispatchDataWrite } from './Dispatcher';
import Reactor from './Reactor.js';
//@flow
import Observable from './Observable';
export default function Data(initialData) {
Reactor.call(this);
export default function Data(initialData: any) {
Observable.call(this);
this.digest(initialData);
this._digest(initialData);
this.pendingChanges = [];
}
Data.prototype = Object.create(Reactor.prototype);
Data.prototype = Object.create(Observable.prototype);
/**
* Dispatch a change instruction to the Data
* @param {Iterable|function(data: Iterable):Iterable} change
*/
Data.prototype.write = function (change) {
dispatchDataWrite(() => {
if (this.closed) {
return;
}
if (typeof change === 'function') {
this._digest(change(this.read()));
} else {
this._digest(change);
}
}, this);
if (this.closed) return;
if (typeof change === 'function') {
this.pendingChanges.push(change);
this.consume(this, executePendingChanges);
} else {
this.consume(change);
}
};
Data.prototype.destroy = function () {
Observable.prototype.destroy.call(this);
this.pendingChanges = null;
};
function executePendingChanges(observable: Data) {
const changed = observable.pendingChanges.reduce(
(result, change) => change(result),
observable.read()
);
observable.pendingChanges = [];
return changed;
}

@@ -1,7 +0,8 @@

import Reactor from './Reactor.js';
//@flow
import Observable from './Observable';
const errorPrefix = 'Immview::Debounce: ';
export default function Debounce(source, timeout = 0) {
Reactor.call(this);
export default function Debounce(source: Observable, timeout: number = 0) {
Observable.call(this);

@@ -13,3 +14,3 @@ if (!(source && source.subscribe)) {

this.timeoutID = null;
this._digest(source.read());
this.digest(source.read());
this.subscription = source.addSubscription(data => {

@@ -21,3 +22,3 @@ if (this.timeoutID) {

this.timeoutID = null;
this._consume(data);
this.consume(data);
}, timeout);

@@ -27,3 +28,3 @@ });

Debounce.prototype = Object.create(Reactor.prototype);
Debounce.prototype = Object.create(Observable.prototype);

@@ -38,3 +39,3 @@ Debounce.prototype.destroy = function () {

}
Reactor.prototype.destroy.call(this);
Observable.prototype.destroy.call(this);
};

@@ -0,1 +1,2 @@

//@flow
import {

@@ -5,10 +6,15 @@ dispatchDataWrite,

} from './Dispatcher';
import type Observable from './Observable';
const schedule = [];
const schedule: {
observable: Observable,
data: any,
process: (subject: any) => any
}[] = [];
export function queue(observable, data, process) {
export function queue(observable: Observable, data: any, process: (subject: any) => any) {
dispatchDataConsume(
() => {
scheduleObservableConsumption(observable, data, process);
processQueue();
dispatchQueueExecution();
}

@@ -20,7 +26,7 @@ );

for (let i = 0; i < schedule.length; i++) {
if (schedule[i].observable._id === observable._id) {
if (schedule[i].observable.priority === observable.priority) {
schedule[i].data = data;
return;
}
if (schedule[i].observable._id > observable._id) {
if (schedule[i].observable.priority > observable.priority) {
schedule.splice(i, 0, { observable, data, process });

@@ -33,12 +39,12 @@ return;

function processQueue() {
dispatchDataWrite(executeNextJob);
function dispatchQueueExecution() {
dispatchDataWrite(executeQueue);
}
function executeNextJob() {
function executeQueue() {
if (schedule.length) {
const [{ observable, data, process }] = schedule.splice(0, 1);
observable._digest(process(data));
processQueue();
observable.digest(process(data));
dispatchQueueExecution();
}
}

@@ -0,3 +1,10 @@

//@flow
let isRunning = false;
let queue = [];
let queue: {
action: () => any,
context: any,
args: any[],
priority: number
}[] = [];
const errorPrefix = 'Immview::Dispatcher: ';

@@ -13,3 +20,3 @@

tick(func) {
tick(func: () => any) {
func();

@@ -34,3 +41,3 @@ },

/**
/*
* Execute first action of current queue

@@ -52,6 +59,8 @@ */

const toRun = findMaxPriority();
queue.splice(
queue.indexOf(toRun),
1
);
if (toRun) {
queue.splice(
queue.indexOf(toRun),
1
);
}
return toRun;

@@ -73,10 +82,11 @@ }

/**
/*
* Append new action onto end of the queue
* @param {Function} action
* @param {*} context
* @param {Array.<*>} args
* @param {number} priority (higher number - sooner execution)
*/
function appendToQueue(action, context = null, args = [], priority = PRIORITY_EXT) {
function appendToQueue(
action: () => any,
context?:any = null,
args?: any[] = [],
priority?: number = PRIORITY_EXT
) {
queue.push({

@@ -90,26 +100,22 @@ priority,

function dispatchDomainAction(action, context, args) {
function dispatchDomainAction(action: () => any, context?: any, args?: any[]) {
dispatch(action, context, args, PRIORITY_DOMAIN);
}
function dispatchDataWrite(action, context, args) {
function dispatchDataWrite(action: () => any, context?: any, args?: any[]) {
dispatch(action, context, args, PRIORITY_DATA_WRITE);
}
function dispatchDataConsume(action, context, args) {
function dispatchDataConsume(action: () => any, context?: any, args?: any[]) {
dispatch(action, context, args, PRIORITY_DATA_CONSUMING);
}
function dispatchExternal(action, context, args) {
function dispatchExternal(action: () => any, context?: any, args?: any[]) {
dispatch(action, context, args, PRIORITY_EXT);
}
/**
/*
* Place provided function on a queue and run it as soon as possible
* @param {function} action
* @param {*} [context]
* @param {Array.<*>} [args]
* @param {number} [priority=0] priority for dispatched action.
*/
function dispatch(action, context, args, priority) {
function dispatch(action: () => any, context?: any, args?: any[], priority: number) {
appendToQueue(action, context, args, priority);

@@ -119,3 +125,3 @@ startQueue();

/**
/*
* Starts executing the queue

@@ -155,8 +161,7 @@ */

/**
/*
* Removes all queued actions tied with a context
* @param context
*/
function rejectContext(context) {
function rejectContext(context: any) {
queue = queue.filter(item => item.context !== context);
}

@@ -0,1 +1,2 @@

//@flow
import {

@@ -5,3 +6,3 @@ dispatchDomainAction,

} from './Dispatcher.js';
import Observable from './Reactor';
import Observable from './Observable';
const noop = () => null;

@@ -11,14 +12,10 @@

/**
/*
* Create a domain holding a view
* @param {Observable} stream
* @optional
* @param {Object.<function>} actions
*/
export default function Domain(stream, actions) {
export default function Domain(stream: Observable, actions: { [id: string]: () => any}) {
if (!stream.subscribe) {
throw new Error(`${errorPrefix} stream source required`);
}
/**
* @type {Observable}
/*
*/

@@ -30,5 +27,4 @@ this.stream = stream;

Domain.prototype = {
/**
/*
* Retrieve last value on stream attached to the Domain
* @returns {Iterable}
*/

@@ -45,58 +41,31 @@ read() {

/**
* Create a new stream from a stream attached to the Domain
* @param {function(Iterable)} nextProcessor
* @returns {View}
*/
map(nextProcessor) {
return this.stream.map(nextProcessor);
map(...args) {
return this.stream.map.apply(this.stream, args);
},
/**
* Create a new stream that will not trigger its subscriptions
* until given amount of miliseconds will pass from last call
* @param {number} timeout
* @returns {Debounce}
*/
debounce(timeout) {
return this.stream.debounce(timeout);
debounce(...args) {
return this.stream.debounce.apply(this.stream, args);
},
/**
* Create a new stream
* that will not trigger its subscriptions immediately,
* but defers updates for a number of miliseconds
* provided with timeout argument
* after first call
* @param {number} timeout
* @returns {Throttle}
*/
throttle(timeout) {
return this.stream.throttle(timeout);
throttle(...args) {
return this.stream.throttle.apply(this.stream, args);
},
scan(valuesToRemember, initialValue) {
return this.stream.scan(valuesToRemember, initialValue);
scan(...args) {
return this.stream.scan.apply(this.stream, args);
},
/**
* Register a listener to changes on data stream.
* Calls provided method upon registration.
* @param reaction
* @returns {function()} unsubscribe
*/
subscribe(reaction) {
return this.stream.subscribe(reaction);
reduce(...args) {
return this.stream.reduce.apply(this.stream, args);
},
/**
* Register a listener to changes on data stream.
* @param reaction
* @returns {function()} unsubscribe
*/
addSubscription(reaction) {
return this.stream.addSubscription(reaction);
subscribe(...args) {
return this.stream.subscribe.apply(this.stream, args);
},
/**
addSubscription(...args) {
return this.stream.addSubscription.apply(this.stream, args);
},
/*
* Remove all subscriptions caused by the domain.

@@ -103,0 +72,0 @@ * Destroy stream attached to it.

@@ -1,7 +0,11 @@

import Domain from './Domain.js';
import Data from './Data.js';
import View from './View.js';
import Debounce from './Debounce.js';
import Throttle from './Throttle.js';
import Scan from './Scan.js';
//@flow
import Observable from './Observable';
import Domain from './Domain';
import Data from './Data';
import View from './View';
import Debounce from './Debounce';
import Throttle from './Throttle';
import Scan from './Scan';
import Merge from './Merge';
import Reduce from './Reduce';
import {

@@ -13,2 +17,3 @@ Dispatcher,

export {
Observable,
Data,

@@ -20,4 +25,6 @@ View,

Scan,
Merge,
Reduce,
Dispatcher,
dispatch,
};

@@ -1,5 +0,10 @@

import Reactor from './Reactor.js';
//@flow
import Observable from './Observable';
export default function Scan(source, valuesToRemember = 2, initialValue = null) {
Reactor.apply(this);
export default function Scan(
source: Observable,
valuesToRemember: number = 2,
initialValue: any = null
) {
Observable.apply(this);

@@ -11,3 +16,3 @@ let history = pushToHistory(

);
this._digest(history);
this.digest(history);

@@ -17,3 +22,3 @@ this.unsubscribe = source.addSubscription(

history = pushToHistory(history, valuesToRemember, sourceData);
this._consume(history);
this.consume(history);
}

@@ -23,10 +28,9 @@ );

Scan.prototype = Object.create(Reactor.prototype);
Scan.prototype = Object.create(Observable.prototype);
Scan.prototype.read = function () {
return [].concat(Reactor.prototype.read.apply(this));
Scan.prototype.read = function (): mixed {
return [].concat(Observable.prototype.read.apply(this));
};
Scan.prototype.destroy = function () {
Reactor.prototype.destroy.apply(this);
Observable.prototype.destroy.apply(this);

@@ -54,2 +58,3 @@ if (this.unsubscribe) {

return newHistory;
}

@@ -1,7 +0,8 @@

import Reactor from './Reactor.js';
//@flow
import Observable from './Observable';
const errorPrefix = 'Immview::Throttle: ';
export default function Throttle(source, timeout = 0) {
Reactor.call(this);
export default function Throttle(source: Observable, timeout: number = 0) {
Observable.call(this);

@@ -14,3 +15,3 @@ if (!(source && source.subscribe)) {

this.timeoutedData = null;
this._digest(source.read());
this.digest(source.read());
this.subscription = source.addSubscription(data => {

@@ -21,3 +22,3 @@ this.timeoutedData = data;

this.timeoutID = null;
this._consume(this.timeoutedData);
this.consume(this.timeoutedData);
}, timeout);

@@ -28,3 +29,3 @@ }

Throttle.prototype = Object.create(Reactor.prototype);
Throttle.prototype = Object.create(Observable.prototype);

@@ -39,3 +40,3 @@ Throttle.prototype.destroy = function () {

}
Reactor.prototype.destroy.call(this);
Observable.prototype.destroy.call(this);
};

@@ -0,8 +1,13 @@

//@flow
import ViewMergeMap from './ViewMergeMap';
import Reactor from './Reactor.js';
import Observable from './Observable';
import env from './env';
const errorPrefix = 'Immview::View: ';
export default function View(source, process = identity) {
Reactor.call(this);
export default function View(
source: Observable,
process: (subject: any) => any = identity
) {
Observable.call(this);

@@ -20,6 +25,6 @@ if (source && typeof source === 'object') {

View.prototype = Object.create(Reactor.prototype);
View.prototype = Object.create(Observable.prototype);
View.prototype.destroy = function destroyView() {
Reactor.prototype.destroy.call(this);
View.prototype.destroy = function () {
Observable.prototype.destroy.call(this);

@@ -38,5 +43,5 @@ if (this.unsubs) {

function connectToSource(aView, source, process) {
aView._digest(process(source.read()));
aView.digest(process(source.read()));
return [
source.addSubscription(data => aView._consume(data, process)),
source.addSubscription(data => aView.consume(data, process)),
];

@@ -46,2 +51,10 @@ }

function connectToMultipleSources(aView, sources, process) {
if (env !== 'production') {
console.warn([
errorPrefix,
'View usage for merging streams is deprecated since 1.7.',
'Consider changing to Merge type of node.',
].join(' '));
}
// initialize as a map{string:Iterable}

@@ -64,3 +77,3 @@ let mergedStructure = new ViewMergeMap();

mergedStructure = mergedStructure.set(sourceName, data);
aView._consume(mergedStructure.clone(), process);
aView.consume(mergedStructure.clone(), process);
}

@@ -70,5 +83,5 @@ )

aView._digest(process(mergedStructure.clone()));
aView.digest(process(mergedStructure.clone()));
return unsubs;
}

@@ -0,1 +1,2 @@

//@flow
/*

@@ -9,3 +10,3 @@ Reason to have this class is to support existing code

export default function ViewMergeMap(initialObject) {
export default function ViewMergeMap(initialObject?: Object) {
for (let prop in initialObject) {

@@ -12,0 +13,0 @@ if (Object.prototype.hasOwnProperty.call(initialObject, prop)) {

@@ -103,6 +103,4 @@ import Data from '../src/Data';

const getDataMap = () => fromJS({ a: 1, b: { c: 2 } });
const d = new Data(fromJS({ a: 1, b: { c: 2 } }));
const d = new Data(getDataMap());
d.subscribe(() => {

@@ -113,7 +111,7 @@ reactions++;

expect(reactions).toBe(1); // subscription -> fake reaction
d.write(getDataMap().set('d', 3)); // change -> reaction
d.write(map => map.set('d', 3)); // change -> reaction
expect(reactions).toBe(2);
d.write(getDataMap().set('d', 3)); // no change -> no reaction
d.write(map => map); // no change -> no reaction
expect(reactions).toBe(2);
d.write(getDataMap().set('d', 4)); // change -> reaction
d.write(map => map.set('d', 4)); // change -> reaction
expect(reactions).toBe(3);

@@ -156,2 +154,3 @@ });

b.write(i => i + 1);
b.write(i => i + 1);

@@ -164,3 +163,3 @@ // as they are queued, updates are not yet performed

expect(a.read()).toBe(1);
expect(b.read()).toBe(2);
expect(b.read()).toBe(3);
});

@@ -183,3 +182,6 @@

dispatch(() => {
a.write(1);
a.write(() => {
expect(true).toBe(false);
throw new Error('should not happen');
});
a.destroy();

@@ -186,0 +188,0 @@ });

@@ -26,3 +26,3 @@ import { Data, View, Domain, Debounce } from '../src';

jasmine.clock().tick(11);
jasmine.clock().tick(20);
expect(debounced.read()).toBe('j');

@@ -29,0 +29,0 @@ });

@@ -0,11 +1,15 @@

import './switchedTicker.spec';
import './data.spec';
import './view.spec';
import './dispatcher.spec.js';
import './merge.spec';
import './dispatcher.spec';
import './domain.spec';
import './debounce.spec';
import './throttle.spec';
import './scan.spec';
import './reduce.spec';
import './interface.spec';
import './branchingStreamPerformantRender';
import './switchedTicker.spec';
import './classExtending';
import './scan.spec';
import './immutabilize.spec';
import './asyncNodes.spec';

@@ -5,2 +5,4 @@ import {

Debounce,
Throttle,
Scan,
Domain,

@@ -19,2 +21,3 @@ Dispatcher,

expect(typeof instance.scan).toBe('function');
expect(typeof instance.reduce).toBe('function');
}

@@ -45,2 +48,16 @@

});
it('Throttle', () => {
expect(Throttle).toBeDefined();
const d = new Data();
const v = new View(d);
const instance = new Throttle(v);
fulfillsReactorInterface(instance);
});
it('Scan', () => {
expect(Scan).toBeDefined();
const d = new Data();
const v = new View(d);
const instance = new Scan(v);
fulfillsReactorInterface(instance);
});
it('Domain', () => {

@@ -47,0 +64,0 @@ expect(Domain).toBeDefined();

@@ -7,12 +7,15 @@ import {

const standardTicker = Dispatcher.tick;
describe('switching dispatcher ticker', () => {
const standardTicker = Dispatcher.tick;
beforeEach(() => {
jasmine.clock().install();
Dispatcher.tick = f => setTimeout(() => {
setTimeout(f, 10);
});
jasmine.clock().install();
});
afterEach(() => {
jasmine.clock().tick(40);
jasmine.clock().uninstall();

@@ -25,2 +28,3 @@ Dispatcher.tick = standardTicker;

const B = new View(A, str => str + '!');
expect(A.read()).toBe('a');

@@ -30,7 +34,8 @@ expect(B.read()).toBe('a!');

A.write('b');
expect(A.read()).toBe('a');
expect(B.read()).toBe('a!');
jasmine.clock().tick(20);
jasmine.clock().tick(20);
jasmine.clock().tick(40);
expect(A.read()).toBe('b');

@@ -37,0 +42,0 @@ expect(B.read()).toBe('b!');

@@ -136,2 +136,13 @@ import Domain from '../src/Domain';

});
typeof window !== 'undefined' &&
window.Proxy &&
it('value given for processing is frozen', () => {
expect(() => {
new Data({ a: 1 }).map(v => {
v.a = 2;
return v;
}).subscribe(v => console.log('WRONG', v));
}).toThrow();
});
});
# Simple usage example
In order to create a complete **Domain** we have to create state stream and actions.
This example requires you to know and understand [Immutable.js](https://facebook.github.io/immutable-js/) already.
## State
Let's create *To do* domain. It should have it's state and best way to stream it is with expectable structure. We will stream `List<Record<{label: string, done: boolean}>>` then.
Let's create *To do* domain. It should have it's state and best way to stream it is with expectable structure. We will stream `Array<{label: string, done: boolean}>` then.
```javascript
import { Data, Domain } from 'immview';
import { List, Record } from 'immutable';
import { Data, Domain } from 'immview'
const ToDoEntry = Record({label:'', done: false});
const ToDoDomainStream = new Data(List());
const ToDoDomainStream = new Data([])
```

@@ -29,5 +26,5 @@

value => value.push(
new ToDoEntry({ label })
{ label, done: false }
)
);
)
},

@@ -37,7 +34,11 @@

ToDoDomainStream.write(
value => value.setIn(
[index, 'done'],
true
)
);
value => {
const copy = [...value]
copy[index] = {
...value[index],
done: true
}
return copy;
}
)
},

@@ -47,6 +48,7 @@

ToDoDomainStream.write(
value => value.remove(index)
);
value =>
value.filter((_, i) => i !== index)
)
}
};
}
```

@@ -62,3 +64,3 @@

ToDoDomainActions
);
)
```

@@ -69,10 +71,16 @@

```javascript
ToDoDomain.subscribe(v => console.log(v.toJS()));
// []
ToDoDomain.read()
// returns: []
ToDoDomain.add('Eat a pizza');
// [{ label: "Eat a pizza" }]
ToDoDomain.subscribe(v => console.log(v))
// outputs: []
// and will output every next ToDoDomain's state
ToDoDomain.check(0);
// [{ label: "Eat a pizza", done: true }]
ToDoDomain.add('Eat a pizza')
ToDoDomain.read()
// returns: [{ label: "Eat a pizza" }]
ToDoDomain.check(0)
ToDoDomain.read()
// returns: [{ label: "Eat a pizza", done: true }]
```

@@ -79,0 +87,0 @@

@@ -0,1 +1,2 @@

// jscs:disable
var path = require('path');

@@ -19,6 +20,7 @@ var webpack = require('webpack');

test: /\.js$/,
exclude: /node_modules\/immutable\/dist\/immutable\.js/,
loader: 'babel',
query: {
presets: ['es2015'],
plugins: ['transform-object-rest-spread'],
plugins: ['transform-object-rest-spread', 'transform-flow-strip-types'],
},

@@ -29,3 +31,9 @@ },

devtool: 'source-map',
plugins: [],
plugins: [
new webpack.DefinePlugin({
'process.env':{
'NODE_ENV': JSON.stringify(process.env.NODE_ENV)
}
})
]
};

@@ -32,0 +40,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc