graphql / graphql-playground

🎮 GraphQL IDE for better development workflows (GraphQL Subscriptions, interactive docs & collaboration)
MIT License
8.73k stars 731 forks source link

Playground stuck forever if I use await #1387

Open Zeioth opened 2 years ago

Zeioth commented 2 years ago

This piece of code make the playground get stuck:

DESCRIPTION: On a graphql resolver, I'm performing a request to another graphql server, waiting for the result, and displaying it.

...
type IUser = {
  firstName: string | ''
  lastName: string | ''
  email: string | ''
}

function getUser(userUuid: string): Promise<IGetUserResponse> {
    const query = `
      query{
        user (uuid: "`+ userUuid + `"){
          firstName
          lastName
          email
        }
      }
      `
    return clientWrapper('users', query) as Promise<IGetUserResponse>
}

const user = await getUser(userUuid)

The issue is caused by the await on the last line. It provokes the playground to get stuck forever.

This is the clientWrapper, if you need it (you shouldn't).

import axios from 'axios'
import {IGenericResponse} from './api.types'

const URL_USERS_API = process.env.USERS_API_URL
if (!URL_USERS_API) {
  throw new Error(`Users api url not defined.`)
}

const SITE_TOKEN = process.env.SITE_TOKEN
if (!SITE_TOKEN) {
  throw new Error(`Site token not defined.`)
}

const AUTH_TOKEN = process.env.AUTH_TOKEN
if (!AUTH_TOKEN) {
  throw new Error(`Auth token not defined.`)
}

const GQL_ERROR = 'gql error'

async function clientWrapper(
  api: 'users',
  query: string,
  variables?: unknown
): Promise<IGenericResponse<string, unknown>> {
  let hasGqlError = false
  try {
    // check env variable
    let url = ''
    if (URL_USERS_API && api === 'users') {
      url = URL_USERS_API
    }

    const resp = await axios({
      url: `${url}/graphql`,
      method: 'post',
      headers: {
        sitetoken: SITE_TOKEN || '',
        authorization: AUTH_TOKEN || '',
      },
      data: {
        query,
        variables,
      },
    })
    /** Generic error handler */
    if (resp.data.errors && resp.data.errors[0] && resp.data.errors[0].message.indexOf('Expired token') !== -1) {
      throw new Error('Expired token')
    }

    if (resp.data.errors && resp.data.errors[0] && resp.data.errors[0].message.indexOf('Forbidden') === 0) {
      throw new Error('Forbidden')
    }

    resp.data.errors?.forEach((err: {message: string}) => {
      console.error(err.message)
    })

    if (resp.data.errors) {
      hasGqlError = true
      throw new Error(GQL_ERROR)
    }

    return resp
  } catch (error) {
    if (!hasGqlError) {
      // print a generic error
      const msg = JSON.stringify(error)
      console.error(msg)
    }
    throw new Error()
  }
}

export default clientWrapper