axios-retryer
Version:
axios-retryer is an advanced Axios request manager offering intelligent retry logic with token refresh, concurrency control, priority queuing, and a flexible plugin architecture, all built with TypeScript for robust HTTP client integrations.
2 lines (1 loc) • 6.06 kB
JavaScript
"use strict";var e=require("axios"),r=function(){return r=Object.assign||function(e){for(var r,t=1,n=arguments.length;t<n;t++)for(var s in r=arguments[t])Object.prototype.hasOwnProperty.call(r,s)&&(e[s]=r[s]);return e},r.apply(this,arguments)};function t(e,r,t,n){return new(t||(t=Promise))((function(s,o){function i(e){try{a(n.next(e))}catch(e){o(e)}}function u(e){try{a(n.throw(e))}catch(e){o(e)}}function a(e){var r;e.done?s(e.value):(r=e.value,r instanceof t?r:new t((function(e){e(r)}))).then(i,u)}a((n=n.apply(e,r||[])).next())}))}function n(e,r){var t,n,s,o={label:0,sent:function(){if(1&s[0])throw s[1];return s[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return i.next=u(0),i.throw=u(1),i.return=u(2),"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function u(u){return function(a){return function(u){if(t)throw new TypeError("Generator is already executing.");for(;i&&(i=0,u[0]&&(o=0)),o;)try{if(t=1,n&&(s=2&u[0]?n.return:u[0]?n.throw||((s=n.return)&&s.call(n),0):n.next)&&!(s=s.call(n,u[1])).done)return s;switch(n=0,s&&(u=[2&u[0],s.value]),u[0]){case 0:case 1:s=u;break;case 4:return o.label++,{value:u[1],done:!1};case 5:o.label++,n=u[1],u=[0];continue;case 7:u=o.ops.pop(),o.trys.pop();continue;default:if(!(s=o.trys,(s=s.length>0&&s[s.length-1])||6!==u[0]&&2!==u[0])){o=0;continue}if(3===u[0]&&(!s||u[1]>s[0]&&u[1]<s[3])){o.label=u[1];break}if(6===u[0]&&o.label<s[1]){o.label=s[1],s=u;break}if(s&&o.label<s[2]){o.label=s[2],o.ops.push(u);break}s[2]&&o.ops.pop(),o.trys.pop();continue}u=r.call(e,o)}catch(e){u=[6,e],n=0}finally{t=s=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}([u,a])}}}"function"==typeof SuppressedError&&SuppressedError;var s={maxRefreshAttempts:3,authHeaderName:"Authorization",refreshStatusCodes:[401],refreshTimeout:15e3,retryOnRefreshFail:!0,tokenPrefix:"Bearer "},o=function(){function o(e,t){this.name="TokenRefreshPlugin",this.version="1.0.0",this.interceptorId=null,this.isRefreshing=!1,this.refreshQueue=[],this.logger=null,this.refreshToken=e,this.options=r(r({},s),t)}return o.prototype.initialize=function(r){var t=this;this.manager=r,this.refreshAxios=e.create(r.axiosInstance.defaults),this.logger=r.getLogger(),this.interceptorId=r.axiosInstance.interceptors.response.use((function(e){return e}),(function(e){return t.handleResponseError(e)})),this.manager.axiosInstance.interceptors.request.use((function(e){var r=t.options.authHeaderName;return t.manager.axiosInstance.defaults.headers.common[r]&&e.headers[r]&&(e.headers[r]=t.manager.axiosInstance.defaults.headers.common[r]),e}))},o.prototype.onBeforeDestroyed=function(e){null!=this.interceptorId&&e.axiosInstance.interceptors.response.eject(this.interceptorId)},o.prototype.handleResponseError=function(e){return t(this,void 0,void 0,(function(){var r;return n(this,(function(t){return(r=e.config)?r.__isRetryRefreshRequest?[2,Promise.reject(e)]:this.isRefreshableError(e)?this.isRefreshing?[2,this.queueRefreshRequest(r)]:[2,this.handleTokenRefresh(r)]:[2,Promise.reject(e)]:[2,Promise.reject(e)]}))}))},o.prototype.isRefreshableError=function(e){var r,t,n=null!==(t=null===(r=e.response)||void 0===r?void 0:r.status)&&void 0!==t?t:-1;return this.options.refreshStatusCodes.includes(n)},o.prototype.handleTokenRefresh=function(e){return t(this,void 0,void 0,(function(){var r,t;return n(this,(function(n){switch(n.label){case 0:this.isRefreshing=!0,e.__isRetryRefreshRequest||this.manager.triggerAndEmit("onBeforeTokenRefresh"),n.label=1;case 1:return n.trys.push([1,3,4,5]),[4,this.executeTokenRefresh()];case 2:return r=n.sent(),this.updateAuthHeader(r),this.retryQueuedRequests(r),[2,this.retryRequest(e,r)];case 3:return t=n.sent(),this.handleRefreshFailure(),[2,Promise.reject(t)];case 4:return this.isRefreshing=!1,[7];case 5:return[2]}}))}))},o.prototype.executeTokenRefresh=function(){return t(this,void 0,void 0,(function(){var e,r,t,s,o,i,u,a,h,c,f,l=this;return n(this,(function(n){switch(n.label){case 0:if(!this.refreshToken)throw new Error("No token refresh handler provided");e=this.options,r=e.maxRefreshAttempts,t=e.refreshTimeout,s=e.retryOnRefreshFail,i=1,n.label=1;case 1:if(!(i<=r))return[3,6];null===(h=this.logger)||void 0===h||h.debug("[".concat(this.name,"] Refresh attempt ").concat(i,"/").concat(r)),n.label=2;case 2:return n.trys.push([2,4,,5]),[4,new Promise((function(e,r){var n=setTimeout((function(){return r(new Error("Token refresh timeout"))}),t);l.refreshToken(l.refreshAxios).then((function(r){clearTimeout(n),e(r)})).catch((function(e){clearTimeout(n),r(e)}))}))];case 3:return u=n.sent().token,this.manager.triggerAndEmit("onTokenRefreshed",u),null===(c=this.logger)||void 0===c||c.debug("[".concat(this.name,"] Token successfully refreshed")),[2,u];case 4:return a=n.sent(),o=a,s&&i<r+1?(null===(f=this.logger)||void 0===f||f.debug("[".concat(this.name,"] Refresh attempt failed, retrying...")),[3,5]):[3,6];case 5:return i++,[3,1];case 6:throw o}}))}))},o.prototype.updateAuthHeader=function(e){var r=this.options,t=r.authHeaderName,n=r.tokenPrefix;this.manager.axiosInstance.defaults.headers.common[t]="".concat(n).concat(e)},o.prototype.retryRequest=function(e,t){var n,s=this.options,o=s.authHeaderName,i=s.tokenPrefix;return e.__isRetryRefreshRequest=!0,e.headers=r(r({},e.headers),((n={})[o]="".concat(i).concat(t),n)),this.refreshAxios(e)},o.prototype.queueRefreshRequest=function(e){var r=this;return new Promise((function(t,n){r.refreshQueue.push({resolve:function(n){return t(r.retryRequest(e,n))},reject:n})}))},o.prototype.retryQueuedRequests=function(e){this.refreshQueue.forEach((function(r){return(0,r.resolve)(e)})),this.refreshQueue=[]},o.prototype.handleRefreshFailure=function(){var e,r=new Error("Token refresh failed");this.refreshQueue.forEach((function(e){return(0,e.reject)(r)})),this.refreshQueue=[],this.manager.triggerAndEmit("onTokenRefreshFailed"),null===(e=this.logger)||void 0===e||e.error("".concat(this.name," Token refresh failed - clearing queue"))},o}();exports.TokenRefreshPlugin=o;