1import { Client, fetchExchange, gql } from 'urql';
2import { authExchange } from '@urql/exchange-auth';
3import { cacheExchange } from '@urql/exchange-graphcache';
4
5const cache = cacheExchange({
6 updates: {
7 Mutation: {
8 createLink(result, _args, cache, _info) {
9 const LinksList = gql`
10 query Links($first: Int!) {
11 links(first: $first) {
12 nodes {
13 id
14 }
15 }
16 }
17 `;
18
19 const linksPages = cache
20 .inspectFields('Query')
21 .filter(field => field.fieldName === 'links');
22
23 if (linksPages.length > 0) {
24 const lastField = linksPages[linksPages.length - 1];
25
26 cache.updateQuery(
27 {
28 query: LinksList,
29 variables: { first: lastField.arguments.first },
30 },
31 data => {
32 return {
33 ...data,
34 links: {
35 ...data.links,
36 nodes: [...data.links.nodes, result.createLink.node],
37 },
38 };
39 }
40 );
41 }
42 },
43 },
44 },
45});
46
47const auth = authExchange(async utilities => {
48 let token = localStorage.getItem('authToken');
49
50 return {
51 addAuthToOperation(operation) {
52 if (!token) return operation;
53 return token
54 ? utilities.appendHeaders(operation, {
55 Authorization: `Bearer ${token}`,
56 })
57 : operation;
58 },
59 didAuthError(error) {
60 return error.graphQLErrors.some(
61 e => e.extensions?.code === 'UNAUTHORIZED'
62 );
63 },
64 willAuthError(operation) {
65 if (!token) {
66 // Detect our login mutation and let this operation through:
67 return (
68 operation.kind !== 'mutation' ||
69 // Here we find any mutation definition with the "signin" field
70 !operation.query.definitions.some(definition => {
71 return (
72 definition.kind === 'OperationDefinition' &&
73 definition.selectionSet.selections.some(node => {
74 // The field name is just an example, since register may also be an exception
75 return node.kind === 'Field' && node.name.value === 'signin';
76 })
77 );
78 })
79 );
80 }
81 return false;
82 },
83 async refreshAuth() {
84 token = localStorage.getItem('authToken');
85 if (!token) {
86 // This is where auth has gone wrong and we need to clean up and redirect to a login page
87 localStorage.clear();
88 window.location.reload();
89 }
90 },
91 };
92});
93
94const client = new Client({
95 url: 'https://trygql.formidable.dev/graphql/web-collections',
96 exchanges: [cache, auth, fetchExchange],
97});
98
99export default client;