felicity-lims/webapp/urql.ts
2024-06-29 15:19:21 +02:00

84 lines
2.7 KiB
TypeScript

import {
createClient,
cacheExchange,
fetchExchange,
errorExchange,
subscriptionExchange,
CombinedError,
Operation,
Exchange,
} from '@urql/vue';
import { SubscriptionClient } from 'subscriptions-transport-ws';
import { pipe, tap } from 'wonka';
import { getAuthData, authLogout } from '@/auth';
import { GQL_BASE_URL, WS_BASE_URL } from '@/conf';
import useNotifyToast from '@/composables/alert_toast';
const { toastError } = useNotifyToast();
const subscriptionClient = new SubscriptionClient(WS_BASE_URL, {
reconnect: true,
lazy: true,
connectionParams: () => {
const authData = getAuthData();
return {
headers: {
...(authData?.auth?.token && {
'x-felicity-user-id': 'felicity-user-x',
'x-felicity-role': 'felicity-role-x',
Authorization: `Bearer ${authData?.auth?.token}`,
}),
},
};
},
});
const resultInterceptorExchange: Exchange =
({ forward }) =>
ops$ =>
pipe(
ops$,
forward,
tap(operationResult => {})
);
export const urqlClient = createClient({
url: GQL_BASE_URL,
exchanges: [
cacheExchange,
errorExchange({
onError: (error: CombinedError, operation: Operation) => {
let isAuthError = false;
if (!error.graphQLErrors || error.graphQLErrors.length === 0) {
isAuthError = error.message === '[Network] Failed to fetch';
} else {
isAuthError = error.graphQLErrors.some(e => e.extensions?.code === 'FORBIDDEN');
}
if (isAuthError) {
toastError('Unknown Network Error Encountered');
authLogout();
}
},
}),
resultInterceptorExchange,
fetchExchange,
subscriptionExchange({
forwardSubscription: operation => subscriptionClient.request(operation) as any,
}),
],
fetchOptions: () => {
const authData = getAuthData();
return {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PATCH, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept, Authorization',
...(authData?.auth?.token && {
Authorization: `Bearer ${authData?.auth?.token}`,
}),
},
};
},
});