[
  {
    "path": ".gitignore",
    "content": "node_modules\n/lib\n/commonjs\n/example/build.js\n/example/build.js.map\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  \"editor.rulers\": [ 120 ],\n  \"prettier.printWidth\": 120,\n  \"prettier.disableLanguages\": [],\n\n  \"[typescript]\": {\n    \"editor.formatOnSave\": true\n  },\n  \"[vue]\": {\n    \"editor.formatOnSave\": true\n  },\n  \"tslint.autoFixOnSave\": true,\n\n  \"vetur.format.defaultFormatter.html\": \"none\",\n  \"vetur.format.defaultFormatter.ts\": \"none\"\n}"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 gertqin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# vuex-class-modules\n\nThis is yet another package to introduce a simple type-safe class style syntax for your vuex modules, inspired by [vue-class-component](https://github.com/vuejs/vue-class-component).\n\n[![npm](https://img.shields.io/npm/v/vuex-class-modules.svg)](https://www.npmjs.com/package/vuex-class-modules)\n\n## Installation\n\n`npm install vuex-class-modules`\n\nAnd make sure to have the `--experimentalDecorators` flag enabled.\n\nBoth a `commonjs` and a `esm` module build are published. If you have a webpack-based setup, it will use the `esm` modules by default.\n\n## Usage\n\nVuex modules can be written using decorators as a class:\n\n```typescript\n// user-module.ts\nimport { VuexModule, Module, Mutation, Action } from \"vuex-class-modules\";\n\n@Module\nclass UserModule extends VuexModule {\n  // state\n  firstName = \"Foo\";\n  lastName = \"Bar\";\n\n  // getters\n  get fullName() {\n    return this.firstName + \" \" + this.lastName;\n  }\n\n  // mutations\n  @Mutation\n  setFirstName(firstName: string) {\n    this.firstName = firstName;\n  }\n  @Mutation\n  setLastName(lastName: string) {\n    this.lastName = lastName;\n  }\n\n  // actions\n  @Action\n  async loadUser() {\n    const user = await fetchUser();\n    this.setFirstName(user.firstName);\n    this.setLastName(user.lastName);\n  }\n}\n\n// register module (could be in any file)\nimport store from \"path/to/store\";\nexport const userModule = new UserModule({ store, name: \"user\" });\n```\n\nThe module will automatically be registered to the store as a namespaced dynamic module when it is instantiated. (The modules are namespaced to avoid name conflicts between modules for getters/mutations/actions.)\n\nThe module can then be used in vue components as follows:\n\n```ts\n// MyComponent.vue\nimport Vue from \"vue\";\nimport { userModule } from \"path/to/user-module.ts\";\n\nexport class MyComponent extends Vue {\n  get firstName() {\n    return userModule.firstName; // -> store.state.user.firstName\n  }\n  get fullName() {\n    return userModule.fullName; // -> store.getters[\"user/fullName]\n  }\n\n  created() {\n    userModule.setFirstName(\"Foo\"); // -> store.commit(\"user/setFirstName\", \"Foo\")\n    userModule.loadUser(); // -> store.dispatch(\"user/loadUser\")\n  }\n}\n```\n\n### What about `rootState` and `rootGetters`?\n\nThere are two ways to access other modules within a module, or dispatch actions to other modules.\n\n1. Simply import the instantiated module (suitable if the modules are instantiated in the same file as they are defined):\n\n```ts\n// my-module.ts\n\n// import the module instance\nimport { otherModule } from \"./other-module\";\n\n@Module\nclass MyModule extends VuexModule {\n  get myGetter() {\n    return otherModule.foo;\n  }\n\n  @Action\n  async myAction() {\n    await otherModule.someAction();\n    // ...\n  }\n}\n```\n\n2. The other module can be registered through the constructor (suitable if the modules are instantiated elsewhere)\n\n```ts\n// my-module.ts\n\n// import the class, not the instance\nimport { OtherModule } from \"./other-module\";\n\n@Module\nexport class MyModule extends VuexModule {\n  private otherModule: OtherModule;\n\n  constructor(otherModule: OtherModule, options: RegisterOptions) {\n    super(options);\n    this.otherModule = otherModule;\n  }\n\n  get myGetter() {\n    return this.otherModule.foo;\n  }\n\n  @Action\n  async myAction() {\n    await this.otherModule.someAction();\n    // ...\n  }\n}\n\n// register-modules.ts\nimport store from \"path/to/store\";\nimport { OtherModule } from \"path/to/other-module\";\nimport { MyModule } from \"path/to/my-module\";\n\nexport const otherModule = new OtherModule({ store, name: \"otherModule\" });\nexport const myModule = new MyModule(otherModule, { store, name: \"myModule\" });\n```\n\nThe local modules will not be part of the state and cannot be accessed from the outside, so they should always be declared private.\n\n```ts\nmyModule.otherModule; // -> undefined\n```\n\n### The `store.watch` function\n\nVuex can also be used ouside of vue modules. To listen for changes to the state, vuex provides a [watch method](https://vuex.vuejs.org/api/#watch).\n\nThis api is also provided by vuex-class-modules under the method name `$watch` to prevent name collisions. For example you can do:\n\n```ts\nimport store from \"./store\";\nimport { MyModule } from \"./my-module\";\n\nconst myModule = new MyModule({ store, name: \"MyModule\" });\nmyModule.$watch(\n  (theModule) => theModule.fullName,\n  (newName: string, oldName: string) => {\n    // ...\n  },\n  {\n    deep: false,\n    immediate: false,\n  }\n);\n```\n\nand to unwatch:\n\n```ts\nconst unwatch = myModule.$watch(...);\nunwatch();\n```\n\n### Register options\n\n- `name` [required]: Name of the module\n- `store` [required]: The vuex store - which can just be instantiated as empty:\n\n```ts\n// store.ts\nimport Vue from \"vue\";\nimport Vuex from \"vuex\";\nVue.use(Vuex);\nconst store = new Vuex.Store({});\n```\n\n### Module options\n\nThe module decorator can also accept options:\n\n- `generateMutationSetters` [optional, default=false]: Whether automatic mutation setters for the state properties should be generated, see [Generate Mutation Setters](#generate-mutation-setters).\n\n## Example\n\nThe vuex shopping cart example rewritten using `vue-class-component` and `vuex-class-modules` can be found in the [example directory](/example). Build the example using:\n\n`npm run example`\n\n## Caveats of `this`\n\nAs for vue-class-component `this` inside the module is just a proxy object to the store. It can therefore only access what the corresponding vuex module function would be able to access:\n\n```ts\n@Module\nclass MyModule extends VuexModule {\n  foo = \"bar\";\n\n  get someGetter() {\n    return 123;\n  }\n  get myGetter() {\n    this.foo; // -> \"bar\"\n    this.someGetter; // -> 123\n    this.someMutation(); // undefined, getters cannot call mutations\n    this.someAction(); // -> undefined, getters cannot call actions\n  }\n\n  @Mutation\n  someMutation() {\n    /* ... */\n  }\n  @Mutation\n  myMutation() {\n    this.foo; // -> \"bar\"\n    this.someGetter; // -> undefined, mutations dont have access to getters\n    this.someMutation(); // -> undefined, mutations cannot call other mutations\n    this.someAction(); // -> undefined, mutations cannot call actions\n  }\n\n  @Action\n  async someAction() {\n    /* ... */\n  }\n  @Action\n  async myAction() {\n    this.foo; // -> \"bar\"\n    this.someGetter; // -> 123\n    this.myMutation(); // Ok\n    await this.someAction(); // Ok\n  }\n}\n```\n\n## Local Functions\n\nThe module can have non-mutation/action functions which can be used inside the module. As for local modules, these functions will not be exposed outside the module and should therefore be private. `this` will be passed on to the local function from the getter/mutation/action.\n\n```ts\n@Module\nclass MyModule extends VuexModule {\n  get myGetter() {\n    return myGetterHelper();\n  }\n  private myGetterHelper() {\n    // same 'this' context as myGetter\n  }\n\n  @Mutation\n  myMutation() {\n    this.myMutationHelper();\n  }\n\n  // should be private\n  myMutationHelper() { /* ... */}\n}\nconst myModule = new MyModule({ store, name: \"myModule });\nmyModule.myMutationHelper // -> undefined.\n```\n\n## Generate Mutation Setters\n\nAs I often find myself writing a lot of simple setter mutations like\n\n```ts\n@Module\nclass UserModule extends VuexModule {\n  firstName = \"Foo\";\n  lastName = \"Bar\";\n\n  @Mutation\n  setFirstName(firstName: string) {\n    this.firstName = firstName;\n  }\n  @Mutation\n  setLastName(lastName: string) {\n    this.lastName = lastName;\n  }\n}\n```\n\na module option `generateMutationSetters` has been added, which when enabled will generate a setter mutation for each state property. The state can then be modified directly from the actions:\n\n```ts\n@Module({ generateMutationSetters: true })\nclass UserModule extends VuexModule {\n  firstName = \"Foo\";\n  lastName = \"Bar\";\n\n  // Auto generated:\n  // @Mutation set__firstName(val: any) { this.firstName = val }\n  // @Mutation set__lastName(val: any) { this.lastName = val }\n\n  @Action\n  async loadUser() {\n    const user = await fetchUser();\n    this.firstName = user.firstName; // -> this.set__firstName(user.firstName);\n    this.lastName = user.lastName; // -> this.set__lastName(user.lastName);\n  }\n}\n```\n\n_NOTE:_ Setters are only generated for root-level state properties, so in order to update a property of an object you have to use a mutation or replace the entire object:\n\n```ts\n@Module({ generateMutationSetters: true })\nclass UserModule extends VuexModule {\n  user = {\n    id: 123,\n    name: \"Foo\",\n  };\n\n  @Mutation\n  setUserName() {\n    this.user.name = \"Bar\"; // OK!\n  }\n\n  @Action\n  async loadUser() {\n    this.user.name = \"Bar\"; // Bad, the state is mutated outside a mutation\n    this.user = { ...this.user, name: \"Bar\" }; // OK!\n  }\n}\n```\n\n## Vite HMR\n\n[Vite](https://vitejs.dev/) (and possibly other bundlers) uses `import.meta.hot` for HMR, which `vuex-class-modules` doesn't support currently. Instead a static property\n\n```ts\nVuexModule.__useHotUpdate = true; // default false\n```\n\nis provided, which will force hot updates to the store instead of throwing an error when a module with a duplicate name is registered. This could for instance be set only in dev mode\n\n```ts\nVuexModule.__useHotUpdate = import.meta.env.DEV;\n```\n\n## License\n\n[MIT](http://opensource.org/licenses/MIT)\n"
  },
  {
    "path": "example/index.html",
    "content": "\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Vuex Class Modules Example</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script src=\"build.js\"></script>\n  </body>\n</html>"
  },
  {
    "path": "example/src/api/shop.ts",
    "content": "/**\n * Mocking client-server processing\n */\nexport interface Product {\n  id: number;\n  title: string;\n  price: number;\n  inventory: number;\n}\n\nexport interface CartItem {\n  id: number;\n  quantity: number;\n}\n\nconst products: Product[] = [\n  { id: 1, title: \"iPad 4 Mini\", price: 500.01, inventory: 2 },\n  { id: 2, title: \"H&M T-Shirt White\", price: 10.99, inventory: 10 },\n  { id: 3, title: \"Charli XCX - Sucker CD\", price: 19.99, inventory: 5 }\n];\n\nexport default {\n  async getProducts() {\n    await new Promise(resolve => setTimeout(resolve, 100));\n    return products;\n  },\n\n  async buyProducts(items: CartItem[]) {\n    await new Promise(resolve => setTimeout(resolve, 100));\n\n    if (Math.random() > 0.5) {\n      throw Error();\n    }\n  }\n};\n"
  },
  {
    "path": "example/src/app.ts",
    "content": "import Vue from \"vue\";\nimport App from \"./components/App.vue\";\nimport store from \"./store\";\n\nnew Vue({\n  el: \"#app\",\n  store,\n  render: h => h(App)\n});\n"
  },
  {
    "path": "example/src/components/App.vue",
    "content": "<template>\n  <div id=\"app\">\n    <h1>Shopping Cart Example</h1>\n    <hr />\n    <h2>Products</h2>\n    <ProductList />\n    <hr />\n    <ShoppingCart />\n  </div>\n</template>\n\n<script lang=\"ts\">\nimport Vue from \"vue\";\nimport Component from \"vue-class-component\";\nimport ProductList from \"./ProductList.vue\";\nimport ShoppingCart from \"./ShoppingCart.vue\";\n\n@Component({\n  components: { ProductList, ShoppingCart }\n})\nexport default class App extends Vue {}\n</script>\n"
  },
  {
    "path": "example/src/components/ProductList.vue",
    "content": "<template>\n  <ul>\n    <li v-for=\"product in products\" :key=\"product.id\">\n      {{ product.title }} - {{ product.price }}€<br />\n      <button :disabled=\"!product.inventory\" @click=\"addProductToCart(product);\">Add to cart</button>\n    </li>\n  </ul>\n</template>\n\n<script lang=\"ts\">\nimport Vue from \"vue\";\nimport Component from \"vue-class-component\";\nimport { productsModule } from \"../store/products\";\nimport { cartModule } from \"../store/cart\";\nimport { Product } from \"../api/shop\";\n\n@Component\nexport default class ProductList extends Vue {\n  get products() {\n    return productsModule.all;\n  }\n\n  created() {\n    productsModule.getAllProducts();\n  }\n\n  addProductToCart(product: Product) {\n    cartModule.addProductToCart(product);\n  }\n}\n</script>\n"
  },
  {
    "path": "example/src/components/ShoppingCart.vue",
    "content": "<template>\n  <div class=\"cart\">\n    <h2>Your Cart</h2>\n    <p v-show=\"!products.length\"><i>Please add some products to cart.</i></p>\n    <ul>\n      <li v-for=\"product in products\" :key=\"product.id\">\n        {{ product.title }} - {{ product.price }}€ x {{ product.quantity }}\n      </li>\n    </ul>\n    <p>Total: {{ total }}€</p>\n    <p><button :disabled=\"!products.length\" @click=\"checkout(products);\">Checkout</button></p>\n    <p v-show=\"checkoutStatus\">Checkout {{ checkoutStatus }}.</p>\n  </div>\n</template>\n\n<script lang=\"ts\">\nimport Vue from \"vue\";\nimport Component from \"vue-class-component\";\nimport { cartModule } from \"../store/cart\";\n\n@Component\nexport default class ShoppingCart extends Vue {\n  get checkoutStatus() {\n    return cartModule.checkoutStatus;\n  }\n  get products() {\n    return cartModule.cartProducts;\n  }\n  get total() {\n    return cartModule.cartTotalPrice;\n  }\n\n  checkout() {\n    cartModule.checkout();\n  }\n}\n</script>\n"
  },
  {
    "path": "example/src/shims-vue.d.ts",
    "content": "declare module \"*.vue\" {\n  import Vue from \"vue\";\n  export default Vue;\n}\n"
  },
  {
    "path": "example/src/store/cart.ts",
    "content": "import store from \"./\";\nimport shop, { CartItem, Product } from \"../api/shop\";\nimport { Module, Mutation, Action, VuexModule } from \"../../../lib/index\";\nimport { productsModule } from \"./products\";\n\n@Module({ generateMutationSetters: true })\nclass Cart extends VuexModule {\n  items: CartItem[] = [];\n  checkoutStatus = \"\";\n\n  get cartProducts() {\n    return this.items.map(({ id, quantity }) => {\n      const product = productsModule.all.find(p => p.id === id);\n      return {\n        title: product!.title,\n        price: product!.price,\n        quantity\n      };\n    });\n  }\n\n  get cartTotalPrice() {\n    return this.cartProducts.reduce((total, product) => {\n      return total + product.price * product.quantity;\n    }, 0);\n  }\n\n  @Mutation\n  pushProductToCart(id: number) {\n    this.items.push({\n      id,\n      quantity: 1\n    });\n  }\n\n  @Mutation\n  incrementItemQuantity(id: number) {\n    const cartItem = this.items.find(item => item.id === id);\n    cartItem!.quantity++;\n  }\n\n  @Action\n  async addProductToCart(product: Product) {\n    this.checkoutStatus = \"\";\n\n    if (product.inventory > 0) {\n      const cartItem = this.items.find(item => item.id === product.id);\n      if (!cartItem) {\n        this.pushProductToCart(product.id);\n      } else {\n        this.incrementItemQuantity(cartItem.id);\n      }\n      // remove 1 item from stock\n      productsModule.decrementProductInventory(product.id);\n    }\n  }\n\n  @Action\n  async checkout() {\n    const savedCartItems = [...this.items];\n    this.checkoutStatus = \"\";\n\n    // empty cart\n    this.items = [];\n\n    try {\n      await shop.buyProducts(savedCartItems);\n      this.checkoutStatus = \"successful\";\n    } catch (e) {\n      this.items = savedCartItems;\n      this.checkoutStatus = \"failed\";\n    }\n  }\n}\n\nexport const cartModule = new Cart({ store, name: \"cart\" });\n"
  },
  {
    "path": "example/src/store/index.ts",
    "content": "import Vue from \"vue\";\nimport Vuex from \"vuex\";\nVue.use(Vuex);\n\nexport default new Vuex.Store({});\n"
  },
  {
    "path": "example/src/store/products.ts",
    "content": "import store from \"./\";\nimport shop, { Product } from \"../api/shop\";\nimport { Module, Mutation, Action, VuexModule } from \"../../../lib/index\";\n\n@Module({ generateMutationSetters: true })\nclass Products extends VuexModule {\n  all: Product[] = [];\n\n  @Mutation\n  decrementProductInventory(id: number) {\n    const product = this.all.find(p => p.id === id);\n    product!.inventory--;\n  }\n\n  @Action\n  async getAllProducts() {\n    this.all = await shop.getProducts();\n  }\n}\n\nexport const productsModule = new Products({ store, name: \"products\" });\n"
  },
  {
    "path": "example/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"lib\": [\n      \"dom\",\n      \"esnext\"\n    ],\n    \"module\": \"es2015\",\n    \"moduleResolution\": \"node\",\n    \"experimentalDecorators\": true,\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": false\n  },\n  \"include\": [\n    \"./**/*.ts\",\n  ]\n}"
  },
  {
    "path": "example/webpack.config.js",
    "content": "const VueLoaderPlugin = require('vue-loader/lib/plugin')\n\nmodule.exports = {\n  mode: 'development',\n  context: __dirname,\n  entry: './src/app.ts',\n  output: {\n    path: __dirname,\n    filename: 'build.js'\n  },\n  resolve: {\n    extensions: ['.ts', '.tsx', '.js']\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.tsx?$/,\n        exclude: /node_modules/,\n        use: [\n          {\n            loader: 'ts-loader',\n            options: {\n              appendTsSuffixTo: [/\\.vue$/],\n              appendTsxSuffixTo: [/\\.vue$/]\n            }\n          }\n        ]\n      },\n      {\n        test: /\\.vue$/,\n        use: ['vue-loader']\n      }\n    ]\n  },\n  devtool: 'source-map',\n  plugins: [\n    new VueLoaderPlugin()\n  ]\n}"
  },
  {
    "path": "jestconfig.json",
    "content": "{\n  \"preset\": \"ts-jest\",\n  \"rootDir\": \"./test\",\n  \"testMatch\": [\"<rootDir>/**/*.ts\"],\n  \"moduleFileExtensions\": [\"ts\", \"tsx\", \"js\", \"jsx\", \"json\", \"node\"],\n  \"globals\": {\n    \"ts-jest\": {\n      \"tsConfig\": {\n        \"isolatedModules\": false,\n        \"esModuleInterop\": true\n      }\n    }\n  }\n}"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"vuex-class-modules\",\n  \"version\": \"1.3.0\",\n  \"description\": \"Typescript class decorators for class-style vuex modules.\",\n  \"main\": \"commonjs/index.js\",\n  \"module\": \"lib/index.js\",\n  \"exports\": {\n    \".\": {\n      \"require\": \"./commonjs/index.js\",\n      \"default\": \"./lib/index.js\"\n    }\n  },\n  \"types\": \"lib/index.d.ts\",\n  \"files\": [\n    \"lib\",\n    \"commonjs\"\n  ],\n  \"scripts\": {\n    \"test\": \"jest --config jestconfig.json\",\n    \"build\": \"npm run build:es2015 && npm run build:commonjs\",\n    \"build:es2015\": \"tsc\",\n    \"build:commonjs\": \"tsc -m commonjs --outDir ./commonjs\",\n    \"lint\": \"tslint -p tsconfig.json --fix\",\n    \"example\": \"npm run build && webpack --config ./example/webpack.config.js\",\n    \"prepare\": \"npm run build\",\n    \"prepublishOnly\": \"npm test && npm run lint\",\n    \"preversion\": \"npm run lint\",\n    \"version\": \"git add -A src\",\n    \"postversion\": \"git push && git push --tags\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/gertqin/vuex-class-modules.git\"\n  },\n  \"keywords\": [\n    \"vue\",\n    \"vuex\",\n    \"typescript\",\n    \"class\",\n    \"decorators\"\n  ],\n  \"author\": \"Gert Qin Hansen\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/gertqin/vuex-class-modules/issues\"\n  },\n  \"homepage\": \"https://github.com/gertqin/vuex-class-modules#readme\",\n  \"devDependencies\": {\n    \"@types/node\": \"12.12.2\",\n    \"@types/jest\": \"^26.0.14\",\n    \"@types/webpack-env\": \"^1.13.9\",\n    \"css-loader\": \"^3.2.0\",\n    \"jest\": \"^26.4.0\",\n    \"ts-jest\": \"^26.4.0\",\n    \"ts-loader\": \"^6.2.0\",\n    \"tslint\": \"^5.20.0\",\n    \"tslint-config-prettier\": \"^1.18.0\",\n    \"tslint-plugin-prettier\": \"^2.0.1\",\n    \"typescript\": \"^3.8.4\",\n    \"vue\": \"^2.6.10\",\n    \"vue-class-component\": \"^7.1.0\",\n    \"vue-loader\": \"^15.7.0\",\n    \"vue-template-compiler\": \"^2.6.10\",\n    \"vuex\": \"^3.1.1\",\n    \"webpack\": \"^4.44.2\",\n    \"webpack-cli\": \"^3.3.12\"\n  }\n}\n"
  },
  {
    "path": "src/VuexModule.ts",
    "content": "import { RegisterOptions } from \"./module-factory\";\nimport { WatchOptions } from \"vue\";\n\nexport class VuexModule {\n  private __options: RegisterOptions;\n\n  static __useHotUpdate: boolean = false;\n\n  constructor(options: RegisterOptions) {\n    this.__options = options;\n  }\n\n  $watch<T>(fn: (arg: this) => T, callback: (newValue: T, oldValue: T) => void, options?: WatchOptions): Function {\n    return function() {};\n  }\n}\n"
  },
  {
    "path": "src/actions.ts",
    "content": "import { ModulePrototype } from \"./module-factory\";\n\nexport function Action<T extends Object>(\n  target: T,\n  key: string | symbol,\n  descriptor: TypedPropertyDescriptor<(arg?: any) => any>\n) {\n  const vuexModule = target.constructor as ModulePrototype;\n  if (!vuexModule.__actions) {\n    vuexModule.__actions = {};\n  }\n  if (descriptor.value) {\n    vuexModule.__actions[key as string] = descriptor.value;\n  }\n}\n"
  },
  {
    "path": "src/index.ts",
    "content": "export { RegisterOptions, ModuleOptions } from \"./module-factory\";\nexport { Action } from \"./actions\";\nexport { Module } from \"./module\";\nexport { Mutation } from \"./mutations\";\nexport { VuexModule } from \"./VuexModule\";\n"
  },
  {
    "path": "src/module-factory.ts",
    "content": "import { Store, Module as StoreModule, GetterTree, ActionContext, Dispatch, Commit } from \"vuex\";\nimport { WatchOptions } from \"vue\";\nimport { VuexModule } from \"./VuexModule\";\n\nexport interface ModuleOptions {\n  generateMutationSetters?: boolean;\n}\n\nexport interface RegisterOptions {\n  store: Store<any>;\n  name: string;\n}\n\nexport interface IVuexModule extends Dictionary<any> {\n  __options: RegisterOptions;\n}\nexport interface IModulePrototype {\n  __mutations?: Dictionary<(payload?: any) => void>;\n  __actions?: Dictionary<(payload?: any) => Promise<void>>;\n}\nexport type ModulePrototype = IModulePrototype & Function;\n\ntype Dictionary<T> = { [k: string]: T };\n\ninterface ModuleDefinition {\n  state: Dictionary<any>;\n  moduleRefs: Dictionary<VuexModule>;\n  getters: Dictionary<() => void>;\n  mutations: Dictionary<(payload?: any) => void>;\n  actions: Dictionary<(payload?: any) => Promise<void>>;\n  localFunctions: Dictionary<(...args: any[]) => any>;\n}\ninterface StoreProxyDefinition {\n  state?: Dictionary<any>;\n  stateSetter?: (key: string, val: any) => void;\n\n  getters?: Dictionary<any>;\n  commit?: Commit;\n  dispatch?: Dispatch;\n\n  useNamespaceKey?: boolean;\n  excludeModuleRefs?: boolean;\n  excludeLocalFunctions?: boolean;\n}\n\nexport class VuexClassModuleFactory {\n  moduleOptions: ModuleOptions;\n  instance: IVuexModule;\n  registerOptions: RegisterOptions;\n\n  definition: ModuleDefinition = {\n    state: {},\n    moduleRefs: {},\n    getters: {},\n    mutations: {},\n    actions: {},\n    localFunctions: {}\n  };\n\n  constructor(classModule: ModulePrototype, instance: IVuexModule, moduleOptions: ModuleOptions) {\n    this.moduleOptions = moduleOptions;\n    this.instance = instance;\n    this.registerOptions = instance.__options;\n    this.init(classModule);\n  }\n\n  private init(classModule: ModulePrototype) {\n    // state\n    for (const key of Object.keys(this.instance)) {\n      const val = this.instance[key];\n      if (key !== \"__options\" && this.instance.hasOwnProperty(key)) {\n        if (val instanceof VuexModule) {\n          this.definition.moduleRefs[key] = val;\n        } else {\n          this.definition.state[key] = this.instance[key];\n        }\n      }\n    }\n\n    const actionKeys = Object.keys(classModule.__actions || {});\n    const mutationKeys = Object.keys(classModule.__mutations || {});\n    const isAction = (key: string) => actionKeys.indexOf(key) !== -1;\n    const isMutation = (key: string) => mutationKeys.indexOf(key) !== -1;\n\n    for (const module of getModulePrototypes(classModule)) {\n      for (const key of Object.getOwnPropertyNames(module.prototype)) {\n        const descriptor = Object.getOwnPropertyDescriptor(module.prototype, key) as PropertyDescriptor;\n\n        const isGetter = !!descriptor.get;\n        if (isGetter && !(key in this.definition.getters)) {\n          this.definition.getters[key] = descriptor.get!;\n        }\n\n        if (isAction(key) && !(key in this.definition.actions) && descriptor.value) {\n          this.definition.actions[key] = module.prototype[key];\n        }\n        if (isMutation(key) && !(key in this.definition.mutations) && descriptor.value) {\n          this.definition.mutations[key] = module.prototype[key];\n        }\n\n        const isHelperFunction =\n          descriptor.value &&\n          typeof module.prototype[key] === \"function\" &&\n          !isAction(key) &&\n          !isMutation(key) &&\n          key !== \"constructor\";\n\n        if (isHelperFunction && !(key in this.definition.localFunctions)) {\n          this.definition.localFunctions[key] = module.prototype[key];\n        }\n      }\n    }\n  }\n\n  registerVuexModule() {\n    const vuexModule: StoreModule<any, any> = {\n      state: this.definition.state,\n      getters: {},\n      mutations: {},\n      actions: {},\n      namespaced: true\n    };\n\n    // getters\n    mapValues(vuexModule.getters!, this.definition.getters, getter => {\n      return (state: any, getters: GetterTree<any, any>) => {\n        const thisObj = this.buildThisProxy({ state, getters });\n        return getter.call(thisObj);\n      };\n    });\n\n    // mutations\n    mapValues(vuexModule.mutations!, this.definition.mutations, mutation => {\n      return (state: any, payload: any) => {\n        const thisObj = this.buildThisProxy({\n          state,\n          stateSetter: (stateField: string, val: any) => {\n            state[stateField] = val;\n          }\n        });\n        mutation.call(thisObj, payload);\n      };\n    });\n    if (this.moduleOptions.generateMutationSetters) {\n      for (const stateKey of Object.keys(this.definition.state)) {\n        const mutation = (state: any, payload: any) => {\n          state[stateKey] = payload;\n        };\n        vuexModule.mutations![this.getMutationSetterName(stateKey)] = mutation;\n      }\n    }\n\n    // actions\n    mapValues(vuexModule.actions!, this.definition.actions, action => {\n      return (context: ActionContext<any, any>, payload: any) => {\n        const proxyDefinition: StoreProxyDefinition = {\n          ...context,\n          stateSetter: this.moduleOptions.generateMutationSetters\n            ? (field: string, val: any) => {\n                context.commit(this.getMutationSetterName(field), val);\n              }\n            : undefined\n        };\n        const thisObj = this.buildThisProxy(proxyDefinition);\n\n        return action.call(thisObj, payload);\n      };\n    });\n\n    // register module\n    const { store, name } = this.registerOptions;\n    if (store.state[name]) {\n      if (VuexModule.__useHotUpdate || (typeof module !== \"undefined\" && module.hot)) {\n        store.hotUpdate({\n          modules: {\n            [name]: vuexModule\n          }\n        });\n      } else {\n        throw Error(`[vuex-class-module]: A module with name '${name}' already exists.`);\n      }\n    } else {\n      store.registerModule(this.registerOptions.name, vuexModule);\n    }\n  }\n\n  buildAccessor() {\n    const { store, name } = this.registerOptions;\n\n    const stateSetter = this.moduleOptions.generateMutationSetters\n      ? (field: string, val: any) => {\n          store.commit(`${name}/${this.getMutationSetterName(field)}`, val);\n        }\n      : undefined;\n\n    const accessorModule = this.buildThisProxy({\n      ...store,\n      state: store.state[name],\n      stateSetter,\n      useNamespaceKey: true,\n      excludeModuleRefs: true,\n      excludeLocalFunctions: true\n    });\n\n    // watch API\n    accessorModule.$watch = (\n      fn: (arg: VuexModule) => any,\n      callback: (newValue: any, oldValue: any) => void,\n      options?: WatchOptions\n    ) => {\n      return store.watch(\n        (state: any, getters: any) =>\n          fn(\n            this.buildThisProxy({\n              state: state[name],\n              getters,\n              useNamespaceKey: true\n            })\n          ),\n        callback,\n        options\n      );\n    };\n\n    Object.setPrototypeOf(accessorModule, Object.getPrototypeOf(this.instance));\n    Object.freeze(accessorModule);\n\n    return accessorModule;\n  }\n\n  private buildThisProxy(proxyDefinition: StoreProxyDefinition) {\n    const obj: any = {};\n\n    if (proxyDefinition.state) {\n      mapValuesToProperty(\n        obj,\n        this.definition.state,\n        key => proxyDefinition.state![key],\n        proxyDefinition.stateSetter\n          ? (key, val) => proxyDefinition.stateSetter!(key, val)\n          : () => {\n              throw Error(\"[vuex-class-module]: Cannot modify state outside mutations.\");\n            }\n      );\n    }\n    if (!proxyDefinition.excludeModuleRefs) {\n      mapValues(obj, this.definition.moduleRefs, val => val);\n    }\n\n    const namespaceKey = proxyDefinition.useNamespaceKey ? this.registerOptions.name + \"/\" : \"\";\n\n    if (proxyDefinition.getters) {\n      mapValuesToProperty(obj, this.definition.getters, key => proxyDefinition.getters![`${namespaceKey}${key}`]);\n    }\n\n    if (proxyDefinition.commit) {\n      mapValues(obj, this.definition.mutations, (mutation, key) => {\n        return (payload?: any) => proxyDefinition.commit!(`${namespaceKey}${key}`, payload);\n      });\n    }\n\n    if (proxyDefinition.dispatch) {\n      mapValues(obj, this.definition.actions, (action, key) => {\n        return (payload?: any) => proxyDefinition.dispatch!(`${namespaceKey}${key}`, payload);\n      });\n    }\n\n    if (!proxyDefinition.excludeLocalFunctions) {\n      mapValues(obj, this.definition.localFunctions, localFunction => {\n        return (...args: any[]) => localFunction.apply(obj, args);\n      });\n    }\n\n    return obj;\n  }\n\n  private getMutationSetterName(stateKey: string) {\n    return \"set__\" + stateKey;\n  }\n}\n\nfunction mapValues<S, V>(target: Dictionary<any>, source: Dictionary<S>, mapFunc: (val: S, key: string) => V) {\n  for (const key of Object.keys(source)) {\n    target[key] = mapFunc(source[key], key);\n  }\n}\n\nfunction mapValuesToProperty<S, V>(\n  target: Dictionary<any>,\n  source: Dictionary<S>,\n  get: (key: string) => any,\n  set?: (key: string, val: any) => void\n) {\n  for (const key of Object.keys(source)) {\n    Object.defineProperty(target, key, {\n      get: () => get(key),\n      set: set ? (val: string) => set(key, val) : undefined\n    });\n  }\n}\n\nfunction getModulePrototypes(module: ModulePrototype): ModulePrototype[] {\n  const prototypes: ModulePrototype[] = [];\n\n  for (let prototype = module; prototype && prototype !== VuexModule; prototype = Object.getPrototypeOf(prototype)) {\n    prototypes.push(prototype);\n  }\n\n  return prototypes;\n}\n"
  },
  {
    "path": "src/module.ts",
    "content": "import { VuexClassModuleFactory, ModuleOptions, IVuexModule } from \"./module-factory\";\nimport { VuexModule } from \"./VuexModule\";\n\ntype VuexModuleClass = new (...args: any[]) => VuexModule;\nexport function Module<T extends VuexModuleClass>(target: T): T;\nexport function Module(options?: ModuleOptions): ClassDecorator;\nexport function Module<T extends VuexModuleClass>(arg?: ModuleOptions | T): ClassDecorator | T {\n  if (typeof arg === \"function\") {\n    return moduleDecoratorFactory()(arg) as T;\n  } else {\n    return moduleDecoratorFactory(arg);\n  }\n}\n\nfunction moduleDecoratorFactory(moduleOptions?: ModuleOptions) {\n  return <TFunction extends Function>(constructor: TFunction): TFunction => {\n    const accessor: any = function(...args: any[]) {\n      const instance = new constructor.prototype.constructor(...args) as IVuexModule;\n      Object.setPrototypeOf(instance, accessor.prototype);\n\n      const factory = new VuexClassModuleFactory(constructor, instance, moduleOptions || {});\n\n      factory.registerVuexModule();\n      return factory.buildAccessor();\n    };\n    accessor.prototype = Object.create(constructor.prototype);\n    accessor.prototype.constructor = accessor;\n    return accessor;\n  };\n}\n"
  },
  {
    "path": "src/mutations.ts",
    "content": "import { ModulePrototype } from \"./module-factory\";\n\nexport function Mutation<T extends Object>(\n  target: T,\n  key: string | symbol,\n  descriptor: TypedPropertyDescriptor<(arg?: any) => void>\n) {\n  const vuexModule = target.constructor as ModulePrototype;\n  if (!vuexModule.__mutations) {\n    vuexModule.__mutations = {};\n  }\n  if (descriptor.value) {\n    vuexModule.__mutations[key as string] = descriptor.value;\n  }\n}\n"
  },
  {
    "path": "test/actions-inheritance.ts",
    "content": "import { Action, Module, Mutation, VuexModule, RegisterOptions } from \"../src\";\nimport Vuex, { Store } from \"vuex\";\nimport Vue from \"vue\";\n\nVue.use(Vuex);\n\nabstract class ParentModule extends VuexModule {\n  foo = \"init\";\n\n  get bigFoo() {\n    return this.foo.toUpperCase();\n  }\n\n  get decoratedFoo() {\n    return `***${this.foo}***`;\n  }\n\n  @Mutation\n  updateFoo(value: string) {\n    this.foo = value;\n  }\n\n  @Action\n  action1() {\n    //\n  }\n\n  @Action\n  action2() {\n    //\n  }\n\n  @Action\n  action3() {\n    //\n  }\n\n  @Action\n  action4() {\n    //\n  }\n\n  @Action\n  action5() {\n    this.updateFoo(this.foo + \"action5\");\n  }\n\n  @Action\n  action6() {\n    this.updateFoo(this.foo + \"polymorphicCallOf\");\n    this.action7();\n  }\n\n  abstract action7(): void;\n}\n\n@Module\nclass Module1 extends ParentModule {\n  private tag = \"child1\";\n  foo: string = \"init\" + this.tag;\n\n  get doubleFoo() {\n    return this.foo + this.foo;\n  }\n\n  @Mutation\n  setFooToExample() {\n    this.foo = \"example\" + this.tag;\n  }\n\n  @Action\n  action1() {\n    this.setFooToExample();\n  }\n\n  @Action\n  action2() {\n    this.updateFoo(\"bar\" + this.tag);\n  }\n\n  @Action\n  action3() {\n    this.updateFoo(this.doubleFoo);\n  }\n\n  @Action\n  action4() {\n    this.updateFoo(this.bigFoo);\n  }\n\n  @Action\n  action5() {\n    super.action5();\n    this.updateFoo(this.foo + this.tag);\n  }\n\n  @Action\n  action7(): void {\n    this.updateFoo(this.foo + \"action7\" + this.tag);\n  }\n}\n\n@Module\nclass Module2 extends ParentModule {\n  private tag = \"child2\";\n\n  constructor(options: RegisterOptions) {\n    super(options);\n    this.foo = this.foo + this.tag;\n  }\n\n  get tripleFoo() {\n    return this.foo + this.foo + this.foo;\n  }\n\n  @Mutation\n  setFooToAnotherExample() {\n    this.foo = \"example\" + this.tag;\n  }\n\n  @Action\n  action1() {\n    this.setFooToAnotherExample();\n  }\n\n  @Action\n  action2() {\n    this.updateFoo(\"baz\" + this.tag);\n  }\n\n  @Action\n  action3() {\n    this.updateFoo(this.tripleFoo);\n  }\n\n  @Action\n  action4() {\n    this.updateFoo(this.decoratedFoo);\n  }\n\n  @Action\n  action5() {\n    super.action5();\n    this.updateFoo(this.foo + this.tag);\n  }\n\n  @Action\n  action7(): void {\n    this.updateFoo(this.foo + \"action7\" + this.tag);\n  }\n}\n\ndescribe(\"actions-inheritance\", () => {\n  let store: Store<any>;\n  let child1: Module1;\n  let child2: Module2;\n\n  beforeEach(() => {\n    store = new Vuex.Store({});\n    child1 = new Module1({ store, name: \"child1\" });\n    child2 = new Module2({ store, name: \"child2\" });\n  });\n\n  test(\"overriden action has access to mutations\", () => {\n    child1.action1();\n    child2.action1();\n    expect(child1.foo).toBe(\"examplechild1\");\n    expect(child2.foo).toBe(\"examplechild2\");\n  });\n\n  test(\"overriden action has access to parent mutations\", () => {\n    child1.action2();\n    child2.action2();\n    expect(child1.foo).toBe(\"barchild1\");\n    expect(child2.foo).toBe(\"bazchild2\");\n  });\n\n  test(\"overriden action has access to getters\", () => {\n    child1.action3();\n    child2.action3();\n    expect(child1.foo).toBe(\"initchild1initchild1\");\n    expect(child2.foo).toBe(\"initchild2initchild2initchild2\");\n  });\n\n  test(\"overriden action has access to parent getters\", () => {\n    child1.action4();\n    child2.action4();\n    expect(child1.foo).toBe(\"INITCHILD1\");\n    expect(child2.foo).toBe(\"***initchild2***\");\n  });\n\n  test(\"overriden action has access to parent method implementation\", () => {\n    child1.action5();\n    child2.action5();\n    expect(child1.foo).toBe(\"initchild1action5child1\");\n    expect(child2.foo).toBe(\"initchild2action5child2\");\n  });\n\n  test(\"parent action access derived action polymorphically\", () => {\n    child1.action6();\n    child2.action6();\n    expect(child1.foo).toBe(\"initchild1polymorphicCallOfaction7child1\");\n    expect(child2.foo).toBe(\"initchild2polymorphicCallOfaction7child2\");\n  });\n  test(\"access action7 directly\", () => {\n    child1.action7();\n    child2.action7();\n    expect(child1.foo).toBe(\"initchild1action7child1\");\n    expect(child2.foo).toBe(\"initchild2action7child2\");\n  });\n});\n"
  },
  {
    "path": "test/actions.ts",
    "content": "import { Module, Mutation, Action, VuexModule } from \"../src\";\nimport Vuex, { Payload, MutationPayload } from \"vuex\";\nimport Vue from \"vue\";\n\nVue.use(Vuex);\nconst store = new Vuex.Store<any>({});\n\n@Module\nclass MyModule extends VuexModule {\n  documentId = 0;\n  text = \"\";\n\n  get documentHasText() {\n    return this.documentId > 10;\n  }\n\n  @Mutation\n  setDocumentId(id: number) {\n    this.documentId = id;\n  }\n  @Mutation\n  setText(text: string) {\n    this.text = text;\n  }\n\n  @Action\n  async dummyAction(payload: any) {\n    // to test accessor\n  }\n\n  @Action\n  async loadText(documentId: number) {\n    if (this.documentId === 0) {\n      this.setDocumentId(documentId);\n\n      if (this.documentHasText) {\n        const text = await Promise.resolve(\"some other text\");\n        this.setText(text);\n      }\n    }\n  }\n}\n\nconst myModule = new MyModule({ store, name: \"myModule\" });\n\ninterface ActionPayload extends Payload {\n  payload?: any;\n}\n\ndescribe(\"actions\", () => {\n  test(\"accessor dispatches action\", async () => {\n    // subscribeAction missing from vuex typings\n    const actionObserver = jest.fn((action: ActionPayload) => action);\n    (store as any).subscribeAction(actionObserver);\n\n    await myModule.dummyAction(5);\n\n    expect(actionObserver.mock.calls.length).toBe(1);\n\n    const mutationPayload = actionObserver.mock.results[0].value as ActionPayload;\n    expect(mutationPayload.type).toBe(\"myModule/dummyAction\");\n    expect(mutationPayload.payload).toBe(5);\n  });\n\n  test(\"'this' matches vuex context\", async () => {\n    const mutationObserver = jest.fn((mutation: MutationPayload) => mutation);\n    store.subscribe(mutationObserver);\n\n    await store.dispatch(\"myModule/loadText\", 11);\n\n    expect(mutationObserver.mock.calls.length).toBe(2);\n\n    const firstMutation = mutationObserver.mock.results[0].value as MutationPayload;\n    expect(firstMutation.type).toBe(\"myModule/setDocumentId\");\n    expect(firstMutation.payload).toBe(11);\n\n    const secondMutation = mutationObserver.mock.results[1].value as MutationPayload;\n    expect(secondMutation.type).toBe(\"myModule/setText\");\n    expect(secondMutation.payload).toBe(\"some other text\");\n  });\n});\n"
  },
  {
    "path": "test/constructor.ts",
    "content": "import { Module, VuexModule, RegisterOptions } from \"../src\";\nimport Vuex from \"vuex\";\nimport Vue from \"vue\";\n\nVue.use(Vuex);\nconst store = new Vuex.Store<any>({});\n\n@Module\nclass MyModule extends VuexModule {\n  foo: string;\n\n  constructor(foo: string, options: RegisterOptions) {\n    super(options);\n    this.foo = foo;\n  }\n}\n\ntest(\"constructor\", () => {\n  const myModule = new MyModule(\"bar\", { store, name: \"myModule\" });\n  expect(myModule.foo).toBe(\"bar\");\n});\n"
  },
  {
    "path": "test/generate-mutations.ts",
    "content": "import Vue from \"vue\";\nimport Vuex, { MutationPayload } from \"vuex\";\nimport { Action, Module, VuexModule } from \"../src\";\n\nVue.use(Vuex);\nconst store = new Vuex.Store<any>({});\n\n@Module({ generateMutationSetters: true })\nclass MyModule extends VuexModule {\n  id = 0;\n  text = \"\";\n\n  @Action\n  async loadData() {\n    const { id, text } = await Promise.resolve({ id: 1, text: \"some text\" });\n    this.id = id;\n    this.text = text;\n  }\n}\n\nconst myModule = new MyModule({ store, name: \"myModule\" });\n\ntest(\"generate-mutations\", async () => {\n  const mutationObserver = jest.fn((mutation: MutationPayload) => mutation);\n  store.subscribe(mutationObserver);\n\n  await myModule.loadData();\n\n  const firstMutation = mutationObserver.mock.results[0].value as MutationPayload;\n  expect(firstMutation.type).toBe(\"myModule/set__id\");\n  expect(firstMutation.payload).toBe(1);\n\n  const secondMutation = mutationObserver.mock.results[1].value as MutationPayload;\n  expect(secondMutation.type).toBe(\"myModule/set__text\");\n  expect(secondMutation.payload).toBe(\"some text\");\n\n  // change state directly using generated mutation\n  myModule.text = \"some other text\";\n\n  const thirdMutation = mutationObserver.mock.results[2].value as MutationPayload;\n  expect(thirdMutation.type).toBe(\"myModule/set__text\");\n  expect(thirdMutation.payload).toBe(\"some other text\");\n});\n"
  },
  {
    "path": "test/getters-inheritance.ts",
    "content": "import { Action, Module, Mutation, VuexModule } from \"../src\";\nimport Vuex, { Store } from \"vuex\";\nimport Vue from \"vue\";\n\nVue.use(Vuex);\n\nclass ParentModule extends VuexModule {\n  foo = \"bar\";\n\n  get bigFoo() {\n    return this.foo.toUpperCase();\n  }\n\n  get snakeFoo() {\n    return \"__\";\n  }\n\n  @Mutation\n  myMutation(value: string) {\n    this.foo = value;\n  }\n\n  @Action\n  myAction() {\n    if (this.bigFoo === \"BAR\") {\n      this.myMutation(\"ok\");\n    }\n    if (this.bigFoo === \"BAZ\") {\n      this.myMutation(\"alright\");\n    }\n  }\n}\n\n@Module\nclass Module1 extends ParentModule {\n  private tag = \"child1\";\n\n  get snakeFoo() {\n    return `_${this.foo}_${this.tag}_`;\n  }\n}\n\n@Module\nclass Module2 extends ParentModule {\n  private tag = \"child2\";\n  foo = \"baz\";\n\n  get snakeFoo() {\n    return `_${this.foo}_${this.tag}_`;\n  }\n}\n\ndescribe(\"getters-inheritance\", () => {\n  let store: Store<any>;\n  let child1: Module1;\n  let child2: Module2;\n\n  beforeEach(() => {\n    store = new Vuex.Store({});\n    child1 = new Module1({ store, name: \"child1\" });\n    child2 = new Module2({ store, name: \"child2\" });\n  });\n\n  test(\"allows the use of getters from an inheriting class\", () => {\n    expect(child1.bigFoo).toBe(\"BAR\");\n    expect(child1.bigFoo).toBe(store.getters[\"child1/bigFoo\"]);\n    expect(child2.bigFoo).toBe(\"BAZ\");\n    expect(child2.bigFoo).toBe(store.getters[\"child2/bigFoo\"]);\n  });\n\n  test(\"allows the use of getters in inherited class\", () => {\n    child1.myAction();\n    child2.myAction();\n    expect(child1.bigFoo).toBe(\"OK\");\n    expect(child1.bigFoo).toBe(store.getters[\"child1/bigFoo\"]);\n    expect(child2.bigFoo).toBe(\"ALRIGHT\");\n    expect(child2.bigFoo).toBe(store.getters[\"child2/bigFoo\"]);\n  });\n\n  test(\"overriden getters behave as expected\", () => {\n    expect(child1.snakeFoo).toBe(\"_bar_child1_\");\n    expect(child1.snakeFoo).toBe(store.getters[\"child1/snakeFoo\"]);\n    expect(child2.snakeFoo).toBe(\"_baz_child2_\");\n    expect(child2.snakeFoo).toBe(store.getters[\"child2/snakeFoo\"]);\n  });\n});\n"
  },
  {
    "path": "test/getters.ts",
    "content": "import { Module, VuexModule } from \"../src\";\nimport Vuex from \"vuex\";\nimport Vue from \"vue\";\n\nVue.use(Vuex);\nconst store = new Vuex.Store<any>({});\n\n@Module\nclass MyModule extends VuexModule {\n  foo = {\n    text: \"some text\"\n  };\n\n  get textTransforms() {\n    return {\n      original: this.foo.text,\n      upperCase: this.foo.text.toUpperCase()\n    };\n  }\n}\n\nconst myModule = new MyModule({ store, name: \"myModule\" });\n\ntest(\"getters\", () => {\n  expect(myModule.textTransforms).toBe(store.getters[\"myModule/textTransforms\"]);\n  expect(myModule.textTransforms.upperCase).toBe(\"SOME TEXT\");\n});\n"
  },
  {
    "path": "test/instanceof.ts",
    "content": "import { Module, VuexModule } from \"../src\";\nimport Vuex from \"vuex\";\nimport Vue from \"vue\";\n\nVue.use(Vuex);\nconst store = new Vuex.Store<any>({});\n\nclass OriginalModule extends VuexModule {\n  foo = {\n    text: \"some text\"\n  };\n  bar = 1;\n}\n\n/** Manually apply decorator, to have access to initial class definition */\nconst MyModule = Module(OriginalModule);\nconst myModule = new MyModule({ store, name: \"myModule\" });\n\ntest(\"instance of\", () => {\n  expect(myModule instanceof OriginalModule).toBe(true);\n  expect(myModule instanceof MyModule).toBe(true);\n  expect(myModule instanceof VuexModule).toBe(true);\n});\n"
  },
  {
    "path": "test/local-functions-inheritance.ts",
    "content": "import Vue from \"vue\";\nimport Vuex, { Store } from \"vuex\";\nimport { Action, Module, Mutation, VuexModule } from \"../src\";\n\nVue.use(Vuex);\n\nabstract class Parent extends VuexModule {\n  canTransform = true;\n  text = \"parent text\";\n\n  get upperCaseText() {\n    return this.text.toUpperCase();\n  }\n\n  get noSpaceText() {\n    return this.snakeText();\n  }\n\n  private snakeText() {\n    // 'this' has access to state & getters\n    return this.canTransform ? this.upperCaseText.replace(/ /g, \"_\") : \"\";\n  }\n\n  @Mutation\n  setText(text: string) {\n    this.localSetText(text);\n  }\n\n  @Mutation\n  clearText() {\n    this.text = \"\";\n  }\n\n  protected abstract localSetText(text: string): void;\n  protected localLoadText() {\n    this.setText(\"parent: yet another text\");\n  }\n}\n\n@Module\nclass Module1 extends Parent {\n  private tag = \"child1\";\n  canTransform = true;\n  text = `${this.tag} text`;\n\n  get upperCaseText() {\n    return this.text.toUpperCase();\n  }\n\n  protected localSetText(text: string) {\n    // 'this' has state\n    this.text = `${text} ${this.tag}`;\n  }\n\n  @Action\n  async loadText() {\n    this.localLoadText();\n  }\n\n  protected localLoadText() {\n    // 'this' has getters & mutations\n    if (!this.upperCaseText) {\n      this.setText(`${this.tag.toUpperCase()}: yet another text`);\n    }\n  }\n}\n\n@Module\nclass Module2 extends Parent {\n  private tag = \"child2\";\n  canTransform = true;\n  text = `${this.tag} text`;\n\n  get upperCaseText() {\n    return this.text.toUpperCase();\n  }\n  get noSpaceText() {\n    return this.dashText();\n  }\n\n  private dashText() {\n    // 'this' has access to state & getters\n    return this.canTransform ? this.upperCaseText.replace(/ /g, \"--\") : \"\";\n  }\n\n  protected localSetText(text: string) {\n    // 'this' has state\n    this.text = `***${text}*** ${this.tag}`;\n  }\n\n  @Action\n  async loadText() {\n    this.localLoadText();\n  }\n\n  protected localLoadText() {\n    // 'this' has getters & mutations\n    if (!this.upperCaseText) {\n      this.setText(`${this.tag}: yet another text`);\n    }\n  }\n}\n\ndescribe(\"local-functions\", () => {\n  let child1: Module1;\n  let child2: Module2;\n  let store: Store<any>;\n\n  beforeEach(() => {\n    store = new Vuex.Store({});\n    child1 = new Module1({ store, name: \"myModule1\" });\n    child2 = new Module2({ store, name: \"myModule2\" });\n  });\n\n  test(\"from getter\", () => {\n    expect(child1.noSpaceText).toBe(\"CHILD1_TEXT\");\n    expect(child2.noSpaceText).toBe(\"CHILD2--TEXT\");\n  });\n\n  test(\"from mutation\", () => {\n    child1.setText(\"some other text\");\n    child2.setText(\"some other text\");\n    expect(child1.text).toBe(\"some other text child1\");\n    expect(child2.text).toBe(\"***some other text*** child2\");\n  });\n\n  test(\"from action\", async () => {\n    child1.clearText();\n    child2.clearText();\n\n    await child1.loadText();\n    await child2.loadText();\n    expect(child1.text).toBe(\"CHILD1: yet another text child1\");\n    expect(child2.text).toBe(\"***child2: yet another text*** child2\");\n  });\n});\n"
  },
  {
    "path": "test/local-functions.ts",
    "content": "import Vue from \"vue\";\nimport Vuex from \"vuex\";\nimport { Action, Module, Mutation, VuexModule } from \"../src\";\n\nVue.use(Vuex);\nconst store = new Vuex.Store<any>({});\n\n@Module\nclass MyModule extends VuexModule {\n  canTransform = true;\n  text = \"some text\";\n\n  get upperCaseText() {\n    return this.text.toUpperCase();\n  }\n  get pascalText() {\n    return this.transformText();\n  }\n  private transformText() {\n    // 'this' has access to state & getters\n    return this.canTransform ? this.upperCaseText.replace(/ /g, \"_\") : \"\";\n  }\n\n  @Mutation\n  setText(text: string) {\n    this.localSetText(text);\n  }\n  private localSetText(text: string) {\n    // 'this' has state\n    this.text = text;\n  }\n\n  @Action\n  async loadText() {\n    this.localLoadText();\n  }\n  private localLoadText() {\n    // 'this' has getters & mutations\n    if (!this.upperCaseText) {\n      this.setText(\"yet another text\");\n    }\n  }\n}\n\nconst myModule = new MyModule({ store, name: \"myModule\" });\n\ndescribe(\"local-functions\", () => {\n  test(\"from getter\", () => {\n    expect(myModule.pascalText).toBe(\"SOME_TEXT\");\n  });\n\n  test(\"from mutation\", () => {\n    myModule.setText(\"some other text\");\n    expect(myModule.text).toBe(\"some other text\");\n  });\n\n  test(\"from action\", async () => {\n    myModule.setText(\"\");\n\n    await myModule.loadText();\n    expect(myModule.text).toBe(\"yet another text\");\n  });\n});\n"
  },
  {
    "path": "test/module-reference.ts",
    "content": "import { Module, VuexModule, RegisterOptions } from \"../src\";\nimport Vuex from \"vuex\";\nimport Vue from \"vue\";\n\nVue.use(Vuex);\nconst store = new Vuex.Store<any>({});\n\n@Module\nclass MyModule extends VuexModule {\n  foo = \"bar\";\n}\n\n@Module\nclass OtherModule extends VuexModule {\n  private myModule: MyModule;\n\n  get moduleRef() {\n    return this.myModule;\n  }\n\n  constructor(myModule: MyModule, options: RegisterOptions) {\n    super(options);\n    this.myModule = myModule;\n  }\n}\n\ntest(\"module references\", () => {\n  const myModule = new MyModule({ store, name: \"myModule\" });\n  const otherModule = new OtherModule(myModule, { store, name: \"otherModule\" });\n  expect(store.state.otherModule.myModule).toBeUndefined();\n  expect(otherModule.moduleRef).toBe(myModule);\n});\n"
  },
  {
    "path": "test/mutations-inheritance.ts",
    "content": "import { Module, Mutation, VuexModule } from \"../src\";\nimport Vuex, { Store } from \"vuex\";\nimport Vue from \"vue\";\n\nVue.use(Vuex);\n\nclass ParentModule extends VuexModule {\n  foo = \"init\";\n\n  @Mutation\n  mutation1(value: string) {\n    //\n  }\n\n  @Mutation\n  mutation2(value: string) {\n    //\n  }\n\n  @Mutation\n  mutation3(value: string) {\n    this.foo = value;\n  }\n}\n\n@Module\nclass Module1 extends ParentModule {\n  private tag = \"child1\";\n  baz = \"init\" + this.tag;\n\n  @Mutation\n  mutation1(value: string) {\n    this.baz = value + this.tag;\n  }\n\n  @Mutation\n  mutation2(value: string) {\n    this.foo = value + this.tag;\n  }\n\n  @Mutation\n  mutation3(value: string) {\n    super.mutation3(value);\n    this.foo = this.foo + this.tag;\n  }\n}\n\n@Module\nclass Module2 extends ParentModule {\n  private tag = \"child2\";\n  bar = \"init\" + this.tag;\n  baz = \"init\" + this.tag;\n\n  @Mutation\n  mutation1(value: string) {\n    this.bar = value + this.tag;\n  }\n\n  @Mutation\n  mutation2(value: string) {\n    this.baz = value + this.tag;\n  }\n\n  @Mutation\n  mutation3(value: string) {\n    super.mutation3(value);\n    this.foo = this.foo + this.tag;\n  }\n}\n\ndescribe(\"mutations-inheritance\", () => {\n  let store: Store<any>;\n  let parent: ParentModule;\n  let child1: Module1;\n  let child2: Module2;\n\n  beforeEach(() => {\n    store = new Vuex.Store({});\n    parent = new ParentModule({ store, name: \"parentModule\" });\n    child1 = new Module1({ store, name: \"myModule1\" });\n    child2 = new Module2({ store, name: \"myModule2\" });\n  });\n\n  test(\"overriden mutation can modify state\", () => {\n    parent.mutation1(\"_\");\n    child1.mutation1(\"bar1\");\n    child2.mutation1(\"bar2\");\n    expect(parent.foo).toBe(\"init\");\n    expect(child1.baz).toBe(\"bar1child1\");\n    expect(child2.bar).toBe(\"bar2child2\");\n    expect(child2.baz).toBe(\"initchild2\");\n  });\n\n  test(\"overriden mutation can modify parent state\", () => {\n    parent.mutation2(\"_\");\n    child1.mutation2(\"bar\");\n    child2.mutation2(\"baz\");\n    expect(parent.foo).toBe(\"init\");\n    expect(child1.foo).toBe(\"barchild1\");\n    expect(child2.bar).toBe(\"initchild2\");\n    expect(child2.baz).toBe(\"bazchild2\");\n  });\n\n  test(\"overriden mutation has access to parent method implementation\", () => {\n    parent.mutation3(\"foo_\");\n    child1.mutation3(\"foo1\");\n    child2.mutation3(\"foo2\");\n    expect(parent.foo).toBe(\"foo_\");\n    expect(child1.foo).toBe(\"foo1child1\");\n    expect(child1.baz).toBe(\"initchild1\");\n    expect(child2.foo).toBe(\"foo2child2\");\n    expect(child2.bar).toBe(\"initchild2\");\n    expect(child2.baz).toBe(\"initchild2\");\n  });\n});\n"
  },
  {
    "path": "test/mutations.ts",
    "content": "import { Module, Mutation, VuexModule } from \"../src\";\nimport Vuex, { MutationPayload } from \"vuex\";\nimport Vue from \"vue\";\n\nVue.use(Vuex);\nconst store = new Vuex.Store<any>({});\n\n@Module\nclass MyModule extends VuexModule {\n  shouldUpdate = true;\n  text = \"\";\n\n  @Mutation\n  setText(text: string) {\n    if (this.shouldUpdate) {\n      this.text = text;\n    }\n  }\n}\n\nconst myModule = new MyModule({ store, name: \"myModule\" });\n\ndescribe(\"mutations\", () => {\n  test(\"accessor calls commit\", () => {\n    const mutationObserver = jest.fn((mutation: MutationPayload) => mutation);\n    store.subscribe(mutationObserver);\n\n    myModule.setText(\"some text\");\n\n    expect(mutationObserver.mock.calls.length).toBe(1);\n\n    const mutationPayload = mutationObserver.mock.results[0].value as MutationPayload;\n    expect(mutationPayload.type).toBe(\"myModule/setText\");\n    expect(mutationPayload.payload).toBe(\"some text\");\n  });\n\n  test(\"updates store\", () => {\n    store.commit(\"myModule/setText\", \"some other text\");\n    expect(store.state.myModule.text).toBe(\"some other text\");\n  });\n});\n"
  },
  {
    "path": "test/state.ts",
    "content": "import { Module, VuexModule } from \"../src\";\nimport Vuex from \"vuex\";\nimport Vue from \"vue\";\n\nVue.use(Vuex);\nconst store = new Vuex.Store<any>({});\n\n@Module\nclass MyModule extends VuexModule {\n  foo = {\n    text: \"some text\"\n  };\n  bar = 1;\n\n  square = (num: number) => num * num;\n}\n\nconst myModule = new MyModule({ store, name: \"myModule\" });\n\ntest(\"state\", () => {\n  expect(myModule.foo).toBe(store.state.myModule.foo);\n  expect(myModule.foo.text).toBe(\"some text\");\n\n  expect(myModule.bar).toBe(store.state.myModule.bar);\n  expect(myModule.bar).toBe(1);\n\n  expect(myModule.square).toBe(store.state.myModule.square);\n  expect(myModule.square(2)).toBe(4);\n});\n"
  },
  {
    "path": "test/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"\",\n    \"experimentalDecorators\": true,\n    \"declaration\": false\n  },\n  \"include\": [\n    \"./**/*.ts\"\n  ]\n}"
  },
  {
    "path": "test/watch.ts",
    "content": "import { Module, Mutation, Action, VuexModule } from \"../src\";\nimport Vuex from \"vuex\";\nimport Vue from \"vue\";\n\nVue.use(Vuex);\nconst store = new Vuex.Store<any>({});\n\n@Module\nclass MyModule extends VuexModule {\n  text = \"\";\n\n  get getText() {\n    return this.text;\n  }\n\n  @Mutation\n  setText(text: string) {\n    this.text = text;\n  }\n\n  @Action\n  async changeText(text: string) {\n    this.setText(text);\n  }\n}\n\nconst myModule = new MyModule({ store, name: \"myModule\" });\n\ndescribe(\"watch\", () => {\n  test(\"watch callback is called\", async () => {\n    const watchCallback = jest.fn((newValue: string, oldValue: string) => undefined);\n\n    myModule.setText(\"bar\");\n    myModule.$watch(theModule => theModule.getText, watchCallback);\n    await myModule.changeText(\"foo\");\n\n    expect(watchCallback.mock.calls.length).toBe(1);\n    expect(watchCallback.mock.calls[0].length).toBe(2);\n    expect(watchCallback.mock.calls[0][0]).toBe(\"foo\");\n    expect(watchCallback.mock.calls[0][1]).toBe(\"bar\");\n  });\n\n  test(\"watch for state changes as well\", async () => {\n    const watchCallback = jest.fn((newValue: string, oldValue: string) => undefined);\n\n    myModule.setText(\"bar\");\n    myModule.$watch(theModule => theModule.text, watchCallback);\n    await myModule.changeText(\"foo\");\n\n    expect(watchCallback.mock.calls.length).toBe(1);\n    expect(watchCallback.mock.calls[0].length).toBe(2);\n    expect(watchCallback.mock.calls[0][0]).toBe(\"foo\");\n    expect(watchCallback.mock.calls[0][1]).toBe(\"bar\");\n  });\n\n  test(\"watch should return unwatch func\", async () => {\n    const watchCallback = jest.fn((newValue: string, oldValue: string) => undefined);\n\n    myModule.setText(\"bar\");\n    const unwatch = myModule.$watch(theModule => theModule.text, watchCallback);\n    await myModule.changeText(\"foo1\");\n\n    expect(watchCallback.mock.calls.length).toBe(1);\n\n    unwatch();\n    await myModule.changeText(\"foo2\");\n\n    expect(watchCallback.mock.calls.length).toBe(1);\n  });\n});\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"module\": \"es2015\",\n    \"moduleResolution\": \"node\",\n    \"lib\": [\n      \"dom\",\n      \"es2015\"\n    ],\n    \"declaration\": true,\n    \"outDir\": \"./lib\",\n    \"strict\": true,\n\n    \"experimentalDecorators\": true\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"node_modules\", \"**/__tests__/*\"]\n}"
  },
  {
    "path": "tslint.json",
    "content": "{\n  \"extends\": [\n    \"tslint:recommended\",\n    \"tslint-config-prettier\"\n  ],\n  \"rulesDirectory\": [\"tslint-plugin-prettier\"],\n  \"rules\": {\n    \"prettier\": [true, { \"printWidth\": 120 }],\n\n    \"no-namespace\": false,\n    \"max-line-length\": false,\n    \"interface-name\": false,\n\n    \"arrow-parens\": [false],\n    \"object-literal-sort-keys\": false,\n    \"ordered-imports\": [\n      false\n    ],\n    \"member-access\": [\n      true, \"no-public\"\n    ],\n    \"max-classes-per-file\": false,\n    \"trailing-comma\": [\n      false\n    ],\n    \"interface-over-type-literal\": false,\n    \"no-console\": [false],\n    \"one-line\": false,\n    \"curly\": false,\n    \"no-empty\": [true, \"allow-empty-catch\", \"allow-empty-functions\"],\n    \"member-ordering\": false,\n    \"no-unused-expression\": false,\n    \"only-arrow-functions\": false,\n    \"ban-types\": [true, \"Function\"],\n    \"variable-name\": false\n  },\n  \"defaultSeverity\": \"warning\"\n}"
  }
]