1+ import isFunction from 'lodash/isFunction' ;
12import {
23 ERROR_INVALID_CONFIG ,
34} from './const' ;
@@ -6,27 +7,70 @@ import TokenExpiredException from './services/TokenExpiredException';
67import RetryCountExceededException from './services/RetryCountExceededException' ;
78import AccessTokenProvider from './AccessTokenProvider' ;
89
10+ /**
11+ * Prepares signed request object which can be used for renewing access token
12+ *
13+ * @callback createAccessTokenRequest
14+ * @param {string } refreshToken Refresh token used to sign the request
15+ * @returns {Request } Signed request object which can be used to get access token
16+ */
17+
18+ /**
19+ * Parses access token from access token response object
20+ *
21+ * @callback parseAccessToken
22+ * @param {Response } response Response object with access token
23+ * @returns {string } Access token parsed from response
24+ */
25+
26+ /**
27+ * Checks whether interceptor will intercept this request or just let it pass through
28+ *
29+ * @callback shouldIntercept
30+ * @param {Request } request Request object
31+ * @returns {bool } A value indicating whether this request should be intercepted
32+ */
33+
34+ /**
35+ * Checks whether provided response invalidates current access token
36+ *
37+ * @callback shouldInvalidateAccessToken
38+ * @param {Response } response Response object
39+ * @returns {bool } A value indicating whether token should be invalidated
40+ */
41+
42+ /**
43+ * Adds authorization for intercepted requests
44+ *
45+ * @callback authorizeRequest
46+ * @param {Request } request Request object being intercepted
47+ * @param {string } accessToken Current access token
48+ * @returns {Request } Authorized request object
49+ */
50+
51+ const getDefaultConfig = ( ) => ( {
52+ fetchRetryCount : 1 ,
53+ createAccessTokenRequest : null ,
54+ shouldIntercept : ( ) => false ,
55+ shouldInvalidateAccessToken : ( ) => false ,
56+ isResponseUnauthorized : http . isResponseUnauthorized ,
57+ parseAccessToken : null ,
58+ authorizeRequest : null ,
59+ onAccessTokenChange : null ,
60+ onResponse : null ,
61+ } ) ;
62+
963/**
1064 * Provides a default implementation for intercepting fetch requests. It will try to resolve
1165 * unauthorized responses by renewing the access token and repeating the initial request.
1266 */
13- export default class FetchInterceptor {
67+ class FetchInterceptor {
1468 constructor ( fetch ) {
1569 // stores reference to vanilla fetch method
1670 this . fetch = fetch ;
1771 this . accessTokenProvider = new AccessTokenProvider ( this . fetch ) ;
1872
19- this . config = {
20- fetchRetryCount : 1 ,
21- createAccessTokenRequest : null ,
22- shouldIntercept : ( ) => false ,
23- shouldInvalidateAccessToken : ( ) => false ,
24- isResponseUnauthorized : http . isResponseUnauthorized ,
25- parseAccessToken : null ,
26- authorizeRequest : null ,
27- onAccessTokenChange : null ,
28- onResponse : null ,
29- } ;
73+ this . config = getDefaultConfig ( ) ;
3074
3175 this . intercept = this . intercept . bind ( this ) ;
3276
@@ -49,37 +93,28 @@ export default class FetchInterceptor {
4993 * Configures fetch interceptor with given config object. All required properties can optionally
5094 * return a promise which will be resolved by fetch interceptor automatically.
5195 *
52- * @param config
53- *
54- * (Required) Prepare fetch request for renewing new access token
55- * createAccessTokenRequest: (refreshToken) => request,
56- *
57- * (Required) Parses access token from access token response
58- * parseAccessToken: (response) => accessToken,
59- *
60- * (Required) Defines whether interceptor will intercept this request or just let it pass through
61- * shouldIntercept: (request) => boolean,
62- *
63- * (Required) Defines whether access token will be invalidated after this response
64- * shouldInvalidateAccessToken: (response) => boolean,
65- *
66- * (Required) Adds authorization for intercepted requests
67- * authorizeRequest: (request, accessToken) => authorizedRequest,
68- *
69- * Checks if response should be considered unauthorized (by default only 401 responses are
70- * considered unauthorized. Override this method if you need to trigger token renewal for
71- * other response statuses.
72- * isResponseUnauthorized: (response) => boolean,
73- *
74- * Number of retries after initial request was unauthorized
75- * fetchRetryCount: 1,
76- *
77- * Event invoked when access token has changed
78- * onAccessTokenChange: null,
79- *
80- * Event invoked when response is resolved
81- * onResponse: null,
82- *
96+ * @param {object } config
97+ * @param {createAccessTokenRequest } config.createAccessTokenRequest
98+ * Prepare fetch request for renewing new access token
99+ * @param {parseAccessToken } config.parseAccessToken
100+ * Parses access token from access token response
101+ * @param {shouldIntercept } config.shouldIntercept
102+ * Defines whether interceptor will intercept this request or just let it pass through
103+ * @param {shouldInvalidateAccessToken } config.shouldInvalidateAccessToken
104+ * Defines whether access token will be invalidated after this response
105+ * @param {authorizeRequest } config.authorizeRequest
106+ * Adds authorization for intercepted requests
107+ * @param {function } [config.isResponseUnauthorized=null]
108+ * Checks if response should be considered unauthorized (by default only 401 responses are
109+ * considered unauthorized. Override this method if you need to trigger token renewal for
110+ * other response statuses.
111+ * @param {number } [config.fetchRetryCount=1]
112+ * Number of retries after initial request was unauthorized
113+ * @param {number } [config.onAccessTokenChange=null]
114+ * Event invoked when access token has changed
115+ * @param {number } [config.onResponse=null]
116+ * Event invoked when response is resolved
117+ * </pre>
83118 */
84119 configure ( config ) {
85120 this . config = { ...this . config , ...config } ;
@@ -93,8 +128,8 @@ export default class FetchInterceptor {
93128
94129 /**
95130 * Authorizes fetch interceptor with given refresh token
96- * @param refreshToken
97- * @param accessToken
131+ * @param { string } refreshToken Refresh token
132+ * @param { string } accessToken Access token
98133 */
99134 authorize ( refreshToken , accessToken ) {
100135 this . accessTokenProvider . authorize ( refreshToken , accessToken ) ;
@@ -115,6 +150,15 @@ export default class FetchInterceptor {
115150 this . accessTokenProvider . clear ( ) ;
116151 }
117152
153+ /**
154+ * Clears current authorization and restores default configuration, e.g. interceptor
155+ * will stop intercepting requests.
156+ */
157+ unload ( ) {
158+ this . clear ( ) ;
159+ this . config = getDefaultConfig ( ) ;
160+ }
161+
118162 /**
119163 * Main intercept method, you should chain this inside wrapped fetch call
120164 * @param args Args initially provided to fetch method
@@ -125,8 +169,11 @@ export default class FetchInterceptor {
125169 }
126170
127171 isConfigValid ( ) {
128- return this . config . shouldIntercept &&
129- this . config . authorizeRequest ;
172+ return this . config . shouldIntercept && isFunction ( this . config . shouldIntercept ) &&
173+ this . config . authorizeRequest && isFunction ( this . config . authorizeRequest ) &&
174+ this . config . isResponseUnauthorized && isFunction ( this . config . isResponseUnauthorized ) &&
175+ this . config . createAccessTokenRequest && isFunction ( this . config . createAccessTokenRequest ) &&
176+ this . config . parseAccessToken && isFunction ( this . config . parseAccessToken ) ;
130177 }
131178
132179 resolveIntercept ( resolve , reject , ...args ) {
@@ -356,3 +403,5 @@ export default class FetchInterceptor {
356403 throw new Error ( error ) ;
357404 }
358405}
406+
407+ export default FetchInterceptor ;
0 commit comments