@@ -52,7 +52,7 @@ const defaultConfig = {
5252 * @returns {Object } ConcurrencyQueue instance with request/response interceptors attached to Axios.
5353 * @throws {Error } If axios instance is not provided or configuration is invalid.
5454 */
55- export function ConcurrencyQueue ( { axios, config } ) {
55+ export function ConcurrencyQueue ( { axios, config, plugins = [ ] } ) {
5656 if ( ! axios ) {
5757 throw Error ( ERROR_MESSAGES . AXIOS_INSTANCE_MISSING )
5858 }
@@ -436,6 +436,30 @@ export function ConcurrencyQueue ({ axios, config }) {
436436 return response
437437 }
438438
439+ // Run plugin onResponse hooks for errors so plugins see every error (including
440+ // those that are rejected without going through the plugin response interceptor).
441+ const runPluginOnResponseForError = ( error ) => {
442+ if ( ! plugins || ! plugins . length ) return error
443+ let currentError = error
444+ for ( const plugin of plugins ) {
445+ try {
446+ if ( typeof plugin . onResponse === 'function' ) {
447+ const result = plugin . onResponse ( currentError )
448+ if ( result !== undefined ) currentError = result
449+ }
450+ } catch ( e ) {
451+ if ( this . config . logHandler ) {
452+ this . config . logHandler ( 'error' , {
453+ name : 'PluginError' ,
454+ message : `Error in plugin onResponse (error handler): ${ e . message } ` ,
455+ error : e
456+ } )
457+ }
458+ }
459+ }
460+ return currentError
461+ }
462+
439463 const responseErrorHandler = error => {
440464 let networkError = error . config . retryCount
441465 let retryErrorType = null
@@ -449,7 +473,8 @@ export function ConcurrencyQueue ({ axios, config }) {
449473
450474 // Original retry logic for non-network errors
451475 if ( ! this . config . retryOnError || networkError > this . config . retryLimit ) {
452- return Promise . reject ( responseHandler ( error ) )
476+ const err = runPluginOnResponseForError ( error )
477+ return Promise . reject ( responseHandler ( err ) )
453478 }
454479
455480 // Check rate limit remaining header before retrying
@@ -465,20 +490,23 @@ export function ConcurrencyQueue ({ axios, config }) {
465490 }
466491 response = error . response
467492 } else {
468- return Promise . reject ( responseHandler ( error ) )
493+ const err = runPluginOnResponseForError ( error )
494+ return Promise . reject ( responseHandler ( err ) )
469495 }
470496 } else if ( ( response . status === 401 && this . config . refreshToken ) ) {
471497 // If error_code is 294 (2FA required), don't retry/refresh - pass through the error as-is
472498 const apiErrorCode = response . data ?. error_code
473499 if ( apiErrorCode === 294 ) {
474- return Promise . reject ( error )
500+ const err = runPluginOnResponseForError ( error )
501+ return Promise . reject ( responseHandler ( err ) )
475502 }
476503
477504 retryErrorType = `Error with status: ${ response . status } `
478505 networkError ++
479506
480507 if ( networkError > this . config . retryLimit ) {
481- return Promise . reject ( responseHandler ( error ) )
508+ const err = runPluginOnResponseForError ( error )
509+ return Promise . reject ( responseHandler ( err ) )
482510 }
483511 this . running . shift ( )
484512 // Cool down the running requests
@@ -492,19 +520,22 @@ export function ConcurrencyQueue ({ axios, config }) {
492520 networkError ++
493521 return this . retry ( error , retryErrorType , networkError , wait )
494522 }
495- return Promise . reject ( responseHandler ( error ) )
523+ const err = runPluginOnResponseForError ( error )
524+ return Promise . reject ( responseHandler ( err ) )
496525 }
497526
498527 this . retry = ( error , retryErrorType , retryCount , waittime ) => {
499528 let delaytime = waittime
500529 if ( retryCount > this . config . retryLimit ) {
501- return Promise . reject ( responseHandler ( error ) )
530+ const err = runPluginOnResponseForError ( error )
531+ return Promise . reject ( responseHandler ( err ) )
502532 }
503533 if ( this . config . retryDelayOptions ) {
504534 if ( this . config . retryDelayOptions . customBackoff ) {
505535 delaytime = this . config . retryDelayOptions . customBackoff ( retryCount , error )
506536 if ( delaytime && delaytime <= 0 ) {
507- return Promise . reject ( responseHandler ( error ) )
537+ const err = runPluginOnResponseForError ( error )
538+ return Promise . reject ( responseHandler ( err ) )
508539 }
509540 } else if ( this . config . retryDelayOptions . base ) {
510541 delaytime = this . config . retryDelayOptions . base * retryCount
0 commit comments