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.

fix(auth): prevent retrying the operation produced by `mutate` (#3164)

Co-authored-by: Phil Pluckthun <phil@kitten.sh>

authored by

Jovi De Croock
Phil Pluckthun
and committed by
GitHub
8e148492 ac439b7c

+27 -6
+5
.changeset/strange-elephants-serve.md
··· 1 + --- 2 + '@urql/exchange-auth': patch 3 + --- 4 + 5 + Fix operations created by `utilities.mutate()` erroneously being retried and sent again like a regular operation
+22 -6
exchanges/auth/src/authExchange.ts
··· 20 20 Exchange, 21 21 DocumentInput, 22 22 AnyVariables, 23 + OperationInstance, 23 24 } from '@urql/core'; 24 25 25 26 /** Utilities to use while refreshing authentication tokens. */ ··· 199 200 init: (utilities: AuthUtilities) => Promise<AuthConfig> 200 201 ): Exchange { 201 202 return ({ client, forward }) => { 202 - const bypassQueue = new WeakSet<Operation>(); 203 + const bypassQueue = new Set<OperationInstance | undefined>(); 203 204 const retries = makeSubject<Operation>(); 204 205 205 206 let retryQueue = new Map<number, Operation>(); ··· 233 234 result$, 234 235 onStart(() => { 235 236 const operation = addAuthToOperation(baseOperation); 236 - bypassQueue.add(operation); 237 + bypassQueue.add( 238 + operation.context._instance as OperationInstance 239 + ); 237 240 retries.next(operation); 238 241 }), 239 - filter(result => result.operation.key === baseOperation.key), 242 + filter( 243 + result => 244 + result.operation.key === baseOperation.key && 245 + baseOperation.context._instance === 246 + result.operation.context._instance 247 + ), 240 248 take(1), 241 249 toPromise 242 250 ); ··· 311 319 const opsWithAuth$ = pipe( 312 320 merge([retries.source, pendingOps$]), 313 321 map(operation => { 314 - if (operation.context.authAttempt) { 315 - return addAuthToOperation(operation); 316 - } else if (bypassQueue.has(operation)) { 322 + if ( 323 + operation.context._instance && 324 + bypassQueue.has(operation.context._instance) 325 + ) { 317 326 return operation; 327 + } else if (operation.context.authAttempt) { 328 + return addAuthToOperation(operation); 318 329 } else if (authPromise) { 319 330 if (!retryQueue.has(operation.key)) { 320 331 retryQueue.set( ··· 341 352 result$, 342 353 filter(result => { 343 354 if ( 355 + !bypassQueue.has(result.operation.context._instance) && 344 356 result.error && 345 357 didAuthError(result) && 346 358 !result.operation.context.authAttempt 347 359 ) { 348 360 refreshAuth(result.operation); 349 361 return false; 362 + } 363 + 364 + if (bypassQueue.has(result.operation.context._instance)) { 365 + bypassQueue.delete(result.operation.context._instance); 350 366 } 351 367 352 368 return true;