vuex-orm / plugin-graphql Goto Github PK
View Code? Open in Web Editor NEWVuex ORM persistence plugin to sync the store against a GraphQL API.
Home Page: https://vuex-orm.github.io/plugin-graphql/
License: MIT License
Vuex ORM persistence plugin to sync the store against a GraphQL API.
Home Page: https://vuex-orm.github.io/plugin-graphql/
License: MIT License
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.
It should be possible to send queries and mutations that are not tied to the ORM or a model in any way.
I get a response of 401 if I am not authenticated in my graphql api.
Is there a way to centralised catch all errors from apollo and do something with it on 1 place.
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 });
And update vuex-orm to 0.24.4
This is not tested yet
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!)
It should be possible to attach different GraphQL APIs with different models in the same app.
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.
Due to the new recursion detection algorithm. Seems to be buggy :)
Currently the system expects a FilterType to exist. But there are cases where this is not given.
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.
Just like the custom mutations it should be possible to send custom queries too.
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.
The code uses import and require statements at the same time. Thus we cannot use rollup to bundle a vue project with vuex, vuex-orm, vuex-orm-graphql.
This seems to be a known problem and is documented here: #rollup/rollup#1058
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' }
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;
}
This plugin should provide some tools to allow the simple unit testing of components which interact with the GraphQL API.
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:
plugin-graphql/src/actions/action.ts
Line 44 in 0730a86
const newId = Number.parseInt(newData.id, 10);
if (!Number.isNaN(newId)) {
newData.id = newId;
}
It seems there are 3 ways out there how you can query a field with multiple records (connections):
nodes
field (this is what the plugin does currently)users {
count
nodes {
id
email
name
}
}
node
field within a edges
fieldusers {
count
edges {
node {
id
email
name
}
}
}
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!
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.
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
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
});
We should support GraphQL Subscriptions
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.
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.
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
Relates to vuex-orm/vuex-orm#147
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.
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.
When a app fires multiple request at the loading in parallel, this plugin will fetch and process the schema for each request.
For fetch, persist, push, destroy like in the vuex-orm core.
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.
Is there any plans to allow this plugin to work serverside or with nuxt?
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:
More to come.
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:
And i receive the following response:
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:
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.
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.
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.
this.record.$mutate({ name: 'reorderItems', args: { itemIds } });
doesn't work. The arguments are completly f*cked up
will this be supported soon?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.