├── .gitignore
├── Gruntfile.js
├── README.md
├── bower.json
├── dist
├── mockstate.js
├── mockstate.js.map
└── mockstate.min.js
├── img
├── logo_full.png
├── logo_h.png
├── logo_h_small.png
├── mockstate-icon.png
├── mockstate-react.gif
└── react-count.gif
├── package.json
├── src
└── mockstate.js
└── tests
├── actions.js
├── emit.js
├── index.html
├── setState.js
└── store.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 | require('time-grunt')(grunt);
3 | grunt.initConfig({
4 | babel: {
5 | options: {
6 | sourceMap: true,
7 | presets: ['babel-preset-es2015-script']
8 | },
9 | dist: {
10 | files: {
11 | 'dist/mockstate.js': 'src/mockstate.js'
12 | }
13 | }
14 | },
15 | uglify: {
16 | my_target: {
17 | files: {
18 | 'dist/mockstate.min.js': ['dist/mockstate.js']
19 | }
20 | },
21 | },
22 | watch: {
23 | scripts: {
24 | files: 'src/**/*.js', tasks: ['babel', 'uglify']
25 | }
26 | }
27 | });
28 | grunt.loadNpmTasks('grunt-contrib-watch');
29 | grunt.loadNpmTasks('grunt-contrib-uglify');
30 | grunt.loadNpmTasks('grunt-babel');
31 | grunt.registerTask('build', ['babel']);
32 | grunt.registerTask('default', ['babel', 'uglify']);
33 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Deprecated! Use [Dutier](https://github.com/luisvinicius167/dutier) instead.
4 |
5 | Mockstate is a centralized state management for Javascript applications. It provides more control of your state application with a simple and efficiently API and keep the state safe, when the user connection goes offline the state is saved in localStorage to be picked up when the connection back.
6 |
7 | ### :information_desk_person: See the [React.js Todo ➞](http://mockstate-react.surge.sh/)
8 | [](https://www.npmjs.com/package/state)
9 | [](https://unpkg.com/mockstate@0.0.7)
10 |
11 |
12 | ## Demos
13 |
14 | [React.js Todo with Mockstate ➞](http://mockstate-react.surge.sh/)
15 | [Preact.js + Mockstate ➞](http://mockstate-preact.surge.sh/)
16 |
17 | ### Influences
18 | Mockstate provides more control of your application state. It's envolve ideas of Redux and Flux, but explores all power of Promises, doing the work with async action easy.
19 |
20 | ## Getting Started
21 |
22 | ### Install
23 | * Npm: ``` npm install mockstate ```
24 | * Bower: ``` bower install mockstate ```
25 | * CDN: ```https://unpkg.com/mockstate@0.0.7```
26 |
27 | ### Why you should be using Mockstate?
28 | * More control of you application state.
29 | * Safe State.
30 | * It's pure flux, the flow is unidirectional.
31 | * Tiny API.
32 | * Actively maintained and being used in production.
33 |
34 | ### The Gist
35 | The application state is stored in an object tree inside a single store.
36 | The only way to change the state tree is to emit an action, that always return a Promise.
37 | You can receive the result of your action using ``.then`` after your ``dispatch`` call.
38 |
39 | That's it!
40 |
41 | ```javascript
42 | import { setState, setActions, subscribe, dispatch } from 'mockstate';
43 |
44 | /**
45 | * Set your store state in a single object.
46 | */
47 | setState({
48 | count: 0
49 | })
50 |
51 | /**
52 | * Set your store state in a single object,
53 | * that always receive the store state as first argument.
54 | */
55 | setActions({
56 | increment: ( state, n ) => {
57 | let count = state.count += n
58 | return count;
59 | }
60 | });
61 |
62 | /**
63 | * You can use subscribe() to update your UI in response to state changes.
64 | * `${this}` can be your UI component, where the subscribe handler will be applied.
65 | */
66 | subscribe( this, ( data ) => {
67 | console.log(`Some action was called, Action name: ${data.action} Action Value: ${data.value}.`);
68 | })
69 |
70 | /**
71 | * The only way to mutate the internal state is to dispatch an action.
72 | * You can receive the response of your action and do something, or not.
73 | */
74 | dispatch('increment', 1).then( data => {
75 | console.log(`The result of this action ${data.action} is: ${data.value}`);
76 | })
77 | //1
78 | dispatch('increment', 1);
79 | //2
80 | dispatch('increment', 1);
81 | //3
82 | ```
83 |
84 | ### Simple and efficiently API.
85 |
86 | Dispatch
87 | * Trigger some action for do something. A Promise will be returned, that contain an Object with the
88 | keys ``action`` and ``value`` of your correspondent action response.
89 | ```javascript
90 | /**
91 | * @name dispatch
92 | * @description Trigger some action.
93 | * @param {string} actionName Action name
94 | * @param { arguments } Arguments You can pass the arguments after the actionName
95 | * @return {Promise} Return a Promise with an Object that contain the value
96 | * of the action and the action name.
97 | * {value, action} = data;
98 | */
99 |
100 | // On your component
101 | import {dispatch} from 'mockstate';
102 |
103 | // You can receive the response of your action and do something, or not.
104 | // If you whant, you can chaining the dispatch Promises.
105 | dispatch('increment', 1)
106 | .then( data => {
107 | console.log(`The action will be called. The result is: ${data.value}`);
108 | return data.value;
109 | })
110 | .then( value => {
111 | console.log(`The response is: ${value}`);
112 | })
113 | ```
114 |
115 | Actions
116 | * Set your actions functions. Your actions always needs to return a value and receive the state as first argument.
117 | ```javascript
118 | /**
119 | * @name setActions
120 | * @description Set the actions functions.
121 | * @param {object} state The Store State as first argument
122 | * @param { any } args Other Arguments
123 | */
124 |
125 | // actions/index.js
126 | import {setActions} from 'mockstate';
127 |
128 | setActions({
129 | // each action receive the state as first argument
130 | increment: (state, n) => {
131 | setTimeout(() => {
132 | let result = state.count += n;
133 | return result;
134 | }, 2000)
135 | }
136 | });
137 | ```
138 |
139 | Store State
140 | * Set the application Store state
141 | ```javascript
142 | /**
143 | * @name setState
144 | * @description Set you application store state
145 | * @param {object} state Your application state data
146 | */
147 |
148 | // store/index.js
149 | import {setState} from 'mockstate';
150 |
151 | setState({
152 | count: 1
153 | });
154 | ```
155 |
156 | Getting the Store State
157 | * Get a state value of your store
158 | ```javascript
159 | /**
160 | * @name getState
161 | * @description Get the state value
162 | * @param {string} stateName The state name
163 | */
164 |
165 | // store/index.js
166 | import {getState} from 'mockstate';
167 |
168 | let count = getState('count');
169 | ```
170 |
171 | Middleware
172 | * Set a middleware function, that will be triggered after the action calls.
173 | ```javascript
174 | /**
175 | * @name middleware
176 | * @description Get the state value
177 | * @param {Function} callback The callback that will be triggered and
178 | * receives the data of your action and the all state of your store application.
179 | */
180 |
181 | // state/index.js
182 | import { middleware } from 'mockstate';
183 |
184 | middleware( (data, state) => {
185 | console.log('After action triggers:', data, ' and the Store State is: ', state);
186 | })
187 |
188 | ```
189 | Emit
190 | * Tell to store that something are happend and the handler function will be triggerd.
191 | ```javascript
192 | /**
193 | * @name emit
194 | * @description Tell to store that something happend,
195 | * and the handler function will be called.
196 | * @return void
197 | **/
198 |
199 | // state/index.js
200 | import { emit } from 'mockstate';
201 |
202 | emit()
203 | .then( () => {
204 | console.log('After emit called.');
205 | });
206 | ```
207 |
208 | Subscribe/Unsubscribe
209 | * Subscribe some UI Component for trigger the handler function when some action are trigger.
210 | * Unsubscribe when you don't wnat to trigger the handler function.
211 | ```javascript
212 | /**
213 | * @name subscribe
214 | * @description Subscribe some UI Component for trigger the handler function when some action calls.
215 | * @param { object } BindComponent The UI element that the handler function will be applied.
216 | * @param { handler } handler Your function that will be triggered when some state change.
217 | */
218 |
219 | // components/app/index.js
220 | import {subscribe, unsubscribe, getState} from 'mockstate';
221 |
222 | componentWillMount(){
223 | // when some state change, do something.
224 | subscribe(this, ( data ) => {
225 | this.setState({count: getState('count')})
226 | });
227 | }
228 |
229 | componentWillUnmount(){
230 | // remove this component for observe the changes on the state
231 | unsubscribe(this)
232 | }
233 | ```
234 |
235 | #### License
236 | MIT License.
237 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mockstate",
3 | "description": "A centralized state management for Javascript applications, made easy.",
4 | "main": "dist/mockstate.min.js",
5 | "authors": [
6 | "Luis Vinícius "
7 | ],
8 | "license": "MIT",
9 | "keywords": [
10 | "riotjs",
11 | "redux-flux",
12 | "riot.js",
13 | "flux",
14 | "redux",
15 | "mockstate"
16 | ],
17 | "homepage": "https://github.com/luisvinicius167/state",
18 | "moduleType": [],
19 | "ignore": [
20 | "**/.*",
21 | "node_modules",
22 | "bower_components",
23 | "test",
24 | "tests"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/dist/mockstate.js:
--------------------------------------------------------------------------------
1 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
2 |
3 | ;
4 | (function (root, factory) {
5 | if (typeof define === "function" && define.amd) {
6 | define([], factory);
7 | } else if ((typeof exports === "undefined" ? "undefined" : _typeof(exports)) === "object") {
8 | module.exports = {
9 | dispatch: factory.dispatch,
10 | getState: factory.getState,
11 | setState: factory.setState,
12 | setActions: factory.setActions,
13 | subscribe: factory.subscribe,
14 | middleware: factory.middleware,
15 | emit: factory.emit,
16 | unsubscribe: factory.unsubscribe
17 | };
18 | } else {
19 | root.Mockstate = factory;
20 | }
21 | })(this, function (global) {
22 | var _this = this;
23 |
24 | /**
25 | * @name Mockstate
26 | * @description The object that will manage all application state
27 | */
28 | var Mockstate = {
29 | /**
30 | * Persists the store state on localStorage
31 | * @name localState
32 | */
33 | localState: {
34 | /**
35 | * @name recoveryStateWhenOffline
36 | * @description When the user will be offline, keep the store state safe.
37 | */
38 | recoveryStateWhenOffline: function recoveryStateWhenOffline() {
39 | // verify if this === window
40 | if (_this.addEventListener !== undefined) {
41 | /**
42 | * When the page reloads, if the recovery state are present
43 | * recovery the store state.
44 | */
45 | _this.addEventListener("load", function () {
46 | // verify if the recored state are present when the page loads
47 | if (localStorage.getItem('mockstate:StateToRecovery') !== null) {
48 | Mockstate.mockStoreState = JSON.parse(localStorage.getItem('mockstate:StateToRecovery'));
49 | // remove the temporary recovery state
50 | localStorage.removeItem('mockstate:StateToRecovery');
51 | };
52 | });
53 |
54 | // if the network connection back whithout the user reload the page, recovery
55 | // the state.
56 | _this.addEventListener('online', function (e) {
57 | var recoveredState = JSON.parse(localStorage.getItem('mockstate:StateToRecovery'));
58 | Mockstate.mockStoreState = recoveredState;
59 |
60 | // remove the temporary recovery state
61 | localStorage.removeItem('mockstate:StateToRecovery');
62 | });
63 |
64 | _this.addEventListener('offline', function (e) {
65 | /**
66 | * when the network connection is offline, store the actual
67 | * state on localStorage to be recovered when the connection
68 | * become without reload the page or when reload in the same route,
69 | * keeping the state and UI component safe.
70 | */
71 | localStorage.setItem('mockstate:StateToRecovery', JSON.stringify(Mockstate.mockStoreState));
72 | });
73 | }
74 | }
75 | },
76 | /**
77 | * The copy of initial store state, that will be used to work
78 | * in application. Keeping the store state immutable.
79 | */
80 | mockStoreState: {},
81 | /**
82 | * @name _store
83 | * @description The private store
84 | */
85 | _store: {
86 | /**
87 | * @name state
88 | * @description The Store application state
89 | */
90 | state: {},
91 | /**
92 | * @name actions
93 | * @description The Functions that will change the Store state
94 | */
95 | actions: {},
96 | /**
97 | * @name state
98 | * @description The Components that was subscribed
99 | */
100 | components: [],
101 | middleware: {}
102 | },
103 | /**
104 | * @name store
105 | * @description Public Store
106 | */
107 | store: {
108 | /**
109 | * @name subscribe
110 | * @description Subscribe to call the handler function when the action will be triggered
111 | * @param {Component} component The Component
112 | * @param {Function} handler The function that will be called
113 | **/
114 | subscribe: function subscribe(component, handler) {
115 | Mockstate._store.components.push({ component: component, handler: handler });
116 | },
117 | unsubscribe: function unsubscribe(component) {
118 | var components = Mockstate._store.components;
119 | components.forEach(el, function (index) {
120 | if (el === component) {
121 | components.splice(index, 1);
122 | }
123 | });
124 | },
125 | /**
126 | * @name middleware
127 | * @description The middleware function that will be triggered
128 | * every time when an action called.
129 | * @param {Function} callback A function that will be called
130 | **/
131 | middleware: function middleware(callback) {
132 | Mockstate._store.middleware = callback;
133 | },
134 | /**
135 | * @name emit
136 | * @description Tell to store that something happend,
137 | * and the handler function will be called.
138 | * @return void
139 | **/
140 | emit: function emit() {
141 | return new Promise(function (resolve, reject) {
142 | // emit just update the components
143 | var state = {
144 | action: null,
145 | value: null
146 | };
147 | var components = Mockstate._store.components;
148 | components.forEach(function (el, i) {
149 | if (el.component !== undefined && typeof el.handler === "function") {
150 | resolve(el.handler(state));
151 | }
152 | });
153 | });
154 | },
155 | /**
156 | * @name dispatch
157 | * @description Dispatch an action to change
158 | * the store state
159 | * @param { string } action The action name
160 | * @param { any } args Arguments sended to the action
161 | */
162 | dispatch: function dispatch(action) {
163 | for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
164 | args[_key - 1] = arguments[_key];
165 | }
166 |
167 | var state = void 0,
168 | components = Mockstate._store.components;
169 |
170 | var updateStoreData = function updateStoreData() {
171 | var updateStoreState =
172 | // actions don't need to return a promise
173 | Promise.resolve(Mockstate._store.actions[action].apply(null, [].concat(Mockstate.mockStoreState, args))).then(function (value) {
174 | var middleware = Mockstate._store.middleware;
175 |
176 | // state that will be returned
177 | var state = {
178 | action: action,
179 | value: value
180 | };
181 |
182 | /**
183 | * has middleware?
184 | **/
185 | if (typeof middleware === "function") {
186 | middleware.call(null, state, Mockstate.mockStoreState);
187 | }
188 |
189 | return state;
190 | }).then(function (state) {
191 | components.forEach(function (el, i) {
192 | if (el.component !== undefined && typeof el.handler === "function") {
193 | el.handler(state);
194 | }
195 | });
196 | return state;
197 | });
198 |
199 | return updateStoreState;
200 | };
201 | return updateStoreData();
202 | },
203 | /**
204 | * @name setState
205 | * @description Sets the application data state
206 | * @param {object} data Simple Object that contain the State
207 | */
208 | setState: function setState(data) {
209 | // setting the immutable initial state
210 | Object.assign(Mockstate._store.state, data);
211 | Object.assign(Mockstate.mockStoreState, data);
212 | Mockstate.localState.recoveryStateWhenOffline();
213 | },
214 | /**
215 | * @name get
216 | * @param {string} stateName The Store state name
217 | */
218 | getState: function getState(stateName) {
219 | if (stateName === '*') {
220 | return Mockstate.mockStoreState;
221 | }
222 | return Mockstate.mockStoreState[stateName];
223 | },
224 | /**
225 | * @name setActions
226 | * @description Sets the application Actions
227 | * that will change the Store state
228 | */
229 | setActions: function setActions(data) {
230 | Object.assign(Mockstate._store.actions, data);
231 | }
232 | }
233 | };
234 | return Mockstate.store;
235 | }(this));
236 | //# sourceMappingURL=mockstate.js.map
237 |
--------------------------------------------------------------------------------
/dist/mockstate.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["../src/mockstate.js"],"names":["root","factory","define","amd","exports","module","dispatch","getState","setState","setActions","subscribe","middleware","emit","unsubscribe","Mockstate","global","localState","recoveryStateWhenOffline","addEventListener","undefined","localStorage","getItem","mockStoreState","JSON","parse","removeItem","e","recoveredState","setItem","stringify","_store","state","actions","components","store","component","handler","push","forEach","el","splice","index","callback","Promise","resolve","reject","action","value","i","args","updateStoreData","updateStoreState","apply","concat","then","call","data","Object","assign","stateName"],"mappings":"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","file":"mockstate.js","sourcesContent":[";\n(function (root, factory) {\n if (typeof define === \"function\" && define.amd) {\n define([], factory);\n } else if (typeof exports === \"object\") {\n module.exports = {\n dispatch: factory.dispatch,\n getState: factory.getState,\n setState: factory.setState,\n setActions: factory.setActions,\n subscribe: factory.subscribe,\n middleware: factory.middleware,\n emit: factory.emit,\n unsubscribe: factory.unsubscribe\n }\n } else {\n root.Mockstate = factory;\n }\n}(this, function (global) {\n /**\n * @name Mockstate\n * @description The object that will manage all application state\n */\n let Mockstate = {\n /**\n * Persists the store state on localStorage\n * @name localState\n */\n localState: {\n /**\n * @name recoveryStateWhenOffline\n * @description When the user will be offline, keep the store state safe.\n */\n recoveryStateWhenOffline: () => {\n // verify if this === window\n if (this.addEventListener !== undefined) {\n /**\n * When the page reloads, if the recovery state are present\n * recovery the store state.\n */\n this.addEventListener(\"load\", () => {\n // verify if the recored state are present when the page loads\n if (localStorage.getItem('mockstate:StateToRecovery') !== null) {\n Mockstate.mockStoreState = JSON.parse(localStorage.getItem('mockstate:StateToRecovery'));\n // remove the temporary recovery state\n localStorage.removeItem('mockstate:StateToRecovery');\n };\n });\n\n // if the network connection back whithout the user reload the page, recovery\n // the state.\n this.addEventListener('online', (e) => {\n let recoveredState = JSON.parse(localStorage.getItem('mockstate:StateToRecovery'));\n Mockstate.mockStoreState = recoveredState;\n\n // remove the temporary recovery state\n localStorage.removeItem('mockstate:StateToRecovery');\n });\n\n this.addEventListener('offline', (e) => {\n /**\n * when the network connection is offline, store the actual\n * state on localStorage to be recovered when the connection\n * become without reload the page or when reload in the same route,\n * keeping the state and UI component safe.\n */\n localStorage.setItem('mockstate:StateToRecovery', JSON.stringify(Mockstate.mockStoreState));\n });\n }\n }\n },\n /**\n * The copy of initial store state, that will be used to work\n * in application. Keeping the store state immutable.\n */\n mockStoreState: {},\n /**\n * @name _store\n * @description The private store\n */\n _store: {\n /**\n * @name state\n * @description The Store application state\n */\n state: {},\n /**\n * @name actions\n * @description The Functions that will change the Store state\n */\n actions: {},\n /**\n * @name state\n * @description The Components that was subscribed\n */\n components: [],\n middleware: {}\n },\n /**\n * @name store\n * @description Public Store\n */\n store: {\n /**\n * @name subscribe\n * @description Subscribe to call the handler function when the action will be triggered\n * @param {Component} component The Component\n * @param {Function} handler The function that will be called\n **/\n subscribe: (component, handler) => {\n Mockstate\n ._store\n .components\n .push({component, handler});\n },\n unsubscribe: (component) => {\n let components = Mockstate._store.components;\n components.forEach(el, index => {\n if (el === component) {\n components.splice(index, 1);\n }\n });\n },\n /**\n * @name middleware\n * @description The middleware function that will be triggered\n * every time when an action called.\n * @param {Function} callback A function that will be called\n **/\n middleware: (callback) => {\n Mockstate._store.middleware = callback;\n },\n /**\n * @name emit\n * @description Tell to store that something happend,\n * and the handler function will be called.\n * @return void\n **/\n emit: () => {\n return new Promise((resolve, reject) => {\n // emit just update the components\n let state = {\n action: null,\n value: null\n };\n let components = Mockstate._store.components;\n components.forEach((el, i) => {\n if (el.component !== undefined && typeof el.handler === \"function\") {\n resolve(el.handler(state));\n }\n });\n });\n },\n /**\n * @name dispatch\n * @description Dispatch an action to change\n * the store state\n * @param { string } action The action name\n * @param { any } args Arguments sended to the action\n */\n dispatch: (action, ...args) => {\n let state,\n components = Mockstate._store.components;\n\n let updateStoreData = () => {\n let updateStoreState =\n // actions don't need to return a promise\n Promise\n .resolve(Mockstate._store.actions[action].apply(null, [].concat(Mockstate.mockStoreState, args)))\n .then(value => {\n let middleware = Mockstate._store.middleware;\n\n // state that will be returned\n let state = {\n action,\n value\n }\n\n /**\n * has middleware?\n **/\n if (typeof middleware === \"function\") {\n middleware.call(null, state, Mockstate.mockStoreState);\n }\n\n return state;\n\n })\n .then(state => {\n components.forEach((el, i) => {\n if (el.component !== undefined && typeof el.handler === \"function\") {\n el.handler(state)\n }\n });\n return state;\n });\n\n return updateStoreState;\n };\n return updateStoreData()\n },\n /**\n * @name setState\n * @description Sets the application data state\n * @param {object} data Simple Object that contain the State\n */\n setState: (data) => {\n // setting the immutable initial state\n Object.assign(Mockstate._store.state, data);\n Object.assign(Mockstate.mockStoreState, data);\n Mockstate\n .localState\n .recoveryStateWhenOffline();\n },\n /**\n * @name get\n * @param {string} stateName The Store state name\n */\n getState: (stateName) => {\n if (stateName === '*') {\n return Mockstate.mockStoreState;\n }\n return Mockstate.mockStoreState[stateName];\n },\n /**\n * @name setActions\n * @description Sets the application Actions\n * that will change the Store state\n */\n setActions: (data) => {\n Object.assign(Mockstate._store.actions, data);\n }\n }\n };\n return Mockstate.store;\n}(this)));"]}
--------------------------------------------------------------------------------
/dist/mockstate.min.js:
--------------------------------------------------------------------------------
1 | var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};!function(a,b){"function"==typeof define&&define.amd?define([],b):"object"===("undefined"==typeof exports?"undefined":_typeof(exports))?module.exports={dispatch:b.dispatch,getState:b.getState,setState:b.setState,setActions:b.setActions,subscribe:b.subscribe,middleware:b.middleware,emit:b.emit,unsubscribe:b.unsubscribe}:a.Mockstate=b}(this,function(a){var b=this,c={localState:{recoveryStateWhenOffline:function(){void 0!==b.addEventListener&&(b.addEventListener("load",function(){null!==localStorage.getItem("mockstate:StateToRecovery")&&(c.mockStoreState=JSON.parse(localStorage.getItem("mockstate:StateToRecovery")),localStorage.removeItem("mockstate:StateToRecovery"))}),b.addEventListener("online",function(a){var b=JSON.parse(localStorage.getItem("mockstate:StateToRecovery"));c.mockStoreState=b,localStorage.removeItem("mockstate:StateToRecovery")}),b.addEventListener("offline",function(a){localStorage.setItem("mockstate:StateToRecovery",JSON.stringify(c.mockStoreState))}))}},mockStoreState:{},_store:{state:{},actions:{},components:[],middleware:{}},store:{subscribe:function(a,b){c._store.components.push({component:a,handler:b})},unsubscribe:function(a){var b=c._store.components;b.forEach(el,function(c){el===a&&b.splice(c,1)})},middleware:function(a){c._store.middleware=a},emit:function(){return new Promise(function(a,b){var d={action:null,value:null},e=c._store.components;e.forEach(function(b,c){void 0!==b.component&&"function"==typeof b.handler&&a(b.handler(d))})})},dispatch:function(a){for(var b=arguments.length,d=Array(b>1?b-1:0),e=1;e",
22 | "license": "MIT",
23 | "bugs": {
24 | "url": "https://github.com/luisvinicius167/state/issues"
25 | },
26 | "homepage": "https://github.com/luisvinicius167/state#readme",
27 | "devDependencies": {
28 | "babel-preset-es2015-script": "^1.1.0",
29 | "grunt": "latest",
30 | "grunt-babel": "^6.0.0",
31 | "grunt-contrib-uglify": "^2.0.0",
32 | "grunt-contrib-watch": "^1.0.0",
33 | "time-grunt": "^1.4.0"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/mockstate.js:
--------------------------------------------------------------------------------
1 | ;
2 | (function (root, factory) {
3 | if (typeof define === "function" && define.amd) {
4 | define([], factory);
5 | } else if (typeof exports === "object") {
6 | module.exports = {
7 | dispatch: factory.dispatch,
8 | getState: factory.getState,
9 | setState: factory.setState,
10 | setActions: factory.setActions,
11 | subscribe: factory.subscribe,
12 | middleware: factory.middleware,
13 | emit: factory.emit,
14 | unsubscribe: factory.unsubscribe
15 | }
16 | } else {
17 | root.Mockstate = factory;
18 | }
19 | }(this, function (global) {
20 | /**
21 | * @name Mockstate
22 | * @description The object that will manage all application state
23 | */
24 | let Mockstate = {
25 | /**
26 | * Persists the store state on localStorage
27 | * @name localState
28 | */
29 | localState: {
30 | /**
31 | * @name recoveryStateWhenOffline
32 | * @description When the user will be offline, keep the store state safe.
33 | */
34 | recoveryStateWhenOffline: () => {
35 | // verify if this === window
36 | if (this.addEventListener !== undefined) {
37 | /**
38 | * When the page reloads, if the recovery state are present
39 | * recovery the store state.
40 | */
41 | this.addEventListener("load", () => {
42 | // verify if the recored state are present when the page loads
43 | if (localStorage.getItem('mockstate:StateToRecovery') !== null) {
44 | Mockstate.mockStoreState = JSON.parse(localStorage.getItem('mockstate:StateToRecovery'));
45 | // remove the temporary recovery state
46 | localStorage.removeItem('mockstate:StateToRecovery');
47 | };
48 | });
49 |
50 | // if the network connection back whithout the user reload the page, recovery
51 | // the state.
52 | this.addEventListener('online', (e) => {
53 | let recoveredState = JSON.parse(localStorage.getItem('mockstate:StateToRecovery'));
54 | Mockstate.mockStoreState = recoveredState;
55 |
56 | // remove the temporary recovery state
57 | localStorage.removeItem('mockstate:StateToRecovery');
58 | });
59 |
60 | this.addEventListener('offline', (e) => {
61 | /**
62 | * when the network connection is offline, store the actual
63 | * state on localStorage to be recovered when the connection
64 | * become without reload the page or when reload in the same route,
65 | * keeping the state and UI component safe.
66 | */
67 | localStorage.setItem('mockstate:StateToRecovery', JSON.stringify(Mockstate.mockStoreState));
68 | });
69 | }
70 | }
71 | },
72 | /**
73 | * The copy of initial store state, that will be used to work
74 | * in application. Keeping the store state immutable.
75 | */
76 | mockStoreState: {},
77 | /**
78 | * @name _store
79 | * @description The private store
80 | */
81 | _store: {
82 | /**
83 | * @name state
84 | * @description The Store application state
85 | */
86 | state: {},
87 | /**
88 | * @name actions
89 | * @description The Functions that will change the Store state
90 | */
91 | actions: {},
92 | /**
93 | * @name state
94 | * @description The Components that was subscribed
95 | */
96 | components: [],
97 | middleware: {}
98 | },
99 | /**
100 | * @name store
101 | * @description Public Store
102 | */
103 | store: {
104 | /**
105 | * @name subscribe
106 | * @description Subscribe to call the handler function when the action will be triggered
107 | * @param {Component} component The Component
108 | * @param {Function} handler The function that will be called
109 | **/
110 | subscribe: (component, handler) => {
111 | Mockstate
112 | ._store
113 | .components
114 | .push({component, handler});
115 | },
116 | unsubscribe: (component) => {
117 | let components = Mockstate._store.components;
118 | components.forEach((el, index) => {
119 | if (el.component === component) {
120 | components.splice(index, 1);
121 | }
122 | });
123 | },
124 | /**
125 | * @name middleware
126 | * @description The middleware function that will be triggered
127 | * every time when an action called.
128 | * @param {Function} callback A function that will be called
129 | **/
130 | middleware: (callback) => {
131 | Mockstate._store.middleware = callback;
132 | },
133 | /**
134 | * @name emit
135 | * @description Tell to store that something happend,
136 | * and the handler function will be called.
137 | * @return void
138 | **/
139 | emit: () => {
140 | return new Promise((resolve, reject) => {
141 | // emit just update the components
142 | let state = {
143 | action: null,
144 | value: null
145 | };
146 | let components = Mockstate._store.components;
147 | components.forEach((el, i) => {
148 | if (el.component !== undefined && typeof el.handler === "function") {
149 | resolve(el.handler(state));
150 | }
151 | });
152 | });
153 | },
154 | /**
155 | * @name dispatch
156 | * @description Dispatch an action to change
157 | * the store state
158 | * @param { string } action The action name
159 | * @param { any } args Arguments sended to the action
160 | */
161 | dispatch: (action, ...args) => {
162 | let state,
163 | components = Mockstate._store.components;
164 |
165 | let updateStoreData = () => {
166 | let updateStoreState =
167 | // actions don't need to return a promise
168 | Promise
169 | .resolve(Mockstate._store.actions[action].apply(null, [].concat(Mockstate.mockStoreState, args)))
170 | .then(value => {
171 | let middleware = Mockstate._store.middleware;
172 |
173 | // state that will be returned
174 | let state = {
175 | action,
176 | value
177 | }
178 |
179 | /**
180 | * has middleware?
181 | **/
182 | if (typeof middleware === "function") {
183 | middleware.call(null, state, Mockstate.mockStoreState);
184 | }
185 |
186 | return state;
187 |
188 | })
189 | .then(state => {
190 | components.forEach((el, i) => {
191 | if (el.component !== undefined && typeof el.handler === "function") {
192 | el.handler(state)
193 | }
194 | });
195 | return state;
196 | });
197 |
198 | return updateStoreState;
199 | };
200 | return updateStoreData()
201 | },
202 | /**
203 | * @name setState
204 | * @description Sets the application data state
205 | * @param {object} data Simple Object that contain the State
206 | */
207 | setState: (data) => {
208 | // setting the immutable initial state
209 | Object.assign(Mockstate._store.state, data);
210 | Object.assign(Mockstate.mockStoreState, data);
211 | Mockstate
212 | .localState
213 | .recoveryStateWhenOffline();
214 | },
215 | /**
216 | * @name get
217 | * @param {string} stateName The Store state name
218 | */
219 | getState: (stateName) => {
220 | if (stateName === '*') {
221 | return Mockstate.mockStoreState;
222 | }
223 | return Mockstate.mockStoreState[stateName];
224 | },
225 | /**
226 | * @name setActions
227 | * @description Sets the application Actions
228 | * that will change the Store state
229 | */
230 | setActions: (data) => {
231 | Object.assign(Mockstate._store.actions, data);
232 | }
233 | }
234 | };
235 | return Mockstate.store;
236 | }(this)));
237 |
--------------------------------------------------------------------------------
/tests/actions.js:
--------------------------------------------------------------------------------
1 | Mockstate.setActions({
2 | increment: function (state) {
3 | return state.count+=1;
4 | }
5 | })
--------------------------------------------------------------------------------
/tests/emit.js:
--------------------------------------------------------------------------------
1 | Mockstate.subscribe(this, function(){
2 | console.log('Updated.');
3 | })
4 |
5 | setTimeout(function(){
6 | Mockstate.emit().then(function(){
7 | console.log('After emit called.')
8 | });
9 | }, 3000)
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Mocha Tests
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/tests/setState.js:
--------------------------------------------------------------------------------
1 | expect = chai.expect;
2 |
3 | describe('StoreState', function () {
4 |
5 | describe('#getState(count)', function () {
6 | it.only('should be 1', function () {
7 | expect(Mockstate.getState('count')).to.equal(1);
8 | });
9 | });
10 |
11 | describe('#IncrementCount', function () {
12 | it.only('The state count should be 2', function () {
13 | Mockstate.dispatch('increment').then(function (data) {
14 | expect(data.value).to.equal(2);
15 | })
16 | });
17 | });
18 |
19 | describe('#IncrementCountInParalel', function () {
20 |
21 | it.only('Verify the result of the action', function () {
22 | Mockstate.dispatch('increment')
23 | .then(function (data) {
24 | expect(data.value).to.equal(3);
25 | })
26 | Mockstate.dispatch('increment')
27 | .then(function (data) {
28 | expect(data.value).to.equal(4);
29 | })
30 | });
31 |
32 | it.only('Verify the value of count', function () {
33 | expect(Mockstate.getState('count')).to.equal(4);
34 | });
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/tests/store.js:
--------------------------------------------------------------------------------
1 | Mockstate.setState({
2 | count: 1
3 | });
--------------------------------------------------------------------------------