-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathindex.js
72 lines (59 loc) · 2.1 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
var globals = [
'DOMContentLoaded',
'DOMTitleChange',
'navigate',
'popState',
'pushState',
'render',
'replaceState'
]
/**
* Create a new store.
*
* @param {object} options - store options
* @param {string} options[].storeName - name of store - used for namespacing & debugging
* @param {object} options[].initialState - initial state of store - used for init & reset
* @param {object} options[].events - event functions
* @return {function} - choo middleware function
*/
function createStore (options) {
var { storeName, initialState, events } = options || {}
if (typeof storeName !== 'string') throw new Error('storeName required')
if (typeof initialState !== 'object') throw new Error('initialState required')
if (typeof events !== 'object') throw new Error('events required')
var props = Object.assign({}, options, { actions: {} })
// API ref: https://github.com/choojs/choo#appusecallbackstate-emitter-app
function store (state, emitter, app) {
state[storeName] = deepClone(initialState)
state.events = state.events || {} // be defensive
state.events[storeName] = {}
// add reset event if undefined
if (!props.events.reset) {
props.events.reset = ({ data, store, emitter }) => {
var { render } = data || {}
state[storeName] = deepClone(initialState)
if (render) emitter.emit('render')
}
}
Object.keys(events).forEach(event => {
var eventName = globals.includes(event) ? event : `${storeName}:${event}`
// attach events to emitter
emitter.on(eventName, data => {
events[event]({ data, store: state[storeName], emitter, state, app })
})
// don't create namespaced event hooks for global events
if (!globals.includes(event)) {
// add event names to state.events
state.events[storeName][event] = eventName
// add action method
props.actions[event] = data => emitter.emit(eventName, data)
}
})
}
Object.assign(store, props)
return store
}
function deepClone (obj) {
return JSON.parse(JSON.stringify(obj))
}
module.exports = createStore