Giter Site home page Giter Site logo

sascha245 / vuex-simple Goto Github PK

View Code? Open in Web Editor NEW
180.0 180.0 15.0 151 KB

A simpler way to write your Vuex store in Typescript

License: MIT License

TypeScript 92.08% JavaScript 5.37% HTML 2.55%
typescript vue vuejs vuex vuex-class vuex-decorators vuex-modules

vuex-simple's People

Contributors

collinestes avatar sascha245 avatar sobolevn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vuex-simple's Issues

Method style access getters

  • I'm submitting a ...
    [ ] bug report
    [ ] feature request
    [ ] question about the decisions made in the repository
    [x] question about how to use this project

  • Summary
    How does one define a method style getter?

  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. StackOverflow, personal fork, etc.)

I tried doing a simple

    @Getter()
    public getNumberButIncreased(someNumber) {
        return someNumber + 1;
    }

but that gives me the following error:
{code: "getter_not_found", message: "Could not find getter "getNumberButIncreased" for module SomeModule", params: {…}} code: "getter_not_found" message: "Could not find getter "getNumberButIncreased" for module SomeModule" params: className: "SomeModule" propertyName: "getNumberButIncreased" } }

As far as I can see, the code always assumes that a @getter will actually always be a getter field and never a function.

registering a submodule dynamically

  • I'm submitting a ...
    [ ] bug report
    [ ] feature request
    [ ] question about the decisions made in the repository
    [x] question about how to use this project

  • Summary
    how does one register a module that is defined using typescript classes dynamically?
    https://vuex.vuejs.org/guide/modules.html#dynamic-module-registration
    This is specifically for use with JS Vue components, that have not yet been converted to vue-class-component TS components.

  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. StackOverflow, personal fork, etc.)

importing the class based submodule and registering it to the store using the registerModule method does not seem to work.

import { SomeVuexModule } from '@store/modules/some-module';
beforeCreate() {
this.$store.registerModule('someModule', SomeVuexModule);
}

or

import { SomeVuexModule } from '@store/modules/some-module';
beforeCreate() {
this.$store.registerModule('someModule', new SomeVuexModule());
}

I think that's because registerModule requires a raw (already mapped) module, but I do not know how to get one from the class based submodule.

Unit test practices

  • I'm submitting a ...
    [ ] bug report
    [ ] feature request
    [ ] question about the decisions made in the repository
    [x] question about how to use this project

  • Summary

What are the best practices to unit tests projects with vuex-simple?
I am taking about several topics:

  1. Providing some state for the tests to run on; like here: https://github.com/wemake-services/wemake-vue-template/blob/master/template/tests/pages/index.spec.ts#L17
  2. Mocking actions, getters, mutations; like here: https://github.com/wemake-services/wemake-vue-template/blob/master/template/tests/components/action-bar.spec.ts#L15
  3. Creating test doubles for the actual store that is mounted with mount() from vue-test-utils; like here: https://github.com/wemake-services/wemake-vue-template/blob/master/template/tests/fixtures/vuex.ts#L34

Would be awesome to cover this things and to create a testing guide.

registerModule from Action

  • I'm submitting a ...
    [ ] bug report
    [x] feature request
    [ ] question about the decisions made in the repository
    [x] question about how to use this project

  • Summary
    I would like to program an Action that registers a dynamic module. Is there a way to get the Store<any> object that must be passed to registerModule from within the Action, e.g. something like this.$store?

  • Other information
    I guess the way to implement it would be to let modules extend a base class that provides access to the vuex store (after being created by createVuexStore)

Is there a way to split the module into files?

  • I'm submitting a ...
    [ ] bug report
    [ ] feature request
    [ ] question about the decisions made in the repository
    [X ] question about how to use this project

  • Summary
    I have a rather large module that I'm currently splitting into separate classes - state, mutations, getters, and actions - and then bringing them together as a Vuex Module object for readability purposes. Do you have any recommendations for doing the same with vuex-simple? I was reading up on Typescript partial types, but not 100% sure if that's the best route.

Thanks!

  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. StackOverflow, personal fork, etc.)

Getters in modules are only reactive to a single state variable in that module

  • I'm submitting a ...
    [ X ] bug report

  • Summary

Getters in modules are only reactive to a single state variable of the module.

  • Other information

Steps to reproduce:

export class MyModule {

  @State()
  public a: number;
  public b: number;

  public constructor(nb: number = 1, nb2: number = 2) {
    this.a = nb2
    this.b = nb;
  }

  @Mutation()
  public setA(nb: number) {
    this.a = nb;
  }

  @Mutation()
  public setB(nb: number) {
    this.b = nb;
  }

