@apifuse/provider-sdk 2.2.0-beta.1 → 2.2.0-beta.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @apifuse/provider-sdk Changelog
2
2
 
3
+ ## 2.2.0-beta.2
4
+
5
+ - Release candidate for main commit ceefad020a1038eade542fd3b128667b39625f6f.
6
+
3
7
  ## 2.2.0-beta.1
4
8
 
5
9
  - Release candidate for main commit 5056b8c89fe0fa8f10bafcd30f83bcc421d4b5c5.
@@ -35,6 +39,7 @@
35
39
  ## Unreleased
36
40
 
37
41
  - Add `arrayBuffer()` and `bytes()` to `HttpResponse` so `ctx.http` consumers can read binary-safe upstream bodies; internal response handling is now byte-first.
42
+ - Preserve identity-only operation `connectionId` values in `ProviderContext` without requiring credential material.
38
43
 
39
44
  ## 2.1.0-beta.15
40
45
 
@@ -1,317 +1,12 @@
1
1
  import { resolveProxyConfigAsync } from "../config/loader";
2
2
  import { ProviderError, TransportError } from "../errors";
3
- import { parseSseStream, readableBytes, readableLines, readableTextChunks, } from "../stream";
4
- import { HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, } from "../types";
3
+ import { parseSseStream, readableBytes, readableLines, readableTextChunks } from "../stream";
4
+ import { computeProxyAttemptIndex, computeProxyTransportRetryDelayMs, createDefaultProxyTransportRetryOptions, isProxyTransportRetryMethod, normalizeProxyTransportRetryOptions, proxyTransportRetryErrorCode, proxyTransportRetryErrorStatus, shouldRetryProxyTransportAttempt, validateUnsafeProxyTransportRetryMethods, } from "./proxy-retry-policy";
5
5
  import { appendQueryParams, normalizeHttpRequestBody } from "./request-options";
6
6
  const DEFAULT_HTTP_BASE_URL = "http://localhost";
7
7
  function isHttpStatusOutcome(outcome) {
8
8
  return "kind" in outcome && outcome.kind === "http-status";
9
9
  }
