Skip to content

Instantly share code, notes, and snippets.

@praveenpuglia
Created May 31, 2019 09:22
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 praveenpuglia/5c17969519160d7f79cce3280c4e3dfa to your computer and use it in GitHub Desktop.
Save praveenpuglia/5c17969519160d7f79cce3280c4e3dfa to your computer and use it in GitHub Desktop.
vue-apollo.ts configuration
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