🚨 Announcement: A New Chapter for Vendure read more

Configuring a GraphQL Client

This guide provides examples of how to set up popular GraphQL clients to work with the Vendure Shop API. These examples are designed to work with both the bearer and cookie methods of managing sessions.

Apollo Client

Here’s an example configuration for Apollo Client with a React app.

import {
  ApolloClient,
  ApolloLink, 
  HttpLink,
  InMemoryCache,
} from '@apollo/client'
import { setContext } from '@apollo/client/link/context'

const AUTH_TOKEN_KEY = 'auth_token';

const httpLink = new HttpLink({
  uri: `${process.env.NEXT_PUBLIC_URL_SHOP_API}/shop-api`,
  withCredentials: true,
});

const afterwareLink = new ApolloLink((operation, forward) => {
  return forward(operation).map((response) => {
    const context = operation.getContext();
    const authHeader = context.response.headers.get('vendure-auth-token');
    if (authHeader) {
      // If the auth token has been returned by the Vendure
      // server, we store it in localStorage  
      localStorage.setItem(AUTH_TOKEN_KEY, authHeader);
    }
    return response;
  });
});

const client = new ApolloClient({
  link: ApolloLink.from([
    setContext(() => {
      const authToken = localStorage.getItem(AUTH_TOKEN_KEY)
      if (authToken) {
        // If we have stored the authToken from a previous
        // response, we attach it to all subsequent requests.  
        return {
          headers: {
            authorization: `Bearer ${authToken}`,
          },
        }
      }
    }),
    afterwareLink,
    httpLink,
  ]),
  cache: new InMemoryCache(),
})

export default client;

Urql

Here’s an example using the urql client:

import * as React from "react"
import { createClient, dedupExchange, fetchExchange, Provider } from "urql"
import { cacheExchange} from "@urql/exchange-graphcache"
import { makeOperation} from "@urql/core"

const AUTH_TOKEN_KEY = "auth_token"

const client = createClient({
  fetch: (input, init) => {
    const token = localStorage.getItem(AUTH_TOKEN_KEY)
    if (token) {
      const headers = input instanceof Request ? input.headers : init.headers;
      headers['Authorization'] = `Bearer ${token}`;
    }
    return fetch(input, init).then(response => {
      const token = response.headers.get("vendure-auth-token")
      if (token) {
        localStorage.setItem(AUTH_TOKEN_KEY, token)
      }
      return response
    })
  },
  url: process.env.NEXT_PUBLIC_URL_SHOP_API,
  exchanges: [
    dedupExchange,
    cacheExchange({
      updates: {
        Mutation: {
          addItemToOrder: (parent, args, cache) => {
            const activeOrder = cache.resolve('Query', 'activeOrder');
            if (activeOrder == null) {
              // The first time that the `addItemToOrder` mutation is called in a session,
              // the `activeOrder` query needs to be manually updated to point to the newly-created
              // Order type. From then on, the graphcache will handle keeping it up-to-date.
              cache.link('Query', 'activeOrder', parent.addItemToOrder);
            }
          },
        },
      },
    }),
    fetchExchange,
  ],
})

export const App = () => (
  <Provider value={client}><YourRoutes /></Provider>
)