GraphQL

Going without dedicated GraphQL clients like Apollo in JS/TS

You can use fetch for making requests to GraphQL servers. Since GraphQL runs on the HTTP protocol, you can use 'POST' for them.

Here, I'm using node-fetch.

First, create a GQL query "string" with a template literal.

const GET_USER_NAME = `
  query GetUser($id: ID!) {
    user: getUser(id: $id) { id, name }
  }
`
  • The leading dollar sign ($) means it's a variable.

  • The trailing exclamation mark (!) means variable id is non-nullable. (Stack Overflow)

What if you want to make a query with a list?

const GET_USERS_NAMES = `
  query GetUsers($ids: [ID!]!) {
    users: getUsers(ids: $ids) { id, name }
  }
`
  • Wrap the variable type with square brackets []. Now it's a List type.

  • Combine Non-Null and List modifiers and you get a list of non-null type. -- [ID!]!

    • It means the List is non-null and the List can't contain null values.

Next, let's make a function to fetch the response and define the response body type.

interface UserWithNameView {
  id: string
  name: string
}

export async function getUserWithName(
  id: string
): Promise<UserWithNameView> {
  const response = await fetch(`${USER_API_URL_BASE}`/gql`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      query: GET_USER_NAME,
      variables: { id },
    }),
  })

  const {
    data: { user },
  } = (await response.json()) as {
    data: { user: UserWithNameView }
  }
  
  return user
}

Let's test it out with Jest!

import { getUserWithName } from '../clients/gql'

test('getUserWithName should return user with name', async () => {
  const id = 'b4622ef2-9426-4737-b8ed-9b7d1561df10'
  const user = await getUserWithName(id)
  
  expect(user.name).toBeDefined()
})

And Voila, you're now the master of GQL with fetch API.

REF

Last updated