  @Getter()
  public get sumAB() {
    return this.a + this.b
  }
}

In Chrome dev console:
Screen Shot 2020-02-11 at 12 41 04 PM

Although setB is correctly setting the state of "b", the value of sumAB will only be recomputed when the state of "a" has changed.

No matter what, getters in modules can only be reactive to a single piece of state in that module.

Note that, if the code above is placed in the store root instead of a module, it will run as expected, being reactive to both "a" and "b" state.

`@Inject()` decorator doesn't work with class inheritance?

  • I'm submitting a ...
    [x] bug report
    [ ] feature request
    [ ] question about the decisions made in the repository
    [ ] question about how to use this project

  • Summary

// base.ts
@Component({})
export default class BaseMini<T> extends Vue {
  get localEntity(): T | undefined {
    return this.entityModule.get(this.entityId);
  }

  @Inject()
  public entityModule!: EntityModule;

  // ...
}

// artifact.ts
@Component({})
export default class ArtifactMini extends BaseMini<IArtifact> {
  // ...
}

Given the above component definitions, when attempting to use the ArtifactMini component, this.entityModule is never assigned.

Major update 2.0.0

Hi everyone,

Being not very familiar with github and not knowing where else to put it, I will post my announce here.

I will probably make a new major version soon (in the next 1-2 weeks) to cleanup unnessecary and deprecated features, as it becomes more and more difficult to add new useful features without first removing the older parts from the codebase.

That is why I will first ask once if the changes seem meaningful (or not) or if there are important features I am missing.

Here the planned changes:

  • Remove typedi / dependency injection by default, as it is not the main concern of this library.
    That way, you will also be able to choose the DI library you want to use (if you want to use one).

  • The modules stay the same, with just the @Module decorator changing its role: It is now used to declare submodules. We don't need to attach the decorator to the class anymore.

class FooModule {

	@State()
	public counter = 0;

	constructor(nb: number) {
		this.counter = nb;
	}

	@Mutation()
	public setCounter(counter: number) {
		this.counter = counter;
	}

	// use as previously
	...
}

class BarModule {

      	// property name becomes module namespace
	@Module()
	public foo1 = new FooModule(5);
	
	@Module()
	public foo2 = new FooModule(7);

	@Getter()
	public get totalCount() {
		return this.fooModule1.counter + this.foo2.counter;
	}

	// use as previously
        ...
}
  • The store will in the end also be build from a module, this also allows us to type the root of our store.
    As we don't use a DI library anymore, we can also easily create multiple stores without having to worry about having multiple instances of a same module.
class MyStore {
	
	@Module()
	public bar1 = new BarModule();
	
	@Module()
	public bar2 = new BarModule();

	@State()
	public version = "1.0.0";
}

const store = createVuexStore(new MyStore(), {
	strict: false,
	modules: {},
	plugins: []
});
  • The usage doesn't change a lot either, but instead of using a container and injecting our modules, we simply use @Store to access our typed root module that will be somewhere within this.$store.
class MyComponent extends Vue {
	
	// get the root module of the store	
	@Store()
	public store!: MyStore;

	// get module by its namespace
	// Note: it is better to store namespaces in an enum or somewhere else to refactor with more ease
	@Store("bar1/foo1")
	public foo1Module!: FooModule;

	// get modules from the root module instance
	public get bar1foo2() {
		return this.store.bar1.foo2; // everything is typed naturally
	}

	// simply use as previously
}

Once again, don't hesitate to tell me what you think about these changes and if they seem meaningful or not.

I wish you a good evening,

Sascha

Generate store type from `vuex-simple`

  • I'm submitting a ...
    [ ] bug report
    [x] feature request
    [x] question about the decisions made in the repository
    [x] question about how to use this project

  • Summary

There are cases where you need Store<StateType> directly.
And there's no way to write it.

When we use vuex-simple we write classes instead of a regular Store, and we do not have this StateType, since it is bundled with other methods, getters, etc.

What do I suggest?

import { State, Module, StateTypeOf } from 'vuex-simple'

class CommentsModule {
  @State()
  public comments: CommentType[] = []
}

class TypedStore {
  @Module()
  public comments = new CommentsModule()
}

type StateType = StateTypeOf<typeof TypedStore>

And later it can be used for Store<StateType>. This way we have the best from the bosth worlds. Native types and no code duplication.

Similar approach: https://github.com/gcanti/io-ts#typescript-integration

Access to local state and rootState within modules

  • I'm submitting a ...
    [ ] bug report
    [ ] feature request
    [ ] question about the decisions made in the repository
    [x] question about how to use this project

  • Summary
    By default, Vuex offers access to a local state within modules. Is there a way to access the local state within modules in vuex-simple as well? For example inside an action function you can get access to state or rootState, as can be seen in the Vuex docs...

  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. StackOverflow, personal fork, etc.)
    Link to Vuex docs: https://vuex.vuejs.org/guide/modules.html

