Comparing version 1.7.3 to 2.0.0
#Changelog | ||
## 2.0.0 | ||
- feat: **Immview** is now written with TypeScript and exposes types declarations | ||
- feat: `Dispatcher` and by that `Domain` actions and `Data` writes return promises of these being executed | ||
- feat: `Observable`s are first class citizens of the library, not implementation detail and follows TC39 Observable proposal as closely as possible and in most usable way https://github.com/tc39/proposal-observable | ||
- feat: `Observable::subscribe` callback will not be immediately called with last shared value | ||
- feat: `View` functionality will be achievable using `Observable::map` function only | ||
- feat: `Scan` functionality will be achievable using `Observable::scan` function only | ||
- feat: `Reduce` functionality will be achievable using `Observable::reduce` function only | ||
- feat: `Debounce` functionality will be achievable using `Observable::debounce` function only | ||
- feat: `Throttle` functionality will be achievable using `Observable::throttle` function only | ||
- feat: `Observable::buffer` function is introduced. Observables next stream values pressure unloading by replacing awaiting values caused by previous implementation of `Dispatcher` will no longer be. | ||
- feat: `Domain` with actions can now be created through factory `Domain.create` | ||
- feat: Adding actions while extending `Domain` class can be achieved through `@action` decorator | ||
--- | ||
## 1.7.3 | ||
@@ -4,0 +21,0 @@ - feat: Domains may be now decorated with function (that become actions) and other fields. |
@@ -1,2 +0,2 @@ | ||
!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(11),s=n(u),a=r(12),c=n(a),f=r(5),l=n(f),d=r(7),h=n(d),p=r(8),m=n(p),g=r(9),y=n(g),b=r(13),v=n(b),_=r(10),j=n(_),O=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=y.default,e.Merge=v.default,e.Reduce=j.default,e.Dispatcher=O.Dispatcher,e.dispatch=O.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(t){return t&&"undefined"!=typeof Symbol&&t.constructor===Symbol?"symbol":typeof t}function u(){var t=this;this.structure=null,this.priority=u.nextPriority++,this.subscriptions=[function(e){t.structure=e}],this.closed=!1}function s(t){return void 0!==t&&null!==t}function a(t){return t}Object.defineProperty(e,"__esModule",{value:!0}),e.default=u;var c=r(2),f=i(c),l=r(3),d=i(l),h=r(4);n(h);u.nextPriority=0,u.prototype={structure:null,priority:0,subscriptions:[],closed:!1,read:function(){return this.structure},shouldObservableUpdate:function(t){return s(t)?"object"===(void 0===t?"undefined":o(t))?!0:this.read()!==t:!1},consume:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:a;f.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](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=r(5).default;return new e(this,t)},debounce:function(t){var e=r(7).default;return new e(this,t)},throttle:function(t){var e=r(8).default;return new e(this,t)},scan:function(t,e){var n=r(9).default;return new n(this,t,e)},reduce:function(t){var e=r(10).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);d.Dispatcher.logger.log("#"+this.priority+" "+t+" "+e)}catch(r){d.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&&g.splice(g.indexOf(t),1),t}function o(){for(var t=-1,e=null,r=0;g.length>r;r++){var n=g[r].priority;n>t&&(e=g[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]:b;g.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,b)}function l(t,e,r,n){u(t,e,r,n),d()}function d(){m||g.length>0&&(m=!0,O.tick(function(){try{n()}catch(t){h(t)}m=!1,d()}))}function h(t){O.logger.error(y+"Error occured while running a function"),"object"===(void 0===t?"undefined":r(t))?t.stack?O.logger.error(t.stack):O.logger.error(t.name,t.message):O.logger.error(t)}function p(t){g=g.filter(function(e){return e.context!==t})}Object.defineProperty(e,"__esModule",{value:!0});var m=!1,g=[],y="Immview::Dispatcher: ",b=0,v=1,_=2,j=3,O={dispatch:f,tick:function(t){t()},rejectContext:p,logger:console};e.default=O,e.Dispatcher=O,e.dispatch=l,e.dispatchDomainAction=s,e.dispatchDataWrite=a,e.dispatchDataConsume=c,e.dispatchExternal=f,e.rejectContext=p},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(6),f=n(c),l=r(1),d=n(l),h=r(4),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.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(4),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){this.stream=t,o(this,e)}function o(t,e){if(!e)return void(t.actions=function(){return[]});var r=Object.keys(e).filter(function(r){var n=e[r];if(void 0!==t[r])throw Error(""+c+r+" is reserved for Domain interface");return"function"!=typeof n?(t[r]=n,!1):(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,!0)});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.actions().forEach(function(e){t[e]=a})}}},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){if(t.closed)return t.read();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}}])}); | ||
!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";var n=r(1),i=r(2),o=r(3);e.Observable=o.Observable;var s=r(9);e.Merge=s.Merge;var u=r(8);e.Domain=u.Domain;var c=r(7);e.action=c.action;var a=function(t){n.Dispatcher.push(t,i.DispatcherPriorities.EXTERNAL)};e.dispatch=a},function(t,e,r){"use strict";var n=r(6),i=r(2),o=new n.Dispatcher;e.Dispatcher=o;var s=function(t,e){void 0===e&&(e=i.DispatcherPriorities.EXTERNAL),o.push(t,e),o.run()};e.dispatch=s;var u=function(t,e){return void 0===e&&(e=i.DispatcherPriorities.EXTERNAL),new Promise(function(r,n){s(function(){try{r(t())}catch(t){console.error(t.stack||t.message||t),n(t)}},e)})};e.dispatchPromise=u},function(t,e){"use strict";var r;!function(t){t[t.OBSERVABLE=1]="OBSERVABLE",t[t.DOMAIN=2]="DOMAIN",t[t.BUFFER=3]="BUFFER",t[t.EXTERNAL=4]="EXTERNAL",t[t.TEST=10]="TEST"}(r=e.DispatcherPriorities||(e.DispatcherPriorities={}))},function(t,e,r){"use strict";var n=this&&this.__extends||function(t,e){function r(){this.constructor=t}for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)},i=r(4),o=r(2),s=r(1),u="undefined"!=typeof Symbol?Symbol("ObservableSymbol"):"ObservableSymbol",c=function(t){function e(){return t.apply(this,arguments)||this}return n(e,t),e.of=function(){for(var t=[],r=0;arguments.length>r;r++)t[r]=arguments[r];return e.from(t)},e.from=function(t){if(t[u])return new e(function(e){t[u]().subscribe(e.next,e.error,e.complete)});if(t[Symbol.iterator])return new e(function(e){for(var r=e.next,n=e.error,i=e.complete,o=t[Symbol.iterator](),s=o.next();s.done===!1;s=o.next())s.value instanceof Error?n(s.value):r(s.value);i()});throw Error("Observable.from incorrect input")},e.prototype.map=function(t){var r=this;return new e(function(e){var n=r.subscribe(function(r){try{e.next(t(r))}catch(t){e.error(t)}},e.error,e.complete);return function(){return n.unsubscribe()}})},e.prototype.flatten=function(){var t=this;return new e(function(e){t.subscribe(function(t){t&&t.subscribe(function(t){e.next(t)},function(t){return e.error(t)})},e.error,e.complete)})},e.prototype.scan=function(t){var r=this;return new e(function(e){var n=null,i=r.subscribe(function(r){var i;try{i=n?t(r,n):r,n=i}catch(t){e.error(t)}e.next(i)},e.error,e.complete);return function(){return i.unsubscribe()}})},e.prototype.filter=function(t){var r=this;return new e(function(e){var n=r.subscribe(function(r){try{t(r)&&e.next(r)}catch(t){e.error(t)}},e.error,e.complete);return function(){return n.unsubscribe()}})},e.prototype.bufferCount=function(t,r){var n=this;void 0===r&&(r=null);var i=r||t,o=[];return new e(function(e){var r=n.subscribe(function(r){o.push(r),o.length===t&&(e.next(o.slice()),o=o.splice(i,t-i))},e.error,function(){o.length>t-i&&e.next(o.slice()),e.complete()});return function(){return r.unsubscribe()}})},e.prototype.buffer=function(t){var r=this;void 0===t&&(t=0);var n=[];return new e(function(e){var i=r.subscribe(function(r){n=t>0?[r].concat(n).splice(0,t):[r].concat(n),s.Dispatcher.push(function(){1>n.length||e.next(n.splice(0,n.length).reverse())},o.DispatcherPriorities.BUFFER).run()},e.error,function(){n.length>0&&e.next(n.splice(0,n.length).reverse()),e.complete()});return function(){return i.unsubscribe()}})},e}(i.BaseObservable);e.Observable=c,c.prototype[u]=function(){return this}},function(t,e,r){"use strict";var n,i=r(1),o=r(2),s=r(10),u=r(5);!function(t){t[t.Next=0]="Next",t[t.Error=1]="Error",t[t.Complete=2]="Complete"}(n=e.MessageTypes||(e.MessageTypes={}));var c=function(){},a=function(){function t(e){var r=this;return this.closed=!1,this.observers=[],this.priority=t.lastObservablePriority++,e?void(this.cancelSubscriber=e(new u.CustomObserver(c,function(t){r.pushMessage([n.Next,"function"==typeof t?t:function(){return t},c])},function(t){r.pushMessage([n.Error,t,c])},function(){r.pushMessage([n.Complete,,c])}))||c):void(this.cancelSubscriber=c)}return t.prototype.previous=function(){return this.lastValue},t.prototype.start=function(){},t.prototype.next=function(t){this.pushMessage([n.Next,"function"==typeof t?t:function(){return t},c])},t.prototype.error=function(t){this.pushMessage([n.Error,t,c])},t.prototype.complete=function(){this.pushMessage([n.Complete,,c])},t.prototype.subscribe=function(){for(var e=this,r=[],n=0;arguments.length>n;n++)r[n]=arguments[n];if(this.closed)return new s.Subscription(null,function(){return!1});if("object"!=typeof r[0]||null===r[0]){var i=r[0],o=void 0===i?c:i,u=r[1],a=void 0===u?c:u,f=r[2],p=void 0===f?c:f;return this.subscribe({start:c,next:o,error:a,complete:p})}var l=r[0];this.observers.push(l);var h=new s.Subscription(function(){e.observers=e.observers.filter(function(t){return t!==l})},function(){return e.observers.indexOf(l)>-1});return l.start(h),t.dispatchDigestMessages(),h},t.prototype.pushMessage=function(e){this.closed||(t.awaitingMessages.push([this,e]),t.dispatchDigestMessages())},t.dispatchDigestMessages=function(){i.dispatch(t.digestAwaitingMessages,o.DispatcherPriorities.OBSERVABLE)},t.digestAwaitingMessages=function(){var e=t.popMessage(),r=e[0],n=e[1];r&&!r.closed&&(t.digestNodeMessage(r,n),t.dispatchDigestMessages())},t.popMessage=function(){if(0===t.awaitingMessages.length)return[null,null];for(var e=0;t.awaitingMessages.length>e;e++){var r=t.awaitingMessages[e],n=r[0],i=void 0===n?null:n,o=r[1];if(i.observers.length)return t.awaitingMessages.splice(e,1),[i,o]}return[null,null]},t.digestNodeMessage=function(t,e){var r=e[0],s=e[2];if(r===n.Next){var u=e,a=u[1],f=a(t.lastValue);t.lastValue=f,t.observers.forEach(function(t){return t.next(f)})}else if(r===n.Error){var p=e,l=p[1];t.observers.forEach(function(t){return t.error(l)})}else r===n.Complete&&(t.cancelSubscriber(),t.cancelSubscriber=c,t.closed=!0,t.observers.splice(0).forEach(function(t){return t.complete()}));i.dispatch(s,o.DispatcherPriorities.OBSERVABLE)},t}();a.awaitingMessages=[],a.lastObservablePriority=0,e.BaseObservable=a},function(t,e){"use strict";var r=function(){function t(t,e,r,n){this.start=t,this.next=e,this.error=r,this.complete=n}return t}();e.CustomObserver=r},function(t,e){"use strict";var r=function(){function t(){this.nextTickScheduler=null,this._isRunning=!1,this.tasks=[]}return Object.defineProperty(t.prototype,"isRunning",{get:function(){return!!this._isRunning},enumerable:!0,configurable:!0}),t.prototype.push=function(t,e){return void 0===e&&(e=0),this.tasks.push({priority:e,job:t}),this},t.prototype.run=function(){var t=this;if(!this._isRunning){this._isRunning=!0;var e=this.findNextJob();return e?void(this.nextTickScheduler=this.nextTickScheduler||Promise.resolve()).then(function(){t.next(function(){try{e.job()}catch(t){console.error(t.stack||t.message||t)}},function(){t._isRunning=!1,t.run()})}):(this.nextTickScheduler=null,void(this._isRunning=!1))}},t.prototype.findNextJob=function(){for(var t=null,e=0;this.tasks.length>e;e++)(null===t||this.tasks[t].priority>this.tasks[e].priority)&&(t=e);return null===t?null:this.tasks.splice(t,1)[0]},t.prototype.next=function(t,e){t(),e()},t}();e.Dispatcher=r},function(t,e,r){"use strict";function n(t,e,r){var n=r.value;r.value=function(){for(var t=this,e=[],r=0;arguments.length>r;r++)e[r]=arguments[r];return o.dispatchPromise(function(){n.apply(t,e)},i.DispatcherPriorities.DOMAIN)}}var i=r(2),o=r(1);e.action=n},function(t,e,r){"use strict";var n=this&&this.__extends||function(t,e){function r(){this.constructor=t}for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)},i=r(3),o=r(1),s=function(t){function e(e){return t.call(this,function(t){e.subscribe(t)})||this}return n(e,t),e.create=function(t,r,n){var i=new e(t);if(r){var s=function(t){return Object.prototype.hasOwnProperty.call(r,t)?void(i[t]=function(){for(var e=[],n=0;arguments.length>n;n++)e[n]=arguments[n];return o.dispatchPromise((s=r[t]).bind.apply(s,[i].concat(e)));var s}):"continue"};for(var u in r)s(u)}if(n)for(var c in n)Object.prototype.hasOwnProperty.call(n,c)&&(i[c]=n[c]);return i},e}(i.Observable);e.Domain=s},function(t,e,r){"use strict";var n=this&&this.__extends||function(t,e){function r(){this.constructor=t}for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)},i=this&&this.__assign||Object.assign||function(t){for(var e,r=1,n=arguments.length;n>r;r++){e=arguments[r];for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i])}return t},o=r(3),s=function(t){function e(e){return t.call(this,function(t){var r=[],n=[],o=[],s={},u=[],c=function(c){return Object.prototype.hasOwnProperty.call(e,c)?(r.push(c),void u.push(e[c].subscribe(function(e){if(o&&o.push([c,e]),n.indexOf(c)<0&&n.push(c),r.length===n.length){if(o){for(var u={},a=[],f=[],p=0;o.length>p;p++)if(a.indexOf(o[p][0])<0){var l=o[p],h=l[0],v=l[1];u[h]=v,a.push(h)}else f.push(o[p]);return t.next(s=u),f.forEach(function(e){var r=e[0],n=e[1];t.next(s=i({},s,(o={},o[r]=n,o)));var o}),void(o=null)}t.next(s=i({},s,(b={},b[c]=e,b)));var b}}))):"continue"};for(var a in e)c(a);return function(){u.forEach(function(t){return t()})}})||this}return n(e,t),e}(o.Observable);e.Merge=s},function(t,e){"use strict";var r=function(){function t(t,e){this.customUnsubscribe=t,this.isSubscriptionActive=e}return Object.defineProperty(t.prototype,"closed",{get:function(){return!this.isSubscriptionActive()},enumerable:!0,configurable:!0}),t.prototype.unsubscribe=function(){var t=this.customUnsubscribe;t&&(this.customUnsubscribe=null,t&&t())},t}();e.Subscription=r}])}); | ||
//# sourceMappingURL=immview.js.map |
375
docs.md
#Docs | ||
> Any types are provided in descriptions follow **flowtype** style. | ||
## class `Observable`<T> | ||
#### (subscriber: (observer: {next: (value: T) => void, error: (err: Error) => void, complete: () => void}) => void | () => void) | ||
Construct with `subscriber` function that receives `observer` object. `Observer` is for pushing values, errors and completion signal. | ||
`Subscriber` function may return function that should be called if `Observable` receives `complete` signal or is cancelled. | ||
- [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) | ||
### Observable::last | ||
#### () => T | ||
Returns last **value** that has been pushed through the `Observable` instance. | ||
## 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 | ||
const source = new Observable(({next}) => { next(1) }) | ||
source.subscribe(value => { | ||
value === source.previous() // true | ||
}) | ||
``` | ||
### Observable::next | ||
#### (nextValue: T) => void | ||
Sends value signal through the `Observable` instance. Values can be received, by `Observable::subscribe` method or `Observable::previous`. | ||
### Observable::error | ||
#### (error: Error) => void | ||
Sends error signal through the `Observable` instance. Errors can be received, with `Observable::subscribe` method. | ||
### Observable::complete | ||
#### () => void | ||
Sends `complete` signal through the `Observable` instance. Completion can be handled, with `Observable::subscribe` method. | ||
### Observable::subscribe | ||
#### ( reaction: (data: mixed) => void ) => () => void | ||
Registers a function called every time when the Observable changes value that it holds. | ||
#### ( { start: (sub: Subscription) => void, next: (value: T) => void, error: (err: Error) => void, complete: () => void } ) => () => void | ||
#### ( onNext?: (value: T) => void, onError?: (err: Error) => void, onCompletion?: () => void ) => () => void | ||
Registers a function called every time when the Observable changes value that it holds, error is pushed or Observable is complete. | ||
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. | ||
## class `Merge`<T> | ||
#### extends `Observable`<T> | ||
#### ( { [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) field in result object. | ||
### Observable::throttle | ||
#### ( timeout: number ) => Throttle (since 1.5) | ||
Creates a new stream of values being push with a provided delay since first update. | ||
```javascript | ||
const join = new Merge({ | ||
a: new Observable(observer => { observer.next('a') }), | ||
b: new Observable(observer => { observer.next('b') }) | ||
}) | ||
join.subscribe(v => { | ||
console.log(v) // {a: 'a', b: 'b'} | ||
}) | ||
``` | ||
### 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`<T> | ||
#### extends `Observable`<T> | ||
#### ( source: Observable<T> ) | ||
## class `Domain` | ||
#### extends `Observable` | ||
#### ( source: Observable ) | ||
#### ( source: Observable , { [name: string]: any } ) | ||
Class constructor alone will be only helpful when extending `Domain` class. | ||
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. | ||
### Domain.create<T> | ||
####( source: Observable<T> , actions: { [name: string]: () => Promise<any> | void }, fields: {}) | ||
Second argument is an object aggregating functions used to create actions and other values that will be exposed as part of the **Domain** interface. Provided functions will be wrapped with an internal Dispatcher calls. **Domain** *actions* won't be ever returning anything and will be executed in call order, **one after another** even if *actions* calls are done from another *action* call. | ||
`Domain` class by design is the only thing that should be exported and used (maybe with an exception of type definitions) outside of `Domain`s scope. | ||
For example: if you have a folder like: | ||
``` | ||
└ SomeDomain | ||
├ index.js // here is Domain creation | ||
├ SomeDomainState.js // downstream - source observables or stream transformations | ||
└ SomeDomainActions.js // functions to manipulate `Domain`'s state | ||
``` | ||
you should export SomeDomain from index.js and use only that in any other file. | ||
First argument of the factory function is an observable emiting messages that will be emited by the `Domain`'s instance too. | ||
Only single data source can be tied to a **Domain**, but you can always use `Merge` to combine multiple streams. | ||
Second argument is an object aggregating functions used to create actions and other values that will be exposed as part of the **Domain** interface. | ||
Provided functions will be wrapped with an internal Dispatcher calls. That mechanism ensures that they will always be executed one **after** another. That is a design decision which makes it easier to reason about what is happening inside application. | ||
Functions provided as **Domain** *actions* must not return any value. | ||
Calling an action however will return a Promise resolved after action function execution. | ||
```javascript | ||
// example usage | ||
import {Data, Merge, Domain} from 'immview' | ||
import {Merge, Domain} from 'immview' | ||
import {HorizonDomain} from './HorizonDomain' | ||
import {MusclesDomain} from './MusclesDomain' | ||
const EyesDomain = new Domain( | ||
const EyesDomain = Domain.create( | ||
new Merge({ | ||
@@ -69,42 +94,14 @@ HorizonDomain, | ||
roll() { | ||
MusclesDomain.doStuff() | ||
}, | ||
EXTRAOCULAR_MUSCLES: 6 | ||
MusclesDomain.doMuscleStuff() | ||
} | ||
}, | ||
{ | ||
EXTRAOCULAR_MUSCLES: 6 | ||
} | ||
) | ||
EyesDomain.roll() | ||
EyesDomain.roll().then(() => { console.log('I saw that!') }) | ||
EyesDomain.EXTRAOCULAR_MUSCLES // 6 | ||
``` | ||
### Domain::read (since 1.2) | ||
bypassed to state stream given in constructor (see `Data.read`) | ||
> 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.subscribe`) | ||
### Domain::map (since 1.4) | ||
bypassed to state stream given in constructor (see `Data.map`) | ||
### Domain::debounce (since 1.5) | ||
bypassed to state stream given in constructor (see `Data.debounce`) | ||
### Domain::throttle (since 1.5) | ||
bypassed to state stream given in constructor (see `Data.throttle`) | ||
### Domain::scan (since 1.6) | ||
bypassed to state stream given in constructor (see `Data.scan`) | ||
### Domain::destroy (since 1.7) | ||
Destroys inner stream, deactivates all actions mounted onto the domain. Recommended for easing GC after i.e. server side render of application, although it is recommended to try to keep domains between renders, to reuse them. | ||
### Domain::actions (since 1.7) | ||
Returns array of actions passed in constructor. | ||
### Domain::stream (since 1.7) | ||
field that holds observable that has been passed into the domain. Handy for testing on mocked domains. *NOT INTENDED FOR REGULAR USAGE* | ||
### Domain::[ACTION_NAME] | ||
@@ -114,4 +111,4 @@ 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), | ||
const domain = Domain.create( | ||
new Observable(observer => { ... }), | ||
{ foo: () => console.log('bar') } | ||
@@ -122,225 +119,1 @@ ) | ||
``` | ||
### Domain::[ACTION_NAME].originalLength (since 1.6) | ||
Amount of arguments indicated by original action function | ||
```javascript | ||
domain.foo.originalLength // 0 | ||
``` | ||
## class `Data` | ||
#### extends `Observable` | ||
#### ( initialData: mixed ) | ||
```javascript | ||
import {Data} from 'immview' | ||
new Data( 2 ) | ||
``` | ||
An **initialData** object can be object any native immutable (bool, string, number) or Immutable.js data structure. | ||
### Data::write | ||
#### (change: mixed ) => void | ||
#### (change: (currentStructure) => mixed) => void | ||
Method used to store new data structure. | ||
**change** parameter is: | ||
- 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. | ||
```javascript | ||
const source = new Data({a: 1}) | ||
source.write({a: 2}) | ||
/* | ||
be also warned, that you should not change any data structures you are given inside these functions | ||
*/ | ||
source.write(data => ({ ...data, b: 3})) | ||
``` | ||
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.** | ||
## class `View` | ||
#### extends `Observable` | ||
#### ( source: Observable, processor: (sourceData: mixed) => mixed ) | ||
```javascript | ||
import { Data, View } from 'immview' | ||
// transform source with processor function | ||
const place = new Data(0) | ||
const transformation = new View (place, v => v + 1) | ||
transformation.read() === 1 // true | ||
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 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 | ||
Same as `Data` function of the same name. | ||
### View::subscribe | ||
Same as `Data` function of the same name. | ||
### View::map (since 1.4) | ||
Same as `Data` function of the same name. | ||
### View::debounce (since 1.5) | ||
Same as `Data` function of the same name. | ||
### View::throttle (since 1.5) | ||
Same as `Data` function of the same name. | ||
### View::scan (since 1.6) | ||
Same as `Data` function of the same name. | ||
## 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(10) | ||
``` | ||
Creates a new stream of values being pushed with a provided delay since **last** update. | ||
Shares interface with a **View**. | ||
## class `Throttle` | ||
(since 1.5) | ||
#### extends `Observable` | ||
#### ( source: Observable, delay: number ) | ||
```javascript | ||
new Throttle(sourceStream, 10) | ||
// or | ||
sourceStream.throttle(10) | ||
``` | ||
Creates a new stream of values being push with a provided delay since **first** update. | ||
Shares interface with a **View**. | ||
## class `Scan` | ||
(since 1.6) | ||
#### extends `Observable` | ||
#### ( source: Observable, valuesToRemember: number = 2, initialValue: any = null ) | ||
```javascript | ||
new Scan(sourceStream, 2) | ||
// or | ||
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 | ||
``` | ||
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. | ||
Shares interface with a **View**. | ||
## class `Reduce` | ||
(since 1.7) | ||
### extends `Observable` | ||
#### <T, U>(source: Observable<T>, (resultState: <U>, sourceState: T) => 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) | ||
Replace to change for logging errors in queue runner | ||
```javascript | ||
// default | ||
Dispatcher.logger = console; | ||
``` | ||
### Dispatcher.tick (since 1.5) | ||
Replace to change how next function is being called. | ||
```javascript | ||
// default | ||
Dispatcher.tick = func => func(); | ||
``` | ||
### Dispatcher.dispatch( action: function, context: any, args: 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!' | ||
``` | ||
### 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!' | ||
``` |
{ | ||
"name": "immview", | ||
"version": "1.7.3", | ||
"version": "2.0.0", | ||
"description": "", | ||
"main": "dist/immview.js", | ||
"jsnext:main": "src/index.js", | ||
"main": "./dist/immview.js", | ||
"types": "./dist/index.d.ts", | ||
"repository": { | ||
@@ -12,13 +12,8 @@ "type": "git", | ||
"scripts": { | ||
"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 && git add -A && git commit -m \"build\";", | ||
"start": "NODE_ENV=testing jest", | ||
"build": "rm -rf ./dist/*.js; rm -rf ./dist/*.js.map; NODE_ENV=production webpack -p; npm run declarations", | ||
"declarations": "rm -rf ./dist/*.d.ts; tsc --declaration --declarationDir ./dist --outDir ./tsc_tmp_output; rm -rf ./dist/*.spec.d.ts; rm -rf ./tsc_tmp_output", | ||
"preversion": "npm run test && npm run build", | ||
"fix:src": "$(npm bin)/jscs --fix src/*.js", | ||
"fix:tests": "$(npm bin)/jscs --fix tests/*.js", | ||
"fix": "npm run fix:src ; npm run fix:tests ;", | ||
"flow": "flow; test $? -eq 0 -o $? -eq 2" | ||
"test": "tsc --noEmit && $(npm bin)/tslint --project ./tsconfig.json --config ./tslint.json --format stylish && jest", | ||
"debug": "node --inspect --debug-brk ./node_modules/.bin/jest -i" | ||
}, | ||
@@ -28,32 +23,30 @@ "author": "Artur Kulig", | ||
"devDependencies": { | ||
"babel-core": "^6.2.1", | ||
"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", | ||
"jasmine-core": "^2.3.4", | ||
"jscs": "^2.10.1", | ||
"karma": "^0.13.14", | ||
"karma-babel-preprocessor": "^6.0.1", | ||
"karma-chrome-launcher": "^0.2.0", | ||
"karma-commonjs": "0.0.13", | ||
"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", | ||
"karma-webpack": "^1.7.0", | ||
"phantomjs": "^1.9.18", | ||
"uglify-loader": "^1.3.0", | ||
"webpack": "^1.12.6", | ||
"webpack-dev-server": "^1.12.1" | ||
"@types/jasmine": "^2.5.38", | ||
"@types/node": "^6.0.53", | ||
"jest": "^18.0.0", | ||
"ts-loader": "^1.3.3", | ||
"tslint": "^4.2.0", | ||
"typescript": "^2.1.4", | ||
"webpack": "^1.14.0" | ||
}, | ||
"engines": { | ||
"node": ">=6" | ||
} | ||
}, | ||
"jest": { | ||
"verbose": true, | ||
"testEnvironment": "node", | ||
"moduleFileExtensions": [ | ||
"ts", | ||
"tsx", | ||
"js" | ||
], | ||
"testPathDirs": [ | ||
"<rootDir>/src" | ||
], | ||
"testRegex": ".*\\.spec\\.ts$", | ||
"transform": { | ||
".*\\.tsx?$": "<rootDir>/jest-ts-preprocessor.js" | ||
} | ||
}, | ||
"dependencies": {} | ||
} |
# <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 data and having specific to them **actions**. It can be used instead of any flux implementation or redux. | ||
**Immview** is a library to create `Domain`s - *non-visual components* | ||
- similar to flux stores, exposing their **state** or emitting **signals** | ||
through `Observable`s pushing values and having specific to their concerns **actions**. | ||
Their primary role is to encapsulate a concern | ||
and to be the only thing exported from a javascript module or modules | ||
that deal with the concern. | ||
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. | ||
It completely replaces any flux implementation or Redux. | ||
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**. | ||
If you are familiar with streaming libraries like RxJS, | ||
an **Immview** taste of `Observable` does not have a different meaning or role. | ||
Also, just as RxJS 5, it tries to follow | ||
[TC39 Observable proposal](https://github.com/tc39/proposal-observable). | ||
All `Domain`s must be provided with a single stream of values | ||
(so either `Origin` or any other transformed `Observable`), | ||
but not all `Observable`s must be attached to a `Domain` | ||
- you can perform many transformations on a source | ||
before it is exposed through a `Domain`. | ||
## Installation | ||
@@ -23,5 +36,24 @@ | ||
# Read more | ||
* [Reactive logic with immview](https://medium.com/@arturkulig/reactive-logic-with-immview-cf60ff06b7dc) - an introduction to reasoning behind immview | ||
* [Documentation](./docs.md) | ||
* [Simple usage](./usage_simple.md) | ||
* [Changelog](./changelog.md) | ||
* [Immview — application state management by streaming 101 (Jan 4, 2017)](https://medium.com/@arturkulig/immview-application-state-management-by-streaming-101-c12f81e3abac) | ||
* [Reactive logic with immview (May 28, 2016)](https://medium.com/@arturkulig/reactive-logic-with-immview-cf60ff06b7dc) - an introduction to reasoning behind immview 1.x | ||
# Compatibility | ||
Not compatible with IE8 unless: | ||
- Array.prototype.filter is polyfilled | ||
# 2.0 Roadmap | ||
- [X] Dispatcher | ||
- [X] BaseObservable | ||
- [X] Data -> Origin | ||
- [X] Merge | ||
- [X] Observable.map | ||
- [X] Observable.scan | ||
- [X] Observable.flatten | ||
- [X] Observable.buffer | ||
- [X] Observable.bufferCount | ||
- [X] Domain | ||
- [ ] external: immview-react-connect 2.0 |
@@ -58,3 +58,3 @@ # Simple usage example | ||
```javascript | ||
const ToDoDomain = new Domain( | ||
const ToDoDomain = Domain.new( | ||
ToDoDomainStream, | ||
@@ -61,0 +61,0 @@ ToDoDomainActions |
@@ -1,9 +0,8 @@ | ||
// jscs:disable | ||
var path = require('path'); | ||
var webpack = require('webpack'); | ||
var path = require('path') | ||
var webpack = require('webpack') | ||
var config = { | ||
entry: path.resolve(__dirname, 'src/index.js'), | ||
entry: path.resolve(__dirname, 'src/index.ts'), | ||
output: { | ||
path: __dirname + '/dist', | ||
path: path.resolve(__dirname, 'dist'), | ||
filename: 'immview.js', | ||
@@ -13,4 +12,4 @@ library: 'immview', | ||
}, | ||
externals: { | ||
immutable: 'immutable', | ||
resolve: { | ||
extensions: ['.ts', '.js', ''] | ||
}, | ||
@@ -20,9 +19,4 @@ module: { | ||
{ | ||
test: /\.js$/, | ||
exclude: /node_modules\/immutable\/dist\/immutable\.js/, | ||
loader: 'babel', | ||
query: { | ||
presets: ['es2015'], | ||
plugins: ['transform-object-rest-spread', 'transform-flow-strip-types'], | ||
}, | ||
test: /\.ts$/, | ||
loader: 'ts-loader' | ||
}, | ||
@@ -34,3 +28,3 @@ ], | ||
new webpack.DefinePlugin({ | ||
'process.env':{ | ||
'process.env': { | ||
'NODE_ENV': JSON.stringify(process.env.NODE_ENV) | ||
@@ -40,3 +34,3 @@ } | ||
] | ||
}; | ||
} | ||
@@ -52,5 +46,5 @@ if (process.env.NODE_ENV === 'production') { | ||
} | ||
})); | ||
})) | ||
} | ||
module.exports = config; | ||
module.exports = config |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
7
59
2
102856
26
339
1