michaelolof / vuex-class-component

A Type Safe Vuex Module or Store Using ES6 Classes and ES7 Decorators written in TypeScript.
217 stars 21 forks source link

Feature request: create proxy inside of VuexModule #21

Open cmeyertons opened 5 years ago

cmeyertons commented 5 years ago

Wow this library is fantastic -- makes working with vuex modules much more intuitive and easy to use w/ type safety and intellisense!

The first module I implemented had to call out to another module that houses same shared logic, so I implemented using the raw action context, which worked but I lost all the type safety

import { VuexModule, Module, getter, action, getRawActionContext, mutation } from 'vuex-class-component';
import RootState from '../../types/RootState'
import Product from '../../types/product/Product';
import bodybuilder from 'bodybuilder';

export interface SubscriptionState {
  subscriptions: Product[] | [],
}

@Module({ namespacedPath: 'subscriptions/' })
export class SubscriptionStore extends VuexModule {
  @getter items: Product[] = []

  @mutation
  loadItems (items: Product[]) {
    this.items = items
  }

  @action({ mode: 'raw'})
  load (): Promise<void> {
    const context = getRawActionContext(this)
    const query = bodybuilder()
      .query('match', 'category.name', 'Subscriptions')
      .build()

    return context.dispatch('product/list', { query, start: 0, size: 10, updateState: false }, { root: true }).then(resp => {
      const subscriptions = (resp.items as Product[]).sort((p1, p2) => +p1.order - (+p2.order))
      context.commit('loadItems', subscriptions)
    }).catch((err) => {
      console.error(err)
    })
  }
}

Would it be possible to create a proxy that takes a VuexModule as a constructor? So inside my subscription vuex module it would look like:

product = ProductStore.CreateProxy(ProductStore, this)

Could that proxy method leverage the raw context to generate the necessary proxy? And then you have all the type safety you need when dispatching an action to another module

asmadsen commented 5 years ago

@cmeyertons With #23 you can create a proxy from inside your actions, like so:

@Module({ namespacedPath: 'subscriptions/' })
export class SubscriptionStore extends VuexModule {
  @getter items: Product[] = []

  @mutation
  loadItems (items: Product[]) {
    this.items = items
  }

  @action
  load (): Promise<void> {
    const productStore = ProductStore.CreateProxy(this.$store, ProductStore)
    const query = bodybuilder()
      .query('match', 'category.name', 'Subscriptions')
      .build()
    return productStore.list({query, start: 0, size: 10, updateState: false }}
        .then(resp => {
      const subscriptions = (resp.items as Product[]).sort((p1, p2) => +p1.order - (+p2.order))
      this.loadItems(subscriptions)
    }).catch((err) => {
      console.error(err)
    })
  }
}
cmeyertons commented 5 years ago

awesome! do you happen to know what version this will be released in?

asmadsen commented 5 years ago

I'm pretty sure it's already in the latest version