forked from storeon/storeon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
133 lines (121 loc) · 2.93 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* Initialize new store and apply all modules to the store.
*
* @param {moduleInitializer[]} modules Functions which will set initial state
* define reducer and subscribe
* to all system events.
*
* @return {Store} The new store.
*
* @example
* import createStore from 'storeon'
* let increment = store => {
* store.on('@init', () => ({ count: 0 }))
* store.on('inc', ({ count }) => ({ count: count + 1 }))
* }
* const store = createStore([increment])
* store.get().count //=> 0
* store.dispatch('inc')
* store.get().count //=> 1
*/
function createStore (modules) {
var events = { }
var state = { }
function on (event, cb) {
if (!events[event]) {
events[event] = [cb]
} else {
events[event].push(cb)
}
return function () {
events[event] = events[event].filter(function (i) {
return i !== cb
})
}
}
function dispatch (event, data) {
if (event !== '@dispatch') {
dispatch('@dispatch', [event, data])
}
if (process.env.NODE_ENV !== 'production') {
if (event.indexOf('@') !== 0 && !events[event]) {
throw new Error('Unknown Storeon event ' + event)
}
}
if (events[event]) {
var changes = { }
var changed, key
events[event].forEach(function (i) {
var diff = i(state, data)
if (diff) {
changed = true
var newState = { }
for (key in state) newState[key] = state[key]
for (key in diff) newState[key] = changes[key] = diff[key]
state = newState
}
})
if (changed) dispatch('@changed', changes)
}
}
function get () {
return state
}
var store = { on: on, dispatch: dispatch, get: get }
modules.forEach(function (i) {
if (i) i(store)
})
dispatch('@init')
return store
}
module.exports = createStore
/**
* Store with application state and event listeners.
*
* @name Store
* @class
*/
/**
* Return current state. You can use this method only to read state.
* Any state changes should be in event listeners.
*
* @return {object} The current state.
*
* @name get
* @function
* @memberof Store#
*/
/**
* Emit event.
*
* @param {string} event The event name.
* @param {*} [data] Any additional data for the event.
*
* @return {object} The current state.
*
* @name dispatch
* @function
* @memberof Store#
*/
/**
* Add event listener.
*
* @param {string} event The event name.
* @param {listener} listener The event listener.
*
* @return {function} The function to remove listener.
*
* @name on
* @function
* @memberof Store#
*/
/**
* @callback moduleInitializer
* @param {Store} store Store to define initial state and reducers.
*/
/**
* @callback listener
* @param {object} state The current state of the store.
* @param {*} [data] The event data if it was passed.
* @return {object|undefined} Changes for next state.
*/