Issue #192

Read https://www.apollographql.com/docs/react/features/error-handling How to catch actual error https://github.com/apollographql/apollo-client/issues/4016 🤔

import { Observable } from 'apollo-link'
import ApolloClient from 'apollo-boost'
import Token from 'library/models/Token'
import TokenService from './TokenService'
import { TokenRefreshException } from 'library/utils/Exception'

const client = new ApolloClient({
  uri: 'https://www.myapp.no/api/',
  request: async (operation) => {
    const token = await TokenService.loadToken()
    updateOperation(operation, token)
  },
  onError: (error) => {
    console.log('ApolloClient error', error)
    if (isAuthError(error)) {
      return handleAuthError(error)
    } else {
      return error.forward(error.operation)
    }
  },
  fetchOptions: {
    mode: 'no-cors',
  }
})

const isValidErrorCode = (statusCode) => {
  if (typeof (statusCode) === 'undefined' || statusCode === null) {
    return false
  } else {
    return true
  }
}

const isAuthError = (error) => {
  console.log('client error', error)
  if (error.networkError) {
    return error.networkError.statusCode === 401
  } else {
    return false
  }
}

const handleAuthError = (error) => {
  return new Observable((observer) => {
    TokenService.refreshToken()
      .then((token) => {
        updateOperation(error.operation, token)
      })
      .then(() => {
        const subscriber = {
          next: observer.next.bind(observer),
          error: observer.error.bind(observer),
          complete: observer.complete.bind(observer)
        }

        error.forward(error.operation).subscribe(subscriber)
      })
      .catch((e) => {
        observer.error(e)
      })
  })
}

const updateOperation = (operation, token: Token) => {
  const tokenHeader = `${token.token_type} ${token.access_token}`

  operation.setContext((context) => {
    return {
      headers: {
        authorization: tokenHeader,
        'Content-Type': 'application/json'
      }
    }
  })
}