@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/LICENSE +15 -0
- package/README.md +160 -0
- package/lib/index.cjs +615 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.cts +382 -0
- package/lib/index.d.ts +382 -0
- package/lib/index.js +604 -0
- package/lib/index.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors/http-client-error.ts","../src/stores/rate-limit-store.ts","../src/stores/request-hasher.ts","../src/stores/rate-limit-config.ts","../src/stores/adaptive-capacity-calculator.ts","../src/http-client/http-client.ts"],"names":["z","createHash","baseUserCapacity","axios"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Base error class for HTTP client errors.\n * Consumers can extend this for domain-specific error handling.\n */\nexport class HttpClientError extends Error {\n public readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message);\n this.name = 'HttpClientError';\n this.statusCode = statusCode;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","import { z } from 'zod';\n\n/**\n * Priority level for API requests\n */\nexport type RequestPriority = 'user' | 'background';\n\n/**\n * Adaptive configuration schema with validation and defaults\n */\nexport const AdaptiveConfigSchema = z\n .object({\n monitoringWindowMs: z\n .number()\n .positive()\n .default(15 * 60 * 1000), // 15 minutes\n highActivityThreshold: z.number().min(0).default(10), // requests per window\n moderateActivityThreshold: z.number().min(0).default(3),\n recalculationIntervalMs: z.number().positive().default(30000), // 30 seconds\n sustainedInactivityThresholdMs: z\n .number()\n .positive()\n .default(30 * 60 * 1000), // 30 minutes\n backgroundPauseOnIncreasingTrend: z.boolean().default(true),\n maxUserScaling: z.number().positive().default(2.0), // don't exceed 2x capacity\n minUserReserved: z.number().min(0).default(5), // requests minimum\n })\n .refine(\n (data) => {\n return data.moderateActivityThreshold < data.highActivityThreshold;\n },\n {\n message:\n 'moderateActivityThreshold must be less than highActivityThreshold',\n },\n );\n\n/**\n * Configuration for adaptive rate limiting\n */\nexport type AdaptiveConfig = z.infer<typeof AdaptiveConfigSchema>;\n\n/**\n * Interface for rate limiting API requests per resource\n */\nexport interface RateLimitStore {\n /**\n * Check if a request to a resource can proceed based on rate limits\n * @param resource The resource name (e.g., 'issues', 'characters')\n * @returns True if the request can proceed, false if rate limited\n */\n canProceed(resource: string): Promise<boolean>;\n\n /**\n * Record a request to a resource for rate limiting tracking\n * @param resource The resource name (e.g., 'issues', 'characters')\n */\n record(resource: string): Promise<void>;\n\n /**\n * Get the current rate limit status for a resource\n * @param resource The resource name\n * @returns Rate limit information including remaining requests and reset time\n */\n getStatus(resource: string): Promise<{\n remaining: number;\n resetTime: Date;\n limit: number;\n }>;\n\n /**\n * Reset rate limits for a resource (useful for testing)\n * @param resource The resource name\n */\n reset(resource: string): Promise<void>;\n\n /**\n * Get the time in milliseconds until the next request can be made\n * @param resource The resource name\n * @returns Milliseconds to wait, or 0 if no waiting is needed\n */\n getWaitTime(resource: string): Promise<number>;\n}\n\n/**\n * Enhanced interface for adaptive rate limiting stores with priority support\n */\nexport interface AdaptiveRateLimitStore extends RateLimitStore {\n /**\n * Check if a request to a resource can proceed based on rate limits\n * @param resource The resource name (e.g., 'issues', 'characters')\n * @param priority The priority level of the request (defaults to 'background')\n * @returns True if the request can proceed, false if rate limited\n */\n canProceed(resource: string, priority?: RequestPriority): Promise<boolean>;\n\n /**\n * Record a request to a resource for rate limiting tracking\n * @param resource The resource name (e.g., 'issues', 'characters')\n * @param priority The priority level of the request (defaults to 'background')\n */\n record(resource: string, priority?: RequestPriority): Promise<void>;\n\n /**\n * Get the current rate limit status for a resource\n * @param resource The resource name\n * @returns Rate limit information including remaining requests and reset time\n */\n getStatus(resource: string): Promise<{\n remaining: number;\n resetTime: Date;\n limit: number;\n adaptive?: {\n userReserved: number;\n backgroundMax: number;\n backgroundPaused: boolean;\n recentUserActivity: number;\n reason: string;\n };\n }>;\n\n /**\n * Get the time in milliseconds until the next request can be made\n * @param resource The resource name\n * @param priority The priority level of the request (defaults to 'background')\n * @returns Milliseconds to wait, or 0 if no waiting is needed\n */\n getWaitTime(resource: string, priority?: RequestPriority): Promise<number>;\n}\n","import { createHash } from 'crypto';\n\n/**\n * Creates a consistent hash for API requests to use as cache/dedupe keys\n * @param endpoint The API endpoint\n * @param params The request parameters\n * @returns A SHA-256 hash of the request\n */\nexport function hashRequest(\n endpoint: string,\n params: Record<string, unknown> = {},\n): string {\n const requestString = JSON.stringify({\n endpoint,\n params: sortObject(params),\n });\n\n return createHash('sha256').update(requestString).digest('hex');\n}\n\n/**\n * Normalises and sorts an object for hashing purposes.\n *\n * The ComicVine API transmits all query parameters as strings. To avoid cache\n * misses caused by treating `10` and `'10'` as different values we normalise\n * primitive types (number and boolean) to their string representation **before**\n * sorting. `undefined` values are intentionally kept as `undefined` so that\n * they are dropped by `JSON.stringify`, maintaining the existing behaviour\n * where an omitted parameter and an `undefined` parameter produce the same\n * hash.\n */\nfunction sortObject(obj: unknown): unknown {\n // Handle primitives first\n if (obj === null) {\n return null;\n }\n\n const objType = typeof obj;\n\n if (objType === 'undefined' || objType === 'string') {\n return obj;\n }\n\n if (objType === 'number' || objType === 'boolean') {\n // Convert to string so that 10 and '10' (or true and 'true') hash equally\n return String(obj);\n }\n\n // Recursively process arrays\n if (Array.isArray(obj)) {\n return obj.map(sortObject);\n }\n\n // For objects – sort keys and recurse\n const sorted: Record<string, unknown> = {};\n const keys = Object.keys(obj as Record<string, unknown>).sort();\n\n for (const key of keys) {\n const value = (obj as Record<string, unknown>)[key];\n const normalisedValue = sortObject(value);\n\n // Skip keys whose value normalises to undefined so omitted & undefined match\n if (normalisedValue !== undefined) {\n sorted[key] = normalisedValue;\n }\n }\n\n return sorted;\n}\n","/**\n * Configuration for per-resource rate limiting.\n *\n * This interface is shared by all store implementations (e.g. in-memory,\n * SQLite) so that callers can use a single canonical type.\n */\nexport interface RateLimitConfig {\n /** Number of requests allowed per time window */\n limit: number;\n /** Duration of the window in milliseconds */\n windowMs: number;\n}\n\n/**\n * Default rate-limit window: 60 requests per minute.\n *\n * Store implementations can reference this to avoid duplicating magic numbers.\n */\nexport const DEFAULT_RATE_LIMIT: RateLimitConfig = {\n limit: 60,\n windowMs: 60_000,\n};\n","import { z } from 'zod';\nimport { AdaptiveConfigSchema } from './rate-limit-store.js';\n\ninterface ActivityMetrics {\n recentUserRequests: Array<number>;\n recentBackgroundRequests: Array<number>;\n userActivityTrend: 'increasing' | 'stable' | 'decreasing' | 'none';\n}\n\ninterface DynamicCapacityResult {\n userReserved: number;\n backgroundMax: number;\n backgroundPaused: boolean;\n reason: string;\n}\n\n/**\n * Calculates dynamic capacity allocation based on real-time user activity patterns\n */\nexport class AdaptiveCapacityCalculator {\n public readonly config: z.infer<typeof AdaptiveConfigSchema>;\n\n constructor(config: Partial<z.input<typeof AdaptiveConfigSchema>> = {}) {\n // Zod handles validation and applies defaults automatically\n this.config = AdaptiveConfigSchema.parse(config);\n }\n\n calculateDynamicCapacity(\n resource: string,\n totalLimit: number,\n activityMetrics: ActivityMetrics,\n ): DynamicCapacityResult {\n const recentUserActivity = this.getRecentActivity(\n activityMetrics.recentUserRequests,\n );\n const activityTrend = this.calculateActivityTrend(\n activityMetrics.recentUserRequests,\n );\n\n // Strategy 1: High Activity - Pause Background\n if (recentUserActivity >= this.config.highActivityThreshold) {\n const userCapacity = Math.min(\n totalLimit * 0.9,\n Math.floor(totalLimit * 0.5 * this.config.maxUserScaling), // 50% base * scaling factor\n );\n\n return {\n userReserved: userCapacity,\n backgroundMax: totalLimit - userCapacity,\n backgroundPaused:\n this.config.backgroundPauseOnIncreasingTrend &&\n activityTrend === 'increasing',\n reason: `High user activity (${recentUserActivity} requests/${this.config.monitoringWindowMs / 60000}min) - prioritizing users`,\n };\n }\n\n // Strategy 2: Moderate Activity - Balanced Scaling\n if (recentUserActivity >= this.config.moderateActivityThreshold) {\n const userMultiplier = this.getUserMultiplier(\n recentUserActivity,\n activityTrend,\n );\n const baseUserCapacity = Math.floor(totalLimit * 0.4); // 40% base allocation\n const dynamicUserCapacity = Math.min(\n totalLimit * 0.7,\n baseUserCapacity * userMultiplier,\n );\n\n return {\n userReserved: dynamicUserCapacity,\n backgroundMax: totalLimit - dynamicUserCapacity,\n backgroundPaused: false,\n reason: `Moderate user activity - dynamic scaling (${userMultiplier.toFixed(1)}x user capacity)`,\n };\n }\n\n // Strategy 3: Low/No Activity - Background Scale Up\n if (recentUserActivity === 0) {\n // If there have never been any requests at all (fresh start), use default capacity allocation\n if (\n activityMetrics.recentUserRequests.length === 0 &&\n activityMetrics.recentBackgroundRequests.length === 0\n ) {\n const baseUserCapacity = Math.floor(totalLimit * 0.3); // 30% base for initial state\n return {\n userReserved: Math.max(baseUserCapacity, this.config.minUserReserved),\n backgroundMax:\n totalLimit -\n Math.max(baseUserCapacity, this.config.minUserReserved),\n backgroundPaused: false,\n reason: 'Initial state - default capacity allocation',\n };\n }\n\n // If there have never been user requests (only background), use background scale up\n if (activityMetrics.recentUserRequests.length === 0) {\n return {\n userReserved: this.config.minUserReserved, // Minimal safety buffer\n backgroundMax: totalLimit - this.config.minUserReserved,\n backgroundPaused: false,\n reason:\n 'No user activity yet - background scale up with minimal user buffer',\n };\n }\n\n // There have been user requests before, check for sustained inactivity\n const sustainedInactivity = this.getSustainedInactivityPeriod(\n activityMetrics.recentUserRequests,\n );\n\n if (sustainedInactivity > this.config.sustainedInactivityThresholdMs) {\n return {\n userReserved: 0, // No reservation - background gets everything!\n backgroundMax: totalLimit, // Full capacity available\n backgroundPaused: false,\n reason: `Sustained zero activity (${Math.floor(sustainedInactivity / 60000)}+ min) - full capacity to background`,\n };\n } else {\n return {\n userReserved: this.config.minUserReserved, // Minimal safety buffer\n backgroundMax: totalLimit - this.config.minUserReserved,\n backgroundPaused: false,\n reason:\n 'Recent zero activity - background scale up with minimal user buffer',\n };\n }\n }\n\n // Strategy 4: Very Low Activity - Gradual Background Scale Up\n const baseUserCapacity = Math.floor(totalLimit * 0.3); // 30% base for very low activity\n return {\n userReserved: Math.max(baseUserCapacity, this.config.minUserReserved),\n backgroundMax:\n totalLimit - Math.max(baseUserCapacity, this.config.minUserReserved),\n backgroundPaused: false,\n reason: `Low user activity (${recentUserActivity} requests/${this.config.monitoringWindowMs / 60000}min) - background scale up`,\n };\n }\n\n getRecentActivity(requests: Array<number>): number {\n const cutoff = Date.now() - this.config.monitoringWindowMs;\n return requests.filter((timestamp) => timestamp > cutoff).length;\n }\n\n calculateActivityTrend(\n requests: Array<number>,\n ): 'increasing' | 'stable' | 'decreasing' | 'none' {\n const now = Date.now();\n const windowSize = this.config.monitoringWindowMs / 3; // Use 1/3 of monitoring window for trend\n const recent = requests.filter((t) => t > now - windowSize).length;\n const previous = requests.filter(\n (t) => t > now - 2 * windowSize && t <= now - windowSize,\n ).length;\n\n if (recent === 0 && previous === 0) return 'none';\n if (recent > previous * 1.5) return 'increasing';\n if (recent < previous * 0.5) return 'decreasing';\n return 'stable';\n }\n\n private getUserMultiplier(activity: number, trend: string): number {\n let base = Math.min(\n this.config.maxUserScaling,\n 1 + activity / this.config.highActivityThreshold,\n );\n\n // Adjust based on trend\n if (trend === 'increasing') base *= 1.2;\n if (trend === 'decreasing') base *= 0.8;\n\n return Math.max(1.0, base);\n }\n\n private getSustainedInactivityPeriod(requests: Array<number>): number {\n if (requests.length === 0) {\n // This should not be called when there are no requests (handled above)\n return 0;\n }\n\n const lastRequest = Math.max(...requests);\n return Date.now() - lastRequest;\n }\n}\n\n// Export types for use in other modules\nexport type { ActivityMetrics, DynamicCapacityResult };\n","import axios, { AxiosError } from 'axios';\nimport { HttpClientError } from '../errors/http-client-error.js';\nimport {\n CacheStore,\n DedupeStore,\n RateLimitStore,\n AdaptiveRateLimitStore,\n RequestPriority,\n hashRequest,\n} from '../stores/index.js';\nimport { HttpClientContract } from '../types/index.js';\n\nconst DEFAULT_RATE_LIMIT_HEADER_NAMES = {\n retryAfter: ['retry-after'],\n limit: ['ratelimit-limit', 'x-ratelimit-limit', 'rate-limit-limit'],\n remaining: [\n 'ratelimit-remaining',\n 'x-ratelimit-remaining',\n 'rate-limit-remaining',\n ],\n reset: ['ratelimit-reset', 'x-ratelimit-reset', 'rate-limit-reset'],\n combined: ['ratelimit'],\n} as const;\n\n/**\n * Wait for a specified period while supporting cancellation via AbortSignal.\n *\n * If the signal is aborted before the timeout completes the promise rejects\n * with an `Error` whose name is set to `AbortError`, mimicking DOMException in\n * browser environments without depending on it. This allows callers to use a\n * single `AbortController` for both the rate-limit wait *and* the subsequent\n * HTTP request.\n */\nfunction wait(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => {\n if (signal) {\n signal.removeEventListener('abort', onAbort);\n }\n resolve();\n }, ms);\n\n function onAbort() {\n clearTimeout(timer);\n const err = new Error('Aborted');\n err.name = 'AbortError';\n reject(err);\n }\n\n if (signal) {\n if (signal.aborted) {\n onAbort();\n } else {\n signal.addEventListener('abort', onAbort, { once: true });\n }\n }\n });\n}\n\nexport interface HttpClientStores {\n cache?: CacheStore;\n dedupe?: DedupeStore;\n rateLimit?: RateLimitStore | AdaptiveRateLimitStore;\n}\n\nexport interface HttpClientOptions {\n /**\n * Default cache TTL in seconds\n */\n defaultCacheTTL?: number;\n /**\n * Whether to throw errors on rate limit violations\n */\n throwOnRateLimit?: boolean;\n /**\n * Maximum time to wait for rate limit in milliseconds\n */\n maxWaitTime?: number;\n /**\n * Optional response transformer applied to the raw response data.\n * Use this for converting snake_case to camelCase, etc.\n */\n responseTransformer?: (data: unknown) => unknown;\n /**\n * Optional error handler to convert errors into domain-specific error types.\n * If not provided, a generic HttpClientError is thrown.\n */\n errorHandler?: (error: unknown) => Error;\n /**\n * Optional response validator/handler called after transformation.\n * Use this to inspect the response and throw domain-specific errors\n * based on response content (e.g., API-level error codes).\n */\n responseHandler?: (data: unknown) => unknown;\n /**\n * Configure rate-limit response header names for standards and custom APIs.\n */\n rateLimitHeaders?: {\n retryAfter?: Array<string>;\n limit?: Array<string>;\n remaining?: Array<string>;\n reset?: Array<string>;\n combined?: Array<string>;\n };\n}\n\ninterface RateLimitHeaderConfig {\n retryAfter: Array<string>;\n limit: Array<string>;\n remaining: Array<string>;\n reset: Array<string>;\n combined: Array<string>;\n}\n\nexport class HttpClient implements HttpClientContract {\n private _http;\n private stores: HttpClientStores;\n private serverCooldowns = new Map<string, number>();\n private options: Required<\n Pick<\n HttpClientOptions,\n 'defaultCacheTTL' | 'throwOnRateLimit' | 'maxWaitTime'\n >\n > &\n Pick<\n HttpClientOptions,\n 'responseTransformer' | 'errorHandler' | 'responseHandler'\n > & {\n rateLimitHeaders: RateLimitHeaderConfig;\n };\n\n constructor(stores: HttpClientStores = {}, options: HttpClientOptions = {}) {\n this._http = axios.create();\n this.stores = stores;\n this.options = {\n defaultCacheTTL: options.defaultCacheTTL ?? 3600,\n throwOnRateLimit: options.throwOnRateLimit ?? true,\n maxWaitTime: options.maxWaitTime ?? 60000,\n responseTransformer: options.responseTransformer,\n errorHandler: options.errorHandler,\n responseHandler: options.responseHandler,\n rateLimitHeaders: this.normalizeRateLimitHeaders(\n options.rateLimitHeaders,\n ),\n };\n }\n\n private normalizeRateLimitHeaders(\n customHeaders?: HttpClientOptions['rateLimitHeaders'],\n ): RateLimitHeaderConfig {\n return {\n retryAfter: this.normalizeHeaderNames(\n customHeaders?.retryAfter,\n DEFAULT_RATE_LIMIT_HEADER_NAMES.retryAfter,\n ),\n limit: this.normalizeHeaderNames(\n customHeaders?.limit,\n DEFAULT_RATE_LIMIT_HEADER_NAMES.limit,\n ),\n remaining: this.normalizeHeaderNames(\n customHeaders?.remaining,\n DEFAULT_RATE_LIMIT_HEADER_NAMES.remaining,\n ),\n reset: this.normalizeHeaderNames(\n customHeaders?.reset,\n DEFAULT_RATE_LIMIT_HEADER_NAMES.reset,\n ),\n combined: this.normalizeHeaderNames(\n customHeaders?.combined,\n DEFAULT_RATE_LIMIT_HEADER_NAMES.combined,\n ),\n };\n }\n\n private normalizeHeaderNames(\n providedNames: Array<string> | undefined,\n defaultNames: ReadonlyArray<string>,\n ): Array<string> {\n if (!providedNames || providedNames.length === 0) {\n return [...defaultNames];\n }\n\n const customNames = providedNames\n .map((name) => name.trim().toLowerCase())\n .filter(Boolean);\n\n if (customNames.length === 0) {\n return [...defaultNames];\n }\n\n return [...new Set([...customNames, ...defaultNames])];\n }\n\n /**\n * Infer the resource name from the endpoint URL\n * @param url The full URL or endpoint path\n * @returns The resource name for rate limiting\n */\n private inferResource(url: string): string {\n try {\n const urlObj = new URL(url);\n // Use the first meaningful path segment as the resource name\n const segments = urlObj.pathname.split('/').filter(Boolean);\n return segments[segments.length - 1] || 'unknown';\n } catch {\n return 'unknown';\n }\n }\n\n /**\n * Extract endpoint and params from URL for request hashing\n * @param url The full URL\n * @returns Object with endpoint and params for hashing\n */\n private parseUrlForHashing(url: string): {\n endpoint: string;\n params: Record<string, unknown>;\n } {\n const urlObj = new URL(url);\n const endpoint = `${urlObj.origin}${urlObj.pathname}`;\n const params: Record<string, unknown> = {};\n\n urlObj.searchParams.forEach((value, key) => {\n const existing = params[key];\n\n // Keep repeated query keys as arrays so semantically distinct URLs like\n // `?tag=a&tag=b` and `?tag=b` do not hash to the same cache/dedupe key.\n if (existing === undefined) {\n params[key] = value;\n return;\n }\n\n if (Array.isArray(existing)) {\n existing.push(value);\n return;\n }\n\n params[key] = [existing, value];\n });\n\n return { endpoint, params };\n }\n\n private getOriginScope(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n return 'unknown';\n }\n }\n\n private getHeaderValue(\n headers: Record<string, unknown> | undefined,\n names: Array<string>,\n ): string | undefined {\n if (!headers) {\n return undefined;\n }\n\n for (const rawName of names) {\n const name = rawName.toLowerCase();\n const value = headers[name] ?? headers[rawName];\n\n if (typeof value === 'string') {\n return value;\n }\n\n if (Array.isArray(value) && value.length > 0) {\n const first = value.find((entry) => typeof entry === 'string');\n if (typeof first === 'string') {\n return first;\n }\n }\n }\n\n return undefined;\n }\n\n private parseIntegerHeader(value: string | undefined): number | undefined {\n if (!value) {\n return undefined;\n }\n\n const parsed = Number.parseInt(value.trim(), 10);\n if (!Number.isFinite(parsed) || parsed < 0) {\n return undefined;\n }\n\n return parsed;\n }\n\n private parseRetryAfterMs(value: string | undefined): number | undefined {\n if (!value) {\n return undefined;\n }\n\n const numeric = Number.parseInt(value.trim(), 10);\n if (Number.isFinite(numeric) && numeric >= 0) {\n return numeric * 1000;\n }\n\n const dateMs = Date.parse(value);\n if (!Number.isFinite(dateMs)) {\n return undefined;\n }\n\n return Math.max(0, dateMs - Date.now());\n }\n\n private parseResetMs(value: string | undefined): number | undefined {\n const parsed = this.parseIntegerHeader(value);\n if (parsed === undefined) {\n return undefined;\n }\n\n if (parsed === 0) {\n return 0;\n }\n\n const nowSeconds = Math.floor(Date.now() / 1000);\n\n if (parsed > nowSeconds + 1) {\n return Math.max(0, (parsed - nowSeconds) * 1000);\n }\n\n return parsed * 1000;\n }\n\n private parseCombinedRateLimitHeader(value: string | undefined): {\n remaining?: number;\n resetMs?: number;\n } {\n if (!value) {\n return {};\n }\n\n const remainingMatch = value.match(/(?:^|[;,])\\s*r\\s*=\\s*(\\d+)/i);\n const resetMatch = value.match(/(?:^|[;,])\\s*t\\s*=\\s*(\\d+)/i);\n\n return {\n remaining: remainingMatch\n ? this.parseIntegerHeader(remainingMatch[1])\n : undefined,\n resetMs: resetMatch ? this.parseResetMs(resetMatch[1]) : undefined,\n };\n }\n\n private applyServerRateLimitHints(\n url: string,\n headers: Record<string, unknown> | undefined,\n statusCode?: number,\n ): void {\n if (!headers) {\n return;\n }\n\n const config = this.options.rateLimitHeaders;\n const retryAfterRaw = this.getHeaderValue(headers, config.retryAfter);\n const resetRaw = this.getHeaderValue(headers, config.reset);\n const remainingRaw = this.getHeaderValue(headers, config.remaining);\n const combinedRaw = this.getHeaderValue(headers, config.combined);\n\n const retryAfterMs = this.parseRetryAfterMs(retryAfterRaw);\n const resetMs = this.parseResetMs(resetRaw);\n const remaining = this.parseIntegerHeader(remainingRaw);\n const combined = this.parseCombinedRateLimitHeader(combinedRaw);\n\n const effectiveRemaining = remaining ?? combined.remaining;\n const effectiveResetMs = resetMs ?? combined.resetMs;\n const hasRateLimitErrorStatus = statusCode === 429 || statusCode === 503;\n\n let waitMs: number | undefined;\n\n if (retryAfterMs !== undefined) {\n waitMs = retryAfterMs;\n } else if (\n effectiveResetMs !== undefined &&\n (hasRateLimitErrorStatus ||\n (effectiveRemaining !== undefined && effectiveRemaining <= 0))\n ) {\n waitMs = effectiveResetMs;\n }\n\n if (waitMs === undefined || waitMs <= 0) {\n return;\n }\n\n const scope = this.getOriginScope(url);\n this.serverCooldowns.set(scope, Date.now() + waitMs);\n }\n\n private async enforceServerCooldown(\n url: string,\n signal?: AbortSignal,\n ): Promise<void> {\n const scope = this.getOriginScope(url);\n const startedAt = Date.now();\n\n // Re-check cooldown after each sleep so we never proceed while a server\n // cooldown is still active. This avoids bypassing limits when cooldown\n // duration is longer than maxWaitTime.\n while (true) {\n const cooldownUntil = this.serverCooldowns.get(scope);\n if (!cooldownUntil) {\n return;\n }\n\n const waitMs = cooldownUntil - Date.now();\n if (waitMs <= 0) {\n this.serverCooldowns.delete(scope);\n return;\n }\n\n if (this.options.throwOnRateLimit) {\n throw new Error(\n `Rate limit exceeded for origin '${scope}'. Wait ${waitMs}ms before retrying.`,\n );\n }\n\n const elapsedMs = Date.now() - startedAt;\n const remainingWaitBudgetMs = this.options.maxWaitTime - elapsedMs;\n\n if (remainingWaitBudgetMs <= 0) {\n throw new Error(\n `Rate limit wait exceeded maxWaitTime (${this.options.maxWaitTime}ms) for origin '${scope}'.`,\n );\n }\n\n await wait(Math.min(waitMs, remainingWaitBudgetMs), signal);\n }\n }\n\n private async enforceStoreRateLimit(\n resource: string,\n priority: RequestPriority,\n signal?: AbortSignal,\n ): Promise<void> {\n const rateLimit = this.stores.rateLimit as AdaptiveRateLimitStore;\n const startedAt = Date.now();\n\n if (this.options.throwOnRateLimit) {\n const canProceed = await rateLimit.canProceed(resource, priority);\n if (!canProceed) {\n const waitTime = await rateLimit.getWaitTime(resource, priority);\n throw new Error(\n `Rate limit exceeded for resource '${resource}'. Wait ${waitTime}ms before retrying.`,\n );\n }\n return;\n }\n\n // Keep polling + waiting until the store explicitly allows the request or\n // we exhaust maxWaitTime. A single one-off sleep can otherwise let a request\n // through while still over limit.\n while (!(await rateLimit.canProceed(resource, priority))) {\n const suggestedWaitMs = await rateLimit.getWaitTime(resource, priority);\n const elapsedMs = Date.now() - startedAt;\n const remainingWaitBudgetMs = this.options.maxWaitTime - elapsedMs;\n\n if (remainingWaitBudgetMs <= 0) {\n throw new Error(\n `Rate limit wait exceeded maxWaitTime (${this.options.maxWaitTime}ms) for resource '${resource}'.`,\n );\n }\n\n // If a store reports \"blocked\" but no wait time, use a tiny backoff to\n // avoid a tight CPU loop while still converging quickly.\n const waitTime =\n suggestedWaitMs > 0\n ? Math.min(suggestedWaitMs, remainingWaitBudgetMs)\n : Math.min(25, remainingWaitBudgetMs);\n\n await wait(waitTime, signal);\n }\n }\n\n private generateClientError(err: unknown): Error {\n // If a custom error handler is provided, use it\n if (this.options.errorHandler) {\n return this.options.errorHandler(err);\n }\n\n if (err instanceof HttpClientError) {\n return err;\n }\n\n const error = err as AxiosError<{ message?: string }>;\n const statusCode = error.response?.status;\n const errorMessage = error.response?.data?.message;\n const message = `${error.message}${errorMessage ? `, ${errorMessage}` : ''}`;\n\n return new HttpClientError(message, statusCode);\n }\n\n async get<Result>(\n url: string,\n options: { signal?: AbortSignal; priority?: RequestPriority } = {},\n ): Promise<Result> {\n const { signal, priority = 'background' } = options;\n const { endpoint, params } = this.parseUrlForHashing(url);\n const hash = hashRequest(endpoint, params);\n const resource = this.inferResource(url);\n\n try {\n await this.enforceServerCooldown(url, signal);\n\n // 1. Cache - check for cached response\n if (this.stores.cache) {\n const cachedResult = await this.stores.cache.get(hash);\n if (cachedResult !== undefined) {\n return cachedResult as Result;\n }\n }\n\n // 2. Deduplication - check for in-progress request\n if (this.stores.dedupe) {\n const existingResult = await this.stores.dedupe.waitFor(hash);\n if (existingResult !== undefined) {\n return existingResult as Result;\n }\n\n if (this.stores.dedupe.registerOrJoin) {\n const registration = await this.stores.dedupe.registerOrJoin(hash);\n\n if (!registration.isOwner) {\n const joinedResult = await this.stores.dedupe.waitFor(hash);\n if (joinedResult !== undefined) {\n return joinedResult as Result;\n }\n }\n } else {\n await this.stores.dedupe.register(hash);\n }\n }\n\n // 3. Rate limiting - check if request can proceed\n if (this.stores.rateLimit) {\n await this.enforceStoreRateLimit(resource, priority, signal);\n }\n\n // 4. Execute the actual HTTP request\n const response = await this._http.get(url, { signal });\n this.applyServerRateLimitHints(\n url,\n response.headers as Record<string, unknown>,\n response.status,\n );\n\n // 5. Apply response transformer if provided\n let data = response.data;\n if (this.options.responseTransformer && data) {\n data = this.options.responseTransformer(data);\n }\n\n // 6. Apply response handler if provided (for domain-specific validation)\n if (this.options.responseHandler) {\n data = this.options.responseHandler(data);\n }\n\n const result = data as Result;\n\n // 7. Record the request for rate limiting\n if (this.stores.rateLimit) {\n const rateLimit = this.stores.rateLimit as AdaptiveRateLimitStore;\n await rateLimit.record(resource, priority);\n }\n\n // 8. Cache the result\n if (this.stores.cache) {\n await this.stores.cache.set(hash, result, this.options.defaultCacheTTL);\n }\n\n // 9. Mark deduplication as complete\n if (this.stores.dedupe) {\n await this.stores.dedupe.complete(hash, result);\n }\n\n return result;\n } catch (error) {\n const axiosError = error as AxiosError;\n if (axiosError.response) {\n this.applyServerRateLimitHints(\n url,\n axiosError.response.headers as Record<string, unknown>,\n axiosError.response.status,\n );\n }\n\n // Mark deduplication as failed\n if (this.stores.dedupe) {\n await this.stores.dedupe.fail(hash, error as Error);\n }\n\n // Allow callers to detect aborts distinctly – do not wrap AbortError.\n if (error instanceof Error && error.name === 'AbortError') {\n throw error;\n }\n\n throw this.generateClientError(error);\n }\n }\n}\n"]}
|
package/lib/index.d.cts
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Interface for caching API responses with TTL support
|
|
5
|
+
*/
|
|
6
|
+
interface CacheStore<T = unknown> {
|
|
7
|
+
/**
|
|
8
|
+
* Retrieve a cached value by hash key
|
|
9
|
+
* @param hash The hash key of the cached item
|
|
10
|
+
* @returns The cached value or undefined if not found or expired
|
|
11
|
+
*/
|
|
12
|
+
get(hash: string): Promise<T | undefined>;
|
|
13
|
+
/**
|
|
14
|
+
* Store a value in the cache with a TTL
|
|
15
|
+
* @param hash The hash key for the cached item
|
|
16
|
+
* @param value The value to cache
|
|
17
|
+
* @param ttlSeconds TTL in seconds after which the item expires
|
|
18
|
+
*/
|
|
19
|
+
set(hash: string, value: T, ttlSeconds: number): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Remove a cached item by hash key
|
|
22
|
+
* @param hash The hash key of the cached item
|
|
23
|
+
*/
|
|
24
|
+
delete(hash: string): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Clear all cached items
|
|
27
|
+
*/
|
|
28
|
+
clear(): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Interface for deduplicating concurrent API requests
|
|
33
|
+
*/
|
|
34
|
+
interface DedupeStore<T = unknown> {
|
|
35
|
+
/**
|
|
36
|
+
* Wait for the result of an existing request if one is in progress
|
|
37
|
+
* @param hash The hash key of the request
|
|
38
|
+
* @returns The result if found, otherwise undefined
|
|
39
|
+
*/
|
|
40
|
+
waitFor(hash: string): Promise<T | undefined>;
|
|
41
|
+
/**
|
|
42
|
+
* Register a new request and get a job ID
|
|
43
|
+
* @param hash The hash key of the request
|
|
44
|
+
* @returns A unique job ID for this request
|
|
45
|
+
*/
|
|
46
|
+
register(hash: string): Promise<string>;
|
|
47
|
+
/**
|
|
48
|
+
* Atomically register or join an in-flight request.
|
|
49
|
+
*
|
|
50
|
+
* When provided, this allows callers to determine ownership and guarantees
|
|
51
|
+
* that only one caller executes the upstream request while others wait.
|
|
52
|
+
* Implementations that do not provide this method remain compatible, but
|
|
53
|
+
* may allow duplicate upstream requests under extreme races.
|
|
54
|
+
*
|
|
55
|
+
* @param hash The hash key of the request
|
|
56
|
+
* @returns The job id and whether the caller owns execution
|
|
57
|
+
*/
|
|
58
|
+
registerOrJoin?(hash: string): Promise<{
|
|
59
|
+
jobId: string;
|
|
60
|
+
isOwner: boolean;
|
|
61
|
+
}>;
|
|
62
|
+
/**
|
|
63
|
+
* Mark a request as complete with its result
|
|
64
|
+
* @param hash The hash key of the request
|
|
65
|
+
* @param value The result of the request
|
|
66
|
+
*/
|
|
67
|
+
complete(hash: string, value: T): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Mark a request as failed with an error
|
|
70
|
+
* @param hash The hash key of the request
|
|
71
|
+
* @param error The error that occurred
|
|
72
|
+
*/
|
|
73
|
+
fail(hash: string, error: Error): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Check if a request is currently in progress
|
|
76
|
+
* @param hash The hash key of the request
|
|
77
|
+
* @returns True if the request is in progress
|
|
78
|
+
*/
|
|
79
|
+
isInProgress(hash: string): Promise<boolean>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Priority level for API requests
|
|
84
|
+
*/
|
|
85
|
+
type RequestPriority = 'user' | 'background';
|
|
86
|
+
/**
|
|
87
|
+
* Adaptive configuration schema with validation and defaults
|
|
88
|
+
*/
|
|
89
|
+
declare const AdaptiveConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
90
|
+
monitoringWindowMs: z.ZodDefault<z.ZodNumber>;
|
|
91
|
+
highActivityThreshold: z.ZodDefault<z.ZodNumber>;
|
|
92
|
+
moderateActivityThreshold: z.ZodDefault<z.ZodNumber>;
|
|
93
|
+
recalculationIntervalMs: z.ZodDefault<z.ZodNumber>;
|
|
94
|
+
sustainedInactivityThresholdMs: z.ZodDefault<z.ZodNumber>;
|
|
95
|
+
backgroundPauseOnIncreasingTrend: z.ZodDefault<z.ZodBoolean>;
|
|
96
|
+
maxUserScaling: z.ZodDefault<z.ZodNumber>;
|
|
97
|
+
minUserReserved: z.ZodDefault<z.ZodNumber>;
|
|
98
|
+
}, "strip", z.ZodTypeAny, {
|
|
99
|
+
monitoringWindowMs: number;
|
|
100
|
+
highActivityThreshold: number;
|
|
101
|
+
moderateActivityThreshold: number;
|
|
102
|
+
recalculationIntervalMs: number;
|
|
103
|
+
sustainedInactivityThresholdMs: number;
|
|
104
|
+
backgroundPauseOnIncreasingTrend: boolean;
|
|
105
|
+
maxUserScaling: number;
|
|
106
|
+
minUserReserved: number;
|
|
107
|
+
}, {
|
|
108
|
+
monitoringWindowMs?: number | undefined;
|
|
109
|
+
highActivityThreshold?: number | undefined;
|
|
110
|
+
moderateActivityThreshold?: number | undefined;
|
|
111
|
+
recalculationIntervalMs?: number | undefined;
|
|
112
|
+
sustainedInactivityThresholdMs?: number | undefined;
|
|
113
|
+
backgroundPauseOnIncreasingTrend?: boolean | undefined;
|
|
114
|
+
maxUserScaling?: number | undefined;
|
|
115
|
+
minUserReserved?: number | undefined;
|
|
116
|
+
}>, {
|
|
117
|
+
monitoringWindowMs: number;
|
|
118
|
+
highActivityThreshold: number;
|
|
119
|
+
moderateActivityThreshold: number;
|
|
120
|
+
recalculationIntervalMs: number;
|
|
121
|
+
sustainedInactivityThresholdMs: number;
|
|
122
|
+
backgroundPauseOnIncreasingTrend: boolean;
|
|
123
|
+
maxUserScaling: number;
|
|
124
|
+
minUserReserved: number;
|
|
125
|
+
}, {
|
|
126
|
+
monitoringWindowMs?: number | undefined;
|
|
127
|
+
highActivityThreshold?: number | undefined;
|
|
128
|
+
moderateActivityThreshold?: number | undefined;
|
|
129
|
+
recalculationIntervalMs?: number | undefined;
|
|
130
|
+
sustainedInactivityThresholdMs?: number | undefined;
|
|
131
|
+
backgroundPauseOnIncreasingTrend?: boolean | undefined;
|
|
132
|
+
maxUserScaling?: number | undefined;
|
|
133
|
+
minUserReserved?: number | undefined;
|
|
134
|
+
}>;
|
|
135
|
+
/**
|
|
136
|
+
* Configuration for adaptive rate limiting
|
|
137
|
+
*/
|
|
138
|
+
type AdaptiveConfig = z.infer<typeof AdaptiveConfigSchema>;
|
|
139
|
+
/**
|
|
140
|
+
* Interface for rate limiting API requests per resource
|
|
141
|
+
*/
|
|
142
|
+
interface RateLimitStore {
|
|
143
|
+
/**
|
|
144
|
+
* Check if a request to a resource can proceed based on rate limits
|
|
145
|
+
* @param resource The resource name (e.g., 'issues', 'characters')
|
|
146
|
+
* @returns True if the request can proceed, false if rate limited
|
|
147
|
+
*/
|
|
148
|
+
canProceed(resource: string): Promise<boolean>;
|
|
149
|
+
/**
|
|
150
|
+
* Record a request to a resource for rate limiting tracking
|
|
151
|
+
* @param resource The resource name (e.g., 'issues', 'characters')
|
|
152
|
+
*/
|
|
153
|
+
record(resource: string): Promise<void>;
|
|
154
|
+
/**
|
|
155
|
+
* Get the current rate limit status for a resource
|
|
156
|
+
* @param resource The resource name
|
|
157
|
+
* @returns Rate limit information including remaining requests and reset time
|
|
158
|
+
*/
|
|
159
|
+
getStatus(resource: string): Promise<{
|
|
160
|
+
remaining: number;
|
|
161
|
+
resetTime: Date;
|
|
162
|
+
limit: number;
|
|
163
|
+
}>;
|
|
164
|
+
/**
|
|
165
|
+
* Reset rate limits for a resource (useful for testing)
|
|
166
|
+
* @param resource The resource name
|
|
167
|
+
*/
|
|
168
|
+
reset(resource: string): Promise<void>;
|
|
169
|
+
/**
|
|
170
|
+
* Get the time in milliseconds until the next request can be made
|
|
171
|
+
* @param resource The resource name
|
|
172
|
+
* @returns Milliseconds to wait, or 0 if no waiting is needed
|
|
173
|
+
*/
|
|
174
|
+
getWaitTime(resource: string): Promise<number>;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Enhanced interface for adaptive rate limiting stores with priority support
|
|
178
|
+
*/
|
|
179
|
+
interface AdaptiveRateLimitStore extends RateLimitStore {
|
|
180
|
+
/**
|
|
181
|
+
* Check if a request to a resource can proceed based on rate limits
|
|
182
|
+
* @param resource The resource name (e.g., 'issues', 'characters')
|
|
183
|
+
* @param priority The priority level of the request (defaults to 'background')
|
|
184
|
+
* @returns True if the request can proceed, false if rate limited
|
|
185
|
+
*/
|
|
186
|
+
canProceed(resource: string, priority?: RequestPriority): Promise<boolean>;
|
|
187
|
+
/**
|
|
188
|
+
* Record a request to a resource for rate limiting tracking
|
|
189
|
+
* @param resource The resource name (e.g., 'issues', 'characters')
|
|
190
|
+
* @param priority The priority level of the request (defaults to 'background')
|
|
191
|
+
*/
|
|
192
|
+
record(resource: string, priority?: RequestPriority): Promise<void>;
|
|
193
|
+
/**
|
|
194
|
+
* Get the current rate limit status for a resource
|
|
195
|
+
* @param resource The resource name
|
|
196
|
+
* @returns Rate limit information including remaining requests and reset time
|
|
197
|
+
*/
|
|
198
|
+
getStatus(resource: string): Promise<{
|
|
199
|
+
remaining: number;
|
|
200
|
+
resetTime: Date;
|
|
201
|
+
limit: number;
|
|
202
|
+
adaptive?: {
|
|
203
|
+
userReserved: number;
|
|
204
|
+
backgroundMax: number;
|
|
205
|
+
backgroundPaused: boolean;
|
|
206
|
+
recentUserActivity: number;
|
|
207
|
+
reason: string;
|
|
208
|
+
};
|
|
209
|
+
}>;
|
|
210
|
+
/**
|
|
211
|
+
* Get the time in milliseconds until the next request can be made
|
|
212
|
+
* @param resource The resource name
|
|
213
|
+
* @param priority The priority level of the request (defaults to 'background')
|
|
214
|
+
* @returns Milliseconds to wait, or 0 if no waiting is needed
|
|
215
|
+
*/
|
|
216
|
+
getWaitTime(resource: string, priority?: RequestPriority): Promise<number>;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Creates a consistent hash for API requests to use as cache/dedupe keys
|
|
221
|
+
* @param endpoint The API endpoint
|
|
222
|
+
* @param params The request parameters
|
|
223
|
+
* @returns A SHA-256 hash of the request
|
|
224
|
+
*/
|
|
225
|
+
declare function hashRequest(endpoint: string, params?: Record<string, unknown>): string;
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Configuration for per-resource rate limiting.
|
|
229
|
+
*
|
|
230
|
+
* This interface is shared by all store implementations (e.g. in-memory,
|
|
231
|
+
* SQLite) so that callers can use a single canonical type.
|
|
232
|
+
*/
|
|
233
|
+
interface RateLimitConfig {
|
|
234
|
+
/** Number of requests allowed per time window */
|
|
235
|
+
limit: number;
|
|
236
|
+
/** Duration of the window in milliseconds */
|
|
237
|
+
windowMs: number;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Default rate-limit window: 60 requests per minute.
|
|
241
|
+
*
|
|
242
|
+
* Store implementations can reference this to avoid duplicating magic numbers.
|
|
243
|
+
*/
|
|
244
|
+
declare const DEFAULT_RATE_LIMIT: RateLimitConfig;
|
|
245
|
+
|
|
246
|
+
interface ActivityMetrics {
|
|
247
|
+
recentUserRequests: Array<number>;
|
|
248
|
+
recentBackgroundRequests: Array<number>;
|
|
249
|
+
userActivityTrend: 'increasing' | 'stable' | 'decreasing' | 'none';
|
|
250
|
+
}
|
|
251
|
+
interface DynamicCapacityResult {
|
|
252
|
+
userReserved: number;
|
|
253
|
+
backgroundMax: number;
|
|
254
|
+
backgroundPaused: boolean;
|
|
255
|
+
reason: string;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Calculates dynamic capacity allocation based on real-time user activity patterns
|
|
259
|
+
*/
|
|
260
|
+
declare class AdaptiveCapacityCalculator {
|
|
261
|
+
readonly config: z.infer<typeof AdaptiveConfigSchema>;
|
|
262
|
+
constructor(config?: Partial<z.input<typeof AdaptiveConfigSchema>>);
|
|
263
|
+
calculateDynamicCapacity(resource: string, totalLimit: number, activityMetrics: ActivityMetrics): DynamicCapacityResult;
|
|
264
|
+
getRecentActivity(requests: Array<number>): number;
|
|
265
|
+
calculateActivityTrend(requests: Array<number>): 'increasing' | 'stable' | 'decreasing' | 'none';
|
|
266
|
+
private getUserMultiplier;
|
|
267
|
+
private getSustainedInactivityPeriod;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
interface HttpClientContract {
|
|
271
|
+
/**
|
|
272
|
+
* Perform a GET request.
|
|
273
|
+
*
|
|
274
|
+
* @param url Full request URL
|
|
275
|
+
* @param options Optional configuration – primarily an AbortSignal so
|
|
276
|
+
* callers can cancel long-running or rate-limited waits.
|
|
277
|
+
*/
|
|
278
|
+
get<Result>(url: string, options?: {
|
|
279
|
+
/**
|
|
280
|
+
* AbortSignal that allows the caller to cancel the request, including any
|
|
281
|
+
* internal rate-limit wait. If the signal is aborted while waiting the
|
|
282
|
+
* promise rejects with an `AbortError`-like `Error` instance.
|
|
283
|
+
*/
|
|
284
|
+
signal?: AbortSignal;
|
|
285
|
+
/**
|
|
286
|
+
* Priority level for the request (affects rate limiting behavior)
|
|
287
|
+
*/
|
|
288
|
+
priority?: RequestPriority;
|
|
289
|
+
}): Promise<Result>;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
interface HttpClientStores {
|
|
293
|
+
cache?: CacheStore;
|
|
294
|
+
dedupe?: DedupeStore;
|
|
295
|
+
rateLimit?: RateLimitStore | AdaptiveRateLimitStore;
|
|
296
|
+
}
|
|
297
|
+
interface HttpClientOptions {
|
|
298
|
+
/**
|
|
299
|
+
* Default cache TTL in seconds
|
|
300
|
+
*/
|
|
301
|
+
defaultCacheTTL?: number;
|
|
302
|
+
/**
|
|
303
|
+
* Whether to throw errors on rate limit violations
|
|
304
|
+
*/
|
|
305
|
+
throwOnRateLimit?: boolean;
|
|
306
|
+
/**
|
|
307
|
+
* Maximum time to wait for rate limit in milliseconds
|
|
308
|
+
*/
|
|
309
|
+
maxWaitTime?: number;
|
|
310
|
+
/**
|
|
311
|
+
* Optional response transformer applied to the raw response data.
|
|
312
|
+
* Use this for converting snake_case to camelCase, etc.
|
|
313
|
+
*/
|
|
314
|
+
responseTransformer?: (data: unknown) => unknown;
|
|
315
|
+
/**
|
|
316
|
+
* Optional error handler to convert errors into domain-specific error types.
|
|
317
|
+
* If not provided, a generic HttpClientError is thrown.
|
|
318
|
+
*/
|
|
319
|
+
errorHandler?: (error: unknown) => Error;
|
|
320
|
+
/**
|
|
321
|
+
* Optional response validator/handler called after transformation.
|
|
322
|
+
* Use this to inspect the response and throw domain-specific errors
|
|
323
|
+
* based on response content (e.g., API-level error codes).
|
|
324
|
+
*/
|
|
325
|
+
responseHandler?: (data: unknown) => unknown;
|
|
326
|
+
/**
|
|
327
|
+
* Configure rate-limit response header names for standards and custom APIs.
|
|
328
|
+
*/
|
|
329
|
+
rateLimitHeaders?: {
|
|
330
|
+
retryAfter?: Array<string>;
|
|
331
|
+
limit?: Array<string>;
|
|
332
|
+
remaining?: Array<string>;
|
|
333
|
+
reset?: Array<string>;
|
|
334
|
+
combined?: Array<string>;
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
declare class HttpClient implements HttpClientContract {
|
|
338
|
+
private _http;
|
|
339
|
+
private stores;
|
|
340
|
+
private serverCooldowns;
|
|
341
|
+
private options;
|
|
342
|
+
constructor(stores?: HttpClientStores, options?: HttpClientOptions);
|
|
343
|
+
private normalizeRateLimitHeaders;
|
|
344
|
+
private normalizeHeaderNames;
|
|
345
|
+
/**
|
|
346
|
+
* Infer the resource name from the endpoint URL
|
|
347
|
+
* @param url The full URL or endpoint path
|
|
348
|
+
* @returns The resource name for rate limiting
|
|
349
|
+
*/
|
|
350
|
+
private inferResource;
|
|
351
|
+
/**
|
|
352
|
+
* Extract endpoint and params from URL for request hashing
|
|
353
|
+
* @param url The full URL
|
|
354
|
+
* @returns Object with endpoint and params for hashing
|
|
355
|
+
*/
|
|
356
|
+
private parseUrlForHashing;
|
|
357
|
+
private getOriginScope;
|
|
358
|
+
private getHeaderValue;
|
|
359
|
+
private parseIntegerHeader;
|
|
360
|
+
private parseRetryAfterMs;
|
|
361
|
+
private parseResetMs;
|
|
362
|
+
private parseCombinedRateLimitHeader;
|
|
363
|
+
private applyServerRateLimitHints;
|
|
364
|
+
private enforceServerCooldown;
|
|
365
|
+
private enforceStoreRateLimit;
|
|
366
|
+
private generateClientError;
|
|
367
|
+
get<Result>(url: string, options?: {
|
|
368
|
+
signal?: AbortSignal;
|
|
369
|
+
priority?: RequestPriority;
|
|
370
|
+
}): Promise<Result>;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Base error class for HTTP client errors.
|
|
375
|
+
* Consumers can extend this for domain-specific error handling.
|
|
376
|
+
*/
|
|
377
|
+
declare class HttpClientError extends Error {
|
|
378
|
+
readonly statusCode?: number;
|
|
379
|
+
constructor(message: string, statusCode?: number);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export { type ActivityMetrics, AdaptiveCapacityCalculator, type AdaptiveConfig, AdaptiveConfigSchema, type AdaptiveRateLimitStore, type CacheStore, DEFAULT_RATE_LIMIT, type DedupeStore, type DynamicCapacityResult, HttpClient, type HttpClientContract, HttpClientError, type HttpClientOptions, type HttpClientStores, type RateLimitConfig, type RateLimitStore, type RequestPriority, hashRequest };
|