@kontent-ai/core-sdk 10.12.5 → 10.12.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/.npmignore +14 -14
  2. package/LICENSE.md +9 -9
  3. package/README.md +30 -30
  4. package/dist/cjs/http/http.functions.js +109 -23
  5. package/dist/cjs/http/http.functions.js.map +1 -1
  6. package/dist/cjs/sdk-info.generated.js +1 -1
  7. package/dist/es6/http/http.functions.js +109 -23
  8. package/dist/es6/http/http.functions.js.map +1 -1
  9. package/dist/es6/sdk-info.generated.js +1 -1
  10. package/dist/esnext/http/http.functions.js +109 -23
  11. package/dist/esnext/http/http.functions.js.map +1 -1
  12. package/dist/esnext/sdk-info.generated.js +1 -1
  13. package/dist/umd/kontent-core.umd.js +646 -147
  14. package/dist/umd/kontent-core.umd.js.map +1 -1
  15. package/dist/umd/kontent-core.umd.min.js +1 -1
  16. package/dist/umd/kontent-core.umd.min.js.LICENSE.txt +1 -1
  17. package/dist/umd/kontent-core.umd.min.js.map +1 -1
  18. package/dist/umd/report.json +1 -1
  19. package/dist/umd/report.min.json +1 -1
  20. package/dist/umd/stats.json +441 -441
  21. package/dist/umd/stats.min.json +449 -449
  22. package/lib/helpers/header.helper.ts +23 -23
  23. package/lib/helpers/headers-helper.ts +15 -15
  24. package/lib/helpers/index.ts +4 -4
  25. package/lib/helpers/retry-helper.ts +204 -204
  26. package/lib/helpers/url.helper.ts +26 -26
  27. package/lib/http/http.debugger.ts +21 -21
  28. package/lib/http/http.functions.ts +416 -314
  29. package/lib/http/http.models.ts +83 -83
  30. package/lib/http/http.service.ts +91 -91
  31. package/lib/http/ihttp.service.ts +20 -20
  32. package/lib/http/index.ts +6 -6
  33. package/lib/http/test-http.service.ts +70 -70
  34. package/lib/index.ts +4 -4
  35. package/lib/models/index.ts +3 -3
  36. package/lib/models/isdk-info.ts +15 -15
  37. package/lib/models/parameters.ts +25 -25
  38. package/lib/models/url.models.ts +3 -3
  39. package/lib/sdk-info.generated.ts +1 -1
  40. package/package.json +93 -93
