Created
May 31, 2019 09:22
-
-
Save praveenpuglia/5c17969519160d7f79cce3280c4e3dfa to your computer and use it in GitHub Desktop.
vue-apollo.ts configuration
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vue from 'vue'; | |
import VueApollo from 'vue-apollo'; | |
import { | |
createApolloClient, | |
restartWebsockets | |
} from 'vue-cli-plugin-apollo/graphql-client'; | |
import ApolloClient from 'apollo-client'; | |
import { InMemoryCache } from 'apollo-cache-inmemory'; | |
import { SubscriptionClient } from 'subscriptions-transport-ws'; | |
import router from '@/router'; | |
import { typeDefs } from '@/graphql/local/typedefs'; | |
/** | |
* Extract all the graphql endpoints from current enviroment | |
*/ | |
const endpoints = Object.keys(process.env) | |
.filter(variable => { | |
return variable.startsWith('VUE_APP_GRAPHQL_'); | |
}) | |
.map(variable => process.env[variable]) as string[]; | |
/** | |
* Name of all the graphql clients extracted from the endpoints in env files | |
*/ | |
export const clientNames = endpoints.map(endpoint => { | |
return endpoint.substr(endpoint.lastIndexOf('/') + 1); | |
}); | |
/** | |
* All the graphql endpoints as enum for better tooling | |
* on the components side. | |
*/ | |
export enum apolloClients { | |
reports = 'reports', | |
care = 'care', | |
admin = 'admin' | |
} | |
export type VueApolloClient = ApolloClient<InMemoryCache> & { | |
wsClient: SubscriptionClient; | |
}; | |
export interface VueApolloClients { | |
[key: string]: VueApolloClient; | |
} | |
// Install the vue plugin | |
Vue.use(VueApollo); | |
// Name of the localStorage item | |
export const AUTH_TOKEN = 'apollo-token'; | |
// Http endpoint | |
const httpEndpoint = process.env.VUE_APP_GRAPHQL_CARE || 'http://localhost'; | |
// Config | |
const defaultOptions: any = { | |
// You can use `https` for secure connection (recommended in production) | |
httpEndpoint, | |
// You can use `wss` for secure connection (recommended in production) | |
// Use `null` to disable subscriptions | |
wsEndpoint: null, // process.env.VUE_APP_GRAPHQL_WS || 'ws://localhost:4000/graphql', | |
// LocalStorage token | |
tokenName: AUTH_TOKEN, | |
// Enable Automatic Query persisting with Apollo Engine | |
persisting: false, | |
// Use websockets for everything (no HTTP) | |
// You need to pass a `wsEndpoint` for this to work | |
websocketsOnly: false, | |
// Is being rendered on the server? | |
ssr: false | |
// Override default apollo link | |
// note: don't override httpLink here, specify httpLink options in the | |
// httpLinkOptions property of defaultOptions. | |
// link: myLink | |
// Override default cache | |
// cache: myCache | |
// Override the way the Authorization header is set | |
// getAuth: (tokenName) => ... | |
// Additional ApolloClient options | |
// apollo: { ... } | |
// Client local data (see apollo-link-state) | |
// clientState: { resolvers: { ... }, defaults: { ... } } | |
}; | |
// Call this in the Vue app file | |
export function createProvider(options = {}) { | |
// Create apollo client | |
const clientInstances = generateClients(options); | |
// Create vue apollo provider | |
const apolloProvider = new VueApollo({ | |
defaultClient: clientInstances.care, | |
defaultOptions: { | |
$query: { | |
fetchPolicy: 'cache-and-network' | |
} | |
}, | |
clients: clientInstances, | |
errorHandler(error) { | |
if (error.networkError && error.networkError.statusCode === 401) { | |
// TODO: Remember the route used was looking to go to | |
// so we can redirect them back to the same place. | |
onLogout(clientInstances); | |
router.push({ | |
name: 'login', | |
params: { | |
message: | |
'The page you requested requires authentication. Please login!' | |
}, | |
query: { | |
redirect: router.currentRoute.path | |
} | |
}); | |
} | |
/* tslint:disable-next-line:no-console */ | |
console.log( | |
'%cError', | |
'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;', | |
error.message | |
); | |
} | |
}); | |
return apolloProvider; | |
} | |
// Manually call this when user log in | |
// TODO: Make them work with multiple clients if required. | |
export async function onLogin(clients: VueApolloClients, token: string) { | |
if (typeof localStorage !== 'undefined' && token) { | |
localStorage.setItem(AUTH_TOKEN, token); | |
} | |
resetCacheAndSockets(clients); | |
} | |
// Manually call this when user log out | |
// TODO: Make them work with multiple clients if required. | |
export async function onLogout(clients: VueApolloClients) { | |
if (typeof localStorage !== 'undefined') { | |
localStorage.removeItem(AUTH_TOKEN); | |
} | |
resetCacheAndSockets(clients); | |
} | |
async function resetCacheAndSockets(clients: VueApolloClients) { | |
for (const client of Object.keys(clients)) { | |
// if (clients[client].wsClient) { | |
// restartWebsockets(clients[client].wsClient); | |
// } | |
try { | |
await clients[client].cache.reset(); | |
} catch (e) { | |
/* tslint:disable-next-line:no-console */ | |
console.log('%cError on cache reset', 'color: orange;', e.message); | |
} | |
} | |
} | |
function generateClients(userOptions: object): VueApolloClients { | |
const clientInstances: { [clientName: string]: VueApolloClient } = {}; | |
(endpoints as string[])!.forEach((endpoint, index) => { | |
let options = { ...defaultOptions }; | |
// for care, the default client, add local state. | |
if (clientNames[index] === 'care') { | |
options = { | |
...options, | |
typeDefs, | |
clientState: { | |
resolvers: { | |
Mutation: { | |
setLoginStatus( | |
_: any, | |
{ isLoggedIn }: { isLoggedIn: boolean }, | |
{ cache }: { cache: InMemoryCache } | |
) { | |
const data = { | |
user: { | |
__typename: 'User', | |
isLoggedIn | |
} | |
}; | |
return cache.writeData({ data }); | |
} | |
} | |
}, | |
defaults: { | |
user: { | |
__typename: 'User', | |
isLoggedIn: false | |
} | |
} | |
} | |
}; | |
} | |
options.httpEndpoint = `${endpoint}/graphql`; | |
const { apolloClient } = createApolloClient({ | |
...options, | |
...userOptions | |
}); | |
clientInstances[clientNames[index]] = apolloClient; | |
}); | |
return clientInstances; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment