Giter Site home page Giter Site logo

vuex-orm / plugin-graphql Goto Github PK

View Code? Open in Web Editor NEW
228.0 10.0 53.0 7.07 MB

Vuex ORM persistence plugin to sync the store against a GraphQL API.

Home Page: https://vuex-orm.github.io/plugin-graphql/

License: MIT License

TypeScript 98.18% Shell 0.25% JavaScript 1.57%
apollo vuex-orm-plugin graphql-api graphql-client vuex vue vuex-plugin vuex-orm

plugin-graphql's Introduction

Vuex ORM

Vuex ORM Plugin: GraphQL

This project is powered by i22 Digitalagentur GmbH

Travis CI JavaScript Style Guide License

Vuex-ORM-GraphQL is a plugin for the amazing Vuex-ORM, which brings Object-Relational Mapping access to the Vuex Store. Vuex-ORM-GraphQL enhances Vuex-ORM to let you sync your Vuex state via the Vuex-ORM models with your server via a GraphQL API.

The plugin will automatically generate GraphQL queries and mutations based on your model definitions and by reading your and GraphQL schema from your server. Thus it hides the specifics of Network Communication, GraphQL, Caching, De- and Serialization of your Data and so on from the developer. Getting a record of a model from the server is as easy as calling Product.fetch(). This allows you to write sophisticated Single-Page Applications fast and efficient without worrying about GraphQL.

Documentation

You can find the complete documentation at https://vuex-orm.github.io/plugin-graphql/.

Questions & Discussions

Join us on our Slack Channel for any questions and discussions.

While there is the Slack Channel, do not hesitate to open an issue for any question you might have. We're always more than happy to hear any feedback, and we don't care what kind of form they are.

Donations

Support this project by sending a small donation to the developer.

paypal

License

Vuex ORM GraphQL is open-sourced software licensed under the MIT license.

plugin-graphql's People

Contributors

cameroncf avatar cwirz avatar dependabot[bot] avatar douglance avatar josx avatar kevinmarrec avatar kiaking avatar ktsn avatar ldiebold avatar phortx avatar romtorres avatar stevefan1999-personal avatar timvandesteeg avatar tldmain avatar toadkicker avatar uplus avatar wittestier 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  avatar

plugin-graphql's Issues

Consume the schema

Theoretically this plugin could fetch the GraphQL schema initially to know how the queries/mutations are shaped and maybe even detect incompatibilities.

Following things could be optimized by leveraging the schema:

  • Whether a custom query/mutation type is a connection (multiple) or not
  • Which fields to skip due to the fact that these are not included in the schema
  • Determine types of generic attributes

More to come.

Mistaken `clone` function behaviour in QueryBuilder.buildQuery method on `src` version

Clone methods in dist/vuex-orm-graphql.esm.js version and src/graphql/query-builder.ts have different behaviours. It is probably the wrong behaviour in src/graphql/query-builder.ts which causes the argument arg property's value undesirable override in mutation.

Example

args = {
  id: '123',
  post: {
    title: 'Title'
  }
}

// after QueryBuilder.buildQuery('mutation', model, 'post', args, multiple, filter) call becomes

args = {
  id: '123',
  post: {
    __type: 'Post'
  }
}

All data inside post ({ title: 'Title' }) overrides with value { __type: 'Post' }

Dist files are very large

Is there any reason that the final dist files are so large? (905Kb) - it's significantly larger than vuex-orm!
It looks like all the devDependencies have been included in the build... unless I'm reading it wrong.

Is it possible to make support of graphile/postgraphile?

Hello, thanks for the great plugin!

I was wondering if it's possible to make it compatible with https://github.com/graphile/postgraphile tool?
It makes a graphql api from existing postgresql tables. This tandem would be awesome.

Data retrieving is working already, but there are minor differences in mutations, for example postraphile makes it this way:


input TodoInput {
  id: Int
  label: String!
  isCompleted: Boolean
}

input CreateTodoInput {
  clientMutationId: String
  todo: TodoInput!
}

type Mutation {
  createTodo(
    input: CreateTodoInput!
  ): CreateTodoPayload

...and so on.

Create a common interface to support both GraphQL and REST

Good day!
I'm currently working on some new project and chose a Vue as frontend framework. After some research i found the VuexORM project as a perfect solution to organise data. But unfortunately it has no built-in communication with API backend. So i've found such an issue in the main VuexORM project and saw your posts about creating this plugin for adding communication with GraphQL backend. Thanks for this great work!
However GraphQL is not the only option and it would be certainly very useful to have an ability to communicate with REST API.
So i'm adding this issue here because the interface of your plugin in fact looks quite general and perfectly fits any backend API. Thus it's more logical to divide your plugin and add one more layer of abstraction which would represent the API methods of communication with backend (fetch, push, destroy and so on). And the very logic of the protocol (GraphQL or REST) move to separate modules.

Optimistic UI

The Apollo-Client supports Optimistic UI. It would be nice when this plugin would support that too.

We have to think about what this means and how this support could look like.

Add version and linked state as debug logging

It would be nice when the plugin could print the version and whether it's linked or not. Like: [Vuex-ORM-GraphQL] Version 1.0.0-rc.8 (linked from /Users/superman/projects/vuex-orm-graphql)

Not sure if it's possible to determine whether the project is linked.

Error installing plugin

Trying to add plugin to vuex-orm and getting this error.
Node: v10.6.0
NPM: 6.4.1
typescript: 2.7.2

import VuexORM from '@vuex-orm/core';
import VuexORMGraphQL from '@vuex-orm/plugin-graphql';
import database from '~/store/database';

VuexORM.use(VuexORMGraphQL, {
  database,
  debug: process.env.NODE_ENV !== 'production'
});

Error: fetch is not found globally and no fetcher passed, to fix pass a fetch for
your environment like https://www.npmjs.com/package/node-fetch.
For example:
import fetch from 'node-fetch';
import { createHttpLink } from 'apollo-link-http';
const link = createHttpLink({ uri: '/graphql', fetch: fetch });

Number coerced to Int

With a schema using ID type, fetching a record via fetch coerces number type to Int.

Example query:

query PriceLists($maoId: ID) {
  priceLists(filter: {maoId: $maoId}) {
    nodes {
      id
      fromDate
      toDate
      active
    }
  }
}

variable:
{
  "maoId": 148
}

Fetching with:
const result = await PriceListsModel.fetch({maoId: 148})

Results in:

operationName: "PriceLists"
query : "query PriceLists($maoId: Int!) {
  priceLists(filter: {maoId: $maoId}) {
    nodes {
      id
      fromDate
      toDate
      active
      __typename
    }
    __typename
  }
}"

variables:{maoId: 148}

The coercion is probably made here: https://github.com/vuex-orm/vuex-orm-graphql/blob/544b2c91b8e5fbab74f329f7a1b8b0e1d005f1b7/src/graphql/query-builder.ts#L221-L222

ID Type is interpreted as String Type

I have a mutation with following signature:

signIn(name: String!, marketPlaceId: ID!, password: String!)

But the plugin sends:

signIn(name: String!, marketPlaceId: String!, password: String!)

Playground

To make the development on this plugin easier, it would be nice if there is some playground: a graphql api server and a vue frontend where we can test vuex-orm-apollo while developing without the requirement to use an own app.

For server we could use https://github.com/graphcool/graphql-server-example.

Recursion detection for models is buggy

In the current implementation the plugin will never be able to generate the following query:

comments {
  posts {
     user { ... }
  }
  user { ... }
}

Because the querybuilder remembers what models are already in the query with a simple array and omits a model if it's already in the array. We rather need some kind of tree structure here.

Real GraphQL Server for the test suite

Currently we mock the response from a GraphQL Server for the tests, but that's not a good idea in long term. Errors in the mock responses can lead to undiscovered bugs in the lib.

It would be better to use Apollo to spawn a GraphQL schema in the test suite and use that for testing.

Creating relations without Id field

My backend doesn't return the ids of the relations out of the box.

This should work:

color: this.hasOne(Color, 'color'),

It should fetch the relation from the color.id field.

Current behavior is that it's simply not working.

Using GraphQL AST syntax tree object version of query in `simpleQuery` method

apollographql/graphql-tag package has webpack loader which preprocesses string queries into GraphQL AST object during import from separated *.graphql files.

And it would be helpful to add support of using GraphQL AST object in simpleQuery and simpleMutation methods.

import query from 'query.gql'
// query now is a GraphQL syntax tree object
console.log(query)
// {
//   "kind": "Document",
//   "definitions": [
//     {
//       "kind": "OperationDefinition",
//       "operation": "query",
//       "name": null,
//       "variableDefinitions": null,
//       "directives": [],
//       "selectionSet": {
//         "kind": "SelectionSet",
//         "selections": [
//           {
//             "kind": "Field",
//             "alias": null,
//             "name": {
//               "kind": "Name",
//               "value": "user",
//               ...
const result = await store.dispatch('entities/simpleQuery', {
  query
});

$id and $isPersisted are sent as arguments

When I want to save a Object A which belongsTo B which belongsTo C then the fields $id and $isPersisted of C are sent to the server.

This is probably because C is not sent to transformOutgoingData, which is a bug.

Custom queries

