phenoml 6.2.0 → 6.3.0
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.
- package/dist/cjs/Client.js +1 -1
- package/dist/cjs/core/fetcher/Fetcher.js +33 -18
- package/dist/cjs/core/fetcher/makeRequest.js +0 -2
- package/dist/cjs/core/fetcher/requestWithRetries.js +0 -9
- package/dist/cjs/core/fetcher/signals.d.ts +0 -6
- package/dist/cjs/core/fetcher/signals.js +0 -12
- package/dist/cjs/core/logging/logger.js +1 -1
- package/dist/cjs/core/url/join.js +0 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/Client.mjs +1 -1
- package/dist/esm/core/fetcher/Fetcher.mjs +33 -18
- package/dist/esm/core/fetcher/makeRequest.mjs +0 -2
- package/dist/esm/core/fetcher/requestWithRetries.mjs +0 -9
- package/dist/esm/core/fetcher/signals.d.mts +0 -6
- package/dist/esm/core/fetcher/signals.mjs +0 -12
- package/dist/esm/core/logging/logger.mjs +1 -1
- package/dist/esm/core/url/join.mjs +0 -1
- package/dist/esm/version.d.mts +1 -1
- package/dist/esm/version.mjs +1 -1
- package/package.json +1 -1
package/dist/cjs/Client.js
CHANGED
|
@@ -52,7 +52,7 @@ class phenomlClient {
|
|
|
52
52
|
this._options = Object.assign(Object.assign({}, _options), { logging: core.logging.createLogger(_options === null || _options === void 0 ? void 0 : _options.logging), headers: (0, headers_js_1.mergeHeaders)({
|
|
53
53
|
"X-Fern-Language": "JavaScript",
|
|
54
54
|
"X-Fern-SDK-Name": "phenoml",
|
|
55
|
-
"X-Fern-SDK-Version": "6.
|
|
55
|
+
"X-Fern-SDK-Version": "6.3.0",
|
|
56
56
|
"User-Agent": "phenoml/auto",
|
|
57
57
|
"X-Fern-Runtime": core.RUNTIME.type,
|
|
58
58
|
"X-Fern-Runtime-Version": core.RUNTIME.version,
|
|
@@ -24,14 +24,21 @@ const RawResponse_js_1 = require("./RawResponse.js");
|
|
|
24
24
|
const requestWithRetries_js_1 = require("./requestWithRetries.js");
|
|
25
25
|
const SENSITIVE_HEADERS = new Set([
|
|
26
26
|
"authorization",
|
|
27
|
+
"www-authenticate",
|
|
27
28
|
"x-api-key",
|
|
28
29
|
"api-key",
|
|
30
|
+
"apikey",
|
|
31
|
+
"x-api-token",
|
|
29
32
|
"x-auth-token",
|
|
33
|
+
"auth-token",
|
|
30
34
|
"cookie",
|
|
31
35
|
"set-cookie",
|
|
32
36
|
"proxy-authorization",
|
|
37
|
+
"proxy-authenticate",
|
|
33
38
|
"x-csrf-token",
|
|
34
39
|
"x-xsrf-token",
|
|
40
|
+
"x-session-token",
|
|
41
|
+
"x-access-token",
|
|
35
42
|
]);
|
|
36
43
|
function redactHeaders(headers) {
|
|
37
44
|
const filtered = {};
|
|
@@ -85,20 +92,26 @@ function redactUrl(url) {
|
|
|
85
92
|
if (protocolIndex === -1)
|
|
86
93
|
return url;
|
|
87
94
|
const afterProtocol = protocolIndex + 3;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
// Find the first delimiter that marks the end of the authority section
|
|
96
|
+
const pathStart = url.indexOf("/", afterProtocol);
|
|
97
|
+
let queryStart = url.indexOf("?", afterProtocol);
|
|
98
|
+
let fragmentStart = url.indexOf("#", afterProtocol);
|
|
99
|
+
const firstDelimiter = Math.min(pathStart === -1 ? url.length : pathStart, queryStart === -1 ? url.length : queryStart, fragmentStart === -1 ? url.length : fragmentStart);
|
|
100
|
+
// Find the LAST @ before the delimiter (handles multiple @ in credentials)
|
|
101
|
+
let atIndex = -1;
|
|
102
|
+
for (let i = afterProtocol; i < firstDelimiter; i++) {
|
|
103
|
+
if (url[i] === "@") {
|
|
104
|
+
atIndex = i;
|
|
96
105
|
}
|
|
97
106
|
}
|
|
98
|
-
|
|
107
|
+
if (atIndex !== -1) {
|
|
108
|
+
url = `${url.slice(0, afterProtocol)}[REDACTED]@${url.slice(atIndex + 1)}`;
|
|
109
|
+
}
|
|
110
|
+
// Recalculate queryStart since url might have changed
|
|
111
|
+
queryStart = url.indexOf("?");
|
|
99
112
|
if (queryStart === -1)
|
|
100
113
|
return url;
|
|
101
|
-
|
|
114
|
+
fragmentStart = url.indexOf("#", queryStart);
|
|
102
115
|
const queryEnd = fragmentStart !== -1 ? fragmentStart : url.length;
|
|
103
116
|
const queryString = url.slice(queryStart + 1, queryEnd);
|
|
104
117
|
if (queryString.length === 0)
|
|
@@ -106,15 +119,15 @@ function redactUrl(url) {
|
|
|
106
119
|
// FAST PATH: Quick check if any sensitive keywords present
|
|
107
120
|
// Using indexOf is faster than regex for simple substring matching
|
|
108
121
|
const lower = queryString.toLowerCase();
|
|
109
|
-
const hasSensitive = lower.includes("token") ||
|
|
110
|
-
lower.includes("key") ||
|
|
111
|
-
lower.includes("password") ||
|
|
112
|
-
lower.includes("passwd") ||
|
|
113
|
-
lower.includes("secret") ||
|
|
114
|
-
lower.includes("session") ||
|
|
115
|
-
lower.includes("auth");
|
|
122
|
+
const hasSensitive = lower.includes("token") ||
|
|
123
|
+
lower.includes("key") ||
|
|
124
|
+
lower.includes("password") ||
|
|
125
|
+
lower.includes("passwd") ||
|
|
126
|
+
lower.includes("secret") ||
|
|
127
|
+
lower.includes("session") ||
|
|
128
|
+
lower.includes("auth");
|
|
116
129
|
if (!hasSensitive) {
|
|
117
|
-
return url;
|
|
130
|
+
return url;
|
|
118
131
|
}
|
|
119
132
|
// SLOW PATH: Parse and redact
|
|
120
133
|
const redactedParams = [];
|
|
@@ -193,6 +206,7 @@ function fetcherImpl(args) {
|
|
|
193
206
|
method: args.method,
|
|
194
207
|
url: redactUrl(url),
|
|
195
208
|
statusCode: response.status,
|
|
209
|
+
responseHeaders: redactHeaders(Object.fromEntries(response.headers.entries())),
|
|
196
210
|
};
|
|
197
211
|
logger.debug("HTTP request succeeded", metadata);
|
|
198
212
|
}
|
|
@@ -209,6 +223,7 @@ function fetcherImpl(args) {
|
|
|
209
223
|
method: args.method,
|
|
210
224
|
url: redactUrl(url),
|
|
211
225
|
statusCode: response.status,
|
|
226
|
+
responseHeaders: redactHeaders(Object.fromEntries(response.headers.entries())),
|
|
212
227
|
};
|
|
213
228
|
logger.error("HTTP request failed with error status", metadata);
|
|
214
229
|
}
|
|
@@ -13,14 +13,12 @@ exports.makeRequest = void 0;
|
|
|
13
13
|
const signals_js_1 = require("./signals.js");
|
|
14
14
|
const makeRequest = (fetchFn, url, method, headers, requestBody, timeoutMs, abortSignal, withCredentials, duplex) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
15
|
const signals = [];
|
|
16
|
-
// Add timeout signal
|
|
17
16
|
let timeoutAbortId;
|
|
18
17
|
if (timeoutMs != null) {
|
|
19
18
|
const { signal, abortId } = (0, signals_js_1.getTimeoutSignal)(timeoutMs);
|
|
20
19
|
timeoutAbortId = abortId;
|
|
21
20
|
signals.push(signal);
|
|
22
21
|
}
|
|
23
|
-
// Add arbitrary signal
|
|
24
22
|
if (abortSignal != null) {
|
|
25
23
|
signals.push(abortSignal);
|
|
26
24
|
}
|
|
@@ -15,25 +15,20 @@ const MAX_RETRY_DELAY = 60000; // in milliseconds
|
|
|
15
15
|
const DEFAULT_MAX_RETRIES = 2;
|
|
16
16
|
const JITTER_FACTOR = 0.2; // 20% random jitter
|
|
17
17
|
function addPositiveJitter(delay) {
|
|
18
|
-
// Generate a random value between 0 and +JITTER_FACTOR
|
|
19
18
|
const jitterMultiplier = 1 + Math.random() * JITTER_FACTOR;
|
|
20
19
|
return delay * jitterMultiplier;
|
|
21
20
|
}
|
|
22
21
|
function addSymmetricJitter(delay) {
|
|
23
|
-
// Generate a random value in a JITTER_FACTOR-sized percentage range around delay
|
|
24
22
|
const jitterMultiplier = 1 + (Math.random() - 0.5) * JITTER_FACTOR;
|
|
25
23
|
return delay * jitterMultiplier;
|
|
26
24
|
}
|
|
27
25
|
function getRetryDelayFromHeaders(response, retryAttempt) {
|
|
28
|
-
// Check for Retry-After header first (RFC 7231), with no jitter
|
|
29
26
|
const retryAfter = response.headers.get("Retry-After");
|
|
30
27
|
if (retryAfter) {
|
|
31
|
-
// Parse as number of seconds...
|
|
32
28
|
const retryAfterSeconds = parseInt(retryAfter, 10);
|
|
33
29
|
if (!Number.isNaN(retryAfterSeconds) && retryAfterSeconds > 0) {
|
|
34
30
|
return Math.min(retryAfterSeconds * 1000, MAX_RETRY_DELAY);
|
|
35
31
|
}
|
|
36
|
-
// ...or as an HTTP date; both are valid
|
|
37
32
|
const retryAfterDate = new Date(retryAfter);
|
|
38
33
|
if (!Number.isNaN(retryAfterDate.getTime())) {
|
|
39
34
|
const delay = retryAfterDate.getTime() - Date.now();
|
|
@@ -42,19 +37,16 @@ function getRetryDelayFromHeaders(response, retryAttempt) {
|
|
|
42
37
|
}
|
|
43
38
|
}
|
|
44
39
|
}
|
|
45
|
-
// Then check for industry-standard X-RateLimit-Reset header, with positive jitter
|
|
46
40
|
const rateLimitReset = response.headers.get("X-RateLimit-Reset");
|
|
47
41
|
if (rateLimitReset) {
|
|
48
42
|
const resetTime = parseInt(rateLimitReset, 10);
|
|
49
43
|
if (!Number.isNaN(resetTime)) {
|
|
50
|
-
// Assume Unix timestamp in epoch seconds
|
|
51
44
|
const delay = resetTime * 1000 - Date.now();
|
|
52
45
|
if (delay > 0) {
|
|
53
46
|
return addPositiveJitter(Math.min(delay, MAX_RETRY_DELAY));
|
|
54
47
|
}
|
|
55
48
|
}
|
|
56
49
|
}
|
|
57
|
-
// Fall back to exponential backoff, with symmetric jitter
|
|
58
50
|
return addSymmetricJitter(Math.min(INITIAL_RETRY_DELAY * Math.pow(2, retryAttempt), MAX_RETRY_DELAY));
|
|
59
51
|
}
|
|
60
52
|
function requestWithRetries(requestFn_1) {
|
|
@@ -62,7 +54,6 @@ function requestWithRetries(requestFn_1) {
|
|
|
62
54
|
let response = yield requestFn();
|
|
63
55
|
for (let i = 0; i < maxRetries; ++i) {
|
|
64
56
|
if ([408, 429].includes(response.status) || response.status >= 500) {
|
|
65
|
-
// Get delay with appropriate jitter applied
|
|
66
57
|
const delay = getRetryDelayFromHeaders(response, i);
|
|
67
58
|
yield new Promise((resolve) => setTimeout(resolve, delay));
|
|
68
59
|
response = yield requestFn();
|
|
@@ -2,10 +2,4 @@ export declare function getTimeoutSignal(timeoutMs: number): {
|
|
|
2
2
|
signal: AbortSignal;
|
|
3
3
|
abortId: NodeJS.Timeout;
|
|
4
4
|
};
|
|
5
|
-
/**
|
|
6
|
-
* Returns an abort signal that is getting aborted when
|
|
7
|
-
* at least one of the specified abort signals is aborted.
|
|
8
|
-
*
|
|
9
|
-
* Requires at least node.js 18.
|
|
10
|
-
*/
|
|
11
5
|
export declare function anySignal(...args: AbortSignal[] | [AbortSignal[]]): AbortSignal;
|
|
@@ -8,26 +8,14 @@ function getTimeoutSignal(timeoutMs) {
|
|
|
8
8
|
const abortId = setTimeout(() => controller.abort(TIMEOUT), timeoutMs);
|
|
9
9
|
return { signal: controller.signal, abortId };
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
12
|
-
* Returns an abort signal that is getting aborted when
|
|
13
|
-
* at least one of the specified abort signals is aborted.
|
|
14
|
-
*
|
|
15
|
-
* Requires at least node.js 18.
|
|
16
|
-
*/
|
|
17
11
|
function anySignal(...args) {
|
|
18
|
-
// Allowing signals to be passed either as array
|
|
19
|
-
// of signals or as multiple arguments.
|
|
20
12
|
const signals = (args.length === 1 && Array.isArray(args[0]) ? args[0] : args);
|
|
21
13
|
const controller = new AbortController();
|
|
22
14
|
for (const signal of signals) {
|
|
23
15
|
if (signal.aborted) {
|
|
24
|
-
// Exiting early if one of the signals
|
|
25
|
-
// is already aborted.
|
|
26
16
|
controller.abort(signal === null || signal === void 0 ? void 0 : signal.reason);
|
|
27
17
|
break;
|
|
28
18
|
}
|
|
29
|
-
// Listening for signals and removing the listeners
|
|
30
|
-
// when at least one symbol is aborted.
|
|
31
19
|
signal.addEventListener("abort", () => controller.abort(signal === null || signal === void 0 ? void 0 : signal.reason), {
|
|
32
20
|
signal: controller.signal,
|
|
33
21
|
});
|
|
@@ -51,7 +51,7 @@ class Logger {
|
|
|
51
51
|
* @returns True if the level should be logged
|
|
52
52
|
*/
|
|
53
53
|
shouldLog(level) {
|
|
54
|
-
return !this.silent && this.level
|
|
54
|
+
return !this.silent && this.level <= logLevelMap[level];
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
57
57
|
* Checks if debug logging is enabled.
|
package/dist/cjs/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "6.
|
|
1
|
+
export declare const SDK_VERSION = "6.3.0";
|
package/dist/cjs/version.js
CHANGED
package/dist/esm/Client.mjs
CHANGED
|
@@ -16,7 +16,7 @@ export class phenomlClient {
|
|
|
16
16
|
this._options = Object.assign(Object.assign({}, _options), { logging: core.logging.createLogger(_options === null || _options === void 0 ? void 0 : _options.logging), headers: mergeHeaders({
|
|
17
17
|
"X-Fern-Language": "JavaScript",
|
|
18
18
|
"X-Fern-SDK-Name": "phenoml",
|
|
19
|
-
"X-Fern-SDK-Version": "6.
|
|
19
|
+
"X-Fern-SDK-Version": "6.3.0",
|
|
20
20
|
"User-Agent": "phenoml/auto",
|
|
21
21
|
"X-Fern-Runtime": core.RUNTIME.type,
|
|
22
22
|
"X-Fern-Runtime-Version": core.RUNTIME.version,
|
|
@@ -20,14 +20,21 @@ import { abortRawResponse, toRawResponse, unknownRawResponse } from "./RawRespon
|
|
|
20
20
|
import { requestWithRetries } from "./requestWithRetries.mjs";
|
|
21
21
|
const SENSITIVE_HEADERS = new Set([
|
|
22
22
|
"authorization",
|
|
23
|
+
"www-authenticate",
|
|
23
24
|
"x-api-key",
|
|
24
25
|
"api-key",
|
|
26
|
+
"apikey",
|
|
27
|
+
"x-api-token",
|
|
25
28
|
"x-auth-token",
|
|
29
|
+
"auth-token",
|
|
26
30
|
"cookie",
|
|
27
31
|
"set-cookie",
|
|
28
32
|
"proxy-authorization",
|
|
33
|
+
"proxy-authenticate",
|
|
29
34
|
"x-csrf-token",
|
|
30
35
|
"x-xsrf-token",
|
|
36
|
+
"x-session-token",
|
|
37
|
+
"x-access-token",
|
|
31
38
|
]);
|
|
32
39
|
function redactHeaders(headers) {
|
|
33
40
|
const filtered = {};
|
|
@@ -81,20 +88,26 @@ function redactUrl(url) {
|
|
|
81
88
|
if (protocolIndex === -1)
|
|
82
89
|
return url;
|
|
83
90
|
const afterProtocol = protocolIndex + 3;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
// Find the first delimiter that marks the end of the authority section
|
|
92
|
+
const pathStart = url.indexOf("/", afterProtocol);
|
|
93
|
+
let queryStart = url.indexOf("?", afterProtocol);
|
|
94
|
+
let fragmentStart = url.indexOf("#", afterProtocol);
|
|
95
|
+
const firstDelimiter = Math.min(pathStart === -1 ? url.length : pathStart, queryStart === -1 ? url.length : queryStart, fragmentStart === -1 ? url.length : fragmentStart);
|
|
96
|
+
// Find the LAST @ before the delimiter (handles multiple @ in credentials)
|
|
97
|
+
let atIndex = -1;
|
|
98
|
+
for (let i = afterProtocol; i < firstDelimiter; i++) {
|
|
99
|
+
if (url[i] === "@") {
|
|
100
|
+
atIndex = i;
|
|
92
101
|
}
|
|
93
102
|
}
|
|
94
|
-
|
|
103
|
+
if (atIndex !== -1) {
|
|
104
|
+
url = `${url.slice(0, afterProtocol)}[REDACTED]@${url.slice(atIndex + 1)}`;
|
|
105
|
+
}
|
|
106
|
+
// Recalculate queryStart since url might have changed
|
|
107
|
+
queryStart = url.indexOf("?");
|
|
95
108
|
if (queryStart === -1)
|
|
96
109
|
return url;
|
|
97
|
-
|
|
110
|
+
fragmentStart = url.indexOf("#", queryStart);
|
|
98
111
|
const queryEnd = fragmentStart !== -1 ? fragmentStart : url.length;
|
|
99
112
|
const queryString = url.slice(queryStart + 1, queryEnd);
|
|
100
113
|
if (queryString.length === 0)
|
|
@@ -102,15 +115,15 @@ function redactUrl(url) {
|
|
|
102
115
|
// FAST PATH: Quick check if any sensitive keywords present
|
|
103
116
|
// Using indexOf is faster than regex for simple substring matching
|
|
104
117
|
const lower = queryString.toLowerCase();
|
|
105
|
-
const hasSensitive = lower.includes("token") ||
|
|
106
|
-
lower.includes("key") ||
|
|
107
|
-
lower.includes("password") ||
|
|
108
|
-
lower.includes("passwd") ||
|
|
109
|
-
lower.includes("secret") ||
|
|
110
|
-
lower.includes("session") ||
|
|
111
|
-
lower.includes("auth");
|
|
118
|
+
const hasSensitive = lower.includes("token") ||
|
|
119
|
+
lower.includes("key") ||
|
|
120
|
+
lower.includes("password") ||
|
|
121
|
+
lower.includes("passwd") ||
|
|
122
|
+
lower.includes("secret") ||
|
|
123
|
+
lower.includes("session") ||
|
|
124
|
+
lower.includes("auth");
|
|
112
125
|
if (!hasSensitive) {
|
|
113
|
-
return url;
|
|
126
|
+
return url;
|
|
114
127
|
}
|
|
115
128
|
// SLOW PATH: Parse and redact
|
|
116
129
|
const redactedParams = [];
|
|
@@ -189,6 +202,7 @@ export function fetcherImpl(args) {
|
|
|
189
202
|
method: args.method,
|
|
190
203
|
url: redactUrl(url),
|
|
191
204
|
statusCode: response.status,
|
|
205
|
+
responseHeaders: redactHeaders(Object.fromEntries(response.headers.entries())),
|
|
192
206
|
};
|
|
193
207
|
logger.debug("HTTP request succeeded", metadata);
|
|
194
208
|
}
|
|
@@ -205,6 +219,7 @@ export function fetcherImpl(args) {
|
|
|
205
219
|
method: args.method,
|
|
206
220
|
url: redactUrl(url),
|
|
207
221
|
statusCode: response.status,
|
|
222
|
+
responseHeaders: redactHeaders(Object.fromEntries(response.headers.entries())),
|
|
208
223
|
};
|
|
209
224
|
logger.error("HTTP request failed with error status", metadata);
|
|
210
225
|
}
|
|
@@ -10,14 +10,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { anySignal, getTimeoutSignal } from "./signals.mjs";
|
|
11
11
|
export const makeRequest = (fetchFn, url, method, headers, requestBody, timeoutMs, abortSignal, withCredentials, duplex) => __awaiter(void 0, void 0, void 0, function* () {
|
|
12
12
|
const signals = [];
|
|
13
|
-
// Add timeout signal
|
|
14
13
|
let timeoutAbortId;
|
|
15
14
|
if (timeoutMs != null) {
|
|
16
15
|
const { signal, abortId } = getTimeoutSignal(timeoutMs);
|
|
17
16
|
timeoutAbortId = abortId;
|
|
18
17
|
signals.push(signal);
|
|
19
18
|
}
|
|
20
|
-
// Add arbitrary signal
|
|
21
19
|
if (abortSignal != null) {
|
|
22
20
|
signals.push(abortSignal);
|
|
23
21
|
}
|
|
@@ -12,25 +12,20 @@ const MAX_RETRY_DELAY = 60000; // in milliseconds
|
|
|
12
12
|
const DEFAULT_MAX_RETRIES = 2;
|
|
13
13
|
const JITTER_FACTOR = 0.2; // 20% random jitter
|
|
14
14
|
function addPositiveJitter(delay) {
|
|
15
|
-
// Generate a random value between 0 and +JITTER_FACTOR
|
|
16
15
|
const jitterMultiplier = 1 + Math.random() * JITTER_FACTOR;
|
|
17
16
|
return delay * jitterMultiplier;
|
|
18
17
|
}
|
|
19
18
|
function addSymmetricJitter(delay) {
|
|
20
|
-
// Generate a random value in a JITTER_FACTOR-sized percentage range around delay
|
|
21
19
|
const jitterMultiplier = 1 + (Math.random() - 0.5) * JITTER_FACTOR;
|
|
22
20
|
return delay * jitterMultiplier;
|
|
23
21
|
}
|
|
24
22
|
function getRetryDelayFromHeaders(response, retryAttempt) {
|
|
25
|
-
// Check for Retry-After header first (RFC 7231), with no jitter
|
|
26
23
|
const retryAfter = response.headers.get("Retry-After");
|
|
27
24
|
if (retryAfter) {
|
|
28
|
-
// Parse as number of seconds...
|
|
29
25
|
const retryAfterSeconds = parseInt(retryAfter, 10);
|
|
30
26
|
if (!Number.isNaN(retryAfterSeconds) && retryAfterSeconds > 0) {
|
|
31
27
|
return Math.min(retryAfterSeconds * 1000, MAX_RETRY_DELAY);
|
|
32
28
|
}
|
|
33
|
-
// ...or as an HTTP date; both are valid
|
|
34
29
|
const retryAfterDate = new Date(retryAfter);
|
|
35
30
|
if (!Number.isNaN(retryAfterDate.getTime())) {
|
|
36
31
|
const delay = retryAfterDate.getTime() - Date.now();
|
|
@@ -39,19 +34,16 @@ function getRetryDelayFromHeaders(response, retryAttempt) {
|
|
|
39
34
|
}
|
|
40
35
|
}
|
|
41
36
|
}
|
|
42
|
-
// Then check for industry-standard X-RateLimit-Reset header, with positive jitter
|
|
43
37
|
const rateLimitReset = response.headers.get("X-RateLimit-Reset");
|
|
44
38
|
if (rateLimitReset) {
|
|
45
39
|
const resetTime = parseInt(rateLimitReset, 10);
|
|
46
40
|
if (!Number.isNaN(resetTime)) {
|
|
47
|
-
// Assume Unix timestamp in epoch seconds
|
|
48
41
|
const delay = resetTime * 1000 - Date.now();
|
|
49
42
|
if (delay > 0) {
|
|
50
43
|
return addPositiveJitter(Math.min(delay, MAX_RETRY_DELAY));
|
|
51
44
|
}
|
|
52
45
|
}
|
|
53
46
|
}
|
|
54
|
-
// Fall back to exponential backoff, with symmetric jitter
|
|
55
47
|
return addSymmetricJitter(Math.min(INITIAL_RETRY_DELAY * Math.pow(2, retryAttempt), MAX_RETRY_DELAY));
|
|
56
48
|
}
|
|
57
49
|
export function requestWithRetries(requestFn_1) {
|
|
@@ -59,7 +51,6 @@ export function requestWithRetries(requestFn_1) {
|
|
|
59
51
|
let response = yield requestFn();
|
|
60
52
|
for (let i = 0; i < maxRetries; ++i) {
|
|
61
53
|
if ([408, 429].includes(response.status) || response.status >= 500) {
|
|
62
|
-
// Get delay with appropriate jitter applied
|
|
63
54
|
const delay = getRetryDelayFromHeaders(response, i);
|
|
64
55
|
yield new Promise((resolve) => setTimeout(resolve, delay));
|
|
65
56
|
response = yield requestFn();
|
|
@@ -2,10 +2,4 @@ export declare function getTimeoutSignal(timeoutMs: number): {
|
|
|
2
2
|
signal: AbortSignal;
|
|
3
3
|
abortId: NodeJS.Timeout;
|
|
4
4
|
};
|
|
5
|
-
/**
|
|
6
|
-
* Returns an abort signal that is getting aborted when
|
|
7
|
-
* at least one of the specified abort signals is aborted.
|
|
8
|
-
*
|
|
9
|
-
* Requires at least node.js 18.
|
|
10
|
-
*/
|
|
11
5
|
export declare function anySignal(...args: AbortSignal[] | [AbortSignal[]]): AbortSignal;
|
|
@@ -4,26 +4,14 @@ export function getTimeoutSignal(timeoutMs) {
|
|
|
4
4
|
const abortId = setTimeout(() => controller.abort(TIMEOUT), timeoutMs);
|
|
5
5
|
return { signal: controller.signal, abortId };
|
|
6
6
|
}
|
|
7
|
-
/**
|
|
8
|
-
* Returns an abort signal that is getting aborted when
|
|
9
|
-
* at least one of the specified abort signals is aborted.
|
|
10
|
-
*
|
|
11
|
-
* Requires at least node.js 18.
|
|
12
|
-
*/
|
|
13
7
|
export function anySignal(...args) {
|
|
14
|
-
// Allowing signals to be passed either as array
|
|
15
|
-
// of signals or as multiple arguments.
|
|
16
8
|
const signals = (args.length === 1 && Array.isArray(args[0]) ? args[0] : args);
|
|
17
9
|
const controller = new AbortController();
|
|
18
10
|
for (const signal of signals) {
|
|
19
11
|
if (signal.aborted) {
|
|
20
|
-
// Exiting early if one of the signals
|
|
21
|
-
// is already aborted.
|
|
22
12
|
controller.abort(signal === null || signal === void 0 ? void 0 : signal.reason);
|
|
23
13
|
break;
|
|
24
14
|
}
|
|
25
|
-
// Listening for signals and removing the listeners
|
|
26
|
-
// when at least one symbol is aborted.
|
|
27
15
|
signal.addEventListener("abort", () => controller.abort(signal === null || signal === void 0 ? void 0 : signal.reason), {
|
|
28
16
|
signal: controller.signal,
|
|
29
17
|
});
|
|
@@ -46,7 +46,7 @@ export class Logger {
|
|
|
46
46
|
* @returns True if the level should be logged
|
|
47
47
|
*/
|
|
48
48
|
shouldLog(level) {
|
|
49
|
-
return !this.silent && this.level
|
|
49
|
+
return !this.silent && this.level <= logLevelMap[level];
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
52
|
* Checks if debug logging is enabled.
|
package/dist/esm/version.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "6.
|
|
1
|
+
export declare const SDK_VERSION = "6.3.0";
|
package/dist/esm/version.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION = "6.
|
|
1
|
+
export const SDK_VERSION = "6.3.0";
|