import type { ActionContext, Getter } from 'vuex'; import type { ModuleBuilder, Mutation, ActionHandler, ActionType, } from './types'; import Vue from 'vue'; const actionCreator =

( moduleName: () => string | undefined, type: string, ) => (payload: P) => ({ type: moduleName() ? `${moduleName()}/${type}` : type, payload, }); function overrideActionContext( action: ActionHandler, ) { return ( store: ActionContext, { payload }: ReturnType>, ) => action( { ...store, commit: (type) => store.commit(type, { root: true }), dispatch: (type) => store.dispatch(type, { root: true }), }, payload, ); } /** * Create a {@see ModuleBuilder} instance. * * ```ts * interface RootState { * module_one: { * list: string[] * } * } * const module = createModule({ list: [] }); * * @param initialState - initial module state * @typeParam State - Type of module state, usually an key in RootState. * @typeParam RootState - Type of root store state */ export function createModule( initialState: State, ): ModuleBuilder { const mutations: Mutation[] = []; const actions: ActionHandler[] = []; const getters: Getter[] = []; let moduleName: string; const getModuleName = () => moduleName; return >{ mutation(type: string, fn?: Mutation) { if (!fn) { return this.mutation(`${type}`, (state, value) => { Vue.set(state as any, `${type}`, value); }); } fn.toString = () => `${type}`; (mutations as Mutation[]).push(fn); return actionCreator(getModuleName, type); }, action( type: string, fn: ActionHandler, ) { fn.toString = () => `${type}`; (actions as ActionHandler[]).push(fn); return actionCreator(getModuleName, type); }, getter(type: string, fn: Getter) { fn.toString = () => `${type}`; getters.push(fn); return (getter: any): Payload => getter[`${moduleName}/${type}`] || getter[type]; }, getModule(name = '') { moduleName = name; return { name: moduleName, namespaced: true, state: initialState, actions: actions.reduce((acc, action) => { acc[action.toString()] = overrideActionContext(action); return acc; }, {}), mutations: mutations.reduce((acc, mutation) => { acc[mutation.toString()] = (store, { payload }) => mutation(store, payload); return acc; }, {}), getters: getters.reduce((acc, getter) => { acc[getter.toString()] = getter; return acc; }, {}), }; }, }; }