Just like the custom mutations it should be possible to send custom queries too.

Filter with String Array

If you try to filter for array items it handles the parameter as an Object, which it isn't.

Example: CarModel.dispatch('fetch', { filter: { carMake_slug_list: 'audi' }}) works fine while CarModel.dispatch('fetch', { filter: { carMake_slug_list: ['audi', 'bmw'] }}) doesn't.

I got it working with catching the following part (which isn't the solution) in the transformer.ts:

try {
  const arrayModel = context.getModel(singularize(key));
  returnValue[key] = value.map(v => this.transformOutgoingData(arrayModel || model, v));
} catch (e) {
  returnValue[key] = value;
}

Load relationships on demand

Currently, all relational data is fetched eagerly.

This could potentially be a problem with related data that has vast amount of records. It is probably not always desirable to fetch all relational data of the parent model.

it would be great if we it were possible to somehow define what related data you want to fetch for that particular request.

Non integer id broken with mutation

If a mutation returns a non integer id (like a relay node), a new record with id NaN is created.
I found this while debugging:

newData.id = parseInt(newData.id, 10);

Something like this might be better:

const newId = Number.parseInt(newData.id, 10);
if (!Number.isNaN(newId)) {
    newData.id = newId;
}

Incorrect type for registration within VuexORM

Hello.

I'm trying to use this plugin but when I try to register it in VuexORM the type of VuexORMGraphQL is not Plugin.

import VuexORM from '@vuex-orm/core';

Vue.use(Vuex);

const database = new VuexORM.Database();

database.register(Answer, answers);
database.register(Question, questions);

import VuexORMGraphQL from '@vuex-orm/plugin-graphql';
VuexORM.use(VuexORMGraphQL, { database });

Argument of type 'typeof VuexORMGraphQLPlugin' is not assignable to parameter of type 'Plugin'.
  Types of property 'install' are incompatible.
    Type '(components: Components, options: Options) => VuexORMGraphQL' is not assignable to type '(components: Components, options: Options) => void'.
      Types of parameters 'options' and 'options' are incompatible.

Querying connections: nodes, edges>nodes vs nothing

It seems there are 3 ways out there how you can query a field with multiple records (connections):

  1. Via a nodes field (this is what the plugin does currently)
users {
  count
  nodes {
    id
    email
    name
  }
}
  1. Via a node field within a edges field
users {
  count
  edges {
    node {
      id
      email
      name
    }
  }
}
  1. Via none of these
users {
  id
  email
  name
}

Due to the fact that some APIs support 1 and 2, some support only 2 and some only support 3, it makes the usage of this plugin difficult, due to the fact that we hard implemented case 1.

Maybe we should implement a cascading detection of how the query should look like based on the schema. The GraphQL Plugin could automatically detect whether nodes is supported or if not whether edges > node is supported and if not fallback to use neither of those.

Additionally there should be a options flag where you can enforce one of these modes.

However for me it's not clear what the standard way is and what makes sense, which is something we have to find out.

Thanks to @oligus for reporting!

Support Graphene like filtering

Python Graphene does filtering like this:

query {
  # Note that fields names become camelcased
  allAnimals(genus: "cat", name_Icontains: "lion") {
    edges {
      node {
        id,
        name
      }
    }
  }
}

I think we should support that too as an alternative to the FilterType based filtering

Custom Mutation Args broken

this.record.$mutate({ name: 'reorderItems', args: { itemIds } }); doesn't work. The arguments are completly f*cked up

Documentation

  • Setup VuePress and GitHub Pages
  • Introduction, Setup
  • GraphQL Schema Design
  • Fetch, Caching
  • Push, Persist, Destroy
  • Relationships
  • Eager Loading
  • skipFields
  • $isPersisted

Saving data into vuex coming from django-graphene backend.

Hi,

First of all thank you for vuex-orm. For me is just a dream come true to be able to replicate a part of back-end data to front-end and using vuex-orm-graphql to be able to do int in one request. I think this is a amazing project.

Now i try to use vuex-orm-graphql plugin, and i have some issues in implementing it in my project.
I am sending following query:
screen shot 2018-07-30 at 14 36 15

And i receive the following response:
screen shot 2018-07-30 at 14 39 29

Until this point all is as expected.

I would like to save a list of articles into store.
Now i need somebody to point me in the right direction because everything that i had tried failed.
My last "working" aka no errors saved in the store:

screen shot 2018-07-30 at 14 45 47

Also tried to create articleModel and articlesModel that has a many relation to articleModel. Failed.
I do receive this in console:

Vuex-ORM: GraphQL Plugin Ignoring entity article because it's not in the schema.

I am doing something wrong and now i am out of ideas.

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.