microcosm
Advanced tools
Comparing version 1.3.0 to 1.4.0
# Changelog | ||
### 1.4.0 | ||
- `Store.deserialize` returns the result of `getInitialState` if no | ||
state is given | ||
- Added `Microcosm.swap` to perform diffing and emission on change | ||
- `Microcosm.seed` will now trigger a change event | ||
- `Heartbeat.js` now invokes callbacks with `callback.call(this)` | ||
### 1.3.0 | ||
@@ -4,0 +12,0 @@ |
@@ -1,2 +0,2 @@ | ||
module.exports=function(t){function r(e){if(n[e])return n[e].exports;var o=n[e]={exports:{},id:e,loaded:!1};return t[e].call(o.exports,o,o.exports,r),o.loaded=!0,o.exports}var n={};return r.m=t,r.c=n,r.p="",r(0)}([function(t,r,n){"use strict";r.__esModule=!0;var e=n(4);r.tag=e,r["default"]=n(2)},function(t){"use strict";var r=function(t,r){if(!(t instanceof r))throw new TypeError("Cannot call a class as a function")},n=function(){function t(){r(this,t),this._callbacks=[]}return t.prototype.ignore=function(t){this._callbacks=this._callbacks.filter(function(r){return r!==t})},t.prototype.listen=function(t){this._callbacks=this._callbacks.concat(t)},t.prototype.pump=function(){for(var t=0;t<this._callbacks.length;t++)this._callbacks[t]()},t}();t.exports=n},function(t,r,n){"use strict";var e=function(t){return t&&t.__esModule?t["default"]:t},o=Object.assign||function(t){for(var r=1;r<arguments.length;r++){var n=arguments[r];for(var e in n)Object.prototype.hasOwnProperty.call(n,e)&&(t[e]=n[e])}return t},i=function(t,r){if("function"!=typeof r&&null!==r)throw new TypeError("Super expression must either be null or a function, not "+typeof r);t.prototype=Object.create(r&&r.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),r&&(t.__proto__=r)},s=function(t,r){if(!(t instanceof r))throw new TypeError("Cannot call a class as a function")},u=e(n(1)),a=e(n(3)),c=e(n(5)),f=function(t){function r(){s(this,r),t.call(this),this._stores=[],this._state=this.getInitialState()}return i(r,t),r.prototype.getInitialState=function(){return{}},r.prototype.shouldUpdate=function(t,r){return 0==c(t,r)},r.prototype.seed=function(t){var r=this.deserialize(t);for(var n in r)this.set(n,r[n])},r.prototype.set=function(t,r){this._state=o({},this._state,function(){var n={};return n[t]=r,n}())},r.prototype.get=function(t){return this._state[t]},r.prototype.send=function(t){for(var r=this,n=arguments.length,e=Array(n>1?n-1:0),o=1;n>o;o++)e[o-1]=arguments[o];if(e.length<t.length)return this.send.bind(this,t);var i=t.apply(void 0,e);return i instanceof Promise?i.then(function(n){return r.dispatch(t,n)}):this.dispatch(t,i)},r.prototype.dispatch=function(t,r){var n=this,e=this._stores.filter(function(r){return t in r}),i=e.reduce(function(e,o){return e[o]=o[t](n.get(o),r),e},{}),s=o({},this._state,i);return this.shouldUpdate(this._state,s)&&(this._state=s,this.pump()),r},r.prototype.addStore=function(){for(var t=this,r=arguments.length,n=Array(r),e=0;r>e;e++)n[e]=arguments[e];this._stores=n.reduce(function(r,n){var e=o({},a,n);return t.set(e,e.getInitialState()),r.concat(e)},this._stores)},r.prototype.serialize=function(){var t=this;return this._stores.reduce(function(r,n){return r[n]=n.serialize(t.get(n)),r},o({},this._state))},r.prototype.deserialize=function(t){return this._stores.reduce(function(r,n){return r[n]=n.deserialize(t[n]),r},o({},t))},r.prototype.toJSON=function(){return this.serialize()},r}(u);t.exports=f},function(t){"use strict";t.exports={getInitialState:function(){return void 0},serialize:function(t){return t},deserialize:function(t){return t},toString:function(){throw new Error("Stores must implement a toString() method")}}},function(t){"use strict";var r=0,n=function(t){return"function"==typeof t},e=function(t,n){var e=t.bind(null),o="_"+n+"_"+r++;return e.toString=function(){return o},e};t.exports=function(t){var r=Object.keys(t);return r.reduce(function(r,o){var i=t[o];return r[o]=n(i)?e(i,o):i,r},{})}},function(t,r,n){/*! | ||
module.exports=function(t){function n(r){if(e[r])return e[r].exports;var i=e[r]={exports:{},id:r,loaded:!1};return t[r].call(i.exports,i,i.exports,n),i.loaded=!0,i.exports}var e={};return n.m=t,n.c=e,n.p="",n(0)}([function(t,n,e){"use strict";n.__esModule=!0;var r=e(4);n.tag=r,n["default"]=e(2)},function(t){"use strict";var n=function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")},e=function(){function t(){n(this,t),this._callbacks=[]}return t.prototype.ignore=function(t){this._callbacks=this._callbacks.filter(function(n){return n!==t})},t.prototype.listen=function(t){this._callbacks=this._callbacks.concat(t)},t.prototype.pump=function(){for(var t=0;t<this._callbacks.length;t++)this._callbacks[t].call(this)},t}();t.exports=e},function(t,n,e){"use strict";var r=function(t){return t&&t.__esModule?t["default"]:t},i=Object.assign||function(t){for(var n=1;n<arguments.length;n++){var e=arguments[n];for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])}return t},o=function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);t.prototype=Object.create(n&&n.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),n&&(t.__proto__=n)},s=function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")},u=r(e(1)),a=r(e(3)),c=r(e(5)),f=function(t){function n(){s(this,n),t.call(this),this._stores=[],this._state=this.getInitialState()}return o(n,t),n.prototype.getInitialState=function(){return{}},n.prototype.shouldUpdate=function(t,n){return 0==c(t,n)},n.prototype.seed=function(t){this.swap(this.deserialize(t))},n.prototype.swap=function(t){this.shouldUpdate(this._state,t)&&(this._state=t,this.pump())},n.prototype.set=function(t,n){this._state=i({},this._state,function(){var e={};return e[t]=n,e}())},n.prototype.get=function(t){return this._state[t]},n.prototype.send=function(t){for(var n=this,e=arguments.length,r=Array(e>1?e-1:0),i=1;e>i;i++)r[i-1]=arguments[i];if(r.length<t.length)return this.send.bind(this,t);var o=t.apply(void 0,r);return o instanceof Promise?o.then(function(e){return n.dispatch(t,e)}):this.dispatch(t,o)},n.prototype.dispatch=function(t,n){var e=this,r=this._stores.filter(function(n){return t in n}),o=r.reduce(function(r,i){return r[i]=i[t](e.get(i),n),r},{});return this.swap(i({},this._state,o)),n},n.prototype.addStore=function(){for(var t=this,n=arguments.length,e=Array(n),r=0;n>r;r++)e[r]=arguments[r];this._stores=e.reduce(function(n,e){var r=i({},a,e);return t.set(r,r.getInitialState()),n.concat(r)},this._stores)},n.prototype.serialize=function(){var t=this;return this._stores.reduce(function(n,e){return n[e]=e.serialize(t.get(e)),n},i({},this._state))},n.prototype.deserialize=function(t){return this._stores.reduce(function(n,e){return n[e]=e.deserialize(t[e]),n},i({},t))},n.prototype.toJSON=function(){return this.serialize()},n}(u);t.exports=f},function(t){"use strict";t.exports={getInitialState:function(){return void 0},serialize:function(t){return t},deserialize:function(){var t=void 0===arguments[0]?this.getInitialState():arguments[0];return t},toString:function(){throw new Error("Stores must implement a toString() method")}}},function(t){"use strict";var n=0,e=function(t){return"function"==typeof t},r=function(t,e){var r=t.bind(null),i="_"+e+"_"+n++;return r.toString=function(){return i},r};t.exports=function(t){var n=Object.keys(t);return n.reduce(function(n,i){var o=t[i];return n[i]=e(o)?r(o,i):o,n},{})}},function(t,n,e){/*! | ||
* is-equal-shallow <https://github.com/jonschlinkert/is-equal-shallow> | ||
@@ -7,3 +7,3 @@ * | ||
*/ | ||
"use strict";var e=n(6);t.exports=function(t,r){if(!t&&!r)return!0;if(!t&&r||t&&!r)return!1;for(var n in r)if(!e(r[n])||!t.hasOwnProperty(n)||t[n]!==r[n])return!1;return!0}},function(t){/*! | ||
"use strict";var r=e(6);t.exports=function(t,n){if(!t&&!n)return!0;if(!t&&n||t&&!n)return!1;for(var e in n)if(!r(n[e])||!t.hasOwnProperty(e)||t[e]!==n[e])return!1;return!0}},function(t){/*! | ||
* is-primitive <https://github.com/jonschlinkert/is-primitive> | ||
@@ -10,0 +10,0 @@ * |
# Actions | ||
1. [Overview](#overview) | ||
2. [Calling Actions](#calling-actions) | ||
3. [Currying](#currying) | ||
## Overview | ||
Actions, as values, describe the signals passed through Microcosm. As | ||
@@ -37,3 +43,3 @@ functions they allow one to prepare data before sending it to Stores | ||
## Callback Shorthand | ||
## Currying | ||
@@ -40,0 +46,0 @@ `app.send` curries actions. This makes it easier to use actions as |
# Stores | ||
1. [Overview](#overview) | ||
2. [API](#api) | ||
3. [Installing Stores](#installing-stores) | ||
4. [Listening to Actions](#listening-to-actions) | ||
## Overview | ||
The responsibility of a Store in Microcosm is to transform state from | ||
@@ -7,4 +14,6 @@ one form to the next. They do not provide any storage of their own | ||
Stores boil down to: | ||
## API | ||
Microcosms call several methods on Stores to help shape information: | ||
```javascript | ||
@@ -11,0 +20,0 @@ var store = { |
{ | ||
"name": "microcosm", | ||
"version": "1.3.0", | ||
"version": "1.4.0", | ||
"description": "An experimental flux implimentation", | ||
@@ -5,0 +5,0 @@ "main": "dist/Microcosm.js", |
@@ -0,1 +1,5 @@ | ||
[![NPM](https://nodei.co/npm/microcosm.png?compact=true)](https://npmjs.org/package/microcosm) | ||
--- | ||
Important! This is largely an exploratory repo, used to vet some ideas | ||
@@ -19,3 +23,3 @@ within Flux/React and support other Viget tools. We will follow semver | ||
[isomorphic](http://artsy.github.io/blog/2013/11/30/rendering-on-the-server-and-client-in-node-dot-js/) | ||
[Flux](facebook.github.io/flux). | ||
[Flux](http://facebook.github.io/flux). | ||
@@ -29,7 +33,7 @@ Specifically, it addresses the problem of isolating state between | ||
Microcosm injects a a couple of opinions regarding the Flux | ||
Microcosm inserts a couple of opinions regarding the Flux | ||
architecture: | ||
1. Typically Flux uses CONSTANT values to pass messages from Actions | ||
to Stores. Microcosm automatically generates these by assigning | ||
1. Flux uses CONSTANT values to pass messages from Actions to | ||
Stores. Microcosm automatically generates these by assigning | ||
each Action function a unique `toString` method. | ||
@@ -39,11 +43,20 @@ 2. Microcosm expects immutability. When an action is fired, the | ||
updated by returning a new value. | ||
3. Stores do not contain data, they _shape_ it. See the section on | ||
3. Stores do not contain data, they _transform_ it. See the section on | ||
stores below. | ||
4. All Actions that return promises will wait to resolve before | ||
dispatching. | ||
5. It should be easily to embed in libraries. Additional features such | ||
should be able to layer on top. | ||
6. It should utilize language features over implementation details as | ||
much as possible. | ||
5. Utilize language features over library abstraction as much as | ||
possible. | ||
## What problems does it attempt to solve? | ||
1. State isolation. Requests to render applications server-side should | ||
be as stateless as possible. Client-side libraries (such as [Colonel | ||
Kurtz](https://github.com/vigetlabs/colonel-kurtz)) need easy | ||
containment from other instances on the page. | ||
2. A reasonable trade-off between the simplicity of singletons and the | ||
state-isolation of class instances. | ||
3. Easy extension of core API and layering of features out of the | ||
framework's scope. | ||
## Design | ||
@@ -50,0 +63,0 @@ |
@@ -13,2 +13,11 @@ import Store from '../Store' | ||
it ('defaults to getInitialState within the deserialize method', function() { | ||
let store = Object.create(Store) | ||
store.getInitialState = sinon.mock() | ||
store.deserialize() | ||
store.getInitialState.should.have.been.called | ||
}) | ||
}) |
@@ -37,3 +37,3 @@ /** | ||
for (var i = 0; i < this._callbacks.length; i++) { | ||
this._callbacks[i]() | ||
this._callbacks[i].call(this) | ||
} | ||
@@ -40,0 +40,0 @@ } |
@@ -21,2 +21,5 @@ /** | ||
getInitialState() { | ||
// Assigns the default state. Most of the time this will not need | ||
// to be overridden, however if using something like ImmutableJS, | ||
// you could return a different data structure here. | ||
return {} | ||
@@ -26,2 +29,6 @@ } | ||
shouldUpdate(prev, next) { | ||
// Whenever an action is dispatched, the resulting state | ||
// modification will be diffed to identify if a change event | ||
// should fire. | ||
// | ||
// The default strategy for determining that state has changed | ||
@@ -33,6 +40,15 @@ // is a simple shallow equals check | ||
seed(data) { | ||
let clean = this.deserialize(data) | ||
// Tells the microcosm how it should handle data injected from | ||
// sources. | ||
// | ||
// By default, it will clean the data with `deserialize` and | ||
// then override the existing data set with the new values | ||
this.swap(this.deserialize(data)) | ||
} | ||
for (var key in clean) { | ||
this.set(key, clean[key]) | ||
swap(next) { | ||
// Given a next state, only trigger an event if state actually changed | ||
if (this.shouldUpdate(this._state, next)) { | ||
this._state = next | ||
this.pump() | ||
} | ||
@@ -42,7 +58,13 @@ } | ||
set(key, value) { | ||
// How state should be re-assigned. This function is useful to | ||
// override with the particular method of assignment for the data | ||
// structure returned from `getInitialState` | ||
this._state = { ...this._state, [key]: value } | ||
} | ||
get(store, seed) { | ||
return this._state[store] | ||
get(key) { | ||
// How state should be retrieved. This function is useful to | ||
// override with the particular method of retrieval for the data | ||
// structure returned from `getInitialState` | ||
return this._state[key] | ||
} | ||
@@ -78,10 +100,4 @@ | ||
// Produce the next state by folding changes into the current state | ||
let next = { ...this._state, ...changes } | ||
this.swap({ ...this._state, ...changes }) | ||
// Finally, only trigger an event if state actually changed | ||
if (this.shouldUpdate(this._state, next)) { | ||
this._state = next | ||
this.pump() | ||
} | ||
// Send back the body to the original signaler | ||
@@ -88,0 +104,0 @@ return body |
@@ -11,3 +11,3 @@ export default { | ||
deserialize(state) { | ||
deserialize(state = this.getInitialState()) { | ||
return state | ||
@@ -14,0 +14,0 @@ }, |
Sorry, the diff of this file is not supported yet
89243
76
1133
314