import { Store , CommitOptions , DispatchOptions } from 'vuex' ; import { Payload , Mutations as BaseMutations , Actions as BaseActions , Dispatcher , Committer , } from './assets' ; import { get , gatherHandlerNames , assert } from './utils' ; import { Module , ModuleOptions } from './module' ; export interface Commit < M > { < K extends keyof M > ( type , payload , options ? ) : void ; < K extends keyof M > ( payload , options ? ) : void ; < K extends { [ K in keyof M ] : M [ K ] extends ( ) => any ? K : never ; } [ keyof M ] > ( type ) : void ; } export interface Dispatch < A > { < K extends keyof A > ( type , payload , options ? ) : Promise < unknown > ; < K extends keyof A > ( payload , options ? ) : Promise < unknown > ; < K extends { [ K in keyof A ] : A [ K ] extends ( ) => any ? K : never ; } [ keyof A ] > ( type ) : Promise < unknown > ; } type State < Mod extends Module < any , any , any , any , any > > = Mod extends Module < infer R , any , any , any , any > ? R : never ; type Getters < Mod extends Module < any , any , any , any , any > > = Mod extends Module < any , infer R , any , any , any > ? R : never ; type Mutations < Mod extends Module < any , any , any , any , any > > = Mod extends Module < any , any , infer R , any , any > ? R : never ; type Actions < Mod extends Module < any , any , any , any , any > > = Mod extends Module < any , any , any , infer R , any > ? R : never ; type ModulesContexts < Mod extends Module < any , any , any , any , any > > = Mod extends Module < any , any , any , any , infer R > ? { [ K in keyof R ] : Context < R [ K ] > ; } : never ; export interface ContextPosition { path : string [ ] ; namespace : string ; } export function createLazyContextPosition ( module ) { const message = 'The module need to be registered a store before using `Module#context` or `createMapper`' ; return { get path ( ) { assert ( module . path !== undefined , message ) ; return module . path ! ; } , get namespace ( ) { assert ( module . namespace !== undefined , message ) ; return module . namespace ! ; } , } ; } function normalizedDispatch ( dispatch , namespace , type , payload , options ? ) { if ( typeof type === 'string' ) { return dispatch ( namespace + type , payload , options ) ; } else { return dispatch ( { ... type , type : namespace + type . type , } , payload ) ; } } export function commit ( store , namespace , type , payload , options ? ) { normalizedDispatch ( store . commit , namespace , type , payload , options ) ; } export function dispatch ( store , namespace , type , payload , options ? ) { return normalizedDispatch ( store . dispatch , namespace , type , payload , options ) ; } export function getters ( store , namespace ) { const sliceIndex = namespace . length ; const getters = { } ; Object . keys ( store . getters ) . forEach ( ( key ) => { const sameNamespace = namespace === key . slice ( 0 , sliceIndex ) ; const name = key . slice ( sliceIndex ) ; if ( ! sameNamespace || ! name ) { return ; } Object . defineProperty ( getters , name , { get : ( ) => store . getters [ key ] , enumerable : true , } ) ; } ) ; return getters ; } export class Context < Mod extends Module < any , any , any , any , any > > { private __mutations__ ? : Committer < Mutations < Mod > > ; private __actions__ ? : Dispatcher < Actions < Mod > > ; internal constructor ( private pos , private store , private moduleOptions ) { } get mutations ( ) : Committer < Mutations < Mod > > { if ( this . __mutations__ ) { return this . __mutations__ ; } const mutations = { } ; const mutationsClass = this . moduleOptions . mutations ; if ( mutationsClass ) { const mutationNames = gatherHandlerNames ( mutationsClass . prototype , BaseMutations ) ; mutationNames . forEach ( ( name ) => { Object . defineProperty ( mutations , name , { value : ( payload ) => this . commit ( name , payload ) , enumerable : true , } ) ; } ) ; } return ( this . __mutations__ = mutations as any ) ; } get actions ( ) : Dispatcher < Actions < Mod > > { if ( this . __actions__ ) { return this . __actions__ ; } const actions = { } ; const actionsClass = this . moduleOptions . actions ; if ( actionsClass ) { const actionNames = gatherHandlerNames ( actionsClass . prototype , BaseActions ) ; actionNames . forEach ( ( name ) => { Object . defineProperty ( actions , name , { value : ( payload ) => this . dispatch ( name , payload ) , enumerable : true , } ) ; } ) ; } return ( this . __actions__ = actions as any ) ; } commit : Commit < Mutations < Mod > > = ( type , payload ? , options ? ) : void => { return commit ( this . store , this . pos . namespace , type , payload , options ) ; } ; dispatch : Dispatch < Actions < Mod > > = ( type , payload ? , options ? ) : any => { return dispatch ( this . store , this . pos . namespace , type , payload , options ) ; } ; get state ( ) : State < Mod > { return get ( this . pos . path , this . store . state ) ; } get getters ( ) : Getters < Mod > { return getters ( this . store , this . pos . namespace ) ; } get modules ( ) : ModulesContexts < Mod > { const modules = { } as ModulesContexts < Mod > ; const children = this . moduleOptions . modules ; if ( ! children ) { return modules ; } Object . keys ( children ) . forEach ( ( key ) => { const child = children [ key ] ; Object . defineProperty ( modules , key , { get : ( ) => { return new Context ( createLazyContextPosition ( child ) , this . store , child . options ) ; } , } ) ; } ) ; return modules ; } }