guesstimate/client/src/util/apollo.ts

77 lines
2.1 KiB
TypeScript

import { ApolloClient, InMemoryCache, HttpLink, from } from '@apollo/client';
import { Config } from '../config';
import { WebSocketLink } from "@apollo/client/link/ws";
import { RetryLink } from "@apollo/client/link/retry";
import { onError } from "@apollo/client/link/error";
import { SubscriptionClient } from "subscriptions-transport-ws";
import { User } from '../types/user';
export function createClient(setLoggedIn: (boolean) => void) {
const subscriptionClient = new SubscriptionClient(Config.subscriptionEndpoint, {
reconnect: true,
});
const errorLink = onError(({ operation }) => {
const { response } = operation.getContext();
if (response.status === 401) setLoggedIn(false);
});
const retryLink = new RetryLink({attempts: {max: 2}}).split(
(operation) => operation.operationName === 'subscription',
new WebSocketLink(subscriptionClient),
new HttpLink({
uri: Config.graphQLEndpoint,
credentials: 'include',
})
);
const cache = new InMemoryCache({});
return new ApolloClient<any>({
cache: cache,
link: from([
errorLink,
retryLink
]),
defaultOptions: {
watchQuery: {
fetchPolicy: 'cache-and-network',
errorPolicy: 'ignore',
},
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all',
},
mutate: {
errorPolicy: 'all',
},
}
});
}
export function mergeArrayByField<T>(fieldName: string) {
return (existing: T[] = [], incoming: T[], { readField, mergeObjects }) => {
const merged: any[] = existing ? existing.slice(0) : [];
const objectFieldToIndex: Record<string, number> = Object.create(null);
if (existing) {
existing.forEach((obj, index) => {
objectFieldToIndex[readField(fieldName, obj)] = index;
});
}
incoming.forEach(obj => {
const field = readField(fieldName, obj);
const index = objectFieldToIndex[field];
if (typeof index === "number") {
merged[index] = mergeObjects(merged[index], obj);
} else {
objectFieldToIndex[name] = merged.length;
merged.push(obj);
}
});
return merged;
}
}