operationName not included as a root key of the query object
aethr opened this issue · 3 comments
We've been using gql-query-builder
to replace hand-written queries in our service layer and so far it's working really well, thanks for creating this library.
I noticed recently that the GraphQL spec includes the following recommendation:
A standard GraphQL POST request should use the application/json content type, and include a JSON-encoded body of the following form:
{
"query": "...",
"operationName": "...",
"variables": { "myVariable": "someValue", ... }
}
We've started work to stub out different gql queries and responses in our cypress test suite, and one of the recommendations is to use an explicit operationName
in your queries, and then use this part of the request object to determine which response to send:
// Utility to match GraphQL mutation based on the operation name
export const hasOperationName = (req, operationName) => {
const { body } = req
return (
body.hasOwnProperty('operationName') && body.operationName === operationName
)
}
cypress.intercept('POST', '/graphql', req => {
if (hasOperationName(req, 'getSite') {
req.alias = 'getSite';
req.send({ fixture: 'getSiteFixturre' });
}
});
This code looks for the operationName
in the root of the request body, and it seems this approach works well for a lot of developers, but isn't working for us because gql-query-builder
only includes the operationName
in the query itself.
For now we're working around this simply like:
const gqlQuery = query({
operation: 'site',
variables: ...,
fields: ...,
}, null, { operationName: 'getSite' }));
// manually add operationName
gqlQuery.operationName = 'getSite';
However, if gql-query-builder
did this for us we could use the intended syntax:
const gqlQuery = query({
operation: 'site',
variables: ...,
fields: ...,
}, null, { operationName: 'getSite' });
Do you think this is something the library should support in the default adapter, and if so would you like me to make a pull request?
As per their docs:
If the query contains several named operations, an operationName query parameter can be used to control which one should be executed.
Are you looking at sending several named operations and need operationName
?
Right now we're not attempting to send several named operations in the same document, we're just trying to add a bit of annotation to the queries we're sending to assist with tooling.
From a brief read of the current spec it seems like operationName
is an optional field that should be fine to send even when there's only one named query.
However, it does make me wonder, does gql-query-builder
allow us to specify operationName for each query in the document if an Array of queries is passed, like:
query([
{ operation: 'me', fields: ['name'] },
{ operation: 'site', fields: ['location'] },
]);
// {
// query: "query { me { name } } { site { location } }",
// }
Since operationName
is passed through a final config
parameter I think it just gets applied to the first query in the document:
query([
{ operation: 'me', fields: ['name'] },
{ operation: 'site', fields: ['location'] },
], null, { operationName: 'getUser' });
// {
// query: "query getUser { me { name } } { site { location } }",
// }
Perhaps operationName
needs to be a field within each query definition, and then the operationName
applied in config might be the one that's added to the root of the document.
query([
{ operation: 'me', fields: ['name'], operationName: 'getUser' },
{ operation: 'site', fields: ['location'], operationName: 'getSite' },
], null, { operationName: 'getUser' });
// {
// query: "query getUser { me { name } } getSite { site { location } }",
// operationName: "getUser",
// }
Apologies if this is wasting your time, I'm pretty new to GraphQL so still learning how all of these features are meant to be used.
I'm out of touch with recent evolution in GraphQL world myself, and would rather ask for help/suggestion on this one.