{"id":13623391,"url":"https://github.com/championswimmer/vuex-module-decorators","last_synced_at":"2025-05-14T08:07:14.652Z","repository":{"id":37493362,"uuid":"131648824","full_name":"championswimmer/vuex-module-decorators","owner":"championswimmer","description":"TypeScript/ES7 Decorators to create Vuex modules declaratively","archived":false,"fork":false,"pushed_at":"2023-09-01T21:32:24.000Z","size":2524,"stargazers_count":1791,"open_issues_count":142,"forks_count":169,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-05-01T12:46:19.367Z","etag":null,"topics":["javascript","typescript","vue","vuejs","vuex","vuex-modules"],"latest_commit_sha":null,"homepage":"https://championswimmer.in/vuex-module-decorators/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/championswimmer.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"github":["championswimmer"],"patreon":"championswimmer","open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":"championswimmer","issuehunt":null,"otechie":null,"custom":null}},"created_at":"2018-04-30T21:33:14.000Z","updated_at":"2025-04-11T01:52:17.000Z","dependencies_parsed_at":"2024-01-29T10:09:22.844Z","dependency_job_id":"a53d98cc-abcc-41f3-87d2-b7de0b4b52e3","html_url":"https://github.com/championswimmer/vuex-module-decorators","commit_stats":{"total_commits":266,"total_committers":39,"mean_commits":6.82051282051282,"dds":0.3308270676691729,"last_synced_commit":"f54a970f694d42e503a2ad435e456dcb1c60445d"},"previous_names":[],"tags_count":53,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/championswimmer%2Fvuex-module-decorators","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/championswimmer%2Fvuex-module-decorators/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/championswimmer%2Fvuex-module-decorators/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/championswimmer%2Fvuex-module-decorators/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/championswimmer","download_url":"https://codeload.github.com/championswimmer/vuex-module-decorators/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253720272,"owners_count":21953009,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","typescript","vue","vuejs","vuex","vuex-modules"],"created_at":"2024-08-01T21:01:31.253Z","updated_at":"2025-05-14T08:07:09.635Z","avatar_url":"https://github.com/championswimmer.png","language":"TypeScript","funding_links":["https://github.com/sponsors/championswimmer","https://patreon.com/championswimmer","https://liberapay.com/championswimmer","https://www.patreon.com/user/creators?u=37365136"],"categories":["TypeScript","Components \u0026 Libraries","vuejs","Utilities","Utilities [🔝](#readme)"],"sub_categories":["Utilities","Typescript"],"readme":"# vuex-module-decorators\n\n[![Usage Guide](https://img.shields.io/badge/usage-guide-1e90ff.svg?style=for-the-badge\u0026longCache=true)](https://championswimmer.in/vuex-module-decorators/)\nDetailed Guide: https://championswimmer.in/vuex-module-decorators/\n\nTypescript/ES7 Decorators to make Vuex modules a breeze\n\n[![Build Status](https://travis-ci.org/championswimmer/vuex-module-decorators.svg?branch=master)](https://travis-ci.org/championswimmer/vuex-module-decorators)\n[![npm:size:gzip](https://img.shields.io/bundlephobia/minzip/vuex-module-decorators.svg?label=npm:size:gzip)](https://bundlephobia.com/result?p=vuex-module-decorators)\n[![cdn:min:gzip](https://img.badgesize.io/https://cdn.jsdelivr.net/npm/vuex-module-decorators.svg?label=cdn:min:gzip\u0026compression=gzip)](https://cdn.jsdelivr.net/npm/vuex-module-decorators/dist/cjs/index.min.js)\n[![codecov](https://codecov.io/gh/championswimmer/vuex-module-decorators/branch/master/graph/badge.svg)](https://codecov.io/gh/championswimmer/vuex-module-decorators)\n[![npm](https://img.shields.io/npm/v/vuex-module-decorators.svg)](https://www.npmjs.com/package/vuex-module-decorators)\n[![npm](https://img.shields.io/npm/dw/vuex-module-decorators.svg?colorB=ff0033)](https://www.npmjs.com/package/vuex-module-decorators)\n![npm type definitions](https://img.shields.io/npm/types/vuex-module-decorators.svg)\n[![Maintainability](https://api.codeclimate.com/v1/badges/5b1dfa8d3d4bdf409b60/maintainability)](https://codeclimate.com/github/championswimmer/vuex-module-decorators/maintainability)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/b7944c579d5c4c1d949f71a91a538d77)](https://www.codacy.com/app/championswimmer/vuex-module-decorators?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=championswimmer/vuex-module-decorators\u0026utm_campaign=Badge_Grade)\n[![codebeat badge](https://codebeat.co/badges/0272746c-8a7d-428b-a20d-387d22bfbcfb)](https://codebeat.co/projects/github-com-championswimmer-vuex-module-decorators-master)\n[![Total alerts](https://img.shields.io/lgtm/alerts/g/championswimmer/vuex-module-decorators.svg?logo=lgtm\u0026logoWidth=18)](https://lgtm.com/projects/g/championswimmer/vuex-module-decorators/alerts/)\n[![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/championswimmer/vuex-module-decorators.svg?logo=lgtm\u0026logoWidth=18)](https://lgtm.com/projects/g/championswimmer/vuex-module-decorators/context:javascript)\n\n## Patrons\nWhile I have a day job and I really maintain open source libraries for fun, any sponsors are extremely graciously thanked for their contributions, and goes a long way 😇 ❤️\n\n- [Thomas Woo](https://www.patreon.com/user/creators?u=37365136)\n\n## CHANGELOG\n\n- There are major type-checking changes (could be breaking) in v0.9.7\n\n- There are major usage improvements (non backwards compatible) in 0.8.0\n\nPlease check [CHANGELOG](CHANGELOG.md)\n\n## Examples\n\nRead the rest of the README to figure out how to use, or if you readily want to jump into a production codebase and see how this is used, you can check out -\n\n- \u003chttps://github.com/Armour/vue-typescript-admin-template\u003e\n- \u003chttps://github.com/xieguangcai/vue-order-admin\u003e\n- \u003chttps://github.com/coding-blocks-archives/realworld-vue-typescript\u003e\n\n## Installation\n\n```shell\nnpm install -D vuex-module-decorators\n```\n\n### Babel 6/7\n\n\u003e **NOTE** This is **not** necessary for `vue-cli@3` projects, since `@vue/babel-preset-app` already includes this plugin\n\n1. You need to install `babel-plugin-transform-decorators`\n\n### TypeScript\n\n1. set `experimentalDecorators` to true\n2. For reduced code with decorators, set `importHelpers: true` in `tsconfig.json`\n3. _(only for TypeScript 2)_ set `emitHelpers: true` in `tsconfig.json`\n\n## Configuration\n\n### Using with `target: es5`\n\n\u003e **NOTE** Since version `0.9.3` we distribute as ES5, so this section is applicable only to v0.9.2 and below\n\nThis package generates code in `es2015` format. If your Vue project targets ES6 or ES2015 then\nyou need not do anything. But in case your project uses `es5` target (to support old browsers), then\nyou need to tell Vue CLI / Babel to transpile this package.\n\n```js\n// in your vue.config.js\nmodule.exports = {\n  /* ... other settings */\n  transpileDependencies: ['vuex-module-decorators']\n}\n```\n\n## Usage\n\n#### The \u003cstrike\u003econventional\u003c/strike\u003e old \u0026 boring way\n\nRemember how vuex modules used to be made ?\n\n```js\nconst moduleA = {\n  state: { ... },\n  mutations: { ... },\n  actions: { ... },\n  getters: { ... }\n}\n\nconst moduleB = {\n  state: { ... },\n  mutations: { ... },\n  actions: { ... }\n}\n\nconst store = new Vuex.Store({\n  modules: {\n    a: moduleA,\n    b: moduleB\n  }\n})\n```\n\n#### Hello Decorators !\n\nWell not anymore. Now you get better syntax. Inspired by `vue-class-component`\n\n```typescript\nimport { Module, VuexModule, Mutation, Action } from 'vuex-module-decorators'\n\n@Module\nexport default class Counter2 extends VuexModule {\n  count = 0\n\n  @Mutation\n  increment(delta: number) {\n    this.count += delta\n  }\n  @Mutation\n  decrement(delta: number) {\n    this.count -= delta\n  }\n\n  // action 'incr' commits mutation 'increment' when done with return value as payload\n  @Action({ commit: 'increment' })\n  incr() {\n    return 5\n  }\n  // action 'decr' commits mutation 'decrement' when done with return value as payload\n  @Action({ commit: 'decrement' })\n  decr() {\n    return 5\n  }\n}\n```\n\n#### async MutationAction === magic\n\nWant to see something even better ?\n\n```typescript\nimport { Module, VuexModule, MutationAction } from 'vuex-module-decorators'\nimport { ConferencesEntity, EventsEntity } from '@/models/definitions'\n\n@Module\nexport default class HGAPIModule extends VuexModule {\n  conferences: Array\u003cConferencesEntity\u003e = []\n  events: Array\u003cEventsEntity\u003e = []\n\n  // 'events' and 'conferences' are replaced by returned object\n  // whose shape must be `{events: [...], conferences: [...] }`\n  @MutationAction({ mutate: ['events', 'conferences'] })\n  async fetchAll() {\n    const response: Response = await getJSON('https://hasgeek.github.io/events/api/events.json')\n    return response\n  }\n}\n```\n\n#### Automatic getter detection\n\n```typescript\n@Module\nclass MyModule extends VuexModule {\n  wheels = 2\n\n  @Mutation\n  incrWheels(extra) {\n    this.wheels += extra\n  }\n\n  get axles() {\n    return this.wheels / 2\n  }\n}\n```\n\nthis is turned into the equivalent\n\n```javascript\nconst module = {\n  state: { wheels: 2 },\n  mutations: {\n    incrWheels(state, extra) {\n      state.wheels += extra\n    }\n  },\n  getters: {\n    axles: (state) =\u003e state.wheels / 2\n  }\n}\n```\n\n## Parameters inside a getter\n\nIn order to handle parameters, simply return a function like so:\n\n```\nget getUser() { \n  return function (id: number) { \n    return this.users.filter(user =\u003e user.id === id)[0];\n  }\n}\n``` \n\n### Putting into the store\n\nUse the modules just like you would earlier\n\n```typescript\nimport Vue from 'nativescript-vue'\nimport Vuex, { Module } from 'vuex'\n\nimport counter from './modules/Counter2'\nimport hgapi from './modules/HGAPIModule'\n\nVue.use(Vuex)\n\nconst store = new Vuex.Store({\n  state: {},\n  modules: {\n    counter,\n    hgapi\n  }\n})\n```\n\n### Module re-use, use with NuxtJS\n\nIf you need to support [module reuse](https://vuex.vuejs.org/guide/modules.html#module-reuse)\nor to use modules with NuxtJS, you can have a state factory function generated instead\nof a static state object instance by using `stateFactory` option to `@Module`, like so:\n\n```typescript\n@Module({ stateFactory: true })\nclass MyModule extends VuexModule {\n  wheels = 2\n\n  @Mutation\n  incrWheels(extra) {\n    this.wheels += extra\n  }\n\n  get axles() {\n    return this.wheels / 2\n  }\n}\n```\n\nthis is turned into the equivalent\n\n```javascript\nconst module = {\n  state() {\n    return { wheels: 2 }\n  },\n\n  mutations: {\n    incrWheels(state, extra) {\n      state.wheels += extra\n    }\n  },\n  getters: {\n    axles: (state) =\u003e state.wheels / 2\n  }\n}\n```\n\n### Dynamic Modules\n\nVuex allows us to register modules into store at runtime after store is\nconstructed. We can do the following to create dynamic modules\n\n```typescript\ninterface StoreType {\n  mm: MyModule\n}\n// Declare empty store first\nconst store = new Vuex.Store\u003cStoreType\u003e({})\n\n// Create module later in your code (it will register itself automatically)\n// In the decorator we pass the store object into which module is injected\n// NOTE: When you set dynamic true, make sure you give module a name\n@Module({ dynamic: true, store: store, name: 'mm' })\nclass MyModule extends VuexModule {\n  count = 0\n\n  @Mutation\n  incrCount(delta) {\n    this.count += delta\n  }\n}\n```\n\nIf you would like to preserve the state e.g when loading in the state from [vuex-persist](https://www.npmjs.com/package/vuex-persist)\n\n```diff\n...\n\n-- @Module({ dynamic: true, store: store, name: 'mm' })\n++ @Module({ dynamic: true, store: store, name: 'mm', preserveState: true })\nclass MyModule extends VuexModule {\n\n...\n```\n\nOr when it doesn't have a initial state and you load the state from the localStorage\n\n```diff\n...\n\n-- @Module({ dynamic: true, store: store, name: 'mm' })\n++ @Module({ dynamic: true, store: store, name: 'mm', preserveState: localStorage.getItem('vuex') !== null })\nclass MyModule extends VuexModule {\n\n...\n```\n\n### Accessing modules with NuxtJS\n\nThere are many possible ways to construct your modules. Here is one way for drop-in use with NuxtJS (you simply need to add your modules to `~/utils/store-accessor.ts` and then just import the modules from `~/store`):\n\n`~/store/index.ts`:\n\n```typescript\nimport { Store } from 'vuex'\nimport { initialiseStores } from '~/utils/store-accessor'\nconst initializer = (store: Store\u003cany\u003e) =\u003e initialiseStores(store)\nexport const plugins = [initializer]\nexport * from '~/utils/store-accessor'\n```\n\n`~/utils/store-accessor.ts`:\n\n```typescript\nimport { Store } from 'vuex'\nimport { getModule } from 'vuex-module-decorators'\nimport example from '~/store/example'\n\nlet exampleStore: example\n\nfunction initialiseStores(store: Store\u003cany\u003e): void {\n  exampleStore = getModule(example, store)\n}\n\nexport { initialiseStores, exampleStore }\n```\n\nNow you can access stores in a type-safe way by doing the following from a component or page - no extra initialization required.\n\n```typescript\nimport { exampleStore } from '~/store'\n...\nsomeMethod() {\n  return exampleStore.exampleGetter\n}\n```\n\n### Using the decorators with ServerSideRender\n\nWhen SSR is involved the store is recreated on each request. Every time the module is accessed\nusing `getModule` function the current store instance must be provided and the module must\nbe manually registered to the root store modules\n\n#### Example\n\n```typescript\n// store/modules/MyStoreModule.ts\nimport { Module, VuexModule, Mutation } from 'vuex-module-decorators'\n\n@Module({\n  name: 'modules/MyStoreModule',\n  namespaced: true,\n  stateFactory: true,\n})\nexport default class MyStoreModule extends VuexModule {\n  public test: string = 'initial'\n\n  @Mutation\n  public setTest(val: string) {\n    this.test = val\n  }\n}\n\n\n// store/index.ts\nimport Vuex from 'vuex'\nimport MyStoreModule from '~/store/modules/MyStoreModule'\n\nexport function createStore() {\n  return new Vuex.Store({\n    modules: {\n      MyStoreModule,\n    }\n  })\n}\n\n// components/Random.tsx\nimport { Component, Vue } from 'vue-property-decorator';\nimport { getModule } from 'vuex-module-decorators';\nimport MyStoreModule from '~/store/modules/MyStoreModule'\n\n@Component\nexport default class extends Vue {\n    public created() {\n        const MyModuleInstance = getModule(MyStoreModule, this.$store);\n        // Do stuff with module\n        MyModuleInstance.setTest('random')\n    }\n}\n```\n\n## Configuration\n\nThere is a global configuration object that can be used to set options across the\nwhole module:\n\n```typescript\nimport { config } from 'vuex-module-decorators'\n// Set rawError to true by default on all @Action decorators\nconfig.rawError = true\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchampionswimmer%2Fvuex-module-decorators","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchampionswimmer%2Fvuex-module-decorators","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchampionswimmer%2Fvuex-module-decorators/lists"}