10
- const DEFAULT_RETRY_METHODS = ["GET", "HEAD", "OPTIONS"];
11
- const DEFAULT_RETRY_ERROR_CODES = [
12
- "transport_network_error",
13
- "transport_timeout",
14
- ];
15
- const SAFE_RETRY_STATUS_CODES = [408, 429, 500, 502, 503, 504];
16
- const RATE_LIMIT_RETRY_STATUS_CODES = [429, 503];
17
- const KNOWN_RETRY_METHODS = new Set([
18
- "GET",
19
- "HEAD",
20
- "POST",
21
- "PUT",
22
- "DELETE",
23
- "OPTIONS",
24
- "TRACE",
25
- "PATCH",
26
- ]);
27
- const UNSAFE_RETRY_METHODS = new Set([
28
- "POST",
29
- "PUT",
30
- "PATCH",
31
- "DELETE",
32
- "TRACE",
33
- ]);
34
- const MAX_RETRY_ATTEMPTS = 8;
35
- const MAX_RETRY_DELAY_MS = 30_000;
36
- function hasOwnValue(values, value) {
37
- if (typeof value !== "string")
38
- return false;
39
- return Object.values(values).some((candidate) => candidate === value);
40
- }
41
- function createInvalidRetryPolicyError(message) {
42
- return new ProviderError(message, { code: "retry_invalid_policy" });
43
- }
44
- function createRetryOptions(preset) {
45
- switch (preset) {
46
- case HttpRetryPreset.Off:
47
- return {
48
- preset,
49
- attempts: 1,
50
- methods: DEFAULT_RETRY_METHODS,
51
- statusCodes: [],
52
- errorCodes: DEFAULT_RETRY_ERROR_CODES,
53
- delayStrategy: HttpRetryDelayStrategy.Exponential,
54
- baseDelayMs: 100,
55
- maxDelayMs: 1_000,
56
- jitter: HttpRetryJitter.Full,
57
- retryAfter: HttpRetryAfterPolicy.Ignore,
58
- unsafeMethodPolicy: HttpRetryUnsafeMethodPolicy.Reject,
59
- };
60
- case HttpRetryPreset.SafeRead:
61
- return {
62
- preset,
63
- attempts: 3,
64
- methods: DEFAULT_RETRY_METHODS,
65
- statusCodes: SAFE_RETRY_STATUS_CODES,
66
- errorCodes: DEFAULT_RETRY_ERROR_CODES,
67
- delayStrategy: HttpRetryDelayStrategy.Exponential,
68
- baseDelayMs: 100,
69
- maxDelayMs: 2_000,
70
- jitter: HttpRetryJitter.Full,
71
- retryAfter: HttpRetryAfterPolicy.Cap,
72
- unsafeMethodPolicy: HttpRetryUnsafeMethodPolicy.Reject,
73
- };
74
- case HttpRetryPreset.AggressiveRead:
75
- return {
76
- preset,
77
- attempts: 4,
78
- methods: DEFAULT_RETRY_METHODS,
79
- statusCodes: SAFE_RETRY_STATUS_CODES,
80
- errorCodes: DEFAULT_RETRY_ERROR_CODES,
81
- delayStrategy: HttpRetryDelayStrategy.Exponential,
82
- baseDelayMs: 150,
83
- maxDelayMs: 5_000,
84
- jitter: HttpRetryJitter.Full,
85
- retryAfter: HttpRetryAfterPolicy.Cap,
86
- unsafeMethodPolicy: HttpRetryUnsafeMethodPolicy.Reject,
87
- };
88
- case HttpRetryPreset.RateLimitAware:
89
- return {
90
- preset,
91
- attempts: 3,
92
- methods: DEFAULT_RETRY_METHODS,
93
- statusCodes: RATE_LIMIT_RETRY_STATUS_CODES,
94
- errorCodes: ["transport_timeout"],
95
- delayStrategy: HttpRetryDelayStrategy.Exponential,
96
- baseDelayMs: 250,
97
- maxDelayMs: 5_000,
98
- jitter: HttpRetryJitter.Equal,
99
- retryAfter: HttpRetryAfterPolicy.Respect,
100
- unsafeMethodPolicy: HttpRetryUnsafeMethodPolicy.Reject,
101
- };
102
- case HttpRetryPreset.TransportTransient:
103
- return {
104
- preset,
105
- attempts: 3,
106
- methods: DEFAULT_RETRY_METHODS,
107
- statusCodes: [],
108
- errorCodes: DEFAULT_RETRY_ERROR_CODES,
109
- delayStrategy: HttpRetryDelayStrategy.Exponential,
110
- baseDelayMs: 100,
111
- maxDelayMs: 1_000,
112
- jitter: HttpRetryJitter.Full,
113
- retryAfter: HttpRetryAfterPolicy.Ignore,
114
- unsafeMethodPolicy: HttpRetryUnsafeMethodPolicy.Reject,
115
- };
116
- }
117
- throw createInvalidRetryPolicyError(`Unknown HTTP retry preset: ${preset}`);
118
- }
119
- function clampPositiveInteger(value, fallback, max) {
120
- if (value === undefined)
121
- return fallback;
122
- if (!Number.isFinite(value) || value < 1)
123
- return fallback;
124
- return Math.min(Math.floor(value), max);
125
- }
126
- function clampDelay(value, fallback) {
127
- if (value === undefined)
128
- return fallback;
129
- if (!Number.isFinite(value) || value < 0)
130
- return fallback;
131
- return Math.min(Math.floor(value), MAX_RETRY_DELAY_MS);
132
- }
133
- function normalizeRetryOptions(retry) {
134
- if (retry === undefined || retry === false) {
135
- return undefined;
136
- }
137
- if (retry === true) {
138
- return createRetryOptions(HttpRetryPreset.TransportTransient);
139
- }
140
- if (typeof retry === "string") {
141
- if (!hasOwnValue(HttpRetryPreset, retry)) {
142
- throw createInvalidRetryPolicyError(`Unknown HTTP retry preset: ${retry}`);
143
- }
144
- return createRetryOptions(retry);
145
- }
146
- if (typeof retry !== "object" || retry === null) {
147
- throw createInvalidRetryPolicyError("HTTP retry policy must be an object");
148
- }
149
- if (Array.isArray(retry)) {
150
- throw createInvalidRetryPolicyError("HTTP retry policy must be a plain object");
151
- }
152
- validateRetryOptionsShape(retry);
153
- const base = createRetryOptions(retry.preset ?? HttpRetryPreset.TransportTransient);
154
- const maxDelayMs = clampDelay(retry.maxDelayMs, base.maxDelayMs);
155
- const normalized = {
156
- preset: retry.preset ?? base.preset,
157
- attempts: clampPositiveInteger(retry.attempts, base.attempts, MAX_RETRY_ATTEMPTS),
158
- methods: retry.methods?.map((method) => method.toUpperCase()) ?? base.methods,
159
- statusCodes: retry.statusCodes?.filter((status) => Number.isInteger(status)) ??
160
- base.statusCodes,
161
- errorCodes: retry.errorCodes ?? base.errorCodes,
162
- delayStrategy: retry.delayStrategy ?? base.delayStrategy,
163
- baseDelayMs: clampDelay(retry.baseDelayMs, base.baseDelayMs),
164
- maxDelayMs,
165
- jitter: retry.jitter ?? base.jitter,
166
- retryAfter: retry.retryAfter ?? base.retryAfter,
167
- unsafeMethodPolicy: retry.unsafeMethodPolicy ?? base.unsafeMethodPolicy,
168
- };
169
- return normalized;
170
- }
171
- function validateRetryOptionsShape(retry) {
172
- if (retry.preset !== undefined &&
173
- !hasOwnValue(HttpRetryPreset, retry.preset)) {
174
- throw createInvalidRetryPolicyError(`Unknown HTTP retry preset: ${String(retry.preset)}`);
175
- }
176
- if (retry.delayStrategy !== undefined &&
177
- !hasOwnValue(HttpRetryDelayStrategy, retry.delayStrategy)) {
178
- throw createInvalidRetryPolicyError(`Unknown HTTP retry delay strategy: ${String(retry.delayStrategy)}`);
179
- }
180
- if (retry.jitter !== undefined &&
181
- !hasOwnValue(HttpRetryJitter, retry.jitter)) {
182
- throw createInvalidRetryPolicyError(`Unknown HTTP retry jitter policy: ${String(retry.jitter)}`);
183
- }
184
- if (retry.retryAfter !== undefined &&
185
- !hasOwnValue(HttpRetryAfterPolicy, retry.retryAfter)) {
186
- throw createInvalidRetryPolicyError(`Unknown HTTP retry-after policy: ${String(retry.retryAfter)}`);
187
- }
188
- if (retry.unsafeMethodPolicy !== undefined &&
189
- !hasOwnValue(HttpRetryUnsafeMethodPolicy, retry.unsafeMethodPolicy)) {
190
- throw createInvalidRetryPolicyError(`Unknown HTTP retry unsafe method policy: ${String(retry.unsafeMethodPolicy)}`);
191
- }
192
- if (retry.methods !== undefined) {
193
- if (!Array.isArray(retry.methods)) {
194
- throw createInvalidRetryPolicyError("HTTP retry methods must be an array");
195
- }
196
- const nonStringMethods = retry.methods.filter((method) => typeof method !== "string");
197
- if (nonStringMethods.length > 0) {
198
- throw createInvalidRetryPolicyError("HTTP retry methods must contain only strings");
199
- }
200
- const unknownMethods = retry.methods
201
- .map((method) => method.toUpperCase())
202
- .filter((method) => !KNOWN_RETRY_METHODS.has(method));
203
- if (unknownMethods.length > 0) {
204
- throw createInvalidRetryPolicyError(`Unknown HTTP retry method(s): ${unknownMethods.join(", ")}`);
205
- }
206
- }
207
- if (retry.statusCodes !== undefined) {
208
- if (!Array.isArray(retry.statusCodes)) {
209
- throw createInvalidRetryPolicyError("HTTP retry statusCodes must be an array");
210
- }
211
- const invalidStatusCodes = retry.statusCodes.filter((status) => !Number.isInteger(status) ||
212
- Number(status) < 100 ||
213
- Number(status) > 599);
214
- if (invalidStatusCodes.length > 0) {
215
- throw createInvalidRetryPolicyError("HTTP retry statusCodes must contain HTTP status integers in [100, 599]");
216
- }
217
- }
218
- if (retry.errorCodes !== undefined) {
219
- if (!Array.isArray(retry.errorCodes)) {
220
- throw createInvalidRetryPolicyError("HTTP retry errorCodes must be an array");
221
- }
222
- const nonStringErrorCodes = retry.errorCodes.filter((errorCode) => typeof errorCode !== "string");
223
- if (nonStringErrorCodes.length > 0) {
224
- throw createInvalidRetryPolicyError("HTTP retry errorCodes must contain only strings");
225
- }
226
- }
227
- if (retry.preset === HttpRetryPreset.Off &&
228
- ((retry.attempts !== undefined && retry.attempts > 1) ||
229
- (retry.statusCodes !== undefined && retry.statusCodes.length > 0))) {
230
- throw createInvalidRetryPolicyError("HTTP retry preset off cannot be combined with retry-enabling overrides");
231
- }
232
- }
233
- function validateUnsafeRetryMethods(options) {
234
- if (options.unsafeMethodPolicy ===
235
- HttpRetryUnsafeMethodPolicy.AllowExplicitUnsafe) {
236
- return;
237
- }
238
- const unsafeMethods = options.methods.filter((method) => UNSAFE_RETRY_METHODS.has(method.toUpperCase()));
239
- if (unsafeMethods.length === 0)
240
- return;
241
- throw new ProviderError(`HTTP retry methods include unsafe method(s): ${unsafeMethods.join(", ")}`, { code: "retry_unsafe_method" });
242
- }
243
- function isMethodRetryable(method, options) {
244
- return options.methods
245
- .map((allowedMethod) => allowedMethod.toUpperCase())
246
- .includes(method.toUpperCase());
247
- }
248
- function retryErrorCode(error) {
249
- if (error instanceof TransportError) {
250
- return error.code;
251
- }
252
- if (error && typeof error === "object" && "code" in error) {
253
- const code = Reflect.get(error, "code");
254
- return typeof code === "string" ? code : undefined;
255
- }
256
- return undefined;
257
- }
258
- function retryErrorStatus(error) {
259
- if (error instanceof TransportError) {
260
- return error.status ?? error.upstreamStatus;
261
- }
262
- return undefined;
263
- }
264
- function shouldRetryTransportError(error, options) {
265
- const code = retryErrorCode(error);
266
- return Boolean(code && options.errorCodes.includes(code));
267
- }
268
- function retryAfterHeader(headers) {
269
- for (const [name, value] of Object.entries(headers)) {
270
- if (name.toLowerCase() === "retry-after")
271
- return value;
272
- }
273
- return undefined;
274
- }
275
- function parseRetryAfterMs(headers, now = Date.now()) {
276
- const value = retryAfterHeader(headers);
277
- if (!value)
278
- return undefined;
279
- const seconds = Number(value);
280
- if (Number.isFinite(seconds)) {
281
- return Math.max(0, Math.floor(seconds * 1_000));
282
- }
283
- const dateMs = Date.parse(value);
284
- if (!Number.isNaN(dateMs)) {
285
- return Math.max(0, dateMs - now);
286
- }
287
- return undefined;
288
- }
289
- function computeRetryDelayMs(options, attemptIndex, headers) {
290
- const multiplier = options.delayStrategy === HttpRetryDelayStrategy.Exponential
291
- ? 2 ** Math.max(0, attemptIndex - 1)
292
- : 1;
293
- const configuredDelay = Math.min(options.baseDelayMs * multiplier, options.maxDelayMs);
294
- const retryAfterMs = options.retryAfter === HttpRetryAfterPolicy.Ignore
295
- ? undefined
296
- : headers
297
- ? parseRetryAfterMs(headers)
298
- : undefined;
299
- if (retryAfterMs !== undefined) {
300
- const boundedRetryAfterMs = Math.min(retryAfterMs, options.maxDelayMs);
301
- if (options.retryAfter === HttpRetryAfterPolicy.Cap) {
302
- return Math.min(boundedRetryAfterMs, configuredDelay);
303
- }
304
- return boundedRetryAfterMs;
305
- }
306
- switch (options.jitter) {
307
- case HttpRetryJitter.None:
308
- return configuredDelay;
309
- case HttpRetryJitter.Equal:
310
- return Math.floor(configuredDelay / 2 + Math.random() * (configuredDelay / 2));
311
- case HttpRetryJitter.Full:
312
- return Math.floor(Math.random() * configuredDelay);
313
- }
314
- }
315
10
  async function sleep(ms) {
316
11
  if (ms <= 0)
317
12
  return;
@@ -330,9 +25,7 @@ function hasHeader(headers, name) {
330
25
  }
331
26
  function withClientHeaders(options, clientOptions, body) {
332
27
  const headers = {
333
- ...(clientOptions.userAgent
334
- ? { "User-Agent": clientOptions.userAgent }
335
- : {}),
28
+ ...(clientOptions.userAgent ? { "User-Agent": clientOptions.userAgent } : {}),
336
29
  ...options?.headers,
337
30
  };
338
31
  if (body !== undefined && !hasHeader(headers, "Content-Type")) {
@@ -344,9 +37,7 @@ function withClientHeaders(options, clientOptions, body) {
344
37
  };
345
38
  }
346
39
  function parseHttpData(body, headers) {
347
- const contentType = headers["content-type"] ??
348
- headers["Content-Type"] ??
349
- headers["CONTENT-TYPE"];
40
+ const contentType = headers["content-type"] ?? headers["Content-Type"] ?? headers["CONTENT-TYPE"];
350
41
  if (contentType?.includes("application/json")) {
351
42
  return body ? JSON.parse(body) : null;
352
43
  }
@@ -403,12 +94,8 @@ async function toNativeHttpResponse(response) {
403
94
  data,
404
95
  headers,
405
96
  json: async () => {
406
- const contentType = headers["content-type"] ??
407
- headers["Content-Type"] ??
408
- headers["CONTENT-TYPE"];
409
- return parseJson(contentType?.includes("application/json") && !rawText
410
- ? "null"
411
- : rawText);
97
+ const contentType = headers["content-type"] ?? headers["Content-Type"] ?? headers["CONTENT-TYPE"];
98
+ return parseJson(contentType?.includes("application/json") && !rawText ? "null" : rawText);
412
99
  },
413
100
  ok: response.status >= 200 && response.status < 300,
414
101
  status: response.status,
@@ -478,17 +165,16 @@ function resolveHttpUrl(baseUrl, url) {
478
165
  return new URL(url, baseUrl ?? DEFAULT_HTTP_BASE_URL).toString();
479
166
  }
480
167
  async function resolveNativeProxy(options, clientOptions, warn, proxyAttemptOffset = 0) {
481
- const baseProxyAttempt = clientOptions.proxyAttempt === undefined ||
482
- !Number.isFinite(clientOptions.proxyAttempt)
483
- ? 0
484
- : Math.max(0, Math.floor(clientOptions.proxyAttempt));
485
168
  const resolvedProxy = await resolveProxyConfigAsync({
486
169
  proxy: options.proxy ?? clientOptions.proxy,
487
170
  upstream: clientOptions.upstream,
488
171
  apifuseConfig: clientOptions.apifuseConfig,
489
172
  proxyPolicy: clientOptions.proxyPolicy,
490
173
  affinityKey: clientOptions.affinityKey,
491
- proxyAttempt: baseProxyAttempt + proxyAttemptOffset,
174
+ proxyAttempt: computeProxyAttemptIndex({
175
+ baseProxyAttempt: clientOptions.proxyAttempt,
176
+ retryAttemptOffset: proxyAttemptOffset,
177
+ }),
492
178
  telemetry: clientOptions.telemetry,
493
179
  });
494
180
  if (resolvedProxy.shouldWarn) {
@@ -622,15 +308,15 @@ export function createHttpClient(baseUrl, clientOptions = {}) {
622
308
  const headersOptions = withClientHeaders(options, clientOptions, options.body);
623
309
  const methodName = normalizeHttpMethod(method);
624
310
  const explicitRetry = headersOptions.retry !== undefined;
625
- const retryOptions = normalizeRetryOptions(headersOptions.retry) ??
626
- (explicitRetry
627
- ? undefined
628
- : createRetryOptions(HttpRetryPreset.TransportTransient));
311
+ const retryOptions = normalizeProxyTransportRetryOptions(headersOptions.retry, {
312
+ label: "HTTP",
313
+ }) ??
314
+ (explicitRetry ? undefined : createDefaultProxyTransportRetryOptions({ label: "HTTP" }));
629
315
  if (retryOptions)
630
- validateUnsafeRetryMethods(retryOptions);
316
+ validateUnsafeProxyTransportRetryMethods(retryOptions, "HTTP");
631
317
  const retryEnabled = Boolean(retryOptions &&
632
318
  retryOptions.attempts > 1 &&
633
- isMethodRetryable(methodName, retryOptions));
319
+ isProxyTransportRetryMethod(methodName, retryOptions));
634
320
  const statusRetryEnabled = Boolean(retryEnabled &&
635
321
  explicitRetry &&
636
322
  retryOptions &&
@@ -655,14 +341,13 @@ export function createHttpClient(baseUrl, clientOptions = {}) {
655
341
  if (isHttpStatusOutcome(outcome)) {
656
342
  lastStatus = outcome.status;
657
343
  if (outcome.retryable && attempt < retryOptions.attempts) {
658
- await sleep(computeRetryDelayMs(retryOptions, attempt, outcome.headers));
344
+ await sleep(computeProxyTransportRetryDelayMs(retryOptions, attempt, outcome.headers));
659
345
  continue;
660
346
  }
661
347
  throw toUpstreamHttpError(outcome.status);
662
348
  }
663
349
  const response = outcome;
664
- if (response.status >= 400 &&
665
- headersOptions.throwOnHttpError !== false) {
350
+ if (response.status >= 400 && headersOptions.throwOnHttpError !== false) {
666
351
  throw toUpstreamHttpError(response.status);
667
352
  }
668
353
  if (attempt > 1) {
@@ -679,13 +364,18 @@ export function createHttpClient(baseUrl, clientOptions = {}) {
679
364
  return response;
680
365
  }
681
366
  catch (error) {
682
- lastErrorCode = retryErrorCode(error);
683
- lastStatus = retryErrorStatus(error);
367
+ lastErrorCode = proxyTransportRetryErrorCode(error);
368
+ lastStatus = proxyTransportRetryErrorStatus(error);
684
369
  const proxyUsed = Boolean(error.proxyUsed);
685
370
  if (attempt < retryOptions.attempts &&
686
- (explicitRetry || proxyUsed) &&
687
- shouldRetryTransportError(error, retryOptions)) {
688
- await sleep(computeRetryDelayMs(retryOptions, attempt));
371
+ shouldRetryProxyTransportAttempt({
372
+ error,
373
+ explicitRetry,
374
+ method: methodName,
375
+ options: retryOptions,
376
+ proxyUsed,
377
+ })) {
378
+ await sleep(computeProxyTransportRetryDelayMs(retryOptions, attempt));
689
379
  continue;
690
380
  }
691
381
  throw error;
@@ -0,0 +1,40 @@
1
+ import type { HttpMethod, HttpRetryOptions, RequestOptions } from "../types";
2
+ import { HttpRetryPreset } from "../types";
3
+ export type NormalizedProxyTransportRetryOptions = Required<Pick<HttpRetryOptions, "attempts" | "delayStrategy" | "baseDelayMs" | "maxDelayMs" | "jitter" | "retryAfter" | "unsafeMethodPolicy">> & {
4
+ preset?: HttpRetryPreset;
5
+ methods: readonly string[];
6
+ statusCodes: readonly number[];
7
+ errorCodes: readonly string[];
8
+ };
9
+ export declare const DEFAULT_PROXY_TRANSPORT_RETRY_METHODS: readonly ["GET", "HEAD", "OPTIONS"];
10
+ export declare const DEFAULT_PROXY_TRANSPORT_RETRY_ERROR_CODES: readonly ["transport_network_error", "transport_timeout"];
11
+ export declare const MAX_PROXY_TRANSPORT_RETRY_ATTEMPTS = 8;
12
+ type RetryPolicyLabel = "HTTP" | "Stealth" | "Proxy transport";
13
+ export declare function proxyTransportRetryErrorCode(error: unknown): string | undefined;
14
+ export declare function proxyTransportRetryErrorStatus(error: unknown): number | undefined;
15
+ export declare function createDefaultProxyTransportRetryOptions(options?: {
16
+ extraErrorCodes?: readonly string[];
17
+ label?: RetryPolicyLabel;
18
+ }): NormalizedProxyTransportRetryOptions;
19
+ export declare function normalizeProxyTransportRetryOptions(retry: RequestOptions["retry"], options?: {
20
+ extraErrorCodes?: readonly string[];
21
+ label?: RetryPolicyLabel;
22
+ }): NormalizedProxyTransportRetryOptions | undefined;
23
+ export declare function validateUnsafeProxyTransportRetryMethods(options: NormalizedProxyTransportRetryOptions, label?: RetryPolicyLabel): void;
24
+ export declare function isProxyTransportRetryMethod(method: HttpMethod | string, options: NormalizedProxyTransportRetryOptions): boolean;
25
+ export declare function shouldRetryProxyTransportError(error: unknown, options: NormalizedProxyTransportRetryOptions): boolean;
26
+ export declare function shouldRetryProxyTransportAttempt(input: {
27
+ error: unknown;
28
+ explicitRetry: boolean;
29
+ method: HttpMethod | string;
30
+ options: NormalizedProxyTransportRetryOptions | undefined;
31
+ proxyUsed: boolean;
32
+ }): boolean;
33
+ export declare function computeProxyTransportRetryDelayMs(options: NormalizedProxyTransportRetryOptions, attemptIndex: number, headers?: Record<string, string>): number;
34
+ export declare function normalizeProxyAttemptIndex(value: number | undefined): number;
35
+ export declare function computeProxyAttemptIndex(options: {
36
+ baseProxyAttempt?: number;
37
+ proxyAttemptOffset?: number;
38
+ retryAttemptOffset?: number;
39
+ }): number;
40
+ export {};