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.5.2 to 1.6.0

src/Digest.js

13

changelog.md
##Changelog
### 1.6
- feat: `Scan` and `*.scan` added
- feat: Actions mounted on domain have additional property originalLength to indicate arguments amount of original action function
#### On the road to have Immutable.js as option
- fix: `Data` no longer *magically* transforms initial data provided in constructor to Immutable.js data structure
- fix: `View` is merging different streams using plain objects instead of Immutable.js map
### 1.5.2

@@ -15,4 +24,4 @@

- feat: streams are sorted so nodes are waiting with their updates for their dependencies are resolved
- feat: `Debounce` and *.debounce() added
- feat: `Throttle` and *.throttle() added
- feat: `Debounce` and `*.debounce()` added
- feat: `Throttle` and `*.throttle()` added
- feat: `Dispatcher` is exposed now

@@ -19,0 +28,0 @@ - feat: `dispatch` function is directly exposed by package for convenience

2

dist/immview.js

@@ -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 o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.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.Throttle=e.Debounce=e.Domain=e.View=e.Data=void 0;var o=n(1),i=r(o),u=n(3),s=r(u),c=n(8),a=r(c),f=n(9),l=r(f),d=n(10),h=r(d),p=n(2),m=r(p),v=m.default.dispatch;e.Data=s.default,e.View=a.default,e.Domain=i.default,e.Debounce=l.default,e.Throttle=h.default,e.Dispatcher=m.default,e.dispatch=v},function(t,e,n){"use strict";function r(t,e){if(!t.subscribe)throw Error(u+" stream source required");this.stream=t,this._claimActions(e)}Object.defineProperty(e,"__esModule",{value:!0}),e.default=r;var o=n(2),i=function(){return null},u="Immview::Domain: ";r.prototype={_claimActions:function(t){var e=this;this._actionNames=t?Object.keys(t):[],this._actionNames.forEach(function(n){if(e[n])throw Error(""+u+n+" is reserved for Domain interface");if("function"!=typeof t[n])throw Error(""+u+n+" action is not a function");e[n]=function(){for(var r=arguments.length,i=Array(r),u=0;r>u;u++)i[u]=arguments[u];(0,o.dispatchDomainAction)(t[n],e,i,1)}})},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)},subscribe:function(t){return this.stream.subscribe(t)},appendReactor:function(t){return this.stream.appendReactor(t)},destroy:function(){var t=this;this.stream.destroy(),this.stream=null,(0,o.rejectContext)(this),this._actionNames.forEach(function(e){t[e]=i}),this._actionNames=null}}},function(t,e){"use strict";function n(t){return t&&"undefined"!=typeof Symbol&&t.constructor===Symbol?"symbol":typeof t}function r(){for(var t=-1,e=null,n=0;v.length>n;n++){var r=v[n].priority;r>t&&(e=v[n],t=r)}return e}function o(){var t=r();return v.splice(v.indexOf(t),1),t}function i(){var t=o();if(t){var e=t.context,n=t.action,r=t.args;n&&n.apply(e,r)}}function u(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]:b;v.push({priority:r,action:t,context:e,args:n})}function s(){m||v.length>0&&(m=!0,O.tick(function(){try{i()}catch(t){c(t)}m=!1,s()}))}function c(t){O.logger.error(g+"Error occured while running a function"),"object"===(void 0===t?"undefined":n(t))?t.stack?O.logger.error(t.stack):O.logger.error(t.name,t.message):O.logger.error(t)}function a(t,e,n,r){u(t,e,n,r),s()}function f(t,e,n){a(t,e,n,y)}function l(t,e,n){a(t,e,n,D)}function d(t,e,n){a(t,e,n,_)}function h(t,e,n){a(t,e,n,b)}function p(t){v=v.filter(function(e){return e.context!==t})}Object.defineProperty(e,"__esModule",{value:!0}),e.dispatch=a,e.dispatchDomainAction=f,e.dispatchDataWrite=l,e.dispatchDataConsume=d,e.dispatchExternal=h,e.rejectContext=p;var m=!1,v=[],g="Immview::Dispatcher: ",b=0,y=1,D=2,_=3,O=e.Dispatcher={dispatch:h,tick:function(t){t()},rejectContext:p,logger:console};e.default=O},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t){a.default.call(this),this.linkTo(null),this.digest((0,u.fromJS)(t))}var i=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t};Object.defineProperty(e,"__esModule",{value:!0}),e.default=o;var u=n(4),s=n(2),c=n(5),a=r(c);o.prototype=i({},a.default.prototype,{write:function(t){var e=this;(0,s.dispatchDataWrite)(function(){e.digest("function"==typeof t?t(e.read()):t)})}})},function(e,n){e.exports=t},function(t,e,n){"use strict";function r(t){return void 0!==t&&null!==t}function o(t,e){return r(e)&&(!r(t)||!(0,a.is)(e,t))}function i(t,e){var n=(0,f.createSchedule)(t);return(0,f.copyQueueOntoSchedule)(e,n)}function u(){(0,f.scheduleLength)(h)>0&&(h=(0,f.runScheduledPriorityJob)(h),(0,l.dispatchDataWrite)(u))}function s(t){return t}function c(){this.reactors=(0,a.Set)()}Object.defineProperty(e,"__esModule",{value:!0}),e.default=c;var a=n(4),f=n(6),l=n(2),d=[],h=[];c.prototype={read:function(){return this.structure},linkTo:function(t){d.push([t&&(t.stream?t.stream:t),this]),h=i(d,h)},unlink:function(){var t=this;d=d.filter(function(e){return e[0]!==t&&e[1]!==t}),h=i(d,h)},consume:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:s;(0,l.dispatchDataConsume)(function(){h=(0,f.scheduleJob)(e,function(){return e.digest(n(t))},h),(0,l.dispatchDataWrite)(u)})},digest:function(t){o(this.structure,t)&&(this.structure=t,this.flush())},appendReactor:function(t){var e=this;return this.reactors=this.reactors.add(t),function(){e.reactors=e.reactors.delete(t)}},subscribe:function(t){return t(this.read()),this.appendReactor(t)},flush:function(){var t=this;this.reactors.forEach(function(e){return e(t.read())})},destroy:function(){this.unlink(),this.structure=null,this.reactors=(0,a.Set)()},map:function(t){var e=n(8).default;return new e(this,t)},debounce:function(t){var e=n(9).default;return new e(this,t)},throttle:function(t){var e=n(10).default;return new e(this,t)}}},function(t,e,n){"use strict";function r(t){return f(t).reduce(function(t,e){return t.unshift([e,null]),t},[])}function o(t,e,n){for(var r=[],o=0;n.length>o;o++){var i=n[o],u=i[0];r.push(u===t?[u,e]:i)}return r}function i(t){for(var e=0,n=0;t.length>n;n++)e+=0|!!t[n][1];return e}function u(t,e){for(var n=0;t.length>n;n++)if(t[n][0]===e)return t[n][1];return null}function s(t,e){for(var n=[].concat(e),r=0;t.length>r;r++){var o=t[r],i=o[0],u=o[1];if(u)for(var s=0;n.length>s;s++){var c=n[s],a=c[0];a===i&&(n[s]=o)}}return n}function c(t){for(var e=null,n=[].concat(t),r=0;t.length>r;r++){var o=t[r],i=o[0],u=o[1];if(u){e=u,n[r]=[i,null];break}}return e&&e(),n}Object.defineProperty(e,"__esModule",{value:!0}),e.sortStreamGraph=void 0,e.createSchedule=r,e.scheduleJob=o,e.scheduleLength=i,e.findJob=u,e.copyQueueOntoSchedule=s,e.runScheduledPriorityJob=c;var a=n(7),f=e.sortStreamGraph=a.getOrder},function(t,e){"use strict";function n(t){return t.reduce(function(t,e){return t.indexOf(e[0])<0&&t.push(e[0]),t.indexOf(e[1])<0&&t.push(e[1]),t},[])}function r(t){var e=[],r=[];return n(t).forEach(function(n){if(!e||e.indexOf(n)<0){var i=o(t,n,r,e);e=i.visited,r=i.stack}}),r}function o(t,e,n,r){var u=r.concat([e]),s=n;return i(t,e).forEach(function(e){if(!u||u.indexOf(e)<0){var n=o(t,e,s,u);u=n.visited,s=n.stack}}),{visited:u,stack:s.concat([e])}}function i(t,e){return t.filter(function(t){return t[0]===e}).map(function(t){return t[1]})}Object.defineProperty(e,"__esModule",{value:!0}),e.getGraphNodes=n,e.getOrder=r,e.visit=o,e.getNodeChildren=i},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t){return t&&"undefined"!=typeof Symbol&&t.constructor===Symbol?"symbol":typeof t}function i(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:f;a.default.call(this),t&&"object"===(void 0===t?"undefined":o(t))&&(t.subscribe?this.connectToSource(t,e):this.connectToMultipleSources(t,e))}var u=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t};Object.defineProperty(e,"__esModule",{value:!0}),e.default=i;var s=n(4),c=n(5),a=r(c),f=function(t){return t};i.prototype=u({},a.default.prototype,{connectToSource:function(t,e){var n=this;this.linkTo(t),this.digest(e(t.read())),this.unsubs=[t.appendReactor(function(t){return n.consume(t,e)})]},connectToMultipleSources:function(t,e){var n=this,r=(0,s.Map)(),o=Object.keys(t);o.forEach(function(e){var o=t[e];n.linkTo(o);var i=o.read();r=r.set(e,i)}),this.unsubs=o.map(function(o){return t[o].appendReactor(function(t){r=r.set(o,t),n.consume(r,e)})}),this.digest(e(r))},destroy:function(){a.default.prototype.destroy.call(this),this.unsubs&&this.unsubs.forEach(function(t){return t()}),this.unsubs=null}})},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(s.default.call(this),!t||!t.subscribe)throw Error(c+"incorrect source");this.linkTo(t),this.timeoutID=null,this.digest(t.read()),this.subscription=t.appendReactor(function(t){e.timeoutID&&clearTimeout(e.timeoutID),e.timeoutID=setTimeout(function(){e.timeoutID=null,e.consume(t)},n)})}var i=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t};Object.defineProperty(e,"__esModule",{value:!0}),e.default=o;var u=n(5),s=r(u),c="Immview::Debounce: ";o.prototype=i({},s.default.prototype,{destroy:function(){this.timeoutID&&(clearTimeout(this.timeoutID),this.timeoutID=null),this.subscription&&this.subscription(),s.default.prototype.destroy.call(this)}})},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(s.default.call(this),!t||!t.subscribe)throw Error(c+"incorrect source");this.linkTo(t),this.timeoutID=null,this.timeoutedData=null,this.digest(t.read()),this.subscription=t.appendReactor(function(t){e.timeoutedData=t,e.timeoutID||(e.timeoutID=setTimeout(function(){e.timeoutID=null,e.consume(e.timeoutedData)},n))})}var i=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t};Object.defineProperty(e,"__esModule",{value:!0}),e.default=o;var u=n(5),s=r(u),c="Immview::Throttle: ";o.prototype=i({},s.default.prototype,{destroy:function(){this.timeoutID&&(clearTimeout(this.timeoutID),this.timeoutID=null),this.subscription&&this.subscription(),s.default.prototype.destroy.call(this)}})}])});
!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 u=n[r]={exports:{},id:r,loaded:!1};return t[r].call(u.exports,u,u.exports,e),u.loaded=!0,u.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 u=n(1),i=r(u),o=n(3),s=r(o),c=n(9),a=r(c),f=n(11),l=r(f),d=n(12),h=r(d),p=n(13),m=r(p),v=n(2);e.Data=s.default,e.View=a.default,e.Domain=i.default,e.Debounce=l.default,e.Throttle=h.default,e.Scan=m.default,e.Dispatcher=v.Dispatcher,e.dispatch=v.dispatch},function(t,e,n){"use strict";function r(t,e){if(!t.subscribe)throw Error(s+" 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(""+s+n+" is reserved for Domain interface");if("function"!=typeof r)throw Error(""+s+n+" action is not a function");t[n]=function(){for(var e=arguments.length,n=Array(e),u=0;e>u;u++)n[u]=arguments[u];(0,i.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=r;var i=n(2),o=function(){return null},s="Immview::Domain: ";r.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)},appendReactor:function(t){return this.stream.appendReactor(t)},destroy:function(){var t=this;this.stream.destroy(),this.stream=null,(0,i.rejectContext)(this),this._actionNames.forEach(function(e){t[e]=o}),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=u();if(t){var e=t.context,n=t.action,r=t.args;n&&n.apply(e,r)}}function u(){var t=i();return v.splice(v.indexOf(t),1),t}function i(){for(var t=-1,e=null,n=0;v.length>n;n++){var r=v[n].priority;r>t&&(e=v[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;v.push({priority:r,action:t,context:e,args:n})}function s(t,e,n){l(t,e,n,b)}function c(t,e,n){l(t,e,n,_)}function a(t,e,n){l(t,e,n,O)}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||v.length>0&&(m=!0,D.tick(function(){try{r()}catch(t){h(t)}m=!1,d()}))}function h(t){D.logger.error(g+"Error occured while running a function"),"object"===(void 0===t?"undefined":n(t))?t.stack?D.logger.error(t.stack):D.logger.error(t.name,t.message):D.logger.error(t)}function p(t){v=v.filter(function(e){return e.context!==t})}Object.defineProperty(e,"__esModule",{value:!0});var m=!1,v=[],g="Immview::Dispatcher: ",y=0,b=1,_=2,O=3,D={dispatch:f,tick:function(t){t()},rejectContext:p,logger:console};e.default=D,e.Dispatcher=D,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){return t&&t.__esModule?t:{"default":t}}function u(t){s.default.call(this),this._linkTo(null),this._digest(t)}Object.defineProperty(e,"__esModule",{value:!0}),e.default=u;var i=n(2),o=n(4),s=r(o);u.prototype=Object.create(s.default.prototype),u.prototype.write=function(t){var e=this;(0,i.dispatchDataWrite)(function(){e._digest("function"==typeof t?t(e.read()):t)})}},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 u(){this._reactors=[]}function i(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=u;var c=n(5),a=n(6),f=r(a);u.prototype={read:function(){return this.structure},_linkTo:function(t){f.link(t&&(t.stream?t.stream:t),this)},_unlink:function(){f.unlink(this)},_consume:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:s;f.queue(this,function(){return e._digest(n(t))})},_digest:function(t){i(this.structure,t)&&(this.structure=t,this._flush(t))},_flush:function(t){this._reactors.forEach(function(e){return e(t)})},appendReactor:function(t){var e=this;return this._reactors.indexOf(t)<0&&this._reactors.push(t),function(){e._reactors=e._reactors.filter(function(e){return e!==t})}},subscribe:function(t){return t(this.read()),this.appendReactor(t)},destroy:function(){this._unlink(),this.structure=null,this._reactors=[]},map:function(t){var e=n(9).default;return new e(this,t)},debounce:function(t){var e=n(11).default;return new e(this,t)},throttle:function(t){var e=n(12).default;return new e(this,t)},scan:function(t,e){var r=n(13).default;return new r(this,t,e)}}},function(e,n){e.exports=t},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 u(t,e){a(c().concat([[t,e]]))}function i(t){a(c().filter(function(e){var n=p(e,2),r=n[0],u=n[1];return r!==t&&u!==t}))}function o(t,e){(0,g.dispatchDataConsume)(function(){h(v.scheduleJob(t,e,d())),s()})}function s(){(0,g.dispatchDataWrite)(l)}function c(){return y}function a(t){y=t,h(f(y,d()))}function f(t,e){var n=v.createSchedule(t);return v.copyQueueOntoSchedule(e,n)}function l(){v.scheduleLength(d())>0&&(h(v.runScheduledPriorityJob(d())),(0,g.dispatchDataWrite)(l))}function d(){return b}function h(t){b=t}var p=function(){function t(t,e){var n=[],r=!0,u=!1,i=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){u=!0,i=c}finally{try{!r&&s.return&&s.return()}finally{if(u)throw i}}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.link=u,e.unlink=i,e.queue=o;var m=n(7),v=r(m),g=n(2),y=[],b=[]},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 u(t){return l.getOrder(t).reduce(function(t,e){return t.unshift([e,null]),t},[])}function i(t,e,n){for(var r=[],u=0;n.length>u;u++){var i=n[u],o=i[0];r.push(o===t?[o,e]:i)}return r}function o(t){for(var e=0,n=0;t.length>n;n++)e+=0|!!t[n][1];return e}function s(t,e){for(var n=0;t.length>n;n++)if(t[n][0]===e)return t[n][1];return null}function c(t,e){for(var n=[].concat(e),r=0;t.length>r;r++){var u=t[r],i=u[0],o=u[1];if(o)for(var s=0;n.length>s;s++){var c=n[s],a=c[0];a===i&&(n[s]=u)}}return n}function a(t){for(var e=null,n=[].concat(t),r=0;t.length>r;r++){var u=t[r],i=u[0],o=u[1];if(o){e=o,n[r]=[i,null];break}}return e&&e(),n}Object.defineProperty(e,"__esModule",{value:!0}),e.createSchedule=u,e.scheduleJob=i,e.scheduleLength=o,e.findJob=s,e.copyQueueOntoSchedule=c,e.runScheduledPriorityJob=a;var f=n(8),l=r(f)},function(t,e){"use strict";function n(t){var e=r(t).reduce(function(e,n){return i(e.visited,n)?e:u(t,n,e)},{visited:[],stack:[]});return e.stack}function r(t){return t.reduce(function(t,e){return t.indexOf(e[0])<0&&t.push(e[0]),t.indexOf(e[1])<0&&t.push(e[1]),t},[])}function u(t,e,n){var r=o(t,e).reduce(function(e,n){return i(e.visited,n)?e:u(t,n,e)},{visited:n.visited.concat([e]),stack:n.stack}),s={visited:r.visited,stack:r.stack.concat([e])};return s}function i(t,e){return t.indexOf(e)>=0}function o(t,e){return t.filter(function(t){return t[0]===e}).map(function(t){return t[1]})}Object.defineProperty(e,"__esModule",{value:!0}),e.getOrder=n,e.getAllNodes=r,e.getOrderStartingFromNode=u,e.getNodeChildren=o},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function u(t){return t&&"undefined"!=typeof Symbol&&t.constructor===Symbol?"symbol":typeof t}function i(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:o;if(d.default.call(this),t&&"object"===(void 0===t?"undefined":u(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._linkTo(e),t._digest(n(e.read())),[e.appendReactor(function(e){return t._consume(e,n)})]}function c(t,e,n){var r=new f.default,u=Object.keys(e);u.forEach(function(n){var u=e[n];t._linkTo(u);var i=u.read();r=r.set(n,i)});var i=u.map(function(u){return e[u].appendReactor(function(e){r=r.set(u,e),t._consume(r.clone(),n)})});return t._digest(n(r.clone())),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=i;var a=n(10),f=r(a),l=n(4),d=r(l),h="Immview::View: ";i.prototype=Object.create(d.default.prototype),i.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 u(t){for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&(this[e]=t[e])}Object.defineProperty(e,"__esModule",{value:!0}),e.default=u,u.prototype={clone:function(){return new u(this)},set:function(t,e){var n=new u(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 u;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],u=e.slice(1),i=arguments[1];return u.length?this.get(r).getIn(u,i):void 0===this.get(r)?i:this.get(r)},setIn:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=n(t),r=e[0],i=e.slice(1),o=arguments[1];return i.length?this.set(r,(this.get(r)||new u).setIn(i,o)):this.set(r,o)}}},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function u(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._linkTo(t),this.timeoutID=null,this._digest(t.read()),this.subscription=t.appendReactor(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=u;var i=n(4),o=r(i),s="Immview::Debounce: ";u.prototype=Object.create(o.default.prototype),u.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 u(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._linkTo(t),this.timeoutID=null,this.timeoutedData=null,this._digest(t.read()),this.subscription=t.appendReactor(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=u;var i=n(4),o=r(i),s="Immview::Throttle: ";u.prototype=Object.create(o.default.prototype),u.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 u(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),this._linkTo(t);var u=o(i(r,n),n,t.read());this._digest(u),this.unsubscribe=t.appendReactor(function(t){u=o(u,n,t),e._consume(u)})}function i(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=u;var s=n(4),c=r(s);u.prototype=Object.create(c.default.prototype),u.prototype.read=function(){return[].concat(c.default.prototype.read.apply(this))},u.prototype.destroy=function(){c.default.prototype.destroy.apply(this),this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null)}}])});
//# sourceMappingURL=immview.js.map
#Docs
## Data
## Domain
### class
#### ( source: Stream )
#### ( source: Stream , { [string]: () => void } )
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.
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.
```javascript
// example usage
import {Data, View, Domain} from 'immview';
const EyesDomain = new Domain(
new View({
HorizonDomain,
MusclesDomain,
}),
{
roll() {
MusclesDomain.doStuff();
}
}
);
EyesDomain.roll();
```
### Domain::read (since 1.2)
bypassed to state stream given in constructor (see `Data` or `View`)
> 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`)
### Domain::map (since 1.4)
bypassed to state stream given in constructor (see `Data`)
### Domain::debounce (since 1.5)
bypassed to state stream given in constructor (see `Data`)
### Domain::throttle (since 1.5)
bypassed to state stream given in constructor (see `Data`)
### Domain::scan (since 1.6)
bypassed to state stream given in constructor (see `Data`)
### Domain::[ACTION_NAME].originalLength (since 1.6)
Amount of arguments indicated by original action function
## Data
### class
#### ( initialData: Immutable )
```javascript
import {Data} from 'immview';
new Data( initialData: Immutable )
new Data( 2 )
```
An **initialData** object can be object any Immutable.js data structure.
An **initialData** object can be object any native immutable (bool, string, number) or Immutable.js data structure.
###read() => Immutable
### Data::read
#### () => Immutable

@@ -18,3 +71,3 @@ Method used to retrieve current structure holden by the Data.

```javascript
//Example
// Example
const source = new Data(fromJS({a: 1}));

@@ -24,4 +77,5 @@ source.read().get('a'); // = 1

### write(change: Immutable ) => void
### write(change: (currentStructure) => Immutable) => void
### Data::write
#### (change: Immutable ) => void
#### (change: (currentStructure) => Immutable) => void

@@ -43,15 +97,28 @@ Method used to store new Immutable data structure.

### subscribe( reaction: (data: Immutable) => void ) => () => void
### 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.
### map( processor: (data: Immutable) => Immutable ) => View (since 1.4)
Creates new **View** with the **Data** 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.
### 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.
### debounce( timeout: number ) => Debounce (since 1.5)
### Data::debounce
#### ( timeout: number ) => Debounce (since 1.5)
Creates a new stream of values being pushed with a provided delay since last update.
### throttle( timeout: number ) => Throttle (since 1.5)
### 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 )

@@ -76,3 +143,4 @@ ```javascript

sourceDataProvider: { [string]: Stream } ,
processor: (sourceData: Immutable) => Immutable
processor:
(sourceData: { [string]: Immutable}) => Immutable
)

@@ -84,69 +152,59 @@ ```

### read() => Immutable
### View::read
Same as `Data` function of the same name.
Method used to retrieve current structure holden by the View.
### View::subscribe
Same as `Data` function of the same name.
### subscribe( reaction: (data) => void ) => () => void
Registers a function called every time when the View changes value that it holds. Returns a function to unregister the subscription.
### View::map (since 1.4)
Same as `Data` function of the same name.
### map( processor: (sourceData: Immutable) => Immutable ) => View (since 1.4)
Creates new View with 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.
### View::debounce (since 1.5)
Same as `Data` function of the same name.
### debounce( timeout: number ) => Debounce (since 1.5)
Creates a new stream of values being pushed with a provided delay since last update.
### View::throttle (since 1.5)
Same as `Data` function of the same name.
### throttle( timeout: number ) => Throttle (since 1.5)
Creates a new stream of values being push with a provided delay since first update.
### View::scan (since 1.6)
Same as `Data` function of the same name.
## Domain
## Debounce (since 1.5)
### class
#### ( sourceStream, delay: number )
```javascript
new Domain ( source: Stream )
new Domain ( source: Stream , { [string]: () => void } )
// or
sourceStream.debounce(delay)
```
First argument of constructor is a data source. That will be a *state* stream of the newly created **Domain**. Only single data source can be tied to it, so **Domain** can be used as data source.
Creates a new stream of values being pushed with a provided delay since **last** update.
Shares interface with a **View**.
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.
## Throttle (since 1.5)
### class
#### ( sourceStream, delay: number )
```javascript
// example usage
import {Data, View, Domain} from 'immview';
const EyesDomain = new Domain(
new View({
HorizonDomain,
MusclesDomain,
}),
{
roll() {
MusclesDomain.doStuff();
}
}
);
EyesDomain.roll();
// or
sourceStream.throttle(delay)
```
### read() => Immutable (since 1.2)
Creates a new stream of values being push with a provided delay since **first** update.
Shares interface with a **View**.
Method used to retrieve current Domain's *state*.
## Scan (since 1.6)
### class
#### ( sourceStream, valuesToRemember: number = 2, initialValue: any = null )
> Although **Domain** can be created using **Data**, Domain won't be having **write** method available to discourage writing directly from dependent instances.
```javascript
// or
sourceStream.scan(valuesToRemember = 2, initialValue = null)
```
### subscribe( reaction: (data) => void ) => () => void (since 1.2)
Registers a function called every time when the Domain's *state* changes. Returns a function to unsubscribe from updates.
Creates a new stream of `Arrays` of values that were pushed from a source stream recently. List has a max length of `valuesToRemember` argument. Additionally if `initialValue` is provided for first `valuesToRemember - 1` runs , `Array` of values is always `valuesToRemember` long and filled with `initialValue` for not yet existing steps.
### map( processor: (sourceData: Immutable) => Immutable ) => View (since 1.4)
Creates new View with the Domain instance source as a data source and **processor** as transformer function. **Processor** function will receive Immutable data structure and should be returned Immutable data structure too.
Shares interface with a **View**.
### debounce( timeout: number ) => Debounce (since 1.5)
Creates a new stream of values being pushed with a provided delay since last update.
### throttle( timeout: number ) => Throttle (since 1.5)
Creates a new stream of values being push with a provided delay since first update.
## Debounce, Throttle
These share interface with a **View**.
## Dispatcher
### module

@@ -156,3 +214,6 @@ ### Dispatcher.logger (since 1.5)

Replace to change for logging errors in queue runner
(default: console)
```javascript
// default
Dispatcher.logger = console;
```

@@ -162,6 +223,6 @@ ### Dispatcher.tick (since 1.5)

Replace to change how next function is being called.
default:
```javascript
// default
Dispatcher.tick = func => func();
```
func => func()
```

@@ -171,5 +232,8 @@ ### Dispatcher.dispatch( action: function, context: any, args: Array<any> ) (since 1.5)

Call to place action on a queue. Can be imported directly from package too.
```javascript
// example
Dispatcher.dispatch( console.log, console, ['oi!'] );
// 'oi!'
```
import { dispatch } from 'immview';
```

@@ -179,1 +243,10 @@ ### Dispatcher.rejectContext( context: any ) (since 1.5)

Call to remove actions with provided context from queue.
```javascript
// example
Dispatcher.dispatch( () => {
console.log('ay!');
Dispatcher.dispatch( console.log, console, ['oi!'] );
Dispatcher.rejectContext( console );
} );
// 'ay!'
```

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

webpackConfig.entry = './tests/index.js';
webpackConfig.externals = null;
webpackConfig.externals = {
immutable: 'Immutable'
};

@@ -12,25 +14,20 @@ module.exports = function(config) {

// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: (process.env.TRAVIS ? ['node_modules/babel-polyfill/dist/polyfill.min.js'] : []).concat([
//'node_modules/immutable/dist/immutable.js',
'node_modules/immutable/dist/immutable.js',
]).concat([
'tests/index.js',
//'src/index.js',
//'tests/*.spec.js',
]),
// list of files to exclude
exclude: [],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'tests/index.js': ['webpack', 'sourcemap', 'coverage'],
'tests/index.js': [
'webpack',
'sourcemap',
// 'coverage',
],
},

@@ -47,18 +44,16 @@

// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress', 'coverage'],
reporters: [
'progress',
// 'coverage',
],
coverageReporter: {
type: 'html',
dir: 'tests',
subdir: 'coverage',
file: 'coverage.html',
},
// coverageReporter: {
// type: 'html',
// dir: 'tests',
// subdir: 'coverage',
// file: 'coverage.html',
// },
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,

@@ -70,7 +65,4 @@

// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: process.env.TRAVIS ? ['PhantomJS'] : ['Chrome'],

@@ -77,0 +69,0 @@

{
"name": "immview",
"version": "1.5.2",
"version": "1.6.0",
"description": "",

@@ -8,8 +8,9 @@ "main": "dist/immview.js",

"scripts": {
"test": "NODE_ENV=testing $(npm bin)/karma start",
"test_once": "NODE_ENV=testing $(npm bin)/karma start --single-run",
"test_node": "NODE_ENV=testing node test_node.js",
"test:once": "NODE_ENV=testing $(npm bin)/karma start --single-run",
"test:node": "NODE_ENV=testing node test_node.js",
"test:watch": "NODE_ENV=testing $(npm bin)/karma start",
"test": "npm run fix && npm run test:node && npm run test:once",
"start": "NODE_ENV=testing $(npm bin)/webpack --watch",
"build": "NODE_ENV=production $(npm bin)/webpack",
"preversion": "npm run test_node && npm run build && git add -A && git commit -m \"build\";",
"build": "NODE_ENV=production $(npm bin)/webpack && git add -A && git commit -m \"build\";",
"preversion": "npm run test && npm run build",
"fix:src": "$(npm bin)/jscs --fix src/*.js",

@@ -16,0 +17,0 @@ "fix:tests": "$(npm bin)/jscs --fix tests/*.js",

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

# immview 1.5
# immview 1.6

@@ -27,4 +27,5 @@ 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.

* [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,5 +0,1 @@

import {
fromJS,
} from 'immutable';
import { dispatchDataWrite } from './Dispatcher';

@@ -11,21 +7,20 @@ import Reactor from './Reactor.js';

this.linkTo(null);
this.digest(fromJS(initialData));
this._linkTo(null);
this._digest(initialData);
}
Data.prototype = {
...Reactor.prototype,
/**
* Dispatch a change instruction to the Data
* @param {Iterable|function(data: Iterable):Iterable} change
*/
write(change) {
dispatchDataWrite(() => {
if (typeof change === 'function') {
this.digest(change(this.read()));
} else {
this.digest(change);
}
});
},
Data.prototype = Object.create(Reactor.prototype);
/**
* Dispatch a change instruction to the Data
* @param {Iterable|function(data: Iterable):Iterable} change
*/
Data.prototype.write = function (change) {
dispatchDataWrite(() => {
if (typeof change === 'function') {
this._digest(change(this.read()));
} else {
this._digest(change);
}
});
};

@@ -12,6 +12,6 @@ import Reactor from './Reactor.js';

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

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

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

@@ -29,15 +29,13 @@ });

Debounce.prototype = {
...Reactor.prototype,
Debounce.prototype = Object.create(Reactor.prototype);
destroy() {
if (this.timeoutID) {
clearTimeout(this.timeoutID);
this.timeoutID = null;
}
if (this.subscription) {
this.subscription();
}
Reactor.prototype.destroy.call(this);
},
Debounce.prototype.destroy = function () {
if (this.timeoutID) {
clearTimeout(this.timeoutID);
this.timeoutID = null;
}
if (this.subscription) {
this.subscription();
}
Reactor.prototype.destroy.call(this);
};

@@ -10,24 +10,25 @@ let isRunning = false;

function findMaxPriority() {
let maxPriority = -1;
let firstOfPriority = null;
for (let i = 0; i < queue.length; i++) {
const jobPriority = queue[i].priority;
if (jobPriority > maxPriority) {
firstOfPriority = queue[i];
maxPriority = jobPriority;
}
}
return firstOfPriority;
}
const Dispatcher = {
dispatch: dispatchExternal,
function shiftFromQueue() {
const toRun = findMaxPriority();
queue.splice(
queue.indexOf(toRun),
1
);
return toRun;
tick(func) {
func();
},
rejectContext,
logger: console,
};
export {
Dispatcher as default,
Dispatcher,
dispatch,
dispatchDomainAction,
dispatchDataWrite,
dispatchDataConsume,
dispatchExternal,
rejectContext,
};
/**

@@ -46,4 +47,26 @@ * Execute first action of current queue

}
};
}
function shiftFromQueue() {
const toRun = findMaxPriority();
queue.splice(
queue.indexOf(toRun),
1
);
return toRun;
}
function findMaxPriority() {
let maxPriority = -1;
let firstOfPriority = null;
for (let i = 0; i < queue.length; i++) {
const jobPriority = queue[i].priority;
if (jobPriority > maxPriority) {
firstOfPriority = queue[i];
maxPriority = jobPriority;
}
}
return firstOfPriority;
}
/**

@@ -65,3 +88,31 @@ * Append new action onto end of the queue

function dispatchDomainAction(action, context, args) {
dispatch(action, context, args, PRIORITY_DOMAIN);
}
function dispatchDataWrite(action, context, args) {
dispatch(action, context, args, PRIORITY_DATA_WRITE);
}
function dispatchDataConsume(action, context, args) {
dispatch(action, context, args, PRIORITY_DATA_CONSUMING);
}
function dispatchExternal(action, context, args) {
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. 0, 1, 2 are acceptable
*/
function dispatch(action, context, args, priority) {
appendToQueue(action, context, args, priority);
startQueue();
}
/**
* Starts executing the queue

@@ -101,23 +152,2 @@ */

export function dispatch(action, context, args, priority) {
appendToQueue(action, context, args, priority);
startQueue();
}
export function dispatchDomainAction(action, context, args) {
dispatch(action, context, args, PRIORITY_DOMAIN);
}
export function dispatchDataWrite(action, context, args) {
dispatch(action, context, args, PRIORITY_DATA_WRITE);
}
export function dispatchDataConsume(action, context, args) {
dispatch(action, context, args, PRIORITY_DATA_CONSUMING);
}
export function dispatchExternal(action, context, args) {
dispatch(action, context, args, PRIORITY_EXT);
}
/**

@@ -127,26 +157,4 @@ * Removes all queued actions tied with a context

*/
export function rejectContext(context) {
function rejectContext(context) {
queue = queue.filter(item => item.context !== context);
}
export const Dispatcher = {
/**
* 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. 0, 1, 2 are acceptable
*/
dispatch: dispatchExternal,
tick(func) {
func();
},
rejectContext,
logger: console,
};
export default Dispatcher;

@@ -17,8 +17,7 @@ import {

export default function Domain(stream, actions) {
if (stream.subscribe) {
this.stream = stream;
} else {
if (!stream.subscribe) {
throw new Error(`${errorPrefix} stream source required`);
}
this._claimActions(actions);
this.stream = stream;
assignActions(this, actions);
}

@@ -28,26 +27,2 @@

/**
* @private
*/
_claimActions(actions) {
/**
* @private
*/
this._actionNames = actions ? Object.keys(actions) : [];
this._actionNames.forEach((actionName) => {
if (this[actionName]) {
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] = (...args) => {
dispatchDomainAction(actions[actionName], this, args, 1);
};
});
},
/**
* Retrieve last value on stream attached to the Domain

@@ -98,2 +73,6 @@ * @returns {Iterable}

scan(valuesToRemember, initialValue) {
return this.stream.scan(valuesToRemember, initialValue);
},
/**

@@ -138,1 +117,30 @@ * Register a listener to changes on data stream.

};
function assignActions(ctx, actions) {
if (!actions) {
ctx.actions = () => [];
return;
}
const actionNames = Object.keys(actions);
actionNames.forEach((actionName) => {
const action = actions[actionName];
if (ctx[actionName] !== undefined) {
throw new Error(`${errorPrefix}${actionName} is reserved for Domain interface`);
}
if (typeof action !== 'function') {
throw new Error(`${errorPrefix}${actionName} action is not a function`);
}
ctx[actionName] = (...args) => {
dispatchDomainAction(action, ctx, args);
};
ctx[actionName].originalLength = action.length || action.originalLength;
});
ctx._actionNames = actionNames; //legacy TODO remove
ctx.actions = () => actionNames;
}

@@ -6,6 +6,8 @@ import Domain from './Domain.js';

import Throttle from './Throttle.js';
import Dispatcher from './Dispatcher';
import Scan from './Scan.js';
import {
Dispatcher,
dispatch,
} from './Dispatcher';
const { dispatch } = Dispatcher;
export {

@@ -17,4 +19,5 @@ Data,

Throttle,
Scan,
Dispatcher,
dispatch,
};
import {
Set,
is,
} from 'immutable';
import {
scheduleLength,
scheduleJob,
runScheduledPriorityJob,
createSchedule,
copyQueueOntoSchedule,
} from './StreamSchedule';
import * as Digest from './Digest';
import {
dispatchDataWrite,
dispatchDataConsume,
} from './Dispatcher';
function hasValue(v) {
return (
v !== undefined &&
v !== null
);
}
function shouldStructureBeReplaced(structure, candidate) {
return (
hasValue(candidate) && (
!hasValue(structure) ||
!is(candidate, structure)
)
);
};
let digestEdges = [];
let digestSchedule = [];
function restoreNodeJobs(edges, currentSchedule) {
const digestJobMap = createSchedule(edges);
return copyQueueOntoSchedule(currentSchedule, digestJobMap);
}
function doNextJob() {
if (scheduleLength(digestSchedule) > 0) {
digestSchedule = runScheduledPriorityJob(digestSchedule);
dispatchDataWrite(doNextJob);
}
}
function identity(v) {
return v;
}
/**
* Reactor is an base class for all immview observables
* @constructor
*/
export default function Reactor() {
/**
* @private
* @type {Function[]}
*/
this.reactors = Set();
this._reactors = [];
}

@@ -66,26 +24,43 @@

linkTo(sourceNode) {
digestEdges.push([
/**
* Registers new connection between new observables
* @protected
* @param {Reactor|Domain} sourceNode
*/
_linkTo(sourceNode) {
Digest.link(
sourceNode && (sourceNode.stream ? sourceNode.stream : sourceNode),
this,
]);
digestSchedule = restoreNodeJobs(digestEdges, digestSchedule);
this
);
},
unlink() {
digestEdges = digestEdges.filter(link => link[0] !== this && link[1] !== this);
digestSchedule = restoreNodeJobs(digestEdges, digestSchedule);
/**
* Unregisters connections between observables
* @protected
*/
_unlink() {
Digest.unlink(this);
},
consume(data, chew = identity) {
dispatchDataConsume(() => {
digestSchedule = scheduleJob(this, () => this.digest(chew(data)), digestSchedule);
dispatchDataWrite(doNextJob);
});
/**
* Defers a digestion with a function
* that can be relaced
* without any data loss
* @protected
* @param {*|null|undefined} data
* @optional
* @param {function()|null} chew
*/
_consume(data, chew = identity) {
Digest.queue(this, () => this._digest(chew(data)));
},
digest(data) {
/**
* Replace current state and push data further
* @param {*|null|undefined} data
*/
_digest(data) {
if (shouldStructureBeReplaced(this.structure, data)) {
this.structure = data;
this.flush();
this._flush(data);
}

@@ -95,2 +70,12 @@ },

/**
* Pushes data to all listeners
* @param data
* @private
*/
_flush(data) {
this._reactors.forEach(reaction => reaction(data));
},
/**
* Registers a function that is going to be fed with new data pushing by this observable
* @param {function} reaction

@@ -100,5 +85,9 @@ * @returns {function()}

appendReactor(reaction) {
this.reactors = this.reactors.add(reaction);
if (this._reactors.indexOf(reaction) < 0) {
this._reactors.push(reaction);
}
return () => {
this.reactors = this.reactors.delete(reaction);
this._reactors = this._reactors.filter(
registeredReaction => registeredReaction !== reaction
);
};

@@ -108,2 +97,4 @@ },

/**
* Registers a function that is going to be fed with new data pushing by this observable.
* Will launch provided function immediately.
* @param {function} reaction

@@ -117,10 +108,6 @@ * @returns {function()}

flush() {
this.reactors.forEach(reaction => reaction(this.read()));
},
destroy() {
this.unlink();
this._unlink();
this.structure = null;
this.reactors = Set();
this._reactors = [];
},

@@ -142,2 +129,27 @@

},
scan(valuesToRemember, initialValue) {
const Scan = require('./Scan.js').default;
return new Scan(this, valuesToRemember, initialValue);
},
};
function shouldStructureBeReplaced(structure, candidate) {
return (
hasValue(candidate) && (
!hasValue(structure) ||
!is(candidate, structure)
)
);
};
function hasValue(v) {
return (
v !== undefined &&
v !== null
);
}
function identity(v) {
return v;
}

@@ -12,6 +12,6 @@ import Reactor from './Reactor.js';

this.linkTo(source);
this._linkTo(source);
this.timeoutID = null;
this.timeoutedData = null;
this.digest(source.read());
this._digest(source.read());
this.subscription = source.appendReactor(data => {

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

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

@@ -29,15 +29,13 @@ }

Throttle.prototype = {
...Reactor.prototype,
Throttle.prototype = Object.create(Reactor.prototype);
destroy() {
if (this.timeoutID) {
clearTimeout(this.timeoutID);
this.timeoutID = null;
}
if (this.subscription) {
this.subscription();
}
Reactor.prototype.destroy.call(this);
},
Throttle.prototype.destroy = function () {
if (this.timeoutID) {
clearTimeout(this.timeoutID);
this.timeoutID = null;
}
if (this.subscription) {
this.subscription();
}
Reactor.prototype.destroy.call(this);
};

@@ -1,7 +0,5 @@

import {
Map,
} from 'immutable';
import ViewMergeMap from './ViewMergeMap';
import Reactor from './Reactor.js';
const identity = data => data;
const errorPrefix = 'Immview::View: ';

@@ -13,64 +11,62 @@ export default function View(source, process = identity) {

if (source.subscribe) {
this.connectToSource(source, process);
this.unsubs = connectToSource(this, source, process);
} else {
this.connectToMultipleSources(source, process);
this.unsubs = connectToMultipleSources(this, source, process);
}
return;
}
throw new Error(`${errorPrefix}No sources to plug in`);
}
View.prototype = {
...Reactor.prototype,
View.prototype = Object.create(Reactor.prototype);
/**
* @private
* @param {Reactor} source
*/
connectToSource(source, process) {
this.linkTo(source);
this.digest(process(source.read()));
this.unsubs = [
source.appendReactor(data => this.consume(data, process)),
];
},
View.prototype.destroy = function destroyView() {
Reactor.prototype.destroy.call(this);
/**
* @private
* @param {Object.<Reactor>} sources
*/
connectToMultipleSources(sources, process) {
// initialize as a map{string:Iterable}
let mergedStructure = Map();
if (this.unsubs) {
this.unsubs.forEach(func => func());
}
const sourcesNames = Object.keys(sources);
this.unsubs = null;
};
// prefill mergedStructure before launching subscriptions
sourcesNames.forEach(sourceName => {
const source = sources[sourceName];
this.linkTo(source);
const sourceData = source.read();
mergedStructure = mergedStructure.set(sourceName, sourceData);
});
function identity(data) {
return data;
}
// subscribe to all data changes in parent views
this.unsubs = sourcesNames.map(
sourceName => sources[sourceName].appendReactor(
data => {
mergedStructure = mergedStructure.set(sourceName, data);
this.consume(mergedStructure, process);
}
)
);
function connectToSource(aView, source, process) {
aView._linkTo(source);
aView._digest(process(source.read()));
return [
source.appendReactor(data => aView._consume(data, process)),
];
}
this.digest(process(mergedStructure));
},
function connectToMultipleSources(aView, sources, process) {
// initialize as a map{string:Iterable}
let mergedStructure = new ViewMergeMap();
destroy() {
Reactor.prototype.destroy.call(this);
const sourcesNames = Object.keys(sources);
if (this.unsubs) {
this.unsubs.forEach(func => func());
}
// prefill mergedStructure before launching subscriptions
sourcesNames.forEach(sourceName => {
const source = sources[sourceName];
aView._linkTo(source);
const sourceData = source.read();
mergedStructure = mergedStructure.set(sourceName, sourceData);
});
this.unsubs = null;
},
};
// subscribe to all data changes in parent views
const unsubs = sourcesNames.map(
sourceName => sources[sourceName].appendReactor(
data => {
mergedStructure = mergedStructure.set(sourceName, data);
aView._consume(mergedStructure.clone(), process);
}
)
);
aView._digest(process(mergedStructure.clone()));
return unsubs;
}

@@ -67,2 +67,3 @@ var fs = require('fs');

.catch(function(err) {
console.error('ERROR!', err);
process.exitCode = 1;

@@ -69,0 +70,0 @@ })

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

import { Data, View, Domain } from '../src';
import { Data, View, Domain, dispatch } from '../src';

@@ -29,3 +29,3 @@ describe('branching and merged streams', () => {

let hits = 0;
let output;
let output = 0;

@@ -42,2 +42,22 @@ end.subscribe(v => {

});
it('is reacting once to two dispatched write jobs affecting single child node', () => {
const parent1 = new Data(1);
const parent2 = new Data(2);
let hits = [];
new View(
{ parent1, parent2 },
data => hits.push([
data.get('parent1'),
data.get('parent2'),
])
);
dispatch(() => {
parent1.write(11);
parent2.write(22);
});
// 1 - initial, 2 - rerender, 3+ - unnecessary
expect(hits.length).toBe(2);
});
});

@@ -12,5 +12,5 @@ import { Data, View } from '../src';

}
expect(new NonStandardView().read()).toBe('a');
});
});
import Data from '../src/Data';
import * as I from 'immutable';
import {
Map,
fromJS,
} from 'immutable';
describe('Data', () => {
let d;
let testDataObject;
beforeEach(() => {
d = new Data(I.Map({ a: 1, b: I.Map({ c: 2 }) }));
testDataObject = new Data(Map({ a: 1, b: Map({ c: 2 }) }));
});
it('can be created', () => {
expect(!!d.subscribe).toBe(true);
expect(!!testDataObject.subscribe).toBe(true);
});
describe('can be created with a boolean value', () => {
const boolDataTest = (startWith) => {
const dataForBool = new Data(startWith);
expect(dataForBool.read()).toBe(startWith);
dataForBool.write(v => !v);
expect(dataForBool.read()).toBe(!startWith);
};
it('T', boolDataTest.bind(null, true));
it('F', boolDataTest.bind(null, false));
});
describe('can be created with a number', () => {
const numberDataTest = (startWith) => {
const dataForNumber = new Data(startWith);
expect(dataForNumber.read()).toBe(startWith);
dataForNumber.write(startWith + 1);
expect(dataForNumber.read()).toBe(startWith + 1);
};
it('2', numberDataTest.bind(null, 2));
it('0', numberDataTest.bind(null, 0));
it('-1', numberDataTest.bind(null, -1));
});
it('can be created with a string', () => {
const dataForString = new Data(' 2 ');
expect(dataForString.read()).toBe(' 2 ');
dataForString.write(' 3 ');
expect(dataForString.read()).toEqual(' 3 ');
});
it('can be created with an object', () => {
const dataForObject = new Data({ test: 1 });
expect(dataForObject.read()).toEqual({ test: 1 });
dataForObject.write({ test: 2 });
expect(dataForObject.read()).toEqual({ test: 2 });
});
it('can be created with an array', () => {
const dataForObject = new Data([2, 3, 4]);
expect(dataForObject.read()).toEqual([2, 3, 4]);
dataForObject.write([2, 3, 4, 5]);
expect(dataForObject.read()).toEqual([2, 3, 4, 5]);
});
it('can be read from', () => {
expect(d.read().get('a')).toBe(1);
expect(d.read().getIn(['b', 'c'])).toBe(2);
expect(d.read().toJS()).toEqual({ a: 1, b: { c: 2 } });
expect(testDataObject.read().get('a')).toBe(1);
expect(testDataObject.read().getIn(['b', 'c'])).toBe(2);
expect(testDataObject.read().toJS()).toEqual({ a: 1, b: { c: 2 } });
});
it('can be written to with a new data', () => {
d.write(d.read().setIn(['b', 'c'], 3));
d.write(d.read().set('d', 3));
expect(d.read().getIn(['b', 'c'])).toBe(3);
expect(d.read().get('d')).toBe(3);
testDataObject.write(testDataObject.read().setIn(['b', 'c'], 3));
testDataObject.write(testDataObject.read().set('d', 3));
expect(testDataObject.read().getIn(['b', 'c'])).toBe(3);
expect(testDataObject.read().get('d')).toBe(3);
});
it('can be written to with a function returning data', () => {
d.write(v => v.setIn(['b', 'c'], 3));
d.write(v => v.set('d', 3));
expect(d.read().getIn(['b', 'c'])).toBe(3);
expect(d.read().get('d')).toBe(3);
testDataObject.write(v => v.setIn(['b', 'c'], 3));
testDataObject.write(v => v.set('d', 3));
expect(testDataObject.read().getIn(['b', 'c'])).toBe(3);
expect(testDataObject.read().get('d')).toBe(3);
});

@@ -39,3 +86,3 @@

d.subscribe(state => {
testDataObject.subscribe(state => {
expect(state.get('a')).toBe(1);

@@ -49,3 +96,3 @@ expect(state.get('d')).toBe(forthVal);

forthVal = 3;
d.write(d.read().set('d', forthVal));
testDataObject.write(testDataObject.read().set('d', forthVal));
});

@@ -57,3 +104,3 @@

const getDataMap = () => I.fromJS({ a: 1, b: { c: 2 } });
const getDataMap = () => fromJS({ a: 1, b: { c: 2 } });

@@ -77,7 +124,7 @@ const d = new Data(getDataMap());

let reactions = 0;
const unsub = d.subscribe(() => {
const unsub = testDataObject.subscribe(() => {
reactions++;
});
d.write(d.read().set('d', 3)); // change -> reaction
testDataObject.write(testDataObject.read().set('d', 3)); // change -> reaction
expect(reactions).toBe(2);

@@ -87,3 +134,3 @@

d.write(d.read().set('d', 5)); // change -> no reaction
testDataObject.write(testDataObject.read().set('d', 5)); // change -> no reaction
expect(reactions).toBe(2);

@@ -94,16 +141,23 @@ });

let reactions = 0;
d.map(dData => {
testDataObject.map(dData => {
reactions += dData.get('a');
});
d.write(d.read().set('d', 3)); // change -> reaction
testDataObject.write(testDataObject.read().set('d', 3)); // change -> reaction
expect(reactions).toBe(2);
});
it('writes can still be queued up and all performed', () => {
const a = new Data(0);
const b = new Data(0);
expect(a.read()).toBe(0);
expect(b.read()).toBe(0);
a.write(i => {
b.write(i => i + 1);
// they are inside so they are actually queued
b.write(i => i + 1);
b.write(i => i + 1);
// as they are queued, updates are not yet performed
expect(a.read()).toBe(0);
expect(b.read()).toBe(0);
return i + 1;

@@ -110,0 +164,0 @@ });

import Domain from '../src/Domain';
import Data from '../src/Data';
import View from '../src/View';
import {
fromJS,
} from 'immutable';

@@ -17,3 +20,3 @@ describe('Domain', () => {

it('can be created from Data type', () => {
const d = new Data({ a: 1 });
const d = new Data(fromJS({ a: 1 }));

@@ -29,3 +32,3 @@ // this should be really tested here

it('can be created from a View type', () => {
const d = new Data({ a: 1 });
const d = new Data(fromJS({ a: 1 }));

@@ -39,5 +42,5 @@ const v = new View(d, data => data);

it('acquire queueable methods', () => {
it('acquire queueable actions', () => {
let testVar = '';
const d = new Data({ a: 1 });
const d = new Data(fromJS({ a: 1 }));
const dmn = new Domain(d, {

@@ -61,5 +64,18 @@ testMethod1: () => {

it('enables to tell which action has what length', () => {
const d = new Data(0);
const dmn = new Domain(d, { doNothing: v => v });
// now, that doNothing on dmn is a new function
// it doesn't inform about real action functions argument amount
// and this information cannot be overridden
expect(dmn.doNothing.length).toBe(0);
// that's why it is being stored on separate property
expect(dmn.doNothing.originalLength).toBe(1);
});
it('allow subscriptions', () => {
let testVar = 0;
const d = new Data({ a: 1 });
const d = new Data(fromJS({ a: 1 }));
const dmn = new Domain(d);

@@ -82,3 +98,3 @@

let testVar = '';
const d = new Data({ a: 1 });
const d = new Data(fromJS({ a: 1 }));
const dmn = new Domain(d, {

@@ -85,0 +101,0 @@ testMethod1: () => {

import {
addEdge,
getOrder,
getGraphNodes,
getAllNodes,
getNodeChildren,
visit,
} from '../src/graphSort.js';
getOrderStartingFromNode,
} from '../src/Graph.js';
describe('graphsort', () => {
it('can get nodes', () => {
expect(getGraphNodes([
expect(getAllNodes([
['a', 'c'],
])).toEqual(['a', 'c']);
expect(getGraphNodes([
expect(getAllNodes([
['a', 'b'],
['a', 'c'],
])).toEqual(['a', 'b', 'c']);
expect(getGraphNodes([
expect(getAllNodes([
['a', 'b'],

@@ -44,3 +46,3 @@ ['a', 'c'],

];
const result = visit(edges, 'a', [], []);
const result = getOrderStartingFromNode(edges, 'a', { visited: [], stack: [] });
expect(result.stack).toEqual(['b', 'f', 'c', 'd', 'a']);

@@ -47,0 +49,0 @@ });

@@ -13,1 +13,2 @@ import './data.spec';

import './classExtending';
import './scan.spec';

@@ -15,6 +15,9 @@ import {

expect(typeof instance.map).toBe('function');
expect(typeof instance.debounce).toBe('function');
expect(typeof instance.throttle).toBe('function');
expect(typeof instance.scan).toBe('function');
}
describe('Immview', () => {
describe('has public interface', () => {
describe('keeps public interface in', () => {
it('Data', () => {

@@ -28,8 +31,12 @@ expect(Data).toBeDefined();

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

@@ -36,0 +43,0 @@ fulfillsReactorInterface(instance);

@@ -8,3 +8,3 @@ import {

copyQueueOntoSchedule,
} from '../src/StreamSchedule';
} from '../src/Schedule';

@@ -11,0 +11,0 @@ const graph = [

import Domain from '../src/Domain';
import Data from '../src/Data';
import View from '../src/View';
import I from 'immutable';
import {
Map,
fromJS,
} from 'immutable';

@@ -9,3 +12,3 @@ describe('View', function () {

it('can be created from a Data', function () {
var aData = new Data({ a: 1 });
var aData = new Data(Map({ a: 1 }));
var resultView = new View(aData, i=>i);

@@ -16,3 +19,3 @@ expect(resultView.read().get('a')).toBe(1);

it('can be created from a View', function () {
var aData = new Data({ a: 1 });
var aData = new Data(Map({ a: 1 }));
var aView = new View(aData, i=>i);

@@ -24,3 +27,3 @@ var resultView = new View(aView, i=>i);

it('can be created from a Domain', function () {
var aData = new Data({ a: 1 });
var aData = new Data(Map({ a: 1 }));
var aView = new View(aData, i=>i);

@@ -33,3 +36,3 @@ var aDomain = new Domain(aView, {});

it('can be created from a Domains', function () {
var aData = new Data({ a: 1 });
var aData = new Data(Map({ a: 1 }));
var aView = new View(aData, i=>i);

@@ -47,3 +50,3 @@ var aDomain = new Domain(aView, {});

beforeEach(() => {
d = new Data({ a: 1, b: { c: 2 } });
d = new Data(fromJS({ a: 1, b: { c: 2 } }));
vReactions = 0;

@@ -88,4 +91,4 @@ v = new View(d, state => {

it('w/o processor func', function () {
var d1 = new Data({ a: 1 });
var d2 = new Data({ a: 2 });
var d1 = new Data(Map({ a: 1 }));
var d2 = new Data(Map({ a: 2 }));
var v2 = new View({ d1, d2 });

@@ -104,8 +107,8 @@ expect(v2.read().toJS()).toEqual({

it('with processor func', function () {
var d1 = new Data({ a: 1 });
var d2 = new Data({ a: 2 });
var d1 = new Data(Map({ a: 1 }));
var d2 = new Data(Map({ a: 2 }));
var v2 = new View({ d1, d2 }, data => {
expect(data.get('d1')).toBeDefined();
expect(data.get('d2')).toBeDefined();
return I.Map({
return Map({
a: data.get('d1'),

@@ -130,3 +133,3 @@ b: data.get('d2'),

it('creates new View deriving from current with \'map\' functions', done => {
new Domain(new Data(I.Map({ a: 1 })), {})
new Domain(new Data(Map({ a: 1 })), {})
.map(data => data.set('b', 2)) // <- view from data

@@ -133,0 +136,0 @@ .map(data => data.setIn(['c'], 3)) // <- view from view

# 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.

@@ -64,5 +65,14 @@ ## State

```javascript
ToDoDomain.subscribe(v => console.log(v.toJS()));
// []
ToDoDomain.add('Eat a pizza');
// [{ label: "Eat a pizza" }]
ToDoDomain.check(0);
// [{ label: "Eat a pizza", done: true }]
```
Please, be aware that all action calls and writes on **Data** instances are going to be dispatched to a execution queue that will run them in call order one after another with prioritization of **Data** writes.
> Please, be aware that all action calls and writes on **Data** instances are going to be dispatched to a execution queue that will run them in call order one after another with prioritization of **Data** writes. This won't be even noticable in this example as calls in it are not nested in a way that would reveal it.
Domain is now ready to be used to connect it a react component using [immview-react-connect](https://github.com/arturkulig/immview-react-connect).

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