import { ApolloClient, ApolloLink, InMemoryCache, split } from "@apollo/client"; import { setContext } from "@apollo/client/link/context"; import { HttpLink } from "@apollo/client/link/http"; //"apollo-link-http"; import { RetryLink } from "@apollo/client/link/retry"; import { WebSocketLink } from "@apollo/client/link/ws"; import { getMainDefinition } from "@apollo/client/utilities"; //import { split } from "apollo-link"; import apolloLogger from "apollo-link-logger"; //import axios from "axios"; import { auth } from "../firebase/firebase.utils"; import errorLink from "../graphql/apollo-error-handling"; import { SentryLink } from "apollo-link-sentry"; //import { store } from "../redux/store"; const httpLink = new HttpLink({ uri: import.meta.env.VITE_APP_GRAPHQL_ENDPOINT }); const wsLink = new WebSocketLink({ uri: import.meta.env.VITE_APP_GRAPHQL_ENDPOINT_WS, options: { lazy: true, reconnect: true, connectionParams: async () => { const token = auth.currentUser && (await auth.currentUser.getIdToken()); if (token) { return { headers: { authorization: token ? `Bearer ${token}` : "" } }; } } } }); const roundTripLink = new ApolloLink((operation, forward) => { // Called before operation is sent to server operation.setContext({ start: new Date() }); return forward(operation).map((data) => { // Called after server responds const time = new Date() - operation.getContext().start; // console.log( // `Operation ${operation.operationName} took ${time} to complete` // ); TrackExecutionTime(operation.operationName, time); return data; }); }); const TrackExecutionTime = async (operationName, time) => { // if (process.env.NODE_ENV === "development") return; // const rdxStore = store.getState(); // try { // axios.post("/ioevent", { // operationName, // time, // dbevent: true, // user: // rdxStore.user && // rdxStore.user.currentUser && // rdxStore.user.currentUser.email, // imexshopid: // rdxStore.user && // rdxStore.user.bodyshop && // rdxStore.user.bodyshop.imexshopid, // }); // } catch (error) { // console.log("IOEvent Error", error); // } }; const subscriptionMiddleware = { applyMiddleware: async (options, next) => { options.authToken = auth.currentUser && (await auth.currentUser.getIdToken()); next(); } }; wsLink.subscriptionClient.use([subscriptionMiddleware]); const link = split( // split based on operation type ({ query }) => { const definition = getMainDefinition(query); // console.log( // "##Intercepted GQL Transaction : " + // definition.operation + // "|" + // definition.name.value + // "##", // query // ); return definition.kind === "OperationDefinition" && definition.operation === "subscription"; }, wsLink, httpLink ); const authLink = setContext((_, { headers }) => { return ( auth.currentUser && auth.currentUser .getIdToken() .then((token) => { if (token) { return { headers: { ...headers, authorization: token ? `Bearer ${token}` : "" } }; } else { console.error("Authentication error. Unable to add authorization token because it was empty."); return { headers }; } }) .catch((error) => { console.error("Authentication error. Unable to add authorization token.", error.message); return { headers }; }) ); }); const retryLink = new RetryLink({ delay: { initial: 500, max: 5, jitter: true }, attempts: { max: 5, retryIf: (error, _operation) => !!error } }); const middlewares = []; if (import.meta.env.DEV) { middlewares.push(apolloLogger); } middlewares.push( new SentryLink().concat(roundTripLink.concat(retryLink.concat(errorLink.concat(authLink.concat(link))))) ); const cache = new InMemoryCache({}); const client = new ApolloClient({ link: ApolloLink.from(middlewares), cache, connectToDevTools: import.meta.env.DEV, defaultOptions: { watchQuery: { fetchPolicy: "network-only", nextFetchPolicy: "network-only", errorPolicy: "ignore" }, query: { fetchPolicy: "network-only", errorPolicy: "all" }, mutate: { errorPolicy: "all" } } }); export default client;