Adding vuex-simple sub module to existing native vuex store implementation

  • I'm submitting a ...
    [ ] bug report
    [ ] feature request
    [ ] question about the decisions made in the repository
    [ X] question about how to use this project

  • Summary
    I'm trying to use this project to start building out new submodules for an existing app I have. But there doesn't seem to be any guide as to how to do this, and my attempts have thus far failed with errors like 'typeof SubModule' has no properties in common with type 'Module<any, any>'

  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. StackOverflow, personal fork, etc.)

No sync between the store properties and tokens

  • I'm submitting a ...
    [ ] bug report
    [ ] feature request
    [X ] question about the decisions made in the repository
    [ ] question about how to use this project

Hi @sascha245

In the new release I found that there is a place for mistake when using the tokens.
A developer can set the store name and have the wrong token defined.

see this example :

//tokens.ts
export default {
  BAR: new Token('bar'),
  BAR_FOO1: new Token('bar/foo1'),
  BAR_FOO3: new Token('bar/foo2')
};
//index.ts
Container.set(store.bar.foo1, tokens.BAR_FOO1);
Container.set(store.bar.foo3, tokens.BAR_FOO3);

here there should be an exception thrown due to a difference between the token string and the store structure.
Can there be a wat to define it only once instead of twice (in the store and in the tokens) so it will have less room for mistakes.

nested modules

  • I'm submitting a ...
    [ ] bug report
    [ ] feature request
    [ ] question about the decisions made in the repository
    [ X ] question about how to use this project

  • Summary

I would like to know if there is a way to have a nested modules, as you can find here : https://vuex.vuejs.org/guide/modules.html

  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. StackOverflow, personal fork, etc.)

@Inject decorator doesn't seem to work

The @Inject decorator doesn't seem to work (at least not on a component, which is where I'm testing it).

Just a stab in the dark, but I wonder if this is possibly related to replacing your custom decorator with typedi's decorator in PR #4?

/// SimpleModule.ts

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

@Module('simple')
export default class SimpleModule
{
    @State() surname = "Baggins";

    @Getter()
    public get formalName()
    {
        return `Mr. ${this.surname}`
    }

    @Mutation()
    public changeName(newName: string)
    {
        this.surname = newName;
    }
}

/// RootComponent.ts
import { Inject } from "typedi";
import Component from "vue-class-component";
import Vue from "vue";
import SimpleModule from "./store/simple/SimpleModule";

@Component({
    template: `
<div style='background: aliceblue; width: 80%; min-height: 100px'>
    {{ formalName }}
</div>
`})
export default class RootComponent extends Vue
{
    /// THIS PROPERTY IS "undefined"
    @Inject()
    simpleModule: SimpleModule

    get formalName() {
        return this.simpleModule.formalName
    }
}

Error when using Vue component with module injection

  • I'm submitting a ...
    [X ] bug report
    [ ] feature request
    [ ] question about the decisions made in the repository
    [ ] question about how to use this project

Hi @sascha245

Please see that in the docs you have

Container.set(instance.bar, tokens.BAR);
Container.set(instance.bar.foo1, tokens.BAR_FOO1);
Container.set(instance.bar.foo2, tokens.BAR_FOO2);

and in the example code it is

Container.set(tokens.MY, instance.my);
Container.set(tokens.TEST, instance.test);
Container.set(tokens.TEST_MY1, instance.test.my1);
Container.set(tokens.TEST_MY2, instance.test.my2);

I belive that the docs are wrong

Edge error 'Expected identifier, string or number'

[ x ] bug report
[ ] feature request
[ ] question about the decisions made in the repository
[ ] question about how to use this project

In Edge browser, using the store does not work. Error sending to:

/*!*************************************************************!*\
  !*** ./node_modules/vuex-simple/build/src/store-builder.js ***!
  \*************************************************************/
/*! exports provided: StoreBuilder, getStoreBuilder */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

==>"use strict";
eval("__webpack_require__.r

index.ts

import Vue from 'vue';

import VuexSimple, { getStoreBuilder } from 'vuex-simple';
import { SearchModule } from './modules/search';

Vue.use(VuexSimple);

const storeBuilder = getStoreBuilder();
storeBuilder.initialize({
    modules: {},
    strict: false,
});
storeBuilder.loadModules([SearchModule]);

const store = storeBuilder.create();

export default store;

use strict mode

  • I'm submitting a ...
    [ ] bug report
    [x ] feature request
    [ ] question about the decisions made in the repository
    [ ] question about how to use this project

  • Summary

  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. StackOverflow, personal fork, etc.)

