Skip to content

Commit

Permalink
ADD inbuild container and module injection support
Browse files Browse the repository at this point in the history
  • Loading branch information
Sascha Braun committed Oct 5, 2018
1 parent b4988a3 commit 637e9c1
Show file tree
Hide file tree
Showing 23 changed files with 410 additions and 5,025 deletions.
48 changes: 0 additions & 48 deletions .circleci/config.yml

This file was deleted.

11 changes: 11 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
root = true

[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
# editorconfig-tools is unable to ignore longs strings or urls
max_line_length = null
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ coverage
*.log

package-lock.json
yarn.lock
yarn.lock
6 changes: 4 additions & 2 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ tslint.json
.prettierignore
.vscode
build/docs
example
tests
**/*.spec.*
coverage
.nyc_output
*.log
.circleci
.editorconfig

package-lock.json
yarn.lock
yarn.lock
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# package.json is formatted by package managers, so we ignore it here
package.json
package.json
README.md
182 changes: 90 additions & 92 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,42 @@

A simpler way to write your Vuex store in Typescript

## TO DO
## Usage

**Note:** this module is still in development and the API may change in later versions</br>
1. Install module:

- Inbuild Container support to allow module injection in Vuejs components
`npm install vuex-simple --save`

## Getting Started
2. Install reflect-metadata package:

### Installing
`npm install reflect-metadata --save`

Install the package with npm:
and import it somewhere in the global place of your app before any service declaration or import (for example in app.ts):

```
npm install vuex-simple
```
`import "reflect-metadata";`

If you use yarn:
3. Enabled following settings in tsconfig.json:

```
yarn add vuex-simple
```json
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
```

### Example
**Note:** *vuex-simple* uses the Container from [typedi](http://github.com/pleerock/typedi).


## Example

#### Module

```ts
// modules/counter.ts
// store/modules/counter.ts

import { Mutation, Module, Getter, State } from 'vuex-simple';

@Module('counter')
class MyCounter {
class CounterModule {

@State()
public counter: number = 0;

Expand All @@ -57,8 +60,6 @@ class MyCounter {
this.counter += nb;
}

// You can also add @Action to transform the function to a store action that will be dispatched on call, but it's not really necessary
// @Action()
public async asyncIncrement() {
await new Promise(r => setTimeout(r, 500));
// simply call mutation function like you would any other function
Expand All @@ -70,128 +71,125 @@ class MyCounter {
#### Store

```ts
// store.ts
// store/index.ts

import Vue from 'vue';

import VuexSimple, { getStoreBuilder } from 'vuex-simple';

import MyCounter from './modules/counter';

// simply instantiate to add module to the store builder singleton
const myCounter = new MyCounter();
import CounterModule from './modules/counter';

Vue.use(VuexSimple);

const store = getStoreBuilder().create();

// simply use mutations or actions as standard functions
// your editor should be able to autocomplete everything
myCounter.increment();
myCounter.incrementBy(10);
const storeBuilder = getStoreBuilder();
storeBuilder.loadModules([
CounterModule
]);
const store = storeBuilder.create();

myCounter.asyncIncrement();
export default store;

// call vuex getter
myCounter.myGetter;
```

### Features
#### Usage

#### Module
To create a module, we declare a new class and decorate it with `@Module(namespace)`
```ts
// In your vue component

#### State
To tell the module which properties of the class will compose the state of the vuex module, we need to decorate those properties with `@State()`
import { Container, Inject } from 'vuex-simple';
import CounterModule from '@/store/modules/counter';

#### Getter
To add a getter, we simply write a normal getter and add a `@Getter()` decorator to it.
@Component
export default class MyComponent extends Vue {

#### Mutation
To add a mutation, we simply write a normal function and add a `@Mutation()` decorator to it. For now, mutations can only have at most 1 parameter.
@Inject()
public counterModule!: CounterModule;

#### Action
To add an action, we simply write a normal function and add a `@Action()` decorator to it. As for mutations, actions can, for now, only have at most 1 parameter.
public get readState() {
// access state like a property
return this.counterModule.counter;
}

**Note on actions:** vuex use actions to do their async stuff, but we don't really need an action for that, a simple function that can call our mutations is all we need, as shown above.</br>
So for now `@Action` is still included, but it may happen that it is removed in later versions.
public get readGetter() {
// access getter like a property
return this.counterModule.myGetter;
}

#### How to setup your store
public commitIncrement() {
// call mutation like a function
this.counterModule.increment();
}

1. Use `Vue.use(VuexSimple)` to load vuex
2. Instantiate all our modules **once** (can also be before step 1)
public commitIncrementBy(number: id) {
// call with parameter / payload
this.counterModule.incrementBy(10);
}

**Warning:** For now, if you instantiate a module multiple times, it will cause quite a lot of problems, so be warned!
public callAction() {
counterModule.asyncIncrement();
}

3. (optional) Add your existing vuex modules: they will still work normally
}

```ts
const storeBuilder = getStoreBuilder();
storeBuilder.addModule(namespace: string, module: Vuex.Module);
```
// Outside of a Vue component, you can also use Container to access the module
const counterModule = Container.get(CounterModule);

4. We finish by creating the store with `storeBuilder.create()`

**Note:** We can't configure the root of the store **for now**. The store is also set to use strict mode by default.
```

## Features

#### Module

### Usage of a Container
To create a module, we declare a new class and decorate it with `@Module(namespace)`

For now, there is no container included by default by *vuex-simple*, so I recommand you to use [typedi](http://github.com/pleerock/typedi) if you want to use one. You will be able to easily inject your modules / services where you need them.
#### Inject

#### Module
Inject another module or service in your module with `@Inject()`. This feature will enable you to easily split up your code across multiple files in a logic way.

```ts
// modules/counter.ts
#### State

import { Container, Service } from 'typedi';
import Vue from 'vue';
To tell the module which properties of the class will compose the state of the vuex module, we need to decorate those properties with `@State()`

import { Mutation, Module, State } from 'vuex-simple';
#### Getter

@Service()
@Module('counter')
class MyCounter {
@State()
public counter: number = 0;
To add a getter, we simply write a normal getter and add a `@Getter()` decorator to it.

@Mutation()
public increment() {
this.counter++;
}
#### Mutation

public async asyncIncrement() {
await new Promise(r => setTimeout(r, 500));
this.increment();
}
}
```
To add a mutation, we simply write a normal function and add a `@Mutation()` decorator to it. For now, mutations can only have at most 1 parameter.

#### Store
#### Action

```ts
// store.ts
To add an action, we simply write a normal function and add a `@Action()` decorator to it. As for mutations, actions can, for now, only have at most 1 parameter.

import Vue from 'vue';
**Note on actions:** vuex use actions to do their async stuff, but we don't really need an action for that, a simple function that can call our mutations is all we need, as shown above.</br>
So for now `@Action` is still included, but it may happen that it is removed in later versions.

import VuexSimple, { getStoreBuilder } from 'vuex-simple';
#### How to setup your store

import MyCounter from './modules/counter';
1. Use `Vue.use(VuexSimple)`
2. Use the StoreBuilder to load your modules

// we need to get the module once so that typedi instantiates it for us
const myCounter = Container.get(MyCounter);
```ts
const storeBuilder = getStoreBuilder();
storeBuilder.loadModules([
CounterModule
]);
```

Vue.use(VuexSimple);
3. (optional) Add your existing vuex modules: they will still work normally

```ts
const storeBuilder = getStoreBuilder();
storeBuilder.create();
storeBuilder.addModule(namespace: string, module: Vuex.Module);
```

// simply use as you would normally do
myCounter.increment();
4. We finish by creating the store with `storeBuilder.create()`


**Note:** We can't configure the root of the store **for now**. The store is also set to use strict mode by default.

myCounter.asyncIncrement();
```

## Contributors

Expand Down
Loading

0 comments on commit 637e9c1

Please sign in to comment.