@@ -2,14 +2,20 @@ import { Configuration, DefaultApi as InfisicalApi } from "./infisicalapi_client
2
2
import { DefaultApiApiV1DynamicSecretsLeasesPostRequest } from "./infisicalapi_client" ;
3
3
import SecretsClient from "./custom/secrets" ;
4
4
import AuthClient from "./custom/auth" ;
5
- import { RawAxiosRequestConfig } from "axios" ;
5
+ import axios , { AxiosError , AxiosInstance , RawAxiosRequestConfig } from "axios" ;
6
6
import DynamicSecretsClient from "./custom/dynamic-secrets" ;
7
7
8
8
import * as ApiClient from "./infisicalapi_client" ;
9
9
import EnvironmentsClient from "./custom/environments" ;
10
10
import ProjectsClient from "./custom/projects" ;
11
11
import FoldersClient from "./custom/folders" ;
12
12
13
+ declare module "axios" {
14
+ interface AxiosRequestConfig {
15
+ _retryCount ?: number ;
16
+ }
17
+ }
18
+
13
19
const buildRestClient = ( apiClient : InfisicalApi , requestOptions ?: RawAxiosRequestConfig ) => {
14
20
return {
15
21
// Add more as we go
@@ -18,6 +24,42 @@ const buildRestClient = (apiClient: InfisicalApi, requestOptions?: RawAxiosReque
18
24
} ;
19
25
} ;
20
26
27
+ const setupAxiosRetry = ( ) => {
28
+ const axiosInstance = axios . create ( ) ;
29
+ const maxRetries = 4 ;
30
+
31
+ const initialRetryDelay = 1000 ;
32
+ const backoffFactor = 2 ;
33
+
34
+ axiosInstance . interceptors . response . use ( null , ( error : AxiosError ) => {
35
+ const config = error ?. config ;
36
+
37
+ if ( ! config ) {
38
+ return Promise . reject ( error ) ;
39
+ }
40
+
41
+ if ( ! config . _retryCount ) config . _retryCount = 0 ;
42
+
43
+ // handle rate limits and network errors
44
+ if ( ( error . response ?. status === 429 || error . response ?. status === undefined ) && config && config . _retryCount ! < maxRetries ) {
45
+ config . _retryCount ! ++ ;
46
+ const baseDelay = initialRetryDelay * Math . pow ( backoffFactor , config . _retryCount ! - 1 ) ;
47
+ const jitter = baseDelay * 0.2 ; // 20% +/- jitter
48
+ const exponentialDelay = baseDelay + ( Math . random ( ) * 2 - 1 ) * jitter ;
49
+
50
+ return new Promise ( resolve => {
51
+ setTimeout ( ( ) => {
52
+ resolve ( axiosInstance ( config ) ) ;
53
+ } , exponentialDelay ) ;
54
+ } ) ;
55
+ }
56
+
57
+ return Promise . reject ( error ) ;
58
+ } ) ;
59
+
60
+ return axiosInstance ;
61
+ } ;
62
+
21
63
// We need to do bind(this) because the authenticate method is a private method, and usually you can't call private methods from outside the class.
22
64
type InfisicalSDKOptions = {
23
65
siteUrl ?: string ;
@@ -34,14 +76,18 @@ class InfisicalSDK {
34
76
#foldersClient: FoldersClient ;
35
77
#authClient: AuthClient ;
36
78
#basePath: string ;
79
+ axiosInstance : AxiosInstance ;
37
80
38
81
constructor ( options ?: InfisicalSDKOptions ) {
39
82
this . #basePath = options ?. siteUrl || "https://app.infisical.com" ;
83
+ this . axiosInstance = setupAxiosRetry ( ) ;
40
84
41
85
this . #apiInstance = new InfisicalApi (
42
86
new Configuration ( {
43
87
basePath : this . #basePath
44
- } )
88
+ } ) ,
89
+ undefined ,
90
+ this . axiosInstance
45
91
) ;
46
92
47
93
this . #authClient = new AuthClient ( this . authenticate . bind ( this ) , this . #apiInstance) ;
@@ -58,7 +104,9 @@ class InfisicalSDK {
58
104
new Configuration ( {
59
105
basePath : this . #basePath,
60
106
accessToken
61
- } )
107
+ } ) ,
108
+ undefined ,
109
+ this . axiosInstance
62
110
) ;
63
111
64
112
this . #requestOptions = {
0 commit comments