Hi @sascha245 - first off, great implementation of vuex type support in stores and in components. It seems to be hard for must libraries to make this work great.
However we need to run our store with strict mode = false for performance concerns - are you working on implementing this as a configurable parameter or shall i do this in a pull request ?

nuxt context combined inject

I'm submitting a ...
[ ] bug report
[x] feature request
[ ] question about the decisions made in the repository
[x] question about how to use this project

Summary
When using vuex-simple with nuxt - the store has to be integrated via 'classical mode'
https://nuxtjs.org/guide/vuex-store/#classic-mode
see #12
First issue: the classical mode is deprecated for Nuxt 3
Second issue: nuxt provides 'combined inject' for its store modules
https://nuxtjs.org/guide/plugins#combined-inject
which allows to define & inject objects/functions into SFC & the vuex store, used e.g. by the axios-plugin to access the configured axios instance in module actions this.$axios.

So not sure what my question really is :-)
I'm not necessarily expecting all of those nuxt specific issues solved by vuex-simple - but as it's a really nice project I'd love to use it with nuxt... so I wanted to start a discussion on how nuxt support could be improved vs. just highlight the limitations I run into with the current state (2.1.0).

(I might be able to provide an example app in a few days once the nuxt <> TS support has been finalised)

Working setup with Nuxt?

  • I'm submitting a ...
    [ ] bug report
    [ ] feature request
    [ ] question about the decisions made in the repository
    [x ] question about how to use this project

  • Summary
    Hi, has someone already got a working integration with nuxt (v2.*)?

Help with error: Uncaught X: Cannot inject value into "Object.entityModule". Please make sure you setup reflect-metadata properly and you don't use interfaces without service tokens as injection value.

  • I'm submitting a ...
    [ ] bug report
    [ ] feature request
    [ ] question about the decisions made in the repository
    [X] question about how to use this project

  • Summary
    I'm working in a typescript Vue-cli3 project where we are also using vuex-simple. When running vue-cli-service serve (webpack-dev-server) my application is working as expect with vuex-simple. However when running vue-cli-service build and then serving those static assets with an NGINX server I am getting the following

inject-util.js:48 Uncaught X: Cannot inject value into "Object.entityModule". Please make sure you setup reflect-metadata properly and you don't use interfaces without service tokens as injection value.
    at i.forEach.n (http://localhost:4000/js/chunk-vendors.3e2289df.js:1317:10455)
    at Array.forEach (<anonymous>)

I'm not sure what the difference in what I'm doing with NGINX vs what the webpack-dev-server is doing, but I'm wondering if you could help point me to what configuration I have incorrect in my build process that I'm getting this error out of vuex-simple?

I do have

import 'reflect-metadata';

in my main.ts (entrypoint)

$i18n, $router

  • I'm submitting a ...
    [ ] bug report
    [ ] feature request
    [ ] question about the decisions made in the repository
    [x] question about how to use this project

  • Summary
    How can I use inside my typed store i18n, default router? Axios use from plugins - this is костыли

  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. StackOverflow, personal fork, etc.)

Instance value is set too late.

A recent commit 810b719 modified metadata.ts so that this line:
Vue.set(instance, propertyName, instance[propertyName]);
Now appears after the property is replaced with a getter/setter.

This causes all initial values in the store to be undefined.

See:

Vue.set(instance, propertyName, instance[propertyName]);

Warning in Nuxt about classic mode

  • I'm submitting a
    [ ] bug report
    [X] feature request
    [ ] question about the decisions made in the repository
    [X] question about how to use this project

  • Summary
    When I use Vuex-simple with Nuxt 2 its working good, but I have a warning in console:
    Classic mode for store/ is deprecated and will be removed in Nuxt 3.
    Can store be implemented not in classic mode with vuex-simple?

  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. StackOverflow, personal fork, etc.)
    Code, which I use in project with warning:
import Vue from 'vue';
import Vuex from 'vuex';
import { createVuexStore } from 'vuex-simple';
import RootStore from './modules/index';

Vue.use(Vuex);
const instance = new RootStore();

const store = createVuexStore(instance, {
  strict: false,
  modules: {},
  plugins: [],
});

export default () => store;

Vue developer tools: commit revert

  • I'm submitting a ...
    [X ] bug report
    [ ] feature request
    [ ] question about the decisions made in the repository
    [ ] question about how to use this project

  • Summary

When using the Vue developer tools and trying to revert a committed mutation, the module's state is unbound from the store and a new separate state instance is bound to the store.
The module isn't synced with the store after that.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.