UNPKG

31.8 kBJavaScriptView Raw
1/**
2 * vuex v4.0.0-alpha.1
3 * (c) 2020 Evan You
4 * @license MIT
5 */
6'use strict';
7
8var vue = require('vue');
9
10var storeKey = 'store';
11
12function useStore (key) {
13 if ( key === void 0 ) key = null;
14
15 return vue.inject(key !== null ? key : storeKey)
16}
17
18function applyMixin (app, store, injectKey) {
19 app.provide(injectKey || storeKey, store);
20
21 // TODO: Refactor this to use `provide/inject`. It's currently
22 // not possible because Vue 3 doesn't work with `$` prefixed
23 // `provide/inject` at the moment.
24 app.mixin({
25 beforeCreate: function beforeCreate () {
26 if (!this.parent) {
27 this.$store = typeof store === 'function' ? store() : store;
28 } else {
29 this.$store = this.parent.$options.$store;
30 }
31 }
32 });
33}
34
35var target = typeof window !== 'undefined'
36 ? window
37 : typeof global !== 'undefined'
38 ? global
39 : {};
40var devtoolHook = target.__VUE_DEVTOOLS_GLOBAL_HOOK__;
41
42function devtoolPlugin (store) {
43 if (!devtoolHook) { return }
44
45 store._devtoolHook = devtoolHook;
46
47 devtoolHook.emit('vuex:init', store);
48
49 devtoolHook.on('vuex:travel-to-state', function (targetState) {
50 store.replaceState(targetState);
51 });
52
53 store.subscribe(function (mutation, state) {
54 devtoolHook.emit('vuex:mutation', mutation, state);
55 });
56}
57
58/**
59 * Get the first item that pass the test
60 * by second argument function
61 *
62 * @param {Array} list
63 * @param {Function} f
64 * @return {*}
65 */
66
67/**
68 * forEach for object
69 */
70function forEachValue (obj, fn) {
71 Object.keys(obj).forEach(function (key) { return fn(obj[key], key); });
72}
73
74function isObject (obj) {
75 return obj !== null && typeof obj === 'object'
76}
77
78function isPromise (val) {
79 return val && typeof val.then === 'function'
80}
81
82function assert (condition, msg) {
83 if (!condition) { throw new Error(("[vuex] " + msg)) }
84}
85
86function partial (fn, arg) {
87 return function () {
88 return fn(arg)
89 }
90}
91
92// Base data struct for store's module, package with some attribute and method
93var Module = function Module (rawModule, runtime) {
94 this.runtime = runtime;
95 // Store some children item
96 this._children = Object.create(null);
97 // Store the origin module object which passed by programmer
98 this._rawModule = rawModule;
99 var rawState = rawModule.state;
100
101 // Store the origin module's state
102 this.state = (typeof rawState === 'function' ? rawState() : rawState) || {};
103};
104
105var prototypeAccessors = { namespaced: { configurable: true } };
106
107prototypeAccessors.namespaced.get = function () {
108 return !!this._rawModule.namespaced
109};
110
111Module.prototype.addChild = function addChild (key, module) {
112 this._children[key] = module;
113};
114
115Module.prototype.removeChild = function removeChild (key) {
116 delete this._children[key];
117};
118
119Module.prototype.getChild = function getChild (key) {
120 return this._children[key]
121};
122
123Module.prototype.update = function update (rawModule) {
124 this._rawModule.namespaced = rawModule.namespaced;
125 if (rawModule.actions) {
126 this._rawModule.actions = rawModule.actions;
127 }
128 if (rawModule.mutations) {
129 this._rawModule.mutations = rawModule.mutations;
130 }
131 if (rawModule.getters) {
132 this._rawModule.getters = rawModule.getters;
133 }
134};
135
136Module.prototype.forEachChild = function forEachChild (fn) {
137 forEachValue(this._children, fn);
138};
139
140Module.prototype.forEachGetter = function forEachGetter (fn) {
141 if (this._rawModule.getters) {
142 forEachValue(this._rawModule.getters, fn);
143 }
144};
145
146Module.prototype.forEachAction = function forEachAction (fn) {
147 if (this._rawModule.actions) {
148 forEachValue(this._rawModule.actions, fn);
149 }
150};
151
152Module.prototype.forEachMutation = function forEachMutation (fn) {
153 if (this._rawModule.mutations) {
154 forEachValue(this._rawModule.mutations, fn);
155 }
156};
157
158Object.defineProperties( Module.prototype, prototypeAccessors );
159
160var ModuleCollection = function ModuleCollection (rawRootModule) {
161 // register root module (Vuex.Store options)
162 this.register([], rawRootModule, false);
163};
164
165ModuleCollection.prototype.get = function get (path) {
166 return path.reduce(function (module, key) {
167 return module.getChild(key)
168 }, this.root)
169};
170
171ModuleCollection.prototype.getNamespace = function getNamespace (path) {
172 var module = this.root;
173 return path.reduce(function (namespace, key) {
174 module = module.getChild(key);
175 return namespace + (module.namespaced ? key + '/' : '')
176 }, '')
177};
178
179ModuleCollection.prototype.update = function update$1 (rawRootModule) {
180 update([], this.root, rawRootModule);
181};
182
183ModuleCollection.prototype.register = function register (path, rawModule, runtime) {
184 var this$1 = this;
185 if ( runtime === void 0 ) runtime = true;
186
187 if (process.env.NODE_ENV !== 'production') {
188 assertRawModule(path, rawModule);
189 }
190
191 var newModule = new Module(rawModule, runtime);
192 if (path.length === 0) {
193 this.root = newModule;
194 } else {
195 var parent = this.get(path.slice(0, -1));
196 parent.addChild(path[path.length - 1], newModule);
197 }
198
199 // register nested modules
200 if (rawModule.modules) {
201 forEachValue(rawModule.modules, function (rawChildModule, key) {
202 this$1.register(path.concat(key), rawChildModule, runtime);
203 });
204 }
205};
206
207ModuleCollection.prototype.unregister = function unregister (path) {
208 var parent = this.get(path.slice(0, -1));
209 var key = path[path.length - 1];
210 if (!parent.getChild(key).runtime) { return }
211
212 parent.removeChild(key);
213};
214
215function update (path, targetModule, newModule) {
216 if (process.env.NODE_ENV !== 'production') {
217 assertRawModule(path, newModule);
218 }
219
220 // update target module
221 targetModule.update(newModule);
222
223 // update nested modules
224 if (newModule.modules) {
225 for (var key in newModule.modules) {
226 if (!targetModule.getChild(key)) {
227 if (process.env.NODE_ENV !== 'production') {
228 console.warn(
229 "[vuex] trying to add a new module '" + key + "' on hot reloading, " +
230 'manual reload is needed'
231 );
232 }
233 return
234 }
235 update(
236 path.concat(key),
237 targetModule.getChild(key),
238 newModule.modules[key]
239 );
240 }
241 }
242}
243
244var functionAssert = {
245 assert: function (value) { return typeof value === 'function'; },
246 expected: 'function'
247};
248
249var objectAssert = {
250 assert: function (value) { return typeof value === 'function' ||
251 (typeof value === 'object' && typeof value.handler === 'function'); },
252 expected: 'function or object with "handler" function'
253};
254
255var assertTypes = {
256 getters: functionAssert,
257 mutations: functionAssert,
258 actions: objectAssert
259};
260
261function assertRawModule (path, rawModule) {
262 Object.keys(assertTypes).forEach(function (key) {
263 if (!rawModule[key]) { return }
264
265 var assertOptions = assertTypes[key];
266
267 forEachValue(rawModule[key], function (value, type) {
268 assert(
269 assertOptions.assert(value),
270 makeAssertionMessage(path, key, type, value, assertOptions.expected)
271 );
272 });
273 });
274}
275
276function makeAssertionMessage (path, key, type, value, expected) {
277 var buf = key + " should be " + expected + " but \"" + key + "." + type + "\"";
278 if (path.length > 0) {
279 buf += " in module \"" + (path.join('.')) + "\"";
280 }
281 buf += " is " + (JSON.stringify(value)) + ".";
282 return buf
283}
284
285// let Vue // bind on install
286
287function createStore (options) {
288 return new Store(options)
289}
290
291var Store = function Store (options) {
292 var this$1 = this;
293 if ( options === void 0 ) options = {};
294
295 // TODO: Bring back this one if needed.
296 //
297 // Auto install if it is not done yet and `window` has `Vue`.
298 // To allow users to avoid auto-installation in some cases,
299 // this code should be placed here. See #731
300 // if (!Vue && typeof window !== 'undefined' && window.Vue) {
301 // install(window.Vue)
302 // }
303
304 if (process.env.NODE_ENV !== 'production') {
305 // TODO: Maybe we can remove this depending on the new implementation.
306 // assert(Vue, `must call Vue.use(Vuex) before creating a store instance.`)
307 assert(typeof Promise !== 'undefined', "vuex requires a Promise polyfill in this browser.");
308 assert(this instanceof Store, "store must be called with the new operator.");
309 }
310
311 var plugins = options.plugins; if ( plugins === void 0 ) plugins = [];
312 var strict = options.strict; if ( strict === void 0 ) strict = false;
313
314 // store internal state
315 this._committing = false;
316 this._actions = Object.create(null);
317 this._actionSubscribers = [];
318 this._mutations = Object.create(null);
319 this._wrappedGetters = Object.create(null);
320 this._modules = new ModuleCollection(options);
321 this._modulesNamespaceMap = Object.create(null);
322 this._subscribers = [];
323 this._makeLocalGettersCache = Object.create(null);
324
325 // bind commit and dispatch to self
326 var store = this;
327 var ref = this;
328 var dispatch = ref.dispatch;
329 var commit = ref.commit;
330 this.dispatch = function boundDispatch (type, payload) {
331 return dispatch.call(store, type, payload)
332 };
333 this.commit = function boundCommit (type, payload, options) {
334 return commit.call(store, type, payload, options)
335 };
336
337 // strict mode
338 this.strict = strict;
339
340 var state = this._modules.root.state;
341
342 // init root module.
343 // this also recursively registers all sub-modules
344 // and collects all module getters inside this._wrappedGetters
345 installModule(this, state, [], this._modules.root);
346
347 // initialize the store vm, which is responsible for the reactivity
348 // (also registers _wrappedGetters as computed properties)
349 resetStoreVM(this, state);
350
351 // apply plugins
352 plugins.forEach(function (plugin) { return plugin(this$1); });
353
354 var useDevtools = options.devtools !== undefined ? options.devtools : /* Vue.config.devtools */ true;
355 if (useDevtools) {
356 devtoolPlugin(this);
357 }
358};
359
360var prototypeAccessors$1 = { state: { configurable: true } };
361
362Store.prototype.install = function install (app, injectKey) {
363 // TODO: Removing double install check for now. Maybe we can bring this
364 // feature back again if needed.
365 //
366 // if (Vue && _Vue === Vue) {
367 // if (process.env.NODE_ENV !== 'production') {
368 // console.error(
369 // '[vuex] already installed. Vue.use(Vuex) should be called only once.'
370 // )
371 // }
372 // return
373 // }
374 // Vue = _Vue
375
376 applyMixin(app, this, injectKey);
377};
378
379prototypeAccessors$1.state.get = function () {
380 return this._vm._data.$$state
381};
382
383prototypeAccessors$1.state.set = function (v) {
384 if (process.env.NODE_ENV !== 'production') {
385 assert(false, "use store.replaceState() to explicit replace store state.");
386 }
387};
388
389Store.prototype.commit = function commit (_type, _payload, _options) {
390 var this$1 = this;
391
392 // check object-style commit
393 var ref = unifyObjectStyle(_type, _payload, _options);
394 var type = ref.type;
395 var payload = ref.payload;
396 var options = ref.options;
397
398 var mutation = { type: type, payload: payload };
399 var entry = this._mutations[type];
400 if (!entry) {
401 if (process.env.NODE_ENV !== 'production') {
402 console.error(("[vuex] unknown mutation type: " + type));
403 }
404 return
405 }
406 this._withCommit(function () {
407 entry.forEach(function commitIterator (handler) {
408 handler(payload);
409 });
410 });
411
412 this._subscribers
413 .slice() // shallow copy to prevent iterator invalidation if subscriber synchronously calls unsubscribe
414 .forEach(function (sub) { return sub(mutation, this$1.state); });
415
416 if (
417 process.env.NODE_ENV !== 'production' &&
418 options && options.silent
419 ) {
420 console.warn(
421 "[vuex] mutation type: " + type + ". Silent option has been removed. " +
422 'Use the filter functionality in the vue-devtools'
423 );
424 }
425};
426
427Store.prototype.dispatch = function dispatch (_type, _payload) {
428 var this$1 = this;
429
430 // check object-style dispatch
431 var ref = unifyObjectStyle(_type, _payload);
432 var type = ref.type;
433 var payload = ref.payload;
434
435 var action = { type: type, payload: payload };
436 var entry = this._actions[type];
437 if (!entry) {
438 if (process.env.NODE_ENV !== 'production') {
439 console.error(("[vuex] unknown action type: " + type));
440 }
441 return
442 }
443
444 try {
445 this._actionSubscribers
446 .slice() // shallow copy to prevent iterator invalidation if subscriber synchronously calls unsubscribe
447 .filter(function (sub) { return sub.before; })
448 .forEach(function (sub) { return sub.before(action, this$1.state); });
449 } catch (e) {
450 if (process.env.NODE_ENV !== 'production') {
451 console.warn("[vuex] error in before action subscribers: ");
452 console.error(e);
453 }
454 }
455
456 var result = entry.length > 1
457 ? Promise.all(entry.map(function (handler) { return handler(payload); }))
458 : entry[0](payload);
459
460 return result.then(function (res) {
461 try {
462 this$1._actionSubscribers
463 .filter(function (sub) { return sub.after; })
464 .forEach(function (sub) { return sub.after(action, this$1.state); });
465 } catch (e) {
466 if (process.env.NODE_ENV !== 'production') {
467 console.warn("[vuex] error in after action subscribers: ");
468 console.error(e);
469 }
470 }
471 return res
472 })
473};
474
475Store.prototype.subscribe = function subscribe (fn) {
476 return genericSubscribe(fn, this._subscribers)
477};
478
479Store.prototype.subscribeAction = function subscribeAction (fn) {
480 var subs = typeof fn === 'function' ? { before: fn } : fn;
481 return genericSubscribe(subs, this._actionSubscribers)
482};
483
484Store.prototype.watch = function watch$1 (getter, cb, options) {
485 var this$1 = this;
486
487 if (process.env.NODE_ENV !== 'production') {
488 assert(typeof getter === 'function', "store.watch only accepts a function.");
489 }
490 return vue.watch(function () { return getter(this$1.state, this$1.getters); }, cb, Object.assign({}, options))
491};
492
493Store.prototype.replaceState = function replaceState (state) {
494 var this$1 = this;
495
496 this._withCommit(function () {
497 this$1._vm._data.$$state = state;
498 });
499};
500
501Store.prototype.registerModule = function registerModule (path, rawModule, options) {
502 if ( options === void 0 ) options = {};
503
504 if (typeof path === 'string') { path = [path]; }
505
506 if (process.env.NODE_ENV !== 'production') {
507 assert(Array.isArray(path), "module path must be a string or an Array.");
508 assert(path.length > 0, 'cannot register the root module by using registerModule.');
509 }
510
511 this._modules.register(path, rawModule);
512 installModule(this, this.state, path, this._modules.get(path), options.preserveState);
513 // reset store to update getters...
514 resetStoreVM(this, this.state);
515};
516
517Store.prototype.unregisterModule = function unregisterModule (path) {
518 var this$1 = this;
519
520 if (typeof path === 'string') { path = [path]; }
521
522 if (process.env.NODE_ENV !== 'production') {
523 assert(Array.isArray(path), "module path must be a string or an Array.");
524 }
525
526 this._modules.unregister(path);
527 this._withCommit(function () {
528 var parentState = getNestedState(this$1.state, path.slice(0, -1));
529 delete parentState[path[path.length - 1]];
530 });
531 resetStore(this);
532};
533
534Store.prototype.hotUpdate = function hotUpdate (newOptions) {
535 this._modules.update(newOptions);
536 resetStore(this, true);
537};
538
539Store.prototype._withCommit = function _withCommit (fn) {
540 var committing = this._committing;
541 this._committing = true;
542 fn();
543 this._committing = committing;
544};
545
546Object.defineProperties( Store.prototype, prototypeAccessors$1 );
547
548function genericSubscribe (fn, subs) {
549 if (subs.indexOf(fn) < 0) {
550 subs.push(fn);
551 }
552 return function () {
553 var i = subs.indexOf(fn);
554 if (i > -1) {
555 subs.splice(i, 1);
556 }
557 }
558}
559
560function resetStore (store, hot) {
561 store._actions = Object.create(null);
562 store._mutations = Object.create(null);
563 store._wrappedGetters = Object.create(null);
564 store._modulesNamespaceMap = Object.create(null);
565 var state = store.state;
566 // init all modules
567 installModule(store, state, [], store._modules.root, true);
568 // reset vm
569 resetStoreVM(store, state, hot);
570}
571
572function resetStoreVM (store, state, hot) {
573 var oldVm = store._vm;
574
575 // bind store public getters
576 store.getters = {};
577 // reset local getters cache
578 store._makeLocalGettersCache = Object.create(null);
579 var wrappedGetters = store._wrappedGetters;
580 var computedObj = {};
581 forEachValue(wrappedGetters, function (fn, key) {
582 // TODO: Refactor following code and comment. We can simplify many things
583 // using computed function.
584 //
585 // use computed to leverage its lazy-caching mechanism
586 // direct inline function use will lead to closure preserving oldVm.
587 // using partial to return function with only arguments preserved in closure environment.
588 computedObj[key] = partial(fn, store);
589 Object.defineProperty(store.getters, key, {
590 get: function () { return vue.computed(function () { return computedObj[key](); }).value; },
591 enumerable: true // for local getters
592 });
593 });
594
595 // TODO: Bring back this if it's still needed.
596 //
597 // use a Vue instance to store the state tree
598 // suppress warnings just in case the user has added
599 // some funky global mixins
600 // const silent = Vue.config.silent
601 // Vue.config.silent = true
602
603 // TODO: Refactor the code and remove this comment.
604 //
605 // New impl with reactive. Defining redundunt keys to make it as close as
606 // the old impl api.
607 store._vm = vue.reactive({
608 _data: {
609 $$state: state
610 }
611 });
612
613 // TODO: Bring back maybe?
614 //
615 // Vue.config.silent = silent
616
617 // enable strict mode for new vm
618 if (store.strict) {
619 enableStrictMode(store);
620 }
621
622 if (oldVm) {
623 if (hot) {
624 // dispatch changes in all subscribed watchers
625 // to force getter re-evaluation for hot reloading.
626 store._withCommit(function () {
627 oldVm._data.$$state = null;
628 });
629 }
630 // TODO: I think we don't need this anymore since we're not using vm?
631 // Vue.nextTick(() => oldVm.$destroy())
632 }
633}
634
635function installModule (store, rootState, path, module, hot) {
636 var isRoot = !path.length;
637 var namespace = store._modules.getNamespace(path);
638
639 // register in namespace map
640 if (module.namespaced) {
641 if (store._modulesNamespaceMap[namespace] && process.env.NODE_ENV !== 'production') {
642 console.error(("[vuex] duplicate namespace " + namespace + " for the namespaced module " + (path.join('/'))));
643 }
644 store._modulesNamespaceMap[namespace] = module;
645 }
646
647 // set state
648 if (!isRoot && !hot) {
649 var parentState = getNestedState(rootState, path.slice(0, -1));
650 var moduleName = path[path.length - 1];
651 store._withCommit(function () {
652 if (process.env.NODE_ENV !== 'production') {
653 if (moduleName in parentState) {
654 console.warn(
655 ("[vuex] state field \"" + moduleName + "\" was overridden by a module with the same name at \"" + (path.join('.')) + "\"")
656 );
657 }
658 }
659 parentState[moduleName] = module.state;
660 });
661 }
662
663 var local = module.context = makeLocalContext(store, namespace, path);
664
665 module.forEachMutation(function (mutation, key) {
666 var namespacedType = namespace + key;
667 registerMutation(store, namespacedType, mutation, local);
668 });
669
670 module.forEachAction(function (action, key) {
671 var type = action.root ? key : namespace + key;
672 var handler = action.handler || action;
673 registerAction(store, type, handler, local);
674 });
675
676 module.forEachGetter(function (getter, key) {
677 var namespacedType = namespace + key;
678 registerGetter(store, namespacedType, getter, local);
679 });
680
681 module.forEachChild(function (child, key) {
682 installModule(store, rootState, path.concat(key), child, hot);
683 });
684}
685
686/**
687 * make localized dispatch, commit, getters and state
688 * if there is no namespace, just use root ones
689 */
690function makeLocalContext (store, namespace, path) {
691 var noNamespace = namespace === '';
692
693 var local = {
694 dispatch: noNamespace ? store.dispatch : function (_type, _payload, _options) {
695 var args = unifyObjectStyle(_type, _payload, _options);
696 var payload = args.payload;
697 var options = args.options;
698 var type = args.type;
699
700 if (!options || !options.root) {
701 type = namespace + type;
702 if (process.env.NODE_ENV !== 'production' && !store._actions[type]) {
703 console.error(("[vuex] unknown local action type: " + (args.type) + ", global type: " + type));
704 return
705 }
706 }
707
708 return store.dispatch(type, payload)
709 },
710
711 commit: noNamespace ? store.commit : function (_type, _payload, _options) {
712 var args = unifyObjectStyle(_type, _payload, _options);
713 var payload = args.payload;
714 var options = args.options;
715 var type = args.type;
716
717 if (!options || !options.root) {
718 type = namespace + type;
719 if (process.env.NODE_ENV !== 'production' && !store._mutations[type]) {
720 console.error(("[vuex] unknown local mutation type: " + (args.type) + ", global type: " + type));
721 return
722 }
723 }
724
725 store.commit(type, payload, options);
726 }
727 };
728
729 // getters and state object must be gotten lazily
730 // because they will be changed by vm update
731 Object.defineProperties(local, {
732 getters: {
733 get: noNamespace
734 ? function () { return store.getters; }
735 : function () { return makeLocalGetters(store, namespace); }
736 },
737 state: {
738 get: function () { return getNestedState(store.state, path); }
739 }
740 });
741
742 return local
743}
744
745function makeLocalGetters (store, namespace) {
746 if (!store._makeLocalGettersCache[namespace]) {
747 var gettersProxy = {};
748 var splitPos = namespace.length;
749 Object.keys(store.getters).forEach(function (type) {
750 // skip if the target getter is not match this namespace
751 if (type.slice(0, splitPos) !== namespace) { return }
752
753 // extract local getter type
754 var localType = type.slice(splitPos);
755
756 // Add a port to the getters proxy.
757 // Define as getter property because
758 // we do not want to evaluate the getters in this time.
759 Object.defineProperty(gettersProxy, localType, {
760 get: function () { return store.getters[type]; },
761 enumerable: true
762 });
763 });
764 store._makeLocalGettersCache[namespace] = gettersProxy;
765 }
766
767 return store._makeLocalGettersCache[namespace]
768}
769
770function registerMutation (store, type, handler, local) {
771 var entry = store._mutations[type] || (store._mutations[type] = []);
772 entry.push(function wrappedMutationHandler (payload) {
773 handler.call(store, local.state, payload);
774 });
775}
776
777function registerAction (store, type, handler, local) {
778 var entry = store._actions[type] || (store._actions[type] = []);
779 entry.push(function wrappedActionHandler (payload) {
780 var res = handler.call(store, {
781 dispatch: local.dispatch,
782 commit: local.commit,
783 getters: local.getters,
784 state: local.state,
785 rootGetters: store.getters,
786 rootState: store.state
787 }, payload);
788 if (!isPromise(res)) {
789 res = Promise.resolve(res);
790 }
791 if (store._devtoolHook) {
792 return res.catch(function (err) {
793 store._devtoolHook.emit('vuex:error', err);
794 throw err
795 })
796 } else {
797 return res
798 }
799 });
800}
801
802function registerGetter (store, type, rawGetter, local) {
803 if (store._wrappedGetters[type]) {
804 if (process.env.NODE_ENV !== 'production') {
805 console.error(("[vuex] duplicate getter key: " + type));
806 }
807 return
808 }
809 store._wrappedGetters[type] = function wrappedGetter (store) {
810 return rawGetter(
811 local.state, // local state
812 local.getters, // local getters
813 store.state, // root state
814 store.getters // root getters
815 )
816 };
817}
818
819function enableStrictMode (store) {
820 vue.watch(function () { return store._vm._data.$$state; }, function () {
821 if (process.env.NODE_ENV !== 'production') {
822 assert(store._committing, "do not mutate vuex store state outside mutation handlers.");
823 }
824 }, { deep: true, flush: 'sync' });
825}
826
827function getNestedState (state, path) {
828 return path.reduce(function (state, key) { return state[key]; }, state)
829}
830
831function unifyObjectStyle (type, payload, options) {
832 if (isObject(type) && type.type) {
833 options = payload;
834 payload = type;
835 type = type.type;
836 }
837
838 if (process.env.NODE_ENV !== 'production') {
839 assert(typeof type === 'string', ("expects string as the type, but found " + (typeof type) + "."));
840 }
841
842 return { type: type, payload: payload, options: options }
843}
844
845/**
846 * Reduce the code which written in Vue.js for getting the state.
847 * @param {String} [namespace] - Module's namespace
848 * @param {Object|Array} states # Object's item can be a function which accept state and getters for param, you can do something for state and getters in it.
849 * @param {Object}
850 */
851var mapState = normalizeNamespace(function (namespace, states) {
852 var res = {};
853 if (process.env.NODE_ENV !== 'production' && !isValidMap(states)) {
854 console.error('[vuex] mapState: mapper parameter must be either an Array or an Object');
855 }
856 normalizeMap(states).forEach(function (ref) {
857 var key = ref.key;
858 var val = ref.val;
859
860 res[key] = function mappedState () {
861 var state = this.$store.state;
862 var getters = this.$store.getters;
863 if (namespace) {
864 var module = getModuleByNamespace(this.$store, 'mapState', namespace);
865 if (!module) {
866 return
867 }
868 state = module.context.state;
869 getters = module.context.getters;
870 }
871 return typeof val === 'function'
872 ? val.call(this, state, getters)
873 : state[val]
874 };
875 // mark vuex getter for devtools
876 res[key].vuex = true;
877 });
878 return res
879});
880
881/**
882 * Reduce the code which written in Vue.js for committing the mutation
883 * @param {String} [namespace] - Module's namespace
884 * @param {Object|Array} mutations # Object's item can be a function which accept `commit` function as the first param, it can accept anthor params. You can commit mutation and do any other things in this function. specially, You need to pass anthor params from the mapped function.
885 * @return {Object}
886 */
887var mapMutations = normalizeNamespace(function (namespace, mutations) {
888 var res = {};
889 if (process.env.NODE_ENV !== 'production' && !isValidMap(mutations)) {
890 console.error('[vuex] mapMutations: mapper parameter must be either an Array or an Object');
891 }
892 normalizeMap(mutations).forEach(function (ref) {
893 var key = ref.key;
894 var val = ref.val;
895
896 res[key] = function mappedMutation () {
897 var args = [], len = arguments.length;
898 while ( len-- ) args[ len ] = arguments[ len ];
899
900 // Get the commit method from store
901 var commit = this.$store.commit;
902 if (namespace) {
903 var module = getModuleByNamespace(this.$store, 'mapMutations', namespace);
904 if (!module) {
905 return
906 }
907 commit = module.context.commit;
908 }
909 return typeof val === 'function'
910 ? val.apply(this, [commit].concat(args))
911 : commit.apply(this.$store, [val].concat(args))
912 };
913 });
914 return res
915});
916
917/**
918 * Reduce the code which written in Vue.js for getting the getters
919 * @param {String} [namespace] - Module's namespace
920 * @param {Object|Array} getters
921 * @return {Object}
922 */
923var mapGetters = normalizeNamespace(function (namespace, getters) {
924 var res = {};
925 if (process.env.NODE_ENV !== 'production' && !isValidMap(getters)) {
926 console.error('[vuex] mapGetters: mapper parameter must be either an Array or an Object');
927 }
928 normalizeMap(getters).forEach(function (ref) {
929 var key = ref.key;
930 var val = ref.val;
931
932 // The namespace has been mutated by normalizeNamespace
933 val = namespace + val;
934 res[key] = function mappedGetter () {
935 if (namespace && !getModuleByNamespace(this.$store, 'mapGetters', namespace)) {
936 return
937 }
938 if (process.env.NODE_ENV !== 'production' && !(val in this.$store.getters)) {
939 console.error(("[vuex] unknown getter: " + val));
940 return
941 }
942 return this.$store.getters[val]
943 };
944 // mark vuex getter for devtools
945 res[key].vuex = true;
946 });
947 return res
948});
949
950/**
951 * Reduce the code which written in Vue.js for dispatch the action
952 * @param {String} [namespace] - Module's namespace
953 * @param {Object|Array} actions # Object's item can be a function which accept `dispatch` function as the first param, it can accept anthor params. You can dispatch action and do any other things in this function. specially, You need to pass anthor params from the mapped function.
954 * @return {Object}
955 */
956var mapActions = normalizeNamespace(function (namespace, actions) {
957 var res = {};
958 if (process.env.NODE_ENV !== 'production' && !isValidMap(actions)) {
959 console.error('[vuex] mapActions: mapper parameter must be either an Array or an Object');
960 }
961 normalizeMap(actions).forEach(function (ref) {
962 var key = ref.key;
963 var val = ref.val;
964
965 res[key] = function mappedAction () {
966 var args = [], len = arguments.length;
967 while ( len-- ) args[ len ] = arguments[ len ];
968
969 // get dispatch function from store
970 var dispatch = this.$store.dispatch;
971 if (namespace) {
972 var module = getModuleByNamespace(this.$store, 'mapActions', namespace);
973 if (!module) {
974 return
975 }
976 dispatch = module.context.dispatch;
977 }
978 return typeof val === 'function'
979 ? val.apply(this, [dispatch].concat(args))
980 : dispatch.apply(this.$store, [val].concat(args))
981 };
982 });
983 return res
984});
985
986/**
987 * Rebinding namespace param for mapXXX function in special scoped, and return them by simple object
988 * @param {String} namespace
989 * @return {Object}
990 */
991var createNamespacedHelpers = function (namespace) { return ({
992 mapState: mapState.bind(null, namespace),
993 mapGetters: mapGetters.bind(null, namespace),
994 mapMutations: mapMutations.bind(null, namespace),
995 mapActions: mapActions.bind(null, namespace)
996}); };
997
998/**
999 * Normalize the map
1000 * normalizeMap([1, 2, 3]) => [ { key: 1, val: 1 }, { key: 2, val: 2 }, { key: 3, val: 3 } ]
1001 * normalizeMap({a: 1, b: 2, c: 3}) => [ { key: 'a', val: 1 }, { key: 'b', val: 2 }, { key: 'c', val: 3 } ]
1002 * @param {Array|Object} map
1003 * @return {Object}
1004 */
1005function normalizeMap (map) {
1006 if (!isValidMap(map)) {
1007 return []
1008 }
1009 return Array.isArray(map)
1010 ? map.map(function (key) { return ({ key: key, val: key }); })
1011 : Object.keys(map).map(function (key) { return ({ key: key, val: map[key] }); })
1012}
1013
1014/**
1015 * Validate whether given map is valid or not
1016 * @param {*} map
1017 * @return {Boolean}
1018 */
1019function isValidMap (map) {
1020 return Array.isArray(map) || isObject(map)
1021}
1022
1023/**
1024 * Return a function expect two param contains namespace and map. it will normalize the namespace and then the param's function will handle the new namespace and the map.
1025 * @param {Function} fn
1026 * @return {Function}
1027 */
1028function normalizeNamespace (fn) {
1029 return function (namespace, map) {
1030 if (typeof namespace !== 'string') {
1031 map = namespace;
1032 namespace = '';
1033 } else if (namespace.charAt(namespace.length - 1) !== '/') {
1034 namespace += '/';
1035 }
1036 return fn(namespace, map)
1037 }
1038}
1039
1040/**
1041 * Search a special module from store by namespace. if module not exist, print error message.
1042 * @param {Object} store
1043 * @param {String} helper
1044 * @param {String} namespace
1045 * @return {Object}
1046 */
1047function getModuleByNamespace (store, helper, namespace) {
1048 var module = store._modulesNamespaceMap[namespace];
1049 if (process.env.NODE_ENV !== 'production' && !module) {
1050 console.error(("[vuex] module namespace not found in " + helper + "(): " + namespace));
1051 }
1052 return module
1053}
1054
1055var index = {
1056 version: '4.0.0-alpha.1',
1057 createStore: createStore,
1058 Store: Store,
1059 useStore: useStore,
1060 mapState: mapState,
1061 mapMutations: mapMutations,
1062 mapGetters: mapGetters,
1063 mapActions: mapActions,
1064 createNamespacedHelpers: createNamespacedHelpers
1065};
1066
1067module.exports = index;