jasonkuhrt / graphql-request

Minimal GraphQL client

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support operation name

Henner25 opened this issue · comments

It is not possible to run queries like this because the name of the operation I want the server to execute cannot be specified (see http://graphql.org/learn/serving-over-http/#post-request):

query HeroName {
  hero {
    name
  }
}

query HeroNameAndFriends {
  hero {
    name
    friends {
      name
    }
  }
}

Do you intend to add this functionality?

Great point @Henner25. Do you have a suggestion on how to extend the API without introducing a breaking change? 💡

You probably do not want request(query, variables, operation) because then the user would have to pass an empty variables object just to select an operation?

Having both request(query, operation, variables) and request(query, variables) and discerning the call by checking the type of the second argument does not feel nice either...

So no, unfortunately I don't know of a very nice way.

How about introducing a new signature for input using JS de-structuring.
request({ query, variables, operation } )

Detecting object vs string for backward compatibility.
Adding the new operation field only to the de-structuring way of input.

And dropping support for old signature request(query, variables) in 2.x or maybe keeping it around forever?

We should explore the implications of having both at the same time in terms of DX (editor auto-completion support, type inference etc).

I'd really like to preserve the simplicity of request('{ hello }') and not complicate it with something like request({ query: '{ hello }' })

We can support both, editor autocomplete works when types for various call signatures is specified like in graphql-yoga. I will set it up and send a couple of GIFs to show how that looks like.

Any intent on when operation name will become supported or what would need to be done in a pr to get support for this feature?

Given the following query:

query HeroName {
  hero {
    name
  }
}

query HeroNameAndFriends {
  hero {
    name
    friends {
      name
    }
  }
}

mutation CreateNewHero($name: String) {
  hero {
      createNewHero(name: $name) {
         id
         name
      }
  }
}

With pull request #165 , HeroName can be called viz:

request(serverUrl, query, { __operation: 'HeroName' });

or, as:

// Configure a custom key for `operationName`
var client = new GraphqlClient(serverUrl, { operationNameKey: '$operationName' });

// Make a request with the custom key
client.request(query, { $operationName: 'HeroName' });

The mutation CreateNewHero can be called viz:

request(serverUrl, query, { __operation: 'CreateNewHero', name: "New Hero Name" });

Notice how the name variable played along with the __operation variable.

This approach would extend the API without introducing a breaking change.

I like @divyenduz suggestion -- allow the first arg to be an object. But given it's been years now, I guess it's not acceptable. An alternative would be to add:

requestOperation(query, variables, operationName, requestHeaders)

Yeah, it's gross but it gives people who want to log operations on the server a way to adopt/keep this nifty library.

Any idea when this will be supported?
Having a hard time intercepting requests made by graphql-request using Cypress

@jasonlimantoro

As a workaround, here my HttpRequestInterceptor to catch GraphQL call and response the correct fixture.

import { HttpRequestInterceptor } from 'cypress/types/net-stubbing'

const stubbedOperations = {
  getSocieties: {
    fixture: 'graphql/getSocieties.json',
  },
}

/**
 * Get operation name from request `query operationName {`
 */
const OPERATION_NAME_REGEX = /(?<=^query\s*)\w+(?=\s*\{)/

/**
 * Stubs the calls to graphql
 * @param req
 */
export const stubGraphql: HttpRequestInterceptor = async (req) => {
  const matching = req.body.query.match(OPERATION_NAME_REGEX)
  const operationName = matching[0]
  const stubbedOperation = stubbedOperations[operationName]
  if (stubbedOperation) {
    console.log('Stubbing operation', stubbedOperation)
    req.alias = `gql${operationName}`
    req.reply({
      statusCode: 200,
      fixture: stubbedOperation.fixture,
    })
  } else {
    console.warn('Un mocked graphQL call')
    req.reply({
      statusCode: 404,
      body: 'Missing GraphQL mock',
    })
  }
}

hey, any update on this feature request?

It is sent now.