UNPKG

5.53 kBJavaScriptView Raw
1/**
2 * @class Apemanstore
3 * @param {Object} state - Preloaded state variables
4 * @param {Object} [options={}] - Optional settings
5 */
6'use strict'
7
8const {
9 create: createStore,
10 devTool
11} = require('bredux')
12const reducer = require('./reducer')
13const {
14 SET,
15 UPDATE,
16 DEL,
17 PUSH,
18 PUSH_ALL,
19 POP,
20 SHIFT,
21 POP_ALL,
22 REJECT,
23 FLIP,
24 INCREMENT,
25 DECREMENT
26} = require('./operations')
27
28const { get, set } = require('json-pointer')
29
30class ApemanstoreBase {
31 constructor (state, options = {}) {
32 const s = this
33 let {
34 scopeName = '/',
35 store = createStore(reducer, state, [
36 devTool && devTool()
37 ])
38 } = options
39 s._store = store
40 s._scopeName = scopeName
41 }
42
43 /**
44 * Dispatch operation
45 * @private
46 * @param {string} operation - Type of operation
47 * @param {string} field - Name of field
48 * @param {*} value - Operation value
49 * @param {boolean} [isError=false]
50 */
51 $do (operation, field, value, isError = false) {
52 const s = this
53 s._store.dispatch({
54 type: [ s._scopeName, operation ].join(':'),
55 meta: { field: field },
56 payload: value,
57 error: isError
58 })
59 }
60
61 /**
62 * Get store value
63 * @param {string} field - Name of field
64 * @returns {*} - Stored value
65 */
66 get (field) {
67 const s = this
68 return [
69 field
70 ].reduce((state = {}, key) => state[ key ], s.toJSON())
71 }
72
73 /**
74 * Create sub store with scope
75 * @param {string} namespace - Name of scope
76 * @returns {Apemanstore}
77 */
78 sub (namespace) {
79 const s = this
80 let invalid = /[\/@]/.test(namespace)
81 if (invalid) {
82 throw new Error(`[apemanstore] Invalid scope name: ${namespace}`)
83 }
84 let scopeName = [ s._scopeName, `${namespace}` ].join('/').replace(/^\/\//, '/')
85 let sub = new Apemanstore(null, {
86 scopeName,
87 store: s._store
88 })
89 sub.super = () => s
90 return sub
91 }
92
93 /**
94 * Convert in to state variables
95 * @returns {Object}
96 */
97 toJSON () {
98 const s = this
99 let state = s._store.getState()
100 let scopeName = s._scopeName
101 return Object.keys(state)
102 .sort()
103 .filter((key) => key.indexOf(scopeName) === 0)
104 .reduce((collapsed, key) => {
105 let subKeys = key.substring(scopeName.length)
106 .split(/\//g)
107 .filter(Boolean)
108 .map((subKey) => `@${subKey}`)
109 let assigning = collapsed
110 for (let subKey of subKeys) {
111 assigning[ subKey ] = assigning[ subKey ] || {}
112 assigning = assigning[ subKey ]
113 }
114 Object.assign(assigning, state[ key ])
115 return collapsed
116 }, {})
117 }
118}
119
120/** @lends Apemanstore */
121class Apemanstore extends ApemanstoreBase {
122 // ---------------
123 // Operation methods
124 // ---------------
125
126 /**
127 * Set a value on field
128 * @param {string} field
129 * @param {*} value
130 */
131 set (field, value) {
132 const s = this
133 let byObject = (arguments.length === 1) && (typeof arguments[ 0 ] === 'object')
134 if (byObject) {
135 Object.keys(arguments[ 0 ]).forEach((field) => {
136 s.set(field, arguments[ 0 ][ field ])
137 })
138 } else {
139 s.$do(SET, field, value)
140 }
141 }
142
143 /**
144 * Do update operation
145 * @param {string} field - Operation target field
146 * @param {*} value - Operation value
147 */
148 update (field, value) {
149 const s = this
150 s.$do(UPDATE, field, value)
151 }
152
153 /**
154 * Do del operation
155 * @param {string} field - Operation target field
156 * @param {*} value - Operation value
157 */
158 del (field, value) {
159 const s = this
160 s.$do(DEL, field, value)
161 }
162
163 /**
164 * Do push operation
165 * @param {string} field - Operation target field
166 * @param {*} value - Operation value
167 */
168 push (field, value) {
169 const s = this
170 s.$do(PUSH, field, value)
171 }
172
173 /**
174 * Do push_all operation
175 * @param {string} field - Operation target field
176 * @param {*} value - Operation value
177 */
178 pushAll (field, value) {
179 const s = this
180 s.$do(PUSH_ALL, field, value)
181 }
182
183 /**
184 * Do pop operation
185 * @param {string} field - Operation target field
186 * @param {*} value - Operation value
187 */
188 pop (field, value) {
189 const s = this
190 s.$do(POP, field, value)
191 }
192
193 /**
194 * Do shift operation
195 * @param {string} field - Operation target field
196 * @param {*} value - Operation value
197 */
198 shift (field, value) {
199 const s = this
200 s.$do(SHIFT, field, value)
201 }
202
203 /**
204 * Do pop_all operation
205 * @param {string} field - Operation target field
206 * @param {*} value - Operation value
207 */
208 popAll (field, value) {
209 const s = this
210 s.$do(POP_ALL, field, value)
211 }
212
213 /**
214 * Do reject operation
215 * @param {string} field - Operation target field
216 * @param {*} value - Operation value
217 */
218 reject (field, value) {
219 const s = this
220 s.$do(REJECT, field, value)
221 }
222
223 /**
224 * Do flip operation
225 * @param {string} field - Operation target field
226 * @param {boolean} [value] - Operation value
227 */
228 flip (field, value) {
229 const s = this
230 s.$do(FLIP, field, value)
231 }
232
233 /**
234 * Do increment operation
235 * @param {string} field - Operation target field
236 * @param {number} value - Operation value
237 */
238 increment (field, value) {
239 const s = this
240 s.$do(INCREMENT, field, value)
241 }
242
243 /**
244 * Do decrement operation
245 * @param {string} field - Operation target field
246 * @param {number} value - Operation value
247 */
248 decrement (field, value) {
249 const s = this
250 s.$do(DECREMENT, field, value)
251 }
252}
253
254module.exports = Apemanstore
255