Open dupski opened 6 years ago
Possible way to implement:
Looking at the usage of @client
from https://github.com/apollographql/apollo-link-state
How about something like this:
const query = {
mutation: {
updateNetworkStatus: {
__args: {
isConnected: true
},
__directives: {
client: true
}
}
}
};
This would then result in:
mutation {
updateNetworkStatus(isConnected: true) @client
}
this should work for sub-nodes too, e.g.:
const query = {
Post: {
id: true,
name: {
__directives: {
some_directive: true
}
}
}
};
This would then result in:
query {
Post {
id
name @some_directive
}
}
It would be cool to support directive arguments too, e.g.:
const query = {
Post: {
id: true,
name: {
__directives: {
myDirective: {
directiveArg: 20
}
}
}
}
};
Adding this support sounds useful. However, I'm wondering about support for the particular use case I have right now.
I have this object:
const everyDayHealthFocuses = {
diet: {
id: 'diet',
options: {
'calorie-count': {
category: 'Diet',
icon: 'fa fa-question-circle',
id: 'calorie-count',
selected: false,
text: 'Calorie Count'
},
mood: {
category: 'Diet',
icon: 'fa fa-question-circle',
id: 'mood',
selected: false,
text: 'Mood'
},
weight: {
category: 'Diet',
icon: 'fa fa-question-circle',
id: 'weight',
selected: false,
text: 'Weight'
},
},
title: 'Diet'
},
};
I want a single function that I can call which will transform this object into a graphql query string, with the addition of the directive which instructs that this should be querying my local cache, e.g. @client
:
query {
diet @client {
id
options {
'calorieCount' {
category
icon
id
selected
text
}
mood {
category
icon
id
selected
text
}
weight {
category
icon
id
selected
text
}
}
title
}
}
As background, this object is an actual object being used in a React component in one of my applications.
As long as I can get this functionality, I'm happy.
I think that what you proposed can be in intermediate step between these two, e.g.:
const query = {
diet: {
__directives: {
'@client': true
}
id: true,
options: {
'calorie-count': {
category: true,
icon: true,
id: true,
selected: true,
text: true,
},
mood: {
category: true,
icon: true,
id: true,
selected: true,
text: true,
},
weight: {
category: true,
icon: true,
id: true,
selected: true,
text: true
},
},
title: true
},
};
Does something like this seem agreeable? I was going for an approach similar to this, but it seemed like more complex / longer code than simple string manipulation. But I think the string manipulation approach I was going for might not be quite as effective for a wider number of use cases.
Also I'm trying to think about the approach you're trying to go for with "directives" and "new WithDirectives()". I assume these are just ideas and you would be leaving the approach for how to finish adding the functionality to me? I've used ES6 classes for react, but never otherwise to combine with the "new" keyword to create an object in this instance. I'm not sure how I would implement this. You mentioned later that you think the "directives" approach would also work; I would also prefer that approach.
Before the string manipulation method, I was simply looking for the last key in my object, and then simply replacing its value with {apolloTarget: {'@client': true}}
, "apolloTarget" just being arbitrarily chosen; I could name it something else of course. I didn't finish that approach completely, though.
On another aside, I'm still new with Apollo and was actually not building my query correctly before. I thought that I was supposed to add @client at the end of my query, as with mutations. But I think with queries, it looks like, if I'm correct, the only place I'd add @client would be between key names in the root of the query, and the next opening curly brace, e.g.:
query {
key1 <could add a directive here> {
...
}
key2 <could also add a directive here> {
...
}
...
}
On an aside, I wonder what the API for this functionality should be... Right now I have it as:
import { objToApolloQuery } from 'json-to-graphql-query';
...
objToApolloQuery(obj, target);
// ex: objToApolloQuery({a: {b: 'c'}}, 'client')
Since in my use case, my entire object will reside in the local cache, maybe export a dedicated function just for that? Ex: objToApolloLocalCacheQuery({a: b: 'c'}})
Idk, let me know if you also have a preference as to how I should expose this functionality to users.
Nice Joe
Yep your example above using __directives
is exactly what I was thinking. I don't think we'll need the WithDirectives
thing so please disregard that! :)
I now also don't think we should have a specific objToApolloQuery method in the library because Apollo is not doing anything non-standard.
All you will need in your own code is a method that does something like:
// get your "data" object, then...
data.diet['__directives`] = { client: true };
const query = jsonToGraphqlQuery(data, { keysToStrip: ['__typename'] });
Hey Russell, Today I did a refactor of the code in PR #6, which includes support for directives, starting with arg-less ones, e.g. Apollo's "@client".
Merged and released Joe's PR, but there are still a few open items:
PRs welcome as always! :)
Multiple directives on one node is kind of supported through this PR (https://github.com/vkolgi/json-to-graphql-query/pull/33) and merged.
Thanks!
There is a need to support Directives, currently just the
@client
directive for apollo, however I would like us to implement this in a generic way to allow for possible use of@skip(if: ...)
, etc. if needed.Relavant GraphQL Spec: http://facebook.github.io/graphql/October2016/#sec-Directives-Are-In-Valid-Locations Medium article: https://medium.com/front-end-developers/graphql-directives-3dec6106c384
Initial Requirements:
Future Requirements