@@ -1,314 +1,416 @@
1
- import axios, { AxiosInstance, Canceler, CancelToken } from 'axios';
2
- import { extractHeadersFromAxiosResponse } from '../helpers/headers-helper';
3
-
4
- import { httpDebugger } from './http.debugger';
5
- import {
6
- IHttpCancelRequestToken,
7
- IHeader,
8
- IHttpDeleteQueryCall,
9
- IHttpGetQueryCall,
10
- IHttpPatchQueryCall,
11
- IHttpPostQueryCall,
12
- IHttpPutQueryCall,
13
- IHttpQueryOptions,
14
- IResponse,
15
- IRetryStrategyOptions
16
- } from './http.models';
17
- import { retryHelper } from '../helpers/retry-helper';
18
-
19
- export interface IHttpFunctionsConfig {
20
- logErrorsToConsole: boolean;
21
- }
22
-
23
- export async function getWithRetryAsync<TRawData>(
24
- instance: AxiosInstance,
25
- call: IHttpGetQueryCall,
26
- functionsConfig: IHttpFunctionsConfig,
27
- options?: IHttpQueryOptions<CancelToken>
28
- ): Promise<IResponse<TRawData>> {
29
- const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
30
-
31
- return await runWithRetryAsync<TRawData>({
32
- retryAttempt: 0,
33
- url: call.url,
34
- retryStrategy: retryStrategyOptions,
35
- functionsConfig: functionsConfig,
36
- call: async (retryAttempt) => {
37
- httpDebugger.debugStartHttpRequest();
38
-
39
- const axiosResponse = await instance.get<TRawData>(call.url, {
40
- headers: getHeadersJson(options?.headers ?? [], false),
41
- responseType: options?.responseType,
42
- cancelToken: options?.cancelToken?.token
43
- });
44
-
45
- const response: IResponse<TRawData> = {
46
- data: axiosResponse.data,
47
- rawResponse: axiosResponse,
48
- headers: extractHeadersFromAxiosResponse(axiosResponse),
49
- status: axiosResponse.status,
50
- retryStrategy: {
51
- options: retryStrategyOptions,
52
- retryAttempts: retryAttempt
53
- }
54
- };
55
-
56
- httpDebugger.debugSuccessHttpRequest();
57
- return response;
58
- }
59
- });
60
- }
61
-
62
- export async function postWithRetryAsync<TRawData>(
63
- instance: AxiosInstance,
64
- call: IHttpPostQueryCall,
65
- functionsConfig: IHttpFunctionsConfig,
66
- options?: IHttpQueryOptions<CancelToken>
67
- ): Promise<IResponse<TRawData>> {
68
- const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
69
-
70
- return await runWithRetryAsync<TRawData>({
71
- retryAttempt: 0,
72
- url: call.url,
73
- retryStrategy: retryStrategyOptions,
74
- functionsConfig: functionsConfig,
75
- call: async (retryAttempt) => {
76
- httpDebugger.debugStartHttpRequest();
77
-
78
- const axiosResponse = await instance.post<TRawData>(call.url, call.body, {
79
- headers: getHeadersJson(options?.headers ?? [], false),
80
- responseType: options?.responseType,
81
- // required for uploading large files
82
- // https://github.com/axios/axios/issues/1362
83
- maxContentLength: 'Infinity' as any,
84
- maxBodyLength: 'Infinity' as any,
85
- cancelToken: options?.cancelToken?.token
86
- });
87
-
88
- const response: IResponse<TRawData> = {
89
- data: axiosResponse.data,
90
- rawResponse: axiosResponse,
91
- headers: extractHeadersFromAxiosResponse(axiosResponse),
92
- status: axiosResponse.status,
93
- retryStrategy: {
94
- options: retryStrategyOptions,
95
- retryAttempts: retryAttempt
96
- }
97
- };
98
-
99
- httpDebugger.debugSuccessHttpRequest();
100
- return response;
101
- }
102
- });
103
- }
104
-
105
- export async function putWithRetryAsync<TRawData>(
106
- instance: AxiosInstance,
107
- call: IHttpPutQueryCall,
108
- functionsConfig: IHttpFunctionsConfig,
109
- options?: IHttpQueryOptions<CancelToken>
110
- ): Promise<IResponse<TRawData>> {
111
- const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
112
-
113
- return await runWithRetryAsync<TRawData>({
114
- retryAttempt: 0,
115
- url: call.url,
116
- retryStrategy: retryStrategyOptions,
117
- functionsConfig: functionsConfig,
118
- call: async (retryAttempt) => {
119
- httpDebugger.debugStartHttpRequest();
120
-
121
- const axiosResponse = await instance.put<TRawData>(call.url, call.body, {
122
- headers: getHeadersJson(options?.headers ?? [], false),
123
- responseType: options?.responseType,
124
- // required for uploading large files
125
- // https://github.com/axios/axios/issues/1362
126
- maxContentLength: 'Infinity' as any,
127
- maxBodyLength: 'Infinity' as any,
128
- cancelToken: options?.cancelToken?.token
129
- });
130
-
131
- const response: IResponse<TRawData> = {
132
- data: axiosResponse.data,
133
- rawResponse: axiosResponse,
134
- headers: extractHeadersFromAxiosResponse(axiosResponse),
135
- status: axiosResponse.status,
136
- retryStrategy: {
137
- options: retryStrategyOptions,
138
- retryAttempts: retryAttempt
139
- }
140
- };
141
-
142
- httpDebugger.debugSuccessHttpRequest();
143
- return response;
144
- }
145
- });
146
- }
147
-
148
- export async function patchWithRetryAsync<TRawData>(
149
- instance: AxiosInstance,
150
- call: IHttpPatchQueryCall,
151
- functionsConfig: IHttpFunctionsConfig,
152
- options?: IHttpQueryOptions<CancelToken>
153
- ): Promise<IResponse<TRawData>> {
154
- const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
155
-
156
- return await runWithRetryAsync<TRawData>({
157
- retryAttempt: 0,
158
- url: call.url,
159
- retryStrategy: retryStrategyOptions,
160
- functionsConfig: functionsConfig,
161
- call: async (retryAttempt) => {
162
- httpDebugger.debugStartHttpRequest();
163
-
164
- const axiosResponse = await instance.patch<TRawData>(call.url, call.body, {
165
- headers: getHeadersJson(options?.headers ?? [], false),
166
- responseType: options?.responseType,
167
- // required for uploading large files
168
- // https://github.com/axios/axios/issues/1362
169
- maxContentLength: 'Infinity' as any,
170
- maxBodyLength: 'Infinity' as any,
171
- cancelToken: options?.cancelToken?.token
172
- });
173
-
174
- const response: IResponse<TRawData> = {
175
- data: axiosResponse.data,
176
- rawResponse: axiosResponse,
177
- headers: extractHeadersFromAxiosResponse(axiosResponse),
178
- status: axiosResponse.status,
179
- retryStrategy: {
180
- options: retryStrategyOptions,
181
- retryAttempts: retryAttempt
182
- }
183
- };
184
-
185
- httpDebugger.debugSuccessHttpRequest();
186
- return response;
187
- }
188
- });
189
- }
190
-
191
- export async function deleteWithRetryAsync<TRawData>(
192
- instance: AxiosInstance,
193
- call: IHttpDeleteQueryCall,
194
- functionsConfig: IHttpFunctionsConfig,
195
- options?: IHttpQueryOptions<CancelToken>
196
- ): Promise<IResponse<TRawData>> {
197
- const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
198
-
199
- return await runWithRetryAsync<TRawData>({
200
- retryAttempt: 0,
201
- url: call.url,
202
- retryStrategy: retryStrategyOptions,
203
- functionsConfig: functionsConfig,
204
- call: async (retryAttempt) => {
205
- httpDebugger.debugStartHttpRequest();
206
-
207
- const axiosResponse = await instance.delete<TRawData>(call.url, {
208
- headers: getHeadersJson(options?.headers ?? [], false),
209
- responseType: options?.responseType,
210
- // required for uploading large files
211
- // https://github.com/axios/axios/issues/1362
212
- maxContentLength: 'Infinity' as any,
213
- maxBodyLength: 'Infinity' as any,
214
- cancelToken: options?.cancelToken?.token
215
- });
216
-
217
- const response: IResponse<TRawData> = {
218
- data: axiosResponse.data,
219
- rawResponse: axiosResponse,
220
- headers: extractHeadersFromAxiosResponse(axiosResponse),
221
- status: axiosResponse.status,
222
- retryStrategy: {
223
- options: retryStrategyOptions,
224
- retryAttempts: retryAttempt
225
- }
226
- };
227
-
228
- httpDebugger.debugSuccessHttpRequest();
229
- return response;
230
- }
231
- });
232
- }
233
-
234
- export function createCancelToken(): IHttpCancelRequestToken<CancelToken> {
235
- let canceler: Canceler;
236
-
237
- const token = new axios.CancelToken((c) => {
238
- // An executor function receives a cancel function as a parameter
239
- canceler = c;
240
- });
241
-
242
- return {
243
- cancel: (cancelMessage) =>
244
- canceler(`${retryHelper.requestCancelledMessagePrefix}: ${cancelMessage ?? 'User cancel'}`),
245
- token: token
246
- };
247
- }
248
-
249
- async function runWithRetryAsync<TRawData>(data: {
250
- url: string;
251
- retryAttempt: number;
252
- call: (retryAttempt: number) => Promise<IResponse<TRawData>>;
253
- retryStrategy: IRetryStrategyOptions;
254
- functionsConfig: IHttpFunctionsConfig;
255
- }): Promise<IResponse<TRawData>> {
256
- try {
257
- return await data.call(data.retryAttempt);
258
- } catch (error) {
259
- const retryResult = retryHelper.getRetryErrorResult({
260
- error: error,
261
- retryAttempt: data.retryAttempt,
262
- retryStrategy: data.retryStrategy
263
- });
264
-
265
- if (retryResult.canRetry) {
266
- httpDebugger.debugRetryHttpRequest();
267
-
268
- // wait time before retrying
269
- await new Promise((resolve) => setTimeout(resolve, retryResult.retryInMs));
270
-
271
- if (data.functionsConfig.logErrorsToConsole) {
272
- console.warn(
273
- `Retry attempt '${data.retryAttempt + 1}' from a maximum of '${
274
- retryResult.maxRetries
275
- }' retries. Request url: '${data.url}'`
276
- );
277
- }
278
-
279
- // retry request
280
- return await runWithRetryAsync({
281
- call: data.call,
282
- retryStrategy: data.retryStrategy,
283
- retryAttempt: data.retryAttempt + 1,
284
- url: data.url,
285
- functionsConfig: data.functionsConfig
286
- });
287
- }
288
-
289
- if (data.functionsConfig.logErrorsToConsole) {
290
- console.error(`Executing '${data.url}' failed. Request was retried '${data.retryAttempt}' times. `, error);
291
- }
292
-
293
- throw error;
294
- }
295
- }
296
-
297
- function getHeadersJson(headers: IHeader[], addContentTypeHeader: boolean): { [header: string]: string } {
298
- const headerJson: { [header: string]: string } = {};
299
-
300
- headers.forEach((header) => {
301
- headerJson[header.header] = header.value;
302
- });
303
-
304
- if (addContentTypeHeader) {
305
- // add default content type header if not present
306
- const contentTypeHeader = headers.find((m) => m.header.toLowerCase() === 'Content-Type'.toLowerCase());
307
-
308
- if (!contentTypeHeader) {
309
- headerJson['Content-Type'] = 'application/json';
310
- }
311
- }
312
-
313
- return headerJson;
314
- }
1
+ import axios, { AxiosInstance, Canceler, CancelToken } from 'axios';
2
+ import { extractHeadersFromAxiosResponse } from '../helpers/headers-helper';
3
+
4
+ import { httpDebugger } from './http.debugger';
5
+ import {
6
+ IHttpCancelRequestToken,
7
+ IHeader,
8
+ IHttpDeleteQueryCall,
9
+ IHttpGetQueryCall,
10
+ IHttpPatchQueryCall,
11
+ IHttpPostQueryCall,
12
+ IHttpPutQueryCall,
13
+ IHttpQueryOptions,
14
+ IResponse,
15
+ IRetryStrategyOptions
16
+ } from './http.models';
17
+ import { retryHelper } from '../helpers/retry-helper';
18
+
19
+ export interface IHttpFunctionsConfig {
20
+ logErrorsToConsole: boolean;
21
+ }
22
+
23
+ export async function getWithRetryAsync<TRawData>(
24
+ instance: AxiosInstance,
25
+ call: IHttpGetQueryCall,
26
+ functionsConfig: IHttpFunctionsConfig,
27
+ options?: IHttpQueryOptions<CancelToken>
28
+ ): Promise<IResponse<TRawData>> {
29
+ const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
30
+
31
+ return await runWithRetryAsync<TRawData>({
32
+ retryAttempt: 0,
33
+ url: call.url,
34
+ retryStrategy: retryStrategyOptions,
35
+ functionsConfig: functionsConfig,
36
+ headers: options?.headers ?? [],
37
+ call: async (retryAttempt) => {
38
+ httpDebugger.debugStartHttpRequest();
39
+
40
+ const axiosResponse = await instance.get<TRawData>(call.url, {
41
+ headers: getHeadersJson(options?.headers ?? [], false),
42
+ responseType: options?.responseType,
43
+ cancelToken: options?.cancelToken?.token
44
+ });
45
+
46
+ const response: IResponse<TRawData> = {
47
+ data: axiosResponse.data,
48
+ rawResponse: axiosResponse,
49
+ headers: extractHeadersFromAxiosResponse(axiosResponse),
50
+ status: axiosResponse.status,
51
+ retryStrategy: {
52
+ options: retryStrategyOptions,
53
+ retryAttempts: retryAttempt
54
+ }
55
+ };
56
+
57
+ httpDebugger.debugSuccessHttpRequest();
58
+ return response;
59
+ }
60
+ });
61
+ }
62
+
63
+ export async function postWithRetryAsync<TRawData>(
64
+ instance: AxiosInstance,
65
+ call: IHttpPostQueryCall,
66
+ functionsConfig: IHttpFunctionsConfig,
67
+ options?: IHttpQueryOptions<CancelToken>
68
+ ): Promise<IResponse<TRawData>> {
69
+ const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
70
+
71
+ return await runWithRetryAsync<TRawData>({
72
+ retryAttempt: 0,
73
+ url: call.url,
74
+ retryStrategy: retryStrategyOptions,
75
+ functionsConfig: functionsConfig,
76
+ headers: options?.headers ?? [],
77
+ call: async (retryAttempt) => {
78
+ httpDebugger.debugStartHttpRequest();
79
+
80
+ const axiosResponse = await instance.post<TRawData>(call.url, call.body, {
81
+ headers: getHeadersJson(options?.headers ?? [], false),
82
+ responseType: options?.responseType,
83
+ // required for uploading large files
84
+ // https://github.com/axios/axios/issues/1362
85
+ maxContentLength: 'Infinity' as any,
86
+ maxBodyLength: 'Infinity' as any,
87
+ cancelToken: options?.cancelToken?.token
88
+ });
89
+
90
+ const response: IResponse<TRawData> = {
91
+ data: axiosResponse.data,
92
+ rawResponse: axiosResponse,
93
+ headers: extractHeadersFromAxiosResponse(axiosResponse),
94
+ status: axiosResponse.status,
95
+ retryStrategy: {
96
+ options: retryStrategyOptions,
97
+ retryAttempts: retryAttempt
98
+ }
99
+ };
100
+
101
+ httpDebugger.debugSuccessHttpRequest();
102
+ return response;
103
+ }
104
+ });
105
+ }
106
+
107
+ export async function putWithRetryAsync<TRawData>(
108
+ instance: AxiosInstance,
109
+ call: IHttpPutQueryCall,
110
+ functionsConfig: IHttpFunctionsConfig,
111
+ options?: IHttpQueryOptions<CancelToken>
112
+ ): Promise<IResponse<TRawData>> {
113
+ const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
114
+
115
+ return await runWithRetryAsync<TRawData>({
116
+ retryAttempt: 0,
117
+ url: call.url,
118
+ retryStrategy: retryStrategyOptions,
119
+ functionsConfig: functionsConfig,
120
+ headers: options?.headers ?? [],
121
+ call: async (retryAttempt) => {
122
+ httpDebugger.debugStartHttpRequest();
123
+
124
+ const axiosResponse = await instance.put<TRawData>(call.url, call.body, {
125
+ headers: getHeadersJson(options?.headers ?? [], false),
126
+ responseType: options?.responseType,
127
+ // required for uploading large files
128
+ // https://github.com/axios/axios/issues/1362
129
+ maxContentLength: 'Infinity' as any,
130
+ maxBodyLength: 'Infinity' as any,
131
+ cancelToken: options?.cancelToken?.token
132
+ });
133
+
134
+ const response: IResponse<TRawData> = {
135
+ data: axiosResponse.data,
136
+ rawResponse: axiosResponse,
137
+ headers: extractHeadersFromAxiosResponse(axiosResponse),
138
+ status: axiosResponse.status,
139
+ retryStrategy: {
140
+ options: retryStrategyOptions,
141
+ retryAttempts: retryAttempt
142
+ }
143
+ };
144
+
145
+ httpDebugger.debugSuccessHttpRequest();
146
+ return response;
147
+ }
148
+ });
149
+ }
150
+
151
+ export async function patchWithRetryAsync<TRawData>(
152
+ instance: AxiosInstance,
153
+ call: IHttpPatchQueryCall,
154
+ functionsConfig: IHttpFunctionsConfig,
155
+ options?: IHttpQueryOptions<CancelToken>
156
+ ): Promise<IResponse<TRawData>> {
157
+ const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
158
+
159
+ return await runWithRetryAsync<TRawData>({
160
+ retryAttempt: 0,
161
+ url: call.url,
162
+ retryStrategy: retryStrategyOptions,
163
+ functionsConfig: functionsConfig,
164
+ headers: options?.headers ?? [],
165
+ call: async (retryAttempt) => {
166
+ httpDebugger.debugStartHttpRequest();
167
+
168
+ const axiosResponse = await instance.patch<TRawData>(call.url, call.body, {
169
+ headers: getHeadersJson(options?.headers ?? [], false),
170
+ responseType: options?.responseType,
171
+ // required for uploading large files
172
+ // https://github.com/axios/axios/issues/1362
173
+ maxContentLength: 'Infinity' as any,
174
+ maxBodyLength: 'Infinity' as any,
175
+ cancelToken: options?.cancelToken?.token
176
+ });
177
+
178
+ const response: IResponse<TRawData> = {
179
+ data: axiosResponse.data,
180
+ rawResponse: axiosResponse,
181
+ headers: extractHeadersFromAxiosResponse(axiosResponse),
182
+ status: axiosResponse.status,
183
+ retryStrategy: {
184
+ options: retryStrategyOptions,
185
+ retryAttempts: retryAttempt
186
+ }
187
+ };
188
+
189
+ httpDebugger.debugSuccessHttpRequest();
190
+ return response;
191
+ }
192
+ });
193
+ }
194
+
195
+ export async function deleteWithRetryAsync<TRawData>(
196
+ instance: AxiosInstance,
197
+ call: IHttpDeleteQueryCall,
198
+ functionsConfig: IHttpFunctionsConfig,
199
+ options?: IHttpQueryOptions<CancelToken>
200
+ ): Promise<IResponse<TRawData>> {
201
+ const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
202
+
203
+ return await runWithRetryAsync<TRawData>({
204
+ retryAttempt: 0,
205
+ url: call.url,
206
+ retryStrategy: retryStrategyOptions,
207
+ functionsConfig: functionsConfig,
208
+ headers: options?.headers ?? [],
209
+ call: async (retryAttempt) => {
210
+ httpDebugger.debugStartHttpRequest();
211
+
212
+ const axiosResponse = await instance.delete<TRawData>(call.url, {
213
+ headers: getHeadersJson(options?.headers ?? [], false),
214
+ responseType: options?.responseType,
215
+ // required for uploading large files
216
+ // https://github.com/axios/axios/issues/1362
217
+ maxContentLength: 'Infinity' as any,
218
+ maxBodyLength: 'Infinity' as any,
219
+ cancelToken: options?.cancelToken?.token
220
+ });
221
+
222
+ const response: IResponse<TRawData> = {
223
+ data: axiosResponse.data,
224
+ rawResponse: axiosResponse,
225
+ headers: extractHeadersFromAxiosResponse(axiosResponse),
226
+ status: axiosResponse.status,
227
+ retryStrategy: {
228
+ options: retryStrategyOptions,
229
+ retryAttempts: retryAttempt
230
+ }
231
+ };
232
+
233
+ httpDebugger.debugSuccessHttpRequest();
234
+ return response;
235
+ }
236
+ });
237
+ }
238
+
239
+ export function createCancelToken(): IHttpCancelRequestToken<CancelToken> {
240
+ let canceler: Canceler;
241
+
242
+ const token = new axios.CancelToken((c) => {
243
+ // An executor function receives a cancel function as a parameter
244
+ canceler = c;
245
+ });
246
+
247
+ return {
248
+ cancel: (cancelMessage) =>
249
+ canceler(`${retryHelper.requestCancelledMessagePrefix}: ${cancelMessage ?? 'User cancel'}`),
250
+ token: token
251
+ };
252
+ }
253
+
254
+ async function runWithRetryAsync<TRawData>(data: {
255
+ url: string;
256
+ retryAttempt: number;
257
+ call: (retryAttempt: number) => Promise<IResponse<TRawData>>;
258
+ retryStrategy: IRetryStrategyOptions;
259
+ functionsConfig: IHttpFunctionsConfig;
260
+ headers: IHeader[];
261
+ }): Promise<IResponse<TRawData>> {
262
+ try {
263
+ return await data.call(data.retryAttempt);
264
+ } catch (error) {
265
+ const retryResult = retryHelper.getRetryErrorResult({
266
+ error: error,
267
+ retryAttempt: data.retryAttempt,
268
+ retryStrategy: data.retryStrategy
269
+ });
270
+
271
+ if (retryResult.canRetry) {
272
+ httpDebugger.debugRetryHttpRequest();
273
+
274
+ // wait time before retrying
275
+ await new Promise((resolve) => setTimeout(resolve, retryResult.retryInMs));
276
+
277
+ if (data.functionsConfig.logErrorsToConsole) {
278
+ console.warn(
279
+ `Retry attempt '${data.retryAttempt + 1}' from a maximum of '${
280
+ retryResult.maxRetries
281
+ }' retries. Request url: '${data.url}'`
282
+ );
283
+ }
284
+
285
+ // retry request
286
+ return await runWithRetryAsync({
287
+ call: data.call,
288
+ retryStrategy: data.retryStrategy,
289
+ retryAttempt: data.retryAttempt + 1,
290
+ url: data.url,
291
+ functionsConfig: data.functionsConfig,
292
+ headers: data.headers
293
+ });
294
+ }
295
+
296
+ // sanitize the error before logging / re-throwing so the authorization token is not leaked
297
+ const sanitizedError = sanitizeError(error, data.headers);
298
+
299
+ if (data.functionsConfig.logErrorsToConsole) {
300
+ console.error(
301
+ `Executing '${data.url}' failed. Request was retried '${data.retryAttempt}' times.`,
302
+ sanitizedError
303
+ );
304
+ }
305
+
306
+ throw sanitizedError;
307
+ }
308
+ }
309
+
310
+ const redactedValue = 'redacted';
311
+ const maxRedactionDepth = 10;
312
+
313
+ /**
314
+ * Returns the caller-supplied 'authorization' header value(s), which are the secret token(s) to
315
+ * scrub from errors. Note: if a consumer sets the authorization token on the axios instance defaults
316
+ * instead of passing it via 'options.headers', it is not known here and cannot be redacted.
317
+ */
318
+ function getSecretHeaderValues(headers: IHeader[]): string[] {
319
+ return headers
320
+ .filter((header) => header.header.toLowerCase() === 'authorization')
321
+ .map((header) => header.value)
322
+ // skip empty values - splitting on an empty string would corrupt every string
323
+ .filter((value) => typeof value === 'string' && value.length > 0);
324
+ }
325
+
326
+ function redactStringValue(value: string, secrets: string[]): string {
327
+ let result = value;
328
+
329
+ for (const secret of secrets) {
330
+ if (result.includes(secret)) {
331
+ result = result.split(secret).join(redactedValue);
332
+ }
333
+ }
334
+
335
+ return result;
336
+ }
337
+
338
+ /**
339
+ * Walks the object graph (cycle- and depth-guarded) replacing every occurrence of a secret with the
340
+ * redacted placeholder in place.
341
+ */
342
+ function redactSecretsInPlace(target: unknown, secrets: string[], seen: WeakSet<object>, depth: number): void {
343
+ if (depth > maxRedactionDepth || target === null || typeof target !== 'object') {
344
+ return;
345
+ }
346
+
347
+ if (seen.has(target)) {
348
+ // break cycles (config.headers, request.socket, response.request, ...)
349
+ return;
350
+ }
351
+ seen.add(target);
352
+
353
+ for (const key of Object.keys(target as Record<string, unknown>)) {
354
+ let value: unknown;
355
+
356
+ try {
357
+ value = (target as Record<string, unknown>)[key];
358
+ } catch {
359
+ // accessing the property threw (e.g. a getter) - skip it
360
+ continue;
361
+ }
362
+
363
+ if (typeof value === 'string') {
364
+ const redacted = redactStringValue(value, secrets);
365
+
366
+ if (redacted !== value) {
367
+ try {
368
+ (target as Record<string, unknown>)[key] = redacted;
369
+ } catch {
370
+ // property is read-only - skip it
371
+ }
372
+ }
373
+ } else if (value && typeof value === 'object') {
374
+ redactSecretsInPlace(value, secrets, seen, depth + 1);
375
+ }
376
+ }
377
+ }
378
+
379
+ /**
380
+ * If 'error' is an axios error, redacts every occurrence of the caller's authorization token (taken
381
+ * from 'headers') throughout the error, replacing it with a redacted placeholder. Non-axios errors
382
+ * and errors with no known token are returned unchanged. This prevents the authorization token from
383
+ * leaking via console logs or the re-thrown error. All other axios properties are preserved.
384
+ */
385
+ function sanitizeError(error: unknown, headers: IHeader[]): unknown {
386
+ if (!axios.isAxiosError(error)) {
387
+ return error;
388
+ }
389
+
390
+ const secrets = getSecretHeaderValues(headers);
391
+ if (secrets.length === 0) {
392
+ return error;
393
+ }
394
+
395
+ redactSecretsInPlace(error, secrets, new WeakSet<object>(), 0);
396
+ return error;
397
+ }
398
+
399
+ function getHeadersJson(headers: IHeader[], addContentTypeHeader: boolean): { [header: string]: string } {
400
+ const headerJson: { [header: string]: string } = {};
401
+
402
+ headers.forEach((header) => {
403
+ headerJson[header.header] = header.value;
404
+ });
405
+
406
+ if (addContentTypeHeader) {
407
+ // add default content type header if not present
408
+ const contentTypeHeader = headers.find((m) => m.header.toLowerCase() === 'Content-Type'.toLowerCase());
409
+
410
+ if (!contentTypeHeader) {
411
+ headerJson['Content-Type'] = 'application/json';
412
+ }
413
+ }
414
+
415
+ return headerJson;
416
+ }