{"_id":"fluxy","_rev":"41-e5f75f0befc0d7f134723efd31a970d8","name":"fluxy","description":"[![Build Status](https://travis-ci.org/jmreidy/fluxy.svg?branch=master)](https://travis-ci.org/jmreidy/fluxy) #Fluxy","dist-tags":{"latest":"0.4.3"},"versions":{"0.1.0":{"name":"fluxy","version":"0.1.0","description":"An implementation of Facebook's Flux architecture.","main":"index.js","directories":{"example":"example","lib":"lib"},"scripts":{"test":"node tests/index.js"},"repository":{"type":"git","url":"https://github.com/jmreidy/fluxy.git"},"author":{"name":"Justin Reidy","email":"jmreidy@rzrsharp.net"},"license":"MIT","dependencies":{"mori":"^0.2.6","bluebird":"^1.2.4","lodash-node":"^2.4.1"},"devDependencies":{"tape":"^2.13.1"},"bugs":{"url":"https://github.com/jmreidy/fluxy/issues"},"homepage":"https://github.com/jmreidy/fluxy","_id":"fluxy@0.1.0","dist":{"shasum":"5cfb623c14d0bc86126b6be787102ed3b88ce560","tarball":"https://registry.npmjs.org/fluxy/-/fluxy-0.1.0.tgz","integrity":"sha512-AZgKFI7V9TAZXN7/skTkygVo3aRCO/oHYMRk2Vzl1uxPrM4FX1XYchcCeDaBzpjUa7QHLYqDVf+tlJHDRY0Rrw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBGUDrXs2a3FT5P/Rf1G/TVGDfshCARuOxhKWRn1IeK9AiBsVgfzEOC9oH/HweZ/L/9Ib/QgISEmXWpdVOUnZL9LFA=="}]},"_from":".","_npmVersion":"1.4.3","_npmUser":{"name":"jmreidy","email":"jmreidy@rzrsharp.net"},"maintainers":[{"name":"jmreidy","email":"jmreidy@rzrsharp.net"}]},"0.1.1":{"name":"fluxy","version":"0.1.1","description":"An implementation of Facebook's Flux architecture.","main":"index.js","directories":{"example":"example","lib":"lib"},"scripts":{"test":"node tests/index.js"},"repository":{"type":"git","url":"https://github.com/jmreidy/fluxy.git"},"author":{"name":"Justin Reidy","email":"jmreidy@rzrsharp.net"},"license":"MIT","dependencies":{"mori":"^0.2.6","bluebird":"^1.2.4","lodash-node":"^2.4.1"},"devDependencies":{"tape":"^2.13.1"},"bugs":{"url":"https://github.com/jmreidy/fluxy/issues"},"homepage":"https://github.com/jmreidy/fluxy","_id":"fluxy@0.1.1","dist":{"shasum":"550b7682c9027af2a485694e3d2e7bbb80133829","tarball":"https://registry.npmjs.org/fluxy/-/fluxy-0.1.1.tgz","integrity":"sha512-e1zqWLAvjOszGlMeTzgENz2dIIL7WjabQ9iDZYupO2E6PHtfWHuodTcjCGI3voVbiO5hMXiQ8QSjlJcJbQ/jLA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC8AxQlgylQTM0+pKam/SXA2Eda8aY8SzEw+OPjb+GbaAiEAgM3XT5V05GiF9kFMk+bG68JaQDOc/PP+j7siUPpb0DM="}]},"_from":".","_npmVersion":"1.4.3","_npmUser":{"name":"jmreidy","email":"jmreidy@rzrsharp.net"},"maintainers":[{"name":"jmreidy","email":"jmreidy@rzrsharp.net"}]},"0.1.2":{"name":"fluxy","version":"0.1.2","description":"An implementation of Facebook's Flux architecture.","main":"index.js","directories":{"example":"example","lib":"lib"},"scripts":{"test":"node tests/index.js"},"repository":{"type":"git","url":"https://github.com/jmreidy/fluxy.git"},"author":{"name":"Justin Reidy","email":"jmreidy@rzrsharp.net"},"license":"MIT","dependencies":{"mori":"^0.2.6","bluebird":"^1.2.4","lodash-node":"^2.4.1"},"devDependencies":{"tape":"^2.13.1"},"bugs":{"url":"https://github.com/jmreidy/fluxy/issues"},"homepage":"https://github.com/jmreidy/fluxy","_id":"fluxy@0.1.2","dist":{"shasum":"6d037dde6e0adad98237b6b1686967c1453d856f","tarball":"https://registry.npmjs.org/fluxy/-/fluxy-0.1.2.tgz","integrity":"sha512-sLdIl29PYCkWoF0vomihQcAjNZi3jsM7HBpZ98re+4FpZ8jvjPlIATETwVD/6UCQeqJazkOYcilQNcAH47WhDA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDbPWpbEcJ0r2+vGW7qXW2CfLCYxZAH3f3wgJRbtHhyjQIhAKmPlAaB5j7Q2pTKvCbPXvpkX+D1HzX8YgXV0xNmZQQQ"}]},"_from":".","_npmVersion":"1.4.3","_npmUser":{"name":"jmreidy","email":"jmreidy@rzrsharp.net"},"maintainers":[{"name":"jmreidy","email":"jmreidy@rzrsharp.net"}]},"0.2.0":{"name":"fluxy","version":"0.2.0","description":"An implementation of Facebook's Flux architecture.","main":"index.js","directories":{"example":"example","lib":"lib"},"scripts":{"test":"node tests/index.js"},"bin":{"fluxy":"./bin/cli.js"},"repository":{"type":"git","url":"https://github.com/jmreidy/fluxy.git"},"author":{"name":"Justin Reidy","email":"jmreidy@rzrsharp.net"},"license":"MIT","dependencies":{"bluebird":"^1.2.4","chalk":"^0.4.0","commander":"^2.2.0","lodash-node":"^2.4.1","minimist":"^0.2.0","mori":"^0.2.6"},"devDependencies":{"tape":"^2.13.1"},"gitHead":"706345c984a2e3e3286b2e0f61542a8f4d83177a","bugs":{"url":"https://github.com/jmreidy/fluxy/issues"},"homepage":"https://github.com/jmreidy/fluxy","_id":"fluxy@0.2.0","_shasum":"e0c58f3dfc537b95735b2b65e97802531c4c978a","_from":".","_npmVersion":"1.4.14","_npmUser":{"name":"jmreidy","email":"jmreidy@rzrsharp.net"},"maintainers":[{"name":"jmreidy","email":"jmreidy@rzrsharp.net"}],"dist":{"shasum":"e0c58f3dfc537b95735b2b65e97802531c4c978a","tarball":"https://registry.npmjs.org/fluxy/-/fluxy-0.2.0.tgz","integrity":"sha512-FCQBECPlfuCjqwcVfJRVu80r6Lb2L39/5hDOeQtIU53XVO7LhR+t3FzPttLa58f+M9ktEmrVHtLEFW67Rk1fmg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEEX15Zaq6POgQcgct7cD2oBcCS+i03AEWGANl6Q7ZLxAiEA/x+s/nEHYqBtNU6OgU+WbPMaZwbk0v/Ul5QjpFbWaGM="}]}},"0.3.0":{"name":"fluxy","version":"0.3.0","description":"An implementation of Facebook's Flux architecture.","main":"index.js","directories":{"example":"example","lib":"lib"},"scripts":{"test":"mocha test/*.test.js","watch":"mocha test/*.test.js -w"},"bin":{"fluxy":"./bin/cli.js"},"repository":{"type":"git","url":"https://github.com/jmreidy/fluxy.git"},"author":{"name":"Justin Reidy","email":"jmreidy@rzrsharp.net"},"license":"MIT","dependencies":{"bluebird":"^1.2.4","chalk":"^0.4.0","commander":"^2.2.0","enum":"^0.2.6","lodash-node":"^2.4.1","minimist":"^0.2.0","mori":"^0.2.9"},"devDependencies":{"mocha":"^1.20.1","proxyquire":"^1.0.1","sinon":"^1.10.3","sinon-chai":"^2.5.0"},"gitHead":"7d68ff37f6128593f02fbada88310b4983dc418c","bugs":{"url":"https://github.com/jmreidy/fluxy/issues"},"homepage":"https://github.com/jmreidy/fluxy","_id":"fluxy@0.3.0","_shasum":"ed12b1fec020f559a71a3a62cbc20a3cc47325c0","_from":".","_npmVersion":"1.4.14","_npmUser":{"name":"jmreidy","email":"jmreidy@rzrsharp.net"},"maintainers":[{"name":"jmreidy","email":"jmreidy@rzrsharp.net"}],"dist":{"shasum":"ed12b1fec020f559a71a3a62cbc20a3cc47325c0","tarball":"https://registry.npmjs.org/fluxy/-/fluxy-0.3.0.tgz","integrity":"sha512-cG19d9alhcGACcYuWCu0sfOc6+szKhsEiYLy1x4CCFbAkQpC6+o+gAhlAf31O5YsR7c52B8PzhUOYc2jKELreg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFB6cQygdx1pNn98zn2OrRJAueHgFz7+vq9kzaEqioGQAiEA7qIjOWRBFCNkXo/Lb5aqoy75MYayxOoDuOvr6XzlgHo="}]}},"0.4.0":{"name":"fluxy","version":"0.4.0","description":"[![Build Status](https://travis-ci.org/jmreidy/fluxy.svg?branch=master)](https://travis-ci.org/jmreidy/fluxy) #Fluxy","main":"index.js","directories":{"example":"example","lib":"lib"},"scripts":{"test":"mocha test/*.test.js","watch":"mocha test/*.test.js -w"},"bin":{"fluxy":"./bin/cli.js"},"repository":{"type":"git","url":"https://github.com/jmreidy/fluxy.git"},"author":{"name":"Justin Reidy","email":"jmreidy@rzrsharp.net"},"license":"MIT","dependencies":{"bluebird":"^1.2.4","chalk":"^0.4.0","commander":"^2.2.0","enum":"^0.2.6","lodash-node":"^2.4.1","minimist":"^0.2.0","mori":"^0.2.9"},"devDependencies":{"body-parser":"^1.5.2","mocha":"^1.20.1","proxyquire":"^1.0.1","sinon":"^1.10.3","sinon-chai":"^2.5.0","superagent":"^0.18.2","transit-js":"^0.8.649"},"bugs":{"url":"https://github.com/jmreidy/fluxy/issues"},"homepage":"https://github.com/jmreidy/fluxy","_id":"fluxy@0.4.0","dist":{"shasum":"ea4c5b85d170f423402d0be61a48f268330f3063","tarball":"https://registry.npmjs.org/fluxy/-/fluxy-0.4.0.tgz","integrity":"sha512-zp7L2COzH2UxWuG7Qpw3aIsSOcJFEIbOIs7fj7jFnyJs/F9DUsKrgaDNVNcpME8atJDv7ubuSKvK7DUH8yJlNA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCLAiebx8JuTUpXFJfSdAnupMZx999m9zaPnvdp0GKL2gIhAJUcun3328Y+VC4I6CHzXf6w6Ws+O9WJqwT59bfxZTiU"}]},"_from":".","_npmVersion":"1.4.3","_npmUser":{"name":"jmreidy","email":"jmreidy@rzrsharp.net"},"maintainers":[{"name":"jmreidy","email":"jmreidy@rzrsharp.net"}]},"0.4.1":{"name":"fluxy","version":"0.4.1","description":"[![Build Status](https://travis-ci.org/jmreidy/fluxy.svg?branch=master)](https://travis-ci.org/jmreidy/fluxy) #Fluxy","main":"index.js","directories":{"example":"example","lib":"lib"},"scripts":{"test":"mocha test/*.test.js","watch":"mocha test/*.test.js -w"},"bin":{"fluxy":"./bin/cli.js"},"repository":{"type":"git","url":"https://github.com/jmreidy/fluxy.git"},"author":{"name":"Justin Reidy","email":"jmreidy@rzrsharp.net"},"license":"MIT","dependencies":{"bluebird":"^1.2.4","chalk":"^0.4.0","commander":"^2.2.0","enum":"^0.2.6","lodash-node":"^2.4.1","minimist":"^0.2.0","mori":"^0.2.9"},"devDependencies":{"body-parser":"^1.5.2","mocha":"^1.20.1","proxyquire":"^1.0.1","sinon":"^1.10.3","sinon-chai":"^2.5.0","superagent":"^0.18.2","transit-js":"^0.8.649"},"gitHead":"9f9e184045ff45da9b5fef97916917866bb956d9","bugs":{"url":"https://github.com/jmreidy/fluxy/issues"},"homepage":"https://github.com/jmreidy/fluxy","_id":"fluxy@0.4.1","_shasum":"e893ce3c83fe8f1e5d3b08ab12183f97d9f6af7d","_from":".","_npmVersion":"1.4.14","_npmUser":{"name":"jmreidy","email":"jmreidy@rzrsharp.net"},"maintainers":[{"name":"jmreidy","email":"jmreidy@rzrsharp.net"}],"dist":{"shasum":"e893ce3c83fe8f1e5d3b08ab12183f97d9f6af7d","tarball":"https://registry.npmjs.org/fluxy/-/fluxy-0.4.1.tgz","integrity":"sha512-demOVb/kNJrAdVbmEa/4pKcGHrWEntvCdf8J4iwKHJyLGEeMWQrL2qbKFrVZrLH8LVmgch2FbrbA5Nb205MFyQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDD/Lb9ETNNs4upYwo5T57kr52UFqrdaiUEjn4lM5JSbAiEA16COyUnNIp+6Y2FHDqVGjCJMSDe1sZ4MYUbhI+1r3+I="}]}},"0.4.2":{"name":"fluxy","version":"0.4.2","description":"[![Build Status](https://travis-ci.org/jmreidy/fluxy.svg?branch=master)](https://travis-ci.org/jmreidy/fluxy) #Fluxy","main":"index.js","directories":{"example":"example","lib":"lib"},"scripts":{"test":"mocha test/*.test.js","watch":"mocha test/*.test.js -w"},"bin":{"fluxy":"./bin/cli.js"},"repository":{"type":"git","url":"https://github.com/jmreidy/fluxy.git"},"author":{"name":"Justin Reidy","email":"jmreidy@rzrsharp.net"},"license":"MIT","dependencies":{"bluebird":"^1.2.4","chalk":"^0.4.0","commander":"^2.2.0","enum":"^0.2.6","lodash-node":"^2.4.1","minimist":"^0.2.0","mori":"^0.2.9"},"devDependencies":{"body-parser":"^1.5.2","mocha":"^1.20.1","proxyquire":"^1.0.1","sinon":"^1.10.3","sinon-chai":"^2.5.0","superagent":"^0.18.2","transit-js":"^0.8.649"},"gitHead":"8f22e652757da29ebab2ab1225a379280a18da1e","bugs":{"url":"https://github.com/jmreidy/fluxy/issues"},"homepage":"https://github.com/jmreidy/fluxy","_id":"fluxy@0.4.2","_shasum":"73df35a27d46cdbb6a0ae1d156abd36197693880","_from":".","_npmVersion":"2.1.7","_nodeVersion":"0.10.32","_npmUser":{"name":"jmreidy","email":"jmreidy@rzrsharp.net"},"maintainers":[{"name":"jmreidy","email":"jmreidy@rzrsharp.net"}],"dist":{"shasum":"73df35a27d46cdbb6a0ae1d156abd36197693880","tarball":"https://registry.npmjs.org/fluxy/-/fluxy-0.4.2.tgz","integrity":"sha512-6BmNWFUVEQ9W/edEUMYBhZ4EAGINPIX0QUiMHiP2ScW+A/OfdbWbnuZ+xBCUR+WcCZEUjr0e2EV9OYHEI5fWkA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICdeRB9wfgc/EjNkHvw7JNaeqvpyIhYH6FzMgReokLrQAiAoXvEjXO/HVm438kAXlmz1ZlAsYcLFJTqwqcwKdhNs+w=="}]}},"0.4.3":{"name":"fluxy","version":"0.4.3","description":"[![Build Status](https://travis-ci.org/jmreidy/fluxy.svg?branch=master)](https://travis-ci.org/jmreidy/fluxy) #Fluxy","main":"index.js","directories":{"example":"example","lib":"lib"},"scripts":{"test":"mocha test/*.test.js","watch":"mocha test/*.test.js -w"},"bin":{"fluxy":"./bin/cli.js"},"repository":{"type":"git","url":"https://github.com/jmreidy/fluxy.git"},"author":{"name":"Justin Reidy","email":"jmreidy@rzrsharp.net"},"license":"MIT","dependencies":{"bluebird":"^1.2.4","chalk":"^0.4.0","commander":"^2.2.0","enum":"^2.1.0","lodash-node":"^2.4.1","minimist":"^0.2.0","mori":"^0.2.9"},"devDependencies":{"body-parser":"^1.5.2","mocha":"^1.20.1","proxyquire":"^1.0.1","sinon":"^1.10.3","sinon-chai":"^2.5.0","superagent":"^0.18.2","transit-js":"^0.8.649"},"gitHead":"1b032d3dab32862685a3bc386a6e5c784a03d4fd","bugs":{"url":"https://github.com/jmreidy/fluxy/issues"},"homepage":"https://github.com/jmreidy/fluxy","_id":"fluxy@0.4.3","_shasum":"07c81bc0940ccb0f80a68e933fa34ab7de5e5d9f","_from":".","_npmVersion":"2.1.7","_nodeVersion":"0.10.32","_npmUser":{"name":"jmreidy","email":"jmreidy@rzrsharp.net"},"maintainers":[{"name":"jmreidy","email":"jmreidy@rzrsharp.net"}],"dist":{"shasum":"07c81bc0940ccb0f80a68e933fa34ab7de5e5d9f","tarball":"https://registry.npmjs.org/fluxy/-/fluxy-0.4.3.tgz","integrity":"sha512-AK+InyqfeOTh3wEK/zZbKgu5E+V5Ndzd0nhhEQLxm6xUPamwVbdxcyKwlv4Ain3FuWfVNNubSFWIyI10ZfTuKg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDR3baIFJmuJ+ZhP2Y9P9GBX9j6P5gCOnFpIIEkeZ3e+AiBjt2+7IDOzYrR4+gZcb3Bg6DpPc9OYvpeu9SWLmay0SA=="}]}}},"readme":"[![Build Status](https://travis-ci.org/jmreidy/fluxy.svg?branch=master)](https://travis-ci.org/jmreidy/fluxy)\n#Fluxy\n\nAn implementation of Facebook's Flux architecture.\n\n##Introduction\n\nThe Facebook / React team has an [introduction to\nFlux](http://facebook.github.io/react/docs/flux-overview.html) included with\nthe React documentation. Distilled to its core, Flux reimagines the\ntraditional MVC approach to client-side webapps, replacing it with the\nsame concept of \"one-way data flow\" that powers React.\n\nWhile the Facebook documentation (and accompanying video) do an excellent job of\nintroducing the core concepts behind Flux, there's a few key details that are important\nto emphasize:\n\n###Stores\nAll application data is managed in Stores, which are Singleton objects focused on a specific\nset of business logic (e.g ArticleStore, UserStore). Views should interact with Stores\nas the single source of data truth. Store *do not replace* the React state system; rather,\nReact components should use state to handle view-specific data state, and stores to handle application\ndata state. Stores are event emitters that emit change events for underlying state changes.\n\n###Actions\nWhile Views access data directly from Stores, they never mutate data directly. Rather,\nViews should trigger Actions, which in turn trigger broadcast notifications throughout the system.\nBroadcast notifications are identified via lookups in enum Constants, and include a payload object.\n\nFor example, clicking a button in a view to favorite an article would make a call to an ArticleFavorite action,\nwhich would then broadcast a FAVORITE_ARTICLE notification with an appropriate payload\nfor any Stores that want to perform an optimistic update. The Action would then interact with a DAO\nor Service to perform the actual server-side favorite; depending on the result of this interaction,\nthe Action would then broadcast a FAVORITE_ARTICLE_COMPLETED or FAVORITE_ARTICLE_FAILED notification.\n\n###Dispatcher\nEach of the notifications broadcast via the Actions described above are marshalled through a central bus,\nthe Dispatcher. The Dispatcher ensures that only one notification can be handled at a time; new notifications\nare queued until all action handlers have finished operating for the previous notification. Stores register\ntheir action handlers for specific notifications directly with the Dispatcher, and can specify action handler\ndependencies - that is, an action handler can have its invocation delayed until the completion of other\naction handlers.\n\n###This Implementation\nFacebook has not yet released their own implementation of Flux, but the JS community\nhas started the ideas behind the Flux architecture, most notably in @BinaryMuse's\n[fluxxor](https://github.com/BinaryMuse/fluxxor). Fluxy is an implementation that\nincludes some differentiating features:\n\n  * View components should be completely separated from Flux. They can intereact with Flux Stores\n  and Actions via direct API calls, without coupling them to the Flux implementation.\n\n  * Promises (via [Bluebird](https://github.com/petkaantonov/bluebird/)) drive the Dispatcher/Action system, along for the easy registration of async action handlers\n\n  * Stores embrace immutable data, going so far as to be powered by [Mori](https://github.com/swannodette/mori), which\n  provides a light convenience API around ClojureScript's data structures.\n\n\n##How it Works\nA Fluxy implementation will define and use three different types of service\nobjects: Stores, Actions, and Constants. While these three types of objects operate\nin concert, their roles are very distinct from one another - in fact, a Store should\nnever call an Action, and an Action should never call into a Store. Instead, the Dispatcher\nunifies Action and Store objects, with messages defined by Constants. (All of the details\nof the Dispatch queue are hidden from the actual application implementation, so you don't need\nto worry about how the communication is happening behind the scenes.)\n\nIn order to keep your application modular, there's just one rule to remember: Views issue\nCOMMANDS to Actions, and QUERIES to Stores.\n\nThat means that *any* updates to application state should be routed through an Action, and never via\na direct call from a view into a Store.\n\n###Actions\nActions can be considered command objects. They are called directly by view components.\nThey trigger service updates directly, and send messages to Stores by calling `this.dispatchAction(messageName, ...args)`.\n\nAn example Action can be seen below:\n\n```javascript\nvar Fluxy = require('fluxy');\n\nvar TodoConstants = require('../constants/TodoConstants');\nvar TodoService = require('../services/TodoService');\n\nvar TodoActions = Fluxy.createActions({\n  serviceActions: {\n    create: [TodoConstants.TODO_CREATE, function (text) {\n      return TodoService.create(text); //returns promise\n    }],\n    destroy: [TodoConstants.TODO_DESTROY, function (id) {\n      return TodoService.destroy(id); //returns promise\n    }]\n  },\n  toggleExpanded: function (expandFlag) {\n    this.dispatchAction(TodoConstants.TODO_TOGGLE_EXPANDED, expandFlag);\n  }\n});\n\nmodule.exports = TodoActions;\n```\nThe most interesting aspect to Actions is the special definition of `serviceActions`.\nBecause so many Fluxy behaviors amount to\nthe same flow - Action Message leading to a service call, which either succeeds (MESSAGE_COMPLETED) or\nfails (MESSAGE_FAILED) - Fluxy defines a special type of action to reduce boilerplate. `serviceActions`\nautomatically wire up a promise and message dispatch queue.\n\nLet's take the first service action defined: `create`.\nThat service action will define a `create(text)` method on the TodoActions singleton. Calling `create(text)` will\nAUTOMATICALLY dispatch a `TODO_CREATE` message. The service action will then call the service method, and wire up\npromise result and failure handlers.\n\nAll of that means, most simply, that this:\n```javascript\nvar TodoActions = Fluxy.createActions({\n  serviceActions: {\n    create: [TodoConstants.TODO_CREATE, function (text) {\n      return TodoService.create(text); //returns promise\n    }]\n  },\n});\n```\nIs actually the same as this:\n```javascript\nvar TodoActions = Fluxy.createActions({\n  create: function (text) {\n    var self = this;\n    this.dispatchAction(TodoConstants.TODO_CREATE);\n    TodoService.create(text)\n      .then(function (result) {\n        self.dispatchAction(TodoConstants.TODO_CREATE_COMPLETED, result);\n      })\n      .catch(function (err) {\n        self.dispatchAction(TodoConstants.TODO_CREATE_FAILED, err);\n      });\n  }\n});\n```\nSee how much boilerplate that saved? It's like a poor dev's macro.\n\nThere's nothing preventing you from defining the `create` action in its longer form. Any methods\ncan be defined on an Action. `serviceActions` just make your life a little easier.\n\n\n###Constants\nConstants are exactly that: Enums of constants. While Constants are primarily used to define\nstring message names for dispatching, they can also store any constant values used by the app.\n\nAn example:\n```javascript\n  var Fluxy = require('fluxy');\n\n  var TodoConstants = Fluxy.createConstants({\n    serviceMessages: [\n      'TODO_CREATE',\n      'TODO_UPDATE_TEXT',\n      'TODO_TOGGLE_COMPLETION',\n      'TODO_COMPLETE_ALL',\n      'TODO_DESTROY',\n      'TODO_DESTROY_COMPLETED_TODOS'\n    ],\n    messages: ['TODO_CHANGED'],\n    values: {\n      MAX_TODOS: 99\n    }\n  });\n\n  module.exports = TodoConstants;\n```\nA Constant singleton is really just an Enum - in fact, the `createConstants` call is simply deferring\nto the [Enum](https://github.com/adrai/enum) constructor. `messages` and `servicesMessages` have\nequivalent key and value pairs. `values` have a string key and a variable value.\n\n`serviceMessages` perform the same helpful function as `serviceActions` above - they accomodate for\nthe routing call/completed/failed service flow. So each string defined in the `serviceMessages` array\nactually creates three string constants. In the example above, `TodoConstants.TODO_CREATE_COMPLETED` and\n`TodoConstants.TODO_CREATE_FAILED` are created in addition to `TODO_CREATE`.\n\n`messages` create string constants as well, they just don't add the `COMPLETED` and `FAILED` pairings.\n\n`values` can have any type of value. In the above example, `TodoConstants.MAX_TODOS.value` will equal 99.\n\n###Stores\nStores are the heart of the Fluxy implementation. In addition to responding to message dispatches, they\nmanage all application state via immutable mori data structures.\n\nAn example Store implementation:\n```javascript\nvar TodoConstants = require('../constants/TodoConstants');\nvar Fluxy = require('fluxy');\nvar $ = Fluxy.$;\n\nvar TodoStore = Fluxy.createStore({\n  getInitialState: function () {\n    return {\n      todos: {}\n    };\n  },\n  areAllComplete: function () {\n    return $.every(function (todo) {\n      return $.get(todo, 'completed') === true;\n    }, $.vals(this.get('todos')));\n  },\n  actions: [\n    [TodoConstants.TODO_CREATE_COMPLETED, function (todo) {\n      this.set(['todos', todo.id.toString()], $.js_to_clj(todo));\n    }],\n    [TodoConstants.TODO_COMPLETE_ALL, function () {\n      this.set(['todos'], function (todoMap) {\n        return $.reduce_kv(\n          function(acc, key, val) {\n            return $.assoc(acc, key, $.assoc(val, 'complete', true));\n          },\n          $.hash_map(),\n          todoMap\n        );\n      });\n    }],\n  ]\n});\n```\nStores are the most complex part of Fluxy, and require a much deeper explanation.\n\nFirst, lets look at the `actions` definition. `actions` autowrite message handlers to\nthe dispatcher. In the example above, a `TodoStore.handleTodoCreateCompleted` function is created.\nThis function is automatically wired to the Fluxy Dispatcher and listens to the `TodoConstants.TODO_CREATE_COMPLETED`\nmessage. The actual handler behavior is defined as a function in the array definition.\n\nAlso note that it's possible to create dependencies in how Stores handle dispatches. In the below example,\nthe defined handler is called AFTER the SessionStore handler has finished.\n```javascript\n  actions: [\n    [UserConstants.LOGIN_COMPLETED, {waitFor: [SessionStore]}, function (user) {\n      this.set('user', user);\n    }],\n  ]\n```\nAnd if the SessionStore handler had returned a promise, the handler above wouldn't\nexecute until after the promise had resolved.\n\nYou'll note the use of `$` in the Store. That's not a jQuery reference! It's a reference to the `mori`\nAPI. You can access mori directly through `Fluxy.$`, or directly on the Store singleton - all of mori's\nfunctions are proxied through to the Store and prefixed with a `$`. (So `Store.$equals` will proxy to mori.equals).\n\n`getInitialState` defines the initial state of the Store. The object that's returned by the `getInitialState`\nfunction will be cast into a ClojureScript data structure. It's accessible directly via `Store.state`, but\nmost of the interactions should be made through the helper API functions `get` and `set`.\n\n`get(keyOrKeyArray)` calls directly into `Store.state`. It can be provided with a string key or an array of keys.\nA string key lookup is the rough equivalent of `state.<key>`. The array lookup is much more powerful, as it allows\nfor \"looking into\" the Store state, reaching deeply into a nested data structore. For example, `get(['todos', 571, 'text'])`\nis the rough equivalent of `Store.state.todos[571].text`. (Don't worry, ClojureScript won't throw an undefined error as it walks\nits data structure!)\n\n`set(keyOrArrayOfKeys, valOrFn)` is the setter equivalent of `get`. In addition to performing the same flat or deep\naccess that `get` provides, it can also update a value in one of two ways - either by assigning a value directly, or\nas the result of an update function. In the example below...\n```javascript\nStore.set(['todos', 101, 'complete'], function (completeFlag) { return !completeFlag; });\n```\n...the state of todo 101's completion is being toggled by the update function. This notation allows for\nsome nice functional composition.\n\nThere are a few other benefits to using the `set` helper. First, it not only updates the Store state - it handles the storage\nof the Store's existing state. That's right - the entire history of Store states is tracked in `Store.state`. That means\nyou can always call `Store.undo()` to rollback state. After updating the Store's state and state history, `set` will trigger\nan event for any defined watchers with references to both the previous state and the new state.\n\nIn addition to `set`, there's a corresponding `setFromJS` method which automatically converts\nthe set value into a ClojureScript data structure (e.g. a JS object to a CLJS map). It delegates\nto the underlying `Store.set` method.\n\nWatchers are defined against the Store directly:\n```javascript\nStore.addWatch(function (keys, oldState, newState) {...});\n```\nAnd removed just as easily:\n```javascript\nStore.removeWatch(watcherFn);\n```\n\nNote the `keys` argument of the watcher handler. It's a reference to string or array of keys passed\ninto the `set` function. Using keys, you can easily figure out whether your watcher handler should\ncare about the updated state (or not).\n\nNote that `get` by default returns the ClojureScript data structure. You can access the JS representation\neither by calling `Store.getAsJS`, which behaves the same as `Store.get`, or by calling `Store.toJS(cljObj)`, which\ncasts the provided structure to JavaScript. Using the ClojureScript objects allows for easy tests in your `shouldComponentUpdate`\nfunctions, but otherwise, ClojureScript objects should not be used extensively (if at all) in your view components, for risk\nof tying your components too tightly to the Fluxy implementation.\n\n\n###\"Harness\"\nStores, Actions, and Constants are all managed by a singleton Fluxy. In addition to allowing you to create\nthese key components of a Fluxy app, it also allows you to easily access the global application state.\n\n`createStore`, `createActions`, and `createConstants` are all described in the respective sections above.\n\n`start(initialState)` is the call that triggers the instantiation and injection of all Fluxy components. If you pass a\nhash map into the start function, it will set the state of each store to reflect the injected map. For example,\nsay you have a Store with a name of `TodoStore` and call start with `{TodoStore: { todos: todosArr }}`; making\nthis call will start the app with the TodoStore having the todo key in its state set to the value of `todosArr`.\n\n`bootstrap(prop, context)` is a convenience method for calling start with the\nvalue of a window prop (or a prop on a provided context). Bootstrap is most useful for, appropriately,\nbootstrapping an application's state with serialized JSON embedded in the page's HTML.\n\n`renderStateToString(serializer)` serializes the entire graph of all Store states to a string,\nwith the keys of the serialization corresponding to each Store's name. While this method will\ndefault to using a \"safe\" version of `JSON.stringify`, any serialization function can be provided - for example,\nthe `write` function from cognitect/transit-js.\n\n`start`, `bootstrap`, and `renderStateToString` can be easily combined to power server-side rendering. Just follow\nthe below steps:\n\n1. Give your stores a unique name. `Fluxy.createStore({name: 'TodoStore', //other config})`\n\n2. Before calling `React.renderComponentToString`, make sure to call `Fluxy.start` on the server,\npassing it a hash of Store initial states (keyed by Store name)\n\n3. Make sure to bootstrap your HTML load with the state you passed to Fluxy with `Fluxy.renderStateToString`\n\n4. Finally, in your client side code, instead of calling `Fluxy.start`, call `Fluxy.bootstrap(windowKeyOfBootstrappedData)`\n\n---\n\nFor further details, be sure to check out the `examples` directory and the test suite.\n\n##Roadmap to 1.0\n- [x] Update generators to work with new API\n- [x] Update example app to work with new API\n- [x] Provide basic implementation steps in the README\n- [ ] Lock down API\n- [ ] Add code documentation\n- [ ] Cleanup internal implementation\n","maintainers":[{"name":"jmreidy","email":"jmreidy@rzrsharp.net"}],"time":{"modified":"2022-06-18T02:31:58.169Z","created":"2014-05-30T17:23:22.728Z","0.1.0":"2014-05-30T17:23:22.728Z","0.1.1":"2014-05-31T02:14:22.054Z","0.1.2":"2014-06-04T00:52:57.268Z","0.2.0":"2014-06-27T00:14:52.932Z","0.2.1":"2014-06-30T20:56:01.631Z","0.3.0-beta1":"2014-07-16T21:15:57.290Z","0.3.0-beta2":"2014-07-16T21:52:14.453Z","0.3.0-beta3":"2014-07-16T23:16:26.569Z","0.3.0-beta4":"2014-07-16T23:37:19.264Z","0.3.0":"2014-07-17T02:31:17.328Z","0.4.0":"2014-07-29T02:50:56.593Z","0.4.1":"2014-07-29T17:37:16.953Z","0.4.2":"2015-01-22T17:29:22.447Z","0.4.3":"2015-06-02T00:10:42.656Z"},"homepage":"https://github.com/jmreidy/fluxy","repository":{"type":"git","url":"https://github.com/jmreidy/fluxy.git"},"author":{"name":"Justin Reidy","email":"jmreidy@rzrsharp.net"},"bugs":{"url":"https://github.com/jmreidy/fluxy/issues"},"license":"MIT","readmeFilename":"README.md","users":{}}