import Module from './module' import { assert, forEachValue } from '../util' export default class ModuleCollection { constructor (rawRootModule) { // register root module (Vuex.Store options) this.register([], rawRootModule, false) } get (path) { return path.reduce((module, key) => { return module.getChild(key) }, this.root) } getNamespace (path) { let module = this.root return path.reduce((namespace, key) => { module = module.getChild(key) return namespace + (module.namespaced ? key + '/' : '') }, '') } update (rawRootModule) { update([], this.root, rawRootModule) } register (path, rawModule, runtime = true) { if (process.env.NODE_ENV !== 'production') { assertRawModule(path, rawModule) } const newModule = new Module(rawModule, runtime) if (path.length === 0) { this.root = newModule } else { const parent = this.get(path.slice(0, -1)) parent.addChild(path[path.length - 1], newModule) } // register nested modules if (rawModule.modules) { forEachValue(rawModule.modules, (rawChildModule, key) => { this.register(path.concat(key), rawChildModule, runtime) }) } } unregister (path) { const parent = this.get(path.slice(0, -1)) const key = path[path.length - 1] if (!parent.getChild(key).runtime) return parent.removeChild(key) } } function update (path, targetModule, newModule) { if (process.env.NODE_ENV !== 'production') { assertRawModule(path, newModule) } // update target module targetModule.update(newModule) // update nested modules if (newModule.modules) { for (const key in newModule.modules) { if (!targetModule.getChild(key)) { if (process.env.NODE_ENV !== 'production') { console.warn( `[vuex] trying to add a new module '${key}' on hot reloading, ` + 'manual reload is needed' ) } return } update( path.concat(key), targetModule.getChild(key), newModule.modules[key] ) } } } function assertRawModule (path, rawModule) { ['getters', 'actions', 'mutations'].forEach(key => { if (!rawModule[key]) return forEachValue(rawModule[key], (value, type) => { assert( typeof value === 'function', makeAssertionMessage(path, key, type, value) ) }) }) } function makeAssertionMessage (path, key, type, value) { let buf = `${key} should be function but "${key}.${type}"` if (path.length > 0) { buf += ` in module "${path.join('.')}"` } buf += ` is ${JSON.stringify(value)}.` return buf }