Giter Site home page Giter Site logo

Comments (12)

phortx avatar phortx commented on May 13, 2024

Hi Michael!

Thanks for the kind words :)

You're right. @kiaking and I had some similar thoughts and I really think we should do that.

In my opinion we should bring the interface to the vuex-orm core with some kind of adapter pattern, which allows plugins to add adapters. Much like js-data does this.

I could imagine way more adapters then REST/JSON and GraphQL: Firebase, localstorage and more.

@kiaking What's on your mind about this topic?

PS: Should we move that issue into the core issue tracker due to the fact that this is a general topic for the vuex-orm ecosystem?

from plugin-graphql.

madmike avatar madmike commented on May 13, 2024

Thanks for the quick reply!
Maybe it can be packed in the separate VuexORM plugin as this yours one. It has some sense to have a VuexORM as such a lightweight model layer which serves only the logic of communicating with Vuex and representing the API to use in the component layer of Vue app. However adding this to the core VuexORM API with the option of LocalStorage by default (for the projects which do not need the communication with serverside) would have some sense too.
I think this issue in anyway is in high demand because to build any serious project needs this persistence layer which would implement the communication with any kind of backend. And I suggest to discuss some solution for the design of this implementation and start working of it as the part of VuexORM core or as the plugin.

from plugin-graphql.

phortx avatar phortx commented on May 13, 2024

Nice to hear. I will be some tough work to define a common API that is generic enough for all kinds of persistence implementations.

I think the base persistence layer without any implementation is very lightweight and it should go into the core to have a single source of truth for the API design and the overall handling and feeling of the library.

from plugin-graphql.

madmike avatar madmike commented on May 13, 2024

Agree with you, it is clearer to have an interface in the core lib and endpoint for each API as plugins.
So if it's possible please describe here a structure how you see this base API and i will try to start implementing REST API logic.

from plugin-graphql.

kiaking avatar kiaking commented on May 13, 2024

Hi guys! Yeah, I think it's a good idea to have single API interface at the core library, or at least as a separated repo. I think it can be in the core until it becomes cluttered. So +1 for moving this issue to the core's issue tracker.

And here is my belief thought on this. In term of user point of view, the interface of the API should be quite simple. I think most of them are already defined at this library, thanks to @phortx.

Maybe we could come up with 3 layers of API.

  1. Interact with Vuex only.
  2. Interact with Backend Only.
  3. Interact with Both.
CRUD Vuex Only Backend Only Both
READ find fetch get
Create insert persist add
Update update push edit
Delete delete destroy remove

Of course, the naming is just an idea but it's a bit more flexible, and a user could use the library to handle generic API call without interacting with Vuex ORM too. Maybe it is enough to have deleteAndDestroy kinda method though.

I think the only thing library author must do is to implement all of the above methods as a modules and make it able to call store.dispatch('entities/users/persist', { ... }).

To be consistent with the argument passed to the library could be tough though. For example, if we were to create REST API library, where should we define the endpoint (URL) for each method and such.

from plugin-graphql.

phortx avatar phortx commented on May 13, 2024

I like the idea of the 3 layer API but I think we should keep the number of terms low, so we don't confuse the developers. Thus I'm for the deleteAndDestroy variant instead of a new set of terms :)

The argument topic is a difficult one. Maybe it's not even possible to have a real adapter independed API because of some specifics 🤔

Maybe we should create some wiki document or something to specify the API together?

from plugin-graphql.

kiaking avatar kiaking commented on May 13, 2024

I like the idea of the 3 layer API but I think we should keep the number of terms low, so we don't confuse the developers. Thus I'm for the deleteAndDestroy variant instead of a new set of terms :)

Yeah you got the point. I think so too.

The argument topic is a difficult one. Maybe it's not even possible to have a real adapter independed API because of some specifics

Yeah... Since we have to use Vuex API, we have the limitation that we can't change the number of arguments too. Anyway, I'll organize the thought and move this issue to the Core!

from plugin-graphql.

phortx avatar phortx commented on May 13, 2024

Thank you very much, kia :)

from plugin-graphql.

madmike avatar madmike commented on May 13, 2024

So yes i think it would be the best start point - to write smth like a wiki or create an interface class.

What about 3 layer interface in my opinion it seems more complicated than it has to be.
In fact i don't see any need to use the backend only api (or if there is ever such a possibility i think it should be the matter of another lib). The logic of Vuex-only API can be easily combined with the logic of persistence layer. For example if u've set up the backend plugin (for example REST API) and call the all method - library can check the in-memory store if it has any data already downloaded and if it has not - make and API call to backend, populate the store with data and return it to the user (sure we need some method which can synchronise the state). Method find is quite similar - search the in-memory store for the id and if it has no luck - ask server to search this id in DB. Creation and Destruction of objects sure are a bit different, you may need separate methods for creating the object in store without persistence and you may want to delete the object just in memory, but again methods create and destroy from the persistence layer can do both tasks at once - delete data from store and from real db at once.
I think interface must be as seamless as possible, offering the most popular cases with the less of configuration and the use of additional methods but sure it must be flexible enough too.

