Skip to content

Instantly share code, notes, and snippets.

@timhanlon
Last active July 20, 2018 22:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timhanlon/58822149b6c528ad42b8e44fd9762f81 to your computer and use it in GitHub Desktop.
Save timhanlon/58822149b6c528ad42b8e44fd9762f81 to your computer and use it in GitHub Desktop.
apollo-module v4.0.0-rc.0 token issue with multiple clients
import Vue from 'vue'
import VueApollo from 'vue-apollo'
import 'isomorphic-fetch'
import { createApolloClient, restartWebsockets } from 'vue-cli-plugin-apollo/graphql-client'
import jsCookie from 'js-cookie'
import cookie from 'cookie'
import { InMemoryCache } from 'apollo-cache-inmemory'
Vue.use(VueApollo)
export default (ctx, inject) => {
const providerOptions = { clients: {} }
const { app, beforeNuxtRender, req } = ctx
const AUTH_TOKEN_NAME = 'apollo-token'
const AUTH_TYPE = 'Bearer '
// Config
const gamesTokenName = '' || AUTH_TOKEN_NAME
function defaultGetAuth () {
let token
if(process.server){
const cookies = cookie.parse((req && req.headers.cookie) || '')
token = cookies[gamesTokenName]
} else {
token = jsCookie.get(gamesTokenName)
}
return token ? AUTH_TYPE + token : ''
}
let gamesClientConfig;
gamesClientConfig = require('~/apollo/client-configs/games.js')
if ('default' in gamesClientConfig) {
gamesClientConfig = gamesClientConfig.default
}
gamesClientConfig = gamesClientConfig(ctx)
const gamesCache = gamesClientConfig.cache
? gamesClientConfig.cache
: new InMemoryCache()
if (!process.server) {
gamesCache.restore(window.__NUXT__ ? window.__NUXT__.apollo.games : null)
}
if (!gamesClientConfig.getAuth) {
gamesClientConfig.getAuth = defaultGetAuth
}
gamesClientConfig.ssr = !!process.server
gamesClientConfig.cache = gamesCache
gamesClientConfig.tokenName = gamesTokenName
// Create apollo client
let gamesApolloCreation = createApolloClient({
...gamesClientConfig
})
gamesApolloCreation.apolloClient.wsClient = gamesApolloCreation.wsClient
providerOptions.clients.games = gamesApolloCreation.apolloClient
const defaultTokenName = '' || AUTH_TOKEN_NAME
function defaultGetAuth () {
let token
if(process.server){
const cookies = cookie.parse((req && req.headers.cookie) || '')
token = cookies[defaultTokenName]
} else {
token = jsCookie.get(defaultTokenName)
}
return token ? AUTH_TYPE + token : ''
}
let defaultClientConfig;
defaultClientConfig = require('~/apollo/client-configs/default.js')
if ('default' in defaultClientConfig) {
defaultClientConfig = defaultClientConfig.default
}
defaultClientConfig = defaultClientConfig(ctx)
const defaultCache = defaultClientConfig.cache
? defaultClientConfig.cache
: new InMemoryCache()
if (!process.server) {
defaultCache.restore(window.__NUXT__ ? window.__NUXT__.apollo.defaultClient : null)
}
if (!defaultClientConfig.getAuth) {
defaultClientConfig.getAuth = defaultGetAuth
}
defaultClientConfig.ssr = !!process.server
defaultClientConfig.cache = defaultCache
defaultClientConfig.tokenName = defaultTokenName
// Create apollo client
let defaultApolloCreation = createApolloClient({
...defaultClientConfig
})
defaultApolloCreation.apolloClient.wsClient = defaultApolloCreation.wsClient
providerOptions.defaultClient = defaultApolloCreation.apolloClient
const vueApolloOptions = Object.assign(providerOptions, {
errorHandler (error) {
console.log('%cError', 'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;', error.message)
}
})
const apolloProvider = new VueApollo(vueApolloOptions)
// Allow access to the provider in the context
app.apolloProvider = apolloProvider
// Install the provider into the app
app.provide = apolloProvider.provide()
if (process.server) {
beforeNuxtRender(async ({ Components, nuxtState }) => {
Components.forEach((Component) => {
// Fix https://github.com/nuxt-community/apollo-module/issues/19
if (Component.options && Component.options.apollo && Component.options.apollo.$init) {
delete Component.options.apollo.$init
}
})
await apolloProvider.prefetchAll(ctx, Components)
nuxtState.apollo = apolloProvider.getStates()
})
}
inject('apolloHelpers', {
onLogin: async (token, apolloClient = apolloProvider.defaultClient) => {
if (token) {
jsCookie.set(AUTH_TOKEN_NAME, token)
} else {
jsCookie.remove(AUTH_TOKEN_NAME)
}
if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient)
try {
await apolloClient.resetStore()
} catch (e) {
// eslint-disable-next-line no-console
console.log('%cError on cache reset (setToken)', 'color: orange;', e.message)
}
},
onLogout: async (apolloClient = apolloProvider.defaultClient) => {
jsCookie.remove(AUTH_TOKEN_NAME)
if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient)
try {
await apolloClient.resetStore()
} catch (e) {
// eslint-disable-next-line no-console
console.log('%cError on cache reset (logout)', 'color: orange;', e.message)
}
},
getToken: (tokenName = AUTH_TOKEN_NAME) => {
if(process.server){
const cookies = cookie.parse((req && req.headers.cookie) || '')
return cookies && cookies[tokenName]
}
return jsCookie.get(tokenName)
}
})
}
// Adapted from https://github.com/GraphCMS/graphcms-examples/blob/master/nuxt-apollo-blog/apollo/client-configs/default.js
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { toIdValue } from 'apollo-utilities'
const GRAPHQL_API = 'xyz'
// If a slug exists, use it as the cache key
const dataIdFromObject = result => {
if (result.slug) return `${result.__typename}:${result.slug}`;
}
// Tell Apollo how to find posts in the cache (by slug)
// Adapted from this Github issue: https://github.com/apollographql/apollo-client/issues/1934
// cacheRedirect documentation: https://www.apollographql.com/docs/react/advanced/caching.html#cacheRedirect
// toIdValue documentation: https://www.apollographql.com/docs/react/features/performance.html#cache-redirects
const cacheRedirects = {
Query: {
postBy: (_, { slug }) => toIdValue(dataIdFromObject({ __typename: 'Post', slug })),
post: (_, { slug }) => toIdValue(dataIdFromObject({ __typename: 'Post', slug }))
}
}
export default () => ({
link: new HttpLink({ uri: GRAPHQL_API }),
cache: new InMemoryCache({
cacheRedirects: cacheRedirects,
dataIdFromObject: dataIdFromObject,
}),
// connectToDevTools: true
})
// There is a good working example of caching by Guillaume Chau here: https://github.com/Akryum/vue-apollo/issues/139
export default function(context){
return {
httpEndpoint: 'http://localhost:3000/games/graphql',
connectToDevTools: true
}
}
apollo: {
clientConfigs: {
games: '~/apollo/client-configs/games.js',
default: '~/apollo/client-configs/default.js',
}
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment