Files
TheGame/packages/web/graphql/client.ts
2022-02-01 11:29:22 -07:00

99 lines
2.6 KiB
TypeScript

import { retryExchange } from '@urql/exchange-retry';
import { CONFIG } from 'config';
import { getTokenFromStore } from 'lib/auth';
import { NextComponentType } from 'next';
import {
initUrqlClient,
NextUrqlContext,
withUrqlClient,
WithUrqlProps,
} from 'next-urql';
import React, { createElement } from 'react';
import {
cacheExchange,
Client,
CombinedError,
createClient,
// debugExchange,
dedupExchange,
fetchExchange,
ssrExchange,
} from 'urql';
const errorHasResponseTimeout = (err: CombinedError): boolean =>
err.graphQLErrors.length > 0 &&
!!err.graphQLErrors.find((e) => e.message === 'ResponseTimeout');
const retryExchangeFunc = retryExchange({
maxNumberAttempts: 5,
initialDelayMs: 1000,
randomDelay: true,
retryIf: (error) => {
console.debug('GraphQL Retry', { error }); // eslint-disable-line no-console
return !!(errorHasResponseTimeout(error) || error.networkError);
},
});
export const client = createClient({
url: CONFIG.graphqlURL,
suspense: false,
exchanges: [dedupExchange, cacheExchange, retryExchangeFunc, fetchExchange],
});
export const getSsrClient = (): [Client, ReturnType<typeof ssrExchange>] => {
const ssrCache = ssrExchange({ isClient: false });
const ssrClient = initUrqlClient(
{
url: CONFIG.graphqlURL,
exchanges: [
// debugExchange,
dedupExchange,
cacheExchange,
ssrCache,
retryExchangeFunc,
fetchExchange,
],
},
false,
);
if (!ssrClient) throw new Error('wtf');
return [ssrClient, ssrCache];
};
// We do this to enable ssr cache on pages that are not directly wrapped in 'withUrqlClient' (but on _app)
// https://github.com/FormidableLabs/urql/issues/1481
const customWithUrqlClient = (
// eslint-disable-next-line @typescript-eslint/ban-types
WithUrql: NextComponentType<NextUrqlContext, {}, WithUrqlProps>,
): React.FC<WithUrqlProps> => ({ pageProps, urqlState, ...props }) =>
createElement(WithUrql, {
urqlState: pageProps.urqlState || urqlState,
pageProps,
...props,
});
export const wrapUrqlClient = (AppOrPage: React.FC<WithUrqlProps>) =>
customWithUrqlClient(
withUrqlClient(
(_ssrExchange, ctx) => ({
url: CONFIG.graphqlURL,
fetchOptions: () => {
const token = ctx
? ctx?.req?.headers?.authorization
: getTokenFromStore();
return {
headers: {
Authorization: token ? `Bearer ${token}` : '',
},
};
},
}),
{
neverSuspend: true,
ssr: false,
},
)(AppOrPage),
);