import getDescriptors from "object.getownpropertydescriptors" ; import { VuexModuleOptions , VuexModuleConstructor , DictionaryField , VuexModule , VuexObject , Map } from "./interfaces" ; import { isFieldASubModule , extractVuexSubModule } from "./submodule" ; import { createLocalProxy } from './proxy' ; import { toCamelCase } from "./utils" ; import { internalAction } from "./actions" ; import { internalMutator } from "./mutations" ; import { internalGetter } from "./getters" ; export function createModule ( options ? ) { /**
     * We do it like this because we don't want intelissense to pick up the
     * options variable as it is an internal variable.
     */ const vuexModule = function ( ) { } as VuexModuleConstructor ; vuexModule . prototype . __options__ = options ; vuexModule . With = defineWithExtension ; return vuexModule as typeof VuexModule ; } function defineWithExtension ( this , options ? ) { const oldOptions = this . prototype . __options__ = { } ; const newVuexModule = function ( ) { } as VuexModuleConstructor ; newVuexModule . prototype . __options__ = { } ; Object . assign ( newVuexModule . prototype . __options__ , oldOptions ) ; if ( options === undefined ) return newVuexModule as typeof VuexModule ; const prototypeOptions = newVuexModule . prototype . __options__ || { } ; if ( options . namespaced ) prototypeOptions . namespaced = options . namespaced ; if ( options . strict ) prototypeOptions . strict = options . strict ; if ( options . target ) prototypeOptions . target = options . target ; if ( options . enableLocalWatchers ) prototypeOptions . enableLocalWatchers = options . enableLocalWatchers ; return newVuexModule as typeof VuexModule ; } function initializeModuleInternals ( cls ) { cls . prototype . __namespacedPath__ = "" ; cls . prototype . __vuex_module_cache__ = undefined ; cls . prototype . __vuex_proxy_cache__ = undefined ; cls . prototype . __vuex_local_proxy_cache__ = undefined ; cls . prototype . __submodules_cache__ = { } ; cls . prototype . __context_store__ = { } ; cls . prototype . __watch__ = { } ; cls . prototype . __explicit_getter_names__ = [ ] ; } export function extractVuexModule ( cls ) { const VuexClass = cls as VuexModuleConstructor ; if ( VuexClass . prototype . __vuex_module_cache__ ) { return VuexClass . prototype . __vuex_module_cache__ ; } initializeModuleInternals ( VuexClass ) ; const fromInstance = extractModulesFromInstance ( VuexClass ) ; const fromPrototype = extractModulesFromPrototype ( VuexClass ) ; VuexClass . prototype . __mutations_cache__ = { __explicit_mutations__ : fromPrototype . mutations . explicitMutations , __setter_mutations__ : fromPrototype . mutations . setterMutations , } ; const className = VuexClass . name . toLowerCase ( ) ; const vuexModule = { namespaced : VuexClass . prototype . __options__ && VuexClass . prototype . __options__ . namespaced ? true : false , state : fromInstance . state , mutations : { ... fromPrototype . mutations . explicitMutations , ... fromPrototype . mutations . setterMutations , [ `__${ className }_internal_mutator__` ] : internalMutator } , getters : { ... fromPrototype . getters , ... fromInstance . getters , [ `__${ className }_internal_getter__` ] : internalGetter } , actions : { ... fromPrototype . actions , [ `__${ className }_internal_action__` ] : internalAction } , modules : fromInstance . submodules , } ; const path = getNamespacedPath ( VuexClass ) || toCamelCase ( VuexClass . name ) ; const rtn = { [ path ] : vuexModule } ; VuexClass . prototype . __vuex_module_cache__ = rtn ; return rtn ; } export function getNamespacedPath ( cls ) { const namespaced = cls . prototype . __options__ && cls . prototype . __options__ . namespaced ; if ( namespaced ) { const namePaths = namespaced . split ( "/" ) ; cls . prototype . __namespacedPath__ = namePaths [ namePaths . length - 1 ] || namePaths [ namePaths . length - 2 ] ; } return cls . prototype . __namespacedPath__ ; } function extractModulesFromInstance ( cls ) { const instance = new cls ( ) as InstanceType < VuexModuleConstructor > & Map ; const classFields = Object . getOwnPropertyNames ( instance ) ; const state = { } ; const mutations = { } ; const submodules = { } ; const submodulesCache = cls . prototype . __submodules_cache__ ; const moduleOptions = cls . prototype . __options__ || { } ; for ( let field of classFields ) { const fieldIsSubModule = isFieldASubModule ( instance , field ) ; if ( fieldIsSubModule ) { submodulesCache [ field ] = instance [ field ] [ "__submodule_class__" ] ; const submodule = extractVuexSubModule ( instance , field ) ; submodules [ field ] = submodule ; continue ; } state [ field ] = instance [ field ] ; } return { submodules , mutations , getters : extractDecoratorGetterNames ( cls . prototype . __decorator_getter_names__ ) , state : moduleOptions . target === "nuxt" ? ( ) => state : state , } ; } function extractModulesFromPrototype ( cls ) { const setterMutations = { } ; const explicitMutations = { } ; const actions = { } ; const getters = { } ; const descriptors = getDescriptors ( cls . prototype ) ; const gettersList = Object . keys ( descriptors ) . filter ( field => descriptors [ field ] . get ) ; const explicitMutationNames = cls . prototype . __explicit_mutations_names__ || [ ] ; const actionNames = cls . prototype . __actions__ || [ ] ; for ( let field in descriptors ) { const fieldIsInternal = ( field === "constructor" || field === "__options__" || field === "__vuex_module_cache__" || field === "__vuex_proxy_cache__" || field === "__mutations_cache__" || field === "__explicit_mutations__" || field === "__getter_mutations__" ) ; if ( fieldIsInternal ) continue ; const descriptor = descriptors [ field ] ; const actionType = ( typeof descriptor . value === "function" ) && actionNames . find ( action => action . __name__ === field ) ; if ( actionType && actionType . __type__ === "mutate" ) { const func = descriptor . value as Function ; const action = function ( context , payload ) { cls . prototype . __context_store__ = context ; const proxy = createLocalProxy ( cls , context ) ; if ( proxy [ "$store" ] === undefined ) { Object . defineProperty ( proxy , "$store" , { value : this } ) ; } return func . call ( proxy , payload ) ; } ; actions [ field ] = action ; continue ; } if ( actionType && actionType . __type__ === "raw" ) { const func = descriptor . value as Function ; const action = ( context , payload ) => func . call ( context , payload ) ; actions [ field ] = action ; continue ; } const fieldIsExplicitMutation = ( typeof descriptor . value === "function" && explicitMutationNames . indexOf ( field ) > - 1 ) ; if ( fieldIsExplicitMutation ) { const mutation = ( state , payload ) => descriptor . value . call ( state , payload ) ; explicitMutations [ field ] = mutation ; continue ; } if ( descriptor . get ) { const getter = ( state , context ) => { const proxy = createLocalProxy ( cls , context ) ; return descriptor . get ! . call ( proxy ) ; } ; getters [ field ] = getter ; } if ( descriptor . set ) { const mutation = ( state , payload ) => descriptor . set ! . call ( state , payload ) ; const mutationHasGetter = gettersList . indexOf ( field ) > - 1 ; if ( mutationHasGetter === false ) { throw new Error ( `\nImproper Use of Setter Mutations:\n` + `at >>\n` + `set ${ field }( payload ) {\n` + `\t...\n` + `}\n` + `\n` + `Setter mutations should only be used if there is a corresponding getter defined.\n` + `\n` + `Either define a corresponding getter for this setter mutation or,\n` + `Define them as an explicit mutation using function assignment.\n` + `Example:\n` + `--------------------\n` + `${ field } = ( payload ) => {\n` + ` ...\n` + `}` ) ; } setterMutations [ field ] = mutation ; } cls . prototype . __explicit_getter_names__ = gettersList ; } return { actions , mutations : { explicitMutations , setterMutations , } , getters } ; } function extractDecoratorGetterNames ( names = [ ] ) { const decorator = { } ; for ( let name of names ) { decorator [ name ] = new Function ( "state" , `return state.${ name }` ) ; } return decorator ; }