@apollo/client#ApolloLink TypeScript Examples

The following examples show how to use @apollo/client#ApolloLink. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: client.ts    From Frontend with MIT License 6 votes vote down vote up
createClient = () => {
  const uri = process.env.GATSBY_GRAPHQL_ENDPOINT;

  const httpLink = createHttpLink({
    uri,
    fetch
  });

  const authToken = hasWindow ? localStorage.getItem('token') : '';

  const authLink = new ApolloLink((operation, forward) => {
    operation.setContext({
      headers: {
        authorization: authToken ? `Bearer ${authToken}` : ''
      }
    });

    return forward(operation);
  });

  const client = new ApolloClient({
    link: authLink.concat(httpLink),
    cache: new InMemoryCache({
      dataIdFromObject: (object) => {
        // eslint-disable-next-line no-underscore-dangle
        switch (object.__typename) {
          case 'Person':
            return object.uid;
          default:
            return defaultDataIdFromObject(object); // fall back to default handling
        }
      }
    })
  });

  return client;
}
Example #2
Source File: apollo.ts    From storefront with MIT License 6 votes vote down vote up
authLink = new ApolloLink((operation, forward) => {
  // If session data exist in local storage, set value as session header.
  const session = process.browser ? localStorage.getItem('session') : null;
  const authToken = process.browser ? localStorage.getItem('authToken') : null;

  operation.setContext(() => ({
    headers: {
      authorization: authToken != null ? `Bearer ${authToken}` : undefined,
      'woocommerce-session': session != null ? `Session ${session}` : undefined,
    },
  }));
  return forward(operation);
})
Example #3
Source File: apollo.ts    From storefront with MIT License 6 votes vote down vote up
afterware = new ApolloLink((operation, forward) =>
  forward(operation).map((response) => {
    // Check for session header and update session in local storage accordingly.
    const {
      response: { headers },
    } = operation.getContext();
    const session = headers.get('woocommerce-session');
    if (process.browser && session != null && localStorage.getItem('session') !== session) {
      localStorage.setItem('session', headers.get('woocommerce-session'));
    }
    return response;
  }),
)
Example #4
Source File: index.ts    From fullstack-starterkit with MIT License 6 votes vote down vote up
function configureApolloClient(config: Config): ApolloClient<NormalizedCacheObject> {
  const httpLink = new HttpLink({ uri: config.endpoints.https });

  const wsLink = new WebSocketLink({
    uri: config.endpoints.wss,
    options: { reconnect: true }
  });

  const link = split(
    ({ query }) => {
      const definition = getMainDefinition(query);
      return definition.kind === 'OperationDefinition' && definition.operation === 'subscription';
    },
    wsLink,
    httpLink
  );

  const client = new ApolloClient({
    link: ApolloLink.from([
      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}`);
        }
      }),
      link
    ]),
    cache: new InMemoryCache()
  });

  return client;
}
Example #5
Source File: apollo-client.ts    From beancount-mobile with MIT License 6 votes vote down vote up
link = middlewareLink.concat(
  ApolloLink.from([
    onErrorLink,
    new HttpLink({
      uri: getEndpoint("api-gateway/"),
      fetch,
    }),
  ])
)
Example #6
Source File: configureGraphQL.ts    From knests with MIT License 6 votes vote down vote up
authMiddleware = new ApolloLink((operation, forward) => {
  operation.setContext({
    headers: {
      authorization: authToken || null,
    },
  });
  // Add onto payload for WebSocket authentication
  (operation as any & { authToken: string | undefined }).authToken = authToken;

  return forward(operation);
})
Example #7
Source File: clientConfig.ts    From OpenVolunteerPlatform with MIT License 5 votes vote down vote up
splitLink = ApolloLink.split(
  ({ query }) => {
    const { kind, operation }: any = getMainDefinition(query);
    return kind === 'OperationDefinition' && operation === 'subscription';
  },
  wsLink,
  httpLink,
)
Example #8
Source File: client.ts    From lexicon with MIT License 5 votes vote down vote up
client = new ApolloClient({
  link: ApolloLink.from([authLink, uploadLink]),
  cache,
})
Example #9
Source File: useLogout.test.ts    From magento_react_native_graphql with MIT License 5 votes vote down vote up
describe('useLogout', () => {
  const customerToken = 'dgFt1#$2i1j';

  beforeEach(async () => {
    const client = new ApolloClient({
      cache: new Cache({
        addTypename: false,
      }),
      link: new ApolloLink(),
    });
    // Pre-fill apollo-cache to mimic logged in user state
    client.writeQuery({
      query: IS_LOGGED_IN,
      data: {
        isLoggedIn: true,
      },
    });
    expect(client.readQuery({ query: IS_LOGGED_IN })).toEqual({
      isLoggedIn: true,
    });
    jest.spyOn(apolloClient, 'getApolloClient').mockResolvedValue(client);
    jest.spyOn(storage, 'saveCustomerToken');
    jest.spyOn(storage, 'loadCustomerToken');
    // Pre-fill the AsyncStorage with customer token to mimic logged in user state
    await storage.saveCustomerToken(customerToken);
    const customerTokenFromCache = await storage.loadCustomerToken();
    expect(customerTokenFromCache).toBe(customerToken);
  });

  afterEach(() => {
    jest.restoreAllMocks();
  });

  test('should clear cache onLogout()', async () => {
    // Setup
    const client = await apolloClient.getApolloClient();
    expect(client).toBeDefined();

    const { result } = renderHook(() => useLogout());
    expect(typeof result.current.logout).toBe('function');

    // Exercise
    await act(async () => {
      await result.current.logout();
    });

    // Verify
    expect(storage.saveCustomerToken).toHaveBeenCalledWith(null);
    const customerTokenFromCache = await storage.loadCustomerToken();
    expect(customerTokenFromCache).toBeNull();
    expect(client.readQuery({ query: IS_LOGGED_IN })).toBeNull();
  });
});
Example #10
Source File: apollo-client.ts    From beancount-mobile with MIT License 5 votes vote down vote up
middlewareLink = new ApolloLink((operation, forward) => {
  operation.setContext({
    headers: { authorization: `Bearer ${store.getState().base.authToken}` },
  });
  return forward(operation);
})
Example #11
Source File: ApolloExtensionsClient.test.ts    From apollo-cache-policies with Apache License 2.0 4 votes vote down vote up
describe('ApolloExtensionsClient', () => {
  let client: ApolloExtensionsClient<NormalizedCacheObject>;
  let cache: InvalidationPolicyCache;

  beforeEach(() => {
    cache = new InvalidationPolicyCache({
      enableCollections: true,
    });
    client = new ApolloExtensionsClient({
      cache,
      link: ApolloLink.empty(),
    });

    cache.writeQuery({
      query: employeesQuery,
      data: employeesResponse,
    });
  });

  describe('watchFragment', () => {
    describe('with a function subscriber', () => {
      test('should emit the employee object', (done) => {
        const observable = client.watchFragment({
          fragment: gql`
            fragment EmployeeFragment on Employee {
              id
              employee_name
            }
          `,
          id: employee.toRef(),
        });

        const subscription = observable.subscribe((val) => {
          expect(val).toEqual({
            __typename: 'Employee',
            id: employee.id,
            employee_name: employee.employee_name,
          });
          // @ts-ignore Type policies is private
          expect(Object.keys(cache.policies.typePolicies.Query.fields).length).toEqual(1);
          subscription.unsubscribe();
          // @ts-ignore Type policies is private
          expect(Object.keys(cache.policies.typePolicies.Query.fields).length).toEqual(0);
          done();
        });
      });

      test('should emit updates', (done) => {
        const observable = client.watchFragment({
          fragment: gql`
            fragment EmployeeFragment on Employee {
              id
              employee_name
            }
          `,
          id: employee.toRef(),
        });

        const subscription = observable.subscribe((val: any) => {
          if (val.employee_name === 'done') {
            expect(val).toEqual({
              __typename: 'Employee',
              id: employee.id,
              employee_name: 'done',
            });

            subscription.unsubscribe();
            done();
          } else {
            expect(val).toEqual({
              __typename: 'Employee',
              id: employee.id,
              employee_name: employee.employee_name,
            });

            cache.writeFragment({
              fragment: gql`
                fragment UpdateEmployee on Employee {
                  employee_name,
                }
              `,
              id: employee.toRef(),
              data: {
                employee_name: 'done',
              },
            });
          }
        });
      });
    });

    describe('with an object subscriber', () => {
      test('should emit the employee object', (done) => {
        const observable = client.watchFragment({
          fragment: gql`
            fragment EmployeeFragment on Employee {
              id
              employee_name
            }
          `,
          id: employee.toRef(),
        });

        const subscription = observable.subscribe({
          next: (val) => {
            expect(val).toEqual({
              __typename: 'Employee',
              id: employee.id,
              employee_name: employee.employee_name,
            });
            subscription.unsubscribe();
            done();
          },
        });
      });
    });
  });

  describe('watchFragmentWhere', () => {
    describe('with a function subscriber', () => {
      test('should emit the employee object', (done) => {
        const observable = client.watchFragmentWhere<EmployeeType>({
          fragment: gql`
            fragment EmployeeFragment on Employee {
              id
              employee_name
            }
          `,
          filter: {
            employee_name: employee.employee_name,
          },
        });

        const subscription = observable.subscribe((val) => {
          expect(val).toEqual([{
            __typename: 'Employee',
            id: employee.id,
            employee_name: employee.employee_name,
          }]);
          subscription.unsubscribe();
          done();
        });
      });

      test('should emit updates', (done) => {
        const observable = client.watchFragmentWhere<EmployeeType>({
          fragment: gql`
            fragment EmployeeFragment on Employee {
              id
              employee_name
            }
          `,
          filter: {
            employee_name: employee.employee_name,
          },
        });

        const subscription = observable.subscribe((val: any) => {
          if (val.length === 0) {
            subscription.unsubscribe();
            done();
          } else {
            expect(val).toEqual([{
              __typename: 'Employee',
              id: employee.id,
              employee_name: employee.employee_name,
            }]);

            cache.writeFragment({
              fragment: gql`
                fragment UpdateEmployee on Employee {
                  employee_name,
                }
              `,
              id: employee.toRef(),
              data: {
                employee_name: 'done',
              },
            });
          }
        });
      });
    });
  });
});
Example #12
Source File: ApolloProvider.tsx    From mStable-apps with GNU Lesser General Public License v3.0 4 votes vote down vote up
ApolloProvider: FC = ({ children }) => {
  const addErrorNotification = useAddErrorNotification()
  const [persisted, setPersisted] = useState(false)
  const network = useNetwork()
  const previousChainId = usePrevious(network.chainId)
  const networkChanged = previousChainId && network.chainId !== previousChainId

  // Serialized array of failed endpoints to be excluded from the client
  const [failedEndpoints] = useState<string>('')

  const handleError = useCallback(
    (message: string, error?: unknown): void => {
      console.error(message, error)

      // Not significant at the moment; falls back to the hosted service
      if (message.includes('Exhausted list of indexers')) return

      let sanitizedError: string = message
      let body: string | undefined
      if (message.includes('Failed to query subgraph deployment')) {
        sanitizedError = `Subgraph: ${message.split(': ')[1] ?? message}`
      }

      if ((error as { operation?: Operation })?.operation?.operationName) {
        body = `Subgraph: ${(error as { operation: Operation }).operation.operationName}`
      }

      addErrorNotification(sanitizedError, body)
    },
    [addErrorNotification],
  )

  useEffect(() => {
    Promise.all(
      Object.keys(caches).map(clientName =>
        persistCache({
          cache: caches[clientName as keyof ApolloClients] as never,
          storage: window.localStorage as never,
          key: `${network.chainId}-${clientName}`,
        }),
      ),
    )
      .catch(_error => {
        console.warn('Cache persist error', _error)
      })
      .finally(() => {
        setPersisted(true)
      })
  }, [setPersisted, network.chainId])

  const apollo = useMemo<{ ready: true; clients: ApolloClients } | { ready: false }>(() => {
    if (!persisted) return { ready: false }

    // const _failedEndpoints = failedEndpoints.split(',')

    const errorLink = onError(error => {
      const { networkError, graphQLErrors } = error
      if (graphQLErrors) {
        graphQLErrors.forEach(({ message, ..._error }) => {
          // if (_failedEndpoints.includes(ctx.uri)) return

          handleError(message, error)

          // On any GraphQL error, mark the endpoint as failed; this may be
          // excessive, but failed endpoints are merely deprioritised rather than
          // excluded completely.
          // _failedEndpoints.push(ctx.uri)
        })
      }

      if (networkError) {
        handleError(networkError.message, error)
      }
      // setFailedEndpoints(_failedEndpoints.join(','))
    })

    const retryIf = (error: { statusCode: number }) => {
      const doNotRetryCodes = [500, 400]
      return !!error && !doNotRetryCodes.includes(error.statusCode)
    }

    const clients = (Object.keys(caches) as AllGqlEndpoints[])
      .map<[AllGqlEndpoints, ApolloClient<NormalizedCacheObject>]>(name => {
        if (!Object.prototype.hasOwnProperty.call(network.gqlEndpoints, name)) {
          return [name, dummyClient]
        }

        const endpoints = network.gqlEndpoints[name as keyof typeof network['gqlEndpoints']]
        const preferred = endpoints.filter(endpoint => !failedEndpoints.split(',').includes(endpoint))[0]
        const fallback = endpoints[0] // There is always a fallback, even if it failed
        const endpoint = preferred ?? fallback
        const timeoutLink = new ApolloLinkTimeout(30000)

        const endpointNameLink = new ApolloLink((operation, forward) => {
          operation.extensions.endpointName = name
          return forward(operation)
        })
        const httpLink = new HttpLink({ uri: endpoint })
        const retryLink = new RetryLink({ delay: { initial: 1e3, max: 5e3, jitter: true }, attempts: { max: 1, retryIf } })
        const link = ApolloLink.from([endpointNameLink, networkStatusLink, retryLink, timeoutLink, errorLink, httpLink])
        const client = new ApolloClient<NormalizedCacheObject>({
          cache: caches[name],
          link,
          defaultOptions: {
            watchQuery: {
              fetchPolicy: 'cache-and-network',
              errorPolicy: 'all',
            },
            query: {
              fetchPolicy: 'cache-first',
              errorPolicy: 'all',
            },
          },
        })

        return [name, client]
      })
      .reduce<ApolloClients>(
        (prev, [clientName, client]) => ({ ...prev, [clientName as keyof ApolloClients]: client }),
        {} as ApolloClients,
      )

    return { ready: true, clients }
  }, [persisted, failedEndpoints, handleError, network])

  useEffect(() => {
    // Reset caches that can have conflicting keyFields on network change
    // This prevents cached data from a previously selected network being used
    // on a newly-selected network
    if (networkChanged && (apollo as { clients: ApolloClients }).clients) {
      ;(apollo as { clients: ApolloClients }).clients.blocks.resetStore().catch(error => {
        console.error(error)
      })
    }
  }, [apollo, networkChanged])

  return apollo.ready ? <apolloClientsCtx.Provider value={apollo.clients}>{children}</apolloClientsCtx.Provider> : <Skeleton />
}