In fact we can start thinking about this API from some real-world example with the backend API and some components which don't need the persistence. For example some ecommerce resource with tons of products. So first of all we need to load the full Category list (and then we can operate with it just in memory) then we like to download some popular products (we can't load all of them in memory), then we need the ability to load products by categories, apply filters and so on (true backend part). And finally we can have just-in-memory shopping cart, for example we don't need to persist its contents (true Vuex part without any backend API).
So as the frontend developer all I want here to call Category.all method at the start point which create automatic request to backend and populate my Category model with data. Then i want to use find or where method (probably order_by and some others too) of Product model to automatically search the cached data or sending requests to server. And finally I want to setup my ShoppingCart model not to use any backend at all thus all its methods will become Vuex only and won't try to exec any backend logic.

Sure I can agree with @phortx here that there is a possibility that not all of the adapters would fit this logic but we can choose this way as the starting point.

from plugin-graphql.

phortx avatar phortx commented on May 13, 2024

What about 3 layer interface in my opinion it seems more complicated than it has to be.
In fact i don't see any need to use the backend only api (or if there is ever such a possibility i think it should be the matter of another lib). The logic of Vuex-only API can be easily combined with the logic of persistence layer. For example if u've set up the backend plugin (for example REST API) and call the all method - library can check the in-memory store if it has any data already downloaded and if it has not - make and API call to backend, populate the store with data and return it to the user (sure we need some method which can synchronise the state).

Unfortunately this is not practicable because you will loose some reactivity with that. We had a similar discussion and we decided not to combine fetching from the server and retrieving from the store.

First this might seem complicated but the other way would produce more complication in the long term.

We can reroll this discussion, but I think the separation of persistence and vuex API is a good way to go and we've made good experience with that :)

Also think of this: How can a call to Category.all know if the records in the store are really all records? There could be more on the server, we can't know. So a Catagory.all would always send a request to the server, which can lead to huge traffic.

I think interface must be as seamless as possible, offering the most popular cases with the less of configuration and the use of additional methods but sure it must be flexible enough too.

I'm on your side. But when you start to work on such plugins you will get in some difficult situations soon. For example does the JSON/REST specification (which is inofficial btw) not specify if keys are camelCase, hyphen-case or snake_case. What is the default behavior? Do you want support all of them? I had and have similar issues with GraphQL. The works-out-of-the-box-with-everything philosophy doesn't work well in the reality. Pity. :(

from plugin-graphql.

madmike avatar madmike commented on May 13, 2024

Yes sure these are just thoughts and I'm not so much acquainted with Vuex at this point but I think finally that it's possible to implement somehow and maybe the ease of the final use of this lib can cost some bigger efforts at the point of it's developing. I've tried some other libs before i came to the Vuex-ORM, e.g. JSORM (which implements JSON API frontend) and i liked it's design, it was developed with inspiration of Rails's ActiveRecord (I came here from the Rails world too) and it's API looks quite simple and powerful, but that library isn't stable yet and I got lots of errors trying to use it in my app. In addition it has nothing with Vuex and I prefer using native technologies with the frontend i choose.
In fact it will have sense to analyze several similar libraries and get their best sides.

Also think of this: How can a call to Category.all know if the records in the store are really all records? There could be more on the server, we can't know. So a Catagory.all would always send a request to the server, which can lead to huge traffic.

For example it can be done with the ability of pagination and total_count field.

I'm on your side. But when you start to work on such plugins you will get in some difficult situations soon. For example does the JSON/REST specification (which is inofficial btw) not specify if keys are camelCase, hyphen-case or snake_case. What is the default behavior? Do you want support all of them? I had and have similar issues with GraphQL. The works-out-of-the-box-with-everything philosophy doesn't work well in the reality. Pity. :(

Sure it's impossible to provide all the possible ways of use at once. In fact it's even not necessary at the moment. The problem with case again can be customisable, we can set the default behaviour which is the most popular and add the way to change it by providing such an option somewhere in the configuration options of the current model or as the global scope option. I like very much the Rails principal of convention over configuration (don't know why it has not become popular in JS world) - to implement some common default behaviour out of the box giving the way to customise everything if you need (mainly it relates to the naming conventions sure but can be expand on these questions too)

We can reroll this discussion, but I think the separation of persistence and vuex API is a good way to go and we've made good experience with that :)

Thumbs up! Let's create the new discussion at the core issue tracker and maybe with the help of others come to some API design which would be possible to start with.
I've already loved the Vue world it seemed to me very efficient and with such a powerful and well-thought ORM library it could become almost perfect for any type of task.

from plugin-graphql.

kiaking avatar kiaking commented on May 13, 2024

OK, I've created the issue at the core! Let's continue over there 👍
vuex-orm/vuex-orm#200

from plugin-graphql.

Related Issues (20)

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.