convert data to error in a custom ApolloLink

627 Views Asked by At

I'm trying to create a custom ApolloLink that converts specific graphql data to an error which will be passed to the onError link. The omg help! error is successfully passed as a network error to onError, but I also get a run time error in my browser: Uncaught (in promise) Error: omg help! at new ApolloError which should not be happening. How do I make sure the error is entirely handled in onError and not also throwing a runtime error from the TransformErrorLink code?

TransformErrorLink.js:

import { ApolloLink, Observable } from 'apollo-link-core';

class TransformErrorLink extends ApolloLink {
  request(operation, forward) {
    const observable = forward(operation);

    return new Observable((observer) => {
      observable.subscribe({
        next: (value) => {
          // reroute Error types as proper errors
          for (const [req, res] of Object.entries(value.data)) {
            if (res?.__typename?.includes('Error')) {
              observer.error(new Error('omg help!'));
            }
          }
          observer.next(value);
        },
        error: observer.error.bind(observer),
        complete: observer.complete.bind(observer)
      });
    });
  }
}

export default new TransformErrorLink();

the composite set of apollo links:

import { from, HttpLink } from '@apollo/client';
import { onError } from '@apollo/client/link/error';
import transformErrorLink from './transformErrors';

const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors)
    graphQLErrors.forEach(({ message, locations, path }) =>
      console.log(
        `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
      )
    );
  if (networkError) console.log(`[Network error]: ${networkError}`);
});

const additiveLink = from([
  errorLink,
  transformErrorLink,
  new HttpLink({ uri: process.env.GRAPH_API_URL })
]);

export default additiveLink;

I tried swapping the order of errorLink and transformErrorLink in the additiveLink, but that resulted in just a runtime error with no console log first.

I have also been reading https://www.apollographql.com/blog/frontend/apollo-link-creating-your-custom-graphql-client-c865be0ce059/ which does the reverse of what I'm doing - convert an error to data.

2

There are 2 best solutions below

0
On

I haven't used apollo-link-core before, but should you not return observable's projection like in the last line below?

class TransformErrorLink extends ApolloLink {
  request(operation, forward) {
    const observable = forward(operation);

    return new Observable((observer) => {
      **return** observable.subscribe({
      ...
0
On

I figured it out - I needed to add an errors property (of type Array) to value and then call observer.next with value instead of calling observer.error with an Error.