import { useStore, Store } from 'vuex' interface InternalModule { state: S actions: A mutations: M getters: G } /** * This function allows us to access the internal vuex properties and * maps them in a way which removes the module prefix. */ function getFromStoreByType( moduleName: string, type: unknown, isNamespaced: boolean, ) { if (isNamespaced) { return Object.keys(type) .filter(t => t.startsWith(`${moduleName}/`)) .reduce((acc, curr) => { const typeName = curr.split('/').pop() const typeValue = type[curr][0] return { [typeName]: typeValue, ...acc } }, {}) as T } return Object.keys(type).reduce((acc, curr) => { const typeValue = type[curr][0] return { [curr]: typeValue, ...acc } }, {}) as T } /* * We have to wrap the getters in a Proxy because we only want to * "access" the getter if it actually being accessed. * * We could technically use the getFromStoreByType function but * the getter would be invoked multiple types on store instantiation. * * This is just a little cheeky workaround. Proxy <3 */ function wrapGettersInProxy( moduleName: string, getters: G, isNamespaced: boolean, ) { return new Proxy(getters as Object, { get(_, prop: string) { if (isNamespaced) return getters[`${moduleName}/${prop}`] return getters[prop] }, }) as G } function isModuleNamespaced(moduleName: string, store: Store): boolean { // @ts-ignore internal Vuex object that isn't typed. return Boolean(store._modulesNamespaceMap[`${moduleName}/`]) } export default function useStoreModule( moduleName: string, storeName?: string, ): InternalModule { // @ts-ignore useStore doesn't yet accept a key as arg const store = storeName ? useStore(storeName) : useStore() const state = store.state[moduleName] const isNamespaced = isModuleNamespaced(moduleName, store) const actions = getFromStoreByType( moduleName, // @ts-ignore internal Vuex object that isn't typed. store._actions, isNamespaced, ) const mutations = getFromStoreByType( moduleName, // @ts-ignore internal Vuex object that isn't typed. store._mutations, isNamespaced, ) const getters = wrapGettersInProxy(moduleName, store.getters, isNamespaced) return { actions, mutations, state, getters, } }