@http-client-toolkit/core 0.0.1

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/lib/index.js ADDED
@@ -0,0 +1,604 @@
1
+ import axios from 'axios';
2
+ import { z } from 'zod';
3
+ import { createHash } from 'crypto';
4
+
5
+ var __async = (__this, __arguments, generator) => {
6
+ return new Promise((resolve, reject) => {
7
+ var fulfilled = (value) => {
8
+ try {
9
+ step(generator.next(value));
10
+ } catch (e) {
11
+ reject(e);
12
+ }
13
+ };
14
+ var rejected = (value) => {
15
+ try {
16
+ step(generator.throw(value));
17
+ } catch (e) {
18
+ reject(e);
19
+ }
20
+ };
21
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
22
+ step((generator = generator.apply(__this, __arguments)).next());
23
+ });
24
+ };
25
+
26
+ // src/errors/http-client-error.ts
27
+ var HttpClientError = class extends Error {
28
+ constructor(message, statusCode) {
29
+ super(message);
30
+ this.name = "HttpClientError";
31
+ this.statusCode = statusCode;
32
+ Object.setPrototypeOf(this, new.target.prototype);
33
+ }
34
+ };
35
+ var AdaptiveConfigSchema = z.object({
36
+ monitoringWindowMs: z.number().positive().default(15 * 60 * 1e3),
37
+ // 15 minutes
38
+ highActivityThreshold: z.number().min(0).default(10),
39
+ // requests per window
40
+ moderateActivityThreshold: z.number().min(0).default(3),
41
+ recalculationIntervalMs: z.number().positive().default(3e4),
42
+ // 30 seconds
43
+ sustainedInactivityThresholdMs: z.number().positive().default(30 * 60 * 1e3),
44
+ // 30 minutes
45
+ backgroundPauseOnIncreasingTrend: z.boolean().default(true),
46
+ maxUserScaling: z.number().positive().default(2),
47
+ // don't exceed 2x capacity
48
+ minUserReserved: z.number().min(0).default(5)
49
+ // requests minimum
50
+ }).refine(
51
+ (data) => {
52
+ return data.moderateActivityThreshold < data.highActivityThreshold;
53
+ },
54
+ {
55
+ message: "moderateActivityThreshold must be less than highActivityThreshold"
56
+ }
57
+ );
58
+ function hashRequest(endpoint, params = {}) {
59
+ const requestString = JSON.stringify({
60
+ endpoint,
61
+ params: sortObject(params)
62
+ });
63
+ return createHash("sha256").update(requestString).digest("hex");
64
+ }
65
+ function sortObject(obj) {
66
+ if (obj === null) {
67
+ return null;
68
+ }
69
+ const objType = typeof obj;
70
+ if (objType === "undefined" || objType === "string") {
71
+ return obj;
72
+ }
73
+ if (objType === "number" || objType === "boolean") {
74
+ return String(obj);
75
+ }
76
+ if (Array.isArray(obj)) {
77
+ return obj.map(sortObject);
78
+ }
79
+ const sorted = {};
80
+ const keys = Object.keys(obj).sort();
81
+ for (const key of keys) {
82
+ const value = obj[key];
83
+ const normalisedValue = sortObject(value);
84
+ if (normalisedValue !== void 0) {
85
+ sorted[key] = normalisedValue;
86
+ }
87
+ }
88
+ return sorted;
89
+ }
90
+
91
+ // src/stores/rate-limit-config.ts
92
+ var DEFAULT_RATE_LIMIT = {
93
+ limit: 60,
94
+ windowMs: 6e4
95
+ };
96
+
97
+ // src/stores/adaptive-capacity-calculator.ts
98
+ var AdaptiveCapacityCalculator = class {
99
+ constructor(config = {}) {
100
+ this.config = AdaptiveConfigSchema.parse(config);
101
+ }
102
+ calculateDynamicCapacity(resource, totalLimit, activityMetrics) {
103
+ const recentUserActivity = this.getRecentActivity(
104
+ activityMetrics.recentUserRequests
105
+ );
106
+ const activityTrend = this.calculateActivityTrend(
107
+ activityMetrics.recentUserRequests
108
+ );
109
+ if (recentUserActivity >= this.config.highActivityThreshold) {
110
+ const userCapacity = Math.min(
111
+ totalLimit * 0.9,
112
+ Math.floor(totalLimit * 0.5 * this.config.maxUserScaling)
113
+ // 50% base * scaling factor
114
+ );
115
+ return {
116
+ userReserved: userCapacity,
117
+ backgroundMax: totalLimit - userCapacity,
118
+ backgroundPaused: this.config.backgroundPauseOnIncreasingTrend && activityTrend === "increasing",
119
+ reason: `High user activity (${recentUserActivity} requests/${this.config.monitoringWindowMs / 6e4}min) - prioritizing users`
120
+ };
121
+ }
122
+ if (recentUserActivity >= this.config.moderateActivityThreshold) {
123
+ const userMultiplier = this.getUserMultiplier(
124
+ recentUserActivity,
125
+ activityTrend
126
+ );
127
+ const baseUserCapacity2 = Math.floor(totalLimit * 0.4);
128
+ const dynamicUserCapacity = Math.min(
129
+ totalLimit * 0.7,
130
+ baseUserCapacity2 * userMultiplier
131
+ );
132
+ return {
133
+ userReserved: dynamicUserCapacity,
134
+ backgroundMax: totalLimit - dynamicUserCapacity,
135
+ backgroundPaused: false,
136
+ reason: `Moderate user activity - dynamic scaling (${userMultiplier.toFixed(1)}x user capacity)`
137
+ };
138
+ }
139
+ if (recentUserActivity === 0) {
140
+ if (activityMetrics.recentUserRequests.length === 0 && activityMetrics.recentBackgroundRequests.length === 0) {
141
+ const baseUserCapacity2 = Math.floor(totalLimit * 0.3);
142
+ return {
143
+ userReserved: Math.max(baseUserCapacity2, this.config.minUserReserved),
144
+ backgroundMax: totalLimit - Math.max(baseUserCapacity2, this.config.minUserReserved),
145
+ backgroundPaused: false,
146
+ reason: "Initial state - default capacity allocation"
147
+ };
148
+ }
149
+ if (activityMetrics.recentUserRequests.length === 0) {
150
+ return {
151
+ userReserved: this.config.minUserReserved,
152
+ // Minimal safety buffer
153
+ backgroundMax: totalLimit - this.config.minUserReserved,
154
+ backgroundPaused: false,
155
+ reason: "No user activity yet - background scale up with minimal user buffer"
156
+ };
157
+ }
158
+ const sustainedInactivity = this.getSustainedInactivityPeriod(
159
+ activityMetrics.recentUserRequests
160
+ );
161
+ if (sustainedInactivity > this.config.sustainedInactivityThresholdMs) {
162
+ return {
163
+ userReserved: 0,
164
+ // No reservation - background gets everything!
165
+ backgroundMax: totalLimit,
166
+ // Full capacity available
167
+ backgroundPaused: false,
168
+ reason: `Sustained zero activity (${Math.floor(sustainedInactivity / 6e4)}+ min) - full capacity to background`
169
+ };
170
+ } else {
171
+ return {
172
+ userReserved: this.config.minUserReserved,
173
+ // Minimal safety buffer
174
+ backgroundMax: totalLimit - this.config.minUserReserved,
175
+ backgroundPaused: false,
176
+ reason: "Recent zero activity - background scale up with minimal user buffer"
177
+ };
178
+ }
179
+ }
180
+ const baseUserCapacity = Math.floor(totalLimit * 0.3);
181
+ return {
182
+ userReserved: Math.max(baseUserCapacity, this.config.minUserReserved),
183
+ backgroundMax: totalLimit - Math.max(baseUserCapacity, this.config.minUserReserved),
184
+ backgroundPaused: false,
185
+ reason: `Low user activity (${recentUserActivity} requests/${this.config.monitoringWindowMs / 6e4}min) - background scale up`
186
+ };
187
+ }
188
+ getRecentActivity(requests) {
189
+ const cutoff = Date.now() - this.config.monitoringWindowMs;
190
+ return requests.filter((timestamp) => timestamp > cutoff).length;
191
+ }
192
+ calculateActivityTrend(requests) {
193
+ const now = Date.now();
194
+ const windowSize = this.config.monitoringWindowMs / 3;
195
+ const recent = requests.filter((t) => t > now - windowSize).length;
196
+ const previous = requests.filter(
197
+ (t) => t > now - 2 * windowSize && t <= now - windowSize
198
+ ).length;
199
+ if (recent === 0 && previous === 0) return "none";
200
+ if (recent > previous * 1.5) return "increasing";
201
+ if (recent < previous * 0.5) return "decreasing";
202
+ return "stable";
203
+ }
204
+ getUserMultiplier(activity, trend) {
205
+ let base = Math.min(
206
+ this.config.maxUserScaling,
207
+ 1 + activity / this.config.highActivityThreshold
208
+ );
209
+ if (trend === "increasing") base *= 1.2;
210
+ if (trend === "decreasing") base *= 0.8;
211
+ return Math.max(1, base);
212
+ }
213
+ getSustainedInactivityPeriod(requests) {
214
+ if (requests.length === 0) {
215
+ return 0;
216
+ }
217
+ const lastRequest = Math.max(...requests);
218
+ return Date.now() - lastRequest;
219
+ }
220
+ };
221
+
222
+ // src/http-client/http-client.ts
223
+ var DEFAULT_RATE_LIMIT_HEADER_NAMES = {
224
+ retryAfter: ["retry-after"],
225
+ limit: ["ratelimit-limit", "x-ratelimit-limit", "rate-limit-limit"],
226
+ remaining: [
227
+ "ratelimit-remaining",
228
+ "x-ratelimit-remaining",
229
+ "rate-limit-remaining"
230
+ ],
231
+ reset: ["ratelimit-reset", "x-ratelimit-reset", "rate-limit-reset"],
232
+ combined: ["ratelimit"]
233
+ };
234
+ function wait(ms, signal) {
235
+ return new Promise((resolve, reject) => {
236
+ const timer = setTimeout(() => {
237
+ if (signal) {
238
+ signal.removeEventListener("abort", onAbort);
239
+ }
240
+ resolve();
241
+ }, ms);
242
+ function onAbort() {
243
+ clearTimeout(timer);
244
+ const err = new Error("Aborted");
245
+ err.name = "AbortError";
246
+ reject(err);
247
+ }
248
+ if (signal) {
249
+ if (signal.aborted) {
250
+ onAbort();
251
+ } else {
252
+ signal.addEventListener("abort", onAbort, { once: true });
253
+ }
254
+ }
255
+ });
256
+ }
257
+ var HttpClient = class {
258
+ constructor(stores = {}, options = {}) {
259
+ this.serverCooldowns = /* @__PURE__ */ new Map();
260
+ var _a, _b, _c;
261
+ this._http = axios.create();
262
+ this.stores = stores;
263
+ this.options = {
264
+ defaultCacheTTL: (_a = options.defaultCacheTTL) != null ? _a : 3600,
265
+ throwOnRateLimit: (_b = options.throwOnRateLimit) != null ? _b : true,
266
+ maxWaitTime: (_c = options.maxWaitTime) != null ? _c : 6e4,
267
+ responseTransformer: options.responseTransformer,
268
+ errorHandler: options.errorHandler,
269
+ responseHandler: options.responseHandler,
270
+ rateLimitHeaders: this.normalizeRateLimitHeaders(
271
+ options.rateLimitHeaders
272
+ )
273
+ };
274
+ }
275
+ normalizeRateLimitHeaders(customHeaders) {
276
+ return {
277
+ retryAfter: this.normalizeHeaderNames(
278
+ customHeaders == null ? void 0 : customHeaders.retryAfter,
279
+ DEFAULT_RATE_LIMIT_HEADER_NAMES.retryAfter
280
+ ),
281
+ limit: this.normalizeHeaderNames(
282
+ customHeaders == null ? void 0 : customHeaders.limit,
283
+ DEFAULT_RATE_LIMIT_HEADER_NAMES.limit
284
+ ),
285
+ remaining: this.normalizeHeaderNames(
286
+ customHeaders == null ? void 0 : customHeaders.remaining,
287
+ DEFAULT_RATE_LIMIT_HEADER_NAMES.remaining
288
+ ),
289
+ reset: this.normalizeHeaderNames(
290
+ customHeaders == null ? void 0 : customHeaders.reset,
291
+ DEFAULT_RATE_LIMIT_HEADER_NAMES.reset
292
+ ),
293
+ combined: this.normalizeHeaderNames(
294
+ customHeaders == null ? void 0 : customHeaders.combined,
295
+ DEFAULT_RATE_LIMIT_HEADER_NAMES.combined
296
+ )
297
+ };
298
+ }
299
+ normalizeHeaderNames(providedNames, defaultNames) {
300
+ if (!providedNames || providedNames.length === 0) {
301
+ return [...defaultNames];
302
+ }
303
+ const customNames = providedNames.map((name) => name.trim().toLowerCase()).filter(Boolean);
304
+ if (customNames.length === 0) {
305
+ return [...defaultNames];
306
+ }
307
+ return [.../* @__PURE__ */ new Set([...customNames, ...defaultNames])];
308
+ }
309
+ /**
310
+ * Infer the resource name from the endpoint URL
311
+ * @param url The full URL or endpoint path
312
+ * @returns The resource name for rate limiting
313
+ */
314
+ inferResource(url) {
315
+ try {
316
+ const urlObj = new URL(url);
317
+ const segments = urlObj.pathname.split("/").filter(Boolean);
318
+ return segments[segments.length - 1] || "unknown";
319
+ } catch (e) {
320
+ return "unknown";
321
+ }
322
+ }
323
+ /**
324
+ * Extract endpoint and params from URL for request hashing
325
+ * @param url The full URL
326
+ * @returns Object with endpoint and params for hashing
327
+ */
328
+ parseUrlForHashing(url) {
329
+ const urlObj = new URL(url);
330
+ const endpoint = `${urlObj.origin}${urlObj.pathname}`;
331
+ const params = {};
332
+ urlObj.searchParams.forEach((value, key) => {
333
+ const existing = params[key];
334
+ if (existing === void 0) {
335
+ params[key] = value;
336
+ return;
337
+ }
338
+ if (Array.isArray(existing)) {
339
+ existing.push(value);
340
+ return;
341
+ }
342
+ params[key] = [existing, value];
343
+ });
344
+ return { endpoint, params };
345
+ }
346
+ getOriginScope(url) {
347
+ try {
348
+ return new URL(url).origin;
349
+ } catch (e) {
350
+ return "unknown";
351
+ }
352
+ }
353
+ getHeaderValue(headers, names) {
354
+ var _a;
355
+ if (!headers) {
356
+ return void 0;
357
+ }
358
+ for (const rawName of names) {
359
+ const name = rawName.toLowerCase();
360
+ const value = (_a = headers[name]) != null ? _a : headers[rawName];
361
+ if (typeof value === "string") {
362
+ return value;
363
+ }
364
+ if (Array.isArray(value) && value.length > 0) {
365
+ const first = value.find((entry) => typeof entry === "string");
366
+ if (typeof first === "string") {
367
+ return first;
368
+ }
369
+ }
370
+ }
371
+ return void 0;
372
+ }
373
+ parseIntegerHeader(value) {
374
+ if (!value) {
375
+ return void 0;
376
+ }
377
+ const parsed = Number.parseInt(value.trim(), 10);
378
+ if (!Number.isFinite(parsed) || parsed < 0) {
379
+ return void 0;
380
+ }
381
+ return parsed;
382
+ }
383
+ parseRetryAfterMs(value) {
384
+ if (!value) {
385
+ return void 0;
386
+ }
387
+ const numeric = Number.parseInt(value.trim(), 10);
388
+ if (Number.isFinite(numeric) && numeric >= 0) {
389
+ return numeric * 1e3;
390
+ }
391
+ const dateMs = Date.parse(value);
392
+ if (!Number.isFinite(dateMs)) {
393
+ return void 0;
394
+ }
395
+ return Math.max(0, dateMs - Date.now());
396
+ }
397
+ parseResetMs(value) {
398
+ const parsed = this.parseIntegerHeader(value);
399
+ if (parsed === void 0) {
400
+ return void 0;
401
+ }
402
+ if (parsed === 0) {
403
+ return 0;
404
+ }
405
+ const nowSeconds = Math.floor(Date.now() / 1e3);
406
+ if (parsed > nowSeconds + 1) {
407
+ return Math.max(0, (parsed - nowSeconds) * 1e3);
408
+ }
409
+ return parsed * 1e3;
410
+ }
411
+ parseCombinedRateLimitHeader(value) {
412
+ if (!value) {
413
+ return {};
414
+ }
415
+ const remainingMatch = value.match(/(?:^|[;,])\s*r\s*=\s*(\d+)/i);
416
+ const resetMatch = value.match(/(?:^|[;,])\s*t\s*=\s*(\d+)/i);
417
+ return {
418
+ remaining: remainingMatch ? this.parseIntegerHeader(remainingMatch[1]) : void 0,
419
+ resetMs: resetMatch ? this.parseResetMs(resetMatch[1]) : void 0
420
+ };
421
+ }
422
+ applyServerRateLimitHints(url, headers, statusCode) {
423
+ if (!headers) {
424
+ return;
425
+ }
426
+ const config = this.options.rateLimitHeaders;
427
+ const retryAfterRaw = this.getHeaderValue(headers, config.retryAfter);
428
+ const resetRaw = this.getHeaderValue(headers, config.reset);
429
+ const remainingRaw = this.getHeaderValue(headers, config.remaining);
430
+ const combinedRaw = this.getHeaderValue(headers, config.combined);
431
+ const retryAfterMs = this.parseRetryAfterMs(retryAfterRaw);
432
+ const resetMs = this.parseResetMs(resetRaw);
433
+ const remaining = this.parseIntegerHeader(remainingRaw);
434
+ const combined = this.parseCombinedRateLimitHeader(combinedRaw);
435
+ const effectiveRemaining = remaining != null ? remaining : combined.remaining;
436
+ const effectiveResetMs = resetMs != null ? resetMs : combined.resetMs;
437
+ const hasRateLimitErrorStatus = statusCode === 429 || statusCode === 503;
438
+ let waitMs;
439
+ if (retryAfterMs !== void 0) {
440
+ waitMs = retryAfterMs;
441
+ } else if (effectiveResetMs !== void 0 && (hasRateLimitErrorStatus || effectiveRemaining !== void 0 && effectiveRemaining <= 0)) {
442
+ waitMs = effectiveResetMs;
443
+ }
444
+ if (waitMs === void 0 || waitMs <= 0) {
445
+ return;
446
+ }
447
+ const scope = this.getOriginScope(url);
448
+ this.serverCooldowns.set(scope, Date.now() + waitMs);
449
+ }
450
+ enforceServerCooldown(url, signal) {
451
+ return __async(this, null, function* () {
452
+ const scope = this.getOriginScope(url);
453
+ const startedAt = Date.now();
454
+ while (true) {
455
+ const cooldownUntil = this.serverCooldowns.get(scope);
456
+ if (!cooldownUntil) {
457
+ return;
458
+ }
459
+ const waitMs = cooldownUntil - Date.now();
460
+ if (waitMs <= 0) {
461
+ this.serverCooldowns.delete(scope);
462
+ return;
463
+ }
464
+ if (this.options.throwOnRateLimit) {
465
+ throw new Error(
466
+ `Rate limit exceeded for origin '${scope}'. Wait ${waitMs}ms before retrying.`
467
+ );
468
+ }
469
+ const elapsedMs = Date.now() - startedAt;
470
+ const remainingWaitBudgetMs = this.options.maxWaitTime - elapsedMs;
471
+ if (remainingWaitBudgetMs <= 0) {
472
+ throw new Error(
473
+ `Rate limit wait exceeded maxWaitTime (${this.options.maxWaitTime}ms) for origin '${scope}'.`
474
+ );
475
+ }
476
+ yield wait(Math.min(waitMs, remainingWaitBudgetMs), signal);
477
+ }
478
+ });
479
+ }
480
+ enforceStoreRateLimit(resource, priority, signal) {
481
+ return __async(this, null, function* () {
482
+ const rateLimit = this.stores.rateLimit;
483
+ const startedAt = Date.now();
484
+ if (this.options.throwOnRateLimit) {
485
+ const canProceed = yield rateLimit.canProceed(resource, priority);
486
+ if (!canProceed) {
487
+ const waitTime = yield rateLimit.getWaitTime(resource, priority);
488
+ throw new Error(
489
+ `Rate limit exceeded for resource '${resource}'. Wait ${waitTime}ms before retrying.`
490
+ );
491
+ }
492
+ return;
493
+ }
494
+ while (!(yield rateLimit.canProceed(resource, priority))) {
495
+ const suggestedWaitMs = yield rateLimit.getWaitTime(resource, priority);
496
+ const elapsedMs = Date.now() - startedAt;
497
+ const remainingWaitBudgetMs = this.options.maxWaitTime - elapsedMs;
498
+ if (remainingWaitBudgetMs <= 0) {
499
+ throw new Error(
500
+ `Rate limit wait exceeded maxWaitTime (${this.options.maxWaitTime}ms) for resource '${resource}'.`
501
+ );
502
+ }
503
+ const waitTime = suggestedWaitMs > 0 ? Math.min(suggestedWaitMs, remainingWaitBudgetMs) : Math.min(25, remainingWaitBudgetMs);
504
+ yield wait(waitTime, signal);
505
+ }
506
+ });
507
+ }
508
+ generateClientError(err) {
509
+ var _a, _b, _c;
510
+ if (this.options.errorHandler) {
511
+ return this.options.errorHandler(err);
512
+ }
513
+ if (err instanceof HttpClientError) {
514
+ return err;
515
+ }
516
+ const error = err;
517
+ const statusCode = (_a = error.response) == null ? void 0 : _a.status;
518
+ const errorMessage = (_c = (_b = error.response) == null ? void 0 : _b.data) == null ? void 0 : _c.message;
519
+ const message = `${error.message}${errorMessage ? `, ${errorMessage}` : ""}`;
520
+ return new HttpClientError(message, statusCode);
521
+ }
522
+ get(_0) {
523
+ return __async(this, arguments, function* (url, options = {}) {
524
+ const { signal, priority = "background" } = options;
525
+ const { endpoint, params } = this.parseUrlForHashing(url);
526
+ const hash = hashRequest(endpoint, params);
527
+ const resource = this.inferResource(url);
528
+ try {
529
+ yield this.enforceServerCooldown(url, signal);
530
+ if (this.stores.cache) {
531
+ const cachedResult = yield this.stores.cache.get(hash);
532
+ if (cachedResult !== void 0) {
533
+ return cachedResult;
534
+ }
535
+ }
536
+ if (this.stores.dedupe) {
537
+ const existingResult = yield this.stores.dedupe.waitFor(hash);
538
+ if (existingResult !== void 0) {
539
+ return existingResult;
540
+ }
541
+ if (this.stores.dedupe.registerOrJoin) {
542
+ const registration = yield this.stores.dedupe.registerOrJoin(hash);
543
+ if (!registration.isOwner) {
544
+ const joinedResult = yield this.stores.dedupe.waitFor(hash);
545
+ if (joinedResult !== void 0) {
546
+ return joinedResult;
547
+ }
548
+ }
549
+ } else {
550
+ yield this.stores.dedupe.register(hash);
551
+ }
552
+ }
553
+ if (this.stores.rateLimit) {
554
+ yield this.enforceStoreRateLimit(resource, priority, signal);
555
+ }
556
+ const response = yield this._http.get(url, { signal });
557
+ this.applyServerRateLimitHints(
558
+ url,
559
+ response.headers,
560
+ response.status
561
+ );
562
+ let data = response.data;
563
+ if (this.options.responseTransformer && data) {
564
+ data = this.options.responseTransformer(data);
565
+ }
566
+ if (this.options.responseHandler) {
567
+ data = this.options.responseHandler(data);
568
+ }
569
+ const result = data;
570
+ if (this.stores.rateLimit) {
571
+ const rateLimit = this.stores.rateLimit;
572
+ yield rateLimit.record(resource, priority);
573
+ }
574
+ if (this.stores.cache) {
575
+ yield this.stores.cache.set(hash, result, this.options.defaultCacheTTL);
576
+ }
577
+ if (this.stores.dedupe) {
578
+ yield this.stores.dedupe.complete(hash, result);
579
+ }
580
+ return result;
581
+ } catch (error) {
582
+ const axiosError = error;
583
+ if (axiosError.response) {
584
+ this.applyServerRateLimitHints(
585
+ url,
586
+ axiosError.response.headers,
587
+ axiosError.response.status
588
+ );
589
+ }
590
+ if (this.stores.dedupe) {
591
+ yield this.stores.dedupe.fail(hash, error);
592
+ }
593
+ if (error instanceof Error && error.name === "AbortError") {
594
+ throw error;
595
+ }
596
+ throw this.generateClientError(error);
597
+ }
598
+ });
599
+ }
600
+ };
601
+
602
+ export { AdaptiveCapacityCalculator, AdaptiveConfigSchema, DEFAULT_RATE_LIMIT, HttpClient, HttpClientError, hashRequest };
603
+ //# sourceMappingURL=index.js.map
604
+ //# sourceMappingURL=index.js.map