Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

(persisted-fetch) - support persisted get (#804)

* transform to exchange factory

* add changeset

* apply PR comments

* apply POST for persisted-miss

authored by

Jovi De Croock and committed by
GitHub
aec38fcb b118c2ca

+101 -18
+25
.changeset/big-worms-punch.md
··· 1 + --- 2 + '@urql/exchange-persisted-fetch': major 3 + --- 4 + 5 + Make the persistedFetchExchange accept an optional argument, this argument consists of one option `preferGetForPersistedQueries`. 6 + 7 + To migrate you will have to change from 8 + 9 + ```js 10 + import { persistedFetchExchange } from '@urql/exchange-persisted-fetch'; 11 + 12 + createClient({ 13 + exchanges: [persistedFetchExchange], 14 + }); 15 + ``` 16 + 17 + to 18 + 19 + ```js 20 + import { persistedFetchExchange } from '@urql/exchange-persisted-fetch'; 21 + 22 + createClient({ 23 + exchanges: [persistedFetchExchange()], 24 + }); 25 + ```
+34 -5
exchanges/persisted-fetch/src/persistedFetchExchange.test.ts
··· 48 48 49 49 const actual = await pipe( 50 50 fromValue(queryOperation), 51 - persistedFetchExchange(exchangeArgs), 51 + persistedFetchExchange()(exchangeArgs), 52 52 toPromise 53 53 ); 54 54 ··· 74 74 75 75 const actual = await pipe( 76 76 fromValue(queryOperation), 77 - persistedFetchExchange(exchangeArgs), 77 + persistedFetchExchange()(exchangeArgs), 78 78 toPromise 79 79 ); 80 80 ··· 84 84 expect(actual.data).not.toBeUndefined(); 85 85 }); 86 86 87 + it('supports GET exclusively for persisted queries', async () => { 88 + const expectedMiss = { 89 + errors: [{ message: 'PersistedQueryNotFound' }], 90 + }; 91 + 92 + const expectedRetry = { 93 + data: { 94 + test: true, 95 + }, 96 + }; 97 + 98 + fetch 99 + .mockResolvedValueOnce({ json: () => expectedMiss }) 100 + .mockResolvedValueOnce({ json: () => expectedRetry }); 101 + 102 + const actual = await pipe( 103 + fromValue(queryOperation), 104 + persistedFetchExchange({ preferGetForPersistedQueries: true })( 105 + exchangeArgs 106 + ), 107 + toPromise 108 + ); 109 + 110 + expect(fetch).toHaveBeenCalledTimes(2); 111 + expect(fetch.mock.calls[0][1].method).toEqual('GET'); 112 + expect(fetch.mock.calls[1][1].method).toEqual('POST'); 113 + expect(actual.data).not.toBeUndefined(); 114 + }); 115 + 87 116 it('supports unsupported persisted query errors', async () => { 88 117 const expectedMiss = { 89 118 errors: [{ message: 'PersistedQueryNotSupported' }], ··· 102 131 103 132 const actual = await pipe( 104 133 fromArray([queryOperation, queryOperation]), 105 - persistedFetchExchange(exchangeArgs), 134 + persistedFetchExchange()(exchangeArgs), 106 135 toPromise 107 136 ); 108 137 ··· 118 147 119 148 pipe( 120 149 fromValue(mutationOperation), 121 - persistedFetchExchange(exchangeArgs), 150 + persistedFetchExchange()(exchangeArgs), 122 151 subscribe(result) 123 152 ); 124 153 ··· 143 172 144 173 await pipe( 145 174 fromValue(queryOperation), 146 - persistedFetchExchange(exchangeArgs), 175 + persistedFetchExchange()(exchangeArgs), 147 176 toPromise 148 177 ); 149 178
+42 -13
exchanges/persisted-fetch/src/persistedFetchExchange.ts
··· 30 30 31 31 import { hash } from './sha256'; 32 32 33 - export const persistedFetchExchange: Exchange = ({ 34 - forward, 35 - dispatchDebug, 36 - }) => { 33 + interface PersistedFetchExchangeOptions { 34 + preferGetForPersistedQueries?: boolean; 35 + } 36 + 37 + export const persistedFetchExchange = ( 38 + options?: PersistedFetchExchangeOptions 39 + ): Exchange => ({ forward, dispatchDebug }) => { 40 + if (!options) options = {}; 41 + 37 42 let supportsPersistedQueries = true; 38 43 39 44 return ops$ => { ··· 52 57 if (!supportsPersistedQueries) { 53 58 // Runs the usual non-persisted fetchExchange query logic 54 59 return pipe( 55 - makePersistedFetchSource(operation, body, dispatchDebug), 60 + makePersistedFetchSource(operation, body, dispatchDebug, false), 56 61 takeUntil(teardown$) 57 62 ); 58 63 } ··· 72 77 }, 73 78 }; 74 79 75 - return makePersistedFetchSource(operation, body, dispatchDebug); 80 + return makePersistedFetchSource( 81 + operation, 82 + body, 83 + dispatchDebug, 84 + !!(options as PersistedFetchExchangeOptions) 85 + .preferGetForPersistedQueries 86 + ); 76 87 }), 77 88 mergeMap(result => { 78 89 if (result.error && isPersistedUnsupported(result.error)) { ··· 81 92 body.extensions = undefined; 82 93 // Disable future persisted queries 83 94 supportsPersistedQueries = false; 84 - return makePersistedFetchSource(operation, body, dispatchDebug); 95 + return makePersistedFetchSource( 96 + operation, 97 + body, 98 + dispatchDebug, 99 + false 100 + ); 85 101 } else if (result.error && isPersistedMiss(result.error)) { 86 102 // Add query to the body but leave SHA256 hash intact 87 103 body.query = query; 88 - return makePersistedFetchSource(operation, body, dispatchDebug); 104 + return makePersistedFetchSource( 105 + operation, 106 + body, 107 + dispatchDebug, 108 + false 109 + ); 89 110 } 90 111 91 112 return fromValue(result); ··· 108 129 const makePersistedFetchSource = ( 109 130 operation: Operation, 110 131 body: FetchBody, 111 - dispatchDebug: ExchangeInput['dispatchDebug'] 132 + dispatchDebug: ExchangeInput['dispatchDebug'], 133 + useGet: boolean 112 134 ): Source<OperationResult> => { 135 + const newOperation = { 136 + ...operation, 137 + context: { 138 + ...operation.context, 139 + preferGetMethod: useGet || operation.context.preferGetMethod, 140 + }, 141 + }; 113 142 const url = makeFetchURL( 114 - operation, 143 + newOperation, 115 144 body.query ? body : { ...body, query: '' } 116 145 ); 117 - const fetchOptions = makeFetchOptions(operation, body); 146 + const fetchOptions = makeFetchOptions(newOperation, body); 118 147 119 148 dispatchDebug({ 120 149 type: 'fetchRequest', 121 150 message: !body.query 122 151 ? 'A fetch request for a persisted query is being executed.' 123 152 : 'A fetch request is being executed.', 124 - operation, 153 + operation: newOperation, 125 154 data: { 126 155 url, 127 156 fetchOptions, ··· 129 158 }); 130 159 131 160 return pipe( 132 - makeFetchSource(operation, url, fetchOptions), 161 + makeFetchSource(newOperation, url, fetchOptions), 133 162 onPush(result => { 134 163 const persistFail = 135 